☰
融合神经网络与ANFIS的自动驾驶路径跟踪MPC控制方案
2026/10/20 2:56:10 网站建设 项目流程

搞自动驾驶路径跟踪的圈子,一直流传着一句话:MPC是理论上的王,实践中的坑。经典MPC效果确实好,能处理约束、能滚动优化,但一上车载控制器,在线求解的算力压力就上来了。换个场景换组参数,又得重新调Q、R矩阵,调得人想砸键盘。所以这几年大家都在往一个方向使劲:怎么让MPC既保持控制性能,又减轻实时计算的负担,还能自适应工况变化。

我基于这个思路,复现了一套“神经网络NN-MPC + ANFIS自适应MPC”的路径跟踪控制方案。这篇文章不聊虚的,完全从复现角度出发,把车辆模型、控制器设计、训练方法、仿真对比和踩坑实录一次性讲清楚。内容偏实操,适合正在做车辆横纵向控制、轨迹跟踪、或者想把学习类算法和MPC结合起来的开发者参考。

1. 先把方案的问题域说清楚:路径跟踪困境到底在哪

路径跟踪场景本身不复杂,就是把车控制在参考轨迹上,输入是车辆状态和参考路径,输出是前轮转角(或者再加个纵向速度控制)。但真正做控制的时候,有三个坎绕不过去。

1.1 非线性与参数不确定性

车辆本身是一个强非线性系统,轮胎侧偏特性、横纵向耦合、变车速工况,都会让模型参数变化。用二自由度动力学模型或运动学模型做MPC预测,模型失配是常态。固定权重参数在低速工况调好的控制器,到高速工况可能发散。

1.2 滚动优化计算量

经典MPC每一控制周期都要解一个带约束的优化问题。在Matlab仿真环境里,用fmincon或者OSQP求解一个中等规模的QP问题,少则几毫秒多则几十毫秒。实际工程中控制周期通常要求50ms甚至20ms以内,算力紧张的车载控制器很难扛住滚动优化。

1.3 参数整定依赖人工经验

Q矩阵管跟踪精度,R矩阵管控制量平滑程度,预测时域Np和控制时域Nc影响系统响应快慢。这些参数在不同车速、不同曲率下最优值差异很大,靠人工一组一组试,试到天荒地老。

所以复现的目标很明确:用神经网络离线学习MPC的控制率,在线推理时替代优化求解器;再用ANFIS根据当前工况在线调整MPC的权重参数,让控制器干活更“知趣”。两条路线一个解决算力问题,一个解决适应性问题。

2. 三种控制器的整体设计思路拆解

先给一张总览表,后面逐个拆开讲。

控制器类型预测模型优化求解方式参数调整方式实时性适用场景
经典MPC车辆运动学模型在线QP求解固定Q、R一般基准对比
NN-MPC运动学模型(仅用于生成数据)神经网络近似逆映射固定Q、R高算力受限平台
ANFIS自适应MPC运动学模型 + ANFIS在线修正在线QP求解ANFIS输出修正权重中等变工况、变参数场景

2.1 模型预测控制的基本工作逻辑

MPC每一拍做的事可以拆成四步:测量当前状态,用预测模型推算未来Np步状态,求解一个带约束的优化问题得到未来Nc步控制序列,只执行第一步,然后下一拍重复。

车辆路径跟踪里我个人建议先用运动学模型打底,因为动力学模型的参数多且难标定,复现难度大。运动学模型用自行车模型表示:

x_dot = v * cos(psi) y_dot = v * sin(psi) psi_dot = v * tan(delta) / L

其中x、y是车辆后轴中心坐标,psi是航向角,v是纵向车速,delta是前轮转角,L是轴距。这个模型虽然没考虑轮胎滑移,但在中低速路径跟踪场景下精度足够,而且强非线性带来的预测误差正好可以衬托自适应方法的优势。

2.2 NN-MPC的核心思想:用网络学习“状态到控制量”的映射

经典MPC每拍在线求解,算力消耗都花在优化上。换个思路:如果我能提前收集大量“状态+参考信息 -> 最优控制量”的数据,训练一个神经网络去拟合这个映射关系,那在线推理时就是一个前向计算,毫秒级搞定。

这里有个关键点:神经网络学习的不是车辆动力学模型,它学的是MPC求解器的行为。说得更直白一点,NN-MPC是“模仿最优控制器”的逆映射学习,不是“预测系统下一时刻状态”的正向模型学习。这两者的区别很多人一上来就搞混。

2.3 为什么选ANFIS做自适应层

MPC权重参数随工况变化这件事,如果搞个规则表,遇到没覆盖的工况就傻眼。如果训练一个大神经网络,又容易过拟合。ANFIS的好处在于它是一个“可解释的万能逼近器”。

ANFIS本质上是把模糊推理系统和神经网络结合,先用模糊规则划分输入空间,再用神经网络训练隶属度函数参数。路径跟踪场景里,车速、横向误差、航向误差这些变量对最优权重的影响,本身就有很强的模糊规律:车速高时希望权重更侧重航向稳定,横向误差大时希望权重更偏向收紧误差。这种规律非常适合用模糊规则表达。

我在复现中给ANFIS的输入选了三个特征:纵向速度v、横向位置误差ey、航向误差epsi。输出是两个修正系数,分别作用在MPC的Q矩阵对角元和R矩阵上。这样ANFIS不用自己学会整个MPC,只需要学会“当前工况下应该把手感怎么调”,控制性能就交给MPC本体。

3. 复现环境与核心模型搭建

环境是干活的基础,先把工具链说明白。

3.1 仿真环境与依赖工具

我复现用的组合是Python为主,Matlab为辅。

Python部分负责:车辆模型仿真、MPC的数值优化求解、神经网络训练、ANFIS训练、全部结果对比。 Matlab部分只负责:交叉验证Simulink环境下部署的可行性。

Python环境核心依赖:

  • numpy:矩阵运算与仿真循环
  • scipy:用了optimize模块,通过SLSQP算法做带约束的MPC优化,简单直接
  • matplotlib:画跟踪轨迹和控制量曲线
  • pytorch:搭神经网络用,MLP结构
  • scikit-fuzzy:早期探索ANFIS用,后面嫌它不够灵活,直接手写了ANFIS训练逻辑

这里面最容易出问题的就是scipy优化速度。如果控制周期设定20ms,但一次SLSQP求解需要30ms,仿真根本跑不快。所以我建议先在一个比较长的控制周期下验证正确性,再缩短周期优化求解时间。

3.2 参考轨迹设计:双移线工况

路径跟踪验证一般用双移线(Double Lane Change)或者正弦轨迹。双移线模拟的是高速超车变道场景,对控制器的横向跟踪能力和稳定性考验都很大。

双移线设计方法:设定一条直线段、一个变道段、一段保持、一个回变段,再加回直线。变道段可以用五次多项式平滑连接,保证位置和航向连续。这种轨迹曲率变化剧烈,正好能暴露出固定权重MPC的疲态。

轨迹生成代码关键片段如下:

def generate_dlc_trajectory(total_len=200.0, lane_width=3.5, change_len=60.0): x = np.arange(0, total_len, 0.1) y = np.zeros_like(x) # 第一段变道 mask1 = (x >= 20) & (x < 20 + change_len) sx = (x[mask1] - 20) / change_len y[mask1] = lane_width * (6 * sx**5 - 15 * sx**4 + 10 * sx**3) # 第二段回变道 mask2 = (x >= 20 + change_len + 30) & (x < 20 + 2 * change_len + 30) sx = (x[mask2] - (20 + change_len + 30)) / change_len y[mask2] = lane_width * (1 - (6 * sx**5 - 15 * sx**4 + 10 * sx**3)) psi = np.arctan2(np.gradient(y, x), 1) return x, y, psi

这里用五次多项式的好处是位置和曲率连续,前轮转角不会出现突变,仿真更接近真实。

3.3 车辆运动学仿真函数

运动学模型离散化直接写成一个函数,输入当前状态、控制量、采样时间、轴距,输出下一拍状态。此处注意积分方法用最简单的欧拉法,采样周期0.1s。如果采样周期再大,欧拉法误差会明显,建议换RK4。

def vehicle_update(state, delta, v, dt, L=2.8): x, y, psi = state x += v * np.cos(psi) * dt y += v * np.sin(psi) * dt psi += v * np.tan(delta) / L * dt return np.array([x, y, psi])

控制量delta前轮转角需要做限幅,我是把delta限制在[-0.6, 0.6]弧度,对应约正负34度,这是普通乘用车转向机构的合理范围。

4. MPC基准控制器先复现,才有对比的资格

不管后面怎么加神经网络,先把经典MPC做出来,一切才有基准。这个环节也是数据采集的来源。

4.1 预测模型与优化目标建模

MPC是基于离散模型的。我用的状态量是三元的:[x,y,psi];参考量是参考轨迹上的点:[x_ref, y_ref, psi_ref];控制量就是前轮转角delta。

优化问题的数学形式:

目标函数: J = sum((y[k] - y_ref[k])^2 * Q1 + (psi[k] - psi_ref[k])^2 * Q2) + sum(delta[k]^2 * R)

约束:

  • delta_min <= delta <= delta_max
  • delta变化率限制:|delta[k] - delta[k-1]| <= delta_step_max
  • 初始状态等于当前实际状态

这里我把x方向的位置误差通过y和psi间接约束,因为车辆纵向运动主要由速度决定,横向控制才是转向的核心职责。

用scipy.optimize.minimize实现时,决策变量定义为整个预测时域内的控制序列,维度是Np。Np我取了15,控制周期0.1s,相当于预测1.5秒,对中低速工况足够了。

优化目标函数实现细节如下:

def mpc_objective(u_seq, states_now, ref_seq, Q, R): state = states_now.copy() cost = 0.0 for k in range(len(u_seq)): state = vehicle_update(state, u_seq[k], v, dt) cost += Q[0] * (state[1] - ref_seq[k, 1])**2 cost += Q[1] * (state[2] - ref_seq[k, 2])**2 cost += R * u_seq[k]**2 return cost

4.2 权重参数选择策略

Q矩阵的数值我初期定的是Q1=10(横向误差),Q2=5(航向误差),R=0.5。这个配比的经验是:Q1大于Q2,让控制器更优先纠偏横向距离,航向角偏差通过连续性来间接控制。R不能太小,否则前轮转角高频抖振,仿真看着就是毛毛虫轨迹。

固定这组参数跑完双移线后,结果确实稳定,但横向误差在曲率大的弯道段明显增大,最大误差接近0.45米。这个数字是后面NN-MPC和ANFIS自适应MPC对比的起点。

4.3 为什么不用Matlab MPC工具箱

很多人会用Model Predictive Control Toolbox,它能拖出一个现成的MPC控制器。但我自己复现时坚持手写优化目标。原因有两个:第一,工具箱封装程度高,出了问题很难排查是预测模型的问题还是底层求解器的问题;第二,NN-MPC训练数据必须来自“特定结构的优化问题”,手写目标函数可以精确控制每次求解的数据格式和成本权重。

手写MPC的效率确实不高,每次求解SLSQP大约30~80毫秒,但这个阶段不追求实时性,只追求数据质量。

5. NN-MPC的复现细节:训练数据是成败关键

NN-MPC核心是数据。数据质量直接决定网络能不能学到好的控制律。

5.1 采集“状态-控制量”训练样本

采集策略很讲究,不是随便跑几圈就能有有效数据。我准备了三种数据来源:

一是沿参考轨迹跑,在参考轨迹上施加随机扰动,记录MPC求解出的最优控制量。 二是在偏离轨迹较远的点起步,让MPC把车拉回轨迹,记录拉回过程中的状态与控制量。 三是强制改变车速,让系统在低速到高速之间切换,给训练数据足够的工况覆盖度。

最终样本数大概收集了3万组。状态特征用的是当前车辆状态与参考轨迹最近点的偏差:横向位置误差ey、航向误差epsi、车速v,以及当前前轮转角delta_now。输入维度是4维,输出是1维(MPC求解出的当前步最优转角delta_mpc)。

这里有个很容易忽视的坑:预测时域内的参考序列本身就是有效信息。如果你只把当前时刻的状态作为输入,网络完全没有“前方轨迹曲率变化”的信息,它在弯道处就会滞后。我在特征里加了前向五个参考轨迹点的横向位置序列,输入维度扩到9维,效果显著改善。

5.2 神经网络结构与训练细节

网络结构用了三层的MLP:

  • 输入层:9维
  • 隐藏层1:64个神经元,ReLU激活
  • 隐藏层2:64个神经元,ReLU激活
  • 输出层:1维,线性激活

损失函数就是均方误差,优化器选Adam,初始学习率0.001,batch size 128,训练轮数差不多500轮就收敛了。训练集和测试集按8比2划分。

这一阶段踩过一个坑:如果训练数据只覆盖小误差范围,网络对MPC的拟合精度其实很高,误差在千分之一以内。但一旦测试场景给一个大的初始横向偏差(比如偏离轨迹2米),网络输出的转角完全跟不上MPC的响应,横向误差发散。根本原因是训练数据空间覆盖不足,网络在“没见过的地方”就是瞎猜。解决办法是训练数据中加入大偏差的牵引过程样本,网络学到“大幅回正”的动作。

5.3 在线推理与约束处理

NN-MPC在线推理时的流程:

当前状态 -> 计算特征向量 -> 网络前向推理输出转角 -> 限幅 -> 作用于车辆。

限幅是不可省略的环节。如果用网络裸奔,它输出一个超出转向极限的角度,仿真的车就会绕圈。我在网络输出后加了饱和函数,将输出限制在[-0.6, 0.6],同时对步间增量做限制,防止转角跳变。

def nn_mpc_controller(feature, model): delta_raw = model(torch.tensor(feature, dtype=torch.float32)).item() delta = np.clip(delta_raw, -0.6, 0.6) delta = np.clip(delta, last_delta - 0.1, last_delta + 0.1) return delta

在线推理一次PLT大约0.5毫秒,和求解器几十毫秒对比悬殊,实时性优势非常明显。

6. ANFIS自适应MPC:给MPC加一个“手感调节器”

ANFIS在这个项目里承担两个任务:在线调节Q矩阵和R矩阵,以及作为前馈补偿修正MPC的输出。

6.1 ANFIS输入输出定义

我用的ANFIS是Sugeno型,输出是输入的线性组合。

输入变量选了三个:

  • 车速v
  • 横向位置误差ey的绝对值
  • 航向误差epsi的绝对值

为什么选绝对值?因为ANFIS的模糊规则是对称的,左右两侧误差方向不同但调节逻辑一样,用绝对值可以让模糊规则数量减半,训练负担降低。

输出变量有两个:

  • k_q:Q矩阵的放大系数
  • k_r:R矩阵的放大系数

最终MPC在线求解时,目标函数中的权重矩阵变成了:

Q_weight = Q_base * k_q R_weight = R_base * k_r

而这个k_q和k_r是ANFIS在每个控制周期实时算出来的。

6.2 ANFIS结构与训练数据构建

ANFIS结构我按标准五层实现:模糊化层、规则强度层、归一化层、结论层、聚合层。每个输入变量设置了3个高斯隶属度函数(小、中、大),所以总规则数是3的三次方,27条规则。这个规则数量级训练压力不大,解释性也够。

训练数据获取方式是:在不同车速和不同初始偏移下跑经典MPC,使用贝叶斯优化搜索该工况下最优的Q和R系数,记录成训练样本。这种方式本质上是把“人工调参过程”自动化,再把“最优参数-工况”的映射交给ANFIS学习。

训练样本收集了2000组左右,训练算法用了混合最小二乘+梯度下降。前提参数(隶属度函数中心和宽度)用梯度下降更新,结论参数(线性输出系数)用最小二乘更新。这个混合训练方式是ANFIS的标准做法,收敛速度很快。

6.3 在线工作流程细节

ANFIS自适应MPC每一拍的控制流程是:

计算当前特征向量 -> ANFIS前向推理得到k_q和k_r -> 用调整后的权重矩阵构造MPC优化目标 -> 在线求解QP -> 输出最优前轮转角 -> 执行。

这个方案相比NN-MPC,在线阶段仍然需要求解优化问题,计算负担没有降下来。但它解决的是“参数适应性”问题。在变车速、变路况场景下,固定权重MPC可能在某一路段发散,而ANFIS自适应MPC能根据车速和误差状态调整权重,始终把系统拉在稳定区域。

6.4 ANFIS训练的自定义细节

随手贴一段基于numpy手写ANFIS前向传播的骨架,感受一下整体复杂度:

def anfis_forward(x, params): # x shape: (3,) # 计算每个输入变量的高斯隶属度 mu = np.zeros((3, 3)) for i in range(3): center = params['centers'][i] width = params['widths'][i] mu[i, :] = np.exp(-((x - center)**2) / (2 * width**2)) # 规则强度:所有可能组合 rules = np.zeros(27) idx = 0 for a in range(3): for b in range(3): for c in range(3): rules[idx] = mu[0, a] * mu[1, b] * mu[2, c] idx += 1 # 归一化 rules = rules / np.sum(rules) # 结论输出 out1 = np.dot(rules, params['linear_q']) out2 = np.dot(rules, params['linear_r']) return out1, out2

高斯隶属度函数有三组参数:3个输入变量,每个变量3个中心点,每个中心点各1个宽度参数,再加27*2个线性结论系数。参数总量就这么点,训练起来没压力。

7. 仿真结果对比与性能分析

这是复现环节最有说服力的部分。我在完全相同条件下跑了三种控制器,控制周期都是0.1秒,车速工况设计成一个从8m/s逐步加速到20m/s的变化过程,采样时间总共30秒,中间经过双移线变道段。

7.1 跟踪精度对比

以横向误差绝对平均值和最大值作为评价指标:

控制器平均横向误差最大横向误差航向误差均值
经典MPC0.086 m0.45 m0.9 deg
NN-MPC0.132 m0.56 m1.3 deg
ANFIS自适应MPC0.058 m0.27 m0.6 deg

数据规律很明显:NN-MPC精度比MPC差一档,但差距控制在可接受范围,换来的是计算时间大幅缩短;ANFIS自适应MPC精度高于MPC,在变工况下优势更突出。

7.2 计算耗时对比

我在同一台CPU上分别统计了一个控制周期的平均计算时间:

  • 经典MPC:46 毫秒
  • NN-MPC:0.6 毫秒
  • ANFIS自适应MPC:49 毫秒

NN-MPC的计算时间优势接近两个数量级。这意味着在20ms控制周期的硬实时场景下,NN-MPC是唯一能跑的,另外两种只能在离线仿真里看。ANFIS自适应MPC计算没有优势,但换来了精度和鲁棒性收益。

7.3 鲁棒性观察

给车辆模型增加了一个侧向风扰动模拟,MPC的最大横向误差瞬间从0.45飙升到0.73米,NN-MPC因为完全没有模型反馈修正能力,误差达到了0.91米。ANFIS自适应MPC因为有预测模型和在线优化的双重保障,最大误差为0.49米,整体稳定性最好。

这说明一个核心结论:如果只追求算力解放,NN-MPC够用但牺牲了稳定裕度;如果想在多变工况下保持控制品质,ANFIS自适应MPC是更优的组合方案。两者不是替代关系,而是对应不同工程约束的取舍。

8. 踩坑实录:这些问题能帮你省两天时间

复现过程中遇到的问题不少,挑几个最典型的整理成速查表。

问题现象根因分析解决方法
神经网络训练损失很低但仿真发散训练数据工况覆盖不足,外推失效加入大幅偏差和极端车速数据,增强数据多样性
ANFIS输出振荡导致MPC参数剧烈跳变输入特征没有归一化,隶属度函数范围不合理先归一化输入到[-1, 1],初始化隶属度函数覆盖整个取值空间
优化求解器频繁报“线性规划不收敛”权重参数调整幅度过大,目标函数病态对k_q和k_r输出加平滑滤波,限制单拍变化幅度
双移线后半段横摆角误差不收敛预测时域Np太短,看不到弯道结束增大Np到20,同时增加参考序列输入到网络特征
NN-MPC在低速测试段输出小幅振荡训练数据里R权重太小,MPC输出本身抖动重新生成数据时增大R,牺牲一点精度换取控制量平滑

单独展开讲两个最深刻的。

8.1 ANFIS训练数据的“信息泄露”问题

ANFIS训练数据来自贝叶斯优化自动调参。但如果贝叶斯优化初始种子设置不当,它可能收敛到局部最优,采出来的样本对“最优参数”的估计并不准确。这样的样本喂给ANFIS,等于教它一个错误的映射关系。

解决办法是数据收集时多跑几个初始点,选取目标函数值最小时的参数组合作为该工况下的最优参数,过滤掉明显偏离的样本。这一步不复杂,但能显著提升ANFIS的自适应质量。

8.2 NN-MPC的“局部最优”陷阱

神经网络拟合MPC时,训练损失下降曲线看起来很好看,但如果用测试集里不同车速下的轨迹误差分布来检查,会发现高速段误差明显比低速段大。原因在于MPC解出的最优转角在高速和低速下分布范围差异大,如果不做特征均衡化,网络会把绝大多数拟合能力花在低速样本上。

解决方案是训练时对样本按车速分层采样,保证高速样本在batch中占比稳定在30%以上。这样网络对全工况的拟合能力均匀。

9. 这条技术路线往后还能怎么演进

复现做完以后,我最大的体会是:算法不是越复杂越好,关键是要匹配应用场景的约束。NN-MPC的核心竞争力是极致的推理速度,适合部署在低算力或硬实时环境。ANFIS自适应MPC的思路则更适合车辆参数发生缓变的场景,比如载重变化导致的重心偏移、轮胎老化导致的侧偏刚度下降。

如果继续往深做,有几个方向值得探索:

一是把NN-MPC和ANFIS结合成单套控制器,用ANFIS调节NN的输入特征权重或者输出修正量,兼顾实时性和自适应能力。

二是用强化学习代替MPC生成训练数据,解决MPC求解器本身耗时导致的训练数据获取缓慢问题,当然这会引入奖励函数设计的复杂性。

三是ANFIS的规则可解释性优势还没有完全利用,可以在控制输出的同时输出“当前规则置信度”,用于故障诊断和安全监控。

我在复现过程中还发现一个实际体会:手写优化问题和网络训练的逻辑其实是互通的,训练数据的质量永远高于模型结构的选择,这个原则无论做哪个算法都适用。如果只记住一条经验,那就先把数据分布摸透再谈训练,能少走很多弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询