Matlab MPT工具箱:多参数规划与显式MPC实战指南
2026/9/2 10:34:53 网站建设 项目流程

简介:Matlab MPT工具箱MPT3.2.1稳定版资源,面向控制、优化与计算几何方向的工程师、科研人员和学生,可用于参数优化、多面体运算、Voronoi图及模型预测控制(MPC)建模与仿真。压缩包共2000个文件,主体是2081个m函数源码,另有1451张示意图、269个html离线帮助页面、46个mexw64动态库,以及mdl模型、mat数据、pdf文档、txt说明和C源码等,既能查看算法实现,也能直接调用运行;整体仅13.61MB,便于在学习中快速部署对照。资源附带的帮助文档覆盖全部函数,多个实例覆盖约束型MPC设计、混合系统建模、几何集合运算等典型场景,并包含底层C源码与编译好的mex接口,可逐层研读求解器机制,也方便二次开发与排错。已有4058人学习,适合从MPT入门到进阶系统学习、需要将预测控制或计算几何方法落地到科研与工程项目中的读者。 做控制、优化或者把规划问题落地成实时算法的朋友,应该都搜过这样一个词组:Matlab MPT工具箱。MPT,Multi-Parametric Toolbox,多参数规划工具箱,做显式模型预测控制(explicit MPC)和分段仿射系统分析时几乎绕不开它。MPT3.2.1这个版本,是2019年更新的稳定版,自带帮助文档和一批demo例子,直到现在我电脑上都在用。它解决的最大痛点,是把“参数变化下的优化问题”一次性离线算完,实时运行时只需要做查表和仿射计算。适合正在做MPC落地方案、研究多参数规划,或者需要算多面体、可达集、不变集的工程师和研究生。这篇文章不打算按官方文档抄一遍,只写我实际使用下来的经验:怎么装、怎么用、怎么把核心流程跑通。

1. MPT3.2.1是什么,以及它凭什么能干活

1.1 多参数规划:把所有最优解一次算完

MPT的核心并不只是“画个分区图”,而是解决一类带有参数θ的数学规划问题:

min f(x, θ) s.t. g(x, θ) ≤ 0

这里的θ是优化参数,在实际系统中对应参考输入、车辆位置、电池SOC、负载力矩等。传统做法是每来一组θ就算一次优化,实时性不够。多参数规划的做法是,把θ当作变量一起处理,一次性把参数空间分成多个多边形区域,并在每个区域给出最优解x*(θ)的显式表达式,通常是affine函数。运行时只需要判断当前θ落在哪个区域,代入公式即可。

这里给个类比:不考虑多参数规划,相当于每次想外出都打开地图重新规划一次路径;多参数规划,相当于提前把整个城市道路分区建好索引,实际开车只需要按区号查表。前者灵活但慢,后者快得可以塞进微控制器。

MPT3把这个过程标准化成:你只需要提供约束矩阵和参数矩阵,调用mpt_mplp或mpt_mpqp,它会自动完成参数空间划分、区域合并、函数表达式计算。3.2.1内部用的是Polyhedron几何对象和一套数值稳定的几何计算库,这也是它能被大量论文引用的原因。

1.2 三个不可替代的典型场景

第一类场景是显式MPC。采样周期短到毫秒级的控制任务,比如电力电子变换器、气动执行机构,在线优化根本跑不完,利用MPT离线生成分区控制律,在线查表就行,实时性能提升非常明显。

第二类是PWA(分段仿射)系统建模分析。动力电池、摩擦系统、非线性饱和,很多模型天然是分段的,MPT提供了pwaSys对象来构造和仿真这类系统,做系统辨识后的分段验证也顺手。

第三类是多面体几何计算。算不变集、可达集、安全性验证时,Polyhedron对象的交、并、极点和体积计算几乎是标配。很多论文里的“吸引域”示意图就是用MPT画的,颜色分区图一出来,整个控制律的几何结构就很直观了。

1.3 为什么大家找的是3.2.1而不是最新版

MPT3相比MPT2是完全重构的。MPT2的多面体对象叫polytope,数值稳定性一般;MPT3改用Polyhedron,底层几何运算稳健很多,也支持多参数LP/QP/MILP的求解。3.2.1是2019年的稳定版,API成熟,demo齐全,网上资料也集中在这一版。

后来的版本虽然也修复了一些问题,但在某些Matlab版本上反而会碰到奇怪的兼容性,所以很多课题组默认都压在3.2.1。我自己也是从MPT2时代一路用过来,换到MPT3之后,最直观的感受是对象属性设计统一了,以前那些不好记的命令基本都被类方法取代,用起来顺手得多。

2. 安装配置实操:从下载到第一个demo运行

2.1 下载与依赖项准备

MPT3.2.1可以从官方GitHub仓库或MathWorks File Exchange下载zip,解压后是一个以mpt3开头的文件夹。解压路径我强烈建议放在纯英文路径下,比如D:\Tools\mpt3。遇到过不少人因为用户名是中文,或者路径里有中文,导致mex编译失败和绘图报错,这不是功能问题,是编码问题。

依赖项方面,MPT3本身不自带求解器,需要外部配置。我整理了一个表,照着确认就行:

依赖项用途是否必需
YALMIP问题建模与求解接口必需
GLPK等LP/QP求解器参数规划内部求解必需
MATLAB Optimization Toolbox提供quadprog等备选求解器可选
Gurobi/MOSEK大规模问题加速可选

我的建议是:如果只是跑demo和一般研究,装YALMIP加GLPK就够。如果后面要算大规模显式MPC,再考虑Gurobi。装YALMIP的方式也很简单,下载后同样addpath到搜索路径即可,它和MPT3没有冲突。

2.2 安装步骤

第一步解压,第二步在Matlab里配置路径:

addpath(genpath('D:\Tools\mpt3')); savepath;

如果之前装过MPT2或旧版MPT3,注意先移除旧路径再添加新路径,防止类名冲突:

rmpath(genpath('D:\old_mpt_path'));

配置完成后可以输入mpt3ver,如果能显示版本信息说明安装成功。如果Matlab提示找不到这个函数,多半是路径没添加成功,或者漏了genpath。这里注意不要偷懒写成addpath('D:\Tools\mpt3'),只加顶层目录的话,子目录里的mex函数和自带demo不会全部被加载,后面调用时会报“未定义函数”莫名其妙的错。

2.3 验证安装是否成功

安装完成后先跑自带demo。MPT3的demo脚本一般以mpt_demo开头,比如:

mpt_demo1; mpt_demo2;

mpt_demo1会生成一堆多面体并画图,mpt_demo2演示参数规划。如果一切正常,会弹出几个图形窗口。我个人的做法是再写一个最小验证:

P = Polyhedron('lb', [-1; -1], 'ub', [1; 1]); P.plot(); disp(P.volume);

如果输出volume等于4,说明Polyhedron对象和图形接口都正常。如果到这里就报错,先别往下做功能,多半是路径或依赖问题。先把第5章的排查表对照一遍再继续。

3. 核心对象与求解流程拆解

3.1 Polyhedron:所有几何计算的地基

MPT3里,多面体一般用H表示,即半空间交集:

P = {x | A x ≤ b },需要时还可以加等式He x = h。

创建方式很直观:

A = [1 0; -1 0; 0 1; 0 -1]; b = [2; 2; 3; 3]; P = Polyhedron('A', A, 'b', b);

也可以直接搞一个盒式区域:

P = Polyhedron('lb', [-1; -1], 'ub', [1; 1]);

拿到对象之后,很多几何信息都是属性,不需要自己写算法:

P.V % 极点(顶点) P.volume % 体积/面积 P.chebyCenter % 切比雪夫中心 P.plot % 画图

两个多面体的交并差也很常用:

P1.intersect(P2) P1.diff(P2)

我在实际使用中想提醒一点:多面体计算本质上是数值运算,容差设置很关键。默认容差在大多数问题下没问题,但如果约束矩阵量级很大(比如10^5)或很小(10^-5),建议先对数据归一化,否则极点和Chebyshev中心可能算出奇怪的结果,后续画图也会出现区域变形。

3.2 Opt类:把参数规划问题交给求解器

MPT3把多参数规划问题包装成Opt对象,常用字段包括:

opt = Opt(... 'A', A, ... % 约束矩阵 'b', b, ... % 约束右侧常数 'F', F, ... % 参数矩阵,对应 theta 'f', f, ... % 线性代价 'H', H, ... % 二次代价(可选) 'lb', lb, 'ub', ub); % 决策变量边界

这里的关键是F的含义。多参数规划的约束写成A x ≤ b + F θ,θ是外部参数,F就是参数对约束边界的扰动矩阵。定义好opt之后,调用:

res = mpt_mplp(opt); % 多参数线性规划 % 或 res = mpt_mpqp(opt); % 多参数二次规划

返回的res里包含了分区和每个区域上的解函数。我做项目时一般会把res里的分区数和每段仿射系数打印出来检查一下,确认数值上没有异常,再去做后续的查表模块。初学的时候容易把F写成零矩阵,那整个问题就退化成了普通的LP/QP,分区图也会消失,这个坑不少人都踩过。

3.3 MPCController与toExplicit:显式MPC控制器

如果你关心MPC的落地方案,MPT3提供了相对上层的接口。比如先通过ltiSys对象定义被控系统,再指定预测时域,就能得到一个在线MPC控制器:

sys = ltiSys('doubleIntegrator'); N = 5; mpc = MPCController(sys, N);

在线使用时调用mpc.eval(x0)即可。如果要显式化,则调用:

expmpc = mpc.toExplicit();

toExplicit的工作原理,就是把MPC的优化问题重写成带参数的多参数QP,再调用mpt_mpqp在后台求解。最终得到一个PolyUnion对象,里边是参数空间的分区以及各分区的仿射反馈控制律。这个流程,本质上是把“在线求解一个QP”变成了“离线划分一个凸区域”。如果你之前直接用mpt_mpqp解过问题,你会发现两个路径殊途同归。

4. 一个能直接跑的例子:双积分器显式MPC

4.1 问题定义与建模

双积分器是最经典的MPC教学模型,状态x1是位置,x2是速度,输入是加速度。离散状态空间是:

A = [1 1; 0 1]; B = [0.5; 1]; C = eye(2); D = zeros(2, 1);

构造MPC控制器之前,需要定状态约束和输入约束,比如速度|u| ≤ 1。在MPT3中,约束是放在系统对象或控制对象中的。我用ltiSys接口时习惯先建系统:

sys = ltiSys('doubleIntegrator'); sys.x.min = [-5; -5]; sys.x.max = [5; 5]; sys.u.min = -1; sys.u.max = 1;

如果你的MPT3版本里ltiSys的属性名略有不同,直接打开help ltiSys查看,demo里也都有完整例子。建模时注意双积分器的离散化方法,采样周期不同,B矩阵差别会很大,最好和你的实际系统保持一致。MPT3自带的help文档里对这些对象属性写得比较细,遇到拿不准的优先查help,别去网上搜二手答案。

4.2 生成显式控制器并查看分区

预测时域N取5,代价矩阵用默认单位矩阵:

N = 5; ctrl = MPCController(sys, N); expmpc = ctrl.toExplicit();

运行完成后,可以用expmpc.plot()直接画出参数空间的分区。图里不同颜色代表不同的仿射控制律区域,区域数量一般会随着时域N增大而指数级增多。N=5时双积分器通常有几十个区域,N=10就有几百个,画图会明显变慢。

这一步如果报错,最先怀疑的不是MPT本身,而是求解器。mpt_mpqp底层需要LP或QP求解器,没有YALMIP或者GLPK时,大概率会卡在“No solver found”上。解决办法见第5章,这里不重复展开。

4.3 用分区查表代替在线求解

显式控制器拿到手之后,仿真时不再需要调用优化器。MPT3的显式控制器对象可以直接对状态求控制量:

x0 = [-3; 1.5]; u0 = expmpc.eval(x0);

做闭环仿真时,可以把它和在线MPC的结果做对比。我在实际测试中跑过多次,只要显式化过程中求解器没有报数值警告,闭环轨迹和在线MPC几乎完全重合,差异只在数值误差级别。这个方法最大的价值,是把“每一步算优化”压成“查区域、代入仿射函数”,计算时间基本可以忽略,适合移植到嵌入式环境。

这里提醒一下:显式MPC的区域数量会随着状态维数、时域和约束数量急剧膨胀,三维以上系统建议先做降维或改用其他近似方法,否则离线求解时间和内存会失控。我见过一个四状态问题,N=10直接把内存吃到了十几个GB,最后只能减小时域。

5. 常见问题与排查技巧实录

5.1 安装后Polyhedron无法创建,或对象被当成double

这个问题在从MPT2导过来的老用户里特别常见。MPT2和MPT3的类名不一样,MPT2用的是polytope,MPT3用的是Polyhedron,但安装目录都叫mpt。如果两个版本的路径同时存在,Matlab会优先加载路径靠前的那个,造成调用混乱。解决办法是彻底rmpath掉旧版本目录,然后重启Matlab再试。不要只在当前会话改路径,要用savepath持久化,否则下次打开Matlab又乱了。

5.2 报错No solver found或者YALMIP相关错误

这种情况最常见的原因是YALMIP没装,或者没有把YALMIP路径加入Matlab。MPT3.2.1的mpt_mplp、mpt_mpqp在求解时依赖外部优化求解器,单独装MPT3不装YALMIP,跑demo到一半就会挂。装完YALMIP后,建议再确认GLPK接口也被识别,可以运行:

yalmiptest('lp')

如果结果显示没有可用的求解器,要么装GLPK,要么在YALMIP里指定其他求解器作为默认。Gurobi和MOSEK都行,只是需要许可证。对教学和研究来说,GLPK完全够用,没必要一上来就上商业求解器。

5.3 新版Matlab出现warning或函数提示隐藏

我用R2021b、R2023a跑MPT3.2.1,会偶尔看到一些关于类属性、函数可见性的warning,比如“method will be removed”之类。这些大多是兼容性提示,不影响核心功能。但要注意一个坑:如果系统里同时装了多个版本的Matlab,并且把MPT3路径写到了startup.m中,换版本后路径里的工具位置可能失效,导致找不到mpt3ver。建议每个版本单独配Path,不要一个startup.m全带。

5.4 计算慢和数值不稳的排查角度

参数规划的复杂度主要来自分区操作。我遇到过一个状态约束量级差别很大的问题,位置约束在10^3量级,速度约束在10^-2量级,MPT算出来的分区数异常多。后来先把约束归一化到同一个量级,分区数明显减少,求解也稳定。另一个经验是,如果只是为了画概念图,在构造Opt时设置verbose参数可以少刷屏:

opt = Opt('A', A, 'b', b, 'F', F, 'verbose', -1);

顺手整理了一个速查表,覆盖九成以上新人会踩的坑:

现象可能原因解决思路
mpt3ver未找到路径没配好addpath(genpath(...))后savepath
Polyhedron未定义旧版MPT2残留移除旧目录并重启Matlab
No solver found缺YALMIP或GLPK安装对应依赖并运行yalmiptest
plot不显示图形图形后端问题用mpt_demo1排查
分区数异常多量级不一致或容差问题归一化约束、调整容差
求解时间长时域或维度太大减小N、降维、换求解器

最后再分享一点我的真实体会。MPT3.2.1这个工具箱,光看文档容易觉得它是个“几何库”,实际上真正把它用起来,最大的门槛在安装和问题建模这两步。安装那头,路径和依赖是硬伤;建模那头,把实际问题写进Opt的A、b、F里,很多人第一步就写反了。建议拿到手后别急着做项目,先把mpt_demo1、mpt_demo2和显式MPC的demo各跑一遍,再把自己的问题往里套。你跑完demo之后会发现,教材里那些看起来很高级的分区图,生成起来其实比想象中简单——真正难的是想清楚你的系统该用什么约束、什么代价、多少时域。这部分没有捷径,只能靠实验和迭代。

再加一个很实用的小技巧:如果你需要把生成的显式控制律导出到C代码,可以用MPT3把每个区域的仿射函数系数写到文本或表格,再在嵌入式端写一个简单的最短距离判区逻辑。别试图把整个Polyhedron对象直接序列化,到了C端根本没法用。我踩过这个坑,最后是写脚本把res里的分区顶点和仿射系数全部导出,才真正落地。

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

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

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

立即咨询