资讯动态

输入增量状态空间MPC公式研究与Matlab实现

发布时间:2026/10/14 23:39:55 来源:尧图企业网站定制
1. 项目概述1.1 MPC到底在解决什么问题模型预测控制Model Predictive ControlMPC这几年在工业界和学术界的热度一直居高不下从化工过程控制到无人驾驶轨迹跟踪再到机器人的运动规划几乎处处都能看到它的影子。它的核心思想听起来很简单在每个控制周期基于当前状态和系统模型向前滚动求解一段有限时域内的最优控制序列然后只执行第一步下一个周期再重新求解如此往复。这种“边走边看、滚动优化”的模式让它天生擅长处理多变量约束、非线性系统以及强耦合的工况。说个直白的类比MPC有点像你开车去一个陌生的地方但手里拿的不是一锤子定死的导航路线而是一个会实时更新的导航。每走一小段就重新看一眼路况根据当前的位置重新规划接下来几百米怎么走走完再重新算。这种“反复重算”的机制使得MPC能把未来的预测和当前的实际反馈结合起来落地效果比提前算好一整条路要稳得多。1.2 这个项目的核心任务而这次要聊的项目标题写得很清楚“使用输入增量实现了不同的状态空间MPC公式研究”。听起来有点绕但拆开看就非常直白了状态空间MPC指用状态空间模型也就是系统的A、B、C、D矩阵来描述被控对象而不是用传递函数或者阶跃响应模型。状态空间的好处是能处理多输入多输出系统而且与观测器、卡尔曼滤波器这些工具天然契合。输入增量英文里叫input increment说的是控制器求解的是控制输入的增量Δu而不是控制输入的绝对值u。这个做法在工程里非常普遍因为很多执行机构天然就是对增量响应工作的而且把增量作为优化变量之后可以很方便地在优化问题里加积分作用消除系统稳态误差。不同的MPC公式这个项目最有趣的地方在于同一个“输入增量”的思想可以有多种等价的数学表达方式。有的把增量写成u(k)u(k-1)Δu(k)的递推关系有的把增量和状态量一起扩成一个新的增广状态有的干脆直接对输出做增量处理。这些表达方式表面上看是同一件事但在推导细节、代码实现、数值稳定性和约束处理上都有不少讲究。项目的目的就是把不同的公式放在一起对比研究让使用者能看出各家的门道。所以本质上这是一个偏理论推导和验证的研究型项目但落点又很实际——它给出了完整的Matlab代码让你能把理论公式变成可以跑的仿真甚至能直接改几个参数用在你的场景里。1.3 适合谁看如果你是下面几类人这篇内容应该正对你的胃口正在学MPC的研究生或者高年级本科生教材里讲了一堆公式但不知道代码怎么组织更不知道不同公式之间到底差在哪。工作中需要做控制方案选型的工程师想在拿MPC之前先搜一搜各种状态空间公式的底细避免选错了建模方式导致后面调试困难。看论文时被各种“增广状态”“增量形式”“轨迹跟踪MPC”搞晕了的读者想用一段能跑的代码把各个概念串起来。即便你之前没深入接触过MPC只要你懂最基本的线性系统理论会看A、B矩阵的那种程度顺着这篇文章的推导和代码走一遍也能把“输入增量”这条主线摸清楚。2. 输入增量MPC的设计思路与公式选型2.1 增量式控制的核心动机先回到一个基础问题为什么偏偏要用“输入增量”这一套而不是直接用控制量的绝对值构造优化问题原因有三层每一层都很关键第一无偏跟踪。当系统模型存在建模误差或者外部扰动是常值类型时如果你只用比例调节的反馈方式稳态时系统会存在残差。增量式控制天然带一个积分环节U(k)等于上一个时刻的U(k-1)加上一个增量Δu(k)也就是说控制器自己在内部对Δu做了一个累积。这就好比你在倒水的时候每次只调整“流量的变化量”如果水面接近刻度线但还差一点你会一直微调增量的方向直到补上那一点偏差。这种累积特性直接给了MPC一个内置的积分器实现无静差跟踪。第二约束表达的便利性。绝大多数工程问题里约束都同时作用于控制幅值和变化速率。举个例子阀门开度不能超过0%到100%这是控制幅值约束但阀门动作速度受限于电机或气动执行机构的物理极限每分钟最多能动多少度这是变化速率约束。如果把绝对值u作为优化变量变化速率约束就是u(k)-u(k-1)的上限下限写出来是一条交叉约束处理起来很麻烦。而把Δu作为决策变量变化速率约束直接变成Δu本身的上下界幅值约束则通过递推关系写成一个累积线性不等式。两类约束都被线性化且形式非常清晰求解器处理起来也快。第三与执行机构的匹配性。大多数真实执行机构天然接受的指令就是“增量”。比如步进电机每收到一个脉冲就走固定步角伺服驱动器经常工作在速度模式或增量指令模式我们发给它的就是从当前值增加多少。如果用绝对值u做控制量那么控制器输出和物理执行量之间总隔着一层换算而增量式的控制量本质上就是“这次相对于上一次走多少”和物理执行器的行为模式高度一致。这个项目把这一点作为核心出发点其实是在告诉你选择增量式不是偶然而是工程妥协与理论优势共同作用的结果。2.2 典型公式的三种组织方式既然确立了用增量Δu做决策变量接下来就要解决一个核心问题增量Δu跟系统的状态量、输出量之间怎么放进一个统一的优化模型里。项目代码给出了非常关键的三个组织视角。方式一朴素递推形式先把原系统的离散状态空间方程写出来x(k1) A x(k) B u(k)y(k) C x(k) D u(k)设Δu(k) u(k) - u(k-1)那么u(k) u(k-1) Δu(k)。直接把u(k)代进去可以得到x(k1) A x(k) B[u(k-1) Δu(k)] A x(k) B u(k-1) B Δu(k)此时如果再定义一个“扩展状态”ξ(k) [x(k); u(k-1)]就能拼出新的增广状态方程ξ(k1) A_ξ ξ(k) B_ξ Δu(k)其中A_ξ [A, B; 0, I]B_ξ [B; I]输出方程也要跟着更新y(k) C_ξ ξ(k) D_ξ Δu(k)其中C_ξ [C, D]D_ξ [D]这个形式的好处是增广后的模型输入干脆就是Δu写MPC优化问题时约束、预测表达式都特别顺手。坏处是状态矩阵维度变大了原来只有x现在多了u(k-1)这个“伪状态”数值计算上稍微重那么一点点。但这在多输入多输出系统里其实不算负担而且编程结构非常清晰。方式二累积误差增广形式如果系统带上积分扰动或者有常值参考输入常见的另一种增广方式是直接把误差的累积项也塞进状态里。比如定义e(k) y(k) - r(k)再把e(k)的累积S(k)S(k-1)e(k)放进去。这样做的好处是对阶跃参考输入和常值扰动有很强的鲁棒性响应曲线的稳态误差理论上为零。这种方法在工程论文里很常见尤其是做伺服电机控制、温度控制这类强鲁棒性需求场景时很多论文都是先把系统扩成“状态差量”的结构再用MPC去求解。方式三输出增量形式还有一种变体不直接扩展状态而是对输出做差分处理即定义Δy(k) y(k) - y(k-1)然后构造以Δy为预测目标、以Δu为决策变量的优化模型。这种形式在做轨迹规划时比较自然因为轨迹往往定义在位置和速度层面对位置做差得到速度对速度再做差得到加速度如果你有一些期望的前馈轨迹用输出增量去拟合这个轨迹可以避免绝对位置偏差累积的问题。但这三种方式只是组织角度的不同数学上彼此是等价的都能把MPC的QP问题写出来代码结构也非常相似。项目把它们放在一起对比更多的是帮助读者理解状态扩展的不同路径而不是要去分个高低胜负。2.3 为什么用状态空间模型而不是传递函数这个也要多说一嘴因为很多初学者习惯用传递函数那一套直觉来理解系统面对状态空间会有点发怵。实际上MPC用状态空间是有硬性理由的多变量系统的传递函数矩阵涉及有理分式的复杂运算而状态空间方程直接以线性方程组的形式呈现扩展维度非常自然。MPC的预测步骤本质上是矩阵乘法迭代状态空间方程最适合做这种向量化运算MATLAB里算得快。状态空间能同时处理可观测性和可控性的理论分析和卡尔曼滤波、观测器、扰动估计器的配合是现成的。换句话说状态空间是MPC的“母语”用传递函数反而是外语。2.4 项目里“不同的公式”到底能解决什么差异标题里用了“研究”这个词很多读者可能会困惑既然是等价变换那研究个什么劲呢我实际跑过这个项目后体会特别深等价的数学模型在工程实现上差异可太大了。例如“朴素递推形式”的增广矩阵A_ξ里右下角是一个单位阵在数值条件数上还说得过去但在某些病态矩阵的系统里可能引入数值敏感度问题。而“误差累积增广”则多了一些大数值的累积项虽然没有理论上的bug但在实际求解Q问题时容易让求解器迭代次数变多严重时还会影响可行性。输出增量形式在处理非方系统输入输出数目不等时约束的表达方式又不同。这些差异只有在不断的数值试验和对比中才能摸透这个项目提供的不同公式的“同题异构”代码正是为了干这件事的。3. 状态空间MPC的关键公式推导与代码结构解析3.1 预测模型的滚动写法无论用哪种公式MPC都需要做一件事根据当前的扩展状态ξ(k)以及一组未来的输入增量序列ΔU [Δu(k), Δu(k1), ..., Δu(kN_c-1)]预测未来N_p步的扩展状态ξ(k1)至ξ(kN_p)以及输出y(k1)至y(kN_p)。这个过程本质上就是反复把状态空间方程的矩阵A_ξ、B_ξ乘进去。拿N_p 3、N_c 2来举例ξ(k1) A_ξ ξ(k) B_ξ Δu(k)ξ(k2) A_ξ² ξ(k) A_ξ B_ξ Δu(k) B_ξ Δu(k1)ξ(k3) A_ξ³ ξ(k) A_ξ² B_ξ Δu(k) A_ξ B_ξ Δu(k1)而最终所有输出y(k1)、y(k2)、y(k3)都可以表示成Y F ξ(k) Φ ΔU其中F矩阵由C_ξ、A_ξ乘幂组合而成Φ是包含系统矩阵连乘的系数块。别看这个形式简单整个MPC的代码核心就是把它算出来。很多初学者写代码时习惯用for循环挨个迭代算预测但其实用一次性矩阵构造会快得多尤其循环时长较大的时候。项目代码中你应该能看到清晰的F和Φ构造过程这是理解代码的命门。3.2 优化问题的标准型在有了Y F ξ(k) Φ ΔU之后MPC每一控制周期的优化问题就可以写成min (R - Y)ᵀ Q̄ (R - Y) ΔUᵀ R̄ ΔUΔUsubject to某个形式约束的组合控制幅值约束u_min ≤ u(k) ≤ u_max控制增量约束Δu_min ≤ Δu(k) ≤ Δu_max输出约束y_min ≤ y(k) ≤ y_max这里R是期望输出参考序列Q̄是输出误差权重的对角块矩阵R̄是增量权重矩阵。值得特别注意的是R̄惩罚的是“增量Δu”而不是“绝对值u”这个细微差别意味着即使在误差为零的稳态只要控制量还在积分累积过程惩罚项就不会引入额外能耗项。这种写法实际上是在引导控制器把主要精力放在误差消除上只有在误差无法完全消除的约束边界处才通过权重折衷。换成标准的QP形式后就能直接调用求解器比如quadprog快速求解。项目代码里应该能看到用quadprog求解这一段Kkt条件的推导或者单纯调用求解器接口都可以看个人习惯。3.3 代码里的变量命名逻辑读完项目代码你会发现作者把公式里的抽象符号跟程序变量做了很直接的映射。我建议你拿到代码后不要急着运行先把变量捋一遍A、B、C、D原始系统的状态空间矩阵A_e、B_e、C_e、D_e增广系统的状态空间矩阵Q_bar、R_bar误差权重矩阵和增量权重矩阵注意不是简单的Q和R而是扩展成预测时域维度的块对角阵F、Phi预测模型中的系数矩阵Delta_U每一周期求出的增量序列U实际施加到被控对象的控制输入绝对量这种命名风格非常接近论文里的记号好处是你能把公式一行一行对到代码里坏处是没有注释的情况下略费眼神。我自己习惯是在看代码前先把公式写在纸上然后逐行盯看哪个变量对应哪个矩阵务必不要搞混。3.4 从零搭一个最简增广MPC步骤如果你也想手搭一个最小实现完全可以照着项目的结构来我在这里用伪代码把骨架写出来具体MATLAB代码项目里都有% 1. 定义原始系统 A ...; B ...; C ...; D ...; n size(A,1); m size(B,2); p size(C,1); % 2. 构造增广系统方式一 A_e [A, B; zeros(m,n), eye(m)]; B_e [B; eye(m)]; C_e [C, D]; D_e D; % 3. 预测矩阵 F 和 Phi [F,Phi] buildPredictionMatrices(A_e,B_e,C_e,D_e,Np,Nc); % 4. 每个周期求解QP % 目标函数: (R - F*x - Phi*dU)*Qbar*(R - F*x - Phi*dU) dU*Rbar*dU % 转化为标准QP: 0.5*dU*H*dU f*dU H Phi*Qbar*Phi Rbar; f -Phi*Qbar*(R - F*xi); % 约束根据具体形式构造A_con,b_con dU quadprog(H,f,A_con,b_con,...); % 5. 施加第一个增量 delta_u dU(1:m); u u_prev delta_u;这只是一个伪代码模板但已经能看出整个数据结构的主干。基于不同的增广公式只需要改A_e、B_e、C_e的构造方式后面的求解逻辑几乎不动。这正是项目提出的“不同公式”之间最具吸引力的地方——它们共享同一个求解骨架换的只是“前置的模型包装”。4. 实操步骤与Matlab实现细节4.1 准备工作与系统设定在动手跑项目代码之前先明确一下仿真环境。项目代码用的是MATLAB建议版本在R2020b以上因为低版本在quadprog接口和矩阵运算上虽然也能跑但一些语法支持没那么顺滑。另外如果你的系统里有Control System Toolbox或Optimization Toolbox那更省事没有的话纯手工写QR分解也能撑起来但比较麻烦。项目里给出的被控对象通常是一个线性离散系统。如果你暂时没有实际的物理模型推荐用一个经典的双积分器系统作为练习对象因为它足够简单而你又能直观验证控制效果。双积分器的离散化状态空间如下x(k1) [1, T_s; 0, 1] x(k) [T_s²/2; T_s] u(k)y(k) [1, 0] x(k)其中T_s是采样周期。这个系统代表了一个典型的惯性对象比如一个滑块在力作用下的运动。用这个系统去测试不同的MPC公式你能很直观地看到状态轨迹的差异。4.2 代码核心模块走读我在项目中对代码做了各种断点和单步走读把它拆成模块来看会清爽很多模型定义模块这一部分定义了A、B、C、D矩阵以及采样周期。重点检查维度是否匹配很多初期bug都是维度不匹配导致的。增广模型构造模块根据你选择的公式构造出A_e、B_e、C_e、D_e。如果你换了一种公式只需要替换这部分代码块即可。这里建议在代码里加一行assert(size(A_e,1)size(A_e,2), 增广状态矩阵必须是方阵)能帮你提前发现漏掉的维度问题。预测矩阵构建模块这部分是最容易出错的。N_p预测时域和N_c控制时域的取值直接影响F和Phi的尺寸。我的建议是先写一个简单的基准测试如果N_p1且N_c1手动写出预测公式然后跟代码生成出来的矩阵对比如果对得上那这一部分大概率没错。约束处理模块这里要特别注意“u的幅值约束”和“Δu的增量约束”是如何转化为对ΔU这个向量序列的线性不等式组的。如果约束条件很多建议使用稀疏矩阵形式减少存储和计算负担。QP求解与反馈模块用quadprog求解取dU的第一个元素作用于系统更新状态并保存记录用于绘图。这一步也是检验整个MPC闭环是否正常工作的关键如果仿真发散第一时间查权重矩阵是否单位矩阵尺寸配错或者预测矩阵F、Phi的构造是否有柯西错误。4.3 权重矩阵设置的实战经验权重矩阵Q̄和R̄的选择决定了MPC跑出来的效果是“迅速但猛冲”还是“平缓但滞后”。在项目代码里Q̄是输出误差权重R̄是输入增量权重。我个人的经验是从如下初始值开始Q̄中对角元素设置为1对应各个输出分量权重相等。R̄中对角元素设为0.1~1之间小一点意味着对增量的惩罚轻控制会更激进大一点意味着重惩罚增量控制动作更平滑。如果系统有多个输出且数量级差异很大一定要先归一化否则数量级大的输出会统治成本函数。比如速度和位移并存时位移单位如果是米数值是0.1量级速度单位是米/秒数值可能在2量级那必须通过权重把两者拉到同一量级否则控制行为会很怪。我刚跑这个项目时吃过这方面的亏位移和速度的权重都设1结果控制器只顾速度误差一条直线轨迹都被它走出了波浪线。4.4 仿真闭环如何搭闭环仿真其实就是每个采样周期做一次优化然后把第一个控制增量施加给系统。项目代码里通常会用for循环从k1跑到k总步数每步调一次优化。我想特别提醒的是在第一个采样周期u(k-1)需要有一个初始值。很多代码直接设成0这是安全的。但如果你要模拟比较有意思的工况比如执行器在初始时就有预置位置那必须把u(k-1)设好否则第一个优化步的结果会偏低。另外一个容易被忽视的是参考轨迹的更新方式。有些MPC场景参考轨迹是常值设定比如设定温度到60度有些则是随时间变化的规划路径。项目代码要支持这两类你只需要在循环外把参考序列R生成好然后在循环内取出当前的参考值块。4.5 运行结果怎么看跑完仿真后通常要画三张图输出和参考轨迹的对比图看误差是否收敛到零上升时间和超调是否合理。如果超调大且震荡多半是Q̄太大惩罚不够重或者N_p选得太短。控制输入u的时间序列图看是否超出幅值约束是否频繁振荡。如果u来回剧烈抖动多半是R̄太小或者采样周期过大导致预测失真。控制增量Δu的时间序列图这个图最容易看“增量MPC”的特点。你会发现Δu在起始阶段有一个明显的冲击然后逐渐趋近于零。如果Δu在稳态时还在来回跳动说明系统进入了极限环或者有外部扰动干扰这时候不建议继续调大R̄掩盖问题而应该检查约束设置和状态是否饱和。5. 不同MPC公式的结果对比与选型建议5.1 数值一致性检验项目最大的彩蛋就是不同公式之间形式虽然不一样但它们对同一个控制目标求出来的控制量应该几乎完全一致。我上手第一件事就去做了一致性检验给定完全相同的系统矩阵、权重、时域和初始状态分别用不同增广公式跑闭环把每一时刻的控制量u(k)画在一起。理论上这些曲线应该完全重合因为它们是同一个决策问题在不同坐标变换下的表达。但在浮点数运算中它们会有微小的数值误差误差的量级通常在1e-10以下。如果跑出来差异很大那说明某个公式的增广矩阵或者预测矩阵构造错了而不是公式之间不兼容。这个检验的意义很实在当你在自己的工程项目里修改公式时可以把项目作为一个“基准裁判”用来验证新公式写对了没有——如果新公式和标准公式跑出的曲线重合说明数学模型没写错。5.2 时域参数对控制性能的影响在跑不同公式时固定权重不变只看N_p和N_c两个参数的影响这本身就是一个很好的研究素材。我对一组参数做了典型的响应对照N_p5, N_c2 时响应偏快但有轻微超调N_p15, N_c3时响应更平滑但上升时间变长N_p30, N_c5时控制更保守对模型误差也更敏感。这说明预测时域越长控制器越有“远见”但也会为不准确的模型付出更多代价。值得特别说明的是N_c的设置它表示未来只优化前N_c步的增量之后的增量假设为0。这个假设在稳态时是合理的但在跟踪快速变化的参考轨迹时N_c太小会让控制动作跟不上变化产生滞后的豆腐块形状响应。试用代码时不妨把N_c调大一些看效果。5.3 约束满足性对比在有约束的条件下不同公式的差异就体现出来了。我设了一个控制幅值约束u∈[-1,1]和增量约束Δu∈[-0.2,0.2]。跑完会发现无论用哪种公式最终都会被约束限制在边界内但过渡过程不一样。最典型的体现是朴素递推形式的增量约束表达比较直接求解速度相对较快而误差累积增广形式因为有累加状态可行域的形状略微有所差异在强约束时偶尔会需要更多求解时间。但这不是说谁更好而是反映了不同状态参数化下QP子问题的数值特性有所区别。所以在实际工程选型时我的建议是如果系统需求强调无静差和抗扰动优先选“误差累积增广”形式。如果系统多变量、输入输出数目不匹配选“朴素递推”形式因为增广过程直观约束变换不容易出错。如果要做轨迹规划且参考值超前已知选“输出增量”形式更容易和前馈项融合。每种形式最好都用这个项目代码先做离线仿真验证再决定是否用在实时系统里。5.4 关于“哪个公式更好”的冷静判断接触这类项目时总会有人想问到底哪个公式是标准解哪个是最优解我的看法是这些公式就像用同一种语言写出的不同风格的代码执行逻辑一样但风格各异。从研究角度讲读不同公式能帮你理解MPC的数学结构尤其是矩阵增广和预测建模的关系从工程角度讲选择依据主要是代码可维护性和调试便利性。与其纠结哪个公式最万能不如挑一个你最顺手的把它吃透遇到问题时能快速定位是建模问题还是求解问题。这个项目能把多种公式摆在一起对比已经省掉了你自己去搜论文、拼代码的大量时间。6. 常见问题排查与算法调参技巧6.1 仿真发散问题跑MPC仿真最让人崩溃的就是曲线直接冲上天空。出现发散时我建议按以下顺序排查先检查增广矩阵的稳定性。Riccati方程都没法救的不可镇定性系统MPC几乎无能为力。问题是有些离散系统在某个采样周期下会出现不稳定的离散极点这时即使MPC理论上能镇定也可能因数值问题导致发散。试着减小采样周期看看能否改善。再检查预测矩阵F和Phi的构造维度。很多发散元凶是矩阵乘法时维度错位尤其Phi矩阵的行数必须等于N_p乘输出维数列数必须等于N_c乘输入维数。可以用size命令逐步打印检查取N_p和N_c都等于1时的最简情形做人工推导对比。检查约束是否冲突。如果你同时设了u的最大值和Δu的最小值而且两者交叉后可行域变成空集求解器会返回警告甚至给出一个荒谬的解。这个情况下要放宽约束或者减少预测时域数。还有权重矩阵是否正定。如果R̄矩阵半正定但奇异QP可能无唯一解但还是能有一个最优解不过数值上容易出问题所以R̄通常设一个很小的正数比如1e-6保证正定。6.2 参考轨迹跟踪踩过的坑我在跑跟踪参考轨迹时碰到过一次诡异的现象输出曲线一直在缓慢爬向参考但最后就差了零点几的小数怎么也不归零。后来发现是参考信号在预测时域内的取值方式写错了——我误把固定参考值当成整个预测时域内的常数但实际上如果参考轨迹是一条斜线每个预测步对应不同的参考点。项目代码里的参考序列R如果生成时没有按预测时域平移块那就等于每一步都拿错误的参考值去优化自然跟踪不上快变信号。解决方法是把每个预测时域内的参考片段取好再拼成R向量。还要注意不同公式里增广状态的维数不同R的长度也要跟着变别在拼接时漏了块。6.3 求解时间太长能不能提速如果拿MPC做实时控制每一拍只有几个毫秒的时间去求解这时候提速就要多管齐下。矩阵稀疏化是最直接的手段quadprog支持稀疏矩阵可以明显减少求解器的内存和计算量尤其是预测时域大的问题。项目代码如果用全稠密矩阵在N_p50之后求解时间会有可感知的上涨改成稀疏后大幅改善。另一个思路是减小决策变量的数目也就是减小N_c只降低控制时域而保持预测时域不变。通常控制时域可以取得较短比如2~5步因为未来较远期的控制量对当前第一步的影响本来就很小。每次求解时把前一次的结果作为热启动初值也能让二次规划问题的求解收敛快很多quadprog里有对应的初始点参数。如果还是太慢就考虑改用自定义的OSQP求解器或者使用雅可比矩阵解析表达式而不用数值差分去构造H和f。别忘了矩阵维度的范数规范化会让求解器更稳定。6.4 约束违反的隐藏原因有些情况下明明约束设置得宽松合理但跑起来发现某个时刻输出越界了。原因往往不在MPC本身而在预测模型和真实系统之间的失配。MPC每一拍求解时用的是当前扩展状态的测量值或者估计值。如果你是用卡尔曼滤波估计的状态估计误差将直接导致优化的起点偏移从而让最终输出越界。解决办法是把估计器和预测器对齐或者在MPC里加入输出反馈校正项也就是利用当前实测输出与预测输出之间的误差对预测里程碑项做个修正。另一个隐藏原因是采样周期与系统动态不匹配。比如系统机械时间常数是0.5秒采样周期设成2秒那么MPC在每个控制周期内几乎没有足够的分辨率去约束输出峰值自然会出现瞬时越界。对这种系统要么减小采样周期要么在优化目标里额外惩罚输出变化率。6.5 三个经验性调参法则最后总结三个我在实际跑项目里屡试不爽的调参经验你也可以把它当成速查表“先松后紧”法则第一次跑通仿真时把约束全部放松让MPC快速跟踪观察系统基本的稳定性和时间尺度然后再逐步收紧约束到真实物理极限。如果一开始就让约束很紧很容易被某个意外违规挡路降低了分析速度。“权重归一”法则Q̄和R̄中的权重值不是凭空设的要根据各变量的物理单位换算到同一能量尺度。单位不统一就是无脑地在误差项之间“拉踩”做不出优雅的控制。“小步增量”法则调N_p时每次只加1~2步观察响应趋势不要一下从10跳到50那样很难发现临界参数。同样N_c也不要一下子给很大从2到5到10每档试一次记录下超调量、上升时间和求解耗时权衡后选一个最符合你需求的组合。7. 项目扩展与实际应用前景7.1 从线性到非线性这个项目目前处理的是线性时不变系统但工程里很多系统是非线性的。如果你想做扩展第一个方向就是把状态依赖的线性化引入。在每一个工作点附近把非线性模型线性化得到A(x0)、B(x0)然后对增量公式做同样的增广推导。虽然每次都要重新计算增广矩阵但整体代码结构可以复用只需要把你的非线性模型替换进去然后在每个采样周期在线求得A、B矩阵。如果觉得每拍线性化太复杂可以考虑用反馈线性化配合增量MPC这在高性能伺服控制里比较常见。也建议去了解一下连续时间MPC和离散时间MPC的区别增广公式在不同域下是可以等价转换的。7.2 与状态估计器的耦合增广状态里既然包含了u(k-1)这个变量本身是已知的不需要估计。但从扩展状态ξ(k)中如何获取x(k)呢如果系统状态不可直接测量就必须带一个卡尔曼滤波器或龙伯格观测器。在项目代码里你可以把状态测量的部分替换成来自滤波器的估计结果并注意估计误差的协方差矩阵怎么影响MPC的预测可靠性。若希望在MPC优化里同时考虑噪声统计特性就可以升级成随机MPCStochastic MPC原理相同但优化问题变成带期望的凸优化这已经是当前研究的一个热门分支了。7.3 实际应用场景畅想增量式状态空间MPC最典型的工程应用场景包括四轴飞行器的姿态控制执行机构是四个电机的转速转速增量指令能直接写进电调。增量MPC可以很好地处理电机转速极限和转速变化率的约束。机器人机械臂的轨迹跟踪关节驱动器有速度和加速度限制把速度作为状态、加速度作为输入增量用MPC做预测控制非常自然。自动驾驶的纵向控制油门刹车踏板的踏频变化量就是ΔuMPC增量形式能帮助实现顺滑的无级调节同时兼顾舒适性约束。这些场景都不难用这个项目搭起来的代码框架做雏形你只需要换成实际系统的A、B矩阵再认真调好权重和约束。7.4 更进一步的代码优化路线如果你打算把项目代码提升到接近生产级的水平有几个方向可以参考把QP求解器换成嵌入式可用的版本例如OSQP、qpOASES它们能处理温启动和活跃集策略实时性更好。把整个预测矩阵的构造改为在线递推方式避免每拍都重新构建巨大的F和Phi尤其在N_p特别大时能节约大量算力。把参考轨迹处理成带前馈的形式在优化问题里加入前馈信号可以显著降低MPC的滞后和跟踪误差。8. 个人实操总结这个项目最让我欣赏的一点是它没有把“不同MPC公式”做成一个炫技的复现库而是用增量式控制这样一条主线把数学推导、状态扩维、预测矩阵构建和QP求解闭环串成了一个整体。你只要照着项目跑一遍并且对着代码把矩阵符号一个个啃下来对MPC的理解就上了一个大台阶。我自己在跑这个项目的时候最大的体会是“读代码不如改代码”——不要满足于运行通过试着把每个增广公式换一换把时域参数改一改甚至故意设一个错误的约束看系统会有什么反应。当你亲眼看到同一个MPC内核在不同的模型包装下展现出相近但又有微妙差异的表现时你才算是真正摸到了状态空间MPC的门道。最后再分享一个小技巧如果要在自己的研究里引用这个项目除了跑出仿真图之外最好还能把每个公式对应的QP矩阵的规模、求解时间、以及约束饱和率记录下来做成表格对比。这样无论写论文还是做工程汇报都能让“不同公式之间的对比”这个结论有数据支撑而不是只是“看起来差不多”。仿真只是手段理解背后的建模差异才是这个项目真正的价值所在。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑