话题清单
章节 |
节点 / 包 |
包路径(工作区 |
说明 |
|---|---|---|---|
§2 |
|
|
主臂:外骨骼 → 关节/扳机/摇杆等话题 |
§3 |
|
|
从臂:跟随主臂 CAN 驱动 |
§4 |
|
|
傲意灵巧手(单独 launch) |
§5 |
|
|
宇树 Dex1 夹爪(单独 launch) |
§6 |
|
|
蓝芯 VMR 底盘摇杆(单独 launch) |
备注
说明:下文路径均相对于工作区根目录(如 ti5-remote_control/)。修改 YAML 后需重启对应 launch;ti5_controller 内 C++ 节点改参一般无需 colcon build,改 launch/Python 或新增包才需重新编译。
1. 命名约定
主臂分话题前缀:
/{master_device_id}/...,默认MASTER_001(仓库配置示例常用ti5_master_001)。从臂分话题前缀:
/{slave_device_id}/...,默认SLAVE_001(仓库配置示例常用ti5_slave_001)。傲意灵巧手(
ti5_aoyihand_node,包src/ti5_aoyihand/):控制输入(订阅)在主臂命名空间/{master_device_id}/...;末端状态(与 Dex1 相同话题名)发布在/{device_id}/...。master_device_id/device_id须在src/ti5_aoyihand/config/ti5_aoyihand_node.yaml(或启动时参数覆盖)与主臂paired_device_id、从臂device_id自行对齐;宇树 Dex1 夹爪(
dex1_gripper_node,包src/dex1_gripper_ros2/)订阅主臂trigger_cmd,状态话题发布在夹爪节点的device_id下(默认与从臂同为ti5_slave_001),即用/<SLAVE_ID>/..._gripper_states。请单独 launch,与从臂 launch 独立。主臂、从臂(包
src/ti5_controller/)、灵巧手、Dex1、底盘等节点各自独立 launch,运行时通过话题与参数约定配合;底盘见 §6(src/lanxin_chassis_controller/)。本文的
<MASTER_ID>、<SLAVE_ID>为占位符。
2. 主臂节点(ti5_master_arm)
包位置:src/ti5_controller/
启动:ros2 launch ti5_controller ti5_master.launch.py(launch 文件:src/ti5_controller/launch/ti5_master.launch.py)
主要配置(src/ti5_controller/config/):
文件 |
用途 |
|---|---|
|
主臂节点 ROS 参数( |
|
外骨骼→机器人关节名与限位(须与从臂 |
|
臂/腿 solver 参数(须与从臂 |
2.1 发布话题
/<MASTER_ID>/right_arm_joint_cmd(sensor_msgs/msg/JointState)name: 右臂关节名(优先来自 retargeting)position: 右臂各关节目标角(弧度)header.frame_id:master_arm
/<MASTER_ID>/left_arm_joint_cmd(sensor_msgs/msg/JointState)同上,左臂
/<MASTER_ID>/head_joint_cmd(sensor_msgs/msg/JointState)name: 头部 R/P/Y 关节名position:[roll, pitch, yaw](弧度)header.frame_id:master_arm
/<MASTER_ID>/waist_joint_cmd(sensor_msgs/msg/JointState)name: 腰部关节名(支持单轴或多轴)position: 腰部目标角(弧度)header.frame_id:master_arm
/<MASTER_ID>/leg_joint_cmd(sensor_msgs/msg/JointState)(仅leg_teleop_enabled且enable_leg_joint_cmd_pub=true)name: 腿部关节名(retargeting 的leg)position: 腿电机目标角(弧度)header.frame_id:master_arm当前为“遥操态按键腿控”输出:会话开始前先请求一次
leg_states刷新,锁存当前末端姿态后仅改末端位置
/<MASTER_ID>/trigger_cmd(sensor_msgs/msg/JointState)name:["right_trigger","left_trigger"][右扳机, 左扳机]position: 范围约[0,1]header.frame_id:trigger_cmd
/<MASTER_ID>/thumb_side_cmd(sensor_msgs/msg/JointState)name:["right_thumb_side","left_thumb_side"]position: 两侧拇指侧向量,范围约[0,1]header.frame_id:thumb_side_cmd
/<MASTER_ID>/rocker_cmd(sensor_msgs/msg/JointState)name:["left_joy_x","left_joy_y","right_joy_x","right_joy_y"]position: 四轴摇杆值header.frame_id:rocker_cmd
/<MASTER_ID>/control_cmd(sensor_msgs/msg/JointState)name[0]:命令字符串(如enter_remote_mode、arm_follow_pause_left);position多为占位。主臂按档位/按键自动发布;从臂如何处理见 §3.1 控制命令。
/<MASTER_ID>/bottom_cmd(sensor_msgs/msg/JointState)用途:按键记录(供录包/数据分析);不驱动从臂,功能映射走
control_cmd。发布时机:某键按住期间,按按键解析频率持续发布;松手即停止。BOTH_3F 下不发布。
命名:
name[0] = {模式前缀}_{left|right}_{键名};position[0]固定0.0;header.frame_id:bottom_cmd。模式前缀:
BOTH_1F→1F_(如1F_left_blue);NONE→None_(如None_right_joystick)。记录的键(左右手对称,共 20 路;未按住则不发布该条):
键名
含义
black/white/blue/red四色面键(白→X、黑→Y、红→A、蓝→B)
joystick摇杆轴心按下)
ext_start/ext_mode/ext_back拓展键(须
enable_extended_buttons: true且协议有按下)ext_rear_up/ext_rear_down拓展后侧上/下
不在本话题:扳机 →
trigger_cmd;拇指侧向 →thumb_side_cmd;摇杆轴值 →rocker_cmd。
2.2 订阅话题
/<SLAVE_ID>/leg_states(sensor_msgs/msg/JointState)(仅折腿遥操启用时)用于主臂折腿 IK 反馈输入
优先按
name对齐读取,回退按下标读取兼容
position.size()==4(标准)或==3(兼容路径)
3. 从臂节点(ti5_follow_arm)
包位置:src/ti5_controller/(与主臂同包,独立进程)
启动:ros2 launch ti5_controller ti5_follow.launch.py(launch 文件:src/ti5_controller/launch/ti5_follow.launch.py)
主要配置(src/ti5_controller/config/):
文件 |
用途 |
|---|---|
|
从臂 ROS 参数( |
|
与主臂同一份( |
|
与主臂同一份( |
3.1 订阅话题
下述话题是否创建受
ti5_follow_config.yaml的enable_*/include*OnCan()影响。
主从遥操输入(来自主臂):
/<MASTER_ID>/right_arm_joint_cmd(sensor_msgs/msg/JointState)/<MASTER_ID>/left_arm_joint_cmd(sensor_msgs/msg/JointState)(双臂话题从臂侧 QoS 为 KEEP_LAST depth=1,减轻暂停恢复后 DDS 堆积旧帧;主臂单侧恢复后会对该臂 pulse 瞬时多发一帧 并唤醒发布节拍,
control_cmd本身不再要求带 7 轴。)/<MASTER_ID>/head_joint_cmd(sensor_msgs/msg/JointState)/<MASTER_ID>/waist_joint_cmd(sensor_msgs/msg/JointState)/<MASTER_ID>/leg_joint_cmd(sensor_msgs/msg/JointState)
控制命令:
/<MASTER_ID>/control_cmd(sensor_msgs/msg/JointState)怎么读:看
name[0]里的命令名;若带:,冒号前是命令、后面是参数。position多数情况只是占位,以命令名为准。进出遥操模式(主臂按档位自动发,从臂据此切换工作模式):
命令
主臂何时发布
从臂收到后
enter_chassis_control一切换到 BOTH_1F(两手 1F)
底盘节点启用摇杆;从臂不处理此命令
enter_remote_modeBOTH_1F 保持满 1 秒且尚未在遥操态
进入遥操跟随(
REMOTE_OPERATION):清跟随缓存、腰/头/臂开始跟主臂;首帧关节会做平滑衔接enter_default_mode① 切到 BOTH_3F(两手 3F)立即发;② 在遥操态切到 NONE 且持续 ≥0.5s(须
none_state_exit_remote: true)退出遥操回待机:清跟随缓存、恢复默认速度限制;若配置了退出回默认位姿则做规划
典型流程:两手 1F 并保持 1s →
enter_chassis_control(进 1F 即发)+enter_remote_mode(满 1s 发)→ 从臂跟随;两手 3F →enter_default_mode→ 从臂待机、主臂停发关节。从臂直接忽略(留给录包/LeRobot 等其它节点):
record_bag_start/record_bag_stoptoggle_record、drop、quit、mark_failure
单侧臂暂停 / 恢复(默认绑在红键 A,BOTH_1F 且已在遥操态;按住 ≥200ms 后松开触发):
命令
主臂何时发布
从臂做什么
arm_follow_pause_left/_right该侧第一次按红键松开
该侧停止向电机发跟随;仍收
*_arm_joint_cmd并更新缓存reset_first_point_left/_right该侧再次按红键松开(恢复)
解除暂停;对该侧再做一次首帧平滑衔接(从当前电机位置插到主臂目标),然后恢复跟随
恢复顺序:主臂先解除该侧轨迹冻结并刷新关节话题 → 等待约 50ms → 发
reset_first_point_*(position一般为占位,目标角来自仍在发布的*_arm_joint_cmd)。腿控与腰控(主臂腿 IK 会话):
命令
含义
refresh_leg_states腿控开始前:请从臂立刻读腿位置并发布
leg_statesleg_hold_disable开始腿控:解除腿部 hold,允许下发
leg_joint_cmdleg_hold_enable腿控结束:非共享腿轴进入 hold
set_waist_teleop_paused1暂停腰遥操 CAN;0恢复(腿控期间避免腰/腿抢轴)set_leg_hold_disabled旧命令,仍兼容;请优先用
leg_hold_enable/leg_hold_disable其它:
adjust_speed_slow/fast(及_left/_right分侧版)、aoyihand_toggle_*_mode等,见src/ti5_controller/config/ti5_master_config.yaml按键映射注释。
3.2 发布话题
/<SLAVE_ID>/right_arm_states(sensor_msgs/msg/JointState)name: 右臂关节名position: 右臂电机角(弧度)header.frame_id:<SLAVE_ID>
/<SLAVE_ID>/left_arm_states(sensor_msgs/msg/JointState)同上,左臂
/<SLAVE_ID>/head_states(sensor_msgs/msg/JointState)name: 头部 R/P/Yposition:[roll,pitch,yaw](弧度)header.frame_id:<SLAVE_ID>
/<SLAVE_ID>/waist_states(sensor_msgs/msg/JointState)name: 腰部关节名(长度可为 1 或更多)position: 腰部电机角(弧度)header.frame_id:<SLAVE_ID>
/<SLAVE_ID>/leg_states(sensor_msgs/msg/JointState)name: 腿关节名(retargeting leg 顺序)position: 腿电机角(弧度;与 CAN/0x44 约定一致)velocity/effort: 当前填 0 占位header.frame_id:<SLAVE_ID>
4. 灵巧手节点(ti5_aoyihand_node,傲意 ROHand)
包位置:src/ti5_aoyihand/
启动:ros2 launch ti5_aoyihand ti5_aoyihand.launch.py(launch 文件:src/ti5_aoyihand/launch/ti5_aoyihand.launch.py)
主要配置:src/ti5_aoyihand/config/ti5_aoyihand_node.yaml(串口、device_id、master_device_id、控制模式等)
源码:src/ti5_aoyihand/src/ti5_aoyihand_node.cpp
备注
说明:与主臂同一网段侧运行。订阅挂在 master_device_id(主臂)。夹爪形态状态挂在 device_id(与从臂一致),仅由本节点在串口上完成「控制帧 → 延时 → 查询帧」后发布;ti5_follow_arm 不参与 Aoyi 指令下发或状态读取。
4.1 订阅话题
/<MASTER_ID>/trigger_cmd(sensor_msgs/msg/JointState)与主臂发布约定一致:
name中right_trigger/left_trigger,或无名时position[0]=右、position[1]=左,值约[0,1]映射为各指弯曲标量(实现内缩放至 0~65000 下发串口);
five_finger/three_finger/two_finger模式下依次参与映射的指序号递减(拇指侧向由thumb_side_cmd单独驱动为第 6 路)
/<MASTER_ID>/thumb_side_cmd(sensor_msgs/msg/JointState)name:right_thumb_side/left_thumb_side,或无名时position[0]=右、position[1]=左映射到第 6 路(拇指侧向轴)
/<MASTER_ID>/control_cmd(sensor_msgs/msg/JointState)使用
name[0]字符串;当收到aoyihand_toggle_left_mode/aoyihand_toggle_right_mode时,在防抖间隔后分别循环切换左/右手控制模式:five_finger→three_finger→two_finger→ …
4.2 发布话题(与 Dex1 对齐,由本节点闭环产生)
每个控制周期内顺序为:对单侧下发 Set_Finger_PosAll → 等待 query_delay_ms(默认 3ms)→ 查询指位/力 → 按 state_publish_hz 分频发布。
/<SLAVE_ID>/right_gripper_states(sensor_msgs/msg/JointState)/<SLAVE_ID>/left_gripper_states(sensor_msgs/msg/JointState)
<SLAVE_ID> = 参数 device_id(src/ti5_aoyihand/config/ti5_aoyihand_node.yaml)。话题名与 §5 Dex1 相同,字段含义不同;Dex1 字段说明见 §5.2。
4.3 可选:模式话题(主臂侧)
/<MASTER_ID>/aoyihand_mode(std_msgs/msg/String)(publish_mode_topic=true时)启动及每次切换模式时发布
data格式:left:<mode>或right:<mode>,<mode>为five_finger|three_finger|two_finger
5. 夹爪节点(dex1_gripper_node,宇树 Dex1-1)
包位置:src/dex1_gripper_ros2/
启动:ros2 launch dex1_gripper_ros2 dex1_gripper.launch.py(launch 文件:src/dex1_gripper_ros2/launch/dex1_gripper.launch.py)
主要配置:src/dex1_gripper_ros2/config/dex1_gripper.yaml(device_id、master_device_id、开合角标定、力矩保护等)
源码:src/dex1_gripper_ros2/src/dex1_gripper_node.cpp
标定/探测脚本(非 ROS 包内):串口can口权限配置/install_scripts/(如 calibrate_dex1_gripper.sh、detect_dex1_gripper.sh)
5.1 订阅话题
/<MASTER_ID>/trigger_cmd(sensor_msgs/msg/JointState)(subscribe_master_trigger=true时)读取优先级:
按
name匹配right_trigger/left_trigger回退
position[0]=右、position[1]=左
将触发量按
trigger_open/trigger_close线性映射到夹爪目标角q_open_rad~q_close_rad
5.2 发布话题:*_gripper_states
话题
话题 |
消息类型 |
出现条件 |
|---|---|---|
|
|
探测到 预设 id=0 的 M4010 电机 |
|
|
探测到 预设 id=1 的 M4010 电机 |
<SLAVE_ID> = 参数 device_id(默认 ti5_slave_001,见 dex1_gripper.yaml)。左右侧由节点预设的固定电机 id 区分:id=0 → 右,id=1 → 左。
备注
说明:与 §4 灵巧手话题名相同;同机勿并行 launch dex1_gripper_node 与 ti5_aoyihand_node。
消息形态
类型:
sensor_msgs/msg/JointState(ROS2 标准关节状态)。每侧只描述 1 个夹爪关节:
name、position、velocity、effort四个数组长度均为 1(无name与数组长度不一致的情况)。未填充的
JointState可选字段(如空header以外的扩展)本节点不使用。
备注
字段说明:发布代码见 dex1_gripper_node.cpp:state.q/dq/tau 为 Unitree SDK 电机侧反馈,再经减速比换算到 关节侧 写入话题。
字段 |
ROS 类型 |
数组下标 |
单位 |
取值 / 换算 |
含义 |
|---|---|---|---|---|---|
|
|
— |
— |
控制环内本电机 |
状态采样时间 |
|
|
— |
— |
等于 |
非 TF 帧名,仅作设备标识 |
|
|
0 |
— |
|
与预设 id 对应(0=右,1=左) |
|
|
0 |
rad |
|
关节侧当前角。M4010 |
|
|
0 |
rad/s |
|
关节侧角速度(电机 |
|
|
0 |
与力矩保护同量纲 |
|
电机反馈力矩链( |
电机侧 ↔ 关节侧(gear_ratio = 25)
量 |
电机侧(SDK |
话题(关节侧) |
|---|---|---|
位置 |
|
|
速度 |
|
|
力矩 |
|
|
控制下发时节点做相反换算:cmd.q = q_cmd × gear_ratio(目标角 q_cmd 与 position[0] 同量纲,均在关节侧 rad)。
与配置参数的对应
position[0]应与q_open_rad/q_close_rad同标度:录包时全闭接近 0,全开接近 5(本机标定值,改 YAML 后以新标定为准)。主臂
trigger_cmd经trigger_open/trigger_close映射的目标角也在该 rad 标度上;不是扳机的[0,1]无量纲值。effort_limit_enable=true时,节点用r = |effort[0]| / effort_limit做单调钳位、kp 软化、超限回退等(详见dex1_gripper.yaml注释);订阅方若做力控显示,应直接使用effort[0],勿再乘减速比。
发布频率
控制周期:
control_period_us(默认 2000 µs → 500 Hz 控制环)。状态发布:
state_publish_hz(默认 100 Hz),在控制环内分频;header.stamp为该次发布对应的控制周期时刻,非独立慢速采样。仅扫描登记成功的电机会创建 publisher;未接线一侧无对应话题。
6. 底盘节点(lanxin_chassis_controller_node,蓝芯 VMR)
包位置:src/lanxin_chassis_controller/
启动:ros2 launch lanxin_chassis_controller lanxin_chassis_launch.py(launch 文件:src/lanxin_chassis_controller/launch/lanxin_chassis_launch.py)
主要配置:src/lanxin_chassis_controller/config/lanxin_chassis_config.yaml(VMR IP、速度缩放、话题前缀、master_device_id 等)
源码:src/lanxin_chassis_controller/src/lanxin_chassis_controller_node.cpp
备注
说明:与主臂同网段即可;不随 ti5_follow.launch.py 启动。默认通过 完整话题名或 master_topic_prefix 订阅主臂侧 control_cmd、rocker_cmd(配置里常为 /ti5_master_001/...)。
6.1 订阅话题
/<MASTER_ID>/control_cmd(sensor_msgs/msg/JointState)取
name[0],并按:截断命令基名enable_cmd(默认enter_chassis_control)使能底盘摇杆disable_cmds(默认enter_default_mode)停用底盘摇杆控制
/<MASTER_ID>/rocker_cmd(sensor_msgs/msg/JointState)支持两种解析:
按
name匹配left_joy_x/y,right_joy_x/y回退按下标
[0..3]
映射关系:
左摇杆左右 -> 角速度
wz右摇杆前后 -> 线速度
vx右摇杆左右 -> 线速度
vy
6.2 发布话题
无 ROS 话题发布。
控制输出通过 VMR SDK 直接下发底盘速度(非 ROS 话题)。