3、第一个URDF文件:创建最简单的机器人模型

好了,到了真正动手写代码的时候了。前面两章我们聊了URDF是什么、为什么用它,现在直接上干货——创建一个最简单的机器人模型。

我个人习惯,学任何新东西都是从最小可行模型开始。你想想看,如果连一个底盘都定义不好,后面加轮子、加传感器只会越搞越乱。所以这一章,我们就只做一件事:用URDF描述一个底盘。

3.1 URDF文件的基本骨架:<robot>标签

每个URDF文件,最外层必须有一个 <robot> 标签。它就像房子的地基,所有零件都装在里面。

<?xml version="1.0" encoding="utf-8"?>
<robot name="my_first_robot">
    <!-- 这里放 link 和 joint -->
</robot>

注意几个细节:

  • name属性是必须的,给机器人取个名字。我一般用项目代号或功能描述,比如 simple_chassis。
  • XML声明可以省略,但建议加上。尤其是中文注释多的时候,指定 encoding="utf-8" 能避免乱码。
  • 注释用 <!-- -->,和HTML一样。我在项目里习惯在文件头部写版本号和修改日期。
小技巧: 如果你用VS Code写URDF,可以安装XML插件,它会自动帮你检查标签是否闭合。我曾经手写一个200行的URDF,少了一个斜杠,Gazebo加载时直接崩溃,排查了半小时……

3.2 定义底盘:<link>标签的核心用法

<link> 描述的是机器人身上的一个刚体部件。底盘、轮子、手臂连杆,都是link。每个link可以包含三个子部分:

子标签 作用 是否必须
<inertial> 质量、惯性矩阵 仿真时必须
<visual> 可视化外观(形状、颜色) 建议有
<collision> 碰撞检测用的简化形状 仿真时必须

对于第一个模型,我们只加 <visual>,先让它在Rviz里能显示出来。

3.3 写一个完整的底盘URDF

下面这个例子,定义了一个长0.6米、宽0.4米、高0.2米的矩形底盘。说白了就是一个盒子。

<?xml version="1.0" encoding="utf-8"?>
<robot name="simple_chassis">

    <link name="base_link">
        <visual>
            <geometry>
                <box size="0.6 0.4 0.2"/>
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <material name="blue">
                <color rgba="0 0 1 1"/>
            </material>
        </visual>
    </link>

</robot>

拆开来看:

  • link name="base_link" —— 底盘的名字。ROS里习惯把机器人的主体叫 base_link,这是约定俗成的根坐标系。
  • <geometry> —— 几何形状。这里用 <box>,三个数字分别对应长、宽、高(单位:米)。
  • <origin> —— 位置和姿态。xyz是相对link坐标系的偏移,rpy是绕固定轴的旋转(roll、pitch、yaw)。这里全零,表示几何中心就在link原点。
  • <material> —— 外观材质。颜色用RGBA四通道,值范围0~1。0 0 1 1 就是不透明的纯蓝色。
关键点: <origin> 的xyz偏移是相对于link自身的坐标系。如果你想让底盘中心在地面以上0.1米,可以写 xyz="0 0 0.1"。我在做AGV小车时,经常用这个偏移来调整底盘离地高度。

3.4 形状不止盒子:cylinder和sphere

除了盒子,URDF还支持圆柱体和球体。下面这个表总结了三种基本形状的写法:

形状 标签 参数 示例
盒子 <box> size="长 宽 高" size="0.6 0.4 0.2"
圆柱体 <cylinder> radius="半径" length="高度" radius="0.15" length="0.1"
球体 <sphere> radius="半径" radius="0.2"

举个例子,如果你想把底盘做成一个圆柱体(像某些扫地机器人那样):

<link name="base_link">
    <visual>
        <geometry>
            <cylinder radius="0.3" length="0.15"/>
        </geometry>
        <origin xyz="0 0 0.075" rpy="0 0 0"/>
        <material name="gray">
            <color rgba="0.5 0.5 0.5 1"/>
        </material>
    </visual>
</link>

注意这里 origin 的z轴设成了 0.075(高度的一半),目的是让圆柱体的底面刚好落在z=0平面上。嗯,这个细节很容易忘,我第一次写的时候就没加,结果底盘悬在半空中……

3.5 本章知识结构图

下面这张图帮你理清URDF文件的基本结构:

URDF文件结构(第3章核心) <robot name="..."> <link name="base_link"> <inertial> <visual> <collision> <geometry> + <origin> + <material> 本章重点:只使用 <visual> 定义底盘外观,inertial 和 collision 后续章节会补上

3.6 验证你的URDF文件

写完了怎么知道对不对?ROS提供了一个命令行工具:check_urdf。

# 安装工具(如果还没装)
sudo apt install liburdfdom-tools

# 检查URDF文件
check_urdf simple_chassis.urdf

如果一切正常,你会看到类似这样的输出:

robot name is: simple_chassis
---------- Successfully Parsed XML ---------------
root link: base_link has 1 child(ren)
    child(1):  base_link
常见错误: 如果你看到 ERROR: No root link found,说明你的URDF里没有定义任何link。或者link的name属性写错了。我曾经犯过一个低级错误——把 name 写成了 Name,XML是大小写敏感的,排查了十分钟才发现。

3.7 在Rviz里看一眼

光看文字不过瘾,我们把它显示出来。用 urdf_to_graphiz 可以生成结构图,但更直观的是用Rviz:

# 启动Rviz并加载URDF
ros2 run urdf_tutorial display.launch.py model:=`pwd`/simple_chassis.urdf

如果你是ROS1用户,命令稍有不同:

roslaunch urdf_tutorial display.launch model:=`pwd`/simple_chassis.urdf

Rviz窗口里应该出现一个蓝色的盒子或圆柱体。你可以用鼠标旋转视角,从各个方向观察它。

个人经验: 第一次在Rviz里看到自己写的模型,那种感觉挺奇妙的。虽然只是一个盒子,但它是你亲手用代码“捏”出来的。我当年做第一个URDF时,盯着那个蓝色方块看了好几分钟,确认它确实在旋转、确实有三维感——嗯,那种成就感是看教程体会不到的。

3.8 本章小结

这一章我们做了三件事:

  • 学会了URDF文件的基本骨架:<robot> 标签
  • 用 <link> 定义了一个底盘,包含 <visual> 和几何形状
  • 掌握了三种基本形状(box、cylinder、sphere)的写法

别看内容少,这是整个机器人建模的起点。后面的所有关节、传感器、传动系统,都是在这个底盘上长出来的。把这个基础打牢,后面会顺很多。