第2章:URDF基础语法:XML标签结构、<robot>根标签、<link>标签详解

各位同学,欢迎来到第二章。上一章我们聊了URDF能干什么,这一章咱们直接上手,把它的骨架拆开看看。

URDF说白了就是一个XML文件。你想想看,机器人那么多关节、连杆,总得有个规矩把它们串起来。XML就是那个规矩。我个人习惯把URDF比作一张「零件清单+装配图」——每个零件长什么样、多重、怎么装,全写在这一个文件里。

2.1 XML标签结构——规矩就是规矩

先看一个最简的骨架:

<?xml version="1.0"?>
<robot name="my_robot">
    <link name="base_link">
        ...
    </link>
    <joint name="base_joint" type="fixed">
        ...
    </joint>
</robot>

嗯,这里要注意:所有标签必须成对出现。有<robot>就必须有</robot>。我在项目中遇到过有人漏了闭合标签,Gazebo直接崩溃,查了半天才发现少了个斜杠。这种低级错误,你写多了自然就条件反射了。

XML的层级关系也很重要:

  • 根标签:<robot>,整个文件的祖宗
  • 一级子标签:<link>、<joint>,平级关系
  • 二级子标签:<inertial>、<visual>、<collision>,属于某个link

为什么强调这个?因为ROS的解析器是按树结构读的。你写错了层级,它就不认。说白了,这就是个「爹-儿子-孙子」的关系,别搞混。

核心原则:每个link必须有唯一name,每个joint也必须唯一。重名?解析器直接报错,不跟你商量。

2.2 <robot>根标签——一切从这里开始

<robot>是整个URDF文件的入口。它只有一个必填属性:name。这个name就是你机器人的名字,比如"panda"、"my_arm"。

<robot name="simple_arm">
    ...
</robot>

我曾经犯过一个错:给两个不同的机器人模型起了同一个名字。结果ROS里加载第二个时,直接把第一个覆盖了。你想想看,调试了半天发现模型不对,最后发现是名字冲突——这种坑,踩过一次就记住了。

除了name,<robot>还可以加一些注释用的子标签,比如<material>定义颜色材质。但说实话,我建议你把材质定义放在具体的link里,这样更清晰。根标签就老老实实当个容器,别塞太多东西。

小技巧:在<robot>里加一个<gazebo>标签,可以配置仿真参数。不过那是后面章节的内容,这里先提一嘴。

2.3 <link>标签详解——机器人的每一块骨头

link就是机器人的一个刚体部件。一个机械臂通常有6-7个link,每个link包含三部分:惯性、视觉、碰撞。这三部分缺一不可,但可以留空。

2.3.1 惯性(inertial)——物理引擎的命根子

惯性参数决定了机器人动起来像什么。你想想看,一个5kg的连杆和一个50kg的连杆,运动起来能一样吗?

<link name="link1">
    <inertial>
        <origin xyz="0 0 0" rpy="0 0 0"/>
        <mass value="2.0"/>
        <inertia ixx="0.01" ixy="0" ixz="0"
                  iyy="0.01" iyz="0"
                  izz="0.01"/>
    </inertial>
</link>

这里有个坑:惯性张量矩阵必须是对称正定的。什么意思?就是ixx、iyy、izz必须大于0,而且不能随便填。我见过有人把ixx写成0,结果仿真时连杆像纸片一样飘——物理引擎直接懵了。

怎么算惯性张量?如果你用的是标准几何体(圆柱、长方体),有公式可以算。如果是复杂形状,我建议用SolidWorks或Fusion 360导出,别手算。手算容易错,而且浪费时间。

避坑指南:我曾经在项目里手算了一个异形连杆的惯性张量,结果仿真时机器人疯狂抖动。后来用CAD软件重新导出,问题立刻解决。所以——能用工具就别手算。

2.3.2 视觉(visual)——看起来像什么

视觉部分只影响显示,不影响物理。你可以把link画成一个圆柱,但碰撞模型用长方体——只要你不觉得别扭就行。

<visual>
    <origin xyz="0 0 0.05" rpy="0 0 0"/>
    <geometry>
        <cylinder length="0.1" radius="0.02"/>
    </geometry>
    <material name="blue">
        <color rgba="0 0 1 1"/>
    </material>
</visual>

注意<origin>的xyz和rpy。这个坐标是相对于link自身坐标系的。我习惯把视觉原点放在link的几何中心,这样旋转时看着自然。但如果你想让某个面朝上,可以调整rpy。

材质颜色用RGBA四通道,A是透明度。1.0表示完全不透明。我一般用0.8-1.0,太透明了看不清。

2.3.3 碰撞(collision)——物理世界的边界

碰撞模型决定了机器人跟外界怎么「硬碰硬」。它跟视觉模型可以不一样,而且我建议你尽量简化碰撞模型。

<collision>
    <origin xyz="0 0 0.05" rpy="0 0 0"/>
    <geometry>
        <box size="0.04 0.04 0.1"/>
    </geometry>
</collision>

为什么简化?因为碰撞检测很费计算。你想想看,一个复杂的机械臂有几十个link,每个link都用精细网格做碰撞检测,仿真帧率直接掉到个位数。用长方体或圆柱体代替,计算量能降一个数量级。

经验之谈:我做过一个六轴机械臂项目,视觉模型用了STL网格,碰撞模型全部用长方体包裹。仿真速度提升了3倍,而且碰撞检测的精度完全够用。记住:碰撞模型是给物理引擎看的,不是给人看的。

2.4 知识体系总览

下面这张图把本章的核心逻辑串起来了。你可以把它当作URDF的「思维导图」:

<robot> 根标签 <link> 连杆 <joint> 关节 惯性 (inertial) 视觉 (visual) 碰撞 (collision) 质量 mass 惯性张量 几何 材质 几何 核心原则 每个link必须包含inertial、visual、collision三部分 碰撞模型尽量简化,视觉模型可以精细

2.5 本章小结

好,我们来捋一捋:

  • XML结构:树形层级,标签成对,name唯一
  • <robot>根标签:整个文件的容器,name属性必填
  • <link>三件套:惯性(物理)、视觉(显示)、碰撞(检测)

我个人觉得,URDF最难的不是语法,而是「惯性张量」这个概念。很多初学者随便填几个数,结果仿真一跑就飞了。我的建议是:先用标准几何体练手,把圆柱、长方体的惯性张量算明白,再碰复杂形状。

下一章我们会讲<joint>标签,那是让机器人动起来的关键。关节类型、运动范围、传动比——这些东西才是机械臂的灵魂。不过那是后话了,先把link吃透再说。

课后练习:写一个包含两个link的URDF文件。第一个link是底座(长方体),第二个link是手臂(圆柱体)。给它们分别配上惯性、视觉、碰撞参数。然后扔到check_urdf命令里检查语法。试试看,10分钟搞定。

可可精品资料库