通用控制器框架,支持步兵和哨兵机器人的统一控制架构。
flowchart TB
subgraph Input Sources
VTM[VTM遥控器<br/>ReadVT13RemoteControl]
NDJ[NDJ遥控器<br/>ReadDJIRC]
AA[自瞄系统<br/>AutoAimCommandMsg]
NAV[导航系统<br/>cmd_vel/Twist]
REF[裁判系统<br/>constraints + game_status]
end
subgraph Interpreters
VTM_INT[VTMInterpreter<br/>独立节点]
NDJ_INT[NDJInterpreter<br/>独立节点]
end
VTM --> VTM_INT
NDJ --> NDJ_INT
VTM_INT -->|UnifiedInput.msg<br/>/universal_controller/input/vtm| HUB
NDJ_INT -->|UnifiedInput.msg<br/>/universal_controller/input/ndj| HUB
AA --> HUB
NAV --> HUB
REF --> HUB
subgraph HUB [Hub - 中心仲裁]
RC_FUSE[RC Fusion<br/>遥控器融合]
MA[Mode Arbiter<br/>模式仲裁]
DISPATCH[Dispatch<br/>指令分发]
end
HUB --> CH[ChassisController]
HUB --> GB[GimbalController]
HUB --> FR[FireController]
CH --> EC[EtherCAT Topics]
GB --> EC
FR --> EC
两个独立的 ROS2 节点,分别处理不同类型的遥控器。两者均以 100Hz 定时器发布 UnifiedInput.msg。
| Interpreter | 订阅消息 | 连接检测 | 默认话题 |
|---|---|---|---|
| VTMInterpreter | ReadVT13RemoteControl |
超时检测 | /ecat/sn4653115/vt13/read |
| NDJInterpreter | ReadDJIRC |
超时检测 | /ecat/sn4653115/app1/read |
两者都发布 UnifiedInput.msg,通过 YAML 配置文件定义拨杆停靠点、切换动作、按钮长短按、滚轮动作等。
解释器通过 YAML 配置文件定义遥控器按键/拨杆的行为映射:
-
VTMInterpreter: 加载
config/vtm_definition.sentry.yaml- 三档拨杆(急停/正常/导航+行为树)
- 自定义按钮(自瞄切换、小陀螺、摩擦轮)支持长按/短按检测
- 滚轮(小陀螺速度调节)
- 扳机(短按单发、长按连发)
-
NDJInterpreter: 加载
config/ndj_definition.sentry.yaml- 左/右拨杆停靠点和切换动作
- 滚轮动作
动作类型包括三态动作(toggle/force-on/force-off)和小陀螺控制(加速/减速)。
Header-only 工具类,提供:
process_joystick: 摇杆死区处理和速度映射compute_chassis_velocity: 键盘 + 摇杆组合速度计算update_keyboard_speed: Shift 加速 / Ctrl 减速分档update_spin_speed: 小陀螺速度调节(拨轮 + 键盘)compute_gimbal_delta: 鼠标云台控制(灵敏度、增益、限幅)
Hub 是系统核心,实现以下功能:
- RC 融合: 按优先级融合多个遥控器输入(模拟量通道支持零值穿透)
- 外部输入: 订阅自瞄指令、导航速度、裁判系统约束和比赛状态
- 模式仲裁: 独立决定各子系统(底盘/云台/发射)的输入来源
- 指令分发: 将融合后的指令分发给对应控制器
- 控制循环: 以 1000Hz 运行主控制循环
Hub 由 4 个源文件组成:
hub_core.cpp: 构造、参数声明、控制循环hub_rc.cpp: RC 融合逻辑hub_subscribers.cpp: 外部输入回调(自瞄、导航、裁判)hub_arbitration.cpp: 模式仲裁和指令分发
所有控制器继承自 BaseController 基类,实现 init()、update(dt)、stop() 接口。
| Controller | 功能 | 电机类型 | 关键特性 |
|---|---|---|---|
| ChassisController | 舵轮底盘控制 | DJI / LK | 四轮舵轮运动学、云台-底盘坐标转换、小陀螺速度抑制 |
| GimbalController | 云台控制 | Pitch: DJI, Yaw: LK | IMU 反馈、自瞄集成(Hub 统一下发)、前馈角速度 |
| FireController | 发射控制 | DJI | 三态状态机(IDLE→LOADING→READY)、裁判约束、单发/连发 |
| Topic | Msg Type | 订阅者 | Purpose |
|---|---|---|---|
/ecat/sn*/vt13/read |
ReadVT13RemoteControl | VTMInterpreter | VTM 遥控器输入 |
/ecat/sn*/app*/read |
ReadDJIRC | NDJInterpreter | NDJ 遥控器输入 |
/universal_controller/input/vtm |
UnifiedInput | Hub | VTM 统一输入 |
/universal_controller/input/ndj |
UnifiedInput | Hub | NDJ 统一输入 |
/sp_vision/autoaim_command |
AutoAimCommandMsg | Hub, GimbalController | 自瞄指令 |
/cmd_vel |
Twist | Hub | 导航速度指令 |
/referee/parsed/common/constraints |
Float32MultiArray | Hub | 功率/热量约束 |
/referee/common/game_status |
GameStatus | Hub | 比赛状态 |
/ecat/sn*/app*/read |
ReadDJIMotor/ReadLkMotor/ReadLkMotorMulti | Controllers | 电机反馈 |
/ecat/sn*/app*/read |
Imu | GimbalController | IMU 姿态反馈 |
| Topic | Msg Type | 发布者 | Purpose |
|---|---|---|---|
/ecat/sn*/app*/write |
WriteDJIMotor | ChassisController, GimbalController, FireController | DJI 电机指令 |
/ecat/sn*/app*/write |
WriteLkMotorBroadcastCurrentControl | ChassisController | LK 舵向/驱动电机电流指令 |
/ecat/sn*/app*/write |
WriteLkMotorTorqueControl | GimbalController | LK Yaw 电机力矩指令 |
统一输入消息格式,由 Interpreter 发布,Hub 订阅:
std_msgs/Header header
string control_source # 当前控制源
bool connected # 遥控器连接状态
# 模式标志
bool emergency_stop # 急停标志
bool autoaim_enabled # 自瞄使能
bool navigation_enabled # 导航模式
# 底盘指令 (云台坐标系)
float64 vx # X方向速度 (前进)
float64 vy # Y方向速度 (横移)
float64 wz # 旋转角速度
bool spin_mode # 小陀螺模式
float64 spin_speed # 小陀螺速度
# 云台指令
float64 pitch_delta # Pitch 增量 (度)
float64 yaw_delta # Yaw 增量 (弧度)
# 发射指令
bool fire_trigger # 发射触发
bool burst_mode # 连发模式
bool friction_on # 摩擦轮开关
float64 friction_speed # 摩擦轮速度
# 速度分档
float64 chassis_speed_scale # 底盘速度比例 (0-1)自瞄系统指令:
builtin_interfaces/Time timestamp
bool control
bool shoot
float64 yaw
float64 pitchHub 对各子系统(底盘/云台/发射)独立进行仲裁,不同子系统可处于不同模式:
| 优先级 | 模式 | 底盘 | 云台 | 发射 |
|---|---|---|---|---|
| 1 (最高) | EMERGENCY_STOP | 遥控器离线或急停 | 遥控器离线或急停 | 遥控器离线或急停 |
| 2 | NAVIGATION | navigation_enabled + 有效 cmd_vel | - | - |
| 3 | AUTOAIM | - | autoaim_enabled + 有效自瞄指令 | - |
| 4 (默认) | MANUAL | RC 输入 | RC 输入 | RC 输入 |
仲裁规则:
- EMERGENCY_STOP:无 UnifiedInput、emergency_stop 标志为真、或遥控器断连时触发,所有电机停止
- NAVIGATION:仅底盘生效,需要
navigation_enabled标志且导航速度在超时窗口内 - AUTOAIM:仅云台生效,需要
autoaim_enabled标志且自瞄指令在超时窗口内 - 发射控制始终来自 RC 输入
RC 融合:当多个遥控器同时在线时,按配置优先级(默认 ['vtm', 'ndj'])选择主输入源。模拟量通道(vx, vy, wz 等)支持零值穿透——高优先级源的摇杆在死区内时,低优先级源可以生效。
所有配置集中在 config/controller_params.yaml,使用 /** 通配符使参数同时作用于所有节点:
/**:
ros__parameters:
control_frequency: 1000
autoaim_timeout_s: 0.2
referee_timeout_s: 0.5
topics:
unified_input: '/hub/rc_unified_input'
autoaim_cmd: '/sp_vision/autoaim_command'
referee_constraints: '/referee/parsed/common/constraints'
referee_game_status: '/referee/common/game_status'
motor_type:
chassis: 'LK' # 'DJI' or 'LK'
gimbal_pitch: 'DJI'
gimbal_yaw: 'LK'
fire_trigger: 'DJI'
controllers:
chassis:
wheel_track: 0.2746
wheel_base: 0.2746
ecd_zeros: [5989, 21248, 23534, 1128]
yaw_center_ecd: 50800
# ... PID 参数、话题名等
gimbal:
pitch_center_ecd: 6050
pitch_min_deg: -25.0
pitch_max_deg: 30.0
# ... Yaw 级联 PID 参数
fire:
enabled: true
friction_speed_default: 6500.0
shot_period_ms: 50.0
# ... 拨盘串级 PID 参数
rc_interpreter:
topic_vtm_rc: '/ecat/sn4653115/vt13/read'
topic_ndj_rc: '/ecat/sn4653115/app1/read'
topic_vtm_output: '/universal_controller/input/vtm'
topic_ndj_output: '/universal_controller/input/ndj'
priority: ['vtm', 'ndj']
# ... 摇杆/键盘/鼠标/小陀螺参数
rc_hub:
topic_vtm_input: '/universal_controller/input/vtm'
topic_ndj_input: '/universal_controller/input/ndj'
topic_unified_output: '/hub/rc_unified_input'
priority: ['vtm', 'ndj']
publish_frequency: 200除主配置外,还有两个 YAML 文件定义遥控器按键映射:
| 文件 | 用途 |
|---|---|
config/vtm_definition.sentry.yaml |
VTM 三档拨杆、按钮、滚轮、扳机映射 |
config/ndj_definition.sentry.yaml |
NDJ 左/右拨杆、滚轮映射 |
| 组件 | DJI 电机 | LK 电机 |
|---|---|---|
| 底盘舵向 | 位置模式(编码器) | 级联 PID(角度环 + 速度环) |
| 底盘驱动 | 速度模式 | 速度环 PID |
| 云台 Pitch | 位置模式(IMU 反馈 + 编码器偏移) | - |
| 云台 Yaw | - | 级联 PID(位置环 + 速度环 + 前馈) |
| 摩擦轮 | 速度模式 | - |
| 拨盘 | 串级 PID(位置环 + 速度环) | - |
LK 电机编码器范围:舵轮使用 32768 周期(非 DJI 的 8192),在 SwerveKinematics 初始化时根据电机类型自动选择。
cd ~/ros2_ws
colcon build --packages-select universal_controller
source install/setup.bashros2 launch universal_controller universal_controller.launch.pyLaunch 参数:
config_file: 配置文件路径(默认为安装目录下的config/controller_params.yaml)robot_type: 机器人类型(infantry/sentry,默认infantry)
universal_controller/
├── CMakeLists.txt
├── package.xml
├── README.md
├── config/
│ ├── controller_params.yaml # 主配置
│ ├── vtm_definition.sentry.yaml # VTM 遥控器按键映射
│ └── ndj_definition.sentry.yaml # NDJ 遥控器按键映射
├── launch/
│ └── universal_controller.launch.py
├── msg/
│ ├── UnifiedInput.msg
│ └── AutoAimCommandMsg.msg
├── include/universal_controller/
│ ├── common/
│ │ ├── types.hpp # 核心类型定义(ControlMode, Command, RefereeConstraints 等)
│ │ └── config.hpp # ConfigLoader + 各控制器 Config 结构体
│ ├── controllers/
│ │ ├── base_controller.hpp # 控制器抽象基类
│ │ ├── chassis_controller.hpp
│ │ ├── gimbal_controller.hpp
│ │ └── fire_controller.hpp
│ ├── interpreters/
│ │ ├── vtm_interpreter.hpp
│ │ └── ndj_interpreter.hpp
│ ├── hub/
│ │ └── hub.hpp
│ └── tools/
│ ├── pid.hpp # PID + CascadePID
│ ├── swerve_kinematics.hpp # 舵轮运动学解算
│ ├── input_processor.hpp # 输入处理工具
│ ├── rc_action_types.hpp # 遥控器动作类型定义
│ └── rc_yaml_parser.hpp # 遥控器 YAML 配置解析
└── src/
├── main.cpp # 入口:创建所有节点,MultiThreadedExecutor
├── hub/
│ ├── hub_core.cpp # Hub 构造、参数、控制循环
│ ├── hub_rc.cpp # RC 融合逻辑
│ ├── hub_subscribers.cpp # 外部输入回调
│ └── hub_arbitration.cpp # 模式仲裁和指令分发
├── controllers/
│ ├── chassis_controller.cpp
│ ├── gimbal_controller.cpp
│ └── fire_controller.cpp
├── interpreters/
│ ├── vtm_interpreter.cpp
│ └── ndj_interpreter.cpp
└── tools/
├── swerve_kinematics.cpp
└── rc_yaml_parser.cpp
rclcpp— ROS2 C++ 客户端库custom_msgs— 自定义 EtherCAT 电机消息(ReadDJIMotor, WriteDJIMotor, ReadLkMotor 等)sp_msgs— 视觉系统消息(AutoAimCommandMsg)dji_referee_protocol— 裁判系统协议sensor_msgs— IMU 消息geometry_msgs— Twist 消息yaml-cpp— YAML 配置解析