scipy.signal.

place_poles#

scipy.signal.place_poles(A, B, poles, method='YT', rtol=0.001, maxiter=30)[源代码]#

计算 K 使得特征值 (A - dot(B, K))=poles。

K 是增益矩阵,使得由线性系统 AX+BU 描述的系统,其闭环极点,即特征值 A - B*K,尽可能接近在极点中要求的那些。

支持 SISO、MISO 和 MIMO 系统。

参数:
A, Bndarray

线性系统 AX + BU 的状态空间表示。

polesarray_like

期望的实极点和/或复共轭极点。只有在 method="YT"(默认)时才支持复极点。

method: {‘YT’, ‘KNV0’}, 可选

选择哪种方法来查找增益矩阵 K。选项之一为:

  • ‘YT’: Yang Tits

  • ‘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-D ndarray

闭环矩阵 K,使得 A-BK 的特征值尽可能接近请求的极点。

computed_poles1-D ndarray

A-BK 对应的极点,先按递增顺序排列实极点,然后按字典顺序排列复共轭极点。

requested_poles1-D ndarray

算法要求放置的极点,按上述顺序排列,它们可能与实际实现的有所不同。

X2-D ndarray

传递矩阵,使得 X * diag(poles) = (A - B*K)*X (见注释)

rtolfloat

det(X) 上实现的相对容差(见注释)。如果可以求解系统 diag(poles) = (A - B*K),则 rtol 将为 NaN,或者当优化算法无法执行任何操作时,即当 B.shape[1] == 1 时,rtol 将为 0。

nb_iterint

收敛之前执行的迭代次数。如果可以求解系统 diag(poles) = (A - B*K),则 nb_iter 将为 NaN,或者当优化算法无法执行任何操作时,即当 B.shape[1] == 1 时,nb_iter 将为 0。

注释

Tits 和 Yang (YT),[2] 论文是对最初的 Kautsky 等人 (KNV) 论文 [1] 的更新。KNV 依靠秩 1 更新来找到传递矩阵 X,使得 X * diag(poles) = (A - B*K)*X,而 YT 使用秩 2 更新。这平均产生更稳健的解决方案(请参阅 [2] pp 21-22),此外,YT 算法支持复极点,而 KNV 在其原始版本中不支持。此处仅实现了 KNV 提出的更新方法 0,因此得名 'KNV0'

扩展到复极点的 KNV 在 Matlab 的 place 函数中使用,YT 由 Slicot 以非免费许可证的形式分发,名称为 robpole。目前尚不清楚并且没有文档记录 KNV0 如何扩展到复极点(Tits 和 Yang 在他们的论文第 14 页声称他们的方法不能用于将 KNV 扩展到复极点),因此在此实现中只有 YT 支持它们。

由于对于 MIMO 系统来说,极点放置问题的解不是唯一的,因此两种方法都从一个试探性的传递矩阵开始,该矩阵以各种方式进行更改以增加其行列式。两种方法都已被证明可以收敛到稳定的解决方案,但是,根据初始传递矩阵的选择方式,它们将收敛到不同的解决方案,因此绝对不能保证使用 'KNV0' 会产生与 Matlab 或这些算法的任何其他实现类似的结果。

在大多数情况下,使用默认方法 'YT' 应该可以;仅在某些特定情况下 'YT' 需要时才提供 'KNV0'。此外,当 abs(det(X)) 用作鲁棒性指标时,'YT' 平均会比 'KNV0' 给出更稳健的结果。

[2] 可在以下 URL 作为技术报告获得:https://hdl.handle.net/1903/5598

参考资料

[1] (1,2)

J. Kautsky、N.K. Nichols 和 P. van Dooren,“线性状态反馈中的鲁棒极点分配”,《国际控制杂志》,第 41 卷,第 1129-1155 页,1985 年。

[2] (1,2,3)

A.L. Tits 和 Y. Yang,“通过状态反馈进行鲁棒极点分配的全局收敛算法”,《IEEE 自动控制汇刊》,第 41 卷,第 1432-1452 页,1996 年。

示例

一个简单的示例,演示了使用 KNV 和 YT 算法进行实极点放置。这是参考 KNV 出版物 ([1]) 第 4 节中的示例 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)
../../_images/scipy-signal-place_poles-1.png