Skip to content

Commit 311e9e2

Browse files
committed
Keep the original place code in a new function, place_varga. The scipy implementation of YT stays in place() proper
1 parent 186d6d8 commit 311e9e2

File tree

1 file changed

+69
-3
lines changed

1 file changed

+69
-3
lines changed

control/statefbk.py

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@
4545
from . import statesp
4646
from .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
5252
def 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>
111177
def acker(A, B, poles):
112178
"""Pole placement using Ackermann method

0 commit comments

Comments
 (0)