第二讲:认识URDF——你的第一个机器人模型
好,咱们进入正题。上一讲我们把Gazebo环境搭起来了,但里面空荡荡的,对吧?这一讲,我们来给这个世界加点料——创建第一个机器人模型。而要做到这一点,必须先搞懂URDF。
什么是URDF?
URDF,全称是Unified Robot Description Format,统一机器人描述格式。说白了,它就是一套用来描述机器人长什么样的“语言”。
我个人习惯把URDF理解为机器人的“身份证”。它告诉系统:这个机器人有几个轮子、几个关节、每个零件多长多重、颜色是什么。Gazebo和ROS就是靠这个文件来认识你的机器人的。
我记得刚接触URDF时,觉得它不就是个XML嘛,有啥难的?结果第一次写出来的机器人,轮子长在头顶上……嗯,后来我学乖了,老老实实把每个坐标轴都画出来再动手。
核心要点:URDF是一个基于XML的文本文件,用来描述机器人的运动学、动力学和可视化信息。
URDF文件结构
URDF的结构其实很清晰,就两大核心元素:link(连杆)和joint(关节)。
- link:机器人的刚体部件。比如底盘、轮子、摄像头支架。
- joint:连接两个link的关节。定义它们之间的相对位置和运动方式。
你想想看,一个机器人不管多复杂,本质上就是一堆连杆通过关节连起来。就像人的手臂,上臂和前臂通过肘关节连接,对吧?
link的结构
每个link通常包含三部分信息:
| 部分 | 作用 | 我踩过的坑 |
|---|---|---|
| visual | 可视化外观,决定你“看到”的机器人长什么样 | 颜色值用RGB,但别忘了加alpha通道 |
| collision | 碰撞检测,决定机器人“碰到”东西时的边界 | 我曾经把collision设得比visual大一圈,结果机器人还没碰到障碍物就停下了 |
| inertial | 惯性参数,决定机器人“动起来”的物理特性 | 质量写错会导致机器人像纸片一样飘 |
joint的类型
关节有几种常见类型,我列个表给你看:
| 类型 | 说明 | 实际例子 |
|---|---|---|
| fixed | 固定连接,两个link之间没有相对运动 | 摄像头固定在支架上 |
| revolute | 旋转关节,绕一个轴转动,有角度限制 | 机械臂的肘关节 |
| continuous | 连续旋转关节,没有角度限制 | 轮子 |
| prismatic | 滑动关节,沿一个轴直线运动 | 升降台 |
避坑指南:我曾经把轮子的joint类型写成revolute,结果轮子只能转180度就卡住了。机器人原地打转,像个陀螺。后来改成continuous才正常。记住:轮子用continuous!
创建第一个机器人模型
好,理论说完了,咱们动手。下面这个例子,是一个最简单的两轮差速机器人。它只有一个底盘和两个轮子。
先看整体结构图:
结构很简单,对吧?底盘是父link,两个轮子通过continuous关节挂在底盘两侧。
下面就是完整的URDF代码:
<?xml version="1.0"?>
<robot name="my_first_robot">
<!-- 底盘 -->
<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.2 0.5 0.8 1.0"/>
</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 name="left_wheel">
<visual>
<geometry>
<cylinder radius="0.05" length="0.04"/>
</geometry>
<origin xyz="0 0 0" rpy="1.5708 0 0"/>
<material name="red">
<color rgba="0.8 0.2 0.2 1.0"/>
</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 name="right_wheel">
<visual>
<geometry>
<cylinder radius="0.05" length="0.04"/>
</geometry>
<origin xyz="0 0 0" rpy="1.5708 0 0"/>
<material name="red">
<color rgba="0.8 0.2 0.2 1.0"/>
</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>
<!-- 左轮关节 -->
<joint name="left_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin xyz="-0.2 0.15 -0.05" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
</joint>
<!-- 右轮关节 -->
<joint name="right_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin xyz="-0.2 -0.15 -0.05" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
</joint>
</robot>
注意:origin中的xyz坐标是相对于父link的。我刚开始写的时候,把轮子的坐标写成了相对于世界坐标系,结果轮子飞到天上了。记住:子link的坐标是相对于父link的!
几个关键点
写URDF时,有几个地方特别容易出错,我单独拎出来说:
- 坐标轴方向:Gazebo里,x轴朝前,y轴朝左,z轴朝上。轮子的旋转轴是y轴,所以axis写的是"0 1 0"。
- 单位:长度用米,质量用千克。别混用,否则物理仿真会崩。
- inertia值:这个值不能全为0,否则Gazebo会报错。简单估算就行,不用太精确。
- collision和visual:可以不一样。比如visual用复杂模型,collision用简化方块,能提高仿真效率。
我的经验:刚开始学URDF时,建议先用简单的几何体(box、cylinder、sphere)搭模型。等熟悉了,再换复杂的mesh文件。我见过有人一上来就用STL文件,结果坐标对不上,折腾了两天。
好了,这一讲的内容就是这些。URDF是机器人建模的基石,别看它简单,但后面所有复杂机器人都基于这个结构。把上面这个例子跑通,你就迈出了第一步。
可可精品资料库