2. URDF标签详解(上):<robot>、<link>、<visual> 标签的使用与属性配置

URDF 是 ROS 里描述机器人模型的骨架。说白了,它就是一堆 XML 标签,告诉系统你的机器人长什么样、关节怎么动。今天咱们先啃最核心的三个标签:<robot>、<link> 和 <visual>。我个人习惯把这三个标签称为「URDF 三兄弟」——没有它们,模型根本立不起来。

URDF 标签结构(上) <robot> <link> <visual> geometry origin

2.1 <robot> —— 模型的根,一切从这里开始

<robot> 是所有 URDF 文件的顶层标签。你想想看,没有它,其他标签往哪儿放?它就像一栋房子的地基,所有 <link> 和 <joint> 都得包在里面。

标准写法:
<robot name="my_robot">
    <link> ... </link>
    <joint> ... </joint>
</robot>

name 属性是必填的,我建议你起个有意义的名字,比如 turtlebot3_waffle 或者 chassis_v2。千万别用 test 或 aaa——我在项目里见过有人这么干,结果三个月后自己都忘了这个模型是干啥的。

2.2 <link> —— 机器人的每一个刚体部件

每个 <link> 代表一个刚体零件。底盘、轮子、激光雷达支架……都是 link。它本身不包含几何形状,但可以挂载 <visual>、<collision> 和 <inertial> 子标签。

嗯,这里要注意:<link> 必须有一个 name 属性,而且名字在整个模型里不能重复。我曾经因为把两个轮子都叫 wheel,导致 TF 树直接崩溃,查了半天才发现是重名。

💡 个人习惯: 命名用下划线分隔,比如 left_front_wheel、base_link。这样在 rviz 里看 TF 树一目了然。

2.3 <visual> —— 让 link 变得「看得见」

<visual> 是 <link> 的子标签,用来定义这个零件的可视化外观。没有它,你的机器人在 rviz 里就是一堆看不见的坐标轴。它包含三个核心子元素:<geometry>、<origin> 和 <material>。

2.3.1 geometry —— 形状由你定

支持四种基本几何:box、cylinder、sphere 和 mesh。我平时用得最多的是 box 和 cylinder,因为简单可靠。但如果你要搞一个酷炫的机器人外壳,那就得上 mesh 了。

几何类型属性示例
boxsize (xyz)<box size="0.4 0.3 0.1"/>
cylinderradius, length<cylinder radius="0.1" length="0.05"/>
sphereradius<sphere radius="0.2"/>
meshfilename, scale<mesh filename="package://my_robot/meshes/arm.stl" scale="1 1 1"/>

2.3.2 origin —— 位置和朝向

用来调整 visual 相对于 link 坐标系的偏移。默认原点在 link 中心,但很多时候你需要微调。比如把轮子视觉模型往下挪一点,让它贴地。

<origin xyz="0 0 -0.05" rpy="0 0 0"/>

rpy 是绕固定轴的旋转(roll, pitch, yaw),单位弧度。我刚开始总搞混顺序,后来记住「先绕 X 转,再绕 Y,最后绕 Z」就再也没错过。

2.3.3 material —— 给点颜色看看

可以定义颜色或纹理。颜色用 RGBA,范围 0~1。比如红色:<color rgba="1 0 0 1"/>。你也可以在 <robot> 里预先定义材质,然后通过 material="red" 引用,这样多个 link 就能共用颜色。

⚠️ 我曾经踩过的坑: 在 <visual> 里只写了 geometry,忘了写 origin,结果模型在 rviz 里飞到了半空中。后来我养成了习惯——每个 visual 都显式写 origin,哪怕全是 0。

2.4 完整示例:一个带底盘的机器人

下面是一个极简 URDF,包含一个底盘 link 和它的 visual。你可以直接复制到 .urdf 文件里试试。

<?xml version="1.0"?>
<robot name="simple_chassis">
    <link name="base_link">
        <visual>
            <geometry>
                <box size="0.5 0.4 0.12"/>
            </geometry>
            <origin xyz="0 0 0.06" rpy="0 0 0"/>
            <material name="blue">
                <color rgba="0.2 0.4 0.9 1"/>
            </material>
        </visual>
    </link>
</robot>

你想想看,这个底盘就是一个 0.5m × 0.4m × 0.12m 的蓝色方块,中心在 base_link 坐标系上方 0.06m 处。保存后用 check_urdf 命令验证,再用 urdf_to_graphiz 就能看到结构图。

🔧 避坑指南: 如果你用 mesh 文件,路径一定要用 package:// 开头,不要写路径。我曾经把同事的 STL 文件放在桌面,用 /home/xxx/desktop/part.stl,结果换台电脑就找不到模型了。用 package:// 才是 ROS 的规范做法。

2.5 三个标签的协作逻辑

简单总结一下:<robot> 是总容器,<link> 是零件,<visual> 是零件的「皮囊」。一个 link 可以有多个 visual(比如一个轮子既有橡胶纹理又有轮毂),但通常一个就够了。我个人习惯把 visual 和 collision 分开写,虽然麻烦点,但后期调导航代价地图时能省不少事。

嗯,这一章的内容其实不多,但都是基本功。下一章我们会继续聊 <collision>、<inertial> 和 <joint>,到时候就能让机器人动起来了。