4747
4848__all__ = ['ctrb' , 'obsv' , 'gram' , 'place' , 'lqr' , 'acker' ]
4949
50+
5051# Pole placement
5152def place (A , B , p ):
5253 """Place closed loop eigenvalues
@@ -63,43 +64,48 @@ def place(A, B, p):
6364 Returns
6465 -------
6566 K : 2-d array
66- Gains such that A - B K has given eigenvalues
67+ Gains such that A - B K has eigenvalues given in p
68+
69+ Algorithm
70+ ---------
71+ This is a wrapper function for scipy.signal.place_poles, which
72+ implements the Tits and Yang algorithm [1]. It will handle SISO,
73+ MISO, and MIMO systems. If you want more control over the algorithm,
74+ use scipy.signal.place_poles directly.
75+
76+ [1] A.L. Tits and Y. Yang, "Globally convergent algorithms for robust
77+ pole assignment by state feedback, IEEE Transactions on Automatic
78+ Control, Vol. 41, pp. 1432-1452, 1996.
79+
80+ Limitations
81+ -----------
82+ The algorithm will not place poles at the same location more
83+ than rank(B) times.
6784
6885 Examples
6986 --------
7087 >>> A = [[-1, -1], [0, 1]]
7188 >>> B = [[0], [1]]
7289 >>> K = place(A, B, [-2, -5])
7390 """
74-
75- # Make sure that SLICOT is installed
76- try :
77- from slycot import sb01bd
78- except ImportError :
79- raise ControlSlycot ("can't find slycot module 'sb01bd'" )
91+ from scipy .signal import place_poles
8092
8193 # Convert the system inputs to NumPy arrays
82- A_mat = np .array (A );
83- B_mat = np .array (B );
84- if (A_mat .shape [0 ] != A_mat .shape [1 ] or
85- A_mat .shape [0 ] != B_mat .shape [0 ]):
86- raise ControlDimension ("matrix dimensions are incorrect" )
87-
88- # Compute the system eigenvalues and convert poles to numpy array
89- system_eigs = np .linalg .eig (A_mat )[0 ]
90- placed_eigs = np .array (p );
91-
92- # SB01BD sets eigenvalues with real part less than alpha
93- # We want to place all poles of the system => set alpha to minimum
94- alpha = min (system_eigs .real );
95-
96- # Call SLICOT routine to place the eigenvalues
97- A_z ,w ,nfp ,nap ,nup ,F ,Z = \
98- sb01bd (B_mat .shape [0 ], B_mat .shape [1 ], len (placed_eigs ), alpha ,
99- A_mat , B_mat , placed_eigs , 'C' );
100-
101- # Return the gain matrix, with MATLAB gain convention
102- return - F
94+ A_mat = np .array (A )
95+ B_mat = np .array (B )
96+ if (A_mat .shape [0 ] != A_mat .shape [1 ]):
97+ raise ControlDimension ("A must be a square matrix" )
98+
99+ if (A_mat .shape [0 ] != B_mat .shape [0 ]):
100+ err_str = "The number of rows of A must equal the number of rows in B"
101+ raise ControlDimension (err_str )
102+
103+ # Convert desired poles to numpy array
104+ placed_eigs = np .array (p )
105+
106+ result = place_poles (A_mat , B_mat , placed_eigs , method = 'YT' )
107+ K = result .gain_matrix
108+ return K
103109
104110# Contributed by Roberto Bucher <roberto.bucher@supsi.ch>
105111def acker (A , B , poles ):
0 commit comments