Skip to content

Commit 5ce5f57

Browse files
committed
Fixed bug #5 ('dt' instead of 'Ts' in dtime.py) and added some unit tests for dtime and FRD bdalg.
1 parent 0ba67cc commit 5ce5f57

6 files changed

Lines changed: 76 additions & 17 deletions

File tree

ChangeLog

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
2014-03-22 Richard Murray <murray@sidamo.local>
2+
3+
* tests/discrete_test.py (TestDiscrete.test_sample_system): added
4+
conversions using tustin and zoh to catch 'dt' bug #5
5+
6+
* src/dtime.py (sample_system): Changed 'dt' to 'Ts' to fix bug #4
7+
8+
* tests/frd_test.py (TestFRD.testbdalg): added unit tests for bdalg
9+
functions operating on FRD data
10+
11+
* src/bdalg.py (series, parallel, negate, feedback): updated
12+
documentation to note that FRD ovjects work.
13+
(feedback): updated conversions to allow for FRD
14+
115
2013-07-15 Richard Murray <murray@altura-2.local>
216

317
* src/frdata.py, src/xferfcn.py: updated to use __truediv__ and

src/bdalg.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,15 @@
5656
import scipy as sp
5757
import control.xferfcn as tf
5858
import control.statesp as ss
59+
import control.frdata as frd
5960

6061
def series(sys1, sys2):
6162
"""Return the series connection sys2 * sys1 for --> sys1 --> sys2 -->.
6263
6364
Parameters
6465
----------
65-
sys1: scalar, StateSpace, or TransferFunction
66-
sys2: scalar, StateSpace, or TransferFunction
66+
sys1: scalar, StateSpace, TransferFunction, or FRD
67+
sys2: scalar, StateSpace, TransferFunction, or FRD
6768
6869
Returns
6970
-------
@@ -105,8 +106,8 @@ def parallel(sys1, sys2):
105106
106107
Parameters
107108
----------
108-
sys1: scalar, StateSpace, or TransferFunction
109-
sys2: scalar, StateSpace, or TransferFunction
109+
sys1: scalar, StateSpace, TransferFunction, or FRD
110+
sys2: scalar, StateSpace, TransferFunction, or FRD
110111
111112
Returns
112113
-------
@@ -148,7 +149,7 @@ def negate(sys):
148149
149150
Parameters
150151
----------
151-
sys: StateSpace or TransferFunction
152+
sys: StateSpace, TransferFunction or FRD
152153
153154
Returns
154155
-------
@@ -179,9 +180,9 @@ def feedback(sys1, sys2=1, sign=-1):
179180
180181
Parameters
181182
----------
182-
sys1: scalar, StateSpace, or TransferFunction
183+
sys1: scalar, StateSpace, TransferFunction, FRD
183184
The primary plant.
184-
sys2: scalar, StateSpace, or TransferFunction
185+
sys2: scalar, StateSpace, TransferFunction, FRD
185186
The feedback plant (often a feedback controller).
186187
sign: scalar
187188
The sign of feedback. `sign` = -1 indicates negative feedback, and
@@ -219,13 +220,13 @@ def feedback(sys1, sys2=1, sign=-1):
219220

220221
# Check for correct input types.
221222
if not isinstance(sys1, (int, float, complex, tf.TransferFunction,
222-
ss.StateSpace)):
223-
raise TypeError("sys1 must be a TransferFunction or StateSpace object, \
224-
or a scalar.")
223+
ss.StateSpace)):
224+
raise TypeError("sys1 must be a TransferFunction or StateSpace " +
225+
"object, or a scalar.")
225226
if not isinstance(sys2, (int, float, complex, tf.TransferFunction,
226-
ss.StateSpace)):
227-
raise TypeError("sys2 must be a TransferFunction or StateSpace object, \
228-
or a scalar.")
227+
ss.StateSpace)):
228+
raise TypeError("sys2 must be a TransferFunction or StateSpace " +
229+
"object, or a scalar.")
229230

230231
# If sys1 is a scalar, convert it to the appropriate LTI type so that we can
231232
# its feedback member function.
@@ -234,6 +235,8 @@ def feedback(sys1, sys2=1, sign=-1):
234235
sys1 = tf._convertToTransferFunction(sys1)
235236
elif isinstance(sys2, ss.StateSpace):
236237
sys1 = ss._convertToStateSpace(sys1)
238+
elif isinstance(sys2, frd.FRD):
239+
sys1 = ss._convertToFRD(sys1)
237240
else: # sys2 is a scalar.
238241
sys1 = tf._convertToTransferFunction(sys1)
239242
sys2 = tf._convertToTransferFunction(sys2)

src/dtime.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def sample_system(sysc, Ts, method='matched'):
112112
from scipy.signal import cont2discrete
113113
sys = [sysc.num[0][0], sysc.den[0][0]]
114114
scipySysD = cont2discrete(sys, Ts, method='bilinear')
115-
sysd = TransferFunction(scipySysD[0][0], scipySysD[1], dt)
115+
sysd = TransferFunction(scipySysD[0][0], scipySysD[1], Ts)
116116
except ImportError:
117117
raise TypeError("cont2discrete not found in scipy.signal; upgrade to v0.10.0+")
118118

@@ -121,7 +121,7 @@ def sample_system(sysc, Ts, method='matched'):
121121
from scipy.signal import cont2discrete
122122
sys = [sysc.num[0][0], sysc.den[0][0]]
123123
scipySysD = cont2discrete(sys, Ts, method='zoh')
124-
sysd = TransferFunction(scipySysD[0][0],scipySysD[1], dt)
124+
sysd = TransferFunction(scipySysD[0][0],scipySysD[1], Ts)
125125
except ImportError:
126126
raise TypeError("cont2discrete not found in scipy.signal; upgrade to v0.10.0+")
127127

src/frdata.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,6 @@ def _convertToFRD(sys, omega, inputs=1, outputs=1):
451451
"""
452452

453453
if isinstance(sys, FRD):
454-
455454
omega.sort()
456455
if (abs(omega - sys.omega) < FRD.epsw).all():
457456
# frequencies match, and system was already frd; simply use

tests/discrete_test.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,12 @@ def test_sample_system(self):
264264
for sysc in (self.siso_ss1, self.siso_ss1c, self.siso_tf1c):
265265
sysd = sample_system(sysc, 1, method='matched')
266266
self.assertEqual(sysd.dt, 1)
267+
268+
sysd = sample_system(sysc, 1, method='tustin')
269+
self.assertEqual(sysd.dt, 1)
270+
271+
sysd = sample_system(sysc, 1, method='zoh')
272+
self.assertEqual(sysd.dt, 1)
267273
# TODO: put in other generic checks
268274

269275
# TODO: check results of converstion

tests/frd_test.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from control.xferfcn import TransferFunction
1111
from control.frdata import FRD, _convertToFRD
1212
from control.matlab import bode
13+
import control.bdalg as bdalg
1314
import control.freqplot
1415
import matplotlib.pyplot as plt
1516

@@ -106,7 +107,43 @@ def testOperatorsTf(self):
106107
(f1 / h2).freqresp([0.1, 1.0, 10])[1],
107108
(h1 / h2).freqresp([0.1, 1.0, 10])[1])
108109
# the reverse does not work
109-
110+
111+
def testbdalg(self):
112+
# get two SISO transfer functions
113+
h1 = TransferFunction([1], [1, 2, 2])
114+
h2 = TransferFunction([1], [0.1, 1])
115+
omega = np.logspace(-1, 2, 10)
116+
f1 = FRD(h1, omega)
117+
f2 = FRD(h2, omega)
118+
119+
np.testing.assert_array_almost_equal(
120+
(bdalg.series(f1, f2)).freqresp([0.1, 1.0, 10])[0],
121+
(bdalg.series(h1, h2)).freqresp([0.1, 1.0, 10])[0])
122+
123+
np.testing.assert_array_almost_equal(
124+
(bdalg.parallel(f1, f2)).freqresp([0.1, 1.0, 10])[0],
125+
(bdalg.parallel(h1, h2)).freqresp([0.1, 1.0, 10])[0])
126+
127+
np.testing.assert_array_almost_equal(
128+
(bdalg.feedback(f1, f2)).freqresp([0.1, 1.0, 10])[0],
129+
(bdalg.feedback(h1, h2)).freqresp([0.1, 1.0, 10])[0])
130+
131+
np.testing.assert_array_almost_equal(
132+
(bdalg.negate(f1)).freqresp([0.1, 1.0, 10])[0],
133+
(bdalg.negate(h1)).freqresp([0.1, 1.0, 10])[0])
134+
135+
# append() and connect() not implemented for FRD objects
136+
# np.testing.assert_array_almost_equal(
137+
# (bdalg.append(f1, f2)).freqresp([0.1, 1.0, 10])[0],
138+
# (bdalg.append(h1, h2)).freqresp([0.1, 1.0, 10])[0])
139+
#
140+
# f3 = bdalg.append(f1, f2, f2)
141+
# h3 = bdalg.append(h1, h2, h2)
142+
# Q = np.mat([ [1, 2], [2, -1] ])
143+
# np.testing.assert_array_almost_equal(
144+
# (bdalg.connect(f3, Q, [2], [1])).freqresp([0.1, 1.0, 10])[0],
145+
# (bdalg.connect(h3, Q, [2], [1])).freqresp([0.1, 1.0, 10])[0])
146+
110147
def testFeedback(self):
111148
h1 = TransferFunction([1], [1, 2, 2])
112149
omega = np.logspace(-1, 2, 10)

0 commit comments

Comments
 (0)