Skip to content

Commit 55df572

Browse files
committed
Changes in preparation for using v0.4 as trunk:
* Added missing MATLAB compatible functions for module reduction * Turned off print statements in unit tests (turn back on using verbose flag) * Removed bug warnings from conversion routines; posted open bug to Pending * Updated examples/pvtol-nested-ss to reflect interface changes * See ChangeLog for a detailed list of changes
1 parent 0f31ff6 commit 55df572

12 files changed

+86
-58
lines changed

ChangeLog

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
2011-04-02 Richard Murray <murray@malabar.local>
22

3+
* src/__init__.py: removed import of tests module (moved to tests/)
4+
5+
* src/matlab.py: Added hsvd, balred, modred to list of functions
6+
that are imported for use as is. Updated documentation string to
7+
indicate that these are implemented, along with a few other
8+
functions (zero, lqr) that weren't properly listed.
9+
10+
* src/modelsimp.py (balred): Removed extraneous print statements
11+
(modred): Set method to be 'matchdc' by default (to match MATLAB)
12+
13+
* src/__init__.py: added missing import of modelsimp functions
14+
15+
* tests/slycot_convert_test.py (TestSlycot.testTF): turned off print
16+
statements in unit test to make it easier to see results. Use
17+
verbose=True to turn back on.
18+
19+
* tests/convert_test.py (TestConvert.testConvert): got rid of print
20+
statements in unittest; clutters the output so that you can't see
21+
the errors clearly. Use verbose=True to turn back on.
22+
23+
* src/statesp.py (_convertToStateSpace): removed "buggy" print
24+
statements
25+
26+
* src/xferfcn.py (_convertToTransferFunction): removed "buggy" print
27+
statements
28+
329
* tests/nichols_test.py (TestStateSpace.testNgrid): updated testcode
430
to turn off grid in initial Nichols chart plot.
531

Pending

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ picture" things that need to be done.
1010

1111
OPEN BUGS
1212
* matlab.step() doesn't handle systems with a pole at the origin (use lsim2)
13-
* tests/convert_test.py not working yet
14-
* tests/test_all.py should report on failed tests
15-
* tests/freqresp.py needs to be converted to unit test
13+
* TF <-> SS transformations are buggy; see tests/convert_test.py
14+
* hsvd returns different value than MATLAB (2010a); see modelsimp_test.py
15+
* MIMO common denominator fails unit test; see convert_test.py
1616

1717
Transfer code from Roberto Bucher's yottalab to python-control
1818
acker - pole placement using Ackermann method
@@ -40,6 +40,9 @@ Examples and test cases
4040
* Put together unit tests for all functions (after deciding on framework)
4141
* Figure out how to import 'figure' command properly (version issue?)
4242
* Figure out source of BadCoefficients warning messages (pvtol-lqr and others)
43+
* tests/test_all.py should report on failed tests
44+
* tests/freqresp.py needs to be converted to unit test
45+
* Convert examples/test-{response,statefbk}.py to unit tests
4346

4447
TransferFunction class fixes
4548
* evalfr is not working (num, den stored as ndarrays, not poly1ds)

examples/pvtol-nested-ss.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,21 +95,21 @@
9595
# (gm, pm, wgc, wpc) = margin(L);
9696

9797
figure(6); clf; subplot(221);
98-
(magh, phaseh) = bode(L);
98+
bode(L, logspace(-4, 3));
9999

100100
# Add crossover line
101-
subplot(magh); hold(True);
102-
loglog([10^-4, 10^3], [1, 1], 'k-')
101+
subplot(211); hold(True);
102+
loglog([1e-4, 1e3], [1, 1], 'k-')
103103

104104
# Replot phase starting at -90 degrees
105-
bode(L, logspace(-4, 3));
106105
(mag, phase, w) = freqresp(L, logspace(-4, 3));
107106
phase = phase - 360;
108-
subplot(phaseh);
109-
semilogx([10^-4, 10^3], [-180, -180], 'k-')
107+
108+
subplot(212);
109+
semilogx([1e-4, 1e3], [-180, -180], 'k-')
110110
hold(True);
111111
semilogx(w, np.squeeze(phase), 'b-')
112-
axis([10^-4, 10^3, -360, 0]);
112+
axis([1e-4, 1e3, -360, 0]);
113113
xlabel('Frequency [deg]'); ylabel('Phase [deg]');
114114
# set(gca, 'YTick', [-360, -270, -180, -90, 0]);
115115
# set(gca, 'XTick', [10^-4, 10^-2, 1, 100]);
@@ -152,8 +152,8 @@
152152

153153
#TODO: PZmap for statespace systems has not yet been implemented.
154154
figure(10); clf();
155-
#(P, Z) = pzmap(T, Plot=True)
156-
#print "Closed loop poles and zeros: ", P, Z
155+
# (P, Z) = pzmap(T, Plot=True)
156+
# print "Closed loop poles and zeros: ", P, Z
157157

158158
# Gang of Four
159159
figure(11); clf();

src/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,4 @@
6363
from bdalg import *
6464
from statefbk import *
6565
from delay import *
66-
67-
from test import *
66+
from modelsimp import *

src/matlab.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
from pzmap import pzmap
8181
from statefbk import ctrb, obsv, gram, place, lqr
8282
from delay import pade
83+
from modelsimp import hsvd, balred, modred
8384

8485
__doc__ += """
8586
The control.matlab module defines functions that are roughly the
@@ -139,9 +140,9 @@
139140
lti/bandwidth - system bandwidth
140141
lti/norm - h2 and Hinfinity norms of LTI models
141142
\* lti/pole - system poles
142-
lti/zero - system (transmission) zeros
143+
\* lti/zero - system (transmission) zeros
143144
lti/order - model order (number of states)
144-
\* pzmap - pole-zero map
145+
\* pzmap - pole-zero map (TF only)
145146
lti/iopzmap - input/output pole-zero map
146147
damp - natural frequency and damping of system poles
147148
esort - sort continuous poles by real part
@@ -173,19 +174,20 @@
173174
Model simplification
174175
minreal - minimal realization and pole/zero cancellation
175176
ss/sminreal - structurally minimal realization (state space)
176-
lti/hsvd - hankel singular values (state contributions)
177-
lti/balred - reduced-order approximations of LTI models
178-
ss/modred - model order reduction
177+
\* lti/hsvd - hankel singular values (state contributions)
178+
\* lti/balred - reduced-order approximations of LTI models
179+
\* ss/modred - model order reduction
179180
180181
Compensator design
181182
rlocus - evans root locus
182-
place - pole placement
183+
\* place - pole placement
183184
estim - form estimator given estimator gain
184185
reg - form regulator given state-feedback and estimator gains
185186
186187
LQR/LQG design
187188
ss/lqg - single-step LQG design
188-
lqr, dlqr - linear-Quadratic (LQ) state-feedback regulator
189+
\* lqr - linear-Quadratic (LQ) state-feedback regulator
190+
\* dlqr - discrete-time LQ state-feedback regulator
189191
lqry - lq regulator with output weighting
190192
lqrd - discrete LQ regulator for continuous plant
191193
ss/lqi - linear-Quadratic-Integral (LQI) controller

src/modelsimp.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def hsvd(sys):
8484
# Return the Hankel singular values
8585
return hsv
8686

87-
def modred(sys,ELIM,method):
87+
def modred(sys,ELIM,method='matchdc'):
8888
"""Model reduction of sys by eliminating the states in ELIM using a given method
8989
9090
Parameters
@@ -207,8 +207,8 @@ def balred(sys,orders,method='truncate'):
207207

208208
#Check system is stable
209209
D,V = np.linalg.eig(sys.A)
210-
print D.shape
211-
print D
210+
# print D.shape
211+
# print D
212212
for e in D:
213213
if e.real >= 0:
214214
raise ValueError, "Oops, the system is unstable!"

src/statesp.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,8 +469,6 @@ def _convertToStateSpace(sys, **kw):
469469
# Repeat the common denominator along the rows.
470470
den = array([den for i in range(sys.outputs)])
471471
# TODO: transfer function to state space conversion is still buggy!
472-
print "Warning: transfer function to state space conversion by td04ad \
473-
is still buggy! Advise converting state space sys back to tf to verify the transformation was correct."
474472
#print num
475473
#print shape(num)
476474
ssout = td04ad('R',sys.inputs, sys.outputs, index, den, num,tol=0.0)

src/xferfcn.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -713,8 +713,6 @@ def _convertToTransferFunction(sys, **kw):
713713

714714
# Use Slycot to make the transformation. TODO: this is still somewhat
715715
# buggy!
716-
print "Warning: state space to transfer function conversion by tb04ad \
717-
is still buggy!"
718716
tfout = tb04ad(sys.states, sys.inputs, sys.outputs, sys.A, sys.B, sys.C,
719717
sys.D,tol1=0.0)
720718

@@ -727,8 +725,8 @@ def _convertToTransferFunction(sys, **kw):
727725
num[i][j] = list(tfout[6][i, j, :])
728726
# Each transfer function matrix row has a common denominator.
729727
den[i][j] = list(tfout[5][i, :])
730-
print num
731-
print den
728+
# print num
729+
# print den
732730
return TransferFunction(num, den)
733731
elif isinstance(sys, (int, long, float, complex)):
734732
if "inputs" in kw:

tests/convert_test.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22

3-
"""TestConvert.py
3+
"""convert_test.py
44
55
Test state space and transfer function conversion.
66
@@ -40,7 +40,7 @@ def printSys(self, sys, ind):
4040
print "sys%i:\n" % ind
4141
print sys
4242

43-
def testConvert(self):
43+
def testConvert(self, verbose=0):
4444
"""Test state space to transfer function conversion."""
4545
#Currently it only tests that a TF->SS->TF generates an unchanged TF
4646

@@ -52,16 +52,20 @@ def testConvert(self):
5252
#start with a random SS system and transform to TF
5353
#then back to SS, check that the matrices are the same.
5454
ssOriginal = matlab.rss(states, inputs, outputs)
55-
self.printSys(ssOriginal, 1)
55+
if (verbose):
56+
self.printSys(ssOriginal, 1)
5657

5758
tfOriginal = matlab.tf(ssOriginal)
58-
self.printSys(tfOriginal, 2)
59+
if (verbose):
60+
self.printSys(tfOriginal, 2)
5961

6062
ssTransformed = matlab.ss(tfOriginal)
61-
self.printSys(ssTransformed, 3)
63+
if (verbose):
64+
self.printSys(ssTransformed, 3)
6265

6366
tfTransformed = matlab.tf(ssTransformed)
64-
self.printSys(tfTransformed, 4)
67+
if (verbose):
68+
self.printSys(tfTransformed, 4)
6569

6670
for inputNum in range(inputs):
6771
for outputNum in range(outputs):
@@ -81,8 +85,6 @@ def testConvert(self):
8185
#[mag,phase,freq]=bode(sys)
8286
#it doesn't seem to......
8387
#This should be added.
84-
85-
8688

8789
def suite():
8890
return unittest.TestLoader().loadTestsFromTestCase(TestConvert)

tests/modelsimp_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def testHSVD(self):
1616
D = np.matrix("9.")
1717
sys = ss(A,B,C,D)
1818
hsv = hsvd(sys)
19-
hsvtrue = np.matrix("24.42686 0.5731395")
19+
hsvtrue = np.matrix("24.42686 0.5731395") # from MATLAB
2020
np.testing.assert_array_almost_equal(hsv, hsvtrue)
2121

2222
def testMarkov(self):

tests/slycot_convert_test.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,21 @@ def setUp(self):
2626
self.maxI = 1
2727
self.maxO = 1
2828

29-
def testTF(self):
29+
def testTF(self, verbose=False):
3030
""" Directly tests the functions tb04ad and td04ad through direct comparison of transfer function coefficients.
31-
Similar to TestConvert, but tests at a lower level.
31+
Similar to convert_test, but tests at a lower level.
3232
"""
3333
for states in range(1, self.maxStates):
3434
for inputs in range(1, self.maxI+1):
3535
for outputs in range(1, self.maxO+1):
3636
for testNum in range(self.numTests):
37-
3837
ssOriginal = matlab.rss(states, inputs, outputs)
39-
40-
print '====== Original SS =========='
41-
print ssOriginal
42-
print 'states=',states
43-
print 'inputs=',inputs
44-
print 'outputs=',outputs
38+
if (verbose):
39+
print '====== Original SS =========='
40+
print ssOriginal
41+
print 'states=',states
42+
print 'inputs=',inputs
43+
print 'outputs=',outputs
4544

4645

4746
tfOriginal_Actrb, tfOriginal_Bctrb, tfOriginal_Cctrb, tfOrigingal_nctrb, tfOriginal_index,\
@@ -55,15 +54,16 @@ def testTF(self):
5554
tfTransformed_index, tfTransformed_dcoeff, tfTransformed_ucoeff = tb04ad(ssTransformed_nr,\
5655
inputs,outputs,ssTransformed_A, ssTransformed_B, ssTransformed_C,ssTransformed_D,tol1=0.0)
5756
#print 'size(Trans_A)=',ssTransformed_A.shape
58-
print '===== Transformed SS =========='
59-
print matlab.ss(ssTransformed_A, ssTransformed_B, ssTransformed_C, ssTransformed_D)
60-
#print 'Trans_nr=',ssTransformed_nr
61-
#print 'tfOrig_index=',tfOriginal_index
62-
#print 'tfOrig_ucoeff=',tfOriginal_ucoeff
63-
#print 'tfOrig_dcoeff=',tfOriginal_dcoeff
64-
#print 'tfTrans_index=',tfTransformed_index
65-
#print 'tfTrans_ucoeff=',tfTransformed_ucoeff
66-
#print 'tfTrans_dcoeff=',tfTransformed_dcoeff
57+
if (verbose):
58+
print '===== Transformed SS =========='
59+
print matlab.ss(ssTransformed_A, ssTransformed_B, ssTransformed_C, ssTransformed_D)
60+
# print 'Trans_nr=',ssTransformed_nr
61+
# print 'tfOrig_index=',tfOriginal_index
62+
# print 'tfOrig_ucoeff=',tfOriginal_ucoeff
63+
# print 'tfOrig_dcoeff=',tfOriginal_dcoeff
64+
# print 'tfTrans_index=',tfTransformed_index
65+
# print 'tfTrans_ucoeff=',tfTransformed_ucoeff
66+
# print 'tfTrans_dcoeff=',tfTransformed_dcoeff
6767
#Compare the TF directly, must match
6868
#numerators
6969
np.testing.assert_array_almost_equal(tfOriginal_ucoeff,tfTransformed_ucoeff,decimal=3)

tests/test_all.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import re # regular expressions
88
import os # operating system commands
99

10-
def test_all(verbosity=2):
10+
def test_all(verbosity=0):
1111
""" Runs all tests written for python-control.
1212
"""
1313
try: # autodiscovery (python 2.7+)

0 commit comments

Comments
 (0)