place_poles#
- scipy.signal.place_poles(A, B, poles, method='YT', rtol=0.001, maxiter=30)[source]#
计算 K 使得特征值 (A - dot(B, K))=poles。
K 是增益矩阵,如由线性系统
AX+BU
描述的工厂将具有其闭环极点,即特征值A - B*K
,尽可能接近 poles 中要求的极点。支持 SISO、MISO 和 MIMO 系统。
- 参数:
- A, Bndarray
线性系统
AX + BU
的状态空间表示。- polesarray_like
期望的实极点和/或共轭复极点。仅在
method="YT"
(默认)时支持复极点。- method: {‘YT’, ‘KNV0’}, 可选
选择哪种方法来查找增益矩阵 K。其中之一
‘YT’:杨提茨
‘KNV0’:Kautsky、Nichols、Van Dooren 更新方法 0
有关算法的详细信息,请参阅参考资料和注释。
- rtol: float, 可选
每次迭代后,都会将特征向量的行列式
A - B*K
与它上一次的值进行比较,当这两个值之间的相对误差小于 rtol 时,算法将停止。默认值为 1e-3。- maxiter:int,可选
计算增益矩阵的最大迭代次数。默认值为 30。
- 返回:
- full_state_feedbackBunch 对象
- full_state_feedback 由以下部分组成
- gain_matrix1 维 ndarray
闭环矩阵 K,它尽可能接近于请求的极点,如同
A-BK
的特征值。- computed_poles1 维 ndarray
对应于
A-BK
的极点按以下方式排序:首先是增序的实数极点,然后再是按字母顺序排列的复数共轭极点。- requested_poles1 维 ndarray
算法尝试放置的极点按上述方式排序,它们可能与达到的极点有所不同。
- X2 维 ndarray
传递矩阵,如
X * diag(poles) = (A - B*K)*X
(参见注解)- rtolfloat
在
det(X)
上达到的相对容差(参见注解)。如果系统diag(poles) = (A - B*K)
能够求解,则 rtol 将为 NaN,或者当优化算法没有任何作用(即当B.shape[1] == 1
)时为 0。- nb_iterint
在收敛之前执行的迭代次数。如果系统
diag(poles) = (A - B*K)
能够求解,则 nb_iter 将为 NaN,或者当优化算法没有任何作用(即当B.shape[1] == 1
)时为 0。
注解
Tits 和 Yang (YT) 的 [2] 论文是原始 Kautsky 等人 (KNV) 论文 [1] 的更新。KNV 依赖于秩 1 更新来查找转移矩阵 X 使得
X * diag(poles) = (A - B*K)*X
,而 YT 使用秩 2 更新。平均而言,这会产生更稳健的解决方案(参见 [2] 第 21-22 页),此外 YT 算法支持复极,而 KNV 在其原始版本中不支持。这里只实现了 KNV 提出的更新方法 0,因此得名'KNV0'
。在 Matlab 的
place
函数中使用了扩展到复极的 KNV,YT 由 Slicot 以robpole
的名称在非免费许可证下分发。目前还不清楚并且没有记录如何将 KNV0 扩展到复极(Tits 和 Yang 在他们论文的第 14 页声称他们的方法不能用于将 KNV 扩展到复极),因此在此实现中只有 YT 支持它们。由于极点放置问题的解决方案对于 MIMO 系统而言并非唯一,因此两种方法都从一个试验转移矩阵开始,该转移矩阵以各种方式进行修改以增加其行列式。两种方法已被证明会收敛到一个稳定的解决方案,但是根据选择初始传递矩阵的方式,它们将收敛到不同的解决方案,因此绝对不能保证使用
'KNV0'
会产生与 Matlab 或任何其他实现类似的结果这些算法。在大多数情况下使用默认方法
'YT'
应该没有问题;提供'KNV0'
只是因为'YT'
在某些特定情况下需要它。此外,当abs(det(X))
用作稳健性指标时,'YT'
给出的平均结果比'KNV0'
更稳健。[2] 可作为技术报告在以下 URL 上获得:https://hdl.handle.net/1903/5598
参考文献
示例
使用 KNV 和 YT 算法展示实际极点配置的简单示例。这是参考 KNV 刊物第 4 部分中的示例 1 ([1])
>>> import numpy as np >>> from scipy import signal >>> import matplotlib.pyplot as plt
>>> A = np.array([[ 1.380, -0.2077, 6.715, -5.676 ], ... [-0.5814, -4.290, 0, 0.6750 ], ... [ 1.067, 4.273, -6.654, 5.893 ], ... [ 0.0480, 4.273, 1.343, -2.104 ]]) >>> B = np.array([[ 0, 5.679 ], ... [ 1.136, 1.136 ], ... [ 0, 0, ], ... [-3.146, 0 ]]) >>> P = np.array([-0.2, -0.5, -5.0566, -8.6659])
现在,使用 KNV 方法 0、使用默认 YT 方法以及使用 YT 方法计算 K,同时强制算法迭代 100 次,并在每次调用后打印一些结果。
>>> fsf1 = signal.place_poles(A, B, P, method='KNV0') >>> fsf1.gain_matrix array([[ 0.20071427, -0.96665799, 0.24066128, -0.10279785], [ 0.50587268, 0.57779091, 0.51795763, -0.41991442]])
>>> fsf2 = signal.place_poles(A, B, P) # uses YT method >>> fsf2.computed_poles array([-8.6659, -5.0566, -0.5 , -0.2 ])
>>> fsf3 = signal.place_poles(A, B, P, rtol=-1, maxiter=100) >>> fsf3.X array([[ 0.52072442+0.j, -0.08409372+0.j, -0.56847937+0.j, 0.74823657+0.j], [-0.04977751+0.j, -0.80872954+0.j, 0.13566234+0.j, -0.29322906+0.j], [-0.82266932+0.j, -0.19168026+0.j, -0.56348322+0.j, -0.43815060+0.j], [ 0.22267347+0.j, 0.54967577+0.j, -0.58387806+0.j, -0.40271926+0.j]])
X 行列式绝对值是一个很好的指标,可用来检查结果的稳健性,
'KNV0'
和'YT'
都旨在最大化它。下面是上述结果稳健性的对比>>> abs(np.linalg.det(fsf1.X)) < abs(np.linalg.det(fsf2.X)) True >>> abs(np.linalg.det(fsf2.X)) < abs(np.linalg.det(fsf3.X)) True
现在是一个复杂极点的简单示例
>>> A = np.array([[ 0, 7/3., 0, 0 ], ... [ 0, 0, 0, 7/9. ], ... [ 0, 0, 0, 0 ], ... [ 0, 0, 0, 0 ]]) >>> B = np.array([[ 0, 0 ], ... [ 0, 0 ], ... [ 1, 0 ], ... [ 0, 1 ]]) >>> P = np.array([-3, -1, -2-1j, -2+1j]) / 3. >>> fsf = signal.place_poles(A, B, P, method='YT')
我们可以在复平面上绘制所需的极点和计算出的极点
>>> t = np.linspace(0, 2*np.pi, 401) >>> plt.plot(np.cos(t), np.sin(t), 'k--') # unit circle >>> plt.plot(fsf.requested_poles.real, fsf.requested_poles.imag, ... 'wo', label='Desired') >>> plt.plot(fsf.computed_poles.real, fsf.computed_poles.imag, 'bx', ... label='Placed') >>> plt.grid() >>> plt.axis('image') >>> plt.axis([-1.1, 1.1, -1.1, 1.1]) >>> plt.legend(bbox_to_anchor=(1.05, 1), loc=2, numpoints=1)