From: <kk...@us...> - 2011-02-08 22:14:04
|
Revision: 52 http://python-control.svn.sourceforge.net/python-control/?rev=52&view=rev Author: kkchen Date: 2011-02-08 22:13:58 +0000 (Tue, 08 Feb 2011) Log Message: ----------- Changed input processing in xferfcn.py; wrote skeleton for xTransferFunction. 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:53 UTC (rev 51) +++ branches/control-0.4a/src/xferfcn.py 2011-02-08 22:13:58 UTC (rev 52) @@ -73,30 +73,25 @@ # Make num and den into 3-d numpy arrays, if necessary. data = [num, den] for i in range(len(data)): - if isinstance(data[i], (int, long, float, complex)): + # 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 isinstance(data[i], sp.ndarray): - 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. - pass - else: - # If the user passed in a 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).") + 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. + pass + else: + # If the user passed in a 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).") [num, den] = data - print num - print den - inputs = num.shape[1] outputs = num.shape[0] @@ -111,9 +106,80 @@ self.den = den Lti2.__init__(self, inputs, outputs) - print self.inputs - print self.outputs + def __str__(self): pass + + def __neg__(self): + """Negate a transfer function.""" + + return xTransferFunction(-self.num, self.den) + + def __add__(self, sys): + """Add two transfer functions (parallel connection).""" + + pass + + def __radd__(self, other): + """Add two transfer functions (parallel connection)""" + + return self + other; + + def __sub__(self, other): + """Subtract two transfer functions.""" + + return self + (-other) + + def __rsub__(self, other): + """Subtract two transfer functions.""" + + return other + (-self) + def __mul__(self, sys): + """Multiply two transfer functions (serial connection)""" + + pass + + def __rmul__(self, other): + """Multiply two transfer functions (serial connection)""" + + return self * other + + def __div__(self, sys): + """Divide two transfer functions""" + + pass + + def __rdiv__(self, sys): + """Reverse divide two transfer functions""" + + pass + + 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) + pass + + # Method for generating the frequency response of the system + def freqresp(self, omega): + """Evaluate a transfer function at a list of frequencies""" + + pass + + def poles(self): + """Compute poles of a transfer function.""" + + pass + + def zeros(self): + """Compute zeros of a transfer function.""" + + pass + + def feedback(sys1, sys2, sign=-1): + """Feedback interconnection between two transfer functions""" + + pass + class TransferFunction(signal.lti): """The TransferFunction class is used to represent linear input/output systems via its transfer function. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
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. |
From: <kk...@us...> - 2011-02-08 22:14:19
|
Revision: 55 http://python-control.svn.sourceforge.net/python-control/?rev=55&view=rev Author: kkchen Date: 2011-02-08 22:14:13 +0000 (Tue, 08 Feb 2011) Log Message: ----------- Added xTransferFunction.__str__ in xferfcn.py. Appears to work well. 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:14:08 UTC (rev 54) +++ branches/control-0.4a/src/xferfcn.py 2011-02-08 22:14:13 UTC (rev 55) @@ -111,14 +111,43 @@ self.den = den Lti2.__init__(self, inputs, outputs) - self.truncatecoeff() + self._truncatecoeff() def __str__(self): """String representation of the transfer function.""" + + mimo = self.inputs > 1 or self.outputs > 1 + outstr = "" + + for i in range(self.inputs): + for j in range(self.outputs): + if mimo: + outstr += "\nInput %i to output %i:" % (i + 1, j + 1) + + lablen = 0 + + # Convert the numerator and denominator polynomials to strings. + numstr = _tfpolyToString(self.num[j][i]); + denstr = _tfpolyToString(self.den[j][i]); + + # Figure out the length of the separating line + dashcount = max(len(numstr), len(denstr)) + dashes = '-' * 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 - pass - - def truncatecoeff(self): + def _truncatecoeff(self): """Remove extraneous zero coefficients from polynomials in numerator and denominator matrices.""" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kk...@us...> - 2011-02-08 22:18:59
|
Revision: 111 http://python-control.svn.sourceforge.net/python-control/?rev=111&view=rev Author: kkchen Date: 2011-02-08 22:18:53 +0000 (Tue, 08 Feb 2011) Log Message: ----------- Fixes in xferfcn.py - Division by a scalar now works. - _common_den() modified so that the numerator coefficient arrays have the same size as the common denominator. This is done by padding with zeros. 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:18:49 UTC (rev 110) +++ branches/control-0.4a/src/xferfcn.py 2011-02-08 22:18:53 UTC (rev 111) @@ -344,14 +344,14 @@ def __div__(self, other): """Divide two LTI objects.""" + # Convert the second argument to a transfer function. + other = _convertToTransferFunction(other) + if (self.inputs > 1 or self.outputs > 1 or other.inputs > 1 or other.outputs > 1): raise NotImplementedError("TransferFunction.__div__ is currently \ implemented only for SISO systems.") - # Convert the second argument to a transfer function. - other = _convertToTransferFunction(other) - num = polymul(self.num[0][0], other.den[0][0]) den = polymul(self.den[0][0], other.num[0][0]) @@ -487,8 +487,9 @@ computes the single denominator containing all the poles of sys.den, and reports it as the array d. The output numerator array n is modified to - use the common denominator. It is an sys.outputs-by-sys.inputs-by- - [something] array. + use the common denominator; the coefficient arrays are also padded with + zeros to be the same size as d. n is an sys.outputs-by-sys.inputs-by- + len(d) array. """ @@ -588,16 +589,12 @@ # Multiply in the missing poles. for p in missingpoles[i][j]: num[i][j] = polymul(num[i][j], [1., -p]) - # Find the largest numerator polynomial size. - largest = 0 + # Pad all numerator polynomials with zeros so that the numerator arrays + # are the same size as the denominator. for i in range(self.outputs): for j in range(self.inputs): - largest = max(largest, len(num[i][j])) - # Pad all smaller numerator polynomials with zeros. - for i in range(self.outputs): - for j in range(self.inputs): - num[i][j] = insert(num[i][j], zeros(largest - len(num[i][j])), - zeros(largest - len(num[i][j]))) + num[i][j] = insert(num[i][j], zeros(len(den) - len(num[i][j])), + zeros(len(den) - len(num[i][j]))) # Finally, convert the numerator to a 3-D array. num = array(num) # Remove trivial imaginary parts. Check for nontrivial imaginary parts. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |