3. 机器人建模与URDF
好,咱们进入第三章。说到机器人建模,URDF 就是 ROS 世界里的“乐高说明书”。你想想看,没有模型,SLAM 和导航都不知道你的机器人长什么样、轮子在哪、激光雷达装多高。我个人习惯先把 URDF 基础啃透,后面调导航参数才不慌。
3.1 URDF 基础语法
URDF 全称 Unified Robot Description Format,说白了就是 XML 格式的机器人描述文件。根标签永远是 <robot>,里面主要装两种东西:link(连杆)和 joint(关节)。
我记得第一次写 URDF 时,把 link 和 joint 搞反了,结果 Rviz2 里机器人直接散架。后来养成了习惯:先画树状图,再写代码。
<robot name="my_robot">
<link name="base_link">
<visual>
<geometry>
<box size="0.4 0.3 0.1"/>
</geometry>
</visual>
</link>
<joint name="base_to_wheel" type="fixed">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin xyz="0.2 0 -0.05"/>
</joint>
</robot>
每个 link 里可以定义 visual(可视化外观)、collision(碰撞模型)和 inertial(惯性参数)。导航中碰撞模型尤其重要——我曾经因为偷懒没写 collision,导致导航规划时机器人“穿模”穿过障碍物。
3.2 连杆与关节定义
关节类型有六种,但咱们做轮式机器人最常用的是 fixed(固定关节)和 continuous(连续旋转关节,比如轮子)。joint 里必须指定 parent 和 child,这就构成了机器人的运动学树。
| 关节类型 | 说明 | 典型用途 |
|---|---|---|
| fixed | 刚性连接,无自由度 | 底盘与激光雷达支架 |
| revolute | 绕单轴旋转,有角度限位 | 关节臂、舵机 |
| continuous | 绕单轴无限旋转 | 车轮、全向轮 |
| prismatic | 沿单轴平移 | 升降机构、滑轨 |
| floating | 6自由度浮动 | 无人机、多机器人 |
| planar | 平面内3自由度 | 全向底盘(较少用) |
<axis xyz="0 0 1"/> 设置正确。我遇到过好几次轮子转轴方向反了,机器人原地打转——检查 axis 是最快的排障方法。
3.3 xacro 优化:告别重复劳动
URDF 写多了你会发现,左右轮子除了名字和坐标,其他几乎一样。这时候 xacro 就派上用场了。xacro 是 URDF 的宏预处理工具,支持数学运算、条件判断、宏定义。
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="robot">
<xacro:macro name="wheel" params="name x y">
<link name="${name}">
<visual>
<geometry><cylinder radius="0.05" length="0.03"/></geometry>
</visual>
</link>
<joint name="${name}_joint" type="continuous">
<parent link="base_link"/>
<child link="${name}"/>
<origin xyz="${x} ${y} -0.02"/>
<axis xyz="0 1 0"/>
</joint>
</xacro:macro>
<xacro:wheel name="left_wheel" x="0.15" y="0.2"/>
<xacro:wheel name="right_wheel" x="0.15" y="-0.2"/>
</robot>
你看,用宏定义之后,加两个轮子只需要两行。我个人习惯把传感器、轮子、支架都写成独立的 xacro 文件,然后用 <xacro:include> 组合。这样维护起来特别清爽。
.xacro,但 launch 文件中引用时要用 urdf 类型。我曾经在这里卡了半小时——launch 里写错后缀,Rviz2 一直报错找不到模型。
3.4 在 Rviz2 中可视化模型
模型写好了,怎么看到它?用 robot_state_publisher 节点把 URDF 发布到 TF 树,然后在 Rviz2 中添加 RobotModel 显示。我常用的 launch 文件长这样:
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='robot_state_publisher',
executable='robot_state_publisher',
arguments=['my_robot.urdf']
),
Node(
package='joint_state_publisher_gui',
executable='joint_state_publisher_gui'
),
Node(
package='rviz2',
executable='rviz2',
arguments=['-d', 'my_config.rviz']
)
])
启动后,你应该能在 Rviz2 中看到机器人模型。如果模型显示为红色或报错“No transform from …”,八成是 TF 树没连上。检查 joint 的 parent 和 child 名称是否一致——我犯过把 base_link 拼成 base_linkk 的低级错误。
- 所有 link 和 joint 名称不要用中文、空格、特殊符号。
- inertial 参数不能省略,否则 gazebo 仿真会崩溃。对于不动的 link,给一个极小的惯性值就行。
- 使用
check_urdf工具验证文件:check_urdf my_robot.urdf,它会输出树状结构,一眼看出断链。
嗯,URDF 建模其实不难,但细节特别多。我每次搭建新机器人,都会先花半小时把模型调通,再开始搞 SLAM 和导航。模型准了,后面所有环节都顺。