4. 动力学约束

好,咱们接着聊。前面几章我们讲了路径规划和速度轮廓的生成,但说实话,那些都还停留在「理想世界」里。真正把算法往车上放的时候,你会发现——嗯,现实很骨感。

为什么?因为车不是数学点,它有物理极限。你规划得再漂亮,执行器跟不上,那就是纸上谈兵。这一章,我们就来聊聊这些绕不开的动力学约束。

4.1 加速度限制:别让乘客晕车

加速度限制,说白了就是车能「推」多快。我习惯把它分成两类:

  • 纵向加速度:油门踩到底能加多快,刹车踩死能减多快。
  • 横向加速度:转弯时,车能承受多大的侧向力。

你想想看,如果规划出来的速度曲线要求车辆在0.1秒内从60km/h刹停,那刹车盘都得冒烟。更别提乘客的感受了——我坐过那种急加速急减速的测试车,一趟下来胃里翻江倒海。

核心公式:

a_max = min(a_engine_max, a_brake_max, a_comfort_max)

其中 a_comfort_max 通常取 2~3 m/s²,这是人体比较舒服的区间。

我在项目中遇到过一个问题:某次做泊车路径规划,算法算出来的路径很完美,但一执行就发现车在终点前反复「点头」。查了半天,原来是加速度限制设得太宽松,导致速度曲线在终点附近剧烈震荡。后来我把加速度限制从 5 m/s² 降到 2.5 m/s²,问题立刻解决。

小技巧:做速度规划时,建议把加速度限制作为硬约束写在优化目标里,而不是事后裁剪。否则容易出现「规划一时爽,执行火葬场」的情况。

4.2 Jerk限制:舒适度的隐形杀手

Jerk,就是加速度的变化率。很多人只关注加速度,忽略了jerk。但我告诉你,jerk才是决定乘坐体验的关键。

举个例子:同样是加速到 3 m/s²,一个方案是 0.1 秒内达到,另一个是 0.5 秒内平滑过渡。前者jerk高达 30 m/s³,后者只有 6 m/s³。你坐上去,前者感觉像被人踹了一脚,后者就像被温柔地推了一把。

为什么会这样?因为人体对「力的突变」特别敏感。加速度本身不可怕,可怕的是加速度突然变化。

我曾经踩过的坑:有一次做自动驾驶的换道规划,我用了五阶多项式来生成轨迹,理论上jerk是连续的。但实际测试时,乘客还是抱怨「换道时晃了一下」。后来发现,问题出在轨迹的边界条件上——起点和终点的jerk虽然连续,但中间点的jerk跳变了。所以,光看曲线连续还不够,还得检查各阶导数的连续性。

Jerk限制的典型值:

场景 最大Jerk (m/s³) 说明
舒适驾驶 2~5 日常通勤,乘客感受良好
运动模式 5~10 可以接受一些顿挫感
紧急避障 10~20 安全优先,舒适度靠后

4.3 轮胎摩擦力约束:别让车「滑」出去

这个约束,说白了就是「轮胎能抓住地面多少力」。我见过太多新手工程师,规划出来的路径在干燥路面上跑得挺好,一到雨天就各种打滑。

轮胎摩擦力可以用摩擦圆(Friction Circle)来描述。简单说,轮胎能提供的总摩擦力是有限的,纵向和横向的摩擦力不能同时达到最大。

摩擦圆约束公式:

sqrt( (F_long / F_max)^2 + (F_lat / F_max)^2 ) ≤ 1

其中 F_long 是纵向力,F_lat 是横向力,F_max 是最大摩擦力。

你想想看,如果车在高速过弯时还猛踩刹车,那横向和纵向都在抢摩擦力,很容易突破摩擦圆边界——结果就是甩尾或者推头。

我记得有一次做极限工况测试,车辆在湿滑路面上做紧急变道。算法规划的路径要求同时减速和转向,结果车直接滑出去了。后来我们在规划层加入了摩擦圆约束,确保在任何时刻,纵向和横向的合力都不超过摩擦圆半径。从那以后,再没出现过类似问题。

实际工程中的简化:摩擦圆约束是非线性的,求解起来比较慢。我个人的做法是把它线性化——用多边形近似圆,这样既能保证安全,又能提高计算效率。

4.4 三种约束的融合:一个完整的例子

好,理论讲完了,咱们来点实际的。假设我们要规划一段从静止加速到 10 m/s 然后匀速行驶的轨迹,需要同时考虑加速度、jerk和摩擦力约束。

下面是一个简单的速度规划代码示例:

def plan_velocity_with_constraints(v_target, a_max, jerk_max, mu, g):
    """
    带动力学约束的速度规划
    v_target: 目标速度 (m/s)
    a_max: 最大加速度 (m/s²)
    jerk_max: 最大jerk (m/s³)
    mu: 路面摩擦系数
    g: 重力加速度 (m/s²)
    """
    # 1. 计算摩擦圆限制下的最大加速度
    a_friction_max = mu * g  # 假设只有纵向运动
    
    # 2. 取三者最小值
    a_effective_max = min(a_max, a_friction_max)
    
    # 3. 用jerk限制生成平滑的加速度曲线
    t_accel = v_target / a_effective_max
    t_jerk = a_effective_max / jerk_max
    
    # 4. 生成三段式速度曲线:加jerk、恒加速、减jerk
    # 这里省略具体实现,只展示核心逻辑
    print(f"有效加速度限制: {a_effective_max:.2f} m/s²")
    print(f"加速时间: {t_accel:.2f} s")
    print(f"Jerk过渡时间: {t_jerk:.2f} s")
    
    return t_accel, t_jerk

这段代码虽然简单,但体现了融合约束的核心思想:取最严格的约束作为实际限制。

4.5 知识体系总览

为了让你更直观地理解这三种约束的关系,我画了一张图:

动力学约束知识体系 动力学约束 加速度限制 纵向/横向加速度上限 Jerk限制 加速度变化率约束 轮胎摩擦力约束 摩擦圆限制 融合原则 取三者中最严格的约束作为实际限制 在规划阶段就考虑约束,避免执行阶段出问题

这张图把三种约束的关系讲得很清楚。你想想看,实际工程中,这三种约束往往是耦合的——比如急转弯时,摩擦力约束会限制你的加速度,而加速度的变化又受jerk限制。所以,做规划时不能孤立地看某一个约束,得把它们放在一起考虑。

好了,这一章的内容就到这里。动力学约束这块,说白了就是「尊重物理规律」。你尊重它,它就让你的车跑得又稳又安全;你不尊重它,它就让你在测试场上出洋相。我个人建议,在做任何规划算法之前,先把这些约束列清楚,写在需求文档的第一页。

可可精品资料库