第1章:求解器选型与对比——OSQP、ACADO、qpOASES、FORCES Pro

做MPC落地,第一步就是选求解器。

说实话,我见过太多人一上来就调参数、写代码,结果到硬件上一跑,要么内存爆了,要么算力不够。嗯,选错求解器,后面全是坑。

1.1 为什么求解器这么重要?

MPC的核心,说白了就是在线求解一个优化问题。你想想看,控制器每走一步,都要解一次带约束的二次规划(QP)。这个求解过程,就是整个系统的瓶颈。

我个人习惯,先把求解器分两类:

  • 通用型QP求解器:OSQP、qpOASES、FORCES Pro
  • 专用型MPC求解器:ACADO、MATLAB MPC Toolbox

通用型更灵活,但需要你自己搭MPC框架。专用型上手快,但定制空间小。怎么选?看你的硬件资源。

核心原则:求解器的计算复杂度,必须小于你的控制周期。比如你控制周期是1ms,那求解时间必须小于1ms。否则,系统就崩了。

1.2 四大求解器横向对比

我直接上干货。这四款求解器,我都在项目里用过。咱们一个一个说。

求解器 算法核心 适用场景 硬件要求 开源?
OSQP ADMM(交替方向乘子法) 大规模稀疏QP,嵌入式 低(ARM Cortex-M可跑) 是(Apache 2.0)
ACADO 多重打靶 + 序列二次规划 非线性MPC,快速原型 中(需要浮点运算单元) 是(GPL)
qpOASES 主动集法(热启动) 小规模QP,实时性要求高 低(代码量小) 是(LGPL)
FORCES Pro 内点法 + 代码生成 工业级,高可靠性 中高(需要商业许可) 否(商业软件)

1.3 逐个拆解:我的实战经验

OSQP——嵌入式首选

OSQP是我个人最常用的。为什么?因为它用ADMM算法,说白了就是迭代快,而且对内存极度友好。

我在一个STM32H7的项目里,控制周期是5ms,状态量12个,控制量4个,预测时域20步。OSQP跑一次求解,平均只要1.2ms。还有余量。

但要注意:ADMM收敛慢,精度要求高的时候,迭代次数会上去。我曾经遇到过,为了达到10^-6的精度,迭代了200多次,直接超时。后来我把精度降到10^-4,问题就解决了。

避坑指南:OSQP的默认容差是10^-3,对于大多数MPC场景已经够用。别盲目追求高精度,够用就行。

ACADO——快速原型利器

ACADO适合做算法验证。它把MPC的整个流程都封装好了,你只需要定义模型和约束,它自动生成C代码。

我记得有一次,客户要求48小时内出一个非线性MPC的demo。我用ACADO,从建模到生成代码,只用了半天。剩下的时间都在调参数。

但ACADO生成的代码体积偏大,大概在200KB左右。如果你用的是Cortex-M0这种小芯片,可能放不下。

qpOASES——小而美

qpOASES的代码量非常小,核心求解器只有几千行。它用主动集法,特别适合小规模问题(变量少于50个)。

我有个同事,在DSP28335上做电机控制,用的就是qpOASES。控制周期100μs,变量只有6个,跑起来毫无压力。

不过,qpOASES对矩阵条件数敏感。如果你的Hessian矩阵病态,求解会失败。嗯,我吃过这个亏,后来加了正则化才解决。

FORCES Pro——工业级选择

FORCES Pro是商业软件,贵,但真香。它用内点法,稳定性极高。而且它支持代码生成,生成的代码是高度优化的,几乎没有冗余。

我在一个汽车电子的项目里用过FORCES Pro。客户要求功能安全,必须通过ISO 26262认证。FORCES Pro提供了认证包,省了我大量时间。

但价格嘛...一套license要几万美金。小团队慎入。

1.4 如何根据硬件选型?

选型其实就三步:

  1. 算力评估:你的CPU主频多少?有没有FPU?
  2. 内存评估:RAM多大?Flash多大?
  3. 实时性要求:控制周期是多少?允许的最大延迟是多少?

我画了个流程图,帮你快速决策:

求解器选型决策流程图 开始选型 CPU主频 > 200MHz 且有FPU? RAM > 64KB 且 Flash > 256KB? 控制周期 < 1ms? OSQP qpOASES FORCES Pro 或 ACADO

简单总结一下:

  • 资源紧张(Cortex-M0/M3,RAM < 32KB):选qpOASES,代码量小,内存占用低
  • 资源中等(Cortex-M4/M7,有FPU):选OSQP,灵活且高效
  • 资源充裕(ARM A系列,Linux系统):选FORCES Pro或ACADO,功能强大
  • 工业级需求(功能安全、高可靠性):直接上FORCES Pro,省心

警告:不要只看算力,还要看内存带宽。我曾经在i.MX6上跑OSQP,CPU占用只有30%,但内存带宽打满了,导致求解时间波动很大。后来用了内存池优化才解决。

1.5 我的选型清单

最后,我列个清单,你照着检查就行:

  1. 问题规模:状态量、控制量、预测时域分别是多少?
  2. 约束类型:是线性约束还是非线性约束?
  3. 硬件平台:MCU还是MPU?有没有FPU?
  4. 实时性:控制周期是多少?允许的最大抖动是多少?
  5. 开发周期:是快速原型还是产品落地?
  6. 预算:有没有钱买商业求解器?

把这六条过一遍,选型就不会出错。

我的建议:如果你刚开始做MPC,先用OSQP搭个原型。等验证通过了,再根据性能瓶颈决定要不要换求解器。别一上来就上FORCES Pro,万一项目黄了,license钱就白花了。

专注资料整理