做控制方向的人,大多都有过同一个烦恼:非线性系统一旦强耦合、带约束,预测和控制两件事都会变得很难啃。传统做法要么上NMPC,在每个采样周期解非线性优化,计算量感人;要么在某个工作点做Taylor展开,用局部线性模型凑合,换一个初始条件可能就崩了。这个项目解决的是一个非常实用的折中问题——用Koopman算子把非线性受控系统在“升维空间”里近似成线性系统,然后在这个线性空间直接跑标准的模型预测控制(MPC)。换句话说,我们不硬解非线性优化,而是先把非线性“洗”成线性,再用成熟的线性MPC体系去控制,既保留了预测控制的约束处理能力,又避开了在线非线性的计算负担。
我最近完整实现并调试了这个方案的Matlab版本,核心流程包括:数据激励、字典函数(lifting functions)设计、用EDMD估计Koopman矩阵、然后用condensing方法构造QP并滚动求解。整个过程用了一个受控Duffing振荡器做测试对象,效果稳定到让人意外。这篇文章会从原理到代码再到避坑,把整个实操路径完整拆开,适合正在做Koopman相关课题、或者想给非线性系统换一个“线性预测器”来匹配MPC的工程师和研究生。你可以不看推导直接抄代码,但我建议至少把第2节和第4节的细节过一遍——那些参数设置和踩坑点,直接决定你复现时效果好坏。
1. Koopman线性预测器:为什么非线性系统要“换个坐标系”看
1.1 非线性预测和控制的老大难问题
模型预测控制的思路其实很朴素:在每个时刻,利用系统模型预测未来一段时域内状态的变化,求解一个有限时域最优控制问题,然后只施加第一段控制,等到下一时刻再用新测量值重新求解。难点在于,如果系统模型是非线性的,这个“有限时域最优控制问题”大概率也是一个非线性非凸优化问题,在线求解的耗时和稳定性都很难保证。
常见的工程妥协方案是在参考工作点附近做Jaccobian线性化,得到线性时变模型,再用线性MPC或者LQR的框架去做。这个方案在小范围波动内是有效的,但本质上是“局部近似”,一旦系统偏离工作点较远,模型失配加剧,预测就会失真,控制质量跟着下降。
另一种更激进的路径是直接上非线性MPC,比如用CasADi配合IPOPT在线求解非线性规划。这个方法精度高,但对实时性要求高的场景不友好,而且对初值和求解器参数非常敏感,一个不好的局部最优解就能让控制器“犯迷糊”。
我当时做这个项目的时候,正是被NMPC的计算开销和局部线性化的脆弱性夹在中间,才决定认真研究Koopman算子这条路线。它提供的不是换一种非线性求解器,而是把“非线性预测”这件事本身转化成“线性预测”的问题——这正好击中了我以前最头疼的两个痛点。
1.2 Koopman算子如何把非线性问题“线性化”
先解释一下Koopman算子的基本思想。考虑一个离散时间系统 x_{k+1}=F(x_k),如果存在一个无限维的线性算子K,作用在观测函数g: X→R 上满足 Kg=g(F(x)),那么K就叫Koopman算子。它的核心特征是:原空间里非线性系统的动力学,在观测函数构成的函数空间里变成了线性的演化关系。
这句话听起来绕,但可以这样理解:我们换了一组“坐标”来看这个系统。原来的坐标是 x,系统演化可能是弯曲的、折叠的;但如果我们把系统抬高到一个更高维的空间里,并且按某种方式选择新坐标——这些坐标就是字典函数 ψ_i(x)——那么系统的演化在新坐标下可以是直的、线性的。当然,这个新空间通常是无限维的,实际做的时候我们只能截取有限维子空间,所以得到的其实是近似线性关系:
ψ(x_{k+1}) ≈ A ψ(x_k) + B u_k
其中 u_k 是控制输入,ψ(x)=[ψ_1(x),ψ_2(x),…,ψ_d(x)]^T 是升维字典向量。A和B就是在这个提升坐标系下的系统矩阵。
对于受控系统,上式本质上是说:我们把状态升高之后,下一时刻的升高向量是当前升高向量和当前控制输入的线性函数。注意,这里不是对原系统做局部线性化,而是在数据覆盖的区域内做一个全局近似的线性化。这也就是标题里所说的“线性预测器”——它用线性模型来预测非线性系统的未来轨迹。
需要提醒的是,Koopman线性预测器并不是万能的。它对系统的控制作用有一个暗含假设:控制输入是线性地进入字典空间。对于很多机械系统、电力电子系统,这个假设基本成立;但如果系统的控制输入本身以强非线性方式进入动力学(比如乘性控制),那就需要改用扩展Koopman/双线性Koopman模型,这个后面会提到。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 从数据到模型:用EDMD学出那个“神奇的线性系统”
2.1 字典函数怎么选:参数与考量
Koopman矩阵 A、B 的估计质量,很大程度上取决于字典函数的选择。字典函数的作用是提供系统的非线性特征,使得系统在这些特征空间中表现出“更多线性”。这其实是一种特征工程:我们希望神经网络里那种自动学特征,而在这里则通常是手动设计。
我在这个项目里测试的对象是带三次弹簧和阻尼的受控Duffing系统:
dx1/dt = x2
dx2/dt = -x1 - 1.0x1^3 - 0.3x2 + u
它的非线性主要体现在 x1^3 项上。因此我选择的字典以多项式函数为主,一直升到4阶,一共15个维度:
- 常数项:1
- 一阶:x1, x2
- 二阶:x1^2, x1x2, x2^2
- 三阶:x1^3, x1^2x2, x1x2^2, x2^3
- 四阶:x1^4, x1^3x2, x1^2x2^2, x1x2^3, x2^4
选择多项式的原因是:Duffing系统的非线性项本身是 x1^3 的多项式形式,用多项式字典可以较好地覆盖。如果你的系统带有sin、cos等周期性动力学(比如倒立摆),那字典里最好加入 sin(x1)、cos(x1) 这类函数,否则用多项式去硬拟合三角函数,需要的阶数和数据量都会暴增。
实际操作中,整个字典的维度不必太大。我试过升级到5阶甚至6阶多项式,结果是线性预测器在训练集上的误差更小,但MPC闭环控制效果反而下降——原因的是高维字典带来过拟合,在验证集上预测偏差增大,优化问题里的高维状态变量也增加了求解器的负担。所以,字典规模的选择本质上是在“表达能力”和“泛化能力”之间做权衡。
2.2 数据生成与EDMD求解:从轨迹到矩阵
EDMD(Extended Dynamic Mode Decomposition)是目前估计Koopman矩阵最常用的方法,核心是最小二乘拟合。给定一批训练数据 (x_k, x_{k+1}) 和对应的控制输入 u_k,我们先计算字典向量 Z_k=ψ(x_k)、Z_k^+=ψ(x_{k+1}),然后构建回归问题:
Zp ≈ W * L
其中 W = [Z, U] 是数据矩阵,L = [A; B] 是待估计的系数矩阵。最小二乘解为:
L = (W^T W + λI)^{-1} W^T Zp
其中λ是正则化系数,用来保证矩阵求逆的数值稳定性。
在生成数据时有一个关键点:激励信号必须充分覆盖状态空间。我用了三段不同初值轨迹,每段3万个采样点,控制输入用随机噪声叠加低频正弦信号,这样可以同时把系统的线性和非线性区域都“激活”出来。训练前,对状态做了一个归一化处理:把
