4545from . import statesp
4646from .exception import ControlSlycot , ControlArgument , ControlDimension
4747
48- __all__ = ['ctrb' , 'obsv' , 'gram' , 'place' , 'lqr' , 'acker' ]
48+ __all__ = ['ctrb' , 'obsv' , 'gram' , 'place' , 'place_varga' , ' lqr' , 'acker' ]
4949
5050
5151# Pole placement
5252def place (A , B , p ):
5353 """Place closed loop eigenvalues
54-
54+ K = place(A, B, p)
5555 Parameters
5656 ----------
5757 A : 2-d array
@@ -64,7 +64,7 @@ def place(A, B, p):
6464 Returns
6565 -------
6666 K : 2-d array
67- Gains such that A - B K has eigenvalues given in p
67+ Gain such that A - B K has eigenvalues given in p
6868
6969 Algorithm
7070 ---------
@@ -107,6 +107,72 @@ def place(A, B, p):
107107 K = result .gain_matrix
108108 return K
109109
110+
111+ def place_varga (A , B , p ):
112+ """Place closed loop eigenvalues
113+ K = place_varga(A, B, p)
114+
115+ Parameters
116+ ----------
117+ A : 2-d array
118+ Dynamics matrix
119+ B : 2-d array
120+ Input matrix
121+ p : 1-d list
122+ Desired eigenvalue locations
123+ Returns
124+ -------
125+ K : 2-d array
126+ Gain such that A - B K has eigenvalues given in p.
127+
128+
129+ Algorithm
130+ ---------
131+ This function is a wrapper for the slycot function sb01bd, which
132+ implements the pole placement algorithm of Varga [1]. In contrast to
133+ the algorithm used by place(), the Varga algorithm can place
134+ multiple poles at the same location. The placement, however, may not
135+ be as robust.
136+
137+ [1] Varga A. "A Schur method for pole assignment."
138+ IEEE Trans. Automatic Control, Vol. AC-26, pp. 517-519, 1981.
139+
140+ Examples
141+ --------
142+ >>> A = [[-1, -1], [0, 1]]
143+ >>> B = [[0], [1]]
144+ >>> K = place(A, B, [-2, -5])
145+ """
146+
147+ # Make sure that SLICOT is installed
148+ try :
149+ from slycot import sb01bd
150+ except ImportError :
151+ raise ControlSlycot ("can't find slycot module 'sb01bd'" )
152+
153+ # Convert the system inputs to NumPy arrays
154+ A_mat = np .array (A );
155+ B_mat = np .array (B );
156+ if (A_mat .shape [0 ] != A_mat .shape [1 ] or
157+ A_mat .shape [0 ] != B_mat .shape [0 ]):
158+ raise ControlDimension ("matrix dimensions are incorrect" )
159+
160+ # Compute the system eigenvalues and convert poles to numpy array
161+ system_eigs = np .linalg .eig (A_mat )[0 ]
162+ placed_eigs = np .array (p );
163+
164+ # SB01BD sets eigenvalues with real part less than alpha
165+ # We want to place all poles of the system => set alpha to minimum
166+ alpha = min (system_eigs .real );
167+
168+ # Call SLICOT routine to place the eigenvalues
169+ A_z ,w ,nfp ,nap ,nup ,F ,Z = \
170+ sb01bd (B_mat .shape [0 ], B_mat .shape [1 ], len (placed_eigs ), alpha ,
171+ A_mat , B_mat , placed_eigs , 'C' );
172+
173+ # Return the gain matrix, with MATLAB gain convention
174+ return - F
175+
110176# Contributed by Roberto Bucher <roberto.bucher@supsi.ch>
111177def acker (A , B , poles ):
112178 """Pole placement using Ackermann method
0 commit comments