4、构建差速底盘:设计并搭建一个两轮差速机器人底盘模型
好,咱们进入正题。差速底盘,说白了就是靠两个轮子转速差来控制方向和速度。你想想看,坦克怎么转弯?一边履带停转,另一边转,车身就拐过去了。机器人差速底盘也是这个道理。
我个人习惯把底盘设计分成三块来考虑:机械结构、运动学模型、URDF建模。咱们一个一个来拆解。
4.1 差速底盘的运动学原理
先搞明白数学关系。差速底盘有两个驱动轮,通常还有一个万向轮做支撑。两个轮子独立驱动,通过转速差实现转向。
核心公式其实就两个:
v = (v_right + v_left) / 2
ω = (v_right - v_left) / d
其中:
- v — 机器人线速度(m/s)
- ω — 机器人角速度(rad/s)
- v_left、v_right — 左右轮线速度
- d — 左右轮间距(轮距)
嗯,这里要注意:轮距d是影响转弯半径的关键参数。我在项目中遇到过,有人把轮距量错了5毫米,结果机器人走直线都画弧线,排查了半天。
关键结论:
- v_left = v_right → 直线前进/后退
- v_left = -v_right → 原地旋转(零半径转弯)
- v_left ≠ v_right → 弧线运动
4.2 设计底盘参数
咱们要搭一个教学用的差速底盘,参数我建议这样定:
| 参数 | 数值 | 说明 |
|---|---|---|
| 轮距 d | 0.4 m | 左右轮中心距离 |
| 车轮半径 r | 0.1 m | 驱动轮尺寸 |
| 车身长 | 0.5 m | 底盘长度 |
| 车身宽 | 0.3 m | 底盘宽度 |
| 离地间隙 | 0.05 m | 底盘最低点距地面 |
为什么选这些值?说白了,0.4米的轮距在室内跑比较灵活,转弯半径小。0.1米的轮子大小适中,过门槛、过线缆都还行。
个人经验:轮距和轮径的比例最好在3:1到5:1之间。比例太小,机器人容易侧翻;比例太大,转弯笨重。我曾经做过一个比例2:1的底盘,一转弯就翘轮子,后来老老实实改回来了。
4.3 URDF模型搭建
好,理论讲完了,咱们动手写URDF。Gazebo里用URDF描述机器人,说白了就是一堆link和joint拼起来。
先看整体结构图:
结构很清晰:一个车身,两个驱动轮,一个万向轮。驱动轮用连续旋转关节,万向轮用固定关节。
4.4 编写URDF代码
来,直接上代码。我习惯把每个link和joint分开写,清晰好维护。
<?xml version="1.0"?>
<robot name="diff_drive_robot">
<!-- 车身 -->
<link name="base_link">
<visual>
<geometry>
<box size="0.5 0.3 0.1"/>
</geometry>
<material name="blue">
<color rgba="0.2 0.5 0.8 1.0"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.5 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>
<!-- 左驱动轮 -->
<link name="left_wheel">
<visual>
<geometry>
<cylinder radius="0.1" length="0.05"/>
</geometry>
<material name="black">
<color rgba="0.2 0.2 0.2 1.0"/>
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.1" length="0.05"/>
</geometry>
</collision>
<inertial>
<mass value="0.5"/>
<inertia ixx="0.001" ixy="0" ixz="0"
iyy="0.001" iyz="0"
izz="0.001"/>
</inertial>
</link>
<!-- 左轮关节 -->
<joint name="left_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin xyz="-0.15 0.2 0" rpy="0 1.5708 0"/>
<axis xyz="0 0 1"/>
</joint>
<!-- 右驱动轮 -->
<link name="right_wheel">
<visual>
<geometry>
<cylinder radius="0.1" length="0.05"/>
</geometry>
<material name="black">
<color rgba="0.2 0.2 0.2 1.0"/>
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.1" length="0.05"/>
</geometry>
</collision>
<inertial>
<mass value="0.5"/>
<inertia ixx="0.001" ixy="0" ixz="0"
iyy="0.001" iyz="0"
izz="0.001"/>
</inertial>
</link>
<!-- 右轮关节 -->
<joint name="right_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin xyz="-0.15 -0.2 0" rpy="0 1.5708 0"/>
<axis xyz="0 0 1"/>
</joint>
<!-- 万向轮 -->
<link name="caster_wheel">
<visual>
<geometry>
<sphere radius="0.03"/>
</geometry>
<material name="gray">
<color rgba="0.5 0.5 0.5 1.0"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.03"/>
</geometry>
</collision>
<inertial>
<mass value="0.1"/>
<inertia ixx="0.0001" ixy="0" ixz="0"
iyy="0.0001" iyz="0"
izz="0.0001"/>
</inertial>
</link>
<!-- 万向轮关节 -->
<joint name="caster_wheel_joint" type="fixed">
<parent link="base_link"/>
<child link="caster_wheel"/>
<origin xyz="0.2 0 -0.05" rpy="0 0 0"/>
</joint>
</robot>
注意:origin中的xyz坐标是相对于父link的。左轮在y正方向,右轮在y负方向,这样才对称。我曾经见过有人把两个轮子放在同一侧,结果机器人原地打转——嗯,这种低级错误我也犯过。
4.5 几个关键细节
写URDF时,有几个坑我得提醒你:
- 轮子朝向:圆柱体默认轴是z轴,但轮子要绕y轴转。所以rpy里要旋转90度,把圆柱横过来。
- 碰撞模型:一定要加collision,不然Gazebo里没有物理碰撞,轮子会陷进地面。
- 惯性参数:别偷懒不写inertial。Gazebo没有惯性数据会报错,或者仿真跑起来怪怪的。
- 万向轮位置:放在车身前方或后方,离地间隙要略小于驱动轮,保证三点支撑稳定。
避坑指南:我曾经在项目里忘了给万向轮加碰撞模型,结果机器人一跑起来就翘头,像要翻跟头似的。排查了半天才发现是万向轮直接穿透了地面,没有支撑力。加上collision后,一切正常。
4.6 验证模型
写完后怎么验证?我一般三步走:
- 用
check_urdf命令检查语法:check_urdf my_robot.urdf - 用
urdf_to_graphiz生成结构图,看看关节关系对不对 - 直接丢进Gazebo,看轮子是否着地,转动是否正常
嗯,到这里,一个完整的差速底盘模型就搭好了。你想想看,其实核心就三个部分:运动学公式、参数设计、URDF描述。搞懂了这些,后面加传感器、加控制器就水到渠成了。
可可精品资料库