做无人驾驶轨迹控制这几年,我踩得最深的一个坑,就是固定预瞄距离和固定P增益在变曲率、变车速场景下完全压不住。后来我把方案改成自适应预瞄与自适应P反馈联合控制,才真正解决了高速大弯和低速急弯兼顾的问题。这篇文章把整套思路、公式推导、标定流程和实车踩坑一次性讲清楚,适合正在做横向控制、轨迹跟踪、或者准备从仿真往实车迁移的同行参考。
先说个结论:横向控制表面上是调一个转角,本质上是在调"车辆看到多远的未来"和"车辆多相信当前误差"。这两个量一旦变成固定值,任何路况都当成同一段路来开,必然在某些场景翻车。下面我从一次实测事故开始拆这套方案。
1. 固定预瞄距离与固定P增益:从一次冲线说起
1.1 我在连续弯道测试中遇到的问题
那次测试用的是带组合惯导和线控底盘的测试车,场地里有一段组合道路,包含半径60米的低速弯、半径150米的高速弯和一段长直线。我把控制器参数设置成最经典的一组固定值:预瞄距离8米,P增益0.6,速度设定从20km/h一路加到60km/h,每个速度下让它跑三圈。
低速弯上首先出问题。20km/h过半径60米弯时,车辆明显向内切,横向误差最大到0.9米,车身姿态已经压到车道内侧边缘。高速弯上情况反过来,60km/h过半径150米弯时车辆往外侧飘,横向误差到了1.3米,最后直接冲出了可行驶区域。同样的参数,低速内切高速外冲,而且误差方向完全相反,这就是固定参数方案的典型症状。
1.2 固定参数的失效本质:控制器的"前瞻时间"在漂移
为什么同一组参数表现会这么分裂?关键在于预瞄距离真正对应的物理量不是距离,而是时间。
预瞄距离Ld可以折算成控制超前时间Tp,关系式是Tp = Ld / Vx,Vx是纵向车速。20km/h大约是5.56m/s,预瞄8米对应的超前时间约1.44秒。对一个半径60米的弯来说,1.44秒后车辆已经走过很长一段弧线,控制器相当于一直在盯着离车很远的点打方向,自然会把弯切掉。60km/h时车速16.67m/s,同样预瞄8米,超前时间只剩0.48秒,控制器反应太晚,车辆沿着切线方向往外冲。
这就是问题根源:固定预瞄距离让前瞻时间随车速剧烈变化,低速时"看得太远",高速时"看得太近"。
P增益也一样。固定0.6的增益,低速时横向误差0.5米会产生约0.3弧度的前轮转角,车辆会有明显的摆动感;相同误差在高速时依然产生相同的转角,但同样的转角在高速下产生的侧向加速度却大得多,车辆很容易突破轮胎附着极限。P增益本质上是把横向误差映射成转向角,而这个映射关系必须随车速变化,否则高速稳定性和低速响应性永远只能二选一。
这个测试之后,我彻底放弃了固定参数方案,转向了自适应预瞄和自适应P反馈联合控制。
2. 自适应预瞄:让"看得多远"跟随运动状态实时变化
2.1 预瞄距离的三种自适应策略
自适应预瞄的第一层,也是最基础的一层,是让预瞄距离随车速线性增大。这是我实际使用的基准形式:
Ld = L0 + Kv * Vx
其中L0是最小预瞄距离,通常取2到4米,保证低速时有基本的前瞻能力;Kv是车速系数,单位秒,实际取值范围大约0.2到0.6秒。用20km/h和60km/h分别代入:取L0=3,Kv=0.3,20km/h时Ld=4.67米,60km/h时Ld=8米。可以看到车速越高预瞄越远,Tp被维持在一个相对稳定的范围内。
第二层自适应要考虑道路曲率。当车辆进入小半径弯道时,预瞄距离如果太长,预瞄点会越过弯心落到弯道另一侧,控制器会认为前方路径走向与当前航向差异巨大,导致过度打角、内切。所以需要在曲率大时缩短预瞄距离。一个工程上常用的修正形式是:
Ld = clamp( (L0 + Kv * Vx) / (1 + Kc * |kappa|), Lmin, Lmax )
kappa是当前路径的曲率,Kc是曲率修正系数,典型值3到8。比如车速30km/h,基准预瞄5.5米,前方弯道曲率0.02,相当于半径50米,取Kc=5,修正后Ld=5.5/(1+0.1)=5.0米。这个公式的物理含义很直观:弯越急,预瞄点往回缩,确保目光始终落在弯道内侧可走的弧线上。
还有第三层,横向误差相关。当车辆离参考线较远时,预瞄距离适当缩短可以让车辆更快回到轨迹上;误差小时拉长预瞄距离,减少修正过度。不过这一层我在实际工程中只做了轻度使用,因为误差项引入太多容易造成预瞄点抖动,后面会专门讲这个问题。
2.2 曲率估计的工程实现
自适应的前提是能实时拿到当前路径曲率。路径通常表示为离散轨迹点序列,假设是全局坐标系下的点列p0, p1, ..., pn,每个点包含x、y坐标和期望航向角。
我用的曲率估计方法是"三点定圆法"。取当前点、往前数m个点、往后数m个点,用这三个点求外接圆半径,曲率就是半径的倒数。m的选取和车速相关,车速越高m取越大,因为高速下需要更长弧段才能稳定估计曲率。三点定圆的方法计算量小、实时性好,但噪声敏感,所以曲率输出必须加一阶低通滤波,时间常数大约0.1秒。我在调试中发现,如果不滤波,曲率估计值的抖动会直接传递到预瞄距离,造成预瞄点前后跳动,转向指令出现高频毛刺。
另一种做法是基于相邻点航向角变化率:曲率近似等于单位弧长上的航向角变化量,即kappa = delta_psi / delta_s。这种方法更平滑,但对点的航向角精度要求高,组合惯导轨迹的航向角噪声如果偏大,反而效果不如三点定圆。工程上建议两种方法都实现,用互相校验确认当前曲率估计是否可靠。
2.3 预瞄点选取与误差计算
有了自适应预瞄距离Ld,下一步就是确定预瞄点在哪个位置。做法是从车辆当前位置沿参考轨迹搜索,找到距离等于Ld的目标点。更工程化的处理方式是先根据车速估算一个粗略的搜索半径,直接索引到轨迹点附近,再在局部做精确距离匹配,这样避免每一控制周期都全轨迹搜索,计算量可以压到很小。
确定预瞄点后,需要计算两个核心误差量:横向误差和航向误差。横向误差是车辆后轴中心到预瞄点的横向偏移,航向误差是当前车辆航向与预瞄点处参考航向的夹角。计算时把参考点坐标先转换到车辆坐标系下,其中x轴指向车头方向,y轴指向左侧,这样横向误差直接就是转换后的y值,航向误差是航向角之差。这一步看起来简单,但坐标系转换的细节经常是实车调试中误差来源之一。
注意:航向误差一定要做角度归一化处理,把差值限制在正负pi之间。否则车辆掉头或倒车时,角度差跳变会让P控制瞬间打满方向。
3. 自适应P反馈:预瞄点选好了,增益还得跟着状态走
3.1 纯跟踪模型的P控制本质
很多人把预瞄和P反馈当成两件独立的事,但从纯跟踪模型的角度看,它们本质上是同一个几何控制器的两个侧面。
纯跟踪模型给出的前轮转角公式是:
delta = 2 * atan( 2 * L * sin(alpha) / Ld )
其中L是车辆轴距,alpha是车辆当前航向与预瞄点方向的夹角,Ld是预瞄距离。当alpha较小时,sin(alpha)近似等于alpha,而alpha又近似等于横向误差e除以预瞄距离Ld,于是可以化简为:
delta ≈ 2 * L * e / (Ld^2)
这个形式已经很明显了:纯跟踪模型在数学上就是一个关于横向误差e的P控制器,等效P增益等于2L除以Ld的平方。也就是说,你调预瞄距离的时候,不只在改变"看多远",也在改变P增益大小。Ld变大,等效增益变小,控制变柔和;Ld变小,等效增益变大,控制变激进。
这给联合控制指了一条明路:自适应预瞄本身已经隐含了一部分P增益自适应。高速时Ld大,等效增益自动变小,正好满足高速需要低增益的稳定性要求;低速时Ld小,等效增益自动变大,满足低速需要强修正的响应要求。所以最合理的做法不是让预瞄和P增益各调各的,而是把P增益设计建立在Ld模型之上。
3.2 增益调度曲线设计
虽然纯跟踪已经内含了部分自适应,但实际工程中还需要额外的P增益调度。原因有二:一是纯跟踪模型的等效增益在小误差时偏温和,大误差时又偏激进,不符合"大误差应该限制增益避免超调"的工程直觉;二是实车转向系统存在延迟和死区,必须用额外增益补偿。
我在项目里用的P增益调度是分段的:
| 速度区间(km/h) | 基础P增益 | 说明 |
|---|---|---|
| 0-20 | 0.8-1.0 | 低速大增益,快速消除初始误差 |
| 20-40 | 0.6-0.8 | 过渡区,增益开始下降 |
| 40-60 | 0.4-0.6 | 中高速,重点关注稳定性 |
| 60-80 | 0.25-0.4 | 高速,增益大幅下降避免摆振 |
这个表不是拍脑袋定的。确定数值时,先以纯跟踪的等效增益2L/Ld^2为基准,再乘一个速度相关的修正因子。修正因子的取值依据是车辆在相应车速下的转向响应带宽:车速越高,转向响应的等效带宽越低,允许的控制增益就越低。实际标定的时候,在每条速度区间跑直线和固定半径弯道,逐步增大增益直到转向指令出现可见的高频振动,然后取振动点的70%作为该区间的上限,再往下留余量。
增益调度还需要和横向误差大小联动。我用了一个简单的变增益策略:横向误差绝对值大于0.5米时,把P增益降到当前速度基准值的60%;误差小于0.2米时,恢复基准值。这其实是变相地防止大误差时车辆猛打方向,给执行器和轮胎留缓冲空间。
3.3 稳定性边界:P增益过大的典型表现
自适应P增益最大的风险不是调不准,而是某个速度点或误差点上增益过高触发振荡。我在实车上见过最典型的现象是"摆振":车辆以50km/h跑直线,横向误差很小,但方向盘持续小幅来回抖动,频率大概2-3Hz,车内能明显感觉到车辆在画龙。
排查后发现速度区间40-60km/h的增益设到了0.75,加上转向执行器本身有约30毫秒的延迟,等效相位裕度不够,控制器在尝试修正微小误差时不断过冲,形成了自激振荡。后来把该区间增益降到0.45,同时给横向误差加上0.02米的死区,振荡立刻消失。
这里有一个工程经验:判断P增益是否过大的最直接手段,是看转向角指令中是否持续存在某个高频分量,而不是看横向误差是否已经发散。误差还没有发散但指令在抖,说明系统处于临界稳定状态,必须降增益。
4. 联合控制的框架搭建与参数整定顺序
4.1 整体控制流程
我最终落地的联合控制框架分七个环节:
- 接收规划模块输出的参考轨迹点序列;
- 根据当前车速和曲率估计,计算自适应预瞄距离Ld;
- 在轨迹序列上搜索距离车辆当前位置为Ld的预瞄点;
- 计算横向误差与航向误差;
- 基于当前速度和误差大小查增益调度表,得到P增益;
- 计算控制转角,叠加曲率前馈补偿;
- 输出给转向执行器,同时用反馈位姿更新下一周期状态。
第6步的曲率前馈补偿非常关键。公式是:
delta_ff = atan(L * kappa)
kappa是当前路径曲率,L是轴距。前馈部分保证车辆在稳定过弯时有基础转角,P反馈部分只负责修正偏离量。加了前馈之后,P增益可以留得更低,整个系统的稳定性和弯道跟踪精度同时提升。我前后对比过,同样一个半径80米的弯,不加前馈横向误差峰值0.35米,加了之后降到0.12米,而且方向盘明显更稳。
4.2 联调时容易被忽略的耦合关系
联合控制最麻烦的地方在于预瞄和P增益互相影响。前面推过,等效P增益是2L/Ld^2。所以当你把预瞄距离调大之后,即使调度表里P增益没变,实际系统的总增益也下降了。反过来,当你调小预瞄距离去改善低速弯道响应时,实际增益又悄悄变大了。
处理这个耦合关系,我的做法是把控制律重写成统一形式:
delta = delta_ff + Kp_schedule(Vx, |e|) * (2L / Ld^2) * e
把Ld和增益的关系显式写进公式,这样调整预瞄距离时,调度表会自动依据新Ld做补偿,不会出现"调了预瞄,系统突然变抖"这种状况。联合控制的"联合"二字,重点就在这个公式里。
4.3 参数整定顺序
考虑到这个耦合关系,参数标定需要按照固定顺序来,否则很容易陷入重复调参的循环。
第一步,最小预瞄距离L0标定。测试条件:低速20km/h,直线道路,缓缓打方向,观察车辆跟随预瞄点变道的过程,确保L0小到能让车辆及时走线,又大到不会让方向响应显得神经质。第二步,标定车速系数Kv。从20km/h开始,以10km/h递增做到80km/h,每个速度下跑固定半径弯道,记录横向误差随速度的变化,调整Kv让误差峰值保持平稳。第三步,标定曲率修正系数Kc。重点测小半径弯道,观察是否内切,内切则加大Kc。第四步,标定P增益调度表。基于上一步的预瞄参数,从低增益往高调,找到每个速度区间的最佳增益。第五步,叠加前馈,重新微调P增益。最后做连续弯道综合验证。
参数初始值建议用下面的表:
| 参数 | 初始值 | 调整方向 |
|---|---|---|
| L0 | 3.0m | 低速内切减小,低速跟踪迟钝增大 |
| Kv | 0.30s | 高速外冲增大,高速摆振减小 |
| Kc | 5.0 | 小半径弯内切增大,大半径弯不稳减小 |
| Kp基础值 | 0.60 | 低速响应慢增大,高速摆振减小 |
| 死区 | 0.02m | 画龙增大,直道误差偏大减小 |
这套初始值在我的测试平台上可以直接跑出可用效果,再基于此微调,通常半天能完成一轮标定。
5. 从仿真到实车:踩过的那些坑和最终效果
5.1 仿真里一切正常,一上车就摆振
这套方案在仿真平台上跑得很顺利,横向误差保持在正负0.08米以内,转向指令平滑。移植到实车后第一次高速测试,50km/h直线就开始摆振,方向盘高频抖动,车内噪音明显增大。
对比仿真与实车的差异,问题出在三个环节。第一是转向执行器延迟,仿真里默认无延迟或只有10毫秒,实车从指令发出到前轮真正响应大概有80到150毫秒。第二是定位噪声,组合惯导给出的横向位置在小误差范围内有厘米级噪声,直接看横向误差的实时值,噪声会被P增益放大进转角指令。第三是转向死区,实车方向盘在中心附近存在一个不敏感区间,P增益小时修正不动,P增益大时又容易越过死区后就给多了,形成极限环。
这三个问题叠加在一起,正是"仿真好、实车烂"的典型原因。解决方案分别是对延迟做Smith预估式补偿,对横向误差做低通滤波,以及加入误差死区。需要特别提醒:噪声滤波和死区会降低有效P增益,所以实车调试时增益往往比仿真值高,这个方向一定不要搞反。
5.2 曲率前馈滞后导致的入弯外冲
另一个让我印象深刻的坑出现在入弯阶段。车辆从直线进入半径80米的弯道,速度60km/h,入弯瞬间横向误差突然从0.1米跳到了0.8米,车辆明显往外侧冲出,过了弯心才慢慢拉回来。
查下来发现是曲率前馈滞后。曲率估计用的是三点定圆加低通滤波,滤波时间常数0.1秒,低通滤波让曲率估计在入弯时衰减了一半,前馈转角给少了,而P反馈还没反应过来。连续几个周期累积下来,车辆就冲出去了。
解决方法是把曲率前馈分成两路:一路用滤波后的曲率做稳定过弯补偿,另一路用原始曲率变化率做入弯提前量补偿。后者相当于给前馈加了一个"加速度项",让车辆在曲率刚开始增大时就提前打方向。改进后入弯横向误差峰值从0.8米降到0.2米,效果立竿见影。
5.3 连续弯道场景的综合表现
方案调完后的最终测试,是在一段包含S弯、减速弯和高速大弯的封闭道路上进行的。目标速度40km/h到60km/h,最终横向误差RMS稳定在0.08米,峰值为0.3米,全程没有出现内切和外冲,方向盘转角指令的抖动幅度比固定参数方案下降了约60%。
我还做了一组对比测试。同一路线、同样速度区间,固定预瞄加固定P增益的方案横向误差RMS为0.28米,峰值超过1米;自适应预瞄加固定P增益,RMS降到0.15米,但高速段仍有轻微摆振;完整联合控制方案RMS降到0.08米。三组数据清楚地展示了每一层自适应带来的增益。
5.4 一点个人调试体会
这套方案做完之后,我对"自适应"三个字的理解变了很多。自适应不是把参数从常数变成公式就完事,而是要确保每个自适应项的物理意义和车辆运动真实对齐。预瞄距离的本质是控制前瞻时间,P增益的本质是误差到转角的映射强度,两者的乘积关系决定了整个闭环的响应特性。调试时反复追问"这个参数到底在物理上代表了什么",往往比盲目调数字更有效。
最后分享一个我在联调阶段一直用的方法:设计一条"扫描式"测试路径,把直线、缓弯、急弯、连续弯按顺序排在一起,每一段对应一个速度区间,跑一圈就能同时观察车辆在全部典型工况下的表现,用一段测试数据代替无数散点调试,效率会高很多。后续想再进一步的话,可以考虑在这个框架上叠加前馈模型、横摆角速度反馈,或者用模型预测控制替换纯P反馈层,预瞄距离的自适应逻辑完全可以复用。