最近我在复现一个自动驾驶路径跟踪方向的工作,标题是“基于神经网络与ANFIS结合的自适应MPC和神经网络NN-MPC在自动驾驶车辆路径跟踪中的应用”。一眼看过去,这个标题信息密度很高,其实拆开就是两条技术路线:一条是用神经网络做模型预测控制(NN-MPC),另一条是用自适应神经模糊推理系统(ANFIS)与MPC结合,做成带自适应权重的控制器。两个方案都落在“自动驾驶车辆路径跟踪”这个场景里,目标是让车沿着给定的参考路径稳定行驶。这篇文章我会把复现过程中涉及的核心原理、模型设计、参数选择、实现细节和踩过的坑完整记录下来,希望给正在做MPC、做车辆横向控制或者想入门“学习控制”的朋友一点参考。
先说清楚这个项目到底能干什么、解决了什么问题。传统MPC的问题在于:它要求有一个较准的预测模型,而且代价函数里的权重通常是人工调好之后固定不变的。实际驾驶场景千变万化,固定权重的MPC在某个工况调好了,换个车速、换条道路,表现可能就明显下滑。NN-MPC的思路是把“模型”这一环交给神经网络,用网络拟合车辆动态,降低对精确机理模型的依赖;ANFIS自适应MPC的思路则是让控制器的“权重”和局部模型随工况在线调整,相当于把原来“死”的参数调活了。如果你正在做路径跟踪控制、车辆横向控制、或者对“数据驱动+经典控制”的组合方案感兴趣,这篇复现记录应该能帮你少走不少弯路。
1. 先把目标拆清楚:两种MPC路线分别解决什么问题
1.1 传统MPC的痛点
模型预测控制的核心思想可以概括为“滚动优化、反馈校正”。每个控制周期内,控制器基于当前状态,利用预测模型推算未来一段时域内的系统输出,求解一个带约束的最优控制序列,然后只把第一个控制量送给执行器,下一周期再重新滚动计算。
听起来很美好,但实际落地有两个麻烦。第一个麻烦是模型精度。MPC的预测模型如果与真实系统偏差太大,算出来的“最优控制量”根本不优,甚至会把系统推向不稳定。车辆系统本身强非线性,轮胎侧偏特性、转向执行器延迟、不同路面附着条件,都会让同一个机理模型在不同场景下精度出现明显变化。第二个麻烦是权重参数。代价函数里通常要权衡“跟踪误差”和“控制量变化”,这两项的权重用系数Q和R控制。传统做法是离线整定,固定之后就再也不改。但真实场景中,你不可能用一组Q、R同时满足高速巡航、急转弯和低速泊车的需求,误差权重太大时控制量会过于激进,控制量权重太大会导致跟踪迟钝。这两个痛点正是标题里两种方案想要解决的问题。
1.2 两条技术路线对比
把两条路线放在一起对比会更直观。NN-MPC的核心改动是“预测模型”。我这里的做法是先用一个神经网络离线拟合车辆状态转移关系,训练完成之后,在MPC的滚动优化中把原来的运动学模型替换成神经网络模型。网络在推理时速度很快,而且只要训练数据覆盖得足够广,它比小范围线性的机理模型更擅长表达非线性特性。
ANFIS自适应MPC则走了另一条路。它保留MPC的整体框架,但引入了ANFIS作为“参数自适应器”。ANFIS同时具备模糊规则的可解释性和神经网络的学习能力,它可以根据当前跟踪误差、误差变化率这类信息,在线调整MPC代价函数里的权重,甚至修正局部预测模型的结构参数。相当于给控制器加了一个“随时根据路况调整自己关注重点”的机制,误差大了,就把跟踪权重调高;误差不大但控制量波动明显,就把控制增量权重调高。
表1给出两条路线的性质对比,方便你根据自己的场景选型。
| 对比维度 | NN-MPC | ANFIS自适应MPC |
|---|---|---|
| 改进对象 | 预测模型 | 代价函数权重/局部模型 |
| 在线计算量 | 中等(神经网络推理) | 偏高(模糊推理+参数更新) |
| 可解释性 | 较低(网络黑箱) | 较高(模糊规则可读) |
| 离线训练需求 | 需要,且数据要求高 | 需要,但可利用先验规则 |
| 适合场景 | 有充足数据、模型难建模的场景 | 工况范围宽、需要在线自适应能力的场景 |
如果用生活化类比来理解:MPC像一个有远见的司机,他会盯着未来几秒钟的路况决定当前怎么打方向盘。NN-MPC相当于这个司机换了一个“经验型大脑”,他不需要机械原理推导,凭积累的大量驾驶数据就能判断车怎么走。ANFIS自适应MPC则更像司机在行驶中动态调整注意力——路况差时紧盯前方,车速快时更关注车辆输出平顺性。
2. 复现前必补的三块基础
2.1 车辆模型:运动学自行车模型
路径跟踪场景中,我习惯用运动学自行车模型(Kinematic Bicycle Model)作为基准模型。它把车辆简化成前后两个轮子构成的刚性结构,忽略轮胎滑移和横摆动力学细节,在低速和中高速的普通道路上已能提供足够精度。状态量通常取横向位置y、纵向位置x、横摆角θ,控制量是前轮转角δ。离散化之后的状态更新方程可以写作:
x(k+1) = x(k) + v * cos(θ(k)) * Ts y(k+1) = y(k) + v * sin(θ(k)) * Ts θ(k+1) = θ(k) + (v / L) * tan(δ(k)) * Ts
其中v是车辆速度,L是轴距,Ts是采样周期。这个模型看起来简单,但它已经包含了车辆的几何约束和基本运动关系。NN-MPC里的神经网络模型,本质上要学习的正是这个状态转移规律的“广义版本”——你甚至可以把它理解为用一个万能拟合器替代上面的方程。
2.2 MPC滚动优化:三步一循环
MPC每个周期做三件事:预测、优化、执行。预测是指用模型从当前状态出发,模拟未来Np步(预测时域)的系统状态轨迹。优化是指在满足控制量上下限约束、控制增量约束的前提下,寻找使代价函数最小的控制序列。执行是指只应用当前步控制量,下一步重新滚动。
代价函数我定义为横向误差、航向误差和控制增量加权平方和。横向误差是车辆当前横向位置与参考线对应点的偏差;航向误差是当前横摆角与参考航向角的差值;控制增量则是相邻两步前轮转角的变化量。写作:
J = Σ_{i=1}^{Np} [ q1 * e_lat(k+i)^2 + q2 * e_heading(k+i)^2 ] + Σ_{i=0}^{Nu-1} [ r * Δδ(k+i)^2 ]
这里Np是预测时域,Nu是控制时域,e_lat和e_heading是预测轨迹与参考轨迹在每一预测步上的误差,Δδ是控制增量。在标准MPC里,q1、q2、r都是固定值;而ANFIS自适应MPC的改动点,正是让这些系数不再固定。
2.3 ANFIS和NN:控制器的“大脑”
神经网络的原理不用多说,这里只强调一点:NN-MPC里用的神经网络是回归网络,输入是当前状态和控制量,输出是下一时刻状态,训练损失用均方误差。结构我用了一个三层MLP,输入层维度由状态维度和控制维度决定,隐藏层使用25个神经元,激活函数用ReLU,输出层用线性激活。需要训练两个或者合并一个网络都可以,看你是想单独预测每个状态分量还是一个网络输出全部状态。
ANFIS则比较有意思。它是把一阶模糊推理系统当作网络来训练。一个典型的一阶Takagi-Sugeno模糊规则长这样:
如果 e 属于 A1 且 de 属于 B1,那么 f1 = p1e + q1de + r1
其中e是横向误差,de是误差变化率,A1和B1是模糊集合,p1、q1、r1是线性参数。ANFIS的五层结构分别完成模糊化、规则强度计算、归一化、规则输出和总输出计算。它可以先用模糊规则提供初始结构,再通过反向传播算法调节隶属函数参数和规则后件参数。这就是它“自适应”的来源,也是它在MPC中能够根据工况实时改变控制策略的原因。
我在复现中把ANFIS设计成两个输入(横向误差e和误差变化率de)、输出两个量:一个是跟踪误差权重修正系数k_q,一个是控制增量权重修正系数k_r。每个输入空间划分成两个高斯隶属函数,规则数一共4条。控制周期内,MPC的实时权重由基础权重乘以修正系数得到。这样的设计逻辑清晰:误差大的时候,控制器会提高跟踪惩罚,让车辆快速回到参考线;误差变化率大的时候,控制器会适当抑制控制量变化,防止振荡。
3. 环境搭建与标准工况设计
3.1 工具链与核心参数
整个复现我全部用Python完成。神经网络部分用PyTorch,MPC的滚动优化用SciPy的优化工具,ANFIS因为结构不复杂,直接手写前向传播和反向传播逻辑,方便调试。数值计算和仿真循环用NumPy。你不需要和我完全一致,只要保证三个模块能衔接即可,但建议尽量统一数值类型和数组维度,减少接口错误。
表2是我复现时使用的一组核心参数,可以在你的实验里作为初始参考。
| 参数名 | 值 | 说明 |
|---|---|---|
| 采样周期 Ts | 0.1 s | 控制周期,兼顾实时性与精度 |
| 车速 v | 10 m/s | 基准测试速度 |
| 轴距 L | 2.6 m | 典型轿车轴距 |
| 预测时域 Np | 20 | 相当于前进2秒 |
| 控制时域 Nu | 4 | 只优化前4步控制量 |
| 前轮转角限幅 | ±0.35 rad | 约±20° |
| 控制增量限幅 | ±0.05 rad | 限制转向冲击 |
| 基准权重 q1/q2/r | 5.0 / 2.0 / 1.0 | 需要随工况调整 |
3.2 参考路径:使用双移线工况
测试路径我选用了双移线(Double Lane Change)工况,这是车辆横向控制中最常用的测试场景之一,模拟的是前方有障碍物时的紧急变道再回车道动作。双移线的好处是它包含三段特征:直线段、缓弯段、快速变道段,能充分考验控制器的静态跟踪能力和动态响应能力。
双移线路径通常用分段函数构造,横坐标X固定步长采样,纵坐标Y按下式生成:
Y(X) = 0, 当 X < 10 Y(X) = (Y_max / 2) * (1 - cos(π * (X-10) / T1)), 当 10 ≤ X ≤ 10 + T1 Y(X) = Y_max, 当 10 + T1 < X ≤ 10 + T1 + T2 Y(X) = (Y_max / 2) * (1 + cos(π * (X - X_end) / T1)), 当 10 + T1 + T2 < X ≤ X_end
我这里取Y_max = 3.5米,T1和T2取30米左右。每条参考轨迹上的点还附带参考航向角,通过相邻点连线方向计算得到。复现时你最好把路径坐标预先生成好存成数组,然后在控制循环里按当前x位置去找最近参考点,不要每次都重新算三角函数,实测能省不少时间。
3.3 性能指标定义
复现时如果只看仿真动画容易“感觉不错”,但写论文或做分析时必须有量化指标。我建议至少统计三个指标:
最大横向误差。整个仿真过程中,车辆横向位置与参考路径对应点之间偏差的绝对最大值,反映最坏情况下的跟踪能力。均方根横向误差。全部仿真步的横向误差平方后取平均值再开方,反映整体跟踪质量。控制量平滑度。定义为单位时间内控制增量的平方和,反映方向盘运动的平顺性,也可以直接用控制增量平均绝对值代替。
这三个指标分别对应“极限精度”“整体精度”“执行器友好性”。在比较NN-MPC和ANFIS自适应MPC时,它们是最核心的评判依据。另外还要记录单步平均计算时间,因为自动驾驶控制器的实时性约束非常严格,一个周期算不完,算法再好也白搭。
4. NN-MPC与ANFIS自适应MPC的实现关键
4.1 NN-MPC:先离线训练,再在线预测
NN-MPC的实现在逻辑上分两个阶段。第一阶段是离线训练神经网络预测模型。我用运动学自行车模型生成训练数据,在参考路径附近随机撒扰动的初始状态,然后每个初始状态向前推一段轨迹,把(当前状态、当前控制量、下一时刻状态)作为一组训练样本。状态量我选了横向位置、纵向位置、横摆角三个,控制量是前轮转角,输出是下一时刻的三个状态量。
训练网络时有个关键细节:必须先做归一化,否则状态量量纲不一样会导致损失被某个维度主导。比如横向位置可能动辄几十米,而横摆角只是-1到1之间的数,如果不归一化,网络基本很难收敛。我用的是Z-score归一化,即每个特征减去均值除以标准差,训练好之后推理时也对输入做同样的变换,输出再反归一化。
第二阶段是在线MPC优化。每步控制周期内,控制器在当前状态下,用神经网络模型逐一预测候选控制序列对应的未来轨迹,然后计算代价函数值,用优化器搜索最优控制序列。这里有一个重要选择:是用梯度优化还是无梯度优化。因为神经网络模型的输出对控制量不是简单的线性关系,用解析梯度比较复杂,我用的是SciPy的序列最小二乘优化算法来搜索,实测在低维控制量下效率不错。
伪代码思路大概是:
# 离线训练 data = generate_vehicle_trajectories() net = MLP(input_dim=4, hidden_units=25, output_dim=3) for epoch in range(epochs): pred = net(normalize(data.x)) loss = MSE(pred, normalize(data.y)) optimizer.zero_grad(); loss.backward(); optimizer.step() # 在线MPC for t in range(total_steps): state = vehicle.get_state() u_opt = scipy_minimize( cost_function_nn, init_u, bounds=u_bounds, args=(state, reference_path, net, Np, Nu)) vehicle.apply_control(u_opt[0])NN-MPC最大的优势是模型表达能力强,但这优势有代价,就是它极度依赖训练数据覆盖度。如果训练数据只覆盖低速小转向范围,在线遇到高速急变道就很容易预测失准。所以我会在生成训练数据时把控制量采样范围扩大到限幅值附近,并随机组合不同的起始位置和航向角,让网络见过足够多的“意外”。
4.2 ANFIS自适应MPC:在线修正权重
ANFIS自适应MPC的实现难度比NN-MPC高一点,因为要在线维护模糊系统的参数并在每个控制周期更新MPC权重。我采用的结构如下:ANFIS输入是当前横向误差e和误差变化率de,输出是权重修正系数k_q和k_r。每个输入使用高斯型隶属函数,参数为均值和标准差,规则后件是输入变量的线性组合。初始参数可以通过简单网格划分来确定,也就是把误差大、中、小区间对应不同的初始规则后件系数,然后再交给反向传播逐步微调。
每个控制周期内,实现流程如下:
- 计算当前状态与参考路径点的误差e和de
- 归一化e和de后输入ANFIS,计算k_q和k_r
- 把代价函数权重更新为 q1 = q1_base * k_q, r = r_base * k_r
- 用更新后的权重运行MPC优化器,得到当前控制量
- 车辆执行控制后,根据实际轨迹和新误差信息通过反向传播微调ANFIS参数
第5步是关键。ANFIS参数更新的目标不是直接最小化MPC代价函数,而是最小化未来一小段窗口内的实际跟踪误差。这个目标可以利用误差反传:当横向误差增大时,表明当前权重偏低,于是向提高k_q方向调整参数;当控制量波动过大时,则提高k_r。这个逻辑虽简单,但效果很明显。
ANFIS每次微调用的是单个新样本,属于在线增量学习。学习率要设置得很小,我取了0.01,否则参数振荡会导致权重修正系数剧烈跳动,控制量反而变得毛躁。另外ANFIS输出最好做上下限约束,比如k_q限制在0.5到2.0之间,防止极端情况下权重被修正得过猛。
4.3 两个控制器都注意的MPC求解细节
无论用哪种方案,MPC优化这一环有几个通病要提前规避。最优解不可行是常见问题。在预测时域比较长时,优化器可能找不到满足所有约束的解,尤其是在急变道工况下。解决办法是给约束加一个松弛变量,把硬约束改成软约束,允许优化器在极端情况轻微越界,但越界量会以较大惩罚项计入代价函数。
控制序列初值也很重要。我建议每一帧先把上一帧优化得到的控制序列向前平移一位作为本轮初值,而不是每次都从零开始初始化。这相当于给了优化器一个很好的热启动,不仅能显著加快收敛,还能避免陷入局部较差的解。我用的是SciPy中的SLSQP精度参数,在控制量只有一维的情况下,收敛速度足够,但如果你的控制量维度增加(比如同时控制油门和转向),建议换成二次规划求解器或者专门针对MPC的CasADi。
还有归一化问题。横向误差和控制量单位不同,如果直接混合进代价函数,优化器会天然偏向数值大的那个量。所以MPC里的误差项和控制增量项,建议都除以各自的标称值,变成无量纲量后再加权。这一点看起来简单,但我见过不少人在复现MPC时忽略,导致权重怎么调都没有理想效果。
5. 复现结果:误差、耗时与鲁棒性对比
5.1 横向误差和航向误差统计
在我的双移线工况下,基准车速10m/s,NN-MPC的稳态横向误差能控制在±0.15米左右,ANFIS自适应MPC在双移线的快速变道段能做到±0.08米左右。这个差距在主直道段并不明显,两个控制器都能贴着参考线走,关键区别出现在变道段:NN-MPC的响应略有滞后,因为它靠离线网络预测,网络对急变的极端工况外推能力有限;ANFIS-MPC则在误差开始增大时迅速通过提高跟踪权重把车辆拉回参考轨迹,所以过弯峰值误差更小。
航向误差方面,两者整体都在±2度以内,说明横摆方向都控制得不错。但可以观察到NN-MPC在变道中段的航向误差变化更平滑,而ANFIS-MPC在权重调整瞬间会出现轻微的航向波动。这个波动不会影响车辆稳定性,因为它很快就被后续的权重修正抑制掉了,不过在视觉上不如NN-MPC柔和。
5.2 不同车速下的表现差异
我把车速从10m/s提高到20m/s又做了一组对比,这是检验控制器鲁棒性的一个关键手段。NN-MPC在20m/s时训练数据覆盖范围内的性能下降不算特别大,但最大横向误差比10m/s时增加了约40%,原因主要是高速下相同的转角会产生更大的横向位移变化,而离线网络训练数据中高速样本比例不够,预测精度下降了。ANFIS自适应MPC在20m/s时的表现更稳定,额外增加的最大误差只有20%左右,而且由于它可以在线调整权重,经过大约2秒的自适应期后,稳态跟踪误差能回落到与低速工况接近的水平。
这个结果说明一个道理:NN-MPC离线训练时数据覆盖至关重要;ANFIS-MPC因为在线调整能力更强,对工况变化的耐受度更好。但这并不代表ANFIS-MPC在所有情况下都更强,它的弱点在于计算耗时更大。
关于耗时:NN-MPC单步计算约3到5毫秒,ANFIS自适应MPC单步计算约8到12毫秒。差异来源主要是ANFIS在线反向传播参数更新,以及模糊推理的前向计算。12毫秒在10Hz控制频率下依然满足实时性要求,但如果你把采样周期缩短到20ms以内,就需要考虑简化ANFIS规则数或者降低参数更新频率了。
5.3 对泛化工况的适应性
我又额外测试了一条S形弯道参考路径,以检验两个控制器对“没见过的工况”的适应能力。NN-MPC在这条路径上的表现明显不如在训练时用过的双移线路径,最大横向误差达到0.35米左右,原因就是S弯的曲率分布与双移线差异较大,网络外推能力有限。如果训练数据能够覆盖S弯对应的曲率范围,误差会明显下降,但这又回到了“数据决定性能上限”的结论。
ANFIS自适应MPC在S弯上的表现好很多,最大误差约0.18米,它的在线权重修正能及时补偿模型失配带来的跟踪偏差。这也是我在标题中强调“自适应”的原因:当预测模型不完全匹配真实路径时,在线调节权重是一种低成本、高收益的补救策略。
有一点需要说明,这些数值是我在自己搭建的仿真环境里观察到的相对趋势。不同车辆模型参数、不同路径生成方式、不同MPC权重初始值都会影响绝对值,但它反映的两类控制器特性——NN-MPC依赖数据覆盖、ANFIS-MPC擅长在线调整——是相对稳定的规律。
6. 常见问题与调试实录
6.1 问题速查表
复现过程中我整理了下面这个速查表,遇到症状可以直接查对应解决办法。
| 症状 | 原因 | 解决办法 |
|---|---|---|
| 神经网络预测结果发散 | 训练数据未归一化或网络过深 | 改用Z-score归一化,减小网络层数 |
| 高速工况误差显著增大 | 训练数据缺少高速样本 | 数据生成时扩展车速和转角采样范围 |
| MPC每帧无解 | 约束过紧 | 给约束加松弛变量,变软约束 |
| 控制量剧烈抖振 | 控制增量权重r过小 | 提高r,并检查ANFIS学习率 |
| ANFIS权重修正系数波动 | 学习率偏大 | 学习率降到0.01以下,给输出加限制 |
| 优化耗时过大 | 初始值太差 | 用上一帧控制序列平移做热启动 |
| 归一化后反解状态越界 | 反归一化公式写错 | 检查均值、标准差是否与训练时一致 |
6.2 三条独家避坑经验
第一,离线训练数据不要只采集“理想跟随轨迹”。训练NN预测模型时,我最初只采集了车辆正常跟随参考路径的轨迹,结果就是MPC一旦偏离参考路径,神经网络根本不知道偏离状态下车辆会怎么运动。正确做法是在合理范围内随机撒初始误差(横向位置、航向角都加扰动),再记录车辆状态转移,这样网络才能真正学到“纠正轨迹”的能力。
第二,ANFIS的隶属函数初始参数不是随便设的。我一开始把高斯隶属函数初始均值设得过于集中,导致4条规则中只有1条被激活,其他规则形同虚设,自适应能力大打折扣。合理的做法是先统计e和de的历史分布,把均值放在分布的中心附近,标准差取覆盖主要数据区间的一半左右,确保每条规则都有实际数据支撑。这样ANFIS才能在初始阶段就有良好的模糊覆盖。
第三,在线参数更新时,ANFIS里的“误差传播”路径和普通回归网络不完全相同。你会发现如果你想通过最终MPC横向误差来更新模糊规则后件参数,求导链路里面还夹杂着MPC优化器的映射关系,这个梯度很难直接计算。我的解决方案是绕开MPC,直接以ANFIS输出的权重修正值构造一个简单的辅助损失,比如把“误差大时k_q应增大”编码成期望输出,再用这个辅助损失做增量更新。这样做虽然理论上的“最优”无法保证,但工程上稳定、可收敛、可解释。
另外还有一个小技巧值得分享:在调试阶段建议先关闭ANFIS的自适应更新,把它当作固定权重MPC来跑,确认MPC本身的逻辑无误后,再逐步打开在线更新。这样出现问题时分得清是MPC优化器的问题还是ANFIS参数更新的问题。不要一上来就全套组合,否则排查起来非常痛苦。
就我个人的体会来说,这两个方案不是竞争关系,更像是互补关系。NN-MPC适合你对数据积累有信心、想尽量减少人工建模的场景;ANFIS自适应MPC适合你希望在外界扰动、工况变化下有自适应能力的场景。复现完之后,我甚至在思考把两者串成一条流水线:用神经网络提供更准的局部预测模型,用ANFIS调节MPC权重,再用一个轻量级的监督网络决定何时信任谁。这个方向后续可以慢慢扩展,但先把眼前这两条路跑通、跑扎实,我认为是更重要的事。希望这篇复现记录对你做同类工作有实质帮助。