4 · 第一个URDF模型
搭建一个简单的两连杆机器人、使用 urdf_to_graphiz 可视化模型、在 Rviz 中加载并显示模型。
4.1 为什么从两连杆开始?
很多初学者一上来就想搭一个六轴机械臂,结果被一堆坐标变换搞晕。我个人习惯是:先让一个关节动起来,再谈复杂结构。两连杆机器人虽然简单,但它包含了 URDF 最核心的三个要素:link、joint 和 geometry。你想想看,只要搞懂这两个杆子怎么连,后面加再多关节都是重复这个套路。
4.2 手写第一个 URDF 文件
我不喜欢用工具自动生成,自己写一遍才能理解每个标签的含义。下面这个文件,我建议你逐行敲进编辑器。
<?xml version="1.0"?>
<robot name="two_link_arm">
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.2" radius="0.05"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</visual>
</link>
<joint name="joint1" type="revolute">
<parent link="base_link"/>
<child link="link1"/>
<origin xyz="0 0 0.1" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-3.14" upper="3.14" effort="10" velocity="1"/>
</joint>
<link name="link1">
<visual>
<geometry>
<box size="0.6 0.04 0.04"/>
</geometry>
<origin xyz="0.3 0 0" rpy="0 0 0"/>
<material name="red">
<color rgba="1 0 0 1"/>
</material>
</visual>
</link>
<joint name="joint2" type="revolute">
<parent link="link1"/>
<child link="link2"/>
<origin xyz="0.6 0 0" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-3.14" upper="3.14" effort="10" velocity="1"/>
</joint>
<link name="link2">
<visual>
<geometry>
<box size="0.5 0.04 0.04"/>
</geometry>
<origin xyz="0.25 0 0" rpy="0 0 0"/>
<material name="green">
<color rgba="0 1 0 1"/>
</material>
</visual>
</link>
</robot>
保存为 two_link_arm.urdf。注意 origin 的偏移量——joint 的位置决定了杆子从哪里长出来。我在项目中遇到过好几次因为 origin 算错,导致模型在空中“劈叉”的情况……
origin 画在草图上。基座在 (0,0,0),关节1在基座顶部,link1 从关节1延伸出去,关节2在 link1 末端,link2 再延伸。这样不容易乱。
4.3 用 urdf_to_graphiz 看结构
写完了对不对?别急着扔进 Rviz。先跑一下 urdf_to_graphiz,它能生成一张树状图,帮你检查父子关系是否正确。
# 终端执行
urdf_to_graphiz two_link_arm.urdf
会生成 two_link_arm.pdf 和 two_link_arm.gv。打开 PDF 你会看到:
- base_link 是根节点
- joint1 连接 base_link → link1
- joint2 连接 link1 → link2
嗯,这里要注意:如果图里出现了意料之外的连线,多半是 parent 或 child 写反了。我曾经有一次把 parent 和 child 搞混,结果 Rviz 里杆子直接穿模,查了半天才发现是 joint 指向反了。
4.4 在 Rviz 里让模型站起来
这一步最让人兴奋。启动 Rviz 并加载你的 URDF:
# 方法一:直接 launch(推荐)
ros2 launch urdf_tutorial display.launch.py model:=`pwd`/two_link_arm.urdf
# 方法二:手动加载
ros2 run robot_state_publisher robot_state_publisher --ros-args -p robot_description:=`cat two_link_arm.urdf`
# 然后另开终端启动 rviz2,添加 RobotModel 显示
如果一切顺利,你会看到一根蓝色圆柱(基座),上面连着一根红色长条(link1),再连着一根绿色长条(link2)。用 joint_state_publisher 拖动关节滑块,两根杆子就会绕 Z 轴旋转。
- 基座是否在地面附近?如果飘在半空,检查 base_link 的 origin。
- 关节旋转方向对不对?axis 设为 (0,0,1) 是绕 Z 转,如果发现杆子横着转,可能是 axis 写错了。
- 颜色是否显示?URDF 中的 material 需要显式引用,或者直接在 visual 里定义。
4.5 常见问题与我的“血泪史”
| 现象 | 大概率原因 | 怎么治 |
|---|---|---|
| Rviz 里看不到模型 | robot_description 参数没传进去 | 检查 launch 文件或 echo 参数 |
| 关节滑块不动 | joint_state_publisher 没启动 | 加 --gui 选项 |
| 杆子位置错乱 | origin 偏移量算错 | 用 urdf_to_graphiz 对比坐标 |
| 颜色全是白的 | material 名称没对应或没定义 | 在 link 内部直接写 color 标签 |
我记得刚学 URDF 那会儿,为了调一个 joint 的 origin,花了整整一下午。后来发现是 rpy 的单位是弧度,我写成了角度…… 所以,所有角度都用弧度,这是新手最容易忽略的细节。
limit 里的 effort 和 velocity 是否设得太小。虽然只是可视化,但底层还是会做简单的动力学检查。
4.6 本章小结
我们亲手写了一个两连杆 URDF,用 urdf_to_graphiz 验证了树结构,最后在 Rviz 里看到了会动的模型。说白了,URDF 就是个“机器人乐高说明书”——你定义零件(link)和连接方式(joint),ROS 帮你渲染和仿真。下一章我们会给模型穿上更漂亮的“衣服”(材质与颜色),但今天你已经迈出了最扎实的一步。