简介:本资源是一份面向控制理论学习者与工程实践者的H2/H∞混合控制仿真教学包,聚焦于线性系统鲁棒控制设计与MATLAB/Simulink实现,适用于自动化、航空航天及精密机电等领域的高年级本科生、研究生及初级控制工程师。压缩包共17个文件(49KB),包含4个核心MATLAB脚本(如simu_K.m用于控制器参数计算)、3个Simulink模型文件(含H2_Hinf.mdl和h2_hinf_simulation.mdl,支持H2与H∞混合控制器搭建与对比仿真)、5个结果可视化fig图(如gama_H2.fig、turb_W.fig等,直观呈现性能指标与扰动响应),以及2个.r13备份模型和1份hslogic.txt逻辑说明文档。已有313人学习下载,资源结构清晰、模块分工明确:建模→控制器设计→多场景仿真→结果分析形成闭环,可直接运行复现H2最优性能与H∞鲁棒边界验证过程,特别适合理解Roofa67典型被控对象下的控制律构造、γ参数整定及仿真结果解读。 做控制的人,迟早会跟H2控制和H∞控制打照面。不管是做四旋翼的姿态环、机械臂的力控,还是伺服系统的速度环,只要模型是多输入多输出的、还带着一堆不确定性和扰动,传统PID就很容易调到头。我这一两年大部分精力都花在一个代号叫roofa67的小型飞行平台上,一开始也是PID和LQR轮着上,直到把H2/H∞控制器设计的完整流程在MATLAB里跑通、再搬到Simulink仿真里验证之后,才真正想明白现代鲁棒控制在一个具体对象上到底该怎么落地。这篇文章就把我在roofa67上从建模、控制器设计到仿真验证的全过程复盘一遍,适合刚接触鲁棒控制、想用MATLAB把H2/H∞控制器真正跑起来、或者正在折腾多变量飞行器控制器的朋友。
1. 先搞清roofa67是什么,以及为什么非要用H2/H∞不可
1.1 roofa67:一个强耦合MIMO对象的模型化过程
roofa67是我手头一个微型四旋翼验证平台的代号,整机质量1.5公斤左右,轴距约360mm。这种对象最麻烦的地方在于通道之间耦合严重:俯仰角一变,前向速度跟着变;总拉力一加,高度变化的同时机身俯仰也会受影响。想用几个独立PID环把六个自由度全稳住,不是不行,但调试量巨大,而且飞起来手感始终差口气。
H2/H∞这类现代控制方法,第一步要求我们把对象写成状态空间模型。我在做roofa67时,不是直接拿完整12阶模型硬刚,而是先做工作点线性化。在悬停点,把纵向通道和垂直通道拿出来,忽略横滚和偏航的耦合,得到一个5阶模型。状态定义为:
- ( u ):机体前向速度,单位m/s
- ( w ):机体垂向速度,单位m/s
- ( q ):俯仰角速率,单位rad/s
- ( \theta ):俯仰角,单位rad
- ( h ):高度偏差(相对悬停点),单位m
控制输入是两个通道的指令:( \delta_e )是俯仰力矩通道,( \delta_t )是总拉力增量。线性化之后的状态矩阵是这样一组数值:
A = [-0.15 0 0 -9.81 0; 0 -0.25 0 0 0; 0 0 -0.8 0 0; 0 0 1 0 0; 0 -1 0 0 0];
B = [0 0; 0 0.667; 7.2 0; 0 0; 0 0];
C = [0 0 0 0 1; 0 0 0 1 0];
D = zeros(2, 2);
这里A矩阵里的-9.81来自重力项,-0.15和-0.25是电机桨气动阻力带来的速度阻尼,-0.8是俯仰阻尼;B矩阵里7.2是俯仰力矩增益除以俯仰转动惯量,0.667是拉力增益除以质量。这套参数不神秘,就是机理建模加简单风洞/悬停实测辨识出来的。
我说这些是想强调一点:H2/H∞控制器设计的质量,极大程度上取决于状态空间模型的准确性。你给控制器喂一个错误的对象模型,后面公式推得再漂亮也是白搭。在工程里,建模工作至少要占整个项目一半时间,这不是夸张。
1.2 H2与H∞的分工:一个管能量最优,一个管最坏情况
既然模型有了,为什么不用LQR完事,非要折腾H2和H∞?关键在于这两个控制器回答的问题不一样。
H2控制,简单理解就是让闭环系统对外部白噪声输入的能量增益最小。它优化的是平均值,是方差,是"大多数情况下的综合表现"。LQG其实是H2方法在状态估计和状态反馈框架下的一种实现。所以如果你的扰动可以用白噪声刻画,关心的指标是响应方差、控制能耗,那H2是很自然的选择。
H∞控制则完全是另一套思路:它要保证的是在最坏情况下,系统增益仍然被压制在一个指定水平以下。它的数学语言是:给定系统的传递函数G(s),H∞范数定义为
|G|\infty = \sup\omega \bar{\sigma}(G(j\omega))
也就是在全频段上,系统增益的最大奇异值峰值。H∞控制器设计的目标,是让这个峰值尽量小,或者至少小到一个满足性能要求的阈值γ。
打个比方:H2像是一辆跑市区通勤的车,追求的是平均油耗最低;H∞像是一辆要求在任何极端路况下都不能翻车的越野车,追求的是最坏情况下的生存能力。在roofa67这种无人机平台上,风扰、气流、载重变化都是不好建模的东西,我更关心的是"突然来一阵侧风能不能稳住",而不是"平均功耗最低",所以H∞在工程上更常用。但H2并非没用,它常被当作一个基准、一个初值,甚至是混合控制器设计中的一部分。
2. 控制器设计背后的关键数学,这里讲人话版
2.1 H2控制器:Riccati方程与LQG的渊源
H2控制器的标准问题框架是:给定广义被控对象P(s),设计控制器K(s)让闭环系统内部稳定,并极小化从外部输入w到性能输出z的闭环传递函数T_zw的H2范数。
数学上,H2范数定义是
|T_{zw}|2^2 = \frac{1}{2\pi}\int{-\infty}^{+\infty} \text{trace}[T_{zw}(j\omega)^* T_{zw}(j\omega)] d\omega
直观理解,这衡量的是系统在白噪声输入下输出的总能量/方差。求解H2问题,核心是两个代数Riccati方程。让我把结论直接摆出来,不绕弯子。
假设广义对象的状态空间实现为:
\dot{x} = Ax + B_1 w + B_2 u z = C_1 x + D_{11} w + D_{12} u y = C_2 x + D_{21} w + D_{22} u
在满足一系列条件(比如(A, B_2)能镇定、(C_2, A)能检测、(A, B_1)能镇定、(C_1, A)能检测,等等)的前提下,H2最优控制器由两个Riccati方程的解给出。一个来自全状态反馈问题,一个来自状态观测器问题,两者合在一起,结构就是"卡尔曼滤波 + LQR增益",这正是LQG的框架。
我在实际中很少手推Riccati方程,因为MATLAB的h2syn函数直接就能解。但理解原理有一个实打实的好处:当你看到h2syn报出"Riccati solution not found"之类错误时,你会知道是系统的可镇定/可检测性质出了问题,而不是傻乎乎去改控制器参数。
2.2 H∞控制器:从范数到加权函数
H∞控制器的标准问题是在同样的广义对象框架下,寻找控制器K使得闭环系统内部稳定,并且
|T_{zw}|_\infty < \gamma
求解方法有两种主流路线:一是基于Riccati方程的双线性变换迭代(也就是MATLAB hinfsyn的老实现思路),二是基于LMI(线性矩阵不等式)。在工程使用层面,我们不关心求解器内部是走哪条路,但必须清楚一个核心问题:性能要求是通过加权函数来表达的。
这就是H∞控制器与LQR/H2最大的不同。H∞设计你不能直接说"我很关心高度,别让它超调",你得把这句人话翻译成加权函数W1、W2、W3,然后构建增广被控对象。加权函数选得不好,H∞控制器就各种别扭。
我常用的输出混合灵敏度结构是:性能输出z = [z1; z2; z3],其中
z1 = W1 * e, e是跟踪误差/测量输出,希望它在低频段被压下去 z2 = W2 * u, u是控制输入,限制控制量的幅值 z3 = W3 * y, y是测量输出,约束高频增益、保证鲁棒性
W1一般是低通滤波器形状,低频增益高,才能迫使闭环灵敏度函数在低频段小于1,实现跟踪和抗扰;W2一般选高通或常数,限制高频控制动作;W3也是高通,压制高频噪声放大。这三个权重的交界频率,直接决定了控制器的带宽和鲁棒性取向。
2.3 混合H2/H∞:鱼和熊掌如何兼得
有时候我们既希望闭环对白噪声有良好的平均性能,又希望对最坏情况有硬性保证。这就引出了混合H2/H∞控制:在闭合环满足
|T_{zw}|\infty < \gamma\infty
的前提下,极小化另一个通道的H2性能指标。这本质是一个带约束的多目标优化问题,工程上通常用LMI工具去数值求解。
我在roofa67上其实做过一次混合设计:把高度跟踪性能放在H2指标里优化,把俯仰通道的鲁棒稳定性放在H∞约束里保证。效果是有改善,但说实话,调参难度比单独H∞高不少。如果你不是有明确的硬约束需求,我不建议一上来就上混合设计,先把H2和H∞分别吃透,比直接用混合方案靠谱得多。
3. 用MATLAB把H2/H∞控制器真正跑起来(roofa67完整实例)
3.1 检查系统基本性质:从状态空间到可控可观性
任何控制器设计之前,我习惯先跑一遍系统基本性质检查。这一步看似不起眼,能省下后面一大半排错时间。完整代码骨架如下:
% roofa67 状态空间模型 A = [-0.15 0 0 -9.81 0; 0 -0.25 0 0 0; 0 0 -0.8 0 0; 0 0 1 0 0; 0 -1 0 0 0]; B = [0 0; 0 0.667; 7.2 0; 0 0; 0 0]; C = [0 0 0 0 1; 0 0 0 1 0]; D = zeros(2, 2); G = ss(A, B, C, D); % 可控性与可观性 co = ctrb(G); ob = obsv(G); fprintf('rank(ctrb) = %d, rank(obsv) = %d\n', rank(co), rank(ob)); % 极点 pole(G) % 系统是否最小实现 G = minreal(G);我在roofa67上跑出来的结果是可控矩阵秩为5、可观矩阵秩为5,系统是最小实现,所有开环极点在左半平面附近但有积分环节拖尾。这说明用H2/H∞设计在结构上是可行的,后面如果跑出"no stabilizing controller"的报错,就得回头仔细检查是不是加权函数把某些不利极点带进了广义对象。
3.2 H2控制器设计:h2syn实战
H2设计我习惯用灵敏度加权结构,但不加太复杂的整形。roofa67上我的做法是:
% 加权函数 W1 = tf(0.8*[1 2], [1 0.02]); % 低频高增益,压跟踪误差 W2 = tf(0.1*[1 10], [1 100]); % 高频惩罚,限制控制动作 W3 = tf(0.2, 1); % 常数鲁棒加权 % 构建广义被控对象 P = augw(G, W1, W2, W3); % H2控制器设计 nmeas = 2; % 测量输出数量 [h, θ] ncont = 2; % 控制输入数量 [δ_e, δ_t] [K_h2, CL_h2, gamma_h2] = h2syn(P, nmeas, ncont); % 查看控制器阶数 size(K_h2)augw这个函数是把对象G和三个加权函数按标准结构拼成广义被控对象P,这是整个流程里最容易出错的地方。很多人不知道augw拼出来的P内部输入输出顺序是什么,导致后面h2syn和hinfsyn的nmeas、ncont填错。我的经验是:先用size(P)看一眼,再对照augw的文档确认输入输出含义,别凭感觉填。
设计完之后,我会立即看闭环特性:
% 闭环灵敏度函数 S_h2 = feedback(1, G*K_h2); stepinfo(S_h2) % 对输出端阶跃 step(feedback(G*K_h2, eye(2)), 5)在roofa67上,H2控制器给出的γ值是1.68左右(H2范数,别和H∞γ混淆)。阶跃响应表现是:高度通道大概1.2秒内跟上,无稳态误差,俯仰角最大偏离0.3弧度左右;控制量比较平缓,没有高频抖动。整体手感偏"温",这是H2的典型气质,它优化的是白噪声下的综合方差,不追求极致的快速性。
3.3 H∞控制器设计:hinfsyn实战
H∞设计的重头戏在加权函数。同样的augw框架,换成hinfsyn调用:
% 调整加权函数,H∞要更关注带宽和高频滚降 W1 = tf([1 3], [1 0.01]); % 低频增益更高、带宽更宽 W2 = tf(0.08*[1 20], [1 200]); % 控制惩罚频率点拉高 W3 = tf(0.5*[1 50], [1 500]); % 高频鲁棒加权 P = augw(G, W1, W2, W3); gamma_try = 1.0; % 目标γ [K_hinf, CL_hinf, gamma_hinf, info] = hinfsyn(P, nmeas, ncont, gamma_try); % 如果不指定γ范围,也可以让 hinfsyn 自动迭代 % [K_hinf, CL_hinf, gamma_hinf, info] = hinfsyn(P, nmeas, ncont);hinfsyn的返回值里gamma_hinf是实际达到的闭环H∞范数。如果gamma_hinf远大于1,说明加权函数要求太苛刻,控制器做不到;如果远小于1,说明性能要求松了,可以收紧W1或W2。我在roofa67上把目标γ设为1.0,最终跑出的gamma_hinf约0.82,说明所有加权的性能指标基本都满足了。
H∞控制器在阶跃响应的表现和H2完全不同:高度通道0.6秒内就能跟上,响应快很多,但控制量前期有一个明显的脉冲式冲击,对执行器其实不太友好。这正是为什么H∞控制器设计之后,一定要评估控制输入的幅值和变化率,必要时在W2上加大高频惩罚。
3.4 Simulink闭环仿真与结果对比
MATLAB里验证完,我习惯再搭一个Simulink模型做带非线性和限幅的仿真。模型结构不复杂:一个roofa67的LTI模块(或者更完整的非线性模型)、一个控制器模块(从K_h2/K_hinf离散化得到)、饱和限幅模块、扰动注入模块、示波器和性能统计模块。
关键设置是:控制器必须用离散模块,采样时间按实际飞控取值。roofa67的飞控采样率是500Hz,也就是Ts=0.002秒。离散化代码:
Ts = 0.002; K_h2_d = c2d(K_h2, Ts, 'tustin'); K_hinf_d = c2d(K_hinf, Ts, 'tustin');我分别跑了两组仿真:给定高度阶跃2米,注入1m/s的风速阶跃扰动(等效为俯仰通道扰动力矩)。结果对比整理成一张表:
| 指标 | H2控制器 | H∞控制器 |
|---|---|---|
| 高度上升时间 | 1.1s | 0.55s |
| 高度超调量 | 8% | 22% |
| 扰动力矩下最大高度偏差 | 0.35m | 0.12m |
| 控制量峰值 | 平稳,无尖峰 | 初始有明显尖峰 |
| 高频噪声灵敏度 | 低 | 中等,靠W3压制 |
这组对比很典型:H∞更快、抗扰更强,但代价是控制更激进、超调更大;H2更温和、超调小,但抗扰反应慢。工程师在两者之间的取舍,本质上是在"性能的上限"和"鲁棒性的下限"之间找一个工程可接受的平衡点。这也是为什么H∞调加权函数时,我会在W1的带宽和W2的惩罚强度之间反复横跳,每调一次就跑一次Simulink看完整闭环行为,光看Bode图和γ值是不够的。
4. 仿真和实调中踩过的坑:问题排查技巧实录
4.1 常见问题速查表
跑H2/H∞控制仿真的人,十有八九都遇到过下面几个经典问题,我自己在roofa67上几乎全踩了一遍。整理成速查表,方便你对照排查:
| 现象 | 可能原因 | 处理办法 |
|---|---|---|
| hinfsyn返回gamma=Inf或无法收敛 | 加权函数使广义对象不满足正则性条件,通常是D11非零或加权不适当 | 检查augw构建的P是否正则,调整W2/W3的高频行为 |
| h2syn报"no stabilizing controller" | 系统存在不可镇定或不可检测模态 | 检查(A,B2)能镇定和(C2,A)能检测,先做可控可观性分解 |
| 仿真闭环出现高频抖振 | W2的高频惩罚不够,控制器放大了测量噪声 | 增大W2高频增益,或者降低W1带宽 |
| 控制器阶数爆炸式增长 | 加权函数阶数再加上对象阶数,一般有10阶以上 | 用balancmr、redschur做平衡截断降阶 |
| 参数变化后闭环失稳 | 标称设计没有覆盖实际模型不确定性 | 增大W3、加宽鲁棒性加权频段,或改用μ综合 |
| 反馈符号接反,仿真发散 | 控制器输出和对象输入的符号定义没对齐 | 先在开环下核对正负方向,再闭合回路 |
4.2 高阶控制器的降阶与离散化
H∞控制器做出来通常都不是"小而美"的控制器。比如roofa67的5阶对象,加上三个加权函数后,控制器阶数能到十几阶。工程上没必要把这十几阶直接部署到飞控里,高阶控制器在离散化、数值实现和代码审查时都是负担。
我的习惯是先降阶再离散化。降阶用平衡截断:
% 平衡截断降阶,保留4阶 K_hinf_red = balancmr(K_hinf, 4); % 或者基于Hankel范数近似 K_hinf_red = hankelmr(K_hinf, 4);降阶之后要用sigma对比原控制器和降阶控制器的闭环特性,如果闭环灵敏度函数在中低频段几乎没变化,就可以放心用。我在roofa67上把控制器从12阶降到4阶,闭环性能几乎没有损失,γ从0.82涨到0.87,仍然满足要求。
离散化注意两点:一是Tustin变换会把频响压到离散域边界,高频特性可能变形;二是离散控制器在仿真和实测中都要特别留意抗饱和、初始化问题。我的习惯是Simulink里用Discrete State-Space模块实现控制器,初值设成稳态工作点的平衡值,避免一上电就给出一个大的控制指令。
4.3 加权函数调参的独家心得
加权函数的调参没有标准答案,但我从roofa67上总结出一套比较实用的初值思路,可以作为起点。
W1的零极点频率,按系统的带宽需求来定。如果希望闭环带宽在1~2Hz附近(无人机姿态环的典型值),W1的穿越频率就放在这个区间附近,低频增益做到20dB以上,用来压制稳态误差;W2的转折频率比W1高一个数量级就行,初始增益给到0.1左右,别一上来就给0.01,否则控制器会变得过于激进;W3的高频段增益从0.1到1之间试,如果对象不确定性主要来自高频模型误差,就加大W3的增益。
还有一个非常容易被忽视的点:augw构造的广义对象P,必须在无穷远处满足"正则"条件。也就是说整个回路在高频段的增益要滚降下去,W2和W3在高频不能是纯常数且同时D12不为零导致D矩阵结构问题。如果hinfsyn报错说对象不是正则的,可以给W2或W3加上一个远高于控制带宽的极点,比如分母上加个s/1000+1,让它在高频段仍然滚降,问题往往就解决了。
调参过程中人很容易陷入"死磕γ值"的误区。我前几次做H∞设计,总想把γ压到0.5以下,结果W1带宽越加越大、W2惩罚越来越小,控制器越来越疯,Simulink一跑就抖振。后来我明白了:γ只是一个数学指标,工程上γ在0.8到1.2之间都是可以接受的设计,真正要盯的是闭环Bode图、阶跃响应和控制量幅值。把γ从0.9降到0.7,远不如把闭环超调从30%压到15%来得实在。
5. 从roofa67推开去:H2/H∞在工程选型中的定位
5.1 和PID、LQR、滑模、MPC放一起怎么选
控制器设计工具越来越多,容易挑花眼。我在roofa67上把主流方法都用过一遍之后,形成了一个比较务实的选型判断,放一张对比表:
| 方法 | 优点 | 缺点 | 最合适的场景 |
|---|---|---|---|
| PID | 简单、成熟、调参工具多 | 多变量耦合难处理,无鲁棒性保证 | SISO回路、低要求、快速原型 |
| LQR | 多变量、能处理耦合,状态反馈形式清晰 | 需要全状态可测,本身无鲁棒性保证 | 全状态可测、二次型性能指标明确 |
| H2/LQG | 白噪声环境下方差最优,和卡尔曼滤波天然契合 | 对最坏情况没有保证 | LQG类问题、导航/估计与控制的联合设计 |
| H∞ | 对模型不确定性和最坏扰动有硬性保证 | 加权函数调参难、控制器阶数高 | 不确定性大、安全边界严格 |
| 滑模控制 | 对匹配干扰有强不敏感性和有限时间收敛 | 抖振问题、对非匹配扰动敏感 | 强非线性、干扰大但可建模为匹配扰动 |
| MPC | 天然处理约束,预测能力强 | 在线计算量大、依赖模型精度 | 有约束、慢速系统(如化工、轨迹规划) |
你看,没有哪个方法是银弹。在roofa67飞控里,我最后实际部署的是"H∞设计提供基准+降阶实现+抗饱和保护"的组合。姿态内环用H∞保证鲁棒性,位置外环反而用了简化的PID,因为外环模型不确定性更大、观测延迟也更明显,强行H∞未必划算。
5.2 这套方法的适用场景与不适用场景
从roofa67的经验往外推,H2/H∞这套方法最适合的场景大概有三个特征:第一,对象是多变量、强耦合的,PID环环相扣很难调;第二,模型可以建立到一定可信度,至少能给出状态空间表达,不需要精确到每个参数,但要能捕捉主要动力学;第三,系统运行环境存在不能简单忽略的扰动或模型变化,需要鲁棒性保证。
反过来,如果系统是单输入单输出、线性度好、运行环境稳定,那PID往往性价比最高。如果模型根本没把握、系统是高度非线性的,H∞这类线性方法做出的线性控制器只能在一个工作点附近有效,这时候滑模、反步法之类非线性控制可能更合适。H2/H∞不是万能钥匙,它是一套需要在合适场景下才能发挥价值的精密工具。
我个人在roofa67上折腾了这么久,最大的体会是:别神话H∞,也别把它当洪水猛兽。它的数学门槛看着高,但现代工具已经把求解器封装得很好了,真正的难点在于理解加权函数表达的设计意图、在仿真和实测里反复校准模型。每次看到gamma收敛、闭环阶跃响应平顺、扰动测试通过的那一刻,你会觉得前面建模和调参花掉的时间,全都值了。最后再分享一个小技巧:所有H2/H∞控制器上线实测之前,一定先在Simulink里做一次"参数摄动扫描",把你认为最可能的模型误差范围加大一倍跑一遍,如果闭环还稳得住,再去动真机不迟。这一步能帮你避掉绝大多数"仿真能过、上机就炸"的尴尬。
本文还有配套的精品资源,点击获取