第1章:机器人模型URDF入门

各位同学,欢迎来到《Gazebo仿真环境下的路径规划实战》的第一课。

今天我们要聊的,是机器人仿真的地基——URDF。说白了,URDF就是机器人的「身份证」加「骨架说明书」。没有它,Gazebo根本不知道你造了个啥玩意儿。我刚开始学的时候也觉得这东西不就是个XML嘛,有啥难的?结果第一次加载模型,轮子飞了,关节反了,底盘直接钻地底下去了……嗯,从那以后我再也不敢小看URDF了。

1.1 URDF语法基础

URDF全称是Unified Robot Description Format,统一机器人描述格式。它用XML语言来描述机器人的运动学和动力学属性。你想想看,一个机器人有多少个零件?每个零件长什么样?它们之间怎么连接的?URDF就是干这个的。

一个标准的URDF文件,核心就两样东西:link(连杆)和joint(关节)。

核心公式: 机器人 = 若干个link + 若干个joint

link是刚体,joint是连接关系。就这么简单。

我个人习惯把URDF文件拆成三部分来看:

  • 头部声明:XML版本、编码格式
  • link定义:每个零件的几何、惯性、碰撞属性
  • joint定义:零件之间的连接方式、位置、运动范围

来看一个最简单的URDF骨架:

<?xml version="1.0" encoding="utf-8"?>
<robot name="my_first_robot">
  <!-- 这里放link和joint -->
</robot>

注意,<robot>标签的name属性是必须的。我在项目中遇到过有人忘了写name,结果Gazebo直接报错,找了半天才发现是这个问题。

1.2 link定义:给机器人造零件

link就是机器人的一个零件。它可以是底盘、轮子、机械臂的臂杆,甚至是一个传感器支架。每个link需要定义三样东西:

属性 作用 我的经验
visual 视觉外观,Gazebo里能看到的样子 用STL或DAE文件更真实,但调试时用简单几何体更快
collision 碰撞检测用的形状 尽量简化,用box或cylinder代替复杂mesh,性能提升明显
inertial 质量、惯性矩阵 这个最容易忽略,但少了它Gazebo会报动力学错误

来看一个底盘link的例子:

<link name="base_link">
  <visual>
    <geometry>
      <box size="0.4 0.3 0.1"/>
    </geometry>
    <material name="blue">
      <color rgba="0 0 1 1"/>
    </material>
  </visual>
  <collision>
    <geometry>
      <box size="0.4 0.3 0.1"/>
    </geometry>
  </collision>
  <inertial>
    <mass value="2.0"/>
    <inertia ixx="0.01" ixy="0" ixz="0"
             iyy="0.01" iyz="0"
             izz="0.02"/>
  </inertial>
</link>

避坑指南: 我曾经把collision的尺寸设得比visual大了一圈,结果机器人明明看着没碰到东西,却被Gazebo弹飞了。后来才发现是碰撞模型比视觉模型大。记住:collision和visual的尺寸必须一致,或者collision略小。

1.3 joint定义:把零件连起来

joint定义了link之间的连接关系。URDF支持6种关节类型,但最常用的就三种:

  • fixed:固定连接,两个link之间没有相对运动
  • revolute:旋转关节,像人的肘关节,只能转不能平移
  • continuous:连续旋转关节,像车轮,可以一直转

其他三种(prismatic、planar、floating)用得少,咱们先不展开。

来看一个轮子joint的例子:

<joint name="left_wheel_joint" type="continuous">
  <parent link="base_link"/>
  <child link="left_wheel"/>
  <origin xyz="0 -0.2 0" rpy="0 0 0"/>
  <axis xyz="0 1 0"/>
</joint>

这里要注意几个点:

  • parent是父link,child是子link。关节的原点是在父link坐标系下定义的。
  • origin的xyz是位置偏移,rpy是旋转角度(roll, pitch, yaw)。
  • axis定义旋转轴。对于轮子,一般是绕Y轴旋转。

警告: 我见过最坑的错误——把parent和child搞反了。结果轮子成了底盘,底盘成了轮子。Gazebo里模型直接乱套。记住:parent是靠近机器人基座的,child是远离的。

1.4 在Gazebo中加载你的第一个机器人

好,理论说完了,咱们来点实战。我带你走一遍完整流程。

第一步:创建URDF文件

在终端里创建一个文件夹,比如my_robot,然后在里面新建一个robot.urdf文件。把上面那个底盘和轮子的代码组合起来,再加上一个简单的轮子link定义。

第二步:启动Gazebo并加载模型

用这条命令:

gazebo --verbose robot.urdf

或者如果你用的是ROS,也可以用:

roslaunch gazebo_ros empty_world.launch
# 然后在另一个终端
rosrun gazebo_ros spawn_model -file robot.urdf -urdf -model my_robot

第三步:观察结果

如果一切顺利,你应该能在Gazebo里看到一个蓝色的底盘,两边各有一个轮子。你可以用鼠标拖拽视角,看看你的机器人长啥样。

常见问题: 如果模型加载后直接掉到地面以下,说明你的link没有设置碰撞属性,或者碰撞模型太小。如果模型悬在半空,说明你的joint原点位置设置不对。

1.5 本章知识体系

为了让你更直观地理解URDF的结构,我画了一张图:

URDF文件结构 <robot> <link> 定义零件 <joint> 定义连接 visual collision inertial parent child origin 核心逻辑 link定义「有什么零件」 joint定义「零件怎么连」 Gazebo根据这些信息构建完整的机器人模型

这张图把URDF的骨架讲得很清楚了。你写URDF的时候,就照着这个结构来:先写robot根节点,然后依次写link和joint。每个link配齐visual、collision、inertial三件套,每个joint写清楚parent、child和origin。

1.6 本章小结

今天我们干了三件事:

  • 搞懂了URDF的语法基础,说白了就是XML套壳
  • 学会了link的定义,记住visual、collision、inertial三件套缺一不可
  • 掌握了joint的定义,parent和child别搞反,origin位置别算错

最后送你一句话:URDF这东西,写多了就熟了。我第一次写的时候改了七八遍才让轮子正常转起来。别怕出错,Gazebo的报错信息其实挺友好的,多看几遍就懂了。

课后练习: 试着写一个两轮差速底盘的URDF,包含一个base_link和两个轮子。加载到Gazebo里看看能不能正常显示。如果轮子飞了,检查joint的origin和axis;如果底盘钻地了,检查collision的尺寸。

可可精品资料库