模型预测控制(MPC)核心:从线性到非线性预测模型的Matlab构建与对比

📅 发布时间:2026/8/27 6:19:08
模型预测控制(MPC)核心:从线性到非线性预测模型的Matlab构建与对比 1. 项目概述从“黑箱”到“白箱”的控制器设计在控制工程的实践里我们常常会遇到一个经典困境面对一个复杂的被控对象比如一台精密的伺服电机、一个化学反应釜或者一辆自动驾驶汽车传统的PID控制器虽然简单可靠但往往显得力不从心。PID就像一个经验丰富的老师傅靠“感觉”和“经验”来调整当系统延迟大、约束多、或者未来状态需要提前规划时它就容易“手忙脚乱”。而模型预测控制恰恰是为解决这类问题而生的“高瞻远瞩”的智能管家。它不再仅仅盯着当前的误差而是利用一个描述系统行为的“模型”去预测未来一段时间内系统的走向并在此基础上计算出一系列最优的控制动作只执行第一个然后周而复始。这种“滚动优化”的策略让它天然具备了处理多变量、带约束和优化性能指标的能力。这个项目的核心就是亲手搭建这个“智能管家”的大脑——预测模型。标题点出的“离散、连续、线性或非线性”正是MPC工具箱里的四把关键钥匙。很多初学者拿到Matlab看到MPC工具箱里琳琅满目的函数容易直接套用默认的线性模型却忽略了模型本身才是MPC的灵魂。模型选得对不对直接决定了你的控制器是“料事如神”还是“瞎指挥”。离散模型对应数字世界的采样系统连续模型描绘物理世界的连续动态线性模型简化计算非线性模型逼近真实。这次我们不满足于调用一个现成的mpc命令而是要深入底层从零开始用Matlab代码清晰地构建这四种典型模型并集成到预测控制的框架中让你彻底理解每一行代码背后的物理意义和数学原理。2. 核心思路拆解为什么模型是MPC的基石在深入代码之前我们必须先理清一个根本逻辑MPC为什么如此依赖模型想象一下你要驾驶一辆车穿过密集的锥桶。PID控制相当于只看着车头发现偏离了车道就猛打方向结果可能就是蛇形走位甚至撞桶。而MPC则像一位赛车手他脑海里有一个车辆动力学模型能预测出未来几秒内“如果我现在方向盘打这么多车子会走出什么样的轨迹”然后他从无数条可能的轨迹中选出一条既快速又不会撞桶的最优路径并只执行第一步的方向盘指令。下一秒他根据车辆新的位置重新进行同样的预测和优化。这里“车辆动力学模型”的准确性直接决定了预测轨迹是否靠谱。如果你的模型认为车子能瞬间漂移那优化出来的路径在实际中必然失控。因此MPC的设计流程可以清晰地分为三步建模、预测、优化。本项目聚焦于最基础也最关键的建模环节。我们将处理两类变量状态变量描述系统内部状况如位置、速度、温度、控制变量我们的输入如电压、阀门开度和输出变量我们能测量的如实际位置、出口浓度。建模就是建立一个数学方程描述控制变量如何驱动状态变量变化以及状态变量如何决定输出变量。线性与非线性决定了这个方程的复杂程度。线性模型满足叠加原理形式优美通常是状态空间方程dx/dt A*x B*u求解其预测轨迹可以转化为高效的二次规划问题。但现实世界本质是非线性的比如空气阻力与速度的平方成正比化学反应速率与温度呈指数关系。忽略非线性在工况大范围变化时控制器性能会严重下降甚至失稳。离散与连续则关乎我们与世界的交互方式。计算机只能处理离散时间点的数据所以我们需要将连续的物理定律微分方程“离散化”成差分方程以便在每一个采样时刻进行预测和计算。本项目的思路就是针对同一个被控对象例如一个带有非线性阻尼的简单质量块系统我们分别用四种方式为其建模并对比在MPC框架下的表现。你会看到针对一个简单系统线性模型可能勉强够用但当系统运行到非线性区域时只有非线性模型才能给出正确的预测和稳定的控制。这才是“知其然更知其所以然”的学习路径。3. 环境准备与模型定义工欲善其事必先利其器。我们首先在Matlab中准备好脚本环境。我强烈建议为这个项目单独创建一个文件夹并新建一个MPC_Modeling_Demo.m的主脚本文件。确保你的Matlab安装了Control System Toolbox和Optimization Toolbox后者对于求解优化问题至关重要。我们先来定义本次演示的被控对象。为了让问题足够典型又便于可视化我选择了一个经典的单摆系统但稍作修改使其包含更明显的非线性特性。考虑一个带有旋转阻尼的摆锤其动力学方程由以下非线性微分方程描述d²θ/dt² - (g/L) * sin(θ) - (c/(m*L²)) * dθ/dt (1/(m*L²)) * u其中θ是摆角我们的状态之一dθ/dt是角速度另一个状态g是重力加速度L是摆长m是质量c是阻尼系数u是施加在摆锤上的扭矩我们的控制输入。我们期望控制摆锤从自然下垂位置θ0快速、平稳地摆动并稳定在一个非零的角度比如θπ/4同时控制输入扭矩u不能过大。在Matlab中我们首先定义这些物理参数并设定MPC的核心参数%% 1. 系统参数与MPC基础设定 clear; clc; close all; % 物理参数 m 1.0; % 质量 (kg) L 1.0; % 摆长 (m) c 0.1; % 阻尼系数 (N*m*s/rad) g 9.81; % 重力加速度 (m/s²) % MPC核心参数 Ts 0.05; % 采样时间 (s) - 离散化的关键 Np 20; % 预测步长 - 看多远 Nc 5; % 控制步长 - 优化多长的控制序列 Q diag([10, 1]); % 状态权重矩阵惩罚角度误差和速度误差 R 0.01; % 控制输入权重矩阵惩罚控制量大小 u_min -2; u_max 2; % 控制输入约束这里Ts的选择很有讲究。它需要远小于系统的主导时间常数对于这个摆周期大约2秒所以Ts0.05s是合理的以保证离散化后的模型能足够精确地反映连续动态。Np和Nc是MPC的性能与计算负担的权衡。Np预测时域决定了“看多远”通常需要覆盖系统的暂态过程。Nc控制时域决定了“优化多长的未来控制序列”Nc之后的控制量假设保持不变。通常Nc≤Np且较小的Nc能减少优化变量加快计算。4. 四大预测模型构建详解接下来我们进入核心环节为这个单摆系统构建四种类型的预测模型。请注意在MPC的在线滚动优化中我们需要的是一个能根据当前状态和未来控制输入预测未来状态序列的模型。我们将构建四个函数它们都接受当前状态和未来控制序列返回预测的状态轨迹。4.1 连续线性模型CLM的构建与局限性线性模型通常在系统的一个平衡点工作点附近进行泰勒一阶展开得到。我们选择期望的稳定点θ π/4, dθ/dt 0, u m*g*L*sin(π/4)即扭矩刚好抵消重力分量。在平衡点附近对非线性项sin(θ)进行线性化sin(θ) ≈ sin(θ0) cos(θ0)*(θ-θ0)。由此我们可以推导出连续时间的线性状态空间模型。定义状态向量x [θ; dθ/dt]控制输入u即为扭矩。线性化后的方程可以写成标准形式dx/dt A*x B*u d其中d是常数项源于工作点的偏移在实际控制中通常可以通过引入积分环节或前馈补偿来处理。为了聚焦于模型对比我们先忽略常数项专注于齐次部分。在Matlab中构建这个模型%% 2.1 构建连续线性模型 (CLM) theta0 pi/4; % 线性化工作点 % 计算线性化后的系统矩阵A和输入矩阵B A21_lin -g/L * cos(theta0); % sin(θ)线性化后对θ的系数 A22_lin -c/(m*L^2); B2_lin 1/(m*L^2); A_clm [0, 1; A21_lin, A22_lin]; B_clm [0; B2_lin]; C_clm eye(2); % 假设状态全可测 D_clm 0; sys_clm ss(A_clm, B_clm, C_clm, D_clm); % 创建连续状态空间模型这个sys_clm对象就是一个标准的连续线性时不变系统模型。在MPC的预测中如果使用连续模型通常需要先将其离散化因为优化是在离散时间点上进行的或者使用连续时间优化器后者更为复杂。更常见的做法是直接使用离散模型。注意线性模型的有效范围仅限于工作点附近。当摆角偏离π/4较大时sin(θ)≈θ的假设不再成立用这个模型去预测未来状态会产生显著误差导致MPC基于错误预测做出的优化决策可能是次优甚至 destabilizing导致不稳定的。这是线性MPC最主要的局限性。4.2 离散线性模型DLM的构建与应用离散模型是MPC实践中最常用的形式因为它天然契合数字控制器的采样周期。我们可以通过多种方法将连续模型离散化如零阶保持法、一阶保持法、双线性变换等。对于MPC最常用的是零阶保持法它假设控制输入在两个采样点之间保持恒定这正好符合我们数字控制器输出保持的特性。Matlab提供了c2d函数可以方便地完成这个转换%% 2.2 构建离散线性模型 (DLM) sys_dlm c2d(sys_clm, Ts, zoh); % ‘zoh’代表零阶保持器 [Ad, Bd, Cd, Dd] ssdata(sys_dlm);现在我们得到了离散状态空间方程x(k1) Ad * x(k) Bd * u(k)y(k) Cd * x(k)这个方程是MPC预测的核心。给定当前时刻k的状态x(k)和未来一系列控制输入{u(k), u(k1), ..., u(kNc-1)}我们可以递归地预测出未来Np个时刻的状态x(k1|k) Ad*x(k) Bd*u(k)x(k2|k) Ad*x(k1|k) Bd*u(k1) Ad^2*x(k) Ad*Bd*u(k) Bd*u(k1)... 依此类推。我们可以将这些预测方程整理成矩阵形式构造一个大的预测方程X P*x(k) H*U其中X是未来状态向量U是待优化的控制序列P和H是由Ad和Bd构成的矩阵。这种形式可以将MPC的优化问题转化为一个标准的二次规划问题求解效率非常高。4.3 连续非线性模型CNM的精确描述为了捕捉系统的真实动态我们必须回到最初的非线性微分方程。在Matlab中我们通常用一个函数文件来定义这个模型。新建一个文件pendulum_ode.mfunction dx pendulum_ode(t, x, u, m, L, c, g) % 连续非线性模型ODE % x(1) theta, x(2) dtheta/dt % u 控制扭矩 theta x(1); dtheta x(2); dx zeros(2,1); dx(1) dtheta; dx(2) -(g/L)*sin(theta) - (c/(m*L^2))*dtheta (1/(m*L^2))*u; end这个函数精确描述了系统在任意状态和控制输入下的瞬时变化率。在MPC的框架下使用连续非线性模型进行预测意味着在每个优化周期内我们需要数值积分这个ODE从当前时刻到未来Np*Ts的时刻。这通常通过调用ODE求解器如ode45在预测时域内进行滚动积分来实现计算量远大于线性模型。4.4 离散非线性模型DNM的实用化实现直接积分连续ODE计算量太大不适合实时性要求高的MPC。一个折中的方案是手动离散化非线性模型。我们采用欧拉前向差分法这是一种显式方法虽然精度不如高阶龙格库塔法但计算简单对于小采样周期Ts的系统常常够用。离散化公式为x(k1) ≈ x(k) Ts * f(x(k), u(k))其中f(x,u)就是上面pendulum_ode函数右边的向量。我们在主脚本中定义一个匿名函数来实现这个离散非线性模型%% 2.4 构建离散非线性模型 (DNM) - 欧拉法 f_nonlinear (x, u) [x(2); ... -(g/L)*sin(x(1)) - (c/(m*L^2))*x(2) (1/(m*L^2))*u]; predict_dnm (x0, U_seq) predict_nonlinear_euler(f_nonlinear, x0, U_seq, Ts, Np);这里predict_nonlinear_euler是一个我们需要编写的预测函数它接受初始状态x0、控制序列U_seq、采样时间Ts和预测步长Np通过欧拉法迭代计算出未来状态轨迹。这个模型比连续非线性模型计算快又比线性模型更接近真实是工程中处理温和非线性的常用手段。5. MPC控制器设计与滚动优化实现有了预测模型我们就可以设计MPC控制器了。MPC的核心是一个在线的、带约束的优化问题。在每个采样时刻k我们测量或估计当前状态x(k)。以x(k)为初始条件利用模型预测未来Np步的状态轨迹X该轨迹是未来Nc步控制序列U [u(k), u(k1), ..., u(kNc-1)]^T的函数。求解一个优化问题其目标函数通常是未来预测状态与期望状态设定点的偏差、以及控制量大小的加权平方和同时满足控制输入约束。将优化得到的最优控制序列的第一个元素u*(k)施加到实际系统上。在下一个采样时刻k1重复步骤1-4。我们以最常用的离散线性模型为例展示如何构建这个优化问题并求解。目标函数通常为J Σ_{i1}^{Np} (x(ki|k) - x_ref)^T Q (x(ki|k) - x_ref) Σ_{j0}^{Nc-1} u(kj)^T R u(kj)其中x_ref是期望的状态设定点。通过前面提到的预测方程X P*x(k) H*U我们可以将目标函数J重写为控制序列U的二次型J 1/2 * U^T * H_hess * U f^T * U constant其中H_hess 2*(H^T * \bar{Q} * H \bar{R})f 2*(x(k)^T * P^T * \bar{Q} * H - x_ref^T * \bar{Q} * H)\bar{Q}和\bar{R}是块对角化的权重矩阵。这是一个标准的二次规划问题。在Matlab中我们可以使用quadprog求解器来解这个带约束的QP问题。下面是一个简化的实现框架%% 3. 基于离散线性模型DLM的MPC滚动仿真 % 构建预测矩阵P和H这部分需要根据Ad, Bd, Np, Nc推导和编码 [P, H] build_prediction_matrices(Ad, Bd, Np, Nc); % 构建二次规划问题的Hessian矩阵和梯度向量 Q_bar kron(eye(Np), Q); % 块对角矩阵 R_bar kron(eye(Nc), R); H_hess 2 * (H * Q_bar * H R_bar); % quadprog要求目标函数为 1/2*x*H*x f*x % 设定点 x_ref [pi/4; 0]; % 期望摆角45度角速度为零 % 初始化 x0 [0; 0]; % 初始状态摆锤自然下垂静止 x_history x0; u_history []; sim_steps 100; % 仿真总步数 % 滚动优化循环 x_current x0; for k 1:sim_steps % 构建当前时刻的梯度向量 f f 2 * (x_current * P * Q_bar * H - x_ref * kron(ones(Np,1), eye(2)) * Q_bar * H); % 设置控制输入约束 (A_ineq * U b_ineq) A_ineq [eye(Nc); -eye(Nc)]; b_ineq [u_max * ones(Nc,1); -u_min * ones(Nc,1)]; % 注意负号处理 % 使用quadprog求解最优控制序列 options optimoptions(quadprog, Display, off); U_opt quadprog(H_hess, f, A_ineq, b_ineq, [], [], [], [], [], options); % 取出当前时刻的最优控制量 u_current U_opt(1); % 施加控制并利用真实非线性模型模拟系统下一步状态以检验控制效果 % 这里用欧拉法模拟真实系统 x_current x_current Ts * f_nonlinear(x_current, u_current); % 记录历史 x_history [x_history, x_current]; u_history [u_history, u_current]; endbuild_prediction_matrices函数需要根据Ad,Bd,Np,Nc构造P和H矩阵这是MPC实现中的一个关键步骤。对于非线性模型预测无法写成漂亮的线性矩阵形式优化问题也变成了非线性规划需要使用fmincon等求解器计算复杂度会大大增加。6. 四种模型控制效果对比与深度分析为了直观对比四种模型在MPC中的表现我们需要用相同的控制器参数Q, R, Np, Nc, 约束分别基于四种模型进行滚动优化并控制同一个“真实”的非线性系统用pendulum_ode的精确积分模拟。然后对比它们的控制效果、计算时间和鲁棒性。我们设计一个对比实验让摆锤从[0;0]出发目标稳定在[π/4;0]。分别运行基于DLM、CNM、DNM的MPC控制器。对于CLM由于其连续特性在离散时间框架下直接使用不便我们通常将其离散化后使用效果与DLM类似因此主要对比后三者与真实非线性模型的匹配度。仿真结果会揭示几个关键结论计算效率DLM最快DNM次之CNM最慢。因为DLM的预测是矩阵乘法而DNM和CNM需要数值迭代。控制精度小范围在设定点π/4附近DLM基于线性化模型性能可能不错甚至与DNM相差无几。因为此时线性化近似是有效的。控制精度大范围如果设定点改变很大例如从0到π/2DLM的性能会显著恶化可能出现超调过大、收敛慢甚至振荡。因为其预测模型在远离线性化点的地方误差很大。而DNM和CNM则能更好地预测非线性效应给出更合理的控制律表现更优。约束处理三者都能处理控制输入约束。但非线性优化用于CNM和DNM在遇到复杂状态约束时可能比二次规划用于DLM更难求解。实操心得在实际工程中模型的选择永远是精度和计算复杂度的权衡。对于像化工过程、航空航天器这类强非线性、高动态的系统非线性MPCNMPC是必须的但需要强大的在线计算能力。对于像电机控制、大多数慢速过程控制在工作点附近运行线性MPC已经足够出色且易于实现。离散非线性模型如基于欧拉法是一个很好的折中它比完全的非线性优化计算量小又比线性模型更准确尤其适合嵌入式系统或对实时性要求较高的场合。7. 常见问题与排查技巧实录在实现和调试MPC控制器的过程中你几乎一定会遇到下面这些问题。这里记录了我的踩坑经验和解决方案。问题1MPC优化求解器quadprog报错“Hessian矩阵非正定”或问题不可行。原因分析这通常是由于预测矩阵H或权重矩阵Q、R的设置不当导致的。H矩阵可能因为系统不可控或Np/Nc设置不合理而出现病态。R矩阵权重过小或为零会使Hessian矩阵半正定。排查步骤检查系统(Ad, Bd)是否可控使用ctrb命令计算可控性矩阵的秩。检查权重矩阵Q和R。R必须为正定标量情况即为正数以确保问题严格凸。可以尝试增大R的值。检查Nc是否小于等于Np且Np是否足够大以捕捉系统动态。对于非线性模型用fmincon检查初始猜测U0是否合理可以尝试用上一时刻的解作为初始值warm-start。问题2控制器震荡或发散无法稳定。原因分析预测模型不准确是首要原因。特别是使用线性模型控制非线性系统时在大信号下模型误差会导致预测失准进而产生错误的控制指令形成正反馈。排查步骤模型验证在开环情况下分别用你的预测模型和“真实”模型高精度仿真模型施加相同的控制序列看预测的状态轨迹是否匹配。这是验证模型准确性的黄金标准。调整权重增大状态误差权重Q尤其是速度误差或减小控制权重R会让控制器更“激进”地纠正误差但可能引发震荡。需要反复调试。缩短预测时域Np太小控制器可能变得短视引发震荡。适当增加Np让控制器看得更远往往能提高稳定性。加入终端约束或终端代价这是一个高级技巧强制预测时域末端的状态接近设定点可以保证闭环稳定性。问题3计算时间过长无法满足实时性要求。原因分析对于非线性MPC每个采样周期都要解一个非线性规划问题计算负担很重。优化技巧减少优化变量减小控制时域Nc。这是最有效的方法。使用更简单的模型用离散非线性模型DNM代替需要积分的连续非线性模型CNM。使用显式MPC对于线性系统可以离线求解所有可能状态下的优化问题在线查表。但这只适用于状态和输入维度很低、约束为多面体的情况。代码优化使用更高效的QP/NLP求解器或利用问题的特殊结构如稀疏性。问题4系统存在稳态误差。原因分析线性模型在工作点线性化时忽略了常数项d或者系统存在未建模的常值扰动如恒定负载。解决方案引入积分动作在MPC框架中通常将状态误差的积分作为新的状态变量加入模型。例如定义x_aug [x; ∫(y-ref) dt]然后为增广系统设计MPC。这能有效消除稳态误差。前馈补偿如果扰动或参考变化的模型已知可以将其作为前馈项直接加到控制输入中。问题速查表现象可能原因优先检查项求解器报错非正定/不可行1. 模型不可控2. 权重矩阵设置不当3. 约束冲突1.rank(ctrb(Ad, Bd))2. 确保R 03. 检查u_min,u_max是否合理闭环系统震荡或发散1. 预测模型误差大2. 权重Q/R失调3. 预测时域Np太短1. 开环模型验证2. 调整Q、R尝试增大Q或R3. 适当增加Np计算超时无法实时运行1.Nc或Np太大2. 非线性优化复杂3. 求解器效率低1. 减小Nc2. 考虑使用线性或离散非线性模型3. 尝试不同的求解器或选项存在稳态误差1. 模型有未补偿的常数项/偏差2. 存在常值扰动1. 在模型中引入积分状态增量式MPC2. 加入扰动观测器或前馈最后分享一个调试中的小技巧始终先做开环测试。在连接闭环之前用你的MPC预测函数给定一个初始状态和一组假设的控制序列画出预测的状态轨迹。同时用你的“真实”系统模型高精度仿真在同样的控制序列下运行画出真实轨迹。将两者对比你能最直接地评估你的预测模型是否可靠。如果开环预测都差之千里那么闭环控制必然问题重重。这个习惯能帮你节省大量盲目调试闭环参数的时间。模型预测控制说到底预测的准确性决定了控制的上限。把模型建好、验好你的MPC就成功了一大半。