Files
acRealman_xr/docs/PROMPT.md

14 KiB
Raw Blame History

Claude Code 生成提示词XR-RM75 双臂遥操作 ROS2 项目

下面这份提示词用于交给 Claude Code让它在一个空的 ROS2 Humble 工作空间中生成一个与当前项目大致等价的代码框架。项目不是完整复刻论文中的 XRoboToolkit而是参考其 OpenXR 数据约定、模块化分层和 grip 相对位移遥操作思想落地一个阶段一可调试版本PICO 4 Ultra 双手柄通过 UDP 控制左右 RM75 机械臂的笛卡尔速度。

当前项目整体脉络

项目根目录是 ROS2 workspace 的 src/ 层,面向 Ubuntu 22.04 + ROS2 Humble。当前核心目标是跑通以下闭环

PICO 4 Ultra 双手柄位姿/按键
  -> UDP JSON 数据包
  -> xr_rm_input/udp_controller_receiver
  -> /xr/left_controller 与 /xr/right_controller
  -> xr_rm_teleop/single_arm_velocity_teleop
  -> MockRealManAdapter 或 RealManAdapter
  -> /xr_rm/<arm>/current_pose、target_pose、cmd_vel 调试话题
  -> 真机模式下调用睿尔曼 RM75 Python API2 的 rm_movev_canfd

当前阶段已包含:

  • PICO/OpenXR 手柄 UDP 输入解析。
  • 左右手柄话题分发。
  • 左右 RM75 单臂速度遥操作节点。
  • 通过统一的 arm_debug.launch.py 支持双臂 mock、双臂真机和单臂调试。
  • acRealman 来源的 RM75 IP、工作空间、圆柱半径约束、初始化点位和部分安全配置。
  • Tkinter 启动面板,用于打开 mock、真机、诊断和话题监控命令。

当前阶段暂不实现:

  • XR 侧 Unity 应用。
  • 夹爪 trigger 桥接和末端执行器 launch 集成。
  • 论文中的低延迟立体视频流。
  • QP IK、灵巧手 retarget、全身追踪、运动捕捉 tracker。
  • VLA 数据集记录和训练流程。
  • 双臂碰撞模型、自动采摘算法、移动底盘和升降柱。

论文 XRoboToolkit 对本项目的启发

论文《XRoboToolkit: A Cross-Platform Framework for Robot Teleoperation》的关键思想如下生成代码时只吸收与当前阶段相关的部分

  • XR 侧遵循 OpenXR 坐标约定:右手系,+X 向右,+Y 向上,+Z 向后6DoF pose 使用位置 [x, y, z] 和四元数 [qx, qy, qz, qw]
  • 实时追踪数据可统一放在一个 JSON 对象里传输,控制器字段包括 pose、grip、trigger、摇杆和按钮等。当前项目只需要 pose、grip、trigger、hand。
  • 控制器遥操作使用 grip 作为使能键。为了稳定直观grip 首次按下时锁定手柄起点和机器人 TCP 起点,之后机器人末端跟随“手柄相对位移”,不是直接跟随绝对 pose。
  • XRoboToolkit 是模块化结构XR 输入、PC 服务、机器人控制、视觉反馈、数据记录彼此解耦。当前项目也按 ROS2 package 拆分interfaces、input、teleop、bringup。
  • 论文完整系统包含 QP IK、立体视觉、运动 tracker、灵巧手 retarget 和数据采集。当前项目的 RM75 阶段一只做笛卡尔速度遥操,后续扩展时再接这些模块。

请 Claude Code 生成的项目

请在一个 ROS2 Humble workspace 的 src/ 目录中生成以下四个 package

xr_rm_interfaces/
  CMakeLists.txt
  package.xml
  msg/XrController.msg

xr_rm_input/
  package.xml
  setup.py
  setup.cfg
  resource/xr_rm_input
  launch/udp_receiver.launch.py
  xr_rm_input/__init__.py
  xr_rm_input/udp_controller_receiver.py
  xr_rm_input/sample_udp_sender.py

xr_rm_teleop/
  package.xml
  setup.py
  setup.cfg
  resource/xr_rm_teleop
  xr_rm_teleop/__init__.py
  xr_rm_teleop/realman_adapter.py
  xr_rm_teleop/single_arm_velocity_teleop.py

xr_rm_bringup/
  CMakeLists.txt
  package.xml
  config/dual_arm_rm75.yaml
  config/left_arm_rm75.yaml
  config/right_arm_rm75.yaml
  launch/arm_debug.launch.py
  tools/launcher_ui.py

同时生成根目录 README.md说明构建、mock 验证、真机验证和话题检查方式。

接口定义

xr_rm_interfaces/msg/XrController.msg

std_msgs/Header header
string hand
bool grip
float32 trigger
geometry_msgs/Pose pose

package.xmlCMakeLists.txt 需要使用 rosidl_default_generators 生成该消息,并依赖 std_msgsgeometry_msgs

xr_rm_input 需求

实现 UdpControllerReceiver 节点,职责是把轻量级 XR UDP JSON 转成左右手柄 ROS2 消息。

节点名:udp_controller_receiver

参数:

  • udp_host,默认 0.0.0.0
  • udp_port,默认 15000
  • topic,兼容旧版单话题,默认 /xr/right_controller
  • left_topic,默认 /xr/left_controller
  • right_topic,默认空字符串,为空时使用 topic
  • default_hand,默认 right
  • timer_hz,默认 100.0
  • quat_order,默认 xyzw,可选 wxyz

实现要点:

  • UDP socket 使用非阻塞模式,定时器里循环读取直到 BlockingIOError
  • 支持单手柄 JSON
{
  "hand": "right",
  "grip": true,
  "trigger": 0.2,
  "pos": [0.12, 1.05, -0.32],
  "quat": [0.0, 0.0, 0.0, 1.0]
}
  • 支持双手柄 JSON
{
  "controllers": {
    "left": {
      "grip": true,
      "trigger": 0.0,
      "pos": [-0.12, 1.05, -0.32],
      "quat": [0.0, 0.0, 0.0, 1.0]
    },
    "right": {
      "grip": true,
      "trigger": 0.4,
      "pos": [0.12, 1.05, -0.32],
      "quat": [0.0, 0.0, 0.0, 1.0]
    }
  }
}
  • 也支持数组、多种字段别名:pos/position/pquat/orientation/qpose 对象或 [x,y,z,qx,qy,qz,qw] 列表。
  • hand 归一化:left/l/left_controller 映射为 leftright/r/right_controller 映射为 right
  • grip 支持 bool 和字符串布尔值。
  • trigger clamp 到 [0, 1]
  • 异常包只 warn不让节点崩溃。

实现 sample_udp_sender.py

  • 命令行参数:--host--port--seconds--hz--amplitude--hand left|right|both
  • 按指定频率发送模拟手柄数据。
  • 发送期间 grip=true,结束时给每只手发送一次 grip=false

udp_receiver.launch.py 启动 udp_controller_receiver,暴露 udp_hostudp_porttopic 参数。

xr_rm_teleop 需求

realman_adapter.py

实现三个对象:

  • ArmPose dataclass字段 x,y,z,rx,ry,rz,提供 xyz()
  • MockRealManAdapter:不连接真机,保存当前 posesend_cartesian_velocity() 按控制周期简单积分速度,适合 mock 验证。
  • RealManAdapter:封装睿尔曼 Python API2。

RealManAdapter 要点:

  • 延迟导入 from Robotic_Arm.rm_robot_interface import RoboticArm, rm_thread_mode_e,未安装时抛出清晰错误。
  • connect() 中创建机械臂连接,支持 IP 和端口。
  • 可选下发安全配置:避奇异、最大线速度、最大角速度、线加速度、角加速度、各关节最大速度和加速度。
  • 可选在连接后执行 rm_movej(initial_joint_pose)rm_movel(initial_tcp_pose),默认关闭。
  • 使用 rm_set_movev_canfd_init(avoid_singularity, frame_type, dt_ms) 初始化速度透传。
  • get_current_pose() 从不同 SDK 返回结构中递归解析常见字段:posetool_posetcp_posecurrent_pose
  • send_cartesian_velocity(velocity, follow) 调用 rm_movev_canfd(velocity, follow, 0, 0)
  • stop() 发送零速度并尝试 slow stop。
  • close() 停止并删除机械臂连接。

single_arm_velocity_teleop.py

实现 SingleArmVelocityTeleop 节点。

节点名:single_arm_velocity_teleop

核心参数:

  • arm_name,默认 rm75
  • controller_topic,默认 /xr/right_controller
  • control_rate_hz,默认 50.0
  • command_timeout_sec,默认 0.12
  • scale,默认 1.0
  • kp_linear,默认 2.0
  • deadband_m,默认 0.002
  • low_pass_alpha,默认 0.35
  • max_linear_speed,默认 0.05
  • enable_position_axes,默认 [true, true, true]
  • workspace_minworkspace_max
  • cyl_radius_limit
  • low_z_threshold
  • low_z_min_radius
  • xr_to_robot_matrix,长度 9
  • use_mock
  • mock_initial_pose
  • robot_iprobot_port
  • avoid_singularityframe_typefollow
  • configure_safety_limits
  • max_line_speedmax_angular_speedmax_line_accmax_angular_acc
  • joint_max_speedjoint_max_acc
  • move_to_initial_pose_on_connect
  • initial_joint_poseinitial_tcp_poseinit_move_speed
  • debug_topic_prefix,默认 /xr_rm

控制流程:

  1. 订阅 controller_topicXrController
  2. 每个控制 tick 检查是否收到消息,未收到或超时则 _safe_stop()
  3. grip 未按下时停止输出,并清空 active 状态、手柄起点、机器人起点。
  4. grip 首次按下时只锁定当前手柄位置和当前 TCP 位置,不立即运动。
  5. grip 持续按下时:
    • 计算 controller_delta = controller_now - controller_start
    • xr_to_robot_matrix 映射为机器人坐标增量
    • target = robot_start + scale * robot_delta
    • 先按 workspace_min/max 限幅,再按 cyl_radius_limit 限制基座圆柱半径,低高度区域使用 low_z_min_radius
    • error = target - robot_now
    • 对禁用轴清零
    • 小于 deadband_m 输出零速度,否则 velocity = kp_linear * error
    • 按向量范数限制 max_linear_speed
    • 做一阶低通滤波
    • 拼成 [vx, vy, vz, 0, 0, 0] 发送给 adapter
  6. 发布调试话题:
    • /xr_rm/<arm_name>/current_posePoseStamped
    • /xr_rm/<arm_name>/target_posePoseStamped
    • /xr_rm/<arm_name>/cmd_velTwistStamped
  7. 所有异常、断连、松手、退出都要发送零速度。

注意:当前阶段只控制 TCP 平移,不控制姿态。

bringup 配置需求

RM75 默认参数

沿用以下现场参数:

  • 左臂 IP192.168.192.18
  • 右臂 IP192.168.192.19
  • TCP 端口:8080
  • 左臂工作空间:x[-0.50, 0.50] y[-0.60, -0.20] z[0.10, 0.50]
  • 右臂工作空间:x[-0.70, 0.50] y[-0.60, 0.40] z[0.10, 0.70]
  • 左右臂圆柱半径限制:[0.20, 0.60]
  • low_z_threshold=0.20
  • low_z_min_radius=0.21
  • 保守速度:max_linear_speed=0.04
  • scale=0.75
  • kp_linear=1.8
  • low_pass_alpha=0.35

坐标映射

遵循论文中的 PICO/OpenXR 坐标:+X 向右,+Y 向上,+Z 向后。

左臂 base 坐标:+X 向下,+Z 向右,前方工作区对应 -Y

左臂映射:

robot_delta = [-controller_y, -controller_z, controller_x]
xr_to_robot_matrix:
[0.0, -1.0, 0.0,
 0.0,  0.0, -1.0,
 1.0,  0.0, 0.0]

右臂 base 坐标:+X 向上,+Z 向左,前方工作区对应 -Y

右臂映射:

robot_delta = [controller_y, -controller_z, -controller_x]
xr_to_robot_matrix:
[0.0, 1.0, 0.0,
 0.0, 0.0, -1.0,
 -1.0, 0.0, 0.0]

初始点位

左臂:

mock_initial_pose: [-0.2562, -0.2765, 0.1489, -3.0190, -0.1010, 3.1400]
initial_joint_pose: [-167.21, 28.48, 28.21, 61.35, -14.40, 84.49, -124.51]
initial_tcp_pose: [-0.2562, -0.2765, 0.1489, -3.0190, -0.1010, 3.1400]

右臂:

mock_initial_pose: [0.2663, -0.2606, 0.1027, 3.0330, 0.0000, 1.0910]
initial_joint_pose: [-25.60, 34.09, -19.55, 71.59, 16.97, 80.98, 59.67]
initial_tcp_pose: [0.2663, -0.2606, 0.1027, 3.0330, 0.0000, 1.0910]

真机 launch 默认不要自动移动到初始化点,只有显式设置 move_to_initial_pose_on_connect:=true 才执行。

launch 文件

arm_debug.launch.py

  • 参数 arm:=left|right|both
  • 参数 use_mock:=true|false
  • 单臂时读取 left_arm_rm75.yamlright_arm_rm75.yaml
  • 双臂时读取 dual_arm_rm75.yaml
  • 总是启动 udp_controller_receiver
  • 这是唯一的遥操作 launch 主入口UI 和命令行调试都优先使用它。

启动面板

tools/launcher_ui.py 做一个简单 Tkinter 面板即可:

  • 自动寻找 workspace 根目录。
  • 每个终端启动前 source /opt/ros/humble/setup.bashinstall/setup.bash
  • 模式包括 Simulation、Left Arm、Right Arm、Dual Arm、Diagnostics。
  • 提供按钮运行 mock launch、真机 launch、sample UDP sender、topic list、node list、topic echo。
  • 提供清理按钮,能关闭由面板启动的终端或进程。

README 运行流程

README 需要包含以下命令。

构建:

source /opt/ros/humble/setup.bash
rosdep update
rosdep install --from-paths src -y --ignore-src
colcon build --symlink-install
source install/setup.bash

mock 验证:

ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=true
ros2 run xr_rm_input sample_udp_sender --hand both --host 127.0.0.1 --port 15000

检查话题:

ros2 topic echo /xr/left_controller
ros2 topic echo /xr/right_controller
ros2 topic echo /xr_rm/left_rm75/cmd_vel
ros2 topic echo /xr_rm/right_rm75/cmd_vel

单臂调试:

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
ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=true

真机启动:

ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=false \
  left_robot_ip:=192.168.192.18 \
  right_robot_ip:=192.168.192.19

安全验证说明:

  • 首次真机测试保持 max_linear_speed <= 0.04
  • 先只上右臂,再上左臂。
  • 每次按住 grip 后分别检查上、前后、左右方向。
  • 方向反了只改对应臂 YAML 中 xr_to_robot_matrix 的符号。
  • 当前没有双臂碰撞模型,首次测试要让两臂工作区物理分离。

代码风格和验收标准

代码要求:

  • Python 使用类型标注,异常信息清晰。
  • ROS2 节点退出时必须安全停止机械臂。
  • mock 模式不得导入或依赖睿尔曼 SDK。
  • 真机 SDK 未安装时要提示使用 use_mock:=true 或安装厂商 API2。
  • 参数校验要覆盖控制频率、timeout、低通系数、工作空间上下界、圆柱半径。
  • 不要引入论文中当前阶段不需要的大型依赖,如 Unity、PlaCo、Pinocchio、MuJoCo、视频流模块。

验收标准:

  • colcon build --symlink-install 能通过。
  • ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=true 能启动三个节点。
  • sample_udp_sender --hand both 后能看到左右 /xr/*_controller/xr_rm/*/cmd_vel
  • 松开 grip、UDP 超时、节点退出时都会发送零速度。
  • 修改 YAML 中 xr_to_robot_matrix 能改变对应臂方向映射。
  • 真机模式只在 use_mock=false 时尝试连接 RM75。