Skip to content

Commit ebd73c1

Browse files
committed
fixes in canonical and canonical_test that were assuming numpy.matrix
1 parent eda91ca commit ebd73c1

File tree

2 files changed

+25
-29
lines changed

2 files changed

+25
-29
lines changed

control/canonical.py

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
from .statesp import StateSpace
77
from .statefbk import ctrb, obsv
88

9-
from numpy import zeros, shape, poly, iscomplex, hstack, dot, transpose
9+
from numpy import zeros, zeros_like, shape, poly, iscomplex, vstack, hstack, dot, \
10+
transpose, empty
1011
from numpy.linalg import solve, matrix_rank, eig
1112

1213
__all__ = ['canonical_form', 'reachable_form', 'observable_form', 'modal_form',
@@ -70,9 +71,9 @@ def reachable_form(xsys):
7071
zsys = StateSpace(xsys)
7172

7273
# Generate the system matrices for the desired canonical form
73-
zsys.B = zeros(shape(xsys.B))
74+
zsys.B = zeros_like(xsys.B)
7475
zsys.B[0, 0] = 1.0
75-
zsys.A = zeros(shape(xsys.A))
76+
zsys.A = zeros_like(xsys.A)
7677
Apoly = poly(xsys.A) # characteristic polynomial
7778
for i in range(0, xsys.states):
7879
zsys.A[0, i] = -Apoly[i+1] / Apoly[0]
@@ -124,9 +125,9 @@ def observable_form(xsys):
124125
zsys = StateSpace(xsys)
125126

126127
# Generate the system matrices for the desired canonical form
127-
zsys.C = zeros(shape(xsys.C))
128+
zsys.C = zeros_like(xsys.C)
128129
zsys.C[0, 0] = 1
129-
zsys.A = zeros(shape(xsys.A))
130+
zsys.A = zeros_like(xsys.A)
130131
Apoly = poly(xsys.A) # characteristic polynomial
131132
for i in range(0, xsys.states):
132133
zsys.A[i, 0] = -Apoly[i+1] / Apoly[0]
@@ -144,7 +145,7 @@ def observable_form(xsys):
144145
raise ValueError("Transformation matrix singular to working precision.")
145146

146147
# Finally, compute the output matrix
147-
zsys.B = Tzx * xsys.B
148+
zsys.B = Tzx.dot(xsys.B)
148149

149150
return zsys, Tzx
150151

@@ -174,9 +175,9 @@ def modal_form(xsys):
174175
# Calculate eigenvalues and matrix of eigenvectors Tzx,
175176
eigval, eigvec = eig(xsys.A)
176177

177-
# Eigenvalues and according eigenvectors are not sorted,
178+
# Eigenvalues and corresponding eigenvectors are not sorted,
178179
# thus modal transformation is ambiguous
179-
# Sorting eigenvalues and respective vectors by largest to smallest eigenvalue
180+
# Sort eigenvalues and vectors from largest to smallest eigenvalue
180181
idx = eigval.argsort()[::-1]
181182
eigval = eigval[idx]
182183
eigvec = eigvec[:,idx]
@@ -189,23 +190,18 @@ def modal_form(xsys):
189190

190191
# Keep track of complex conjugates (need only one)
191192
lst_conjugates = []
192-
Tzx = None
193+
Tzx = empty((0, xsys.A.shape[0])) # empty zero-height row matrix
193194
for val, vec in zip(eigval, eigvec.T):
194195
if iscomplex(val):
195196
if val not in lst_conjugates:
196197
lst_conjugates.append(val.conjugate())
197-
if Tzx is not None:
198-
Tzx = hstack((Tzx, hstack((vec.real.T, vec.imag.T))))
199-
else:
200-
Tzx = hstack((vec.real.T, vec.imag.T))
198+
Tzx = vstack((Tzx, vec.real, vec.imag))
201199
else:
202200
# if conjugate has already been seen, skip this eigenvalue
203201
lst_conjugates.remove(val)
204202
else:
205-
if Tzx is not None:
206-
Tzx = hstack((Tzx, vec.real.T))
207-
else:
208-
Tzx = vec.real.T
203+
Tzx = vstack((Tzx, vec.real))
204+
Tzx = Tzx.T
209205

210206
# Generate the system matrices for the desired canonical form
211207
zsys.A = solve(Tzx, xsys.A).dot(Tzx)

control/tests/canonical_test.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ def test_reachable_form(self):
2222
D_true = 42.0
2323

2424
# Perform a coordinate transform with a random invertible matrix
25-
T_true = np.matrix([[-0.27144004, -0.39933167, 0.75634684, 0.44135471],
25+
T_true = np.array([[-0.27144004, -0.39933167, 0.75634684, 0.44135471],
2626
[-0.74855725, -0.39136285, -0.18142339, -0.50356997],
2727
[-0.40688007, 0.81416369, 0.38002113, -0.16483334],
2828
[-0.44769516, 0.15654653, -0.50060858, 0.72419146]])
29-
A = np.linalg.solve(T_true, A_true)*T_true
29+
A = np.linalg.solve(T_true, A_true).dot(T_true)
3030
B = np.linalg.solve(T_true, B_true)
31-
C = C_true*T_true
31+
C = C_true.dot(T_true)
3232
D = D_true
3333

3434
# Create a state space system and convert it to the reachable canonical form
@@ -69,11 +69,11 @@ def test_modal_form(self):
6969
D_true = 42.0
7070

7171
# Perform a coordinate transform with a random invertible matrix
72-
T_true = np.matrix([[-0.27144004, -0.39933167, 0.75634684, 0.44135471],
72+
T_true = np.array([[-0.27144004, -0.39933167, 0.75634684, 0.44135471],
7373
[-0.74855725, -0.39136285, -0.18142339, -0.50356997],
7474
[-0.40688007, 0.81416369, 0.38002113, -0.16483334],
7575
[-0.44769516, 0.15654653, -0.50060858, 0.72419146]])
76-
A = np.linalg.solve(T_true, A_true)*T_true
76+
A = np.linalg.solve(T_true, A_true).dot(T_true)
7777
B = np.linalg.solve(T_true, B_true)
7878
C = C_true*T_true
7979
D = D_true
@@ -98,9 +98,9 @@ def test_modal_form(self):
9898
C_true = np.array([[1, 0, 0, 1]])
9999
D_true = np.array([[0]])
100100

101-
A = np.linalg.solve(T_true, A_true) * T_true
101+
A = np.linalg.solve(T_true, A_true).dot(T_true)
102102
B = np.linalg.solve(T_true, B_true)
103-
C = C_true * T_true
103+
C = C_true.dot(T_true)
104104
D = D_true
105105

106106
# Create state space system and convert to modal canonical form
@@ -132,9 +132,9 @@ def test_modal_form(self):
132132
C_true = np.array([[0, 1, 0, 1]])
133133
D_true = np.array([[0]])
134134

135-
A = np.linalg.solve(T_true, A_true) * T_true
135+
A = np.linalg.solve(T_true, A_true).dot(T_true)
136136
B = np.linalg.solve(T_true, B_true)
137-
C = C_true * T_true
137+
C = C_true.dot(T_true)
138138
D = D_true
139139

140140
# Create state space system and convert to modal canonical form
@@ -173,13 +173,13 @@ def test_observable_form(self):
173173
D_true = 42.0
174174

175175
# Perform a coordinate transform with a random invertible matrix
176-
T_true = np.matrix([[-0.27144004, -0.39933167, 0.75634684, 0.44135471],
176+
T_true = np.array([[-0.27144004, -0.39933167, 0.75634684, 0.44135471],
177177
[-0.74855725, -0.39136285, -0.18142339, -0.50356997],
178178
[-0.40688007, 0.81416369, 0.38002113, -0.16483334],
179179
[-0.44769516, 0.15654653, -0.50060858, 0.72419146]])
180-
A = np.linalg.solve(T_true, A_true)*T_true
180+
A = np.linalg.solve(T_true, A_true).dot(T_true)
181181
B = np.linalg.solve(T_true, B_true)
182-
C = C_true*T_true
182+
C = C_true.dot(T_true)
183183
D = D_true
184184

185185
# Create a state space system and convert it to the observable canonical form

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy