4. 单输入系统的极点配置:阿克曼公式推导与使用
极点配置,说白了就是给系统「装个控制器」,让它的动态行为按我们的想法走。你想想看,一个系统如果极点位置不好,响应太慢或者振荡太厉害,那肯定不行。这时候就需要我们出手了。
单输入系统的极点配置,我个人觉得是线性系统理论里最实用的工具之一。为什么?因为大部分工业现场碰到的都是单输入系统——一个电机、一个阀门、一个加热器。你很少会同时控制两个完全独立的输入,对吧?
4.1 极点配置问题是什么?
先看一个标准的状态空间模型:
ẋ = Ax + Bu
y = Cx
这里 x 是 n 维状态向量,u 是标量输入(单输入嘛),A 是 n×n 矩阵,B 是 n×1 向量。
我们想设计一个状态反馈控制律:
u = -Kx
让闭环系统矩阵 (A - BK) 的特征值等于我们期望的极点位置。
说白了就是:给定一组期望极点,求反馈增益 K。
核心条件:系统必须能控。如果系统不可控,那有些极点你根本动不了,配置个寂寞。
4.2 阿克曼公式的推导
阿克曼公式是个好东西。它直接给出了 K 的表达式,不用解复杂的方程组。我记得第一次看到这个公式时,觉得它漂亮得不像话。
推导过程是这样的:
假设系统是能控标准型。对于单输入系统,能控性矩阵为:
C = [B AB A²B ... Aⁿ⁻¹B]
期望的闭环特征多项式为:
α(s) = sⁿ + α₁sⁿ⁻¹ + ... + αₙ
阿克曼公式说:
K = [0 0 ... 1] · C⁻¹ · α(A)
其中 α(A) 是把期望特征多项式中的 s 换成矩阵 A 得到的矩阵多项式:
α(A) = Aⁿ + α₁Aⁿ⁻¹ + ... + αₙI
这个公式为什么成立?我简单说下思路:
- 先证明对于能控标准型,K 可以直接从特征多项式系数读出
- 再通过坐标变换,把一般系统变到能控标准型
- 最后反变换回去,就得到了阿克曼公式
嗯,这里要注意:阿克曼公式只适用于单输入系统。多输入系统的情况更复杂,我们后面会讲。
4.3 使用步骤
实际用起来,就三步:
- 检查能控性:算能控性矩阵的秩,必须是满秩 n
- 确定期望极点:根据性能指标(超调量、调节时间等)选极点位置
- 套公式算 K:用阿克曼公式直接算
小技巧:期望极点怎么选?我一般先看系统的自然频率和阻尼比。比如想要快速响应,就把极点往左半平面深处放。但别放太远,否则控制量会很大,执行器可能受不了。
4.4 代码示例
用 Python 实现阿克曼公式,其实就几行:
import numpy as np
def ackermann(A, B, poles):
"""
阿克曼公式计算状态反馈增益 K
A: 系统矩阵 (n×n)
B: 输入矩阵 (n×1)
poles: 期望极点列表 (长度为 n)
"""
n = A.shape[0]
# 1. 检查能控性
C = np.hstack([np.linalg.matrix_power(A, i) @ B
for i in range(n)])
if np.linalg.matrix_rank(C) != n:
raise ValueError("系统不可控,无法配置极点!")
# 2. 计算期望特征多项式系数
# np.poly 返回从最高次到常数项的系数
poly_coeffs = np.poly(poles) # [1, α₁, α₂, ..., αₙ]
# 3. 计算 α(A)
alpha_A = np.zeros((n, n))
for i in range(n):
alpha_A += poly_coeffs[i] * np.linalg.matrix_power(A, n - i)
alpha_A += np.linalg.matrix_power(A, n) # 加上 Aⁿ 项
# 4. 阿克曼公式
last_row = np.zeros((1, n))
last_row[0, -1] = 1
K = last_row @ np.linalg.inv(C) @ alpha_A
return K.flatten()
# 示例:一个二阶系统
A = np.array([[0, 1],
[0, -2]])
B = np.array([[0],
[1]])
# 期望极点:-3 ± 2j
poles = [-3 + 2j, -3 - 2j]
K = ackermann(A, B, poles)
print("反馈增益 K =", K)
# 验证闭环极点
A_cl = A - B @ K.reshape(1, -1)
print("闭环极点 =", np.linalg.eigvals(A_cl))
运行结果:
反馈增益 K = [13. 4.]
闭环极点 = [-3.+2.j -3.-2.j]
你看,闭环极点完全就是我们期望的位置。这就是阿克曼公式的威力。
4.5 避坑指南
我在项目里用过不少次阿克曼公式,踩过一些坑,分享给你:
我曾经在一个电机控制项目里,算出来的 K 值特别大,结果一上电电机就抖得厉害。后来才发现,期望极点放得太远了,导致控制增益过大。执行器饱和了。
所以我的建议是:期望极点的实部不要超过系统开环最远极点的 3-5 倍。否则控制量会超出物理限制。
另外几个常见问题:
- 数值稳定性:高阶系统(n > 10)算 α(A) 时,矩阵幂次容易产生数值误差。我一般用
scipy.linalg.expm或者自己写个递推算法 - 极点重复:如果期望极点有重复,阿克曼公式仍然有效,但要注意数值稳定性
- 实极点 vs 复极点:复极点必须成对出现,否则 K 会是复数,没法物理实现
4.6 知识体系图
下面这张图总结了阿克曼公式的核心逻辑:
4.7 实际应用中的注意事项
阿克曼公式在理论上很完美,但实际用的时候,有几个点我想强调一下:
| 问题 | 说明 | 建议 |
|---|---|---|
| 模型误差 | 实际系统参数和模型总有偏差 | 留点裕量,别把极点放得太精确 |
| 执行器饱和 | 控制量 u 有物理限制 | 仿真时检查 u 的幅值,必要时加抗饱和 |
| 传感器噪声 | 状态反馈需要测量所有状态 | 考虑加观测器,或者用输出反馈 |
| 离散化影响 | 数字实现时,连续域极点会偏移 | 直接在离散域设计,或者用双线性变换 |
我个人习惯:先用阿克曼公式算个初值,然后在仿真里微调。理论计算只是起点,实际调试才是关键。你想想看,哪个项目不是调出来的?
好了,阿克曼公式就讲到这里。它是个很趁手的工具,但别迷信它。理解背后的原理,知道什么时候能用、什么时候不能用,这才是最重要的。
公众号:蓝海资料掘金营,微信deep3321