2、XML基础回顾:XML标签与属性、XML的树形结构、URDF中的XML规范

好,咱们正式开始第二讲。在动手写URDF之前,我强烈建议先花点时间把XML的基础过一遍。你可能会想:“XML嘛,不就是一堆尖括号?” 嗯,话是这么说,但URDF对XML的用法有它自己的脾气。我在项目里见过太多因为少写一个斜杠、搞错属性位置,导致整个机器人模型加载不出来的情况。所以,这一节咱们把地基打牢。

2.1 XML标签与属性:机器人的“骨架”和“关节”

说白了,XML就是一种用纯文本描述数据结构的语言。它只有两个核心概念:标签(Tag) 和 属性(Attribute)。

  • 标签:就像机器人的骨架。它定义了“这是什么”。比如 <link> 表示一个连杆,<joint> 表示一个关节。标签必须成对出现,有头有尾:<link>...</link>。如果标签里没有内容,可以简写为自闭合形式:<link />。
  • 属性:就像骨架上的关节参数。它定义了“这个东西长什么样”。属性写在起始标签里,格式是 名字="值"。比如 <joint name="shoulder_pan" type="revolute">,这里的 name 和 type 就是属性。

核心记忆点: 标签定义结构,属性定义参数。在URDF里,你几乎所有的机器人参数(尺寸、颜色、惯性、传动比)都是通过属性传递的。

举个例子,一个最简单的连杆长这样:

<link name="base_link">
  <visual>
    <geometry>
      <box size="0.2 0.2 0.1" />
    </geometry>
  </visual>
</link>

你看,<link> 是标签,name="base_link" 是属性。<box> 也是标签,它的 size 属性定义了长宽高。这里有个小细节:<box /> 是自闭合的,因为它里面没有子标签了。

我的习惯: 写属性值时,我永远用双引号,不用单引号。虽然XML语法上单引号也行,但ROS的解析器在某些旧版本里对单引号支持得不好。为了避免这种莫名其妙的坑,统一用双引号最省心。

2.2 XML的树形结构:从“散装零件”到“装配体”

XML最牛的地方在于它的树形结构。你可以把标签一层层嵌套起来,形成父子关系。这跟机器人本身的层级结构天然吻合——一个关节下面挂一个连杆,连杆下面再挂子关节,子关节下面再挂子连杆……

我刚开始学的时候,总觉得这玩意儿不就是个文件夹嘛。但真正在调试一个六轴机械臂时,我才体会到树形结构的重要性。你想想看,如果所有零件都平铺在同一个层级,那修改一个末端执行器的位置,你得手动算一堆坐标变换。但有了树形结构,你只需要改父关节的参数,子零件会自动跟着动。

来看一个典型的树形结构:

<robot name="my_robot">
  <link name="base"> ... </link>
  <joint name="joint1" type="continuous">
    <parent link="base"/>
    <child link="arm1"/>
  </joint>
  <link name="arm1"> ... </link>
  <joint name="joint2" type="revolute">
    <parent link="arm1"/>
    <child link="arm2"/>
  </joint>
  <link name="arm2"> ... </link>
</robot>

这个结构用图表示更清楚。我画了一张SVG图,帮你理解这种层级关系:

URDF 树形结构示例 <robot name="my_robot"> <link name="base"> <joint name="joint1"> <link name="arm1"> 层级关系说明 • robot 是根节点 • link 是实体零件 • joint 连接父子 link • 子节点继承父节点坐标

看到没?<robot> 是根,下面挂着 <link> 和 <joint>。每个 <joint> 通过 <parent> 和 <child> 标签,把两个 <link> 串起来。这就是URDF的核心逻辑——用树形结构描述运动链。

2.3 URDF中的XML规范:那些“潜规则”

XML本身很灵活,但URDF给它加了很多硬性规定。这些规定不是随便定的,而是为了让ROS的解析器能高效、无歧义地读取你的机器人模型。我整理了一个表格,把最关键的规范列出来:

规范项 具体要求 我曾经踩过的坑
根标签 必须且只能有一个 <robot> 标签,必须有 name 属性 有一次我忘了写 name,结果 gazebo 直接报错“robot has no name”,排查了半天
标签顺序 同一层级下,<link> 必须在 <joint> 之前定义 我习惯先写关节再写连杆,结果解析器说“找不到父连杆”,后来才改过来
属性命名 所有名称(name)必须唯一,不能有空格或特殊字符 用中文命名?想都别想,ROS 1 的解析器直接崩溃
单位制 长度用米(m),角度用弧度(rad),质量用千克(kg) 有一次我把角度写成了度数,结果机械臂转得跟抽风一样
自闭合标签 没有子内容的标签必须自闭合,如 <box /> 写 <box></box> 虽然语法没错,但有些旧版解析器会警告

特别注意: URDF 对大小写敏感!<Link> 和 <link> 是两个完全不同的标签。我见过有人把 <visual> 写成 <Visual>,结果模型加载出来是透明的。所有标签和属性名都必须小写。

另外,还有一个容易被忽略的点:注释。XML的注释是 <!-- 注释内容 -->。我建议在复杂的关节或连杆定义前加注释,方便以后自己回头看。比如:

<!-- 基座连杆,固定在桌面上 -->
<link name="base_link">
  ...
</link>

嗯,这些规范看起来琐碎,但真能帮你省下大把调试时间。我个人习惯是在写完URDF后,先用 check_urdf 命令跑一遍语法检查。这个工具会告诉你哪里标签没闭合、哪里属性值不对。强烈推荐。

最后总结一下:XML的标签和属性是URDF的“砖瓦”,树形结构是“蓝图”,而URDF规范就是“施工标准”。这三样东西搞明白了,后面写URDF就是水到渠成的事。