【NexArm智能机械臂】MoveIt2 快速上手:运动规划入门

【NexArm智能机械臂】MoveIt2 快速上手:运动规划入门

产品图示:


适用于产品: 幻尔科技NexArm智能机械臂

涉及模块: MoveIt2仿真

MoveIt 2 是 ROS 2 生态中常用的机械臂运动规划框架,负责逆运动学、碰撞检测、路径规划和轨迹执行。它并不限定某一个型号:只要机械臂具备正确的 URDF/SRDF、运动学插件、控制器配置和 ros2_control 接口,就可以复用本文的基本流程。本文使用 NexArm 五自由度机械臂完成实测;对于 Simulations 功能包支持的其他机型,应切换对应的描述包、MoveIt 配置包和控制器参数。

完成本文后,你将能够:

  • 启动NexArm机械臂对应的 MoveIt 2 配置,并理解本文命令中的可替换部分;
  • 理解 URDF、SRDF、运动学插件和控制器配置之间的关系;
  • 在 RViz2 中设置目标位姿并执行运动规划;
  • 在 Gazebo Sim 中验证机械臂是否按规划轨迹运动;
  • 排查模型、TF、IK 和控制器相关的常见问题。

1. 实测环境与适用范围

1.1 软件版本

项目 实测版本
适用设备 通用 ROS 2 设备或开发电脑,不要求连接机器人
操作系统 Ubuntu 22.04
ROS 2 ROS 2 Humble
MoveIt 2 核心组件 moveit_ros_move_group 2.5.6
RViz2 11.2.12
Gazebo Gazebo Sim 6.16.0
ROS-Gazebo 接口 ros_ign_gazebo、ros_ign_bridge、ign_ros2_control
实测机械臂模型 NexArm机械臂模型
MoveIt 规划组 arm:joint1~joint5
RViz2 仿真硬件接口 mock_components/GenericSystem
Gazebo 仿真硬件接口 ign_ros2_control/IgnitionSystem

本文的操作方法并不只适用于 NexArm。对于其他机械臂,通常需要替换描述包、SRDF 规划组、末端链路、关节名称、运动学插件以及控制器名称。本文命令与运行结果只对NexArm机械臂流程进行实测,因此其他机型必须按各自的配置包再次验证,不能直接照抄 nexarm_moveit_config 包名。

本文只讨论仿真,不连接实体机械臂,不涉及舵机控制板、电源、串口、USB 或总线接线。

1.2 版本检查

执行以下命令检查 ROS 2、MoveIt 2、RViz2 和 Gazebo Sim 版本:

echo $ROS_DISTRO
ros2 pkg xml moveit_ros_move_group | grep '<version>'
ros2 pkg xml rviz2 | grep '<version>'
dpkg -s ros-$ROS_DISTRO-rviz2 | grep Version
ign gazebo --version

本次实测得到的关键输出如下:

humble
<version>2.5.6</version>
<version>11.2.12</version>
Version: 11.2.12-1jammy.20240327.181147
Gazebo Sim, version 6.16.0

注意:执行 dpkg -s ros-humble-moveit 时提示元包未安装,并不代表 MoveIt 2 不可用。本环境安装了 MoveIt 2 的独立组件,ros2 pkg xml moveit_ros_move_group 能够返回 2.5.6,且 move_group 已实测正常启动。


2. 工程组成与工作原理

本文涉及以下主要 ROS 2 功能包:

~/ros2_ws/src/simulations/
├── nexarm_description/       # NexArm 的 URDF/Xacro 与 STL 网格模型
├── nexarm_moveit_config/     # NexArm 的 SRDF、运动学、控制器及启动文件
├── robot_moveit_config/      # 其他机型的 MoveIt 配置示例
└── robot_gazebo/             # Gazebo 世界、模型生成和 ros_ign_bridge

关键文件及其作用如下:

文件 作用
nexarm_description/urdf/nexarm.urdf.xacro 定义机械臂连杆、关节、碰撞模型和关节限位
nexarm_moveit_config/config/NexArm.srdf 定义 arm、gripper 规划组和命名姿态
nexarm_moveit_config/config/kinematics.yaml 为 arm 配置 TRAC-IK 求解器
nexarm_moveit_config/config/joint_limits.yaml 设置 MoveIt 侧速度与加速度缩放
nexarm_moveit_config/config/ros2_controllers.yaml 配置 mock 模式下的 ros2_control 控制器
nexarm_moveit_config/config/moveit_controllers.yaml 建立 MoveIt 与轨迹控制器 Action 的映射
nexarm_moveit_config/launch/demo.launch.py 启动 RViz2、move_group、TF 及所需控制节点
robot_gazebo/launch/worlds.launch.py 启动 Gazebo 世界、生成模型并加载桥接节点

教程资料将整个 simulations 目录放入 ~/ros2_ws/src/。不同机型的模型和 MoveIt 配置不同,运行前应确认当前环境选择的机器类型与要启动的配置包一致。本文后续命令中的 nexarm_moveit_config、arm、joint1~joint5 都是 NexArm 实测值,不是所有产品的固定名称。

一次完整运动的消息链路可以概括为:

RViz2 目标位姿
      ↓
MoveIt 2 / move_group
      ↓
逆运动学 + 碰撞检测 + 路径规划
      ↓
arm_controller/follow_joint_trajectory
      ↓
mock_components 或 ign_ros2_control
      ↓
关节状态反馈 → RViz2 / Gazebo 更新模型

2.1 规划组

NexArm.srdf 将五个旋转关节定义为 arm 规划组:

<group name="arm">
    <joint name="joint1"/>
    <joint name="joint2"/>
    <joint name="joint3"/>
    <joint name="joint4"/>
    <joint name="joint5"/>
</group>

因此,在 RViz2 的 MotionPlanning 面板中必须选择 arm。夹爪属于单独的 gripper 组,不应把它当作机械臂末端位姿规划组。

2.2 逆运动学配置

当前工程使用 TRAC-IK:

arm:
  kinematics_solver: trac_ik_kinematics_plugin/TRAC_IKKinematicsPlugin
  kinematics_solver_search_resolution: 0.005
  kinematics_solver_timeout: 0.005
  position_only_ik: true

position_only_ik: true 表示求解时重点满足末端位置,不强制满足完整三维姿态。这与 NexArm 只有五个主要旋转关节有关:它无法像标准六自由度工业机械臂那样,在任意位置同时实现任意方向。


3. 前置条件

开始前应满足以下条件:

  1. Ubuntu 22.04 已安装 ROS 2 Humble;
  2. MoveIt 2、TRAC-IK、ros2_control、RViz2 和 Gazebo Sim 相关组件已安装;
  3. simulations 中的相关功能包已放入同一个 ROS 2 工作空间并完成编译;
  4. 每个新终端都已加载 ROS 2 和工作空间环境;
  5. 虚拟机设置与配套教程保持一致。本教程使用的虚拟机要求在显示器设置中取消“加速 3D 图形”;不同虚拟化软件的图形兼容性可能不同,不应直接套用其他平台的设置。

3.1 编译功能包

首次导入资料时,将提供的 simulations.zip 解压并放入 ~/ros2_ws/src/simulations。如果工作空间中已经存在该目录,可直接进入编译步骤,不要再次复制同名功能包,否则 colcon 可能报告 duplicate package name。

假设工作空间为 ~/ros2_ws,执行:

source /opt/ros/humble/setup.bash
cd ~/ros2_ws
colcon build --symlink-install

编译结束时不应出现 Failed。如果依赖已经安装,相关功能包应全部完成构建。

3.2 加载环境并检查功能包

假设工作空间为 ~/ros2_ws,每个新终端先执行:

source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash
source ~/ros2_ws/.typerc

配套教程会把工作空间环境和 .typerc 写入 ~/.bashrc。如果已经完成该配置,也可以在新终端执行 source ~/.bashrc 一次性加载。.typerc 中包含设备或机器类型等环境配置;切换产品后,应先按对应产品资料更新该文件,再重新打开终端。

检查三个功能包是否可以被 ROS 2 找到:

ros2 pkg prefix nexarm_description
ros2 pkg prefix nexarm_moveit_config
ros2 pkg prefix robot_gazebo

三个命令都应返回工作空间 install 目录下的安装路径。如果提示 package not found,优先检查是否忘记加载 install/setup.bash。


4. 第一阶段:使用 mock_components 在 RViz2 中规划

这一阶段不启动 Gazebo。MoveIt 2 使用 mock_components/GenericSystem 模拟硬件接口,适合快速检查模型、规划组、逆运动学和控制器配置。

4.1 启动 MoveIt 2

打开终端,加载环境后执行:

ros2 launch nexarm_moveit_config demo.launch.py

该命令会启动:

  • move_group:MoveIt 2 的核心规划节点;
  • RViz2 及 MotionPlanning 插件;
  • robot_state_publisher 和静态 TF;
  • ros2_control_node;
  • joint_state_broadcaster;
  • arm_controller 和 gripper_controller。

默认 mock 硬件接口来自 NexArm.ros2_control.xacro:

<ros2_control name="FakeSystem" type="system">
    <hardware>
        <plugin>mock_components/GenericSystem</plugin>
    </hardware>
    <!-- joint1~joint5 与 gripper_base_joint -->
</ros2_control>

RViz2 正常启动后,应看到完整的 NexArm机械臂 模型,Global Options 中的 Fixed Frame 为 world,左侧 Displays 中没有持续的红色错误。


一号位置为:RVIZ工具栏、二号位置为:Movelt调试区、三号位置为:仿真模型调节区。

4.2 设置规划参数

在 RViz2 的 MotionPlanning 面板中进行以下设置:

  1. 打开 Planning 标签页;
  2. 将 Planning Group 设置为 arm;
  3. 将 Start State 设置为当前状态;
  4. 通过红、绿、蓝交互标记拖动末端目标,或打开 Joints 面板单独调整关节;
  5. 正常可规划的目标通常显示为橙色;如果目标与底座或其他连杆发生碰撞,会显示为红色,此时应重新调整;
  6. 需要检查场景碰撞时,在 Planning 区域启用 Collision-aware IK;
  7. 首次测试时不要把目标放得过远,也不要让机械臂穿过自身或地面。

由于当前配置使用 position_only_ik: true,建议先测试位置变化,不要把“必须精确满足任意末端朝向”作为成功标准。

4.3 规划并执行

通过红、绿、蓝交互标记拖动末端目标

回到 Planning 面板,点击 Plan。

需要观察轨迹的连续过程时,可在 RViz2 工具栏依次展开 MotionPlanning → Planned Path,勾选 Show Trail。

开启 Show Trail 后,可以看到机械臂沿规划路径运动时的连续姿态:

轨迹观察结束后建议取消勾选 Show Trail,避免画面残留过多轨迹帧。

确认轨迹没有异常后点击 Execute。在 mock 模式下,GenericSystem 会接收关节轨迹并更新关节状态,RViz2 中的机械臂移动到目标姿态。

也可以直接点击 Plan & Execute,但第一次调试时建议将规划和执行分开,以便判断问题发生在规划侧还是控制器侧。

4.4 验证控制器

保持 RViz2 运行,再打开一个已加载环境的终端:

ros2 control list_controllers

正常情况下应能看到以下控制器处于 active 状态:

joint_state_broadcaster   joint_state_broadcaster/JointStateBroadcaster   active
arm_controller            joint_trajectory_controller/JointTrajectoryController   active
gripper_controller        joint_trajectory_controller/JointTrajectoryController   active

再检查轨迹 Action:

ros2 action list | grep follow_joint_trajectory

至少应包含:

/arm_controller/follow_joint_trajectory

5. 第二阶段:接入 Gazebo Sim 联合仿真

完成 RViz2 mock 模式验证后,先用 Ctrl+C 关闭该模式的启动进程。不要让 mock 控制器与 Gazebo 控制器同时占用相同的节点名和控制器名。

联合仿真需要两个终端:终端一启动 Gazebo 世界和 NexArm 模型,终端二启动 MoveIt 2 与 RViz2。

5.1 终端一:启动 Gazebo 世界

source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash
source ~/ros2_ws/.typerc
ros2 launch robot_gazebo worlds.launch.py moveit_unite:=true

worlds.launch.py 会完成以下工作:

  1. 加载 empty.sdf 世界;
  2. 通过 robot_state_publisher 发布 NexArm 的 robot_description;
  3. 将 NexArm 模型生成到 Gazebo;
  4. 启动 ros_ign_bridge;
  5. 加载 Gazebo 侧 ros2_control 系统和 arm_controller。

等待 Gazebo 完成加载,并确认场景中出现 NexArm 机械臂模型后,再启动终端二。

5.2 终端二:启动 MoveIt 2 和 RViz2

source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash
source ~/ros2_ws/.typerc
ros2 launch nexarm_moveit_config demo.launch.py use_sim_time:=true use_gazebo:=true

两个参数的含义如下:

  • use_sim_time:=true:让 MoveIt 2、RViz2 和状态发布节点使用仿真时钟;
  • use_gazebo:=true:禁止 demo.launch.py 再启动本地 mock ros2_control_node 和控制器,避免与 Gazebo 侧控制器冲突。

启动文件中的关键逻辑是:

ros2_control_node = Node(
    package="controller_manager",
    executable="ros2_control_node",
    # use_gazebo=true 时不启动本地 mock 控制节点
    condition=UnlessCondition(use_gazebo),
)

arm_controller_spawner = Node(
    package="controller_manager",
    executable="spawner",
    arguments=["arm_controller", "-c", "/controller_manager"],
    condition=UnlessCondition(use_gazebo),
)

5.3 在 RViz2 中规划并同步到 Gazebo

在 RViz2 中重复以下操作:

  1. Planning Group 选择 arm;
  2. 设置一个位于工作空间内的目标;
  3. 确认目标为橙色可执行状态,而不是红色碰撞状态;
  4. 点击 Plan,确认规划轨迹正常;
  5. 点击 Execute,或直接使用 Plan & Execute;
  6. 同时观察 RViz2 和 Gazebo。

本次实测结果为:

  • Gazebo 中能够正常生成 NexArm;
  • RViz2 能够正常显示机械臂模型;
  • MotionPlanning 面板可选择 arm;
  • 拖动目标后可以成功 Plan;
  • Execute 后,RViz2 与 Gazebo 中的机械臂能够同步运动。

5.4 关于夹爪控制和不同机型

配套教程还包含 gripper 规划组的夹爪操作,但不同产品的夹爪关节名称并不相同:当前 NexArm SRDF 使用 gripper_base_joint,其他配置中可能出现 r_joint 等名称。因此,切换机型时必须同时检查 SRDF、ros2_controllers.yaml 和 moveit_controllers.yaml,不要只修改 RViz2 中的 Planning Group。

5.5 用命令检查联合仿真结果

执行过程中可打开第三个终端检查控制器:

source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash
source ~/ros2_ws/.typerc
ros2 control list_controllers

机械臂轨迹执行的必要条件是 arm_controller 处于 active 状态。还可以检查关节状态是否持续更新:

ros2 topic echo /joint_states --once

正常输出中应包含 joint1~joint5,执行轨迹前后对应的 position 数值会发生变化。


6. 配置代码解读

6.1 MoveIt 如何找到轨迹控制器

moveit_controllers.yaml 把 MoveIt 2 的执行请求映射到 arm_controller:

moveit_controller_manager: moveit_simple_controller_manager/MoveItSimpleControllerManager

moveit_simple_controller_manager:
  controller_names:
    - arm_controller
    - gripper_controller

  arm_controller:
    type: FollowJointTrajectory
    action_ns: follow_joint_trajectory
    default: true
    joints:
      - joint1
      - joint2
      - joint3
      - joint4
      - joint5

这里的关节名称和顺序必须与 ros2_controllers.yaml 中的 arm_controller 一致。否则可能出现“规划成功但执行失败”。

6.2 为什么默认运动比较慢

joint_limits.yaml 中设置了:

default_velocity_scaling_factor: 0.1
default_acceleration_scaling_factor: 0.1

这表示默认只使用最大速度和加速度的 10%,适合首次仿真验证。确认模型、碰撞和控制稳定后,可以在不超过 1.0 的范围内逐步提高缩放比例,不建议一开始直接设为最大值。

6.3 可用规划器

demo.launch.py 加载了三类规划流水线:

.planning_pipelines(
    pipelines=["ompl", "chomp", "pilz_industrial_motion_planner"]
)

入门阶段建议先使用 RViz2 中的默认 OMPL 规划器。CHOMP 更偏向轨迹优化,Pilz 则常用于点到点、直线和圆弧等工业运动。切换规划器后,应重新验证规划成功率和碰撞行为。


7. 常见问题

7.1 Package 'nexarm_moveit_config' not found

原因通常是工作空间没有编译,或者当前终端没有加载工作空间环境。

首先确认包已位于工作空间的 src 目录并完成编译,然后在当前终端执行:

source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash
source ~/ros2_ws/.typerc
ros2 pkg prefix nexarm_moveit_config

不要只在第一个终端执行 source。每打开一个新终端,都需要重新加载环境。

7.2 ros-humble-moveit 显示未安装,为什么仍能运行?

ros-humble-moveit 是一个元包。元包未安装不等于其全部组件都不存在。本环境的 moveit_ros_move_group 组件版本为 2.5.6,能够被 ROS 2 查找到,实际规划流程也已通过验证。

判断 MoveIt 2 是否可用时,应检查具体组件:

ros2 pkg prefix moveit_ros_move_group
ros2 pkg xml moveit_ros_move_group | grep '<version>'

7.3 RViz2 能显示模型,但拖动末端时提示 IK 失败

常见原因有:

  • 目标超出 NexArm 的可达范围;
  • 目标与机械臂自身发生碰撞;
  • 目标要求的姿态不适合五自由度机械臂;
  • TRAC-IK 插件没有正确安装或加载;
  • 初始姿态接近关节极限。

处理方法:先把目标放在机械臂前方、靠近当前末端的位置,只改变较小距离;确认 Planning Group 为 arm;再查看启动终端中是否出现 kinematics solver 加载错误。

7.4 Plan 成功,但 Execute 失败

这类问题通常在控制器侧。执行:

ros2 control list_controllers
ros2 action list | grep follow_joint_trajectory

确认 arm_controller 为 active,并存在 /arm_controller/follow_joint_trajectory。同时检查 moveit_controllers.yaml 与 ros2_controllers.yaml 中的关节名称是否都是 joint1~joint5。

如果日志提示起始状态偏差超过容差,还应确认 /joint_states 正常更新,避免在 Gazebo 尚未稳定时立即执行轨迹。

7.5 RViz2 在动,但 Gazebo 不动

重点检查以下几项:

  1. 是否先执行了 worlds.launch.py moveit_unite:=true;
  2. MoveIt 启动命令是否同时带有 use_sim_time:=true use_gazebo:=true;
  3. Gazebo 侧的 arm_controller 是否为 active;
  4. 是否误启动了另一个 mock controller_manager;
  5. Gazebo 启动终端中是否出现 ign_ros2_control 插件加载失败。

联合仿真时必须使用:

ros2 launch nexarm_moveit_config demo.launch.py use_sim_time:=true use_gazebo:=true

如果漏掉 use_gazebo:=true,MoveIt 启动文件会创建本地 mock 控制器,轨迹可能只被 mock 系统执行。

7.6 出现 controller manager、节点名或资源重复错误

不要同时运行以下两种模式:

  • ros2 launch nexarm_moveit_config demo.launch.py;
  • Gazebo 联合仿真的两个启动命令。

切换模式前,先在旧终端中按 Ctrl+C,等待相关节点退出,再启动新模式。

7.7 RViz2 报 No transform 或模型散开

检查 Fixed Frame 是否为 world,并确认 robot_state_publisher、静态 TF 和 /joint_states 正常。Gazebo 启动较慢时,RViz2 可能短暂显示 TF 警告;等待模型和控制器完成加载后再观察。

可检查:

ros2 topic echo /joint_states --once
ros2 run tf2_ros tf2_echo world base_link

7.8 Gazebo 或 RViz2 在虚拟机中卡顿、黑屏

先核对配套教程中的虚拟机显示设置:本文使用的虚拟机要求取消“加速 3D 图形”。同时分配足够的 CPU 与内存,并分别启动 Gazebo 和 RViz2,判断是图形渲染问题还是 ROS 节点问题。不同 VMware/VirtualBox 版本的表现可能不同,调整前应记录原配置;远程桌面环境也可能导致 OpenGL 上下文创建失败。


8. 总结

机械臂的 MoveIt 2 快速上手可以分成两个层次:先用 mock_components 在 RViz2 中验证模型、IK、规划和轨迹控制链路,再将轨迹执行交给 Gazebo 侧的仿真硬件接口。本文的 NexArm 工程通过 use_gazebo:=true 切换到 ign_ros2_control;迁移到其他产品时,核心方法不变,但包名、规划组、关节、控制器和硬件插件需要使用对应产品的配置。

本文环境已实测完成以下完整流程:

启动 Gazebo → 生成 NexArm → 启动 MoveIt 2/RViz2
→ 选择 arm 规划组 → 设置目标 → Plan → Execute
→ RViz2 与 Gazebo 中的机械臂同步到达目标姿态

掌握这一流程后,可以继续学习添加碰撞物体、编写 MoveIt 2 接口程序、规划笛卡尔路径,以及将 mock/仿真硬件接口替换为 NexArm 实机驱动。

simulations.zip是在哪里下载的