|
From: <kk...@us...> - 2011-02-08 22:14:12
|
Revision: 53
http://python-control.svn.sourceforge.net/python-control/?rev=53&view=rev
Author: kkchen
Date: 2011-02-08 22:14:03 +0000 (Tue, 08 Feb 2011)
Log Message:
-----------
xTransferFunction changed so that num and den are lists of lists of arrays,
instead of 3-d numpy arrays. Also implemented xTransferFunction.__add__; seems
to work so far.
Kevin K. Chen <kk...@pr...>
Modified Paths:
--------------
branches/control-0.4a/src/xferfcn.py
Modified: branches/control-0.4a/src/xferfcn.py
===================================================================
--- branches/control-0.4a/src/xferfcn.py 2011-02-08 22:13:58 UTC (rev 52)
+++ branches/control-0.4a/src/xferfcn.py 2011-02-08 22:14:03 UTC (rev 53)
@@ -55,69 +55,92 @@
class xTransferFunction(Lti2):
"""The TransferFunction class is derived from the Lti2 parent class. The
- main data members are 'num' and 'den', which are 3-D numpy arrays of
- MIMO numerator and denominator coefficients. For instance,
+ main data members are 'num' and 'den', which are 2-D lists of arrays
+ containing MIMO numerator and denominator coefficients. For example,
+
+ >>> num[2][5] = [1., 4., 8.]
- >>> num[2, 5] = numpy.array([1, 4, 8])
-
means that the numerator of the transfer function from the 6th input to the
- 3rd output is set to s^2 + 4s + 8.
+ 3rd output is set to s^2 + 4s + 8."""
- Note that numpy requires all polynomials in within an array to have the same
- order. Be sure to pad leading coefficients with 0 as necessary."""
-
- def __init__(self, num=sp.array([[[1.]]]), den=sp.array([[[1.]]])):
+ def __init__(self, num=1, den=1):
"""This is the constructor. The default transfer function is 1 (unit
gain direct feedthrough)."""
-
+
# Make num and den into 3-d numpy arrays, if necessary.
data = [num, den]
for i in range(len(data)):
- # Convert non-array types to array first.
- data[i] = sp.array(data[i])
-
- if data[i].ndim == 0:
- # Convert scalar to 3-d array.
- data[i] = sp.array([[[data[i]]]])
- elif data[i].ndim == 1:
- # Convert SISO transfer function polynomial to 3-d array.
- data[i] = sp.array([[data[i]]])
- elif data[i].ndim == 3:
- # We already have a MIMO system.
+ if isinstance(data[i], (int, float, long, complex)):
+ # Convert scalar to list of list of array.
+ data[i] = [[[data[i]]]]
+ elif isinstance(data[i], (list, tuple, sp.ndarray)) and \
+ isinstance(data[i][0], (int, float, long, complex)):
+ # Convert array to list of list of array.
+ data[i] = [[data[i]]]
+ elif isinstance(data[i], (list, tuple, sp.ndarray)) and \
+ isinstance(data[i][0], (list, tuple, sp.ndarray)) and \
+ isinstance(data[i][0][0], (list, tuple, sp.ndarray)) and \
+ isinstance(data[i][0][0][0], (int, float, long, complex)):
+ # We already have the right format.
pass
else:
- # If the user passed in a anything else, then it's unclear
- # what the meaning is.
+ # If the user passed in anything else, then it's unclear what
+ # the meaning is.
raise ValueError("The numerator and denominator inputs must be \
- scalars or vectors (for SISO), or 3-d arrays (for MIMO).")
+scalars or arrays (for\nSISO), or lists of lists of arrays (for MIMO).")
[num, den] = data
- inputs = num.shape[1]
- outputs = num.shape[0]
+ inputs = len(num[0])
+ outputs = len(num)
- if inputs != den.shape[1]:
+ if inputs != len(den[0]):
raise ValueError("The numerator and denominator matrices must have \
- the same column (input) size.")
- if outputs != den.shape[0]:
+the same column\n(input) size.")
+ if outputs != len(den):
raise ValueError("The numerator and denominator matrices must have \
- the same row (output) size.")
-
+the same row\n(output) size.")
+ for i in range(1, outputs):
+ if len(num[i]) != inputs:
+ raise ValueError("Each row of the numerator matrix must have \
+the same number of\nelements.")
+ if len(den[i]) != inputs:
+ raise ValueError("Each row of the denominator matrix must have \
+the same number of\nelements.")
+
self.num = num
self.den = den
Lti2.__init__(self, inputs, outputs)
- def __str__(self): pass
+ def __str__(self):
+ """String representation of the transfer function."""
+ pass
+
def __neg__(self):
"""Negate a transfer function."""
return xTransferFunction(-self.num, self.den)
- def __add__(self, sys):
+ def __add__(self, other):
"""Add two transfer functions (parallel connection)."""
-
- pass
-
+
+ # Convert the second argument to a transfer function.
+ if not isinstance(other, xTransferFunction):
+ other = ss2tf(other)
+
+ # 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])
+
+ return xTransferFunction(num, den)
+
def __radd__(self, other):
"""Add two transfer functions (parallel connection)"""
@@ -348,24 +371,11 @@
# Return the result as a transfer function
return TransferFunction(num, den)
-# Function to create a transfer function from another type
-def convertToTransferFunction(sys):
- """Convert a system to a transfer fuction (if needed)"""
- if (isinstance(sys, TransferFunction)):
- # Already a transfer function; just return it
- return sys
+def ss2tf(sys):
+ """Convert a state space object to a transfer function object."""
- elif (isinstance(sys, statesp.StateSpace)):
- # State space system, convert using signal.lti
- return TransferFunction(sys.A, sys.B, sys.C, sys.D)
+ pass
- elif (isinstance(sys, (int, long, float, complex))):
- # Convert a number into a transfer function
- return TransferFunction(sys, 1)
-
- else:
- raise TypeError("can't convert given type to TransferFunction")
-
# Utility function to convert a transfer function polynomial to a string
# Borrowed from poly1d library
def _tfpolyToString(coeffs, var='s'):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|