【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. 前置条件
开始前应满足以下条件:
- Ubuntu 22.04 已安装 ROS 2 Humble;
- MoveIt 2、TRAC-IK、
ros2_control、RViz2 和 Gazebo Sim 相关组件已安装; simulations中的相关功能包已放入同一个 ROS 2 工作空间并完成编译;- 每个新终端都已加载 ROS 2 和工作空间环境;
- 虚拟机设置与配套教程保持一致。本教程使用的虚拟机要求在显示器设置中取消“加速 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 面板中进行以下设置:
- 打开 Planning 标签页;
- 将 Planning Group 设置为
arm; - 将 Start State 设置为当前状态;
- 通过红、绿、蓝交互标记拖动末端目标,或打开 Joints 面板单独调整关节;
- 正常可规划的目标通常显示为橙色;如果目标与底座或其他连杆发生碰撞,会显示为红色,此时应重新调整;
- 需要检查场景碰撞时,在 Planning 区域启用 Collision-aware IK;
- 首次测试时不要把目标放得过远,也不要让机械臂穿过自身或地面。
由于当前配置使用 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 会完成以下工作:
- 加载
empty.sdf世界; - 通过
robot_state_publisher发布 NexArm 的robot_description; - 将 NexArm 模型生成到 Gazebo;
- 启动
ros_ign_bridge; - 加载 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再启动本地 mockros2_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 中重复以下操作:
- Planning Group 选择
arm; - 设置一个位于工作空间内的目标;
- 确认目标为橙色可执行状态,而不是红色碰撞状态;
- 点击 Plan,确认规划轨迹正常;
- 点击 Execute,或直接使用 Plan & Execute;
- 同时观察 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 不动
重点检查以下几项:
- 是否先执行了
worlds.launch.py moveit_unite:=true; - MoveIt 启动命令是否同时带有
use_sim_time:=true use_gazebo:=true; - Gazebo 侧的
arm_controller是否为active; - 是否误启动了另一个 mock
controller_manager; - 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 实机驱动。









