第4章 SRDF与配置包
SRDF,全称是 Semantic Robot Description Format。说白了,它就是给机器人模型“注入灵魂”的文件。URDF 只告诉 MoveIt 你的机器人长什么样、有几个关节,但 SRDF 告诉它:哪些关节是一组的、哪些地方不能碰撞、末端执行器怎么抓东西。没有 SRDF,MoveIt 就是个睁眼瞎。
4.1 SRDF 到底干了什么?
我刚开始接触 MoveIt 时,以为只要 URDF 写好了就能规划。结果一运行,规划器直接报错:“找不到规划组”。后来才明白,SRDF 里必须定义好 group、end_effector、passive_joint 这些语义信息。它本质上是一个“配置文件”,告诉 MoveIt 怎么理解你的机器人。
- 规划组(group):比如把左臂的 6 个关节打包成
left_arm,方便调用。 - 末端执行器(end_effector):定义夹爪或工具,关联到某个规划组。
- 碰撞矩阵(disable_collisions):哪些连杆之间永远不会碰撞,比如相邻连杆,省掉不必要的碰撞检测。
- 虚拟关节(virtual_joint):把机器人固定在世界上,或者让它在平面上移动。
4.2 生成 SRDF —— MoveIt Setup Assistant
手动写 SRDF 太容易出错了。官方推荐用 MoveIt Setup Assistant(简称 MSA)来生成。它是一个图形化工具,你只需要加载 URDF,然后点点点,就能导出完整的配置包。
启动方式很简单:
roslaunch moveit_setup_assistant setup_assistant.launch
然后跟着向导走:
- 加载你的 URDF 文件(或者 xacro)。
- 添加虚拟关节 —— 我一般选
fixed或planar。 - 定义规划组:比如
arm_group,选择 kinematic chain,指定基座和末端。 - 定义末端执行器:关联到规划组,并指定抓取点。
- 生成碰撞矩阵:MSA 会自动计算并推荐忽略的碰撞对。
- 配置机器人自碰撞、附加物体等。
- 最后点击“生成配置包”,一个完整的 MoveIt 配置包就诞生了。
4.3 配置包的目录结构解析
生成后的配置包通常以 robot_name_moveit_config 命名。它的目录结构非常固定,我带你过一遍核心文件:
| 文件/目录 | 作用 |
|---|---|
config/ | 存放所有配置文件,包括 SRDF、 kinematics.yaml、joint_limits.yaml 等 |
config/robot_name.srdf | 核心语义文件,就是本章的主角 |
config/kinematics.yaml | 运动学求解器配置,比如选择 KDL 还是 TRAC-IK |
config/joint_limits.yaml | 关节速度、加速度限制,规划器会遵守这些限制 |
config/ompl_planning.yaml | OMPL 规划器的参数,比如规划时间、优化目标 |
launch/ | 启动文件,包括 planning_context.launch、move_group.launch 等 |
launch/planning_context.launch | 加载 URDF 和 SRDF,是其他 launch 文件的基础 |
launch/move_group.launch | 启动 move_group 节点,这是 MoveIt 的核心 |
嗯,这里要注意:config 目录下的 fake_controllers.yaml 也很重要,仿真时用虚拟控制器,不需要真实硬件。
4.4 手动调整 SRDF 的小技巧
虽然 MSA 能生成大部分内容,但有些细节还是得手调。比如你想让某个关节在规划时保持不动,可以加 <passive_joint name="finger_joint1"/>。或者你想自定义末端执行器的抓取点,直接在 SRDF 里改 <end_effector> 的 parent_link。
我记得有一次,客户要求机器人的夹爪必须从特定方向抓取。我就在 SRDF 里给末端执行器加了一个 group 属性,然后重新生成了碰撞矩阵。整个过程不到十分钟,比重新跑一遍 MSA 快多了。
4.5 验证你的配置包
生成完配置包,别急着写代码。先用 MoveIt 自带的 demo 启动一下:
roslaunch your_robot_moveit_config demo.launch
如果 RViz 里能显示机器人,并且你可以拖动规划组运动,说明 SRDF 基本没问题。如果报错说找不到某个组,八成是 SRDF 里的 group 名称写错了,或者 URDF 里的关节名对不上。
end_effector 配置漏了,结果抓取规划一直失败。后来在 SRDF 里补上 parent_group 就好了。