Files
acRealman_xr/docs/superpowers/specs/2026-07-28-rm75-so3-omnipicker-teleop-design.md
T

242 lines
10 KiB
Markdown
Raw 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.
# RM75 SO(3) 姿态跟随与 OmniPicker 一体化模型设计
日期:2026-07-28
状态:已确认
## 1. 背景与目标
当前遥操作链路已经使用 Placo QP 将 TCP 目标转换为 RM75 七关节目标,但姿态目标在进入 QP 前会转换为 RPY,并按三个欧拉角分量进行滤波和限速。RM75 当前姿态接近俯仰角 `±90°` 时,同一个物理姿态可能切换到另一组等价 RPY,导致控制器把很小的手柄旋转解释为大角度路径,出现机械臂绕行和跟随时间过长。
本设计是
`2026-07-27-rm75-placo-qp-ik-design.md`
的增量修改;它覆盖旧设计中的模型、TCP 变换、姿态表示、控制频率和相关验收
内容。现有的关节反馈、单步 QP、`rm_movej_canfd`、last-known-good 和停止链路
继续保留。
本次修改的目标是:
1. 姿态控制全程使用旋转矩阵和 SE(3),按 SO(3) 最短旋转路径滤波和限速。
2. 左右臂统一使用用户提供的 `RM75-B_OmniPicker_fixed.urdf`
3. 在 URDF 内定义 `omnipicker_tcp`,取消 Placo 中重复的运行时末端变换。
4. 首轮真机测试继续使用低跟随,将控制频率设为 `125 Hz`TCP 目标角速度上限统一为 `0.5 rad/s`
5. 保留现有工作空间、圆柱、关节速度、指令超时和安全停止行为。
## 2. 本次不处理的内容
- 不开启高跟随,`follow` 继续为 `false`
- 不改变现有 Wi-Fi/有线混合网络拓扑。
- 不新增高跟随周期看门狗。
- 不修改 `avoid_singularity`,不新增奇异点检测或降速策略。
- 首轮不删除或调整现有可操作度优化任务。
- 不修改 `peripherals_rm75.yaml` 中的夹爪选择、工具位姿或负载。
- 不新增 ROS2 节点、消息、求解器工厂或第三方依赖。
- Codex 不连接或移动真实机械臂和夹爪。
## 3. 姿态数据模型
控制路径中的机器人位姿统一为有限的 `4×4` NumPy SE(3) 矩阵:
```text
T = [ R p ]
[ 0 1 ]
```
其中 `R``3×3` 旋转矩阵,`p` 为 TCP 在机器人基坐标系下的位置。Placo 正解直接返回该矩阵,QP 目标也直接接收该矩阵。现有仅保存 `x/y/z/rx/ry/rz``ArmPose` 不再作为控制路径接口,避免在遥操作节点与 Placo 之间发生 RPY 往返转换。
ROS 调试边界按消息类型转换:
- `PoseStamped`:旋转矩阵转换为四元数后发布。
- `TwistStamped.angular`:发布相邻两个目标旋转之间、在机器人基坐标系表达的 SO(3) 旋转向量速度。
## 4. XR 姿态到机器人姿态
Grip 按下时保存 XR 初始四元数和当前 `omnipicker_tcp` 初始旋转矩阵。每周期计算:
```text
R_xr_delta = R_xr_now * transpose(R_xr_start)
R_robot_delta = M * R_xr_delta * transpose(M)
R_raw_target = R_robot_delta * R_robot_start
```
`M` 为现有 `xr_to_robot_matrix`,其左右臂映射保持不变。`enable_orientation_axes` 继续保留;被关闭的机器人基坐标轴通过将对应 SO(3) 相对旋转向量分量置零实现,不再通过拼接 RPY 分量实现。
姿态处理统一使用基坐标系下的左乘增量:
```text
R_error = R_target * transpose(R_current)
r = Log(R_error)
R_next = Exp(scale * r) * R_current
```
处理顺序为:
1.`norm(Log(R_target * R_lastᵀ))` 判断 `orientation_deadband_rad`
2.`orientation_filter_alpha` 缩放从滤波状态到目标的最短旋转向量。
3. 将从上一发送姿态到滤波姿态的旋转角限制在
`max_orientation_speed / control_rate_hz` 以内。
4. 将限速后的旋转和已通过现有工作空间限制的位置合成为 SE(3)。
该路径不使用 RPY 展开、分量插值或分量限速。相对旋转接近 `π` 时也必须选择物理最短路径;四元数 `q``-q` 必须得到相同目标。
位姿误差采用与 Placo `FrameTask` 一致的解耦 `3+3` 形式:
```text
e_position = p_target - p_current
e_orientation = Log(R_target * transpose(R_current))
e_pose = [e_position; e_orientation]
```
其中 `e_pose` 可视为六维任务误差,但不是
`Log_SE3(T_target * inverse(T_current))`。本次不引入完整 SE(3) 对数映射中的
平移—旋转耦合。
## 5. URDF 与 TCP
用户上传的
`/home/robot/下载/Models/RM75-B_OmniPicker_Pinocchio.zip`
作为模型来源。将 fixed URDF 和被引用的 RM75、OmniPicker mesh 放入
`xr_rm_teleop/models/rm75_omnipicker`,由现有 `xr_rm_teleop` 包安装。
`RM75-B_OmniPicker_fixed.urdf` 中增加:
```xml
<link name="omnipicker_tcp"/>
<joint name="omnipicker_tcp_joint" type="fixed">
<parent link="omnipicker_base_link"/>
<child link="omnipicker_tcp"/>
<origin xyz="0 0 0.16" rpy="0 0 0"/>
</joint>
```
该变换表示 TCP 相对 RM75 法兰坐标系沿 `+Z` 方向平移 `0.16 m`、坐标轴方向不变。上传模型中 `rm75_flange``omnipicker_base_link` 为零固定变换,因此上述定义与已确认的法兰到 TCP 变换一致。
`arm_debug.launch.py` 的左臂、右臂和双臂节点统一加载这一份 fixed URDF。模型仍只有 `joint_1``joint_7` 七个运动关节,OmniPicker 关节均保持 fixed。
## 6. Placo QP
`PlacoIkSolver` 改为:
```text
构造参数:URDF 路径、dt
当前位姿:get_T_world_frame("omnipicker_tcp")
目标任务:add_frame_task("omnipicker_tcp", target_se3)
```
删除仅供 Placo 使用的 `tool_pose` 构造参数、`_tool_transform`
`_tool_inverse` 和对应的法兰/TCP换算函数。`peripherals_rm75.yaml` 保持原状,
仍供 `RealManAdapter` 配置真实控制器的工具坐标、负载和末端外设;其中的
`pose` 不再传入 Placo,因此不会在 QP 中重复叠加末端偏移。
QP 配置首轮保持:
```text
frame task: soft, 1.0
manipulability task: soft, 5e-2
kinetic energy regularizer: 1e-6
```
可操作度任务已知会造成目标静止时的关节姿态变化,但按用户决定本轮保留,
待确认 RPY 绕行消失后再单独评估。关节位置和单周期速度校验继续使用 URDF
限制,固定虚拟基座和 `q[7:14]` 的七关节映射保持不变。
## 7. 参数与启动行为
以下配置在 `left_arm_rm75.yaml``right_arm_rm75.yaml`
`dual_arm_rm75.yaml` 对应节点中同步:
```yaml
control_rate_hz: 125.0
orientation_deadband_rad: 0.005
orientation_filter_alpha: 0.65
max_orientation_speed: 0.5
follow: false
```
`arm_debug.launch.py``control_rate_hz` 默认值同步为 `125.0``follow`
默认值继续为 `false``single_arm_velocity_teleop` 内部参数默认值同步,
避免绕过 YAML 启动时回到旧频率或旧角速度。
`right_arm_rm75.yaml``move_to_initial_pose_on_connect``True` 改为
`false`,与左臂、双臂以及 launch 默认安全行为一致。其他左右臂空间范围、
线速度、关节速度、加速度、初始关节角和外设配置不变。
## 8. 异常与停止
现有异常策略保持:
- 非法 XR 四元数、Grip 松开、XR 超时、关节反馈过期或通信失败时执行现有慢停止并重置激活状态。
- QP 失败或输出违反关节位置/速度限制时继续使用上一组有效关节目标。
- 第一次有效关节反馈前不发送运动命令。
- `configure_safety_limits` 保持启用。
- Mock 模式不导入睿尔曼 SDK。
新增 SO(3) 运算必须拒绝非有限矩阵和零四元数。旋转矩阵若满足
`norm(RᵀR-I) <= 1e-3` 且行列式为正,则使用 `3×3` SVD 投影到最近的合法旋转;
超出该范围时停止输出,不能把明显无效的输入静默修正成运动目标。
## 9. 验证
### 9.1 自动测试
扩展 `test_orientation_control.py`,至少覆盖:
- 初始姿态俯仰接近 `+90°``-90°` 时,小手柄旋转仍产生相同量级的最短物理旋转。
- 目标跨越原 RPY 表示分支时,不产生接近 `π` 的错误路径。
- `q``-q` 产生相同旋转矩阵。
- SO(3) 死区使用整体旋转角。
- 每周期姿态步长不超过 `0.5 / 125 rad`
- SO(3) 滤波沿最短路径收敛。
- 调试四元数有限且归一化。
更新 Placo 变换测试和 smoke test,验证:
- fixed URDF 可加载,运动关节仍严格为七个且顺序正确。
- `omnipicker_tcp` 相对法兰的变换为 `[0, 0, 0.16]` 和单位旋转。
- 当前/原始目标/发送目标均表示 `omnipicker_tcp`
- 一次 QP 输出七个有限关节角并满足位置与单周期速度限制。
- 目标静止两秒时记录左右臂最大关节变化,但本轮不以 `≤0.5°` 作为通过条件。
- 目标停止后 TCP 位置误差不超过 `5 mm`、姿态误差不超过 `2°`
### 9.2 命令
所有命令从 `/home/robot/WS_xr` 执行:
```bash
source /opt/ros/humble/setup.bash
PYTHONPATH=src/xr_rm_teleop pytest -q \
src/xr_rm_teleop/test/test_orientation_control.py
source /opt/ros/humble/setup.bash
colcon build --symlink-install
source /opt/ros/humble/setup.bash
source install/setup.bash
ros2 launch xr_rm_bringup arm_debug.launch.py arm:=left use_mock:=true
ros2 launch xr_rm_bringup arm_debug.launch.py arm:=right use_mock:=true
```
Placo smoke test继续使用已验证的
`/home/robot/miniconda3/envs/xr/bin/python`,周期改为 `1/125 s`
### 9.3 真机人工验收
Codex 只提供步骤,不执行真机操作。用户应分别测试左右臂:
1. 确认急停可用、周围无障碍物且 `move_to_initial_pose_on_connect=false`
2. 先保持手柄和目标姿态不变,记录 TCP 与关节变化。
3. 仅改变手柄姿态,重点跨越原俯仰 `±90°` 附近的 RPY 分支。
4. 确认 TCP 以最短物理旋转跟随,没有绕一大圈。
5. 确认 `omnipicker_tcp` 位置保持在允许误差内。
## 10. 完成标准
1. 控制路径中的目标生成、滤波、限速和 QP 接口不再使用 RPY。
2. 左右臂都由同一 fixed URDF 的 `omnipicker_tcp` 作为控制帧。
3. Placo 不再使用 `peripherals_rm75.yaml` 的工具位姿进行矩阵换算。
4. 可操作度任务保持现状,漂移数据被记录但不作为首轮阻断项。
5. 三份配置使用 `125 Hz``0.5 rad/s` 和低跟随。
6. 右臂连接时不再自动移动到初始关节姿态。
7. 指定测试、构建和左右臂 mock 启动验证通过。
8. 未改变工作空间、圆柱、关节限制、指令超时、安全停止或奇异点设置。