ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

自动驾驶MPC控制:从预测模型到实车部署的工程实践

自动驾驶MPC控制:从预测模型到实车部署的工程实践 第一次在仿真器里跑通MPC很多人的反应都一样这算法也就那么回事给一条参考轨迹方向盘自己转跟踪误差漂亮得可以发个朋友圈。可到了实车路测抖动、超调、发飘各种问题轮流来。真正把MPC搞清楚、能稳定跑在车上其实是从放弃“背公式”开始的。MPC也就是模型预测控制在自动驾驶控制算法里的地位有点像“手自一体里的聪明自动挡”——理论不新但确实能打。它不是用来替代PID的神秘公式而是一套把预测模型、滚动优化、约束处理全部揉进一个控制器设计框架里的工程方法论。这篇文章我不打算堆公式会直接从工程视角拆MPC为什么自动驾驶要用它、预测模型怎么建、优化问题怎么解、上车之后会遇到哪些书里没写的坑。不管你是刚接触自动驾驶的学生还是已经在做路径跟踪的工程师应该都能在里面找到点能直接抄作业的东西。1. 为什么自动驾驶场景绕不开MPCPID和LQR的局限性1.1 控制量是方向盘和油门不是坐标聊MPC之前先把控制对象说清楚。自动驾驶车辆的横纵向控制输入是参考路径、参考速度、车辆当前状态输出是前轮转角、油门和刹车。横向控制的核心任务是让车辆贴合期望路径纵向控制的核心任务是精确跟住速度曲线。这里的难点不在“控制”本身而在于车辆是一个强耦合、非线性、带执行器约束的时变系统。PID的控制逻辑是经典的“反馈误差驱动”u(t) Kp·e(t) Ki·∫e(t)dt Kd·de(t)/dt也就是看到当前误差才作出反应。问题是PID不知道未来会发生什么。举一个最典型的场景车速80km/h前方是急弯参考轨迹的曲率突然变大。PID只有在横向偏差和航向角偏差真正变大之后才会逐渐加大打角力度。这个过程会产生明显的滞后车辆会往外侧飘然后再被拉回来。MPC不一样它在每个控制周期内都会“推算”未来一段时间的轨迹提前把转角做准备所以过弯动作会明显更顺、更稳。1.2 LQR虽然是最优控制但缺了“约束”这块拼图LQR线性二次调节器是自动控制原理里非常有价值的方法。它通过求解Riccati方程得到状态反馈增益矩阵K让控制量u -Kx使得线性系统中的无穷时域二次代价最小。但LQR有它的天然边界它设计的前提是“无约束”。真实车辆哪里没有约束方向盘转角有机械限位方向盘的转角速度受制于转向电机功率侧向加速度受轮胎附着极限约束正常行驶时还不希望车辆压到车道线。LQR的反馈增益是离线算好的它不会主动为这些约束作出让步。当系统接近约束边界时LQR很容易给出一个实际执行不了的指令然后由底层执行器硬削波控制的匹配质量会明显下降。MPC和LQR的差异不在“谁更优”而在“谁更会处理现实问题”。MPC在每一个控制周期都显式求解一个带约束的优化问题把机械限位、安全边界、舒适性要求全部写进数学约束里得到一组“在每个约束都不越界的前提下最优”的控制序列。1.3 三种算法的直观对比控制策略是否利用模型是否具备预测性能否处理约束计算开销典型适用场景PID基本不用/只用误差无不能极低低速简单跟踪、底层执行器闭环LQR需要线性化模型无无穷时域静态反馈不能直接处理低车辆稳定控制、简单路径跟踪MPC需要预测模型有滚动时域能较高复杂场景轨迹跟踪、约束较多的控制任务有一点需要坦白园区低速场景、平直高速公路巡航PID和LQR已经能干得很好MPC的优势不是“所有场景都碾压”。它的收益主要在“约束多、目标冲突、未来趋势明显”的复杂场景里——匝道汇入、紧急避障、大曲率过弯。换句话说MPC是一把好用的多功能刀具但不意味着每个厨房都需要它。这里也顺便说一句MPC的思想并不只属于自动驾驶石化行业的霍尼韦尔过程控制、四足机器人的姿态平衡、电机驱动控制、温度控制等领域都在用同一套“预测滚动优化”框架只是被控对象不同、模型复杂度不同而已。2. 预测模型怎么搭状态变量、车辆模型与约束表达2.1 状态量别用绝对坐标用误差模型做路径跟踪时很多新手会把车辆的世界坐标x、y当作状态量写进MPC。这当然可以但代价是优化问题里所有参数都要跟着参考轨迹做平移变换求解的数值稳定性也比较差。更常规的做法是使用“相对于参考路径的误差状态”典型的状态向量长这样x [e_y, e_ψ, v_x, r]^T其中e_y是横向偏差e_ψ是航向角偏差v_x是纵向车速r是横摆角速度。控制量u [δ, a]^Tδ是前轮转角a是纵向加速度。这样定义之后控制目标变成“把横向偏差和航向角偏差都压到0”参考路径的作用主要体现在航向角偏差微分里的曲率前馈项。低速场景下误差模型可以进一步线性化为ė_y v_x·e_ψ v_x·β ė_ψ r - κ·v_x其中β是质心侧偏角κ是参考路径曲率。这里曲线曲率是作为干扰项进入模型的MPC在预测未来状态时会把它当成已知扰动这也是MPC能“看弯”的关键所在。2.2 运动学模型还是动力学模型按速度切车辆建模有一个绕不开的分歧用运动学还是动力学。低速下比如40km/h以内轮胎侧偏角很小自行车运动学模型就能满足精度要求ẋ v·cos(θ) ẏ v·sin(θ) θ̇ (v / L)·tan(δ)这里L是轴距δ是前轮转角。运动学模型参数少、线性化后结构简单、求解快非常适合低速园区巡航、自动泊车这类场景。但车速一上来比如80km/h以上轮胎侧偏就不能忽略了。这时候需要单轨动力学模型状态里加入质心侧偏角β和横摆角速度r核心方程简化后大致长这样β̇ (C_f C_r)/(m·v_x)·β [ (C_f·l_f - C_r·l_r)/(m·v_x²) - 1 ]·r - (C_f/(m·v_x))·δ ṙ (C_f·l_f - C_r·l_r)/(I_z)·β (C_f·l_f² C_r·l_r²)/(I_z·v_x)·r - (C_f·l_f/I_z)·δ这里C_f、C_r是前后轮侧偏刚度l_f、l_r是质心到前后轴的距离I_z是整车横摆转动惯量。工程上的经验是40km/h以下运动学模型完全够用40到80km/h之间看工况普通变道和跟车时运动学加一个横摆角速度响应模型也能凑合80km/h以上尽量上动力学模型。如果车辆本身有ESP/ESC在底层做稳定性控制那么预测模型可以简化成运动学加上一个“可控的横摆角速度响应”近似这是很多量产项目的折中做法省算力且足够稳定。2.3 约束怎么写才不“作死”MPC相对LQR的核心优势之一就是约束处理但约束定义也是导致求解失败的常见原因。工程上需要的典型约束包括前轮转角机械限位δ_min ≤ δ(ki) ≤ δ_max转角变化率限制电机响应能力、防止扫膛Δδ_min ≤ Δδ(ki) ≤ Δδ_max侧向加速度限制舒适性、轮胎附着-a_y,max ≤ v_x·r(ki) ≤ a_y,max横向偏差限制不压车道线e_y,min s ≤ e_y(ki) ≤ e_y,max s最后这个式子里的s是松弛变量这个设计非常重要。我见过很多团队一开始把车道偏离做成硬约束结果在车辆已经小幅压线的瞬间QP问题直接无解控制器输出乱跳。正确做法是把“物理极限”设成硬约束转向限位、执行器极限把“安全边界”设成软约束让求解器在软约束上加惩罚项min J ... ρ·s²这样即使车辆暂时压了一点线优化问题也有解控制器会尽可能让车辆回到边界内而不是直接崩溃。这一点放到后面调参部分还会再提。2.4 预测时域N和执行周期Ts怎么定预测时域N和执行周期Ts是MPC的表层参数但决定了一个控制器的“视野长度”。预测的时间范围是T_preview N · Ts举个例子如果车速v_x 25m/sTs 30msN 20那么预测范围 25 × 0.6 15米。对高速公路工况15米足够覆盖大多数曲率变化和跟车风险但在90km/h下如果需要更早感知前方弯道就要适当加大N。经验上N取15到30比较常见Ts取20到50ms。N过小像近视眼前方信息看不远N过大模型误差在长时域里累积导致预测不可信而且计算量随N增长非常快后面讲实时求解时会细说。低速蠕行时车辆每周期移动距离很短N可以适当减小几米的预测视野就够用。3. 滚动时域优化的完整机制预测、求解、再校正3.1 单个控制周期里发生的事情MPC的每个控制周期可以拆成四步读取当前车辆状态x(k)包括横向偏差、航向角偏差、车速、横摆角速度等基于预测模型从当前状态出发推算未来N步的状态轨迹求解一个带约束的优化问题得到最优控制序列u(k), u(k1), …, u(kN-1)只把第一步u(k)发送给执行器下一周期重复以上全部步骤。这四步合起来就是“滚动时域优化”英文叫Receding Horizon Control。它的精髓不是算一次管一辈子而是每20到50毫秒就把未来的计划重新算一遍永远用最新状态校正控制方向。3.2 为什么“只执行第一步”很多第一次接触MPC的人会问既然已经算出了未来N步的最优序列为什么不全执行完再重新算答案很简单模型不准世界在变。预测模型不可能100%还原真实车辆。轮胎侧偏刚度会随胎压和载荷变化风阻随车速变化地面附着系数因为雨天而下降。如果一次求解就把N步控制量全部发给执行器这些模型误差和外界扰动会一路累积控制品质会直线下降。只执行第一步然后用下一周期的真实状态重新求解等于给系统加了一个“每30ms校正一次”的反馈环这是MPC鲁棒性的重要来源。3.3 代价函数权重设计就是第一轮调参MPC的目标函数一般写成J Σᵢ₌₁ᴺ ( w_y·e_y²(ki) w_ψ·e_ψ²(ki) )Σᵢ₌₀ᴺ⁻¹ ( w_δ·δ²(ki) w_Δδ·Δδ²(ki) )ρ·s²四个权重各有各的脾气w_y横向偏差权重决定“回到中心线”的决心。给太小会让车辆贴在车道边缘滑行给太大会导致过弯时疯狂向内侧修正表现为车辆画龙。w_ψ航向角偏差权重影响车辆姿态是否顺滑。单独调w_y不够加上w_ψ之后车辆的横摆回正会更克制减少超调。w_δ控制幅值权重影响打角力度。取太大会导致转向太肉弯道里跟不上轨迹。w_Δδ控制变化率权重影响方向盘抖振。这个权重一般要大于w_δ因为工程上最怕执行器频繁反向打角既伤硬件又让乘坐体验很糟糕。个人调试时常用的参考量级是w_y 80w_ψ 20w_δ 0.5w_Δδ 2ρ 1000。但这些数值跟状态量纲、预测模型线性化方式强相关不要直接抄重点是看相对量级——横向偏差权重要远大于控制量权重控制变化率权重要大于控制幅值权重。调参顺序也有讲究先把预测时域和模型固定住只调Q、R、S每组权重至少要跑完一个包含直线、弯道、变道的完整工况再下结论不要只看一个场景就断言“这组参数不行”。3.4 MPC解出来的是什么一组控制序列也是一个局部计划从传统控制论角度看MPC的输出是控制量u(k)但从轨迹规划角度看预测出来的状态轨迹本身就是一条“局部计划”。现在很多工程方案把MPC横向控制和速度规划合并进同一个优化问题状态里同时包含位置、速度、加速度输出同时包含转角和加速度指令这样能保证横向动作和纵向加减速互相协调避免转过头的同时猛加速这类低级错误。这种扩展被称为“轨迹规划MPC”是自动代客泊车、城市领航等场景的主流选择之一。4. 实时求解与代码工程从几十毫秒压到几毫秒4.1 在线求解的本质一个带约束的二次规划预测模型固定、目标函数是二次型、约束是线性不等式时MPC每一步求解的数学问题就是一个带约束的二次规划写成标准形式是min (1/2)·zᵀ·H·z fᵀ·z s.t. l ≤ A·z ≤ u这里的z是包含未来控制量和松弛变量的决策向量。H矩阵来自目标函数的二次项A矩阵来自预测模型的展开l和u是上下界。H、A的规模和结构决定了求解难度这也是为什么看MPC论文时经常看到这些符号。4.2 求解器怎么选通用QP还是代码生成求解器算法类型开源特点适合场景OSQP一阶迭代法是实现简单鲁棒性好中等规模快原型验证、快速二次开发qpOASES活动集法是热启动效果好小规模快嵌入式小规模QPACADOS实时代码生成SQP/RTI是把模型编译成高度优化C代码紧凑高效嵌入式ARM、非线性MPCFORCES Pro代码生成内点法商用针对嵌入式极致优化内存占用低量产项目、安全关键场景如果是课程设计或项目原型OSQP已经够快。但量产项目里我更推荐使用ACADOS这类“代码生成型”工具优化问题在部署前就被编译成专用C代码没有通用求解器那么多分支判断内存布局完全静态化实时性非常稳定。实测参考状态量4、控制量2、N20的线性MPC在普通工控机上OSQP大概2到4ms求解一次同样的工况用ACADOS代码生成后可以做到0.5到1.5ms。不同CPU型号、是否开多核、问题尺度都会影响数字但量级差异是真实的。4.3 一个可以快速跑通的工程套路用ACADOS搭MPC的路线大致分五步使用CasADi符号框架定义连续动力学模型也就是ẋ f(x, u)选择离散化方式比如多重打靶法Multiple Shooting或直接配点法Direct Collocation配置目标函数权重和约束边界生成C代码编译链接到自己已有的控制程序里在每个控制周期内读取传感器状态 - 调用求解器 - 把最优解的第一步下发到执行器。一个极简的示意片段伪代码维度# 定义动力学 x_dot casadi.SX.sym(x_dot, 4) x_dot f(x, u) # 车辆误差模型或动力学模型 # 配置ACADOS ocp acados_ocp() ocp.set_model(x_dot) ocp.set_cost(w_y, w_psi, w_delta, w_ddelta) ocp.set_constraints(delta_min, delta_max, e_y_max) # 生成C代码 acados.generate_c_code(ocp) # 每个控制周期 solution acados_solve(current_state, reference_path) steer_cmd solution[u0]真正量产时控制程序一般用C开发ACADOS生成的是纯C代码集成起来很顺。注意别在控制循环里频繁创建和销毁对象所有内存最好在初始化阶段一次性分配好。4.4 压缩实时性的几个改动热启动把上一周期的最优解作为本次迭代的初始猜测迭代次数能明显下降这是最便宜也最有效的优化手段。固定迭代次数不求每次都收敛到最优固定30到50次迭代就退出。实时控制最忌迭代时间忽长忽短宁可次优也不允许偶尔超时。稀疏结构利用MPC展开后的QP矩阵是带状稀疏结构使用稀疏线性代数库能省掉大量无效乘零运算。避免动态内存分配嵌入式环境里new、malloc这类调用尽量别出现在控制循环中全部用启动时预分配的固定缓冲。传感器滤波别过度低通滤波会引入相位延迟MPC对状态的“新鲜度”比噪声更敏感滤波深度要克制。5. 实车部署最难受的三个问题模型失配、延迟和调参5.1 模型失配仿真能跑上车发飘仿真里MPC表现很好一上车就发飘这是最常见的“翻车”现场。原因十有八九是模型失配低速运动学模型被拿去做高速工况轮胎侧偏刚度参数离真实值太远或者车辆载重变化导致质心位置偏移预测模型从一开始就不准。处理的手段按优先级排列离线参数辨识扫阶梯转向输入记录横摆角速度和侧向加速度响应估算轮胎刚度和轴距等关键参数。这个步骤本质上是给模型“称重”值得做。在线误差补偿在MPC外部加一个误差积分项把“真实状态-模型预测状态”的偏差负反馈进预测起点相当于给模型安装一个随动校正器。限制运行域当车辆状态超出模型适用边界时切换到更保守的控制策略。这比让MPC在模型失配区硬撑要理智得多。5.2 执行器延迟MPC预测失真的最大敌人MPC的预测基于“这一步指令立即生效”的假设。但真实车辆的转向执行器从指令到真正转到目标角度中间有响应延迟电子助力转向系统普遍存在100到200毫秒的固有响应滞后制动系统的建压过程更是明显。如果有200ms延迟而预测模型假设为零延迟车越快预测误差越大。工程上常用的补偿思路有三种Smith预估器思想预测模型里把当前状态外推d步用“未来状态”作为反馈进入求解器相当于把时间轴对齐到执行器真正开始动作的时刻。显式延迟建模把执行器行为当作一阶惯性环节写进预测模型比如δ_dot (1/τ_delay)·(δ_cmd - δ)。这样求解器自然会把延迟纳入优化考量。相位超前补偿对控制序列做一定程度的提前处理。这是最常见的土办法但要注意别让超前量超出执行器物理能力否则会被饱和抵消反而更糟。5.3 时间戳和零点标定容易被忽视的坑MPC的反馈来自多个传感器GPS/组合惯性导航给出位置和航向IMU给出横摆角速度底盘CAN总线给出车速和转角。这些信号各自有自己的采样时刻。如果时间戳没对齐控制器拿到的“当前状态”实际上是几个不同时刻的状态拼在一起横向偏差和航向角偏差互相矛盾MPC就会像个拿着过时地图导航的人一直在修方向。这个问题没有高深的解法就是在控制器前面加一层时间对齐模块用外推或插值把所有状态统一到同一个参考时刻。另一个常被忽略的是转向零位标定如果方向盘角度传感器零位偏了0.5度高速行驶时横向偏差会缓慢漂移MPC权重再大也救不回来因为它在用错误的零点持续修正。5.4 一个我自己验证过的调参顺序供你逐步复现调MPC最忌讳一步到位我建议按下面的顺序来第一步低速直线跟踪车速压在5m/s以下给非常宽松的约束只保留w_y明显大于其他权重先确认控制器不振荡、能收敛。发散就先查模型和反馈状态不要急着调权重。第二步加入w_ψ观察车辆过弯后的回正行为。如果横向超调明显说明航向角偏差惩罚不够如果车辆回应显得迟钝说明w_ψ偏大。第三步加入Δδ惩罚跑连续变道工况看方向盘是否有高频抖振。如果打角很频繁把w_Δδ往上抬直到动作平滑。第四步收紧约束把道路边界约束从软约束开始逐渐收紧到真实允许范围同时观察求解器是否偶尔出现无解日志。出现无解就继续增大ρ或放宽软约束上限。第五步提高车速10m/s、20m/s逐级往上升确认模型适用边界。一旦出现明显滞后或发飘不是权重问题而是模型该换成动力学版本了。最后说点个人体会。MPC的理论门槛没有网上说的那么高真正吃时间的是模型标定、延迟补偿和权重匹配这三件事。我见过太多人把权重翻来覆去调了一整天最后发现问题是反馈状态的时间戳差了100ms也见过参数看起来很差但把执行器延迟模型加进去之后突然就稳了。如果你正在被某个MPC问题卡住先别怀疑权重先回去把模型和状态质量检查一遍。
返回列表