V0'`` is only provided because it is needed by ``'YT'`` in some specific cases. Furthermore ``'YT'`` gives on average more robust results than ``'KNV0'`` when ``abs(det(X))`` is used as a robustness indicator. [2]_ is available as a technical report on the following URL: https://hdl.handle.net/1903/5598 References ---------- .. [1] J. Kautsky, N.K. Nichols and P. van Dooren, "Robust pole assignment in linear state feedback", International Journal of Control, Vol. 41 pp. 1129-1155, 1985. .. [2] A.L. Tits and Y. Yang, "Globally convergent algorithms for robust pole assignment by state feedback", IEEE Transactions on Automatic Control, Vol. 41, pp. 1432-1452, 1996. Examples -------- A simple example demonstrating real pole placement using both KNV and YT algorithms. This is example number 1 from section 4 of the reference KNV publication ([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]) Now compute K with KNV method 0, with the default YT method and with the YT method while forcing 100 iterations of the algorithm and print some results after each call. >>> 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]]) The absolute value of the determinant of X is a good indicator to check the robustness of the results, both ``'KNV0'`` and ``'YT'`` aim at maximizing it. Below a comparison of the robustness of the results above: >>> 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 Now a simple example for complex poles: >>> 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') We can plot the desired and computed poles in the complex plane: >>> 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) r