|
From: <mur...@us...> - 2014-03-22 18:09:56
|
Revision: 294
http://sourceforge.net/p/python-control/code/294
Author: murrayrm
Date: 2014-03-22 18:09:48 +0000 (Sat, 22 Mar 2014)
Log Message:
-----------
Fixed bug #5 ('dt' instead of 'Ts' in dtime.py) and added some unit tests for dtime and FRD bdalg.
Modified Paths:
--------------
trunk/ChangeLog
trunk/src/bdalg.py
trunk/src/dtime.py
trunk/src/frdata.py
trunk/tests/discrete_test.py
trunk/tests/frd_test.py
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2013-07-16 14:59:20 UTC (rev 293)
+++ trunk/ChangeLog 2014-03-22 18:09:48 UTC (rev 294)
@@ -1,3 +1,17 @@
+2014-03-22 Richard Murray <mu...@si...>
+
+ * tests/discrete_test.py (TestDiscrete.test_sample_system): added
+ conversions using tustin and zoh to catch 'dt' bug #5
+
+ * src/dtime.py (sample_system): Changed 'dt' to 'Ts' to fix bug #4
+
+ * tests/frd_test.py (TestFRD.testbdalg): added unit tests for bdalg
+ functions operating on FRD data
+
+ * src/bdalg.py (series, parallel, negate, feedback): updated
+ documentation to note that FRD ovjects work.
+ (feedback): updated conversions to allow for FRD
+
2013-07-15 Richard Murray <mu...@al...>
* src/frdata.py, src/xferfcn.py: updated to use __truediv__ and
Modified: trunk/src/bdalg.py
===================================================================
--- trunk/src/bdalg.py 2013-07-16 14:59:20 UTC (rev 293)
+++ trunk/src/bdalg.py 2014-03-22 18:09:48 UTC (rev 294)
@@ -56,14 +56,15 @@
import scipy as sp
import control.xferfcn as tf
import control.statesp as ss
+import control.frdata as frd
def series(sys1, sys2):
"""Return the series connection sys2 * sys1 for --> sys1 --> sys2 -->.
Parameters
----------
- sys1: scalar, StateSpace, or TransferFunction
- sys2: scalar, StateSpace, or TransferFunction
+ sys1: scalar, StateSpace, TransferFunction, or FRD
+ sys2: scalar, StateSpace, TransferFunction, or FRD
Returns
-------
@@ -105,8 +106,8 @@
Parameters
----------
- sys1: scalar, StateSpace, or TransferFunction
- sys2: scalar, StateSpace, or TransferFunction
+ sys1: scalar, StateSpace, TransferFunction, or FRD
+ sys2: scalar, StateSpace, TransferFunction, or FRD
Returns
-------
@@ -148,7 +149,7 @@
Parameters
----------
- sys: StateSpace or TransferFunction
+ sys: StateSpace, TransferFunction or FRD
Returns
-------
@@ -179,9 +180,9 @@
Parameters
----------
- sys1: scalar, StateSpace, or TransferFunction
+ sys1: scalar, StateSpace, TransferFunction, FRD
The primary plant.
- sys2: scalar, StateSpace, or TransferFunction
+ sys2: scalar, StateSpace, TransferFunction, FRD
The feedback plant (often a feedback controller).
sign: scalar
The sign of feedback. `sign` = -1 indicates negative feedback, and
@@ -219,13 +220,13 @@
# Check for correct input types.
if not isinstance(sys1, (int, float, complex, tf.TransferFunction,
- ss.StateSpace)):
- raise TypeError("sys1 must be a TransferFunction or StateSpace object, \
-or a scalar.")
+ ss.StateSpace)):
+ raise TypeError("sys1 must be a TransferFunction or StateSpace " +
+ "object, or a scalar.")
if not isinstance(sys2, (int, float, complex, tf.TransferFunction,
- ss.StateSpace)):
- raise TypeError("sys2 must be a TransferFunction or StateSpace object, \
-or a scalar.")
+ ss.StateSpace)):
+ raise TypeError("sys2 must be a TransferFunction or StateSpace " +
+ "object, or a scalar.")
# If sys1 is a scalar, convert it to the appropriate LTI type so that we can
# its feedback member function.
@@ -234,6 +235,8 @@
sys1 = tf._convertToTransferFunction(sys1)
elif isinstance(sys2, ss.StateSpace):
sys1 = ss._convertToStateSpace(sys1)
+ elif isinstance(sys2, frd.FRD):
+ sys1 = ss._convertToFRD(sys1)
else: # sys2 is a scalar.
sys1 = tf._convertToTransferFunction(sys1)
sys2 = tf._convertToTransferFunction(sys2)
Modified: trunk/src/dtime.py
===================================================================
--- trunk/src/dtime.py 2013-07-16 14:59:20 UTC (rev 293)
+++ trunk/src/dtime.py 2014-03-22 18:09:48 UTC (rev 294)
@@ -112,7 +112,7 @@
from scipy.signal import cont2discrete
sys = [sysc.num[0][0], sysc.den[0][0]]
scipySysD = cont2discrete(sys, Ts, method='bilinear')
- sysd = TransferFunction(scipySysD[0][0], scipySysD[1], dt)
+ sysd = TransferFunction(scipySysD[0][0], scipySysD[1], Ts)
except ImportError:
raise TypeError("cont2discrete not found in scipy.signal; upgrade to v0.10.0+")
@@ -121,7 +121,7 @@
from scipy.signal import cont2discrete
sys = [sysc.num[0][0], sysc.den[0][0]]
scipySysD = cont2discrete(sys, Ts, method='zoh')
- sysd = TransferFunction(scipySysD[0][0],scipySysD[1], dt)
+ sysd = TransferFunction(scipySysD[0][0],scipySysD[1], Ts)
except ImportError:
raise TypeError("cont2discrete not found in scipy.signal; upgrade to v0.10.0+")
Modified: trunk/src/frdata.py
===================================================================
--- trunk/src/frdata.py 2013-07-16 14:59:20 UTC (rev 293)
+++ trunk/src/frdata.py 2014-03-22 18:09:48 UTC (rev 294)
@@ -451,7 +451,6 @@
"""
if isinstance(sys, FRD):
-
omega.sort()
if (abs(omega - sys.omega) < FRD.epsw).all():
# frequencies match, and system was already frd; simply use
Modified: trunk/tests/discrete_test.py
===================================================================
--- trunk/tests/discrete_test.py 2013-07-16 14:59:20 UTC (rev 293)
+++ trunk/tests/discrete_test.py 2014-03-22 18:09:48 UTC (rev 294)
@@ -264,6 +264,12 @@
for sysc in (self.siso_ss1, self.siso_ss1c, self.siso_tf1c):
sysd = sample_system(sysc, 1, method='matched')
self.assertEqual(sysd.dt, 1)
+
+ sysd = sample_system(sysc, 1, method='tustin')
+ self.assertEqual(sysd.dt, 1)
+
+ sysd = sample_system(sysc, 1, method='zoh')
+ self.assertEqual(sysd.dt, 1)
# TODO: put in other generic checks
# TODO: check results of converstion
Modified: trunk/tests/frd_test.py
===================================================================
--- trunk/tests/frd_test.py 2013-07-16 14:59:20 UTC (rev 293)
+++ trunk/tests/frd_test.py 2014-03-22 18:09:48 UTC (rev 294)
@@ -10,6 +10,7 @@
from control.xferfcn import TransferFunction
from control.frdata import FRD, _convertToFRD
from control.matlab import bode
+import control.bdalg as bdalg
import control.freqplot
import matplotlib.pyplot as plt
@@ -106,7 +107,43 @@
(f1 / h2).freqresp([0.1, 1.0, 10])[1],
(h1 / h2).freqresp([0.1, 1.0, 10])[1])
# the reverse does not work
-
+
+ def testbdalg(self):
+ # get two SISO transfer functions
+ h1 = TransferFunction([1], [1, 2, 2])
+ h2 = TransferFunction([1], [0.1, 1])
+ omega = np.logspace(-1, 2, 10)
+ f1 = FRD(h1, omega)
+ f2 = FRD(h2, omega)
+
+ np.testing.assert_array_almost_equal(
+ (bdalg.series(f1, f2)).freqresp([0.1, 1.0, 10])[0],
+ (bdalg.series(h1, h2)).freqresp([0.1, 1.0, 10])[0])
+
+ np.testing.assert_array_almost_equal(
+ (bdalg.parallel(f1, f2)).freqresp([0.1, 1.0, 10])[0],
+ (bdalg.parallel(h1, h2)).freqresp([0.1, 1.0, 10])[0])
+
+ np.testing.assert_array_almost_equal(
+ (bdalg.feedback(f1, f2)).freqresp([0.1, 1.0, 10])[0],
+ (bdalg.feedback(h1, h2)).freqresp([0.1, 1.0, 10])[0])
+
+ np.testing.assert_array_almost_equal(
+ (bdalg.negate(f1)).freqresp([0.1, 1.0, 10])[0],
+ (bdalg.negate(h1)).freqresp([0.1, 1.0, 10])[0])
+
+# append() and connect() not implemented for FRD objects
+# np.testing.assert_array_almost_equal(
+# (bdalg.append(f1, f2)).freqresp([0.1, 1.0, 10])[0],
+# (bdalg.append(h1, h2)).freqresp([0.1, 1.0, 10])[0])
+#
+# f3 = bdalg.append(f1, f2, f2)
+# h3 = bdalg.append(h1, h2, h2)
+# Q = np.mat([ [1, 2], [2, -1] ])
+# np.testing.assert_array_almost_equal(
+# (bdalg.connect(f3, Q, [2], [1])).freqresp([0.1, 1.0, 10])[0],
+# (bdalg.connect(h3, Q, [2], [1])).freqresp([0.1, 1.0, 10])[0])
+
def testFeedback(self):
h1 = TransferFunction([1], [1, 2, 2])
omega = np.logspace(-1, 2, 10)
|