3. 第一个URDF模型:创建简单的连杆与关节
说实话,URDF 这玩意儿刚接触时挺唬人的。一堆 XML 标签,什么 link、joint、geometry,看着像天书。但你别怕,拆开来看,其实就两样东西:连杆(link)和关节(joint)。
我当年第一次写 URDF,花了整整一下午才让一个方块出现在 Rviz 里。后来发现,核心逻辑就三句话:
- 连杆是「零件」
- 关节是「连接方式」
- Rviz 是「照妖镜」,能让你看到模型长啥样
好,咱们直接动手。
3.1 连杆(link)—— 机器人的「骨头」
连杆就是机器人的每一个刚体部件。底座、手臂、轮子、摄像头支架……全是 link。每个 link 在 URDF 里就是一个 <link> 标签。
一个最简单的 link 长这样:
<link name="base_link">
<visual>
<geometry>
<box size="0.2 0.1 0.05"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</visual>
</link>
这里我解释一下每个字段:
| 字段 | 含义 | 我的经验 |
|---|---|---|
name |
连杆的唯一标识 | 建议用英文小写+下划线,别用中文 |
visual |
可视化属性,决定你在 Rviz 里看到什么 | 可以没有,但你就看不见它了 |
geometry |
形状:box、cylinder、sphere、mesh | 调试阶段用 box 最方便 |
origin |
相对于 link 坐标系的偏移和旋转 | 默认是 (0,0,0),别乱改 |
material |
颜色和材质 | 颜色用 RGBA,A=1 不透明 |
3.2 关节(joint)—— 连接「骨头」的「韧带」
关节把两个 link 连在一起,并定义它们之间的相对运动。没有关节,你的机器人就是一盘散沙。
关节有几种常见类型:
| 类型 | 自由度 | 典型用途 |
|---|---|---|
fixed |
0 | 螺丝固定、焊接、底座 |
revolute |
1(旋转) | 关节电机、轮子 |
prismatic |
1(平移) | 伸缩臂、滑轨 |
continuous |
1(无限旋转) | 车轮、转台 |
floating |
6 | 无人机、自由漂浮物 |
一个最简单的 fixed 关节:
<joint name="base_to_wheel" type="fixed">
<parent link="base_link"/>
<child link="wheel_link"/>
<origin xyz="0.1 0 0" rpy="0 0 0"/>
</joint>
注意三个关键点:
- parent:父连杆,通常是靠近基座的部件
- child:子连杆,相对于父连杆运动
- origin:子连杆在父连杆坐标系中的位置
3.3 完整示例:一个两连杆的简单模型
咱们把上面两个概念合起来,写一个完整的 URDF 文件。这个模型包含一个底座和一个轮子,用 fixed 关节连接。
<?xml version="1.0"?>
<robot name="simple_robot">
<!-- 底座 -->
<link name="base_link">
<visual>
<geometry>
<box size="0.3 0.2 0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
<material name="blue">
<color rgba="0.2 0.4 0.8 1"/>
</material>
</visual>
</link>
<!-- 轮子 -->
<link name="wheel_link">
<visual>
<geometry>
<cylinder radius="0.05" length="0.04"/>
</geometry>
<origin xyz="0 0 0" rpy="1.57 0 0"/>
<material name="gray">
<color rgba="0.5 0.5 0.5 1"/>
</material>
</visual>
</link>
<!-- 连接底座和轮子 -->
<joint name="base_to_wheel" type="fixed">
<parent link="base_link"/>
<child link="wheel_link"/>
<origin xyz="0.15 0 -0.05" rpy="0 0 0"/>
</joint>
</robot>
你发现没有?轮子用了 cylinder,并且 rpy="1.57 0 0" 把它旋转了 90 度,让圆柱的轴线朝 Y 轴方向——这样看起来才像个轮子。1.57 弧度就是 90 度,我习惯用弧度,因为 URDF 只认弧度。
3.4 在 Rviz 中可视化你的第一个模型
模型写好了,怎么看?Rviz 就是你的「3D 预览窗口」。
步骤很简单:
- 把上面的 URDF 保存为
simple_robot.urdf - 启动 Rviz:
rviz2(ROS2)或rviz(ROS1) - 在 Rviz 中,添加一个 RobotModel 显示插件
- 在 RobotModel 的属性中,把 Robot Description 设为
robot_description - 发布 URDF 到参数服务器:
ros2 run robot_state_publisher robot_state_publisher simple_robot.urdf
嗯,这里要注意:Rviz 本身不直接读 URDF 文件。它从 ROS 参数服务器获取模型。所以你需要先启动 robot_state_publisher 节点,它会自动把 URDF 加载到参数里。
3.5 本章知识结构图
下面这张图帮你理清 URDF 模型的核心组成和可视化流程:
3.6 常见问题与避坑
我整理了几个新手最容易踩的坑,你写 URDF 时多留个心眼:
- 忘记加
<robot>根标签——URDF 文件必须有一个<robot name="xxx">包裹所有内容 - link 名称重复——每个 link 的 name 必须唯一,重复会导致加载失败
- joint 的 parent 和 child 写反——父连杆靠近基座,子连杆远离基座
- origin 坐标乱写——子连杆的位置是相对于父连杆的,不是世界坐标系
- 忘记启动 robot_state_publisher——Rviz 不会自动加载 URDF,必须通过这个节点发布
<geometr>,少了个 y。URDF 解析器不会报错,只会默默跳过。所以,写完一定要用 check_urdf 工具验证一下。
验证命令:
check_urdf simple_robot.urdf
如果输出类似下面这样,说明语法正确:
robot name is: simple_robot
---------- Successfully Parsed XML ---------------
root link: base_link has 1 child(ren)
child(1): wheel_link
看到这个输出,你就可以放心去 Rviz 里欣赏你的第一个 URDF 模型了。