4 · 第一个URDF模型

搭建一个简单的两连杆机器人、使用 urdf_to_graphiz 可视化模型、在 Rviz 中加载并显示模型。

第4章 核心流程 ① 编写两连杆URDF ② urdf_to_graphiz ③ Rviz 加载显示 从零构建 → 结构验证 → 可视化调试

4.1 为什么从两连杆开始?

很多初学者一上来就想搭一个六轴机械臂,结果被一堆坐标变换搞晕。我个人习惯是:先让一个关节动起来,再谈复杂结构。两连杆机器人虽然简单,但它包含了 URDF 最核心的三个要素:link、joint 和 geometry。你想想看,只要搞懂这两个杆子怎么连,后面加再多关节都是重复这个套路。

💡 核心知识点:一个 link 定义刚体(形状、尺寸、颜色),一个 joint 定义两个 link 之间的相对运动(旋转或平移)。两连杆就是“基座 → 关节1 → 连杆1 → 关节2 → 连杆2”。

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 算错,导致模型在空中“劈叉”的情况……

🔧 我的小习惯:写 URDF 时,先把每个 link 的 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 指向反了。

⚠️ 避坑指南:urdf_to_graphiz 只检查语法和树结构,不检查碰撞尺寸。就算你的杆子长到月球上,它也能生成漂亮的图。所以图形正确只是第一步。

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 的单位是弧度,我写成了角度…… 所以,所有角度都用弧度,这是新手最容易忽略的细节。

💬 一点经验:如果你在 Rviz 里拖动关节时模型剧烈抖动,检查一下 limit 里的 effort 和 velocity 是否设得太小。虽然只是可视化,但底层还是会做简单的动力学检查。

4.6 本章小结

我们亲手写了一个两连杆 URDF,用 urdf_to_graphiz 验证了树结构,最后在 Rviz 里看到了会动的模型。说白了,URDF 就是个“机器人乐高说明书”——你定义零件(link)和连接方式(joint),ROS 帮你渲染和仿真。下一章我们会给模型穿上更漂亮的“衣服”(材质与颜色),但今天你已经迈出了最扎实的一步。