☰
二自由度模型+MPC车道保持:从动力学到QP求解的工程实践
2026/10/29 12:11:56 网站建设 项目流程

简介:面向汽车工程专业学生、自动驾驶研发人员与控制系统工程师的MPC横向控制实践资料,聚焦二自由度车辆动力学建模、轨迹跟踪与车道保持的Simulink实现,帮助读者理解预测时域、控制时域与权重矩阵等关键参数的整定逻辑。压缩包共1个PDF文件,约114KB,内容围绕状态方程线性化、MPC控制器搭建、执行器饱和限制以及单移线工况仿真展开,并附有调参经验与常见问题排查思路,便于对照复现与二次开发。已有62人学习,适合作为入门MPC车辆横向控制的参考材料,读者可从中获取从动力学方程到控制器验证的完整链路认知,理解模型假设的有效范围及其对控制效果的影响,并在精度与计算开销之间寻找平衡。

1. 二自由度模型凭什么撑起一套车道保持控制器

方向盘突然传来一阵细微震动,车道保持系统正在和物理极限较劲。很多人第一次看到「二自由度车辆模型」都会犯嘀咕:真车有悬架、有侧倾、有载荷转移,凭什么砍到只剩侧偏角和横摆角速度两个状态,还能把轨迹跟踪做稳?反直觉的地方在于,MPC 要的从来不是一个高保真数字孪生,而是一个「预测误差可控、求解速度够快」的线性预测模型。二自由度模型恰好卡在这个甜点上:它保留了横向动力学最核心的耦合关系,又把状态维度压到控制器一个控制周期内能解完 QP 问题的程度。搞懂这套模型预测控制为什么能在简化模型上 work,比背十个调参口诀有用得多,也是理解轨迹跟踪、车道保持这类横向控制问题的起点。

2. 二自由度动力学:两个状态方程怎么描述一台车

2.1 状态量选取:为什么是侧偏角和横摆角速度

把车放在平面上看,最朴素的描述是「车往哪走、车头朝哪」。但横向控制真正关心的是车相对道路的姿态偏差,于是状态量通常选质心侧偏角 β 和横摆角速度 r。β 描述车身速度方向与车头朝向的夹角,r 描述车身绕垂直轴的旋转快慢。这两个量直接决定了轮胎侧偏角,而轮胎侧偏角又决定了侧向力,闭环就成立了。

常见的实现思路是把动力学方程写成状态空间形式 ẋ = Ax + Bu,其中 u 是前轮转角 δ。下面这段是输入里给出的核心方程,我按机制拆开注释:

function dx = vehicleModel(t, x, u) % 参数区 m = 1573; % 整备质量(kg) lf = 1.4; % 前轴到质心距离(m) lr = 1.7; % 后轴到质心距离(m) C_alpha = 80000; % 轮胎侧偏刚度(N/rad) beta = x(1); % 质心侧偏角 r = x(2); % 横摆角速度 dx = zeros(2,1); % dβ/dt:侧向力合力除以质量,再减去横摆带来的附加项 dx(1) = (-(C_alpha*(lf+lr)/(m*(lf+lr)^2)))*beta + ... ((C_alpha*(lr^2 - lf*lr)/(m*(lf+lr)^2)) - 1)*r + ... (C_alpha*lf/(m*(lf+lr)^2))*u; % dr/dt:前后轴侧向力对质心的力矩之和除以转动惯量 dx(2) = (-(C_alpha*(lf+lr)/((lf+lr)^2)))*beta + ... (-(C_alpha*(lf^2 + lr^2)/((lf+lr)^2)))*r/(Iz) + ... (C_alpha*lf/((lf+lr)^2))*u/Iz; end

第一行里那个-1是容易被忽略的细节:横摆角速度本身会让速度矢量方向转动,所以 β 的变化率里必须扣掉 r 这一项,否则低速时模型会给出「车头转了但车身没跟上」的错误预测。第二行里Iz是横摆转动惯量,输入里没在参数区显式给出,实际建模时一般取 2500~3000 kg·m² 量级,这个值直接决定横摆响应的快慢,填错会让 MPC 的预测轨迹整体偏软或偏硬。

2.2 线性化假设:轮胎侧偏刚度为什么能当常数

上面方程成立的前提是轮胎侧向力与侧偏角成正比,即 Fy = C_alpha · α。真实轮胎在侧偏角超过 4~5 度后进入非线性区,侧向力饱和甚至回落。输入里提到「方向盘转角超过 ±25 度后轮胎就进入非线性区」,本质就是前轮转角经几何关系换算后,轮胎侧偏角越过了线性边界。

所以这套模型的有效域是有明确边界的:小侧偏角、中低速、准静态工况。MPC 之所以还能用,是因为它在每个控制周期都用当前状态重新线性化一次,把工作点附近的局部线性模型喂给 QP 求解器。这属于「沿轨迹线性化」的思路,不是拿一个固定线性模型打天下。理解这一点,后面看到「高速下出现周期性振荡」就不会觉得是玄学,而是线性假设失效后的必然结果。

2.3 从连续到离散:c2d 这一步为什么不能省

控制器在数字系统里跑,预测模型必须是离散的。输入里给了一段状态空间离散化代码:

A = [0, 1, 0, 0; 0, -(Cf+Cr)/(m*vx), (Cf+Cr)/m, -(a*Cf - b*Cr)/(m*vx); 0, 0, 0, 1; 0, -(a*Cf - b*Cr)/(Iz*vx), (a*Cf - b*Cr)/Iz, -(a^2*Cf + b^2*Cr)/(Iz*vx)]; B = [0; Cf/m; 0; a*Cf/Iz]; C = eye(4); D = zeros(4,1); sys_cont = ss(A,B,C,D); sys_disc = c2d(sys_cont, Ts); % Ts = 0.1 秒

这里扩成了四状态,多出来的两个是横向位置和航向角,方便直接算道路坐标系下的偏差。c2d默认用零阶保持器,物理含义是「一个采样周期内控制量保持不变」,这和真实执行器的行为一致。如果跳过离散化直接把连续矩阵塞进 MPC,求解器会按连续时间推演预测,仿真步长和预测步长对不上,轻则跟踪滞后,重则 QP 无解。输入里说「连续系统直接怼进 MPC 仿真速度掉到 0.5 倍速」,根子就在这里:求解器在和一个时间尺度错位的模型较劲。

3. MPC 控制器:预测、滚动优化与 QP 求解的完整链路

3.1 预测矩阵构造:kron 展开背后的状态推演

MPC 的核心动作是:以当前状态为起点,假设未来 N 步控制量已知,把未来 N 步状态全部用当前状态和控制序列表示出来。输入里用kron快速拼预测矩阵,这是工程上很常见的写法:

function delta = MPC_Controller(x0, refTraj) [A, B] = calcAB(x0); % 在当前工作点线性化 Q = diag([10, 1]); % 状态权重:横向偏差重罚,横摆角速度轻罚 R = 0.1; % 控制量权重 N = 10; % 预测步长 % 构造 QP 的 Hessian 与线性项 H = blkdiag(kron(eye(N), Q), R*eye(N)); f = zeros(size(H,1),1); % 等式约束:把状态递推关系写成 Aeq * z = beq Aeq = [kron(eye(N), A) - eye(N*size(A,1)), kron(eye(N), B)]; beq = -A*x0; options = optimoptions('quadprog','Display','off'); sol = quadprog(H, f, [], [], Aeq, beq, [], [], [], options); delta = sol(end-N+1); % 只取第一个控制量,滚动优化 end

kron(eye(N), A)的作用是把单步状态转移矩阵沿预测时域复制成块对角结构,-eye(N*size(A,1))则把「下一时刻状态」和「当前时刻状态」的差值关系摆正。beq = -A*x0把初始状态作为已知量移到等式右边。求解完只取sol(end-N+1),也就是控制序列的第一个元素,下一周期重新测量、重新求解,这就是滚动时域的本质。参数上,Q 比 R 大一个量级,说明设计意图是「宁可多打方向盘也要压住轨迹偏差」,安全优先于执行器舒适性。

3.2 权重矩阵:Q 和 R 到底在惩罚什么

Q 惩罚状态偏差,R 惩罚控制量。输入里提到「Q 对角线给横向偏差和横摆角偏差加 10 倍权重,R 设 0.1 防止方向盘抽风」,还给了[10, 5, 0.1]这种对角配置。机制上,Q 越大,控制器越愿意用大幅控制动作去消除偏差,响应快但容易过冲;R 越大,控制动作越保守,平顺但跟踪滞后。

一个血泪经验是:Q(1,1) 也就是横向偏差权重,调太大反而导致转向延迟。原因是过大的偏差惩罚会让 QP 在约束边界附近频繁切换活跃集,求解器给出的解在相邻周期之间跳变,表现出来就是方向盘先愣一下再猛打。输入里建议从 [5, 20] 区间试,这个范围是合理的起点,但真正决定成败的是它和预测时域 N 的配比,而不是绝对值本身。

3.3 约束与饱和:把物理极限写进数学问题

MPC 相对 PID 最大的结构性优势,是能把执行器和物理约束显式写进优化问题。输入里给了两处约束写法:

% 执行器饱和:方向盘转角限幅 set_param('mpc_lka/SteeringActuator', 'UpperLimit', '25*pi/180'); set_param('mpc_lka/SteeringActuator', 'LowerLimit', '-25*pi/180'); % 状态软约束:侧偏角限制,防止进入轮胎非线性区 % -5*pi/180 < beta_k < 5*pi/180

第一处是硬约束,直接卡执行器输出,防止控制器给出物理上打不到的角度。第二处是状态约束,把「轮胎别进非线性区」翻译成 β 的上下界。实际工程里这类状态约束通常做成软约束,加松弛因子,否则一旦初始状态已经在约束外,QP 直接无解,控制器输出会掉到默认值,车就真的画龙了。输入里说「加个松弛因子就像给控制器吃了镇定剂」,说的就是这个机制:允许约束以一定代价被短暂违反,保证问题始终可行。

4. 坐标系与执行器:那些让仿真突然发疯的细节

4.1 Frenet 坐标转换:弯道发疯的根因

输入里有一段 C 代码,专门提醒坐标系转换:

for(int i=0; i<PH; i++){ // 注意这里用的是相对道路坐标系 road_frame_error = transform_to_frenet(car_state, ref_path[i]); cost += Q[0]*road_frame_error.ey * road_frame_error.ey; cost += Q[1]*road_frame_error.epsi * road_frame_error.epsi; }

ey是横向偏差,epsi是航向偏差,两者都必须在道路坐标系(Frenet 系)下计算。如果偷懒用惯性系下的绝对位置做差,直道上看起来没问题,一进弯道,参考点的切线方向在变,误差的定义就跟着漂,控制器会朝着一个错误的方向修正。输入里说「有工程师忘记转换,测试时车子画出毕加索风格的轨迹」,这不是夸张,是坐标系错位后的典型表现。判断方法很简单:直道正常、弯道发散,优先查坐标变换。

4.2 执行器建模:理想线性转向和真实 EPS 的差距

输入里提到「把转向执行器模型从理想线性改成带速率限制的,更贴近真实 EPS 系统」。理想线性模型假设指令下去角度立刻到位,真实电动助力转向有电机响应延迟和速率上限。MPC 预测时如果按理想执行器算,会低估实际跟踪滞后,导致在曲率突变点抖动。加一个一阶惯性环节或速率限制模块,预测模型和真实被控对象的一致性提升,抖动会明显缓解。这也是为什么输入里说「在动力学模型里加个饱和限制,比在控制器里叠十层约束都有用」——被控对象建模的保真度,往往比控制器参数更决定上限。

4.3 预测时域与控制时域:精度和算力的拉锯

输入里给了两组配置:预测时域 10 步、控制时域 5 步,以及预测时域 20 步。机制上,预测时域越长,控制器看得越远,对曲率变化的预判越充分,但 QP 问题的变量数线性增长,求解时间上升。输入里说「从 10 步调到 20 步,振幅减小但 CPU 占用率飙升 50%」,这是典型的精度换算力。

控制时域小于预测时域,是工程上的常规操作:只优化前几步控制量,后面假设控制量保持不变,既减少决策变量,又避免远端的控制决策因为模型误差而失真。输入里还提到一个反直觉现象「增大控制时域反而恶化跟踪性能」,原因通常是预测模型和真实车辆之间存在未建模动态(比如侧倾),控制时域一长,控制器就开始对模型误差做过度补偿。

5. 避坑与排查:五条来自仿真现场的记录

5.1 现象:直道稳、弯道画龙

原因:代价函数里的偏差在惯性系下计算,没有转到道路坐标系,弯道处参考切线方向变化导致误差定义漂移。 解决:所有ey、epsi统一在 Frenet 系下算,参考路径每个预测点都要做一次投影变换,别只在起点转一次。

5.2 现象:QP 求解器偶发报无解,控制器输出归零

原因:状态硬约束(如 β 限幅)在初始状态已越界时不可行,或者执行器饱和约束和状态约束互相打架。 解决:状态约束改软约束加松弛因子,松弛项权重设得比 Q 大一个量级,保证「尽量不违反,但违反时问题仍可解」。

5.3 现象:车速提到 80 km/h 后出现周期性振荡

原因:轮胎线性区假设在高速大转角下失效,预测模型给出的侧向力和真实值偏差变大,闭环增益实际变高。 解决:短期在 Q 里给横摆角速度加惩罚项压住振荡,长期升级到带非线性轮胎或三自由度模型,并在约束里收紧侧偏角上限。

5.4 现象:方向盘在稳态附近高频小幅抖动

原因:控制量权重 R 太小,或者 QP 活跃集在相邻周期反复切换,解不连续。 解决:适当增大 R,或在目标函数里加控制量变化率惩罚项(Δu 惩罚),让相邻周期的控制指令平滑过渡。

5.5 现象:仿真步长改小后跟踪反而变差

原因:离散化用的 Ts 和 Simulink 求解步长不一致,预测模型的时间尺度和仿真时间尺度错位。 解决:c2d的 Ts 必须和控制器采样周期严格一致,仿真求解器用固定步长,步长取 Ts 的整数分之一。

6. 设计取舍:简化模型、约束与实时性之间的那条线

这套方案最值得琢磨的地方,不是某个参数怎么调,而是它做了一连串明确的取舍。二自由度模型放弃了侧倾、载荷转移和轮胎非线性,换来的是每个控制周期内 QP 可解、可预测、可解释;线性化放弃了全工况精度,换来的是凸优化问题的全局最优性;软约束放弃了「绝不越界」的绝对保证,换来的是问题始终可行。每一条都是拿精度换实时性和鲁棒性,而 MPC 的价值恰恰在于这些取舍是显式的、可调的,不像 PID 那样把矛盾藏在几个增益里。

验证一套控制器是否真的 work,我一般不看单移线工况的最大偏差那一个数字,而是看三件事:预测轨迹和实际轨迹在时域上的贴合度、约束活跃集切换的频率、以及车速和路面附着变化时误差的单调性。如果预测线在动画里集体「折腰」,说明约束太紧;如果活跃集每周期都在跳,说明权重配比让求解器在边界上反复横跳。这些现象比任何单一指标都更能说明问题。

从那以后我每次搭 MPC 模型,都强制先把被控对象的有效域和约束边界写清楚,再动权重——因为翻车从来不是因为参数不够玄,而是因为模型假设早就悄悄失效了。希望帮到你。

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

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

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

立即咨询