2. 机器人模型URDF
说实话,URDF(Unified Robot Description Format)是每个机器人工程师的入门必修课。我当年第一次接触它时,觉得不就是个XML文件嘛,有什么难的?结果真到自己写的时候,link和joint的关系绕得我头晕。今天咱们就把它彻底捋清楚。
2.1 URDF到底是什么?
URDF说白了就是机器人的「身份证」。它用XML格式描述机器人长什么样、关节怎么动、传感器装在哪。你想想看,仿真器不认识你的机器人,你得用URDF告诉它:这里有个轮子,那里有个手臂,它们之间怎么连接。
我个人习惯把URDF看作机器人的「骨架」——link是骨头,joint是关节。骨头本身不会动,关节决定了骨头之间怎么相对运动。
核心概念:
- link:刚体部件,有质量、惯性、视觉形状、碰撞形状
- joint:连接两个link,定义运动类型和相对位置
2.2 从零写一个最简单的URDF
咱们先别整复杂的。我带你写一个只有两个link和一个joint的「哑铃」模型。嗯,就是一根杆子两头各一个球。
<?xml version="1.0"?>
<robot name="dumbbell">
<!-- 第一个球 -->
<link name="left_ball">
<visual>
<geometry>
<sphere radius="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
</visual>
</link>
<!-- 第二个球 -->
<link name="right_ball">
<visual>
<geometry>
<sphere radius="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
</visual>
</link>
<!-- 连接杆 -->
<link name="bar">
<visual>
<geometry>
<cylinder length="0.5" radius="0.02"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
</visual>
</link>
<!-- 固定关节:左球到杆 -->
<joint name="left_joint" type="fixed">
<parent link="bar"/>
<child link="left_ball"/>
<origin xyz="-0.25 0 0" rpy="0 0 0"/>
</joint>
<!-- 固定关节:右球到杆 -->
<joint name="right_joint" type="fixed">
<parent link="bar"/>
<child link="right_ball"/>
<origin xyz="0.25 0 0" rpy="0 0 0"/>
</joint>
</robot>
这里有个坑,我当年踩过:joint的origin是相对于parent link的坐标系。也就是说,左球在杆的左边0.25米处,右球在右边0.25米处。如果你搞反了parent和child,机器人会直接「散架」。
2.3 link的视觉与碰撞模型
你可能注意到了,上面只写了<visual>。但在真机迁移时,<collision>才是关键。为什么?
视觉模型只负责「看起来像」,碰撞模型才负责「物理上撞到」。我在做AGV小车时,为了好看把视觉模型做得很精细,结果碰撞模型没更新,仿真里小车直接穿墙而过……嗯,那场面挺尴尬的。
我的建议:
- 视觉模型可以用复杂mesh,好看就行
- 碰撞模型尽量用基本几何体(box、cylinder、sphere),计算效率高
- 如果必须用mesh做碰撞,记得简化顶点数
2.4 joint的六种类型
joint类型决定了自由度。我整理了一张表,你直接拿去用:
| 类型 | 自由度 | 典型应用 |
|---|---|---|
| fixed | 0 | 底盘与传感器支架 |
| revolute | 1(旋转) | 机械臂关节、轮子 |
| prismatic | 1(平移) | 升降台、滑轨 |
| continuous | 1(无限旋转) | 全向轮、转台 |
| planar | 2(平面运动) | AGV全向移动 |
| floating | 6(全自由) | 无人机、水下机器人 |
你想想看,如果选错了类型,仿真里关节要么卡死,要么乱飞。我见过有人把机械臂的旋转关节写成prismatic,结果一启动手臂直接「伸长」了半米……
2.5 在仿真中显示你的机器人
写好了URDF,怎么看到它?最直接的方式是用robot_state_publisher + joint_state_publisher + Rviz。
# 1. 启动robot_state_publisher,它会解析URDF并发布tf
ros2 launch robot_state_publisher robot_state_publisher.launch.py \
urdf_file:=/path/to/your/dumbbell.urdf
# 2. 启动joint_state_publisher(如果有可动关节)
ros2 run joint_state_publisher joint_state_publisher
# 3. 打开Rviz,添加RobotModel显示
rviz2
在Rviz中,记得把Fixed Frame设为你的根link(比如上面的"bar")。我第一次做的时候忘了设,结果机器人模型在屏幕外飘着,找了半天……
注意:URDF中必须有一个根link,且所有joint最终都要连接到这个根上。否则Rviz会报错「No transform from ... to ...」。
2.6 知识体系结构图
下面这张图帮你理清URDF的核心逻辑。我画了好几次才满意,你仔细看看:
2.7 避坑指南:我踩过的三个坑
- 坐标系搞反:我曾经把parent和child写反,结果机器人关节反向旋转。检查方法很简单——在Rviz里手动拖动joint,看运动方向对不对。
- 惯性参数缺失:Gazebo仿真时,如果link没有
<inertial>,物理引擎会报错。我建议用urdf_to_graphiz工具检查完整性。 - 文件名编码问题:URDF里引用的mesh文件路径不要有中文或空格。我在Windows上写路径时吃过这个亏,ROS直接不认。
实用工具推荐:
check_urdf:检查URDF语法错误urdf_to_graphiz:生成机器人结构图rviz+robot_state_publisher:实时可视化调试
好了,URDF的基础就这些。你写的时候记住一句话:link是零件,joint是装配关系。把这个想明白,后面学xacro、学MoveIt都会轻松很多。
可可精品资料库