Koopman算子+EDMD:四旋翼数据驱动建模与MPC预测控制

发布时间:2026/10/3 15:30:49
Koopman算子+EDMD:四旋翼数据驱动建模与MPC预测控制
简介基于Koopman算子与扩展动态模式分解EDMD的四旋翼无人机数据驱动控制Matlab实现方案面向计算机、电子工程及数学专业学生可用于课程项目、综合实验与毕业课题。压缩包共包含90个文件其中核心为41个脚本与函数文件另配有可视化图片、仿真数据、幻灯片说明及备份内容整体约49.66MB并兼容Matlab 2014、2019a与2024a等版本便于多环境使用。当前已有110人学习下载。整个方案重点演示了基于Koopman算子将非线性系统转化为线性描述的方法以及利用EDMD从实际测量数据中提取动态模式的具体流程代码中包含模型预测控制、EDMD评估与轨迹生成等模块均采用参数化设计并附有详尽注释实验数据可直接加载复现便于理解关键数据结构与算法逻辑。通过学习读者能够掌握四旋翼数据驱动建模与控制的核心步骤理解特征值分析、控制性能对比等难点为后续研究或毕业设计提供实践基础。1. 直接给四旋翼建模为什么越建越虚Koopman算子换了个玩法做四旋翼无人机控制的人大概都有同感动力学看着简单真要把模型建到能上机的精度质量、转动惯量、气动系数每一个都够折腾。小角度假设能把姿态方程拉成线性但一旦做大速度机动或重载飞行线性模型又立刻失效。这两年我在Matlab里试了一套基于Koopman算子与EDMD算法的数据驱动控制方案绕开逐项参数辨识直接用飞行状态数据把非线性动力学提升成高维线性模型再在这个线性模型上设计MPC。这套方案尤其适合做控制算法预研、仿真验证和课题起步不需要额外硬件不依赖精确气动参数一台装好Matlab的电脑就能把整条链路跑通。2. 先把Koopman算子讲透非线性系统在什么条件下能变成线性模型2.1 Koopman算子到底在做什么状态提升与线性演化传统建模思路是直接写状态方程x_{k1} F(x_k)。四旋翼的F包含推力与姿态的耦合、角速度到欧拉角变化率的三角函数、以及空气阻力这类非线性项形式很复杂。Koopman算子的核心想法是换个视角不去线性化F本身而是找一个观测函数g让g(x_{k1}) K g(x_k)成立。这里的K是这个无穷维线性空间上的算子它不近似F而是精确地描述所有观测函数的演化。这个「换空间」的代价是把有限维状态提升到无穷维函数空间。实际使用中我们用一组有限的字典函数{ψ_1, ψ_2, ..., ψ_N}张成一个子空间在这个子空间里找一个K的有限维矩阵近似。只要字典选得好非线性动力学在这个提升空间里可以被一个常数矩阵准确描述且适用范围比在原始状态上的局部线性化宽得多。这正是Koopman算子跟传统泰勒展开线性化的本质区别它不做局部近似而是做全局嵌入。实现上我们把原始状态x提升为z [x; sin(x_i); cos(x_j); x_i*x_j; ...]然后假设z_{k1} A z_k B u_k。这里的A矩阵就是Koopman矩阵的有限维实现B矩阵处理控制输入。Koopman算子在这里起的作用不是某个具体数值而是一整套提法先定观测空间再在观测空间上求线性演化。2.2 EDMD算法从快照数据回归Koopman矩阵EDMDExtended Dynamic Mode Decomposition扩展动态模态分解是求这个Koopman矩阵最常用的数据驱动方法。它的输入是一组快照对状态序列x_1, x_2, ..., x_{m1}以及对应的下一时刻状态y_k x_{k1}。把每个快照都通过字典函数提升成向量ψ(x)然后构造两块数据矩阵Ψ_X [ψ(x_1), ψ(x_2), ..., ψ(x_m)]Ψ_Y [ψ(y_1), ψ(y_2), ..., ψ(y_m)]如果字典函数张成的空间足够好那么存在矩阵K使得Ψ_Y ≈ K Ψ_X。用最小二乘求解K Ψ_Y · pinv(Ψ_X)。等价写法是K (G λI)^{-1} A其中G Ψ_X Ψ_X^T是协方差矩阵A Ψ_X Ψ_Y^T是互协方差矩阵λ是正则化系数。EDMD算法落地步骤非常直白从仿真或实飞记录里取等间隔的状态序列与控制序列定义字典函数集写出提升函数lift(x)对每个时刻k构造快照对(x_k, x_{k1})生成矩阵Ψ_X和Ψ_Y用伪逆或带正则化的最小二乘求K验证K的特征值是否位于单位圆内以及提升模型的预测误差。这个流程用Matlab实现核心代码往往不超过二十行。但EDMD的结果质量高度依赖第2步的字典设计字典太小无法表达非线性结构字典太大会让回归矩阵病态。悬停点附近用几次多项式就够了要覆盖大角度机动就必须引入三角函数与耦合项。2.3 为什么偏偏是四旋翼耦合、欠驱动与弱非线性假设四旋翼是典型的欠驱动系统四个电机输入控制六个自由度。它的动力学非线性主要体现在三个方面推力矢量随姿态变化、欧拉角运动学方程中的三角函数耦合、以及高速飞行时的气动阻力。很多控制方案在小角度假设下线性化把耦合项当作扰动交给PID去扛。这个方法在悬停和小机动场景够用但做大速度前飞、大角度拉起时线性模型里的耦合项误差会被MPC这类预测控制器放大。数据驱动控制解决的是「模型精度与建模成本」的矛盾。Koopman算子对四旋翼特别合适的原因在于四旋翼动力学不是强非线性或混沌系统它的非线性主要来自姿态三角函数的耦合与二次型阻力这些恰好都能被多项式字典和三角函数字典有效表达。也就是说用EDMD把12维状态提升到30到80维的字典空间线性模型的预测精度就足够支撑MPC设计。另外一个工程层面的理由传统方法需要精确的转动惯量、电机时间常数、升力系数等参数这些参数在不同载荷条件下都会漂移。EDMD不需要这些物理参数的准确值它直接从飞行数据里学出输入到状态演化的映射关系换一架负载不同的机架时重新录一段数据重跑一遍辨识就能更新模型。这个特性让它在快速原型验证里特别省事。3. Matlab跑通EDMD辨识从仿真数据到Koopman矩阵3.1 在Matlab里搭一个带激励的四旋翼数据源在Matlab里定义微分方程有几种常见姿势可以用ode45配函数句柄也可以用离散递推。做EDMD我一般直接用离散递推因为后面辨识需要等间隔采样递推模型天然就是一步预测的形式。下面是我在脚本里用的简化四旋翼刚体模型速度环、位置环不展开状态取为[位置, 速度, 欧拉角, 角速度]共12维。% 四旋翼刚体动力学离散递推dt为采样周期 function x_next quad_dynamics(x, u, dt) % x: [px; py; pz; vx; vy; vz; phi; theta; psi; p; q; r] % u: [thrust; tau_phi; tau_theta; tau_psi] g 9.81; m 1.2; Ixx 0.008; Iyy 0.008; Izz 0.014; phi x(7); theta x(8); psi x(9); p x(10); q x(11); r x(12); % 位置导数机体速度旋转到世界系 R euler_to_R(phi, theta, psi); vel_world R * x(4:6); % 力方程thrust沿机体z轴重力沿世界z轴 accel_body [0; 0; u(1)/m] - R * [0; 0; g]; accel_world R * accel_body; % 姿态运动学欧拉角变化率与体角速度关系 phi_dot p q*sin(phi)*tan(theta) r*cos(phi)*tan(theta); theta_dot q*cos(phi) - r*sin(phi); psi_dot (q*sin(phi) r*cos(phi)) / cos(theta); % 角速度动力学欧拉方程(忽略陀螺力矩) p_dot (u(2) (Iyy-Izz)*q*r) / Ixx; q_dot (u(3) (Izz-Ixx)*p*r) / Iyy; r_dot (u(4) (Ixx-Iyy)*p*q) / Izz; x_next x dt * [vel_world; accel_world; phi_dot; theta_dot; psi_dot; p_dot; q_dot; r_dot]; end这段代码的R euler_to_R(phi, theta, psi)负责把机体速度转到世界系实际使用时可以用angle2dcm函数替代。关键参数是采样周期dtEDMD要求数据是等间隔的我习惯设dt 0.01秒也就是100Hz控制频率。状态序列x的维度是12控制输入u的维度是4。升力系数、转动惯量在仿真里是「真实」参数但EDMD辨识时完全用不到这些数值这正是数据驱动的意义。采集数据时不能只录悬停激励信号很关键。我一般用悬停油门叠加扫频信号频率从0.1Hz扫到10Hz覆盖姿态和速度的主要动态范围。Matlab里生成这种激励用chirp函数即可幅值取悬停油门值的5%到15%太大容易让欧拉角超出小角度假设太小又激发不出非线性特征。3.2 字典函数怎么选从单项式到三角函数再到耦合项字典设计是EDMD里最影响结果的操作也是我觉得最像「调参玄学」的地方。我的默认策略是原始状态必须包含在字典里否则最后预测出的状态没法直接从提升空间里读出来。除此之外加三类扩展项——状态的平方项、欧拉角的三角函数项、以及速度与姿态角的耦合项。下面这个字典在12维状态上扩展到了54维基本覆盖四旋翼在中等机动范围内的非线性特征。% 构造提升向量z lift(x)字典由多项式、三角函数与耦合项组成 function z lift(x) % 基础状态位置、速度、欧拉角、角速度 z x; % 速度平方项表达阻力与动压效应 v x(4:6); sq v.^2; z [z; sq]; % 姿态角三角函数表达重力分量与旋转矩阵元素 sphi sin(x(7)); cphi cos(x(7)); stheta sin(x(8)); ctheta cos(x(8)); spsi sin(x(9)); cpsi cos(x(9)); z [z; sphi; cphi; stheta; ctheta; spsi; cpsi]; % 速度与姿态角的耦合项表达推力矢量在速度方向的投影 z [z; v(1)*stheta; v(2)*sphi; v(3)*stheta; v(1)*cphi]; % 角速度平方项表达陀螺进动力矩 omega x(10:12); z [z; omega(1)*omega(2); omega(2)*omega(3); omega(3)*omega(1)]; end字典把12维状态提升到了54维。第一项到第十二项就是原始状态本身这样预测结束后可以直接取z的前12个分量恢复出x的预测值。速度平方项用来拟合空气阻力三角函数项覆盖欧拉角到旋转矩阵的映射耦合项解决水平速度与姿态角之间的联动。这四个耦合项的选择依据是四旋翼的平移动力学前飞时推力倾斜产生的水平加速度与theta成正比侧向力与phi相关。做EDMD最忌讳字典设计不看物理背景。比如把状态的所有五次方项都加进去维数直接飙升到上百条件数恶化不说辨识出来的模型抗噪声能力也差。可以先用这个54维字典跑一遍看预测误差主要出现在哪些状态上再有针对性地补字典而不是一次性堆满。3.3 用伪逆求解Koopman矩阵一条命令背后的数值风险数据生成和字典定义好之后EDMD求解本身只有几行代码。将状态序列提升成矩阵Ψ_X和Ψ_Y然后用右除算子求解K。这个右除本质上是最小二乘等价于pinv伪逆但对矩阵结构更友好速度也更快。% 从仿真数据辨识Koopman矩阵 % u_all: 4xN 控制输入x_all: 12xN 状态序列 N size(x_all, 2); % 提升所有快照生成字典矩阵 Psi_X zeros(dim_z, N-1); Psi_Y zeros(dim_z, N-1); for k 1:N-1 Psi_X(:, k) lift(x_all(:, k)); Psi_Y(:, k) lift(x_all(:, k1)); end % 最小二乘求Koopman矩阵右除等价于 Psi_Y * pinv(Psi_X) K Psi_Y / Psi_X; % 检查K的特征值是否都在单位圆内 ev eig(K); disp([max abs eigenvalue , num2str(max(abs(ev)))]);这段代码里Psi_X的每一列是一个快照的提升向量Psi_Y的对应列是下一时刻的提升向量。K的维度是dim_z乘dim_z这里就是54乘54。如果max abs eigenvalue大于1.01说明模型有不稳定模态通常是字典病态或数据激励不足导致的要先排查而不是急着接控制器。单靠特征值还不够我会再做一次开环预测验证从某个初始状态出发用辨识出的K独立推50步把预测轨迹与真实仿真轨迹对比计算归一化均方根误差。% 开环预测验证对比EDMD模型与真实模型的轨迹 x_pred zeros(12, H); z lift(x_all(:, 1)); % 取第一帧作为初始提升状态 for k 1:H z K * z; x_pred(:, k) z(1:12); % 前12维还原原始状态 end % 归一化误差 err x_pred - x_all(:, 1:H); nmse sum(err.^2, all) / sum(x_all(:, 1:H).^2, all); fprintf(NMSE %.4f\n, nmse);预测误差如果超过5%我一般先怀疑字典不充分比如缺少某个耦合项如果误差集中在姿态角优先在字典里补三角函数相关项如果误差在所有维度均匀偏大则考虑数据激励幅值不够。开环验证通过后再进入控制器设计阶段。4. 在Koopman线性模型上设计MPC预测控制与Matlab求解4.1 从提升状态到线性预测模型A、B矩阵的组合回归上一章的K只表达了无控制输入的自由演化。四旋翼必须有控制输入所以需要把EDMD扩展成带输入的回归形式z_{k1} A z_k B u_k。严格来说四旋翼是控制仿射系统提升之后理论上会变成双线性结构输入与状态相乘的项但工程实践里我们在工作点附近把B当作常数矩阵处理悬停和中低速机动范围内精度足够。求A和B的做法是把输入也放进回归变量里一边是[Ψ_X; u]另一边是Ψ_Y这样解出来的矩阵前半部分对应A后半部分对应B。% 带控制输入的EDMDz_{k1} A * z_k B * u_k % 构造组合回归矩阵 X_reg [Psi_X; u_all(:, 1:N-1)]; % (dim_z 4) x (N-1) Y_reg Psi_Y; % dim_z x (N-1) % 最小二乘组合求解 M Y_reg / X_reg; A M(:, 1:dim_z); B M(:, dim_z1:end); % 稳定性检查 if max(abs(eig(A))) 1.01 warning(A矩阵存在不稳定模态请检查字典与激励信号); end这里B矩阵的物理含义是每个控制通道推力、滚转力矩、俯仰力矩、偏航力矩对全部54个字典状态的单步影响。因为B是从数据里回归出来的它天然包含了输入到加速度、角加速度的增益关系不需要单独辨识转动惯量。要注意的是B是常数矩阵一旦机动幅度变大B的精度会下降这是这种方法的边界。4.2 用quadprog写线性MPC约束、参考值与代价函数有了线性模型z_{k1} A z_k B u_kMPC设计就成了标准的线性二次规划问题。目标函数惩罚三类量未来预测状态与参考值的偏差、控制量大小、以及控制量变化率。约束条件包括电机推力上下限和姿态角速率限制。在Matlab里我用quadprog求解这个QP问题。function [u_opt, z_pred] koopman_mpc(z0, u_prev, x_ref, A, B, C, Np, Nc, Q, R, umax) % z0: 当前提升状态C: 从提升状态提取原始状态的矩阵 % Np: 预测时域步数Nc: 控制时域步数 dim_z length(z0); dim_u size(B, 2); % 构造预测矩阵Z_pred Phi_z * z0 Phi_u * U % 这里用循环构造方便理解大规模场景可以换为稀疏矩阵 Phi_z zeros(Np*dim_z, dim_z); Phi_u zeros(Np*dim_z, Nc*dim_u); % 状态传播z_{k1} A z_k B u_k A_pow eye(dim_z); for i 1:Np A_pow A * A_pow; Phi_z((i-1)*dim_z1 : i*dim_z, :) A_pow; for j 1:min(i, Nc) A_pow_ij A^(i-j); Phi_u((i-1)*dim_z1 : i*dim_z, (j-1)*dim_u1 : j*dim_u) A_pow_ij * B; end end % 目标函数矩阵只惩罚原始状态分量(C*z)不需要给所有字典状态设参考 Q_bar kron(eye(Np), C * Q * C); R_bar kron(eye(Nc), R); H Phi_u * Q_bar * Phi_u R_bar; f Phi_u * Q_bar * (Phi_z * z0 - repmat(x_ref, Np, 1)); % 输入幅值约束 lb -umax * ones(Nc*dim_u, 1); ub umax * ones(Nc*dim_u, 1); % 求解QP options optimoptions(quadprog, Display, off); U quadprog(2*H, 2*f, [], [], [], [], lb, ub, [], options); u_opt U(1:dim_u); z_pred Phi_z * z0 Phi_u * U; end这个MPC函数里有几个容易绕进去的点。第一个是参考值只能针对原始状态定义比如位置、速度、姿态角不能针对全部54维字典状态因为RBF或平方项根本没有物理含义。所以我用C矩阵把预测状态映射回12维原始状态再用Q矩阵加权。第二个是构造Phi_u矩阵时j循环只跑到min(i, Nc)控制时域之后的输入保持为0这是MPC约定俗成的处理。第三个是quadprog被写成了2H和2f这是因为quadprog默认最小化0.5*xHx fx而标准MPC代价是xHx fx要换算系数。4.3 闭环仿真与控制器参数调法闭环仿真就是把MPC编进主循环里每步采样后用当前状态求解控制量再作用到四旋翼模型上。这是在Matlab里验证整套方案的最后一步也是暴露模型失配问题的关键时刻。% 闭环仿真主循环 x x_init; u u_hover; x_log zeros(12, T_total); for k 1:T_total z_k lift(x); [u, ~] koopman_mpc(z_k, u, x_ref, A, B, C, 30, 5, ... diag([10 10 10 1 1 1 5 5 5 0.1 0.1 0.1]), ... 0.1*eye(4), 2.0); x quad_dynamics(x, u, dt); x_log(:, k) x; end预测时域Np我习惯取30步对应0.3秒的预测长度对四旋翼姿态控制足够又不至于让QP矩阵过大。控制时域Nc取5到8步太大会让优化变量过多、求解变慢太小会丧失MPC的预见性。Q权重里位置和速度的权重是关键想让无人机快速跟踪轨迹就加大位置权重想让姿态过渡平顺就提高姿态角权重并压低角速度权重。R取0.1 * eye(4)表示对四个控制通道施加相同程度的惩罚实际调试如果发现油门抖动先把R对应的推力通道权重加大到0.5。调参顺序上我的经验是先固定R把Q从大到小试一遍找到临界稳定的点再固定Q微调R消除高频抖动最后再微调Np和Nc。如果闭环一开始就发散先别急着调权重回头检查A矩阵特征值和开环预测误差大概率是模型本身没辨识好。5. EDMD落地最容易翻车的5个坑从字典病态到闭环发散5.1 数值病态与字典设计问题条件数过大导致K矩阵不可用现象Psi_X矩阵的条件数高达1e14求解出的K不满足稳定性检查特征值散落在单位圆外开环预测几步就爆掉。原因字典里混入了量级差异极大的特征。比如位置状态可能是10米量级角速度可能是2弧度每秒量级而速度平方项直接到了100。这些不同量纲的观测函数放在同一个矩阵里最小二乘会被大数值项主导小数值项对应的动力学被数值噪声淹没。另一个常见诱因是两个字典函数高度线性相关比如同时加入了sin(phi)和phi或者同时加入了cos(theta)和1 - theta^2/2。解决先对每个字典分量做归一化。统计训练数据里每个字典分量的均值和标准差把Psi_X和Psi_Y都减去均值再除以标准差求解完成后再把A矩阵还原到原始量纲。用Matlab的zscore函数就能做。同时检查字典函数是否线性独立用rank(Psi_X)对比矩阵行数缺秩就删掉冗余项。我常用的做法是先用54维基础字典出现问题再逐步加项而不是一次性堆到上百维。5.2 欧拉角在正负180度跳变导致预测发散现象开环验证里俯仰角或偏航角预测误差随时间线性增大一旦无人机做了超过90度的翻转预测立刻跳到完全相反的方向。原因欧拉角本身不是连续量psi从179度变到-179度时数值跳了358度但实际飞机姿态只变了2度。EDMD回归的是数值映射关系它无法理解这种跳变背后的拓扑含义于是把一次正常的跨越边界当作一次剧烈的动力学事件预测自然爆掉。解决不要直接用欧拉角作为字典分量改用旋转矩阵的元素或四元数。最省事的方法是把姿态表示换成欧拉角的三角函数组合也就是字典里的sphi、ctheta这些项原始状态里的欧拉角仍然保留给参考值和显示用但预测循环内部操作的是提升状态。如果一定要直接预测欧拉角就在采集数据之前把psi序列做unwrap处理让角度序列连续变化但这个方法只对小角度范围有效。5.3 数据激励不足悬停数据辨识出的模型在机动时失效现象用悬停加小幅扰动数据辨识出的模型开环验证NMSE只有1%但接上MPC做大机动跟踪时预测轨迹和实际轨迹迅速分离控制器在机动指令发出后出现明显的滞后和振荡。原因EDMD本质上是在拟合字典空间内的输入输出映射。训练数据没有覆盖的动力学区域模型完全靠外推。悬停数据里速度始终接近零速度平方项的系数拟合出来接近于随机值一旦做大速度前飞平方项被激活错误的系数就直接体现在预测误差里。这跟神经网络过拟合是一个道理只是EDMD的字典是显式的更容易看清症结。解决采集数据时把激励幅值放宽到目标工作范围。做轨迹跟踪就往对应的速度区间扫频做大姿态机动就加入方波形式的姿态指令激励。更稳妥的做法是设计一个递进式的数据采集流程先用小幅激励辨识一个粗模型在这个模型上跑一个保守的MPC再用闭环数据二次辨识逐步扩大工作范围。用闭环数据做EDMD时要注意把输入也记录下来闭环EDMD的关键是回归新数据时把历史模型作为先验正则项防止新数据覆盖掉悬停附近的动态。5.4 闭环里预测误差累积开环验证通过但闭环发散现象开环预测50步的NMSE只有3%看起来模型质量很好。一旦接入MPC闭环第一个步长还正常二十步之后控制量开始高频振荡最终发散。原因开环预测误差是单步误差不断累加的结果而闭环控制会实时纠正真实状态与预测状态的偏差。问题往往不在模型精度而在于MPC对模型失配的反馈增益太高。Koopman模型在字典子空间内的预测是线性的但真实系统的非线性残留会让MPC的优化解在某些状态上产生过大的控制增量这些增量反过来又让模型在下一步更不准确形成恶性循环。解决给MPC增加鲁棒性手段。第一是在代价函数里加入控制增量惩罚项限制控制量每一步的变化幅度避免模型失配带来的控制量突变。第二是把持续扰动当作附加状态在预测模型里加一项L(z - z_true)作为误差反馈修正项其中L通过对比历史预测误差统计得出。第三是保守地缩短预测时域Np从30步收到15步虽然预见性变弱但模型失配的影响在短时域内被摊薄。最后一种做法是牺牲一部分性能把Q权重里速度项降低让控制器不那么激进地响应预测偏差。5.5 求解方式用错右除、伪逆与截断SVD的选择现象同样的快照数据用Psi_Y / Psi_X快速求解得到的结果正常换成pinv(Psi_X) * Psi_Y之后K的特征值出现变化MPC效果也差了一截。原因右除和pinv在线性代数里数学上等价但数值行为不同。右除算子对欠定和接近病态的矩阵会走最小二乘路径遇到奇异值极小的方向会自动丢弃部分信息。pinv默认保留所有非零奇异值当Psi_X存在接近零的奇异值时逆运算会把噪声放大到离谱的程度。两种求解方式在不病态的矩阵上结果一致但四旋翼字典矩阵经常不是良态的。解决统一使用带截断的求解方式。先对Psi_X做奇异值分解把小于最大奇异值千分之一的奇异值直接归零再求伪逆。Matlab里可以用[U,S,V] svd(Psi_X)把S的对角元小于eps * max_sv的部分置零然后重建伪逆。或者更省事的方式是给正规方程加一个小正则项。这一步的差别在开环验证里不容易看出来但往往决定了闭环能不能稳定。6. 从离线辨识到在线修正收敛性检查与字典再设计Koopman模型不是辨识完就能一直用的。每次换载荷、改机架、换旋翼动力学都会变数据驱动模型最实际的维护方式是新数据进来之后做增量更新。EDMD的增量版实现起来很简单EDMD求解的中间量G和A可以累加新数据到来时把新的快照对加入G和A不需要重新遍历历史数据。Matlab里维护这两个累加矩阵用G_new G_old Psi_X_new * Psi_X_newA_new A_old Psi_X_new * Psi_Y_new再对G_new加一个极小的单位阵正则项直接解K G_new \ A_new。字典再设计要基于残差分析而不是拍脑袋。完成一轮辨识后把预测残差按12个原始状态分量分别统计哪个方向误差大就在哪个方向补字典。比如位置预测误差偏大通常是速度与姿态的耦合项不足偏航角误差偏大通常是psi的三角函数项缺失或者欧拉角跨越边界。每次补字典之后重新跑开环预测观察NMSE是否真的下降如果加了新项但误差没变说明该项与现有字典线性相关直接去掉不要舍不得。我这几年的习惯是每个项目都固定保留两份脚本一份是EDMD辨识与验证一份是MPC闭环仿真。辨识脚本里把字典结构、激励信号、求解方式全部参数化换新机型时只改参数不重写代码。闭环仿真里固定记录特征值、开环NMSE和闭环跟踪误差三个指标任何修改都以这三个指标不变差为准。先开环后闭环先调字典后调控制器这个顺序帮我避开了大半的调试翻车现场。这套方案从仿真到半实物仿真的迁移路线也清晰把辨识脚本里的仿真数据源替换成飞行日志MPC的输入输出接口不变就可以直接验证真实飞行数据下的控制效果。希望帮到你。本文还有配套的精品资源点击获取