车辆运动学模型:从几何到离散化的完整链路
各位同学,今天我们聊一个非常基础但又极其重要的内容——车辆运动学模型。说实话,很多做规划控制的同行,一开始都容易忽略这部分,觉得不就是几个几何公式嘛。但我可以负责任地告诉你,模型选不对,后面所有算法都是空中楼阁。
我个人习惯把运动学模型比作「车辆的骨架」。你想想看,规划算法要生成轨迹,控制算法要跟踪轨迹,如果骨架都歪了,那肌肉再发达也没用。今天我们就从最经典的自行车模型讲起,一路聊到阿克曼转向、微分方程,最后落地到离散化方法。
一、自行车模型:为什么它能代表四轮车?
先问大家一个问题:一辆四轮汽车,转弯时四个轮子的转角都不一样,怎么建模?
嗯,这里有个核心假设——低速行驶时,车辆的侧偏角可以忽略。说白了,就是轮胎不打滑,滚动方向就是轮胎指向的方向。在这个前提下,我们可以把左右两个前轮合并成一个虚拟前轮,左右后轮合并成一个虚拟后轮。这就是自行车模型的由来。
核心假设条件:
- 车辆低速行驶(通常 < 5 m/s)
- 忽略轮胎侧偏特性
- 前后轴距固定不变
- 车辆为刚体,不考虑悬架变形
我在项目中遇到过一件事:有一次做自动泊车,直接用了自行车模型,结果在非常窄的车位里怎么都规划不出来。后来发现,是因为泊车速度虽然低,但方向盘打得特别快,轮胎其实已经出现了微小侧偏。所以大家记住:自行车模型适用于低速、小转角场景,大转角时要小心。
二、阿克曼转向模型:真实车辆的转向几何
自行车模型虽然简洁,但它忽略了一个关键问题——真实车辆转弯时,内外侧车轮的转角是不一样的。这就是阿克曼转向几何要解决的问题。
为什么会这样?因为四个轮子要绕同一个瞬时转向中心做圆周运动。如果内外侧车轮转角相同,内侧轮就会产生滑移,轮胎磨损加剧,控制精度也会下降。
| 参数 | 含义 | 典型值 |
|---|---|---|
| L | 轴距 | 2.5 - 3.0 m |
| δ_in | 内侧前轮转角 | 比外侧大 2-5° |
| δ_out | 外侧前轮转角 | 比内侧小 2-5° |
| R | 转弯半径 | 由 δ 决定 |
阿克曼转向的数学关系其实不复杂:
cot(δ_out) - cot(δ_in) = 轮距 / 轴距
我曾经在实车调试时踩过一个坑:用自行车模型算出来的转弯半径,和实际车辆转弯半径差了将近 0.3 米。后来一查,原来是阿克曼率没调对。所以做高精度控制时,阿克曼模型是绕不开的。
三、运动学微分方程:状态怎么随时间变化?
有了几何模型,接下来要回答一个问题:车辆的状态(位置、朝向)随时间怎么变?
这就引出了运动学微分方程。以自行车模型为例,状态量通常取:
- x, y:后轴中心位置
- θ:车辆航向角
- δ:前轮转角
- v:纵向速度
微分方程长这样:
dx/dt = v * cos(θ)
dy/dt = v * sin(θ)
dθ/dt = v * tan(δ) / L
dδ/dt = ω_δ // 转向角速度,通常作为控制输入
dv/dt = a // 加速度,通常作为控制输入
嗯,这里要注意:dθ/dt 的公式里,分母是轴距 L。轴距越长,同样的转角产生的角速度越小,车就越「稳」。我在做高速车道保持时,就发现轴距长的车,控制起来更平顺,但响应也慢半拍。
个人经验: 如果做 MPC 控制,建议把 δ 和 v 也作为状态量,而不是直接作为控制量。因为实际执行器有响应延迟,直接控制 δ 和 v 会导致模型失配。我曾经因为这个原因,MPC 在实车上抖得像筛糠一样。
四、模型离散化方法:从连续到离散
计算机只能处理离散数据,所以必须把连续微分方程变成离散差分方程。常用的方法有三种:
4.1 前向欧拉法(最简单,但精度低)
x(k+1) = x(k) + dt * v(k) * cos(θ(k))
y(k+1) = y(k) + dt * v(k) * sin(θ(k))
θ(k+1) = θ(k) + dt * v(k) * tan(δ(k)) / L
这个方法我一般只在仿真初期用,或者采样时间特别短(< 10ms)的时候。为什么?因为它是显式方法,数值稳定性差。dt 一大,状态就飞了。
4.2 后向欧拉法(隐式,稳定但麻烦)
x(k+1) = x(k) + dt * v(k+1) * cos(θ(k+1))
y(k+1) = y(k) + dt * v(k+1) * sin(θ(k+1))
注意看,等式右边出现了 k+1 时刻的状态。这意味着你需要解方程组。我个人不太喜欢用这个方法,因为实时性要求高的场景下,解非线性方程组太耗时。
4.3 龙格-库塔法(精度与效率的平衡)
四阶龙格-库塔(RK4)是我在实车上用得最多的方法。它通过四个中间步的加权平均,把精度提升到 O(dt⁴)。
k1 = f(x(k), u(k))
k2 = f(x(k) + 0.5*dt*k1, u(k))
k3 = f(x(k) + 0.5*dt*k2, u(k))
k4 = f(x(k) + dt*k3, u(k))
x(k+1) = x(k) + (dt/6)*(k1 + 2*k2 + 2*k3 + k4)
避坑指南: 我曾经在 RK4 上吃过一次亏——控制输入 u(k) 在四个中间步里都用了同一个值。但实际执行器在 dt 时间内是变化的。后来我改成在每个中间步里线性插值控制输入,精度提升了一个数量级。
五、实际工程中的模型选择建议
说了这么多,到底该用哪个模型?我给大家一个参考:
| 应用场景 | 推荐模型 | 离散化方法 |
|---|---|---|
| 自动泊车(低速) | 自行车模型 | 前向欧拉(dt ≤ 20ms) |
| 城市道路巡航 | 自行车模型 + 阿克曼修正 | RK4 |
| 高速车道保持 | 自行车模型 + 侧偏角补偿 | RK4 或后向欧拉 |
| 精确轨迹跟踪 | 阿克曼模型 | RK4 带输入插值 |
最后说一句:模型不是越复杂越好。你想想看,模型越复杂,参数就越多,标定就越困难。我见过有人用七自由度模型做规划,结果光参数标定就花了三个月,最后效果还不如自行车模型加个补偿项。所以,够用就好,留有余量。
好了,这一章的内容就到这里。下一章我们会聊到「车辆动力学模型」,那才是真正考验功力的地方。到时候我会分享一个我在高速爆胎场景下的控制经验,很有意思。