ROS2_CANopen + MoveIt2 实战:从零搭建机械臂控制系统
ROS2 + CANopen + MoveIt2 实战:从零搭建机械臂控制系统
在工业自动化领域,CANopen 是一种广泛应用的通信协议,而 ROS2 作为机器人操作系统的新标准,如何将两者完美结合一直是开发者关注的热点。本文将通过一个完整的实战项目,详细介绍如何在 ROS2 Jazzy 上实现 CANopen 与 MoveIt2 的集成,控制 Pilz PRBT 机械臂。
项目地址:ROS2 CANopen Demo
环境要求:Ubuntu 24.04 + ROS2 Jazzy
项目背景
CANopen 作为基于 CAN 总线的应用层协议,在工业机械臂、伺服驱动器等设备中占据重要地位。ROS2 虽然在导航、感知等领域生态丰富,但在工业现场总线支持方面一直缺乏成熟的解决方案。
本项目的目标是:在 ROS2 中通过 CANopen 协议控制机械臂,并使用 MoveIt2 进行运动规划,提供一个完整的、可直接运行的示例。
核心挑战与解决方案
1. 启动时序问题(Boot Timeout)
问题描述:在调试过程中发现,CANopen 主站会报Boot Timeout错误。原因是 ros2_control_node 启动过早,在 CANopen 从站发送 Boot-Up 帧之前就开始尝试通信。
解决方案:
# 在 bus.yml 中配置
master:
boot_timeout: 10000 # 主站超时 10s
defaults:
boot_timeout_ms: 5000 # 从站 boot 等待时间 5s
同时优化启动顺序:
- 先启动虚拟从站(fake_slaves)
- 等待 Boot-Up 帧发送完成
- 再启动 ros2_control_node
- 最后加载控制器
使用 launch 文件中的 TimerAction 实现自动化的时序控制:
# moveit_ros2canopen_headless.launch.py
TimerAction(period=5.0, actions=[ros2_control_node]), # 延迟 5s 启动
2. 虚拟 CAN 接口配置
实现方式:
# 加载内核模块
sudo modprobe vcan
# 创建 vcan0 接口
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0
项目提供自动化配置 launch 文件:
ros2 launch prbt_robot_moveit_config vcan.launch.py
3. CANopen 与 ros2_control 的桥接
架构设计:
┌─────────────────────────────────────────┐
│ MoveIt2 运动规划 │
└──────────────┬──────────────────────────┘
│
┌──────────────▼──────────────────────────┐
│ Joint Trajectory Controller │
└──────────────┬──────────────────────────┘
│
┌──────────────▼──────────────────────────┐
│ ros2_control Hardware Interface │
│ (canopen_ros2_control/RobotSystem) │
└──────────────┬──────────────────────────┘
│ CANopen
┌──────────────▼──────────────────────────┐
│ CANopen Master + Slaves │
└─────────────────────────────────────────┘
关键配置:
URDF 中集成 ros2_control:
<!-- prbt_canopen.urdf.xacro -->
<ros2_control name="prbt" type="system">
<hardware>
<plugin>canopen_ros2_control/RobotSystem</plugin>
<param name="bus_config">$(find prbt_robot_support)/config/prbt/bus.yml</param>
<param name="master_dcf">$(find prbt_robot_support)/config/prbt/master.dcf</param>
<param name="can_interface_name">vcan0</param>
</hardware>
<!-- 关节配置 -->
</ros2_control>
CANopen 总线配置:
# bus.yml
master:
node_id: 1
nodes:
joint_1:
node_id: 3
dcf: "ZeroErr_Driver_V1.5.eds"
# ... joint_2 到 joint_6
项目结构
ROS2_jazzy_moveit2_test/
├── src/
│ ├── prbt_robot_moveit_config/ # MoveIt2 配置
│ │ ├── config/
│ │ │ ├── prbt_canopen.urdf.xacro
│ │ │ ├── prbt_canopen_ros2_controllers.yaml
│ │ │ └── moveit_controllers.yaml
│ │ ├── launch/
│ │ │ ├── moveit_ros2canopen.launch.py
│ │ │ ├── moveit_ros2canopen_with_fake_slaves.launch.py # ⭐ 推荐
│ │ │ └── moveit_ros2canopen_headless.launch.py # 无头模式
│ │ └── scripts/
│ │ └── test_moveit_headless.py # 自动化测试
│ │
│ ├── prbt_robot_support/ # CANopen 支持
│ │ ├── config/prbt/
│ │ │ ├── bus.yml # CANopen 配置 ⭐
│ │ │ └── prbt_0_1.dcf # 设备配置
│ │ └── launch/fake_slaves.launch.py
│ │
│ └── arm_prbt/ # 机器人 URDF
│
└── build/ & install/ # 编译输出
快速入门
1. 安装依赖
sudo apt update
sudo apt install -y \
ros-jazzy-moveit \
ros-jazzy-ros2-canopen \
ros-jazzy-canopen-fake-slaves \
ros-jazzy-ros2-control \
ros-jazzy-ros2-controllers \
can-utils
2. 编译工作空间
cd ~/ROS2_jazzy_moveit2_test
colcon build
source install/setup.bash
3. 启动系统
方式一:完整演示(带 RViz)
ros2 launch prbt_robot_moveit_config moveit_ros2canopen_with_fake_slaves.launch.py
在 RViz 中:
- 拖动交互标记设置目标位姿
- 点击 Plan 规划路径
- 点击 Execute 执行运动
方式二:无头模式(适用于测试)
终端 1:启动系统
ros2 launch prbt_robot_moveit_config moveit_ros2canopen_headless.launch.py
终端 2:运行测试脚本
python3 src/prbt_robot_moveit_config/scripts/test_moveit_headless.py
4. 验证运行
# 查看 CAN 总线消息
candump -ta vcan0
# 查看关节状态
ros2 topic echo /joint_states --once
# 查看控制器状态
ros2 control list_controllers
深度解析
CANopen 通信流程
-
NMT 状态机启动:
- 从站上电后进入
Switch On Disabled状态 - 调用
/joint_X/init服务切换到Operation Enabled - 启动后系统自动完成状态转换
- 从站上电后进入
-
同步周期通信:
- SYNC 周期:10ms(100Hz)
- RPDO:主站发送目标位置
- TPDO:从站反馈实际位置
-
CIA 402 驱动器配置:
- 位置模式:周期同步位置模式(CSP,模式 8)
- 控制字:6040h
- 状态字:6041h
- 目标位置:607Ah
- 实际位置:6064h
启动时序分析
完整的启动过程(使用合并 launch 文件):
Time Component Action
─────────────────────────────────────────────────
0s ├─ fake_slaves 6个虚拟从站节点启动
│ 发送Boot-Up帧(心跳报文)
│
5s ├─ ros2_control_node 启动,Master开始配置从站
│ 读取DCF文件,配置SDO参数
│ 启动SYNC周期
│
10s ├─ joint_state_broadcaster 发布关节状态
│
└─ prbt_group_controller 接收运动指令
参数调优经验
-
boot_timeout_ms:
- 默认值:2000ms(易超时)
- 推荐值:5000ms(考虑系统负载)
-
SYNC 周期:
- 虚拟 CAN:10ms(100Hz)足够
- 真实硬件:根据驱动器能力调整(1ms-10ms)
-
控制器参数:
prbt_group_controller: type: joint_trajectory_controller/JointTrajectoryController joints: [joint_1, joint_2, joint_3, joint_4, joint_5, joint_6] command_interfaces: [position] state_interfaces: [position, velocity]
调试技巧
1. CAN 总线监控
# 实时查看所有报文
candump -ta vcan0
# 筛选特定节点(如 node_id=3)
candump -ta vcan0 | grep " 003"
# 分析SYNC报文
candump -ta vcan0 | grep " 000"
典型输出:
(169.558018) vcan0 003 [8] 00 00 00 00 00 00 00 00 # TPDO1: 状态
(169.558018) vcan0 000 [0] # SYNC
(169.568018) vcan0 103 [8] 00 00 00 00 00 00 00 00 # RPDO1: 目标位置
2. ROS2 节点诊断
# 查看节点列表
ros2 node list
# 查看话题
ros2 topic list
ros2 topic hz /joint_states
# 服务调试
ros2 service list | grep init
3. 控制器调试
# 查看控制器状态
ros2 control list_controllers
# 手动发送轨迹(测试用)
ros2 topic pub /joint_trajectory_controller/joint_trajectory \
trajectory_msgs/msg/JointTrajectory '{...}'
4. 日志分析
# 查看特定节点日志
ros2 node info /controller_manager
# 实时日志过滤
ros2 topic echo /rosout | grep ERROR
常见问题 FAQ
Q1: 出现 Boot Timeout 错误?
A: 检查两点:
bus.yml中boot_timeout_ms: 5000- 使用合并 launch 文件启动(自动处理时序)
Q2: 控制器无法启动?
A: 通常是前面的错误导致 ros2_control_node 崩溃:
# 检查前面的日志
ros2 node list # 确认 /controller_manager 存在
Q3: 如何切换到真实 CAN 接口?
A: 修改两处配置:
- URDF:
<param name="can_interface_name">can0</param> - bus.yml:
master: { can_device: can0 }
Q4: 如何支持更多关节?
A: 修改以下文件:
- URDF: 添加 joint_X 和 transmission
- bus.yml: 添加对应节点配置
- controllers.yaml: 更新 joints 列表
Q5: 无头模式如何扩展?
A: 参考 test_moveit_headless.py,使用 MoveIt Python API:
import moveit_py
# 连接到 MoveGroup
robot = moveit_py.Robot("prbt")
arm = robot.get_planning_component("prbt_arm")
# 设置目标
arm.set_goal_state(...)
# 规划并执行
plan = arm.plan()
arm.execute(plan)
总结
本项目展示了 ROS2 CANopen 集成的完整流程,主要贡献包括:
- 解决启动时序问题:通过 TimerAction 和 boot_timeout 配置,确保系统稳定启动
- 提供完整示例:包含配置、启动、测试全套流程,开箱即用
- 支持无头模式:便于自动化测试和 CI/CD 集成
- 详细调试指南:CAN 总线监控、日志分析等实用技巧
下一步工作
- 接入真实 CANopen 驱动器(非虚拟)
- 集成视觉伺服
- 支持多机器人协同
更多推荐


所有评论(0)