|
From: <kk...@us...> - 2011-02-08 22:15:13
|
Revision: 66
http://python-control.svn.sourceforge.net/python-control/?rev=66&view=rev
Author: kkchen
Date: 2011-02-08 22:15:06 +0000 (Tue, 08 Feb 2011)
Log Message:
-----------
Old TransferFunction class removed from xferfcn.py. The "developer version"
xTransferFunction is now renamed TransferFunction.
Related fixes in bdalg.py, TestXferFcn.py, and TestBDAlg.py.
Kevin K. Chen <kk...@pr...>
Modified Paths:
--------------
branches/control-0.4a/src/TestBDAlg.py
branches/control-0.4a/src/TestXferFcn.py
branches/control-0.4a/src/bdalg.py
branches/control-0.4a/src/xferfcn.py
Modified: branches/control-0.4a/src/TestBDAlg.py
===================================================================
--- branches/control-0.4a/src/TestBDAlg.py 2011-02-08 22:15:01 UTC (rev 65)
+++ branches/control-0.4a/src/TestBDAlg.py 2011-02-08 22:15:06 UTC (rev 66)
@@ -1,7 +1,7 @@
#!/usr/bin/env python
import numpy as np
-from xferfcn import xTransferFunction
+from xferfcn import TransferFunction
from statesp import StateSpace
from bdalg import feedback
import unittest
@@ -15,7 +15,7 @@
"""This contains some random LTI systems and scalars for testing."""
# Two random SISO systems.
- self.sys1 = xTransferFunction([1, 2], [1, 2, 3])
+ self.sys1 = TransferFunction([1, 2], [1, 2, 3])
self.sys2 = StateSpace([[1., 4.], [3., 2.]], [[1.], [-4.]],
[[1., 0.]], [[0.]])
# Two random scalars.
Modified: branches/control-0.4a/src/TestXferFcn.py
===================================================================
--- branches/control-0.4a/src/TestXferFcn.py 2011-02-08 22:15:01 UTC (rev 65)
+++ branches/control-0.4a/src/TestXferFcn.py 2011-02-08 22:15:06 UTC (rev 66)
@@ -1,7 +1,7 @@
#!/usr/bin/env python
import numpy as np
-from xferfcn import xTransferFunction
+from xferfcn import TransferFunction
import unittest
class TestXferFcn(unittest.TestCase):
@@ -15,42 +15,42 @@
def testBadInputType(self):
"""Give the constructor invalid input types."""
- self.assertRaises(TypeError, xTransferFunction, [[0., 1.], [2., 3.]],
+ self.assertRaises(TypeError, TransferFunction, [[0., 1.], [2., 3.]],
[[5., 2.], [3., 0.]])
def testInconsistentDimension(self):
"""Give the constructor a numerator and denominator of different
sizes."""
- self.assertRaises(ValueError, xTransferFunction, [[[1.]]],
+ self.assertRaises(ValueError, TransferFunction, [[[1.]]],
[[[1.], [2., 3.]]])
- self.assertRaises(ValueError, xTransferFunction, [[[1.]]],
+ self.assertRaises(ValueError, TransferFunction, [[[1.]]],
[[[1.]], [[2., 3.]]])
- self.assertRaises(ValueError, xTransferFunction, [[[1.]]],
+ self.assertRaises(ValueError, TransferFunction, [[[1.]]],
[[[1.], [1., 2.]], [[5., 2.], [2., 3.]]])
def testInconsistentColumns(self):
"""Give the constructor inputs that do not have the same number of
columns in each row."""
- self.assertRaises(ValueError, xTransferFunction, 1.,
+ self.assertRaises(ValueError, TransferFunction, 1.,
[[[1.]], [[2.], [3.]]])
- self.assertRaises(ValueError, xTransferFunction, [[[1.]], [[2.], [3.]]],
+ self.assertRaises(ValueError, TransferFunction, [[[1.]], [[2.], [3.]]],
1.)
def testZeroDenominator(self):
"""Give the constructor a transfer function with a zero denominator."""
- self.assertRaises(ValueError, xTransferFunction, 1., 0.)
- self.assertRaises(ValueError, xTransferFunction,
+ self.assertRaises(ValueError, TransferFunction, 1., 0.)
+ self.assertRaises(ValueError, TransferFunction,
[[[1.], [2., 3.]], [[-1., 4.], [3., 2.]]],
[[[1., 0.], [0.]], [[0., 0.], [2.]]])
def testAddInconsistentDimension(self):
"""Add two transfer function matrices of different sizes."""
- sys1 = xTransferFunction([[[1., 2.]]], [[[4., 5.]]])
- sys2 = xTransferFunction([[[4., 3.]], [[1., 2.]]],
+ sys1 = TransferFunction([[[1., 2.]]], [[[4., 5.]]])
+ sys2 = TransferFunction([[[4., 3.]], [[1., 2.]]],
[[[1., 6.]], [[2., 4.]]])
self.assertRaises(ValueError, sys1.__add__, sys2)
self.assertRaises(ValueError, sys1.__sub__, sys2)
@@ -60,21 +60,21 @@
def testMulInconsistentDimension(self):
"""Multiply two transfer function matrices of incompatible sizes."""
- sys1 = xTransferFunction([[[1., 2.], [4., 5.]], [[2., 5.], [4., 3.]]],
+ sys1 = TransferFunction([[[1., 2.], [4., 5.]], [[2., 5.], [4., 3.]]],
[[[6., 2.], [4., 1.]], [[6., 7.], [2., 4.]]])
- sys2 = xTransferFunction([[[1.]], [[2.]], [[3.]]],
+ sys2 = TransferFunction([[[1.]], [[2.]], [[3.]]],
[[[4.]], [[5.]], [[6.]]])
self.assertRaises(ValueError, sys1.__mul__, sys2)
self.assertRaises(ValueError, sys2.__mul__, sys1)
self.assertRaises(ValueError, sys1.__rmul__, sys2)
self.assertRaises(ValueError, sys2.__rmul__, sys1)
- # Tests for xTransferFunction._truncatecoeff
+ # Tests for TransferFunction._truncatecoeff
def testTruncateCoeff1(self):
"""Remove extraneous zeros in polynomial representations."""
- sys1 = xTransferFunction([0., 0., 1., 2.], [[[0., 0., 0., 3., 2., 1.]]])
+ sys1 = TransferFunction([0., 0., 1., 2.], [[[0., 0., 0., 3., 2., 1.]]])
np.testing.assert_array_equal(sys1.num, [[[1., 2.]]])
np.testing.assert_array_equal(sys1.den, [[[3., 2., 1.]]])
@@ -82,17 +82,17 @@
def testTruncateCoeff2(self):
"""Remove extraneous zeros in polynomial representations."""
- sys1 = xTransferFunction([0., 0., 0.], 1.)
+ sys1 = TransferFunction([0., 0., 0.], 1.)
np.testing.assert_array_equal(sys1.num, [[[0.]]])
np.testing.assert_array_equal(sys1.den, [[[1.]]])
- # Tests for xTransferFunction.__neg__
+ # Tests for TransferFunction.__neg__
def testNegScalar(self):
"""Negate a direct feedthrough system."""
- sys1 = xTransferFunction(2., np.array([-3]))
+ sys1 = TransferFunction(2., np.array([-3]))
sys2 = - sys1
np.testing.assert_array_equal(sys2.num, [[[-2.]]])
@@ -101,7 +101,7 @@
def testNegSISO(self):
"""Negate a SISO system."""
- sys1 = xTransferFunction([1., 3., 5], [1., 6., 2., -1.])
+ sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1.])
sys2 = - sys1
np.testing.assert_array_equal(sys2.num, [[[-1., -3., -5.]]])
@@ -117,22 +117,22 @@
den1 = [[[-3., 2., 4.], [1., 0., 0.], [2., -1.]],
[[3., 0., .0], [2., -1., -1.], [1.]]]
- sys1 = xTransferFunction(num1, den1)
+ sys1 = TransferFunction(num1, den1)
sys2 = - sys1
- sys3 = xTransferFunction(num3, den1)
+ sys3 = TransferFunction(num3, den1)
for i in range(sys3.outputs):
for j in range(sys3.inputs):
np.testing.assert_array_equal(sys2.num[i][j], sys3.num[i][j])
np.testing.assert_array_equal(sys2.den[i][j], sys3.den[i][j])
- # Tests for xTransferFunction.__add__
+ # Tests for TransferFunction.__add__
def testAddScalar(self):
"""Add two direct feedthrough systems."""
- sys1 = xTransferFunction(1., [[[1.]]])
- sys2 = xTransferFunction(np.array([2.]), [1.])
+ sys1 = TransferFunction(1., [[[1.]]])
+ sys2 = TransferFunction(np.array([2.]), [1.])
sys3 = sys1 + sys2
np.testing.assert_array_equal(sys3.num, 3.)
@@ -141,8 +141,8 @@
def testAddSISO(self):
"""Add two SISO systems."""
- sys1 = xTransferFunction([1., 3., 5], [1., 6., 2., -1])
- sys2 = xTransferFunction([[np.array([-1., 3.])]], [[[1., 0., -1.]]])
+ sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1])
+ sys2 = TransferFunction([[np.array([-1., 3.])]], [[[1., 0., -1.]]])
sys3 = sys1 + sys2
# If sys3.num is [[[0., 20., 4., -8.]]], then this is wrong!
@@ -165,8 +165,8 @@
den3 = [[[3., -2., -4.], [1., 2., 3., 0., 0.], [-2., -1., 1.]],
[[-12., -9., 6., 0., 0.], [2., -1., -1.], [1., 0.]]]
- sys1 = xTransferFunction(num1, den1)
- sys2 = xTransferFunction(num2, den2)
+ sys1 = TransferFunction(num1, den1)
+ sys2 = TransferFunction(num2, den2)
sys3 = sys1 + sys2
for i in range(sys3.outputs):
@@ -174,13 +174,13 @@
np.testing.assert_array_equal(sys3.num[i][j], num3[i][j])
np.testing.assert_array_equal(sys3.den[i][j], den3[i][j])
- # Tests for xTransferFunction.__sub__
+ # Tests for TransferFunction.__sub__
def testSubScalar(self):
"""Add two direct feedthrough systems."""
- sys1 = xTransferFunction(1., [[[1.]]])
- sys2 = xTransferFunction(np.array([2.]), [1.])
+ sys1 = TransferFunction(1., [[[1.]]])
+ sys2 = TransferFunction(np.array([2.]), [1.])
sys3 = sys1 - sys2
np.testing.assert_array_equal(sys3.num, -1.)
@@ -189,8 +189,8 @@
def testSubSISO(self):
"""Add two SISO systems."""
- sys1 = xTransferFunction([1., 3., 5], [1., 6., 2., -1])
- sys2 = xTransferFunction([[np.array([-1., 3.])]], [[[1., 0., -1.]]])
+ sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1])
+ sys2 = TransferFunction([[np.array([-1., 3.])]], [[[1., 0., -1.]]])
sys3 = sys1 - sys2
sys4 = sys2 - sys1
@@ -215,8 +215,8 @@
den3 = [[[3., -2., -4], [1., 2., 3., 0., 0.], [1]],
[[-12., -9., 6., 0., 0.], [2., -1., -1], [1., 0.]]]
- sys1 = xTransferFunction(num1, den1)
- sys2 = xTransferFunction(num2, den2)
+ sys1 = TransferFunction(num1, den1)
+ sys2 = TransferFunction(num2, den2)
sys3 = sys1 - sys2
for i in range(sys3.outputs):
@@ -224,13 +224,13 @@
np.testing.assert_array_equal(sys3.num[i][j], num3[i][j])
np.testing.assert_array_equal(sys3.den[i][j], den3[i][j])
- # Tests for xTransferFunction.__mul__
+ # Tests for TransferFunction.__mul__
def testMulScalar(self):
"""Multiply two direct feedthrough systems."""
- sys1 = xTransferFunction(2., [1.])
- sys2 = xTransferFunction(1., 4.)
+ sys1 = TransferFunction(2., [1.])
+ sys2 = TransferFunction(1., 4.)
sys3 = sys1 * sys2
sys4 = sys1 * sys2
@@ -242,8 +242,8 @@
def testMulSISO(self):
"""Multiply two SISO systems."""
- sys1 = xTransferFunction([1., 3., 5], [1., 6., 2., -1])
- sys2 = xTransferFunction([[[-1., 3.]]], [[[1., 0., -1.]]])
+ sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1])
+ sys2 = TransferFunction([[[-1., 3.]]], [[[1., 0., -1.]]])
sys3 = sys1 * sys2
sys4 = sys2 * sys1
@@ -273,8 +273,8 @@
0., 0.]],
[[-48., 60., 84., -81., -45., 21., 9., 0., 0., 0., 0., 0., 0.]]]
- sys1 = xTransferFunction(num1, den1)
- sys2 = xTransferFunction(num2, den2)
+ sys1 = TransferFunction(num1, den1)
+ sys2 = TransferFunction(num2, den2)
sys3 = sys1 * sys2
for i in range(sys3.outputs):
@@ -282,13 +282,13 @@
np.testing.assert_array_equal(sys3.num[i][j], num3[i][j])
np.testing.assert_array_equal(sys3.den[i][j], den3[i][j])
- # Tests for xTransferFunction.__div__
+ # Tests for TransferFunction.__div__
def testDivScalar(self):
"""Divide two direct feedthrough systems."""
- sys1 = xTransferFunction(np.array([3.]), -4.)
- sys2 = xTransferFunction(5., 2.)
+ sys1 = TransferFunction(np.array([3.]), -4.)
+ sys2 = TransferFunction(5., 2.)
sys3 = sys1 / sys2
np.testing.assert_array_equal(sys3.num, [[[6.]]])
@@ -297,8 +297,8 @@
def testDivSISO(self):
"""Divide two SISO systems."""
- sys1 = xTransferFunction([1., 3., 5], [1., 6., 2., -1])
- sys2 = xTransferFunction([[[-1., 3.]]], [[[1., 0., -1.]]])
+ sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1])
+ sys2 = TransferFunction([[[-1., 3.]]], [[[1., 0., -1.]]])
sys3 = sys1 / sys2
sys4 = sys2 / sys1
@@ -307,12 +307,12 @@
np.testing.assert_array_equal(sys4.num, sys3.den)
np.testing.assert_array_equal(sys4.den, sys3.num)
- # Tests for xTransferFunction.evalfr.
+ # Tests for TransferFunction.evalfr.
def testEvalFrSISO(self):
"""Evaluate the frequency response of a SISO system at one frequency."""
- sys = xTransferFunction([1., 3., 5], [1., 6., 2., -1])
+ sys = TransferFunction([1., 3., 5], [1., 6., 2., -1])
np.testing.assert_array_almost_equal(sys.evalfr(1.),
np.array([[-0.5 - 0.5j]]))
@@ -326,20 +326,20 @@
[[1.], [4., 0.], [1., -4., 3.]]]
den = [[[-3., 2., 4.], [1., 0., 0.], [2., -1.]],
[[3., 0., .0], [2., -1., -1.], [1.]]]
- sys = xTransferFunction(num, den)
+ sys = TransferFunction(num, den)
resp = [[0.147058823529412 + 0.0882352941176471j, -0.75, 1.],
[-0.083333333333333, -0.188235294117647 - 0.847058823529412j,
-1. - 8.j]]
np.testing.assert_array_almost_equal(sys.evalfr(2.), resp)
- # Tests for xTransferFunction.freqresp.
+ # Tests for TransferFunction.freqresp.
def testFreqRespSISO(self):
"""Evaluate the magnitude and phase of a SISO system at multiple
frequencies."""
- sys = xTransferFunction([1., 3., 5], [1., 6., 2., -1])
+ sys = TransferFunction([1., 3., 5], [1., 6., 2., -1])
truemag = [[[4.63507337473906, 0.707106781186548, 0.0866592803995351]]]
truephase = [[[-2.89596891081488, -2.35619449019234,
@@ -360,7 +360,7 @@
[[1.], [4., 0.], [1., -4., 3.]]]
den = [[[-3., 2., 4.], [1., 0., 0.], [2., -1.]],
[[3., 0., .0], [2., -1., -1.], [1.]]]
- sys = xTransferFunction(num, den)
+ sys = TransferFunction(num, den)
trueomega = [0.1, 1., 10.]
truemag = [[[0.496287094505259, 0.307147558416976, 0.0334738176210382],
@@ -380,12 +380,12 @@
np.testing.assert_array_almost_equal(phase, truephase)
np.testing.assert_array_equal(omega, trueomega)
- # Tests for xTransferFunction.feedback.
+ # Tests for TransferFunction.feedback.
def testFeedbackSISO(self):
- sys1 = xTransferFunction([-1., 4.], [1., 3., 5.])
- sys2 = xTransferFunction([2., 3., 0.], [1., -3., 4., 0])
+ sys1 = TransferFunction([-1., 4.], [1., 3., 5.])
+ sys2 = TransferFunction([2., 3., 0.], [1., -3., 4., 0])
sys3 = sys1.feedback(sys2)
sys4 = sys1.feedback(sys2, 1)
Modified: branches/control-0.4a/src/bdalg.py
===================================================================
--- branches/control-0.4a/src/bdalg.py 2011-02-08 22:15:01 UTC (rev 65)
+++ branches/control-0.4a/src/bdalg.py 2011-02-08 22:15:06 UTC (rev 66)
@@ -47,6 +47,21 @@
import xferfcn as tf
import statesp as ss
+def series(sys1, sys2):
+ """Return the series connection sys1 * sys2 for --> sys2 --> sys1 -->."""
+
+ return sys1 * sys2
+
+def parallel(sys1, sys2):
+ """Return the parallel connection sys1 + sys2."""
+
+ return sys1 + sys2
+
+def negate(sys):
+ """Return the negative of a system."""
+
+ return -sys;
+
def feedback(sys1, sys2, sign=-1):
"""Feedback interconnection between two I/O systems.
@@ -79,11 +94,11 @@
xferfcn.feedback."""
# Check for correct input types.
- if not isinstance(sys1, (int, long, float, complex, tf.xTransferFunction,
+ if not isinstance(sys1, (int, long, float, complex, tf.TransferFunction,
ss.StateSpace)):
raise TypeError("sys1 must be a TransferFunction or StateSpace object, \
or a scalar.")
- if not isinstance(sys2, (int, long, float, complex, tf.xTransferFunction,
+ if not isinstance(sys2, (int, long, float, complex, tf.TransferFunction,
ss.StateSpace)):
raise TypeError("sys2 must be a TransferFunction or StateSpace object, \
or a scalar.")
@@ -91,7 +106,7 @@
# If sys1 is a scalar, convert it to the appropriate LTI type so that we can
# its feedback member function.
if isinstance(sys1, (int, long, float, complex)):
- if isinstance(sys2, tf.xTransferFunction):
+ if isinstance(sys2, tf.TransferFunction):
sys1 = tf.convertToTransferFunction(sys1)
elif isinstance(sys2, ss.StateSpace):
sys1 = ss.convertToStateSpace(sys1)
Modified: branches/control-0.4a/src/xferfcn.py
===================================================================
--- branches/control-0.4a/src/xferfcn.py 2011-02-08 22:15:01 UTC (rev 65)
+++ branches/control-0.4a/src/xferfcn.py 2011-02-08 22:15:06 UTC (rev 66)
@@ -54,7 +54,7 @@
import statesp
from lti2 import Lti2
-class xTransferFunction(Lti2):
+class TransferFunction(Lti2):
"""The TransferFunction class is derived from the Lti2 parent class. The
main data members are 'num' and 'den', which are 2-D lists of arrays
containing MIMO numerator and denominator coefficients. For example,
@@ -210,13 +210,13 @@
for j in range(self.inputs):
num[i][j] *= -1
- return xTransferFunction(num, self.den)
+ return TransferFunction(num, self.den)
def __add__(self, other):
"""Add two transfer functions (parallel connection)."""
# Convert the second argument to a transfer function.
- if not isinstance(other, xTransferFunction):
+ if not isinstance(other, TransferFunction):
other = convertToTransferFunction(other, self.inputs, self.outputs)
# Check that the input-output sizes are consistent.
@@ -236,7 +236,7 @@
num[i][j], den[i][j] = _addSISO(self.num[i][j], self.den[i][j],
other.num[i][j], other.den[i][j])
- return xTransferFunction(num, den)
+ return TransferFunction(num, den)
def __radd__(self, other):
"""Add two transfer functions (parallel connection)."""
@@ -257,7 +257,7 @@
"""Multiply two transfer functions (serial connection)."""
# Convert the second argument to a transfer function.
- if not isinstance(other, xTransferFunction):
+ if not isinstance(other, TransferFunction):
other = convertToTransferFunction(other, self.inputs, self.inputs)
# Check that the input-output sizes are consistent.
@@ -285,7 +285,7 @@
num[i][j], den[i][j] = _addSISO(num[i][j], den[i][j],
num_summand[k], den_summand[k])
- return xTransferFunction(num, den)
+ return TransferFunction(num, den)
def __rmul__(self, other):
"""Multiply two transfer functions (serial connection)."""
@@ -298,17 +298,17 @@
if self.inputs > 1 or self.outputs > 1 or \
other.inputs > 1 or other.outputs > 1:
- raise NotImplementedError("xTransferFunction.__div__ is currently \
+ raise NotImplementedError("TransferFunction.__div__ is currently \
implemented only for SISO systems.")
# Convert the second argument to a transfer function.
- if not isinstance(other, xTransferFunction):
+ if not isinstance(other, TransferFunction):
other = convertToTransferFunction(other, 1, 1)
num = sp.polymul(self.num[0][0], other.den[0][0])
den = sp.polymul(self.den[0][0], other.num[0][0])
- return xTransferFunction(num, den)
+ return TransferFunction(num, den)
# TODO: Division of MIMO transfer function objects is quite difficult.
def __rdiv__(self, other):
@@ -316,7 +316,7 @@
if self.inputs > 1 or self.outputs > 1 or \
other.inputs > 1 or other.outputs > 1:
- raise NotImplementedError("xTransferFunction.__rdiv__ is currently \
+ raise NotImplementedError("TransferFunction.__rdiv__ is currently \
implemented only for SISO systems.")
return other / self
@@ -371,7 +371,7 @@
if self.inputs > 1 or self.outputs > 1 or \
other.inputs > 1 or other.outputs > 1:
- raise NotImplementedError("xTransferFunction.feedback is currently \
+ raise NotImplementedError("TransferFunction.feedback is currently \
only implemented for SISO functions.")
num1 = self.num[0][0]
@@ -382,185 +382,13 @@
num = sp.polymul(num1, den2)
den = sp.polyadd(sp.polymul(den2, den1), -sign * sp.polymul(num2, num1))
- return xTransferFunction(num, den)
+ return TransferFunction(num, den)
# For MIMO or SISO systems, the analytic expression is
# self / (1 - sign * other * self)
# But this does not work correctly because the state size will be too
# large.
-# This is the old TransferFunction class. It will be superceded by the
-# xTransferFunction class (which will be renamed TransferFunction) when it is
-# completed.
-class TransferFunction(signal.lti):
- """The TransferFunction class is used to represent linear
- input/output systems via its transfer function.
- """
- # Constructor
- def __init__(self, *args, **keywords):
- # First initialize the parent object
- signal.lti.__init__(self, *args, **keywords)
-
- # Make sure that this is only a SISO function
- if (self.inputs != 1 or self.outputs != 1):
- raise NotImplementedError("MIMO transfer functions not supported")
-
- # Now add a few more attributes
- self.variable = 's'
-
- # Style to use for printing (similar to MATLAB)
- def __str__(self):
- labstr = ""
- outstr = ""
- for i in range(self.inputs):
- for j in range(self.outputs):
- # Create a label for the transfer function and extract
- # numerator polynomial (depends on number of inputs/outputs)
- if (self.inputs > 1 and self.outputs > 1):
- labstr = "H[] = "; lablen = 7;
- numstr = _tfpolyToString(self.num[i,j], self.variable);
- elif (self.inputs > 1):
- labstr = "H[] = "; lablen = 7;
- numstr = _tfpolyToString(self.num[i], self.variable);
- elif (self.outputs > 1):
- labstr = "H[] = "; lablen = 7;
- numstr = _tfpolyToString(self.num[j], self.variable);
- else:
- labstr = ""; lablen = 0;
- numstr = _tfpolyToString(self.num, self.variable);
-
- # Convert the (common) denominator polynomials to strings
- denstr = _tfpolyToString(self.den, self.variable);
-
- # Figure out the length of the separating line
- dashcount = max(len(numstr), len(denstr))
- dashes = labstr + '-' * dashcount
-
- # Center the numerator or denominator
- if (len(numstr) < dashcount):
- numstr = ' ' * \
- int(round((dashcount - len(numstr))/2) + lablen) + \
- numstr
- if (len(denstr) < dashcount):
- denstr = ' ' * \
- int(round((dashcount - len(denstr))/2) + lablen) + \
- denstr
-
- outstr += "\n" + numstr + "\n" + dashes + "\n" + denstr + "\n"
- return outstr
-
- # Negation of a transfer function
- def __neg__(self):
- """Negate a transfer function"""
- return TransferFunction(-self.num, self.den)
-
- # Subtraction (use addition)
- def __sub__(self, other):
- """Subtract two transfer functions"""
- return self + (-other)
-
- def __rsub__(self, other):
- """Subtract two transfer functions"""
- return other + (-self)
-
- # Addition of two transfer functions (parallel interconnection)
- def __add__(self, sys):
- """Add two transfer functions (parallel connection)"""
- # Convert the second argument to a transfer function
- other = convertToTransferFunction(sys)
-
- # Compute the numerator and denominator of the sum
- den = sp.polymul(self.den, other.den)
- num = sp.polyadd(sp.polymul(self.num, other.den), \
- sp.polymul(other.num, self.den))
-
- return TransferFunction(num, den)
-
- # Reverse addition - just switch the order
- def __radd__(self, other):
- """Add two transfer functions (parallel connection)"""
- return self + other;
-
- # Multiplication of two transfer functions (series interconnection)
- def __mul__(self, sys):
- """Multiply two transfer functions (serial connection)"""
- # Make sure we have a transfer function (or convert to one)
- other = convertToTransferFunction(sys)
-
- # Compute the product of the transfer functions
- num = sp.polymul(self.num, other.num)
- den = sp.polymul(self.den, other.den)
- return TransferFunction(num, den)
-
- # Reverse multiplication - switch order (works for SISO)
- def __rmul__(self, other):
- """Multiply two transfer functions (serial connection)"""
- return self * other
-
- # Division between transfer functions
- def __div__(self, sys):
- """Divide two transfer functions"""
- other = convertToTransferFunction(sys);
- return TransferFunction(sp.polymul(self.num, other.den),
- sp.polymul(self.den, other.num));
-
- # Reverse division
- def __rdiv__(self, sys):
- """Divide two transfer functions"""
- other = convertToTransferFunction(sys);
- return TransferFunction(sp.polymul(other.num, self.den),
- sp.polymul(other.den, self.num));
-
- # Method for evaluating a transfer function at one frequency
- def evalfr(self, freq):
- """Evaluate a transfer function at a single frequency"""
- return sp.polyval(self.num, freq*1j) / sp.polyval(self.den, freq*1j)
-
- # Method for generating the frequency response of the system
- def freqresp(self, omega):
- """Evaluate a transfer function at a list of frequencies"""
- # Convert numerator and denomintator to 1D polynomials
- num = sp.poly1d(self.num)
- den = sp.poly1d(self.den)
-
- # Generate the frequency response at each frequency
- fresp = map(lambda w: num(w*1j) / den(w*1j), omega)
-
- mag = sp.sqrt(sp.multiply(fresp, sp.conjugate(fresp)));
- phase = sp.angle(fresp)
-
- return mag, phase, omega
-
- # Compute poles and zeros
- def poles(self): return sp.roots(self.den)
- def zeros(self): return sp.roots(self.num)
-
- # Feedback around a transfer function
- def feedback(sys1, sys2, sign=-1):
- """Feedback interconnection between two transfer functions"""
- # Get the numerator and denominator of the first system
- if (isinstance(sys1, (int, long, float, complex))):
- num1 = sys1; den1 = 1;
- elif (isinstance(sys1, TransferFunction)):
- num1 = sys1.num; den1 = sys1.den;
- else:
- raise TypeError
-
- # Get the numerator and denominator of the second system
- if (isinstance(sys2, (int, long, float, complex))):
- num2 = sys2; den2 = 1;
- elif (isinstance(sys2, TransferFunction)):
- num2 = sys2.num; den2 = sys2.den;
- else:
- raise TypeError
-
- # Compute sys1/(1 - sign*sys1*sys2)
- num = sp.polymul(num1, den2);
- den = sp.polysub(sp.polymul(den1, den2), sign * sp.polymul(num1, num2))
-
- # Return the result as a transfer function
- return TransferFunction(num, den)
-
# Utility function to convert a transfer function polynomial to a string
# Borrowed from poly1d library
def _tfpolyToString(coeffs, var='s'):
@@ -622,7 +450,7 @@
def convertToTransferFunction(sys, inputs=1, outputs=1):
"""Convert a system to transfer function form (if needed.)"""
- if isinstance(sys, xTransferFunction):
+ if isinstance(sys, TransferFunction):
return sys
elif isinstance(sys, statesp.StateSpace):
raise NotImplementedError("State space to transfer function conversion \
@@ -634,6 +462,6 @@
for i in range(min(inputs, outputs)):
num[i][i] = [sys]
- return xTransferFunction(num, den)
+ return TransferFunction(num, den)
else:
- raise TypeError("Can't convert given type to xTransferFunction system.")
+ raise TypeError("Can't convert given type to TransferFunction system.")
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|