Files
linkerhand_retarget_ros2/docs/O30右手三相机标定与URDF修正操作说明.md
2026-08-17 17:55:13 +08:00

6.3 KiB
Raw Permalink Blame History

O30 右手三相机标定与 URDF 修正操作说明

支持范围:O30 右手、20 个有效电机、20 个主动 URDF 关节。

1. 固定输入

O30 SDK 工程:

/home/lxp/projects/linkerhand-o30-ros2

原始 CAD URDF:

/home/lxp/projects/linkerhand-urdf/O30/urdf_0803-right/src/linkerhand_O30i_right.urdf/linkerhand_O30i_right-0803.urdf

标定基准命令固定为:

[0, 0, 255, 205, 165, 20,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

20 个通道均按完整 255→0→255 行程扫描。Tag 0~10 的机位、ID 和 父子连杆角色与 G20 右手标定保持一致。

2. SDK 与 URDF 映射

SDK 下标 SDK 名称 URDF 关节
0 thumb_roll thumb_cmc_roll
1 thumb_yaw thumb_cmc_yaw
2~5 index/middle/ring/little_yaw 四指 mcp_roll
6 thumb_root1 thumb_mcp
7~10 四指 root1 四指 mcp_pitch
11~14 四指 root2 四指 pip
15 thumb_tip thumb_ip
16~19 四指 tip 四指 dip

O30 没有 thumb_cmc_pitch,也没有 G20 的被动 IP/DIP;O30 JSON 中的 20 个 URDF 关节全部标记为主动关节。

3. 扫描任务

右手以小指为四指参考源,共执行 8 个任务、每项 3 轮:

顺序 关节 电机 机位
1 thumb_cmc_roll 0 front
2 thumb_mcp 6 front
3 thumb_ip 15 front
4 pinky_mcp_roll 5 front
5 pinky_mcp_pitch 10 side
6 pinky_pip 14 side
7 pinky_dip 19 side
8 thumb_cmc_yaw 1 top

总计 8 × 3 × 2 = 48 个唯一扫描方向。O30 每一轮固定按 0→255、255→0 完成一次往返,因此单关节三轮均为 0→255→0,并在 每轮第一个方向前重新初始化活动机位的PnP跟踪。状态中的计划进度只统计48个 唯一方向,另行显示包含自动重扫在内的实际执行方向次数。扫描小指 mcp_roll 时,电机 2/3/4 固定为 255,使未贴 Tag 的三指避开正面机位。

O30 命令增大时 URDF 动态角度增大;这与 G20 的命令—角度方向相反,标定 JSON 会保存单调非递减曲线,并在各电机自己的基准命令处严格归零。

O30 的固件反馈端点允许使用独立于 G20 的到位死区:一般通道为 ±4 u8; 拇指 CMC 侧摆电机 0 在低速命令 255 端为 ±9 u8; 食指 MCP 侧摆电机 2 在命令 255 端为 ±8 u8; O30 固件的速度 0 仍然很快,且实机位置-时间模式无法可靠连续往返,因此标定 强制使用普通位置模式和最低内部速度 o30_internal_speed_u8:=0。标定节点只发送 最终目标,O30 SDK 在独立的约 125 Hz 控制线程中生成单字节位置斜坡,避免相机/PnP 计算延迟导致 3~5 u8 的补偿跳步。默认 o30_command_full_range_seconds:=6.0, 完整走过 0~255 约需 6 秒,两个方向采用相同限速。暂停、终止或异常时立即把 斜坡目标替换为当前反馈并恢复直控模式。该策略不改变安全扫描范围,也不改变四指 MCP 侧摆静态零位固定为 CAD 0 的规则。拇指 CMC 侧摆使用 1 u8 细步,其余 通道累计 3 u8 后再向固件更新目标;后者为每个目标留出保持时间,避免电机6等 关节因持续刷新单格目标而一直不启动,总体斜率和正反向用时保持不变。 拇指 MCP(电机 6)在命令 0 端实测稳定反馈为 7,因此该端使用 ±8 u8。 这些门限只判断固件是否已经稳定到位,不改变实际下发的 0~255 扫描范围。

4. 静态 URDF 零位策略

  • 四指 mcp_roll:测量小指动态曲线,但四个关节的静态 URDF 零偏全部固定为 0。
  • 小指 mcp_pitch:可由下游 PIP 轴观测并通过留出验证后修正。
  • 小指 pip:可由下游 DIP 轴线相位观测并通过留出验证后修正。
  • 小指 dip、拇指 ip:没有下游观察关节,静态零偏固定为 0。
  • 食指、中指、无名指:动态曲线从小指曲线按各自基准命令重新归零;静态偏差不继承。
  • 拇指 cmc_roll/cmc_yaw/mcp:按相邻下游轴逐级求解并执行第三轮留出验证。

修正 URDF 只改通过验证的关节 origin.rpy,不改 origin.xyz、axis、 mesh、连杆长度和 CAD 限位。生成后的 URDF 不能作为下一次标定的源文件。

5. 启动

先保证 O30 SDK 已编译,并依次加载 ROS、O30 SDK 和本工程:

source /opt/ros/jazzy/setup.bash
source /home/lxp/projects/linkerhand-o30-ros2/install/setup.bash
source /home/lxp/projects/linkerhand_retarget_ros2/install/setup.bash

预检(不运动):

ros2 launch g20_thumb_apriltag_calibration \
  three_camera_calibration.launch.py \
  hand_model:=O30 hand_type:=right \
  serial_number:=O30_RIGHT_001 \
  source_urdf_path:=/home/lxp/projects/linkerhand-urdf/O30/urdf_0803-right/src/linkerhand_O30i_right.urdf/linkerhand_O30i_right-0803.urdf \
  camera_extrinsics_file:=/home/lxp/projects/linkerhand_retarget_ros2/config/o30_three_camera_extrinsics.yaml \
  start_sdk:=false commands_enabled:=false

正式启动,蓝色/黑色厂商 CANFD 盒:

ros2 launch g20_thumb_apriltag_calibration \
  three_camera_calibration.launch.py \
  hand_model:=O30 hand_type:=right \
  serial_number:=O30_RIGHT_001 \
  source_urdf_path:=/home/lxp/projects/linkerhand-urdf/O30/urdf_0803-right/src/linkerhand_O30i_right.urdf/linkerhand_O30i_right-0803.urdf \
  camera_extrinsics_file:=/home/lxp/projects/linkerhand_retarget_ros2/config/o30_three_camera_extrinsics.yaml \
  o30_comm_type:=libcanbus canfd_device:=0 o30_auto_setup:=false \
  o30_internal_speed_u8:=0 o30_command_full_range_seconds:=6.0

三个机位预检通过后查看状态并启动:

ros2 topic echo /o30_calibration/status_text
ros2 service call /o30_calibration/start std_srvs/srv/Trigger {}

暂停、继续和终止服务分别为:

/o30_calibration/pause
/o30_calibration/resume
/o30_calibration/abort

6. 产物

会话目录中生成:

raw_samples.jsonl
o30_right_<serial>_calibration.json

修正 URDF 默认生成在原始 URDF 同目录,文件名包含 zero_calibrated_<serial>_<timestamp>。JSON 的动态角度必须和这次生成的修正 URDF 配套使用;运行时不能再次叠加 urdf_zero_offset_rad。