Files
acRealman_xr/docs/superpowers/specs/2026-08-04-dual-arm-mujoco-teleoperation-design.md

250 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 双臂 MuJoCo 运动学遥操作设计
## 背景与目标
当前项目已经通过 PICO/XR 手柄、两个独立的单臂遥操作节点和 Placo QP 完成双
RM75 遥操作。左右节点共同加载
`xr_rm_teleop/models/dual_rm75/Dual_arm.urdf`,但现有 `use_mock:=true` 只在内存中
保存关节状态,没有可视化模型。
本次变更增加一个独立的 MuJoCo 运动学仿真包,使双臂在不连接真机时可以由 PICO
遥操作并可视化,也允许连接真机时把实际关节反馈同步显示在 MuJoCo 中。仿真用于更
方便地观察和改进现有 QP 算法,不替代现有控制与安全链路。
首版目标:
- 直接加载现有双臂 URDF,保持它是唯一模型源;
- 复用现有 PICO 输入、目标生成、工作空间限制和 Placo QP;
- 使用一个 MuJoCo 进程显示完整 14 关节双臂模型;
- 无真机时显示 Mock 关节状态,连接真机时显示实际关节反馈;
- 支持 Mock 模式下用左手 X、右手 A 立即 Reset 对应机械臂;
- 保持当前 mock、真机和夹爪功能的默认行为不变。
首版不实现 MuJoCo 动力学、执行器、接触、碰撞约束、双臂协同 QP、轨迹记录或
MuJoCo 对真机的任何控制。
## 目录与包边界
新增独立的 `ament_python``xr_rm_mujoco`,运行配置仍统一由
`xr_rm_bringup` 管理:
```text
src/
├── xr_rm_mujoco/
│ ├── package.xml
│ ├── setup.py
│ ├── setup.cfg
│ ├── resource/
│ │ └── xr_rm_mujoco
│ ├── xr_rm_mujoco/
│ │ ├── __init__.py
│ │ └── dual_arm_simulator.py
│ └── test/
│ └── test_dual_arm_simulator.py
├── xr_rm_bringup/
│ ├── config/
│ │ ├── dual_arm_rm75.yaml
│ │ └── dual_arm_mujoco.yaml
│ └── launch/
│ └── arm_debug.launch.py
└── xr_rm_teleop/
├── models/
│ └── dual_rm75/
│ └── Dual_arm.urdf
└── xr_rm_teleop/
└── single_arm_velocity_teleop.py
```
各部分职责:
- `xr_rm_mujoco` 只加载模型、接收关节状态、更新 MuJoCo `qpos` 和刷新画面;
- `xr_rm_teleop` 继续负责 PICO 映射、目标滤波、安全限幅、QP 和适配器选择,只
增加关节目标及当前关节状态发布;
- `xr_rm_bringup` 保持唯一遥操作 launch 入口,并保存 MuJoCo 运行参数;
- `Dual_arm.urdf` 和现有 meshes 保持原位置,不复制或生成持久化 MJCF;
- 不拆出新的 description 包,不增加第二套遥操作实现。
## 模型与 MuJoCo 更新方式
`dual_arm_simulator` 从安装空间解析
`xr_rm_teleop/models/dual_rm75/Dual_arm.urdf`,MuJoCo 直接加载该文件及其相对路径
网格。节点按 URDF 关节名称查找 MuJoCo qpos 地址,不写死 14 个数组下标。
左右首帧合法关节状态到达后,节点把状态写入相应 `qpos`,调用 `mj_forward()`
更新运动学,再由被动 viewer 显示。首版不调用 `mj_step()` 推进动力学,MuJoCo
不会生成控制量或新的关节运动。
画面按 `60 Hz` 刷新。`xr_rm_bringup/config/dual_arm_mujoco.yaml` 首版只包含:
```yaml
dual_arm_simulator:
ros__parameters:
render_rate_hz: 60.0
```
初始关节角不在该文件中重复配置。
## ROS 话题与状态来源
左右遥操作节点使用标准 `sensor_msgs/msg/JointState` 发布:
| 话题 | 内容 |
|---|---|
| `/xr_rm/left_rm75/joint_states` | 左臂当前适配器反馈 |
| `/xr_rm/right_rm75/joint_states` | 右臂当前适配器反馈 |
| `/xr_rm/left_rm75/joint_target` | 左臂经关节限速后实际下发的目标 |
| `/xr_rm/right_rm75/joint_target` | 右臂经关节限速后实际下发的目标 |
MuJoCo 只订阅两个 `joint_states` 话题。`joint_target` 用于后续记录和比较,不驱动
MuJoCo。消息必须携带对应侧完整的 7 个关节名称和位置,MuJoCo 按名称映射,不能
依赖消息数组顺序。
状态来源由现有 `use_mock` 唯一决定:
```text
use_mock:=true
PICO → Placo QP → MockRealManAdapter → joint_states → MuJoCo
use_mock:=false
PICO → Placo QP → RealManAdapter → 真机
真机实时反馈 → joint_states → MuJoCo
```
每个遥操作节点只创建一种适配器。真机连接或反馈失败时不得创建、切换或回退到
Mock。MuJoCo 不需要独立的状态来源参数;同一状态话题发现多个发布者时输出明确
报警,防止同时运行两套 launch 造成状态混合。
## 更新频率
两侧 `dual_arm_rm75.yaml``control_rate_hz` 均为 `90.0`
- Mock 模式:Mock 状态在遥操作节点的 `90 Hz` 控制周期中读取并发布,MuJoCo
名义关节接收频率为 `90 Hz`
- 真机模式:RealMan 的 `realtime_push_cycle_ms: 5` 使适配器原始反馈名义频率为
`200 Hz`,遥操作节点在 `90 Hz` 控制周期取最新快照并发布,因此 MuJoCo 名义
关节接收频率仍为 `90 Hz`
- 画面独立按 `render_rate_hz: 60.0` 刷新,每帧显示当时最新的 14 关节状态。
以上是名义频率,实际频率会受系统调度影响,运行时使用 `ros2 topic hz` 检查。
## 初始姿态与 A/X Reset
`dual_arm_rm75.yaml` 继续作为双臂初始姿态和控制限制的唯一配置源。Mock 适配器
创建时已经读取对应节点的 `initial_joint_pose`,将角度转换成弧度并作为初始关节
状态。左右遥操作节点初始化完成后立即各发布一帧状态,因此无真机 MuJoCo 的默认
姿态就是 YAML 中的左右初始姿态。
现有 `XrController.primary` 和按键上升沿逻辑继续复用:
```text
左手 X → 左臂立即 Reset 到左臂 initial_joint_pose
右手 A → 右臂立即 Reset 到右臂 initial_joint_pose
同时按 X、A → 双臂分别立即 Reset
```
Mock Reset 不生成平滑轨迹,而是立即更新对应 7 个关节并发布新状态。Reset 前先
退出旧的相对位姿控制;如果 Grip 仍保持按下,下一控制周期使用“当前手柄姿态 +
Reset 后机械臂姿态”自动建立新基准,随后可以继续遥操作,不要求先松开 Grip,
也不能沿用 Reset 前的相对位姿基准。
真机的 A/X 回位行为保持现状:调用 RealMan 初始位姿运动,完成后重新同步反馈,
并要求先松开 Grip 才能重新使能。该差异只由 `use_mock` 决定。
三份 RM75 配置中的 `move_to_initial_pose_on_connect` 默认继续保持 `false`。MuJoCo
初始显示和按键 Reset 都不依赖该开关,连接真机时不得默认自动移动双臂。
## 控制限制与安全隔离
Mock + MuJoCo 继续执行 `dual_arm_rm75.yaml` 中现有的软件控制约束:
- `workspace_min``workspace_max``cyl_radius_limit` 和低位圆柱限制;
- `max_linear_speed``max_orientation_speed`
- `joint_max_speed``joint_max_acc`
- Placo 的关节位置、速度和求解收敛检查;
- Grip 运动门控、XR/反馈超时、QP 失败保持和安全停止。
MuJoCo 直接显示已经受限的离散关节状态,本身不额外模拟连续动力学。
`max_line_speed``max_angular_speed``max_line_acc``max_angular_acc` 以及
`configure_safety_limits` 是 RealMan 控制器配置,只在真机适配器中调用;这不影响
上述对 Mock 同样生效的软件限位。
MuJoCo 节点只订阅状态,不发布机器人控制指令,不导入 RealMan SDK,也不创建新的
RealMan 连接。MuJoCo 启动失败、运行异常或窗口关闭不得改变真机命令、安全停止或
夹爪行为。
## 启动设计
继续使用唯一入口 `xr_rm_bringup/launch/arm_debug.launch.py`,增加默认关闭的
`use_mujoco` 参数:
| `use_mock` | `use_mujoco` | 行为 |
|---|---|---|
| `true` | `false` | 现有内存 Mock,无 MuJoCo |
| `true` | `true` | Mock + MuJoCo 双臂显示 |
| `false` | `false` | 现有双臂真机遥操作 |
| `false` | `true` | 双臂真机遥操作 + 实际反馈同步显示 |
`use_mujoco` 不参与适配器选择。首版只接受
`arm:=both use_mujoco:=true`,避免单臂启动时另一侧状态和初始姿态不明确。
无真机使用方式:
```bash
ros2 launch xr_rm_bringup arm_debug.launch.py \
arm:=both use_mock:=true use_mujoco:=true
```
真机同步显示方式:
```bash
ros2 launch xr_rm_bringup arm_debug.launch.py \
arm:=both use_mock:=false use_mujoco:=true
```
第二条命令会连接并控制真机,只能在完成现有真机安全检查后使用。所有自动化和首次
集成验收只运行 `use_mock:=true`
MuJoCo 进程使用项目现有的 XR Conda Python,因为本机 MuJoCo 与 Placo 均安装在
该环境中。未启用 `use_mujoco` 时不启动或导入 MuJoCo,新包不能让现有 mock 模式
强制依赖厂商 SDK。
## 校验与异常处理
- URDF、网格或 MuJoCo 加载失败:MuJoCo 节点明确报错并退出,现有遥操节点不改变;
- 收到关节缺失、重复、数量错误或包含 NaN/Inf 的消息:拒绝整帧并保持上一姿态;
- 尚未收齐左右首帧状态:等待并报告缺失侧,不把零位姿冒充有效初始姿态;
- 任一侧状态暂时中断:保持该侧最后有效姿态,不生成运动、不切换来源;
- 同一状态话题存在多个发布者:输出明确报警;
- viewer 关闭:只结束 MuJoCo 显示,不触发或改变机器人运动。
## 测试与验收
使用现有 pytest、ROS2 Humble 和 colcon,不增加测试框架,不连接真机。
最小自动化覆盖:
- MuJoCo 可以直接加载现有双臂 URDF;
- 14 个活动关节名称与左右 qpos 映射正确,消息顺序变化不会串臂;
- YAML 初始角度经 Mock 转换后能正确写入 MuJoCo
- 非法关节消息不会部分污染当前状态;
- Mock A/X Reset 后回到对应 YAML 姿态;
- Reset 时 Grip 保持按下能够重新锚定并继续控制;
- 真机路径仍保留 Grip 松开后重新使能要求;
- `use_mujoco` 默认关闭,现有三种 mock/真机启动行为不变。
在工作空间根目录执行:
```bash
cd /home/robot/WS_xr
source /opt/ros/humble/setup.bash
/home/robot/miniconda3/envs/xr/bin/python -m pytest \
src/xr_rm_mujoco/test/test_dual_arm_simulator.py -v
pytest src/xr_rm_teleop/test/test_joint_control.py -v
pytest src/xr_rm_teleop/test/test_orientation_control.py -v
colcon build --symlink-install
```
构建后只用 Mock 启动并通过 PICO 或 sample UDP 检查:左右模型初始姿态、独立运动、
A/X Reset、Reset 后继续遥操作、话题频率和关闭 viewer 后遥操作节点状态。不得在
自动化验收中使用 `use_mock:=false`