|
From: <kk...@us...> - 2011-02-08 22:14:14
|
Revision: 54
http://python-control.svn.sourceforge.net/python-control/?rev=54&view=rev
Author: kkchen
Date: 2011-02-08 22:14:08 +0000 (Tue, 08 Feb 2011)
Log Message:
-----------
Worked on xTransferFunction.__add__ and __mul__ in xferfcn.py.
Also added tests in TestXferFcn.py.
Minor edit in statesp.py.
Kevin K. Chen <kk...@pr...>
Modified Paths:
--------------
branches/control-0.4a/src/statesp.py
branches/control-0.4a/src/xferfcn.py
Added Paths:
-----------
branches/control-0.4a/src/TestXferFcn.py
Added: branches/control-0.4a/src/TestXferFcn.py
===================================================================
--- branches/control-0.4a/src/TestXferFcn.py (rev 0)
+++ branches/control-0.4a/src/TestXferFcn.py 2011-02-08 22:14:08 UTC (rev 54)
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+
+import numpy as np
+from xferfcn import xTransferFunction
+import unittest
+
+class TestXferFcn(unittest.TestCase):
+ """These are tests for functionality and correct reporting of the transfer
+ function class."""
+
+ def testTruncateCoeff(self):
+ """Remove extraneous zeros in polynomial representations."""
+
+ sys1 = xTransferFunction([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.]]])
+
+ def testAddSISO1(self):
+ """Add two direct feedthrough systems."""
+
+ # Try different input formats, too.
+ sys1 = xTransferFunction(1., [[[1.]]])
+ sys2 = xTransferFunction([2.], [1.])
+ sys3 = sys1 + sys2
+
+ np.testing.assert_array_equal(sys3.num, 3.)
+ np.testing.assert_array_equal(sys3.den, 1.)
+
+ def testAddSISO2(self):
+ """Add two SISO systems."""
+
+ # Try different input formats, too.
+ sys1 = xTransferFunction([1., 3., 5], [1., 6., 2., -1])
+ sys2 = xTransferFunction([[[-1., 3.]]], [[[1., 0., -1.]]])
+ sys3 = sys1 + sys2
+
+ # If sys3.num is [[[0., 20., 4., -8.]]], then this is wrong!
+ np.testing.assert_array_equal(sys3.num, [[[20., 4., -8]]])
+ np.testing.assert_array_equal(sys3.den, [[[1., 6., 1., -7., -2., 1.]]])
+
+ def testAddMIMO(self):
+ """Add two MIMO systems."""
+
+ num1 = [[[1., 2.], [0., 3.], [2., -1.]],
+ [[1.], [4., 0.], [1., -4., 3.]]]
+ den1 = [[[-3., 2., 4.], [1., 0., 0.], [2., -1.]],
+ [[3., 0., .0], [2., -1., -1.], [1.]]]
+ num2 = [[[0., 0., -1], [2.], [-1., -1.]],
+ [[1., 2.], [-1., -2.], [4.]]]
+ den2 = [[[-1.], [1., 2., 3.], [-1., -1.]],
+ [[-4., -3., 2.], [0., 1.], [1., 0.]]]
+ num3 = [[[3., -3., -6], [5., 6., 9.], [-4., -2., 2]],
+ [[3., 2., -3., 2], [-2., -3., 7., 2.], [1., -4., 3., 4]]]
+ 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)
+
+ sys3 = sys1 + sys2
+
+ for i in range(sys3.outputs):
+ for j in range(sys3.inputs):
+ np.testing.assert_array_equal(sys3.num[i][j], num3[i][j])
+ np.testing.assert_array_equal(sys3.den[i][j], den3[i][j])
+
+if __name__ == "__main__":
+ unittest.main()
\ No newline at end of file
Property changes on: branches/control-0.4a/src/TestXferFcn.py
___________________________________________________________________
Added: svn:executable
+ *
Modified: branches/control-0.4a/src/statesp.py
===================================================================
--- branches/control-0.4a/src/statesp.py 2011-02-08 22:14:03 UTC (rev 53)
+++ branches/control-0.4a/src/statesp.py 2011-02-08 22:14:08 UTC (rev 54)
@@ -195,7 +195,7 @@
# Check to make sure the dimensions are OK
if (self.outputs != other.inputs):
raise ValueError, "Number of first's outputs must match number \
- of second's inputs."
+of second's inputs."
# Concatenate the various arrays
A = concatenate((
@@ -236,7 +236,7 @@
# Check to make sure the dimensions are OK
if ((self.inputs != other.outputs) or (self.outputs != other.inputs)):
raise ValueError, "State space systems don't have compatible \
- inputs/outputs for feedback."
+inputs/outputs for feedback."
# note that if there is an algebraic loop then this matrix inversion
# won't work
Modified: branches/control-0.4a/src/xferfcn.py
===================================================================
--- branches/control-0.4a/src/xferfcn.py 2011-02-08 22:14:03 UTC (rev 53)
+++ branches/control-0.4a/src/xferfcn.py 2011-02-08 22:14:08 UTC (rev 54)
@@ -111,11 +111,32 @@
self.den = den
Lti2.__init__(self, inputs, outputs)
+ self.truncatecoeff()
+
def __str__(self):
"""String representation of the transfer function."""
pass
+ def truncatecoeff(self):
+ """Remove extraneous zero coefficients from polynomials in numerator and
+ denominator matrices."""
+
+ data = [self.num, self.den]
+
+ for p in range(len(data)):
+ for i in range(self.outputs):
+ for j in range(self.inputs):
+ # Find the first nontrivial coefficient.
+ k = 0
+ while not data[p][i][j][k]:
+ k += 1
+
+ # Now truncate the trivial coefficients.
+ data[p][i][j] = data[p][i][j][k:]
+
+ [self.num, self.den] = data
+
def __neg__(self):
"""Negate a transfer function."""
@@ -128,16 +149,22 @@
if not isinstance(other, xTransferFunction):
other = ss2tf(other)
+ # Check that the input-output sizes are consistent.
+ if self.inputs != other.inputs:
+ raise ValueError("The two systems to be added must have the same \
+input size.")
+ if self.outputs != other.outputs:
+ raise ValueError("The two systems to be added must have the same \
+output size.")
+
# Preallocate the numerator and denominator of the sum.
num = [[[] for j in range(self.inputs)] for i in range(self.outputs)]
den = [[[] for j in range(self.inputs)] for i in range(self.outputs)]
for i in range(self.outputs):
for j in range(self.inputs):
- num[i][j] = sp.polyadd(
- sp.polymul(self.num[i][j], other.den[i][j]),
- sp.polymul(other.num[i][j], self.den[i][j]))
- den[i][j] = sp.polymul(self.den[i][j], other.den[i][j])
+ 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)
@@ -156,11 +183,40 @@
return other + (-self)
- def __mul__(self, sys):
+ def __mul__(self, other):
"""Multiply two transfer functions (serial connection)"""
- pass
+ # Convert the second argument to a transfer function.
+ if not isinstance(other, xTransferFunction):
+ other = ss2tf(other)
+
+ # Check that the input-output sizes are consistent.
+ if self.inputs != other.outputs:
+ raise ValueError("C = A * B: A must have the same number of \
+columns (inputs) as B has\nrows (outputs).")
+ inputs = other.inputs
+ outputs = self.outputs
+
+ # Preallocate the numerator and denominator of the sum.
+ num = [[[0] for j in range(inputs)] for i in range(outputs)]
+ den = [[[0] for j in range(inputs)] for i in range(outputs)]
+
+ # Temporary storage for the summands needed to find the (i, j)th element
+ # of the product.
+ num_summand = [[] for k in range(self.inputs)]
+ den_summand = [[] for k in range(self.inputs)]
+
+ for i in range(outputs): # Iterate through rows of product.
+ for j in range(inputs): # Iterate through columns of product.
+ for k in range(self.inputs): # Multiply & add.
+ num_summand[k] = sp.polymul(self.num[i][k], other.num[k][j])
+ den_summand[k] = sp.polymul(self.den[i][k], other.den[k][j])
+ num[i][j], den[i][j] = addSISO(num[i][j], den[i][j],
+ num_summand[k], den_summand[k])
+
+ return xTransferFunction(num, den)
+
def __rmul__(self, other):
"""Multiply two transfer functions (serial connection)"""
@@ -371,11 +427,6 @@
# Return the result as a transfer function
return TransferFunction(num, den)
-def ss2tf(sys):
- """Convert a state space object to a transfer function object."""
-
- pass
-
# Utility function to convert a transfer function polynomial to a string
# Borrowed from poly1d library
def _tfpolyToString(coeffs, var='s'):
@@ -424,3 +475,17 @@
else:
thestr = newstr
return thestr
+
+def addSISO(num1, den1, num2, den2):
+ """Return num/den = num1/den1 + num2/den2, where each numerator and
+ denominator is a list of polynomial coefficients."""
+
+ num = sp.polyadd(sp.polymul(num1, den2), sp.polymul(num2, den1))
+ den = sp.polymul(den1, den2)
+
+ return num, den
+
+def ss2tf(sys):
+ """Convert a state space object to a transfer function object."""
+
+ pass
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|