4. URDF模型构建:从零搭建你的机械臂“骨架”
URDF,全称是Unified Robot Description Format。说白了,它就是机器人的“身份证”。ROS2靠它知道你的机械臂长什么样、关节在哪、能怎么动。
我记得刚入行那会儿,总觉得URDF就是个XML文件,随便写写就行。结果第一次在RViz里加载模型,整个机械臂拧成一团麻花……嗯,从那以后我再也不敢小看这个文件了。
核心要点:URDF定义了机器人的运动学树——从基座到末端执行器,每个连杆(link)和关节(joint)都必须严格按父子关系排列。
4.1 连杆与关节:机械臂的“骨头”和“关节”
一个机械臂模型,本质上就是一堆连杆通过关节串起来。每个连杆有几何形状、尺寸、颜色;每个关节决定相邻两个连杆的相对运动方式。
先看一个最简单的连杆定义:
<link name="base_link">
<visual>
<geometry>
<box size="0.2 0.2 0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</visual>
</link>
这里我习惯把visual标签放在最前面,因为它最直观——你一眼就能看到这个连杆长什么样。但实际项目中,碰撞参数和惯性参数才是真正决定机器人能不能跑起来的关键。
关节的定义稍微复杂一点:
<joint name="joint1" type="revolute">
<parent link="base_link"/>
<child link="link1"/>
<origin xyz="0 0 0.1" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-3.14" upper="3.14" effort="10" velocity="1"/>
</joint>
注意origin的位置——它是关节相对于父连杆的变换。我曾经在这里栽过跟头:把xyz写成了相对于子连杆,结果模型在RViz里直接飞出去了。
我的习惯:先画一张连杆-关节树形图,标清楚每个关节的原点和旋转轴,再动手写URDF。磨刀不误砍柴工。
4.2 使用xacro:告别重复劳动
写几个连杆还行,但六轴机械臂写下来,你会发现大量重复代码——每个连杆的碰撞参数、惯性矩阵几乎一样,只是尺寸不同。
xacro(XML Macros)就是来解决这个问题的。它让你可以定义变量、写宏、做数学运算。
举个例子,定义一个通用的连杆宏:
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="my_arm">
<xacro:macro name="link_with_inertia" params="name length radius color">
<link name="${name}">
<visual>
<geometry>
<cylinder length="${length}" radius="${radius}"/>
</geometry>
<material name="${color}">
<color rgba="0 0 1 1"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="${length}" radius="${radius}"/>
</geometry>
</collision>
<inertial>
<mass value="1.0"/>
<inertia ixx="0.1" ixy="0" ixz="0"
iyy="0.1" iyz="0"
izz="0.1"/>
</inertial>
</link>
</xacro:macro>
<xacro:link_with_inertia name="link1" length="0.3" radius="0.05" color="red"/>
<xacro:link_with_inertia name="link2" length="0.25" radius="0.04" color="green"/>
</robot>
你看,原来要写几十行的代码,现在几行就搞定了。我个人建议把所有连杆的惯性参数也做成宏参数,因为不同连杆的质量分布差异很大,统一写死容易出问题。
避坑指南:xacro文件里不要用中文注释!ROS2的XML解析器对中文支持不好,我曾经因为一个中文分号,排查了整整一下午。
4.3 在RViz中可视化:眼见为实
模型写好了,怎么验证?RViz就是你的“照妖镜”。
启动命令很简单:
# 先安装必要工具
sudo apt install ros-humble-joint-state-publisher ros-humble-robot-state-publisher
# 启动RViz并加载模型
ros2 launch urdf_tutorial display.launch.py model:=my_arm.urdf
如果用的是xacro文件,需要先转换成URDF:
ros2 run xacro xacro my_arm.xacro > my_arm.urdf
在RViz里,你可以做三件事:
- 检查模型结构——每个连杆是否在正确位置,关节轴方向对不对
- 手动拖动关节——通过Joint State Publisher面板,拖动滑块看运动范围
- 查看TF树——确认父子关系是否和设计一致
我记得有一次,模型在RViz里显示正常,但一跑运动规划就报错。后来发现是碰撞模型比可视化模型大了一圈,导致自碰撞检测一直失败。所以,可视化没问题不代表模型就对了。
调试技巧:在RViz里把RobotModel的Alpha值调到0.5,半透明显示,这样能同时看到内部结构和碰撞体。
4.4 添加碰撞与惯性参数:让模型“真实”起来
可视化参数只是“面子”,碰撞和惯性参数才是“里子”。没有它们,运动规划、动力学仿真全都跑不起来。
碰撞参数决定了机器人在运动规划中如何检测自碰撞和环境碰撞。我一般直接用可视化几何体的简化版本——比如把复杂的网格模型简化成圆柱或长方体,计算量小很多。
<collision>
<geometry>
<cylinder radius="0.05" length="0.3"/>
</geometry>
<origin xyz="0 0 0.15" rpy="0 0 0"/>
</collision>
惯性参数是动力学仿真的基础。每个连杆都需要指定质量和惯性张量矩阵。这里有个常见的误区:
| 参数 | 含义 | 常见错误 |
|---|---|---|
| mass | 连杆质量(kg) | 忘记加单位,默认是kg但写成了g |
| ixx/iyy/izz | 绕x/y/z轴的转动惯量 | 数值数量级错误,差几个量级 |
| ixy/ixz/iyz | 惯性积 | 非对称连杆直接填0,导致动力学失真 |
对于规则形状(圆柱、长方体),惯性张量可以用公式计算。我习惯写一个Python脚本自动算,省得手算出错。
重要提醒:惯性矩阵必须是正定的(所有特征值大于0)。如果填错了,Gazebo仿真会直接崩溃,连错误日志都不给。
4.5 本章知识体系总览
下面这张图总结了URDF模型构建的核心流程和各个模块的关系:
从这张图可以看得很清楚:URDF模型不是一蹴而就的。你需要先搭好连杆和关节的骨架,再用xacro优化代码结构,最后通过RViz反复验证和调整。每一步都踩实了,后面的运动控制才能跑得稳。
我的经验:一个高质量的URDF模型,至少需要迭代3-5轮。第一轮搭结构,第二轮调碰撞,第三轮校准惯性参数。别指望一次搞定。