轮毂电机平台4WS+DYC协调控制:Nash博弈与模糊神经网络实战
2026/9/6 16:47:27 网站建设 项目流程

简介:一套面向车辆工程与控制领域研究人员的论文复现资源,聚焦轮毂电机驱动电动汽车主动四轮转向(4WS)与直接横摆力矩控制(DYC)的协调控制策略。内容以完整可运行的MATLAB代码为主线,逐步讲解整车参数初始化、双移线参考路径生成、二自由度车辆动力学建模、基于非合作Nash博弈的4WS控制器、基于质心侧偏角相平面分区的DYC控制器,以及模糊神经网络协调策略的设计思路,并通过CarSim/Simulink联合仿真和硬件在环试验验证控制效果。资源共1个PDF文件,大小469KB,内含详细代码及解释,已有70人学习下载。读者可借此复现论文核心逻辑,掌握Nash博弈、相平面法、模糊神经网络在车辆稳定性控制中的工程实现方法,对开展相关课题研究或毕业设计具有直接参考价值。 去年我把一套轮毂电机驱动平台的4WS+DYC协调控制方案从Simulink仿真一路做到HIL台架验证,最大的感触是:控制算法本身不算门槛,真正的门槛在于让“都想当老大”的两个控制器别打架。4WS负责后轮转向,DYC负责附加横摆力矩,两个执行器都直接影响横摆运动,如果只是各自接一个PID,跑几个工况就能看到它们互相较劲的丑态。我最后落地的方案是用Nash博弈做执行器分配,再用模糊神经网络实时调整博弈权重,效果比传统加权分配和分层PID都稳得多。这篇就把完整思路、核心代码和调试经验都写出来,供做底盘域控和智能车辆控制的朋友参考。

1. 从“能控”到“好控”:轮毂电机电驱动平台上4WS+DYC的底气与难点

1.1 轮毂电机驱动把控制自由度补齐了

传统内燃机车辆想做DYC,往往得靠差速制动或者复杂的动力传动系统,响应慢,还会牺牲驱动效率。轮毂电机驱动完全没有这个问题:四个车轮独立驱动,每个轮子的扭矩可以单独控制,通过左右轮纵向力差值就能快速产生附加横摆力矩。这个力矩不受发动机响应延迟和传动机构的束缚,毫秒级就能上去。

在此基础上再加4WS,等于又多了一个直接改变后轴侧向力的执行器。传统前轮转向只能靠前轴“拽着”车走,后轮转向可以主动去“推”一下车尾,在低速时减小转弯半径、高速时改善横摆阻尼。可以说,轮毂电机带来的DYC和4WS叠加起来,路径跟踪和稳定性的执行器冗余已经很充分了,问题是控制策略怎么接住这些冗余。

1.2 执行器多了,冲突也来了

执行器冗余听着是好事,但控制上最怕的就是一个误差信号驱动多个执行器。举个实际例子:高速单移线工况下,路径跟踪层发现横摆角速度误差偏大,4WS控制器为了让车尾跟上会主动给一个后轮转角;DYC控制器同时看到同一个误差,也会立刻叠加上一个附加横摆力矩。如果两者各自独立去消误差,结果常常是过冲加剧:后轮先推一下,力矩再拧一下,横摆角速度是回来了,但质心侧偏角突然变大,车身姿态反而更危险。

我在初版方案里试过简单加权求和:把4WS和DYC的输出按固定系数加起来,低速还行,到了高速连续变道工况就开始抖。这种冲突不是调两个P值能解决的,必须有一套机制让两个执行器在每一控制步长里“商量”着来。

1.3 为什么我选了Nash博弈而不是传统加权

传统做法是把路径跟踪误差和稳定性误差揉成一个目标函数,比如J = w1 * 跟踪误差 + w2 * 稳定性误差,然后一次性解出所有控制量。这种做法的问题在于权重w1和w2很难定:路面附着好、车速低的时候可以多照顾跟踪精度;附着差、车速高的时候必须优先稳定。固定权重必然顾此失彼。

Nash博弈则把这俩当成两个独立玩家:4WS玩家最小化自己的代价函数,DYC玩家最小化自己的代价函数,两者各自决策又能看到对方的策略,最终停在纳什均衡点。说人话就是,4WS和DYC都有自己的KPI,但也知道对方在干什么,最终达成一个大家都能接受的状态。

Nash均衡不保证全局最优,但它的优势是控制结构清楚、对工况变化更鲁棒,而且天然适合分层分布式控制器。后续再加一个模糊神经网络去动态调节两个玩家的目标权重,基本就把“什么时候该谁出力”这个问题解决掉了。

2. 我的分层控制策略:路径跟踪在上,Nash博弈中承,FNN补偿垫底

2.1 上层路径跟踪:先生成参考横摆角速度

控制结构不能一上来就做博弈,先把上层目标说清楚。我用的上层模块是预瞄误差 + 参考横摆角速度生成器。它不直接输出后轮转角和横摆力矩,而是把路径跟踪需求翻译成车辆应该按什么横摆角速度运动。

对一个轴距L、车速vx的车辆,参考横摆角速度大致可以写成:

gamma_d = vx / (L * (1 + K * vx^2)) * delta_d

其中delta_d是预瞄点对应的等效前轮转角,K是稳定性因数。这个值还要做一层物理限制:gamma_max = mu * g / vx。低附着路面上如果不做这个限幅,控制器会要一个轮胎根本给不出来的横摆角速度,后面的博弈再聪明也是白搭。

同时我还会给一个参考质心侧偏角beta_d,正常情况下取0或者一个很小的修正值。上层输出的这两个量,就是下层的博弈目标。

2.2 中层Nash博弈:4WS和DYC各自的代价函数

车辆模型我用的是经典二自由度自行车模型扩展4WS后的形式,状态量是质心侧偏角beta和横摆角速度gamma:

m * vx * (beta_dot + gamma) = Fyf + Fyr
Iz * gamma_dot = a * Fyf - b * Fyr + Mz

其中后轴侧向力Fyr里包含后轮转角项:

Fyf = Cf * (delta_f - beta - a * gamma / vx)
Fyr = Cr * (delta_r - beta + b * gamma / vx)

注意,delta_r是后轮转角,Mz是DYC附加横摆力矩,这两个就是Nash博弈里两个玩家的控制量。

玩家1是4WS,它的代价函数这样定义:

J1 = q1 * (gamma - gamma_d)^2 + q2 * (delta_r - delta_r_prev)^2 + r1 * delta_r^2

玩家2是DYC,它的代价函数这样定义:

J2 = q1 * (beta - beta_d)^2 + q2 * (gamma - gamma_d)^2 + r2 * Mz^2

两者的差异在于:4WS更看重横摆角速度跟踪,同时要控制后轮转角的变化率,不能让后轮高频摆动;DYC则把质心侧偏角误差放在更重要的位置,因为侧偏角是稳定性最直接的指标。它们的代价函数里都有对方关心的项,这就是“互相看见对方策略”的体现。

Nash求解我用的是串行迭代,不直接解耦合Riccati方程。工程上更实用的做法是:固定DYC当前输入,用优化器最小化J1更新delta_r;再固定更新后的delta_r,用同一个优化器最小化J2更新Mz;如此交替迭代,直到控制量变化小于阈值。

2.3 下层模糊神经网络:动态调节两个玩家的权重

Nash博弈结构定下来之后,还有一个关键问题:q1、q2这些权重在不同工况下应该不一样。低附着路面上beta稍大一点就要全力保稳定,这时候DYC的权重必须提高;路面好的换道工况则应该让4WS多承担路径跟踪任务。

这个调整我交给了一个模糊神经网络。它的输入取beta、beta_dot、估计的路面附着系数mu,输出两个权重修正系数k1、k2,分别作用于4WS和DYC的代价函数。选模糊神经网络而不是普通神经网络,是因为模糊规则可以先给一套可解释的初值,神经网络再在这些规则之间做光滑插值:

  • 如果mu低且beta大,说明车辆接近侧滑,k2增大,让DYC更激进;
  • 如果beta小但beta_dot大,说明车正处于瞬态响应过程,k1适当增大,让4WS先跟上路径趋势;
  • 如果mu高且误差平稳,k1、k2都回到基准值,避免过度干预。

这样下层不是去替代Nash博弈,而是让Nash博弈里的“目标权重”随工况自适应,整个系统才真正有优化能力。

3. 代码逐段拆解:Nash迭代、模糊神经网络和力矩分配怎么落地

3.1 车辆模型和Nash分配函数

我在MATLAB里没有直接用Simulink自带的车辆模块,而是在S函数里写了一个二自由度模型,方便做Nash迭代。核心的车辆状态导数函数是这样:

function yDot = vehicle2DOF(y, delta_f, delta_r, Mz, p) % y = [beta; gamma] beta = y(1); gamma = y(2); vx = p.vx; Fyf = p.Cf * (delta_f - beta - p.a * gamma / vx); Fyr = p.Cr * (delta_r - beta + p.b * gamma / vx); betaDot = (Fyf + Fyr) / (p.m * vx) - gamma; gammaDot = (p.a * Fyf - p.b * Fyr + Mz) / p.Iz; yDot = [betaDot; gammaDot]; end

这里没有用完整的魔术公式轮胎模型,因为Nash迭代在每个控制周期都要预测状态,模型太重实时性扛不住。简单轮胎线性模型配合模糊神经网络补偿,效果足够接近。

Nash分配函数的核心是迭代求解:

function [delta_r, Mz] = nashAllocate(curY, ref, p, w, lastU, opt) delta_r = lastU.delta_r; Mz = lastU.Mz; for k = 1 : opt.maxIter old = [delta_r, Mz]; % 玩家1:4WS,最优响应 delta_r = fminunc(@(dd) cost4WS(dd, Mz, curY, ref, p, w), ... delta_r, opt.fminOpt); % 玩家2:DYC,最优响应 Mz = fminunc(@(tt) costDYC(tt, delta_r, curY, ref, p, w), ... Mz, opt.fminOpt); % 对迭代结果做惯性滤波,防抖 delta_r = opt.alpha * delta_r + (1 - opt.alpha) * old(1); Mz = opt.alpha * Mz + (1 - opt.alpha) * old(2); if norm([delta_r, Mz] - old) < opt.tol break; end end end

代价函数里用一步前向欧拉预测下一时刻的beta和gamma来算误差:

function J = cost4WS(delta_r, Mz, curY, ref, p, w) yNext = curY + p.dt * vehicle2DOF(curY, p.delta_f, delta_r, Mz, p); eGamma = yNext(2) - ref.gamma_d; eDelta = delta_r - curY(3); % 上一周期的delta_r J = w.q1 * eGamma^2 + w.q2 * eDelta^2 + w.r1 * delta_r^2; end

实际调用时,上一时刻的控制量要作为“暖启动”初值传进来,能让Nash迭代少算好几轮。我设过maxIter为10,一般工况三步内就能收敛,tol取1e-4,控制周期10毫秒实测能跑满。

3.2 模糊神经网络的前向计算和在线更新

模糊神经网络我采用的是常用的TS模糊神经网络结构:高斯隶属度函数、乘积推理、归一化输出。前向计算就是标准的三层结构:

function [y, phi] = fnnForward(net, x) % x = [beta; betaDot; muHat] nIn = length(x); nMF = size(net.c, 1); phi = ones(nMF, 1); for i = 1 : nMF for j = 1 : nIn phi(i) = phi(i) * exp(-0.5 * ((x(j) - net.c(i,j)) / net.sigma(i,j))^2); end end phiBar = phi / sum(phi); y = net.w' * phiBar; end

在线学习我用的是一阶梯度下降,权值更新公式很直接:

function net = fnnUpdate(net, phi, target, eta) phiBar = phi / sum(phi); y = net.w' * phiBar; e = target - y; % 后件参数修正 net.w = net.w + eta * e * phiBar; % 对隶属度中心做微调,步长通常设置得更小 for i = 1 : length(net.w) net.c(i,:) = net.c(i,:) + 0.1 * eta * e * net.w(i) * ... (x - net.c(i,:)) ./ net.sigma(i,:).^2; end end

这里有个容易忽略的点:在线学习的target不能拍脑袋定。我的做法是先用离线仿真生成一组多工况样本,把基于规则的期望权重作为teacher信号,把模糊神经网络离线训好。真正上车或上台架之后,只在原权重附近做小步长微调,learning rate取0.01,绝对不要在零基础下纯在线训练。

3.3 横摆力矩Mz到四个轮毂电机扭矩的分配

Nash博弈算出来的Mz是一个整车层面的附加横摆力矩,但发给轮毂电机的必须是四个轮端扭矩指令。我用了这样的分配方式:先通过轮距B把Mz换算成左右纵向力差,再按轴荷比例分到前后轴。

function T = torqueAllocate(Td, Mz, p) dF = Mz / (p.trackWidth / 2); FxTotal = Td / p.wheelRadius; FxLeft = (FxTotal - dF) / 2; FxRight = (FxTotal + dF) / 2; % 按前40%、后60%分配,实际项目应使用实时轴荷 T = zeros(4,1); T(1) = 0.4 * FxLeft * p.wheelRadius; T(2) = 0.4 * FxRight * p.wheelRadius; T(3) = 0.6 * FxLeft * p.wheelRadius; T(4) = 0.6 * FxRight * p.wheelRadius; % 限幅:电机峰值扭矩和路面附着力都需要限制 for i = 1 : 4 Tmax = min(p.motorPeak, p.mu * p.Fz(i) * p.wheelRadius); T(i) = max(-Tmax, min(Tmax, T(i))); end end

限幅这一个步骤看着不起眼,实际特别关键。轮毂电机响应快,如果只按Mz回路给扭矩而不做路面附着限制,控制器会在低附着路面上要求一组轮胎根本抓不住的纵向力,结果横摆力矩没形成,反而把侧向附着给占了,车辆更容易失稳。

4. 仿真和台架试验里最容易翻车的几个地方

4.1 Nash迭代结果抖动

第一次跑连续正弦转向工况时,我遇到过一个很尴尬的现象:delta_r和Mz每步都在跳,横摆角速度跟踪看着还行,但后轮转向执行器一直在高频抖动,台上听着就很不舒服。

查到最后是两个原因:一是代价函数里没有加入控制量增量惩罚,后轮转角可以自由突变;二是迭代没有完全收敛就开始输出。解决办法就是代码里的两处:增量惩罚项w.q2 * eDelta^2,以及每次迭代后的惯性滤波opt.alpha = 0.6。alpha这个值不要调太小,太小会让控制变得迟钝;0.5到0.7之间是比较好的平衡点。

4.2 模糊神经网络在线训练发散

FNN刚开始在线微调时,我遇到过跑着跑着权重修正系数突然冲到很大,直接把Nash博弈的权重顶到边界,整车控制量跟着狂抖的情况。

后来总结经验是三个错误叠加了:输入没有归一化、学习率太大、误差死区没设。beta和beta_dot的数值尺度差了十倍以上,同一个学习率对两个输入就是不合理的。现在我的处理是先把输入全部归一化到[-1, 1],学习率设在0.01,并且设一个误差死区:误差小于0.02时不做任何权值更新,防止传感器噪声把网络带偏。还要加一个L2正则项,让权值不会漂得太远。

4.3 从仿真到上车的距离,基本由轮胎附着决定

纯仿真里我把路面附着系数固定成0.85,控制效果非常理想。换到HIL里模拟积雪路面、mu突然从0.85跳到0.3的时候,Nash博弈还在按高附着模型要力矩,结果输出的附加横摆力矩远超附着极限,车辆侧偏角一路拉大。

这件事让我意识到,状态估计和FNN的输入mu_hat才是整个系统真正的天花板。mu估计得不准,后面所有优化都是白搭。所以我后来在FNN输入里加了mu_hat,并且在中层对期望横摆角速度做了更严格的限幅:gamma_max = 0.85 * mu * g / vx。限幅虽然保守,但能保证在附着突变时车辆先稳定下来再说。

4.4 4WS和DYC还是会“打架”,但打架方式变了

用了Nash博弈之后,两个执行器不会像独立控制那样同时向同一个误差狂冲,但如果权重设得不合理,它们会在均衡点上互相拉锯:delta_r一直给一个恒定的偏置,Mz则刚好用相反的符号去抵消它。这个状态从横摆角速度误差曲线上看非常小,但两个执行器都在持续出力,能耗和磨损都很差。

我最后的处理原则是:让4WS管中低频路径趋势,让DYC管高频稳定性修正。具体实现就是把4WS代价函数里的控制量增量惩罚设得大一点,限制后轮转角变化率;DYC代价函数则可以允许更高频的Mz输出,毕竟轮毂电机响应快、带宽高。这样分工之后,打架现象基本消失。

5. 关于权重标定我最后想说的话

整套方案里最花时间的其实不是Nash博弈迭代,也不是FNN训练,而是权重标定。我的流程是先把FNN停掉,用固定权重在冰雪、干沥青、湿沥青三个典型路面上分别手调基准权重,保证基础控制不发散;之后才把FNN接入,让它根据输入在基准权重附近输出0.5到2.0倍的修正系数。这个顺序写起来只有一行字,但实际占了我大概一半的调试时间。

还有一个细节分享给做台架的朋友:Nash迭代里的fminunc工具在离线仿真里很好用,但上了实时系统之后要留意优化器耗时抖动。我建议先用离线仿真把所有边界工况遍历一遍,把每个工况下Nash均衡点对应的控制量固化出来查表兜底,实时运行时再让Nash在查表结果附近做小范围搜索。这样既保留博弈的自适应性,又给实时性上了保险。

本文还有配套的精品资源,点击获取

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

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

立即咨询