第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的「思维导图」:
2.5 本章小结
好,我们来捋一捋:
- XML结构:树形层级,标签成对,name唯一
- <robot>根标签:整个文件的容器,name属性必填
- <link>三件套:惯性(物理)、视觉(显示)、碰撞(检测)
我个人觉得,URDF最难的不是语法,而是「惯性张量」这个概念。很多初学者随便填几个数,结果仿真一跑就飞了。我的建议是:先用标准几何体练手,把圆柱、长方体的惯性张量算明白,再碰复杂形状。
下一章我们会讲<joint>标签,那是让机器人动起来的关键。关节类型、运动范围、传动比——这些东西才是机械臂的灵魂。不过那是后话了,先把link吃透再说。
课后练习:写一个包含两个link的URDF文件。第一个link是底座(长方体),第二个link是手臂(圆柱体)。给它们分别配上惯性、视觉、碰撞参数。然后扔到check_urdf命令里检查语法。试试看,10分钟搞定。
可可精品资料库