运动规划概述

相关源文件

以下文件用作生成此 wiki 页面的上下文:

MoveIt2 集成为 IB-Robot 中的机械臂提供基于轨迹的运动规划和逆运动学 (IK) 求解。该系统支持高级基于位姿的控制、碰撞避免和约束运动规划。该集成专门设计用于通过特殊的 IK 求解策略处理 SO101 机械臂的 5 自由度 (5DOF) 运动学约束。

关于使用模型推理的端到端 AI 策略控制,请参阅 动作分发。关于控制模式切换,请参阅 控制模式架构


系统架构

MoveIt2 作为 IB-Robot 中三种控制模式之一运行,通过运动规划和 IK 求解将高级笛卡尔位姿命令转换为关节轨迹。

IB-Robot 中的 MoveIt 集成

graph TB subgraph "Application Layer" USER["User/Application"] CMD_POSE["/cmd_pose topic<br/>(geometry_msgs/Pose)"] end subgraph "MoveIt Gateway Node" GATEWAY["MoveItGateway"] IK_SOLVER["Multi-Strategy IK Solver"] CONSTRAINT_GEN["Constraint Generator"] COORD_TRANSFORM["Coordinate Transform"] end subgraph "MoveIt2 Core" MOVE_GROUP["move_group node"] PLANNING_SCENE["Planning Scene"] KINEMATICS["KDL Kinematics Plugin"] PLANNER["OMPL/Pilz Planner"] end subgraph "Execution Layer" ACTION_DISPATCH["action_dispatcher_node"] ROS2_CONTROL["ros2_control"] end subgraph "Hardware/Simulation" HARDWARE["so101_hardware / Gazebo"] end USER --> CMD_POSE CMD_POSE --> GATEWAY GATEWAY --> COORD_TRANSFORM COORD_TRANSFORM --> CONSTRAINT_GEN CONSTRAINT_GEN --> IK_SOLVER IK_SOLVER --> MOVE_GROUP MOVE_GROUP --> PLANNING_SCENE MOVE_GROUP --> KINEMATICS MOVE_GROUP --> PLANNER PLANNER --> ACTION_DISPATCH ACTION_DISPATCH --> ROS2_CONTROL ROS2_CONTROL --> HARDWARE

来源: src/robot_moveit/scripts/moveit_gateway.py:1-310, src/robot_moveit/docs/moveit_gateway.md:1-50, README.md:15-16

控制模式架构

MoveIt 规划模式通过 control_mode 参数激活,并与统一的硬件抽象层集成:

graph LR subgraph "Control Mode Selection" LAUNCH["robot.launch.py"] CONFIG["robot_config YAML"] end subgraph "Mode: moveit_planning" MOVEIT_LAUNCH["so101_moveit.launch.py"] GATEWAY["moveit_gateway.py"] MOVE_GROUP["move_group"] end subgraph "Unified Execution" ACTION_EXEC["ActionExecutor"] TRAJECTORY_CTRL["trajectory_controllers"] end subgraph "Hardware Layer" ROS2_CTRL["ros2_control"] end LAUNCH --> CONFIG CONFIG -->|"control_mode:<br/>moveit_planning"| MOVEIT_LAUNCH MOVEIT_LAUNCH --> GATEWAY MOVEIT_LAUNCH --> MOVE_GROUP MOVE_GROUP --> ACTION_EXEC ACTION_EXEC --> TRAJECTORY_CTRL TRAJECTORY_CTRL --> ROS2_CTRL

来源: src/robot_config/robot_config/launch_builders/moveit.py:1-79, README.md:136-143


MoveItGateway 节点

moveit_gateway.py 节点作为 MoveIt2 的高级接口,提供位姿命令订阅、多策略 IK 求解和末端执行器状态发布功能。

节点接口

接口类型

话题/参数

消息类型

描述

订阅

/cmd_pose

geomet ry_msgs/Pose

目标末端执 行器位姿命令

订阅

/joint_states

sensor_msg s/JointState

当前关节状 态 (IK 初 始猜测)

发布

/robot _status/ee_pose

` geometry_msgs /PoseStamped`

当前末端执 行器位姿 (10Hz)

参数

` arm_group_name`

string

MoveIt 规 划组名称

参数

base_link

string

基座坐标系

参数

ee_link

string

末端执行器 连杆名称

参数

shoulder_link

string

肩部连杆 (用于 5DOF 投影)

参数

joint_names

`` list[string]``

机械臂关节 名称列表

来源: src/robot_moveit/scripts/moveit_gateway.py:24-80, src/robot_moveit/docs/moveit_gateway.md:9-22

关键组件

src/robot_moveit/scripts/moveit_gateway.py:24-310 中的 MoveItGateway 类初始化以下内容:

  1. TF2 缓冲区和监听器 (line 48-49): 用于坐标系变换

  2. MoveIt2 接口 (line 53-66): 带有可重入回调组的 pymoveit2.MoveIt2 包装器

  3. 关节状态订阅者 (line 68-69): 跟踪当前机械臂配置

  4. 位姿命令订阅者 (line 73-74): 接收目标位姿

  5. 末端执行器位姿发布者 (line 71): 发布当前末端执行器状态

  6. 状态定时器 (line 77): 10Hz 末端执行器位姿发布

来源: src/robot_moveit/scripts/moveit_gateway.py:24-80


5DOF 运动学约束

SO101 机械臂有 5 个关节,提供 5 个自由度 (DOF)。标准的 6DOF 位姿目标 (3 位置 + 3 姿态) 对该机械臂来说在数学上是过约束的,会导致频繁的 IK 失败。MoveIt 集成实现了专门的约束处理来解决这个问题。

仅位置 IK 配置

运动学求解器在 src/robot_moveit/config/lerobot/so101/kinematics.yaml:6 中配置了 position_only_ik: True

arm:
  kinematics_solver: kdl_kinematics_plugin/KDLKinematicsPlugin
  kinematics_solver_search_resolution: 0.01
  kinematics_solver_timeout: 2.0
  kinematics_solver_attempts: 50
  position_only_ik: True

``position_only_ik: True`` 的效果: - KDL 求解器仅优化**位置** (3 DOF),而非姿态 (3 DOF) - 目标姿态仍会传递给求解器,但在优化过程中不强制执行 - 最终解可以根据提供的姿态约束进行验证 - 将 5DOF 机械臂的 IK 成功率从约 10% 提高到 80% 以上

来源: src/robot_moveit/config/lerobot/so101/kinematics.yaml:1-7, src/robot_moveit/docs/moveit_gateway.md:34-67

姿态约束策略

网关实现了两种几何约束投影方法,用于引导 IK 求解器找到可行的姿态:

策略 1:仅 Z 轴约束

constrain_to_z_axis_only() 方法 (src/robot_moveit/scripts/moveit_gateway.py:118-175) 保持末端执行器 Z 轴方向,同时放宽绕 Z 轴的旋转 (滚转):

graph TD INPUT["Input Quaternion<br/>(x, y, z, w)"] TO_MATRIX["Convert to<br/>Rotation Matrix R"] EXTRACT_Z["Extract Z-axis<br/>(R column 3)"] PROJECT_X["Project original X-axis<br/>onto plane ⊥ Z"] NORMALIZE_X["Normalize projected<br/>X-axis"] CROSS_Y["Y = Z × X<br/>(cross product)"] REBUILD["Rebuild R' from<br/>(X', Y', Z)"] TO_QUAT["Convert back to<br/>quaternion"] OUTPUT["Constrained Quaternion<br/>(x', y', z', w')"] INPUT --> TO_MATRIX TO_MATRIX --> EXTRACT_Z TO_MATRIX --> PROJECT_X EXTRACT_Z --> CROSS_Y PROJECT_X --> NORMALIZE_X NORMALIZE_X --> CROSS_Y CROSS_Y --> REBUILD REBUILD --> TO_QUAT TO_QUAT --> OUTPUT

算法 (src/robot_moveit/scripts/moveit_gateway.py:133-174): 1. 将四元数转换为旋转矩阵 2. 保留 Z 轴 (第 3 列) 3. 将原始 X 轴投影到垂直于 Z 轴的平面上 4. 通过叉积计算 Y 轴:Y = Z × X 5. 重构旋转矩阵并转换回四元数

来源: src/robot_moveit/scripts/moveit_gateway.py:118-175, src/robot_moveit/docs/moveit_gateway.md:62-67

策略 2:肩部 XZ 平面投影

project_orientation_to_shoulder_xz_plane() 方法 (src/robot_moveit/scripts/moveit_gateway.py:177-264) 将姿态变换到肩部坐标系,并将其约束在 XZ 平面上:

graph TD INPUT["Target Quaternion<br/>in base frame"] TF_LOOKUP["Lookup TF:<br/>base → shoulder"] TRANSFORM["Transform quaternion<br/>to shoulder frame"] TO_MATRIX["Convert to<br/>Rotation Matrix"] PROJECT["Constrain X, Z axes<br/>to XZ plane (Y=0)"] NORMALIZE["Normalize X and Z"] CROSS["Y = Z × X"] REBUILD["Rebuild rotation<br/>matrix R'"] TO_QUAT["Convert to<br/>quaternion"] TRANSFORM_BACK["Transform back<br/>to base frame"] OUTPUT["Constrained Quaternion<br/>in base frame"] INPUT --> TF_LOOKUP TF_LOOKUP --> TRANSFORM TRANSFORM --> TO_MATRIX TO_MATRIX --> PROJECT PROJECT --> NORMALIZE NORMALIZE --> CROSS CROSS --> REBUILD REBUILD --> TO_QUAT TO_QUAT --> TRANSFORM_BACK TRANSFORM_BACK --> OUTPUT

算法 (src/robot_moveit/scripts/moveit_gateway.py:193-264): 1. 通过 TF2 获取 base shoulder 变换 2. 将目标姿态变换到肩部坐标系 3. 将 X 轴和 Z 轴的 Y 分量设为零 4. 归一化约束后的轴 5. 重构旋转矩阵并变换回基座坐标系

来源: src/robot_moveit/scripts/moveit_gateway.py:177-264, src/robot_moveit/docs/moveit_gateway.md:68-72

多策略回退系统

cmd_pose_callback() 方法 (src/robot_moveit/scripts/moveit_gateway.py:266-310) 实现了一个分层回退系统,包含 4 种姿态策略 × 5 个容差级别 = 共 20 次尝试:

策略

方法

描述

  1. 夹爪 Z 轴

constrain_t o_z_axis_only()

保持夹爪 Z 方向,释放滚转

  1. 肩部 XZ 投影

project_or ientation_to_shou lder_xz_plane()

几何精确的 5DOF 约束

  1. 当前姿态

使用 lat est_joint_state

保持现有机械臂姿态

  1. 默认姿态

单位四元数 (0,0,0,1)

无旋转约束

容差级别 (应用于每种策略):

级别

X, Y 容差 (rad)

Z 容差 (rad)

角度 (约)

严格

0.1

0.05

X/Y: ±5.7°, Z: ±2.8°

中等

0.3

0.1

X/Y: ±17°, Z: ±5.7°

宽松

0.5

0.15

X/Y: ±28°, Z: ±8.6°

仅 Z

1.0

0.2

X/Y: ±57°, Z: ±11°

无姿态约束

来源: src/robot_moveit/scripts/moveit_gateway.py:266-310, src/robot_moveit/docs/moveit_gateway.md:73-95


配置系统

MoveIt 配置在 robot_config YAML 中定义,并通过启动系统传递。

机器人配置 YAML 结构

示例来自 src/robot_config/config/robots/test_single_arm_single_cam.yaml:30-35

moveit:
  arm_group_name: arm
  base_link: base
  ee_link: gripper
  shoulder_link: shoulder

这些参数通过位于 src/robot_config/robot_config/launch_builders/moveit.py:52-68 的启动构建器传递给 moveit_gateway 节点:

来源: src/robot_config/config/robots/test_single_arm_single_cam.yaml:30-35, src/robot_config/robot_config/launch_builders/moveit.py:52-68

MoveIt2 配置文件

位于 robot_moveit/config/lerobot/so101/

文件

用途

kinematics.yaml

IK 求解器配置 (position_only_ik: True)

so101.srdf

语义机器人描述 (规划组、位姿)

joint_limits.yaml

关节速度/加速度限制

moveit_controllers.yaml

轨迹执行的控制器名称

pilz_cartesian_limits.yaml

笛卡尔速度/加速度限制

moveit.rviz

RViz 可视化配置

来源: src/robot_moveit/launch/so101_moveit.launch.py:60-76


启动系统

MoveIt2 通过统一的 robot.launch.py 入口点使用 moveit_planning 控制模式启动。

启动流程

graph TB ROBOT_LAUNCH["robot.launch.py"] CONFIG_YAML["robot_config YAML"] MODE_CHECK{"control_mode<br/>contains<br/>'moveit'?"} MOVEIT_BUILDER["moveit.py<br/>launch_builder"] MOVEIT_LAUNCH["so101_moveit.launch.py"] subgraph "Launched Nodes" MOVE_GROUP["move_group"] RVIZ["rviz2 (optional)"] GATEWAY["moveit_gateway.py"] end ROBOT_LAUNCH --> CONFIG_YAML CONFIG_YAML --> MODE_CHECK MODE_CHECK -->|"Yes"| MOVEIT_BUILDER MODE_CHECK -->|"No"| SKIP["Skip MoveIt"] MOVEIT_BUILDER --> MOVEIT_LAUNCH MOVEIT_LAUNCH --> MOVE_GROUP MOVEIT_LAUNCH --> RVIZ MOVEIT_LAUNCH --> GATEWAY

来源: src/robot_config/robot_config/launch_builders/moveit.py:15-78, README.md:136-143

启动命令

带 RViz 可视化

ros2 launch robot_config robot.launch.py \
  robot_config:=so101_single_arm \
  control_mode:=moveit_planning \
  use_sim:=true

无头模式 (无 RViz)

ros2 launch robot_config robot.launch.py \
  robot_config:=so101_single_arm \
  control_mode:=moveit_planning \
  use_sim:=true \
  moveit_display:=false

来源: README.md:136-143

启动构建器实现

位于 src/robot_config/robot_config/launch_builders/moveit.py:15-78generate_moveit_nodes() 函数执行:

  1. 模式检测 (line 31-34): 检查控制模式字符串中是否包含 'moveit'

  2. 参数提取 (line 47-55): 从机器人配置中提取关节名称和坐标系 ID

  3. 启动文件包含 (line 58-69): 包含 so101_moveit.launch.py 并映射参数

来源: src/robot_config/robot_config/launch_builders/moveit.py:15-78


控制流程

位姿命令处理

从位姿命令到关节运动的完整流程:

graph TB CMD["/cmd_pose<br/>(Pose message)"] CALLBACK["cmd_pose_callback()"] TF_CALC["Calculate TF:<br/>base → shoulder"] DIST_CHECK["Compute distances:<br/>- from base origin<br/>- from shoulder origin"] subgraph "Multi-Strategy Loop" STRATEGY["For each strategy:<br/>1. Z-axis<br/>2. Shoulder XZ<br/>3. Current orient<br/>4. Default orient"] subgraph "Tolerance Loop" TOL["For each tolerance:<br/>1. Strict<br/>2. Medium<br/>3. Relaxed<br/>4. Z-only<br/>5. None"] CREATE_CONSTRAINT["create_orientation_constraint()"] SOLVE["solve_and_move()"] IK_CALL["moveit2.compute_ik_async()"] WAIT["Wait for IK result"] CHECK_SUCCESS{"IK<br/>success?"} end end MOVE_JOINTS["moveit2.move_to_joint()"] SUCCESS["Motion Executed"] FAIL["All strategies failed"] CMD --> CALLBACK CALLBACK --> TF_CALC TF_CALC --> DIST_CHECK DIST_CHECK --> STRATEGY STRATEGY --> TOL TOL --> CREATE_CONSTRAINT CREATE_CONSTRAINT --> SOLVE SOLVE --> IK_CALL IK_CALL --> WAIT WAIT --> CHECK_SUCCESS CHECK_SUCCESS -->|"Yes"| MOVE_JOINTS CHECK_SUCCESS -->|"No"| TOL TOL -->|"All tolerances tried"| STRATEGY STRATEGY -->|"All strategies tried"| FAIL MOVE_JOINTS --> SUCCESS

来源: src/robot_moveit/scripts/moveit_gateway.py:266-310, src/robot_moveit/docs/moveit_gateway.md:122-205

约束创建

create_orientation_constraint() 方法 (src/robot_moveit/scripts/moveit_gateway.py:312-340) 生成 OrientationConstraint 消息:

消息结构

constraint = OrientationConstraint()
constraint.header.frame_id = "base"
constraint.link_name = "gripper"
constraint.orientation.x = quat[0]
constraint.orientation.y = quat[1]
constraint.orientation.z = quat[2]
constraint.orientation.w = quat[3]
constraint.absolute_x_axis_tolerance = x_tol
constraint.absolute_y_axis_tolerance = y_tol
constraint.absolute_z_axis_tolerance = z_tol
constraint.weight = 1.0

来源: src/robot_moveit/scripts/moveit_gateway.py:312-340, src/robot_moveit/docs/moveit_gateway.md:206-229


坐标系变换

基座到肩部坐标系转换

网关执行坐标变换以准确评估工作空间可达性。从基座坐标系到肩部坐标系的变换为:

P_shoulder = R × (P_base - T)

其中: - P_base: 基座坐标系中的目标位置 - T: 基座坐标系中肩部原点的平移偏移 - R: 从基座到肩部的旋转矩阵 - P_shoulder: 肩部坐标系中的目标位置

实现 位于 src/robot_moveit/scripts/moveit_gateway.py:266-310

  1. TF 查询 (line 280-285): 获取 base shoulder 变换

  2. 平移偏移 (line 287-290): 从变换中提取 T

  3. 旋转矩阵 (line 292-297): 将四元数转换为 3×3 矩阵

  4. 向量变换 (line 299-302): 应用 R × (P - T)

  5. 距离计算 (line 304-306): 计算距肩部的欧几里得距离

日志输出示例

[INFO] Target Pose: x=-0.046, y=-0.000, z=0.423
[INFO]   Target in shoulder frame: x=-0.034, y=0.012, z=-0.323
[INFO]   Distance from base origin: 0.426 m
[INFO]   Distance from shoulder origin: 0.325 m

来源: src/robot_moveit/scripts/moveit_gateway.py:266-310, src/robot_moveit/docs/moveit_gateway.md:97-120

四元数工具

网关使用 scipy.spatial.transform.Rotation 实现四元数运算:

函数

行号

用途

`` quaternion_multiply()``

82-90

组合两个旋转: q = q1 * q2

q uaternion_conjugate()

92-98

逆旋转: q* = q^(-1)

quaternion _to_rotation_matrix()

100-107

将四元数转换为 3×3 矩阵

rotation_m atrix_to_quaternion()

109-116

将 3×3 矩阵转换为 四元数

来源: src/robot_moveit/scripts/moveit_gateway.py:82-116


使用示例

发送位姿命令

/cmd_pose 发布目标位姿:

ros2 topic pub --once /cmd_pose geometry_msgs/msg/Pose \
  "{position: {x: 0.3, y: 0.0, z: 0.2}, \
    orientation: {x: 0.0, y: 0.0, z: 0.0, w: 1.0}}"

监控末端执行器状态

订阅当前末端执行器位姿:

ros2 topic echo /robot_status/ee_pose

调试 IK 失败

启用调试日志以查看 IK 策略尝试:

ros2 run robot_moveit moveit_gateway.py --ros-args --log-level debug

来源: src/robot_moveit/scripts/moveit_gateway.py:1-10, src/robot_moveit/docs/moveit_gateway.md:1-50


与动作分发的集成

moveit_planning 控制模式下,MoveIt2 生成轨迹,通过 action_dispatchActionExecutor 组件执行。这与 model_inference 模式不同,后者使用 TopicExecutor 进行高频位置流传输。

执行路径

moveit_gateway → move_group → trajectory → ActionExecutor → trajectory_controllers → ros2_control

关于动作执行的详细信息,请参阅 动作分发。关于控制模式切换,请参阅 控制模式架构

来源: src/action_dispatch/README.en.md:35-38, README.md:15-16


性能特征

指标

IK 成功率 (5DOF, 仅位置)

~80-90%

IK 成功率 (5DOF, 完整 6DOF 约束)

~10-20%

平均 IK 求解时间

50-200 ms

末端执行器位姿发布频率

10 Hz

最大 IK 求解器尝试次数

50 (每个容差级别)

IK 求解器超时

2.0 秒

来源: src/robot_moveit/config/lerobot/so101/kinematics.yaml:3-5, src/robot_moveit/docs/moveit_gateway.md:34-51