第四章 预测模型:状态空间模型、传递函数模型、阶跃响应模型

说到MPC的预测模型,我琢磨了很久该怎么讲清楚。说白了,预测模型就是MPC的"水晶球"——你得靠它看到未来。没有这个水晶球,后面的优化控制全是空谈。

我个人习惯把预测模型分成三类来理解:状态空间模型、传递函数模型、阶跃响应模型。这三种模型各有各的脾气,也各有各的用武之地。今天咱们就一个一个把它们掰开揉碎了讲。

4.1 状态空间模型——我最常用的"老伙计"

状态空间模型,说白了就是用一组一阶微分方程来描述系统。你想想看,一个复杂的工业过程,可能涉及温度、压力、流量好多个变量,状态空间模型就能把这些变量之间的关系理得清清楚楚。

标准形式长这样:

x(k+1) = A·x(k) + B·u(k)
y(k)   = C·x(k) + D·u(k)

其中 x 是状态向量,u 是输入,y 是输出。A、B、C、D 就是系统矩阵。

我在项目中遇到过一件事:有个化工反应器的温度控制,用传递函数怎么调都不对劲。后来换成状态空间模型,把反应器内部的温度分布作为状态变量,一下子就搞定了。为什么?因为状态空间模型能捕捉系统内部的动态特性,而不仅仅是输入输出关系。

4.2 传递函数模型——经典控制的老本行

传递函数模型,搞控制的人应该都不陌生。它用拉普拉斯变换把微分方程变成了代数方程,用起来特别方便。

嗯,这里要注意:传递函数模型只适用于线性时不变系统。如果你遇到的是非线性系统,或者参数随时间变化,那传递函数就不太够用了。

一个小技巧:从传递函数转到状态空间模型,可以用可控标准型或可观标准型。我建议你记住这个转换方法,因为很多实际工程中,我们拿到的是传递函数,但MPC需要的是状态空间模型。

% 从传递函数转到状态空间
G = tf([1 2], [1 3 2]);  % 传递函数
sys = ss(G);              % 转成状态空间

4.3 阶跃响应模型——工业现场的最爱

阶跃响应模型,这个我得好好说说。你想想看,在工业现场,你给系统一个阶跃输入,然后记录输出响应,这不就是最直观的建模方式吗?

阶跃响应模型的数学表达是这样的:

y(k) = y(0) + Σ S(i)·Δu(k-i)

其中 S(i) 是阶跃响应系数,Δu 是输入的变化量。这个模型的好处是:不需要知道系统的内部结构,只需要实验数据。

我曾经踩过一个坑:用阶跃响应模型做MPC时,采样时间选得太大了。结果预测出来的轨迹跟实际系统差了十万八千里。后来才明白,阶跃响应模型的精度很大程度上取决于采样时间的选择。采样时间太大,会丢失系统的动态信息;采样时间太小,模型阶数又太高。

4.4 三种模型的对比与选择

这三种模型到底选哪个?我个人的经验是这样的:

模型类型 优点 缺点 适用场景
状态空间模型 能描述内部动态,适合多变量系统 需要知道系统结构,参数辨识复杂 复杂工业过程、航空航天
传递函数模型 形式简单,经典控制理论成熟 只适用于SISO系统,非线性处理困难 单变量系统、教学演示
阶跃响应模型 不需要模型结构,直接从数据得到 模型阶数高,对噪声敏感 工业现场、过程控制

4.5 从模型到预测——核心逻辑

有了预测模型,我们怎么用它来做预测呢?说白了就是:给定当前的状态和未来的控制输入,用模型算出未来的输出。

以状态空间模型为例,预测的公式是这样的:

Y_p = F·x(k) + G·U

其中 Y_p 是预测的输出序列,U 是未来的控制输入序列,F 和 G 是由系统矩阵 A、B、C 计算得到的预测矩阵。

关键点:预测矩阵 F 和 G 是离线计算好的,在线运行时只需要做矩阵乘法。这就是MPC能实时运行的原因之一。

下面这张图展示了预测模型在MPC中的核心位置:

MPC预测模型核心逻辑 当前状态 x(k) 预测模型 状态空间/传递函数/阶跃响应 未来输入 U 预测输出 Y_p Y_p = F·x(k) + G·U

4.6 实战:用Python实现状态空间预测

光说不练假把式。咱们来看看怎么用Python实现状态空间模型的预测:

import numpy as np

class StateSpacePredictor:
    def __init__(self, A, B, C, D):
        self.A = A
        self.B = B
        self.C = C
        self.D = D
    
    def predict(self, x0, U, N):
        """
        x0: 初始状态
        U: 未来控制输入序列,形状 (N, m)
        N: 预测时域
        """
        n = self.A.shape[0]  # 状态维度
        p = self.C.shape[0]  # 输出维度
        
        # 初始化预测矩阵
        F = np.zeros((p*N, n))
        G = np.zeros((p*N, N))
        
        # 计算F矩阵
        for i in range(N):
            F[i*p:(i+1)*p, :] = self.C @ np.linalg.matrix_power(self.A, i+1)
        
        # 计算G矩阵
        for i in range(N):
            for j in range(i+1):
                G[i*p:(i+1)*p, j] = self.C @ np.linalg.matrix_power(self.A, i-j) @ self.B
        
        # 计算预测输出
        Y_p = F @ x0 + G @ U.flatten()
        
        return Y_p.reshape(N, p)

使用建议:在实际项目中,我一般会把预测矩阵F和G离线算好,存起来。在线运行时只需要做矩阵乘法,速度能快不少。

4.7 模型失配怎么办?

说实话,完美的模型是不存在的。模型和实际系统之间总会有差距,这就是模型失配。我在做项目时遇到过好几次,模型预测得挺好,一上实际系统就翻车。

怎么处理?我的经验是:

  • 加反馈校正:用实际输出和预测输出的差值来修正预测
  • 在线辨识:实时更新模型参数
  • 鲁棒设计:在优化问题中加入约束,让控制器对模型误差不那么敏感

这三种方法各有千秋。我个人比较喜欢加反馈校正,简单有效,而且不会增加太多计算量。

好了,关于预测模型就讲这么多。记住一点:模型是MPC的基石,模型选得好,后面的事就顺了。选模型的时候,多想想你的系统是什么特点,现场能拿到什么数据,计算资源够不够用。这些实际问题,往往比理论推导更重要。

专注资料整理