4. 能控性判据(二):秩判据(Kalman判据),标准形式与MATLAB实现
好,咱们接着聊能控性判据。上一节讲了格拉姆矩阵判据,那个方法理论完美,但实际用起来有点麻烦——你得解矩阵微分方程,还得判断矩阵是否奇异。说实话,做工程的人没那个耐心。
所以这一节,我带你看看真正实用的方法:秩判据,也叫Kalman判据。这是现代控制理论里最经典的结论之一,简单、直接、暴力。
4.1 秩判据的核心思想
先问一个问题:一个系统能不能控,到底由什么决定?
答案是:由系统矩阵A和输入矩阵B共同决定。
Kalman老爷子在1960年代给出了一个极其优雅的结论:
线性定常系统 (A, B) 完全能控的充要条件是:
能控性矩阵 Q_c = [B, AB, A²B, ..., Aⁿ⁻¹B] 满秩,即 rank(Q_c) = n
其中 n 是系统的阶数。
说白了,你把这个矩阵拼出来,看看它的秩是不是等于系统维数。是,就能控;不是,就不能控。就这么简单。
我个人习惯把这个矩阵叫做「能控性判别矩阵」,虽然教科书上叫Kalman矩阵。嗯,名字不重要,会用就行。
4.2 秩判据的直观理解
为什么会这样?我给你一个直观的解释。
你想想看,控制输入u是通过B矩阵进入系统的。但B只能直接影响一部分状态变量。那些不能直接影响的变量,就得靠系统自身的动态(A矩阵)来「传递」控制作用。
A²B表示经过两步传递,A³B表示三步传递……直到Aⁿ⁻¹B。如果这些矩阵合起来能张满整个n维空间,那就说明:无论哪个状态变量,都能通过某种方式被控制到。
我在项目中遇到过这样一个案例:一个四阶系统,B矩阵只有一列,看起来好像控制力很弱。但算了一下能控性矩阵,秩正好是4。这说明什么?说明虽然只有一个输入,但通过系统内部的耦合,这个输入能影响到所有状态变量。
小技巧: 实际计算时,不需要真的把Aⁿ⁻¹B全部算出来。一旦发现前面几列已经满秩了,后面的就不用算了。我在MATLAB里经常用这个技巧来节省计算时间。
4.3 标准形式:能控标准型
如果一个系统是能控的,我们可以把它变换成一种特别的形式——能控标准型。这种形式下,系统的能控性一目了然。
能控标准型有两种常见形式:
| 形式 | 特点 | 应用场景 |
|---|---|---|
| 能控标准I型 | A矩阵是友矩阵(companion matrix)形式 | 极点配置、状态反馈设计 |
| 能控标准II型 | B矩阵是[0,0,...,1]ᵀ形式 | 理论分析、证明 |
我个人更喜欢用能控标准I型,因为它的A矩阵直接包含了特征多项式的系数,做极点配置时特别方便。
变换方法其实不复杂:
- 计算能控性矩阵Q_c
- 取Q_c的最后一列,构造变换矩阵P
- 用P对原系统做相似变换
嗯,这里要注意:如果系统不是完全能控的,这个变换就做不了。所以第一步永远是先算秩。
4.4 MATLAB实现:从理论到代码
理论说完了,咱们看看怎么在MATLAB里实现。我保证,代码比理论简单得多。
4.4.1 计算能控性矩阵
% 定义系统矩阵
A = [0 1 0; 0 0 1; -6 -11 -6];
B = [0; 0; 1];
% 计算能控性矩阵
Qc = ctrb(A, B);
% 显示结果
disp('能控性矩阵 Qc =');
disp(Qc);
% 计算秩
rank_Qc = rank(Qc);
n = size(A, 1);
if rank_Qc == n
disp('系统完全能控!');
else
disp(['系统不完全能控,秩为 ', num2str(rank_Qc)]);
end
你看,MATLAB里一个ctrb()函数就搞定了。但我建议你至少手动实现一次,理解它的原理:
% 手动计算能控性矩阵
n = size(A, 1);
Qc_manual = [];
for i = 0:n-1
Qc_manual = [Qc_manual, A^i * B];
end
我曾经犯过一个错误:在循环里直接用A^i,结果当n很大时计算量爆炸。后来改用power(A, i),效率高了不少。这些小坑,踩过才知道。
4.4.2 变换到能控标准型
% 计算能控标准型
[Ac, Bc, Cc, Tc] = canon(A, B, C, 'companion');
disp('能控标准型 A 矩阵:');
disp(Ac);
disp('能控标准型 B 矩阵:');
disp(Bc);
这里canon()函数直接给出了变换后的系统和变换矩阵Tc。我个人习惯把Tc保存下来,因为后面做状态反馈设计时还要用到。
警告: canon()函数要求系统是完全能控的。如果系统不能控,MATLAB会报错。所以一定要先检查能控性。
4.5 实战案例:一个三阶系统
咱们看一个完整的例子。假设有一个三阶系统:
A = [1 2 0; 3 -1 1; 0 2 0];
B = [1; 0; 1];
% 第一步:检查能控性
Qc = ctrb(A, B);
r = rank(Qc);
if r == 3
disp('系统能控,可以进行极点配置');
% 第二步:计算能控标准型
[Ac, Bc, Cc, Tc] = canon(A, B, [1 0 0], 'companion');
% 第三步:设计状态反馈(极点配置到[-2, -3, -4])
p = [-2, -3, -4];
Kc = place(Ac, Bc, p);
% 第四步:变换回原坐标系
K = Kc * inv(Tc);
disp('状态反馈增益矩阵 K =');
disp(K);
else
disp(['系统不能控,秩为 ', num2str(r)]);
end
这个流程我用了不下百次。记住:先判能控,再做设计。这是铁律。
4.6 避坑指南
最后,分享几个我踩过的坑:
- 数值精度问题: 当系统矩阵很大时,Aⁿ⁻¹B的数值可能会变得非常大或非常小,导致秩的判断出错。我建议用
rank(Qc, tol)指定一个容差,比如tol = 1e-10。 - 离散系统: 秩判据同样适用于离散系统,但要注意:离散系统的能控性矩阵定义和连续系统完全一样。
- 时变系统: 秩判据只适用于线性定常系统。时变系统要用格拉姆矩阵判据,别搞混了。
核心总结:
- 秩判据 = 计算能控性矩阵 → 检查是否满秩
- 能控标准型 = 能控系统的规范形式,方便设计
- MATLAB三件套:ctrb()、canon()、place()
好了,秩判据就讲到这里。下一节咱们聊能观性,你会发现它和能控性是对偶的——理解了能控性,能观性就是照葫芦画瓢。
公众号:蓝海资料掘金营,微信deep3321