3. 差速底盘运动学模型:左右轮独立驱动原理

聊到移动机器人,差速底盘绝对是最经典的结构之一。我个人习惯把它叫做「两轮差速」——两个驱动轮各自独立,再加一个或两个万向轮撑着。说白了,就是靠左右轮的速度差来实现转向。

你想想看,如果左右轮速度一样,车就走直线。如果左边快右边慢,车就往右拐。反过来,左边慢右边快,就往左拐。极端情况,左右轮速度大小相等、方向相反——原地转圈。这就是差速底盘最核心的思想。

核心要点:差速底盘没有专门的转向机构,转向完全由左右轮的速度差产生。

3.1 左右轮独立驱动原理

我在项目中遇到过不少新手,上来就问:「为什么不用舵机转向?」嗯,差速底盘的优势在于结构简单、成本低、控制灵活。你只需要两个电机,两个驱动器,一个控制器,就能让机器人满屋子跑。

左右轮独立驱动,意味着每个轮子都有自己的电机和编码器。控制器给左右轮分别发速度指令,编码器反馈实际转速。这里有个坑——我曾经在调试时发现,两个同样的电机,给同样的PWM,转速居然不一样。为什么?

原因很简单:电机本身有制造公差,地面摩擦也不均匀,电池电压波动也会影响。所以,闭环控制是必须的。我建议至少用PID做速度闭环,否则运动学算得再准,实际跑起来也是歪的。

驱动方式 左轮速度 右轮速度 底盘运动
直线前进 v v 向前直行
右转 v + Δv v - Δv 向右转弯
左转 v - Δv v + Δv 向左转弯
原地旋转 绕中心旋转

3.2 线速度与角速度推导

好,现在我们来推公式。别怕,其实很简单。

先定义几个参数:

  • vL:左轮线速度
  • vR:右轮线速度
  • L:左右轮间距(轮距)
  • v:底盘中心的线速度
  • ω:底盘绕中心旋转的角速度

底盘中心的线速度,其实就是左右轮速度的平均值:

v = (vL + vR) / 2

角速度呢?想想看,左右轮速度差会导致底盘旋转。轮距L越大,同样的速度差产生的角速度越小。公式是:

ω = (vR - vL) / L

这里要注意符号约定。我习惯定义:逆时针旋转为正。所以如果右轮比左轮快,ω为正,底盘逆时针转。嗯,这个约定在ROS里也是通用的。

个人经验:轮距L的测量要精确。我曾经用卷尺量,误差5mm,结果机器人走10米就偏了30度。后来我用游标卡尺量,再跑直线就好多了。建议L的测量误差控制在1mm以内。

3.3 前向运动学公式

前向运动学,说白了就是「已知左右轮速度,求底盘怎么动」。上面两个公式合起来就是完整的前向运动学模型:

v = (vL + vR) / 2
ω = (vR - vL) / L

写成矩阵形式更清晰:

[ v ]   [ 1/2   1/2  ] [ vL ]
[ ω ] = [ -1/L  1/L  ] [ vR ]

这个2x2矩阵就是前向运动学矩阵。你给它左右轮速度,它吐出底盘的速度和角速度。

有了v和ω,我们还能进一步推算底盘的位置变化。假设dt时间内,底盘移动了:

Δx = v * cos(θ) * dt
Δy = v * sin(θ) * dt
Δθ = ω * dt

这就是航迹推演(Odometry)的基础。我在做AGV项目时,就是靠这个公式推算位置,配合编码器数据,精度能做到厘米级。

注意:航迹推演有累积误差。轮子打滑、地面不平、编码器分辨率不够,都会让误差越来越大。我曾经在瓷砖地面上跑,误差每小时累积超过1米。后来加了IMU做融合,才压住误差。

3.4 知识体系结构图

下面这张图,是我梳理的差速底盘运动学知识体系。你可以把它当作本章的「地图」:

差速底盘运动学模型 左右轮独立驱动 线速度与角速度 前向运动学公式 电机控制 编码器反馈 速度合成 矩阵表示 航迹推演 实际应用:AGV导航 / 机器人定位 / 运动控制 ⚠ 注意:所有公式都基于刚体假设和纯滚动条件

3.5 代码实现示例

最后,给一个简单的C语言实现。我在STM32上跑过类似的代码,效果不错:

// 差速底盘前向运动学计算
typedef struct {
    float v;      // 线速度 (m/s)
    float omega;  // 角速度 (rad/s)
} ChassisState;

ChassisState forwardKinematics(float vL, float vR, float wheelTrack) {
    ChassisState state;
    state.v = (vL + vR) / 2.0f;
    state.omega = (vR - vL) / wheelTrack;
    return state;
}

// 航迹推演更新
void updateOdometry(float vL, float vR, float wheelTrack, float dt) {
    ChassisState state = forwardKinematics(vL, vR, wheelTrack);
    
    // 更新位姿
    robot.x += state.v * cos(robot.theta) * dt;
    robot.y += state.v * sin(robot.theta) * dt;
    robot.theta += state.omega * dt;
    
    // 角度归一化到 [-PI, PI]
    if (robot.theta > M_PI) robot.theta -= 2 * M_PI;
    if (robot.theta < -M_PI) robot.theta += 2 * M_PI;
}

避坑指南:我曾经在角度归一化上吃过亏。如果不做归一化,theta会一直累加,浮点数精度问题会导致角度漂移。另外,dt要用定时器精确测量,不要用delay——那玩意儿不准。

好了,差速底盘运动学就聊到这儿。核心就是两个公式、一个矩阵、一段代码。你动手写一遍,跑一跑,比看十遍都管用。


公众号:蓝海资料掘金营,微信deep3321