第2章:机器人模型URDF入门:编写简单URDF模型,在Gazebo中加载并显示机器人,理解link与joint
各位同学,欢迎来到实战训练的第二课。今天咱们要亲手搭建一个机器人模型——用URDF语言。说白了,URDF就是机器人的“身份证”,告诉Gazebo你长什么样、胳膊腿儿怎么连。
我记得刚入行那会儿,第一次写URDF,把轮子和底盘的坐标搞反了,结果机器人一加载就在地上“劈叉”。嗯,这种坑咱们今天必须绕过去。
2.1 URDF到底是什么?
URDF全称是Unified Robot Description Format,统一机器人描述格式。它用XML语法描述机器人的运动学和动力学属性。你想想看,一个机器人无非就是:
- link:刚体部件,比如底盘、轮子、手臂
- joint:连接两个link的关节,定义它们之间的相对运动
我个人习惯把URDF想象成“乐高说明书”——每个零件(link)怎么摆,用什么方式连接(joint),一目了然。
核心要点:URDF只描述树状结构,不能有闭环。如果你要做四足机器人或者并联机构,得用xacro或者SDF格式。这个后面章节会讲。
2.2 第一个URDF模型:一个底盘加两个轮子
咱们从最简单的开始。一个矩形底盘,两个圆柱轮子。先看完整代码,我再逐行拆解。
<?xml version="1.0"?>
<robot name="my_robot">
<!-- 底盘 link -->
<link name="base_link">
<visual>
<geometry>
<box size="0.4 0.3 0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
<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.01"/>
</inertial>
</link>
<!-- 左轮 link -->
<link name="left_wheel">
<visual>
<geometry>
<cylinder radius="0.05" length="0.04"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
<material name="gray">
<color rgba="0.5 0.5 0.5 1"/>
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.05" length="0.04"/>
</geometry>
</collision>
<inertial>
<mass value="0.2"/>
<inertia ixx="0.0001" ixy="0" ixz="0" iyy="0.0001" iyz="0" izz="0.0001"/>
</inertial>
</link>
<!-- 右轮 link -->
<link name="right_wheel">
<!-- 内容与左轮相同,略 -->
</link>
<!-- 底盘到左轮的 joint -->
<joint name="left_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin xyz="-0.15 0.2 0" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
</joint>
<!-- 底盘到右轮的 joint -->
<joint name="right_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin xyz="-0.15 -0.2 0" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
</joint>
</robot>
2.3 逐元素拆解:link的三大件
每个link必须包含三个子元素,缺一不可。我在项目中见过有人只写visual,结果Gazebo里能看到但碰撞检测失效,机器人直接穿模。
| 元素 | 作用 | 个人经验 |
|---|---|---|
| <visual> | 定义外观,Gazebo里你看到的样子 | 颜色用RGBA,A是透明度,设为0就隐身了 |
| <collision> | 定义碰撞体,用于物理引擎计算 | 尽量用简单几何体,复杂mesh会拖慢仿真 |
| <inertial> | 定义惯性参数,质量+惯性张量 | 惯性张量算不对,机器人会像纸片一样飘 |
小技巧:collision的几何体可以比visual小一圈。比如底盘visual是0.4x0.3,collision用0.38x0.28。这样机器人过窄缝时更顺滑,不会卡边。
2.4 joint的类型与坐标变换
joint定义了父子link之间的相对位置和运动方式。我建议你记住这六种类型:
- continuous:无限旋转,轮子专用
- revolute:有限角度旋转,像手臂关节
- prismatic:直线滑动,像升降台
- fixed:刚性连接,两个link焊死
- floating:6自由度,一般不用
- planar:平面运动,少见
joint里最关键的属性是<origin>和<axis>。origin定义child link相对于parent link的位置偏移。axis定义旋转轴或滑动方向。
我曾经犯过一个低级错误:把左轮的origin写成了xyz="0.15 0.2 0",结果轮子跑到底盘前面去了。你想想看,轮子应该在底盘两侧,x方向应该和底盘中心对齐才对。
2.5 在Gazebo中加载并显示
模型写好了,怎么让它动起来?你需要一个launch文件。我个人习惯用spawn_model命令把URDF“生”到Gazebo里。
<launch>
<!-- 启动Gazebo空世界 -->
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="paused" value="false"/>
<arg name="use_sim_time" value="true"/>
</include>
<!-- 将URDF加载到参数服务器 -->
<param name="robot_description"
textfile="$(find my_robot_description)/urdf/my_robot.urdf"/>
<!-- 在Gazebo中生成机器人 -->
<node name="spawn_urdf" pkg="gazebo_ros" type="spawn_model"
args="-param robot_description -urdf -model my_robot -x 0 -y 0 -z 0.1"/>
</launch>
注意-z 0.1这个参数。底盘高度是0.1,轮子半径0.05,所以底盘中心离地应该是0.05+0.05/2=0.075?不对,这里要算清楚。我建议你直接设-z 0.05,让底盘底面刚好贴地。嗯,这个值你得根据实际模型微调。
2.6 知识体系总览
下面这张图帮你理清URDF的核心逻辑。我画了张SVG,把link、joint、Gazebo三者的关系串起来。
2.7 避坑指南:我踩过的三个坑
坑一:惯性张量瞎填
我曾经为了省事,把所有link的惯性张量都设成ixx="0.01" iyy="0.01" izz="0.01"。结果机器人一跑起来就像在冰面上打转,完全不受控。后来老老实实用urdf_sim_tutorial里的计算脚本才算对。
坑二:joint的origin坐标搞反
joint的origin是child link相对于parent link的偏移。我见过有人把parent和child写反,结果轮子跑到底盘里面去了。记住:parent是“爸爸”,child是“儿子”,儿子站在爸爸的肩膀上。
坑三:忘记加collision
Gazebo里如果没有collision,机器人会直接穿过地面。嗯,我第一次看到机器人“遁地”时还以为是重力设错了,查了半天才发现是collision没写。
2.8 动手练一练
光看不练假把式。我建议你按这个步骤来:
- 创建一个ROS包,比如
my_robot_description - 在
urdf/目录下新建my_robot.urdf,把上面的代码复制进去 - 创建launch文件,启动Gazebo并加载模型
- 用
rosrun rqt_tf_tree rqt_tf_tree查看坐标变换树 - 尝试修改轮子的位置和颜色,重新加载看看效果
如果你看到Gazebo里出现一个蓝色底盘、两个灰色轮子,而且轮子能跟着底盘动——恭喜你,URDF入门成功了!
调试小技巧:用check_urdf my_robot.urdf命令可以检查语法错误。我每次写完URDF都会跑一遍这个命令,能省下不少排查时间。
好了,这一章的内容就到这里。URDF是机器人建模的基石,后面所有章节——从传感器仿真到导航调参——都建立在这个基础上。把今天的内容吃透,后面的路就好走了。
可可精品资料库