2、基础运动学模型:两轮差速模型、阿克曼模型、单车模型,运动学约束与状态空间表示

做轨迹跟踪,第一件事不是调参数,而是搞清楚你的车到底是个什么玩意儿在动。

我见过太多人上来就调 PID,结果车在原地打转——为什么?因为模型选错了。你想想看,一个差速底盘和一个汽车底盘,它们的运动方式完全不同。今天我们就来把这三个最常用的运动学模型掰开揉碎讲清楚。

2.1 两轮差速模型

这是移动机器人最常用的模型。两个驱动轮独立控制,一个万向轮跟着跑。说白了,靠左右轮的速度差来实现转弯。

核心思想:左轮速度 vL,右轮速度 vR,轮距 L。机器人的线速度 v 和角速度 ω 由下式决定:

v = (v_R + v_L) / 2
ω = (v_R - v_L) / L

状态空间表示很简单。取机器人位姿为 [x, y, θ]T,控制输入为 [v, ω]T:

ẋ = v * cos(θ)
ẏ = v * sin(θ)
θ̇ = ω

嗯,这里要注意:这个模型有一个非完整约束——机器人不能横向移动。也就是说,它的速度方向永远指向车头朝向。

我的经验:做差速模型调参时,我习惯先把轮距 L 测量精确。差 1 厘米,转弯半径就偏 5%。曾经有个项目,机器人走直线总是偏右,查了三天发现是轮距标定错了。

2.2 阿克曼模型

汽车底盘用的就是这个。前轮转向,后轮驱动。左右前轮的转向角不一样——内轮转角比外轮大,这样才能保证所有轮子绕同一个圆心转。

阿克曼转向几何的核心条件:

cot(δ_L) - cot(δ_R) = L_w / L_b

其中 δL、δR 是左右前轮转角,Lw 是轮距,Lb 是轴距。

实际工程中,我们通常用单车模型来近似阿克曼模型。为什么?因为四个轮子的运动学太复杂了,控制算法里用不着那么细。

参数 符号 典型值 说明
轴距 Lb 2.5 m 前后轴距离
轮距 Lw 1.5 m 左右轮距离
前轮转角 δ ±30° 单车模型等效转角
最大曲率 κmax tan(δmax)/Lb 转弯能力上限

避坑指南:我曾经在实车上直接用阿克曼模型做轨迹跟踪,结果发现前轮转角超过 25° 时,轮胎侧偏严重,模型完全失效。后来加了侧偏角补偿才解决。记住:阿克曼模型只在低速(< 5 m/s)和小转角(< 20°)下才准确。

2.3 单车模型(Bicycle Model)

这是我最常用的模型。把左右轮合并成一个虚拟轮,放在前后轴中间。简单、实用、够用。

状态空间表示:

ẋ = v * cos(θ + β)
ẏ = v * sin(θ + β)
θ̇ = (v / L_b) * cos(β) * tan(δ)
β = arctan( (L_r / L_b) * tan(δ) )

其中 β 是质心侧偏角,Lr 是后轴到质心的距离。如果质心在后轴中心,β = 0,模型退化为:

ẋ = v * cos(θ)
ẏ = v * sin(θ)
θ̇ = (v / L_b) * tan(δ)

你看,这个形式和差速模型很像,区别在于角速度控制变成了前轮转角控制。

三种模型对比:

  • 差速模型:直接控制 v 和 ω,适合室内机器人、AGV
  • 阿克曼模型:控制 v 和 δL、δR,适合真实车辆
  • 单车模型:控制 v 和 δ,是阿克曼的简化版,适合算法开发

2.4 运动学约束

搞清楚了模型,还得知道它的限制。我总结了三类约束:

  1. 非完整约束:不能横向移动。数学上表示为 ẋ·sin(θ) - ẏ·cos(θ) = 0
  2. 输入约束:速度有上下限,转角有机械限位
  3. 曲率约束:转弯半径不能小于最小转弯半径 Rmin = Lb / tan(δmax)

为什么这些约束重要?因为轨迹跟踪算法生成的参考轨迹,必须满足这些约束。否则控制器会饱和,跟踪性能直接崩掉。

我的习惯:做轨迹规划时,我会把约束直接写进优化目标里。比如在 MPC 中,把 vmin ≤ v ≤ vmax 和 |δ| ≤ δmax 作为硬约束。这样生成的轨迹天然可执行。

2.5 知识体系总览

下面这张图把三种模型的关系和适用场景串起来了。我建议你保存下来,以后选模型时对照着看。

运动学模型知识体系 运动学模型知识体系 运动学模型 两轮差速模型 阿克曼模型 单车模型 输入: v, ω 输入: v, δL, δR 输入: v, δ 约束 非完整约束 约束 阿克曼几何 + 机械限位 约束 曲率 + 输入限幅 室内机器人、AGV 真实车辆、低速场景 算法开发、仿真验证 选择模型时,先问自己:控制频率多高?计算资源够不够?实车还是仿真?

2.6 状态空间表示的统一形式

三种模型其实可以写成统一的形式:

ż = f(z, u)

其中 z = [x, y, θ]T 是状态,u 是控制输入。差速模型的 u = [v, ω]T,单车模型的 u = [v, δ]T。

做轨迹跟踪时,我们通常把模型线性化,得到:

ż = A·z + B·u

然后在这个线性化模型上设计控制器。具体怎么线性化,我们后面章节会详细讲。

一个小技巧:我习惯在代码里把模型封装成一个类,输入是状态和控制量,输出是状态导数。这样换模型时只需要改这个类,控制器代码完全不用动。