From: <kk...@us...> - 2011-02-08 22:16:13
|
Revision: 78 http://python-control.svn.sourceforge.net/python-control/?rev=78&view=rev Author: kkchen Date: 2011-02-08 22:16:06 +0000 (Tue, 08 Feb 2011) Log Message: ----------- More docstrings written in preparation for Sphinx documentation. Miscellaneous edits, including raising NotImplementedError, using parentheses instead of '\' for line continuation, and converting types. Kevin K. Chen <kk...@pr...> Modified Paths: -------------- branches/control-0.4a/src/bdalg.py branches/control-0.4a/src/matlab.py branches/control-0.4a/src/statesp.py branches/control-0.4a/src/xferfcn.py Modified: branches/control-0.4a/src/bdalg.py =================================================================== --- branches/control-0.4a/src/bdalg.py 2011-02-08 22:16:00 UTC (rev 77) +++ branches/control-0.4a/src/bdalg.py 2011-02-08 22:16:06 UTC (rev 78) @@ -68,7 +68,7 @@ Raises ------ ValueError - if sys2.inputs does not equal sys1.outputs + if `sys2.inputs` does not equal `sys1.outputs` See Also -------- @@ -78,8 +78,8 @@ Notes ----- This function is a wrapper for the __mul__ function in the StateSpace and - TransferFunction classes. The output type is usually the type of sys2. If - sys2 is a scalar, then the output type is the type of sys1. + TransferFunction classes. The output type is usually the type of `sys2`. + If `sys2` is a scalar, then the output type is the type of `sys1`. Examples -------- @@ -105,7 +105,7 @@ Raises ------ ValueError - if sys1 and sys2 do not have the same numbers of inputs and outputs + if `sys1` and `sys2` do not have the same numbers of inputs and outputs See Also -------- @@ -115,8 +115,8 @@ Notes ----- This function is a wrapper for the __add__ function in the StateSpace and - TransferFunction classes. The output type is usually the type of sys1. If - sys1 is a scalar, then the output type is the type of sys2. + TransferFunction classes. The output type is usually the type of `sys1`. If + `sys1` is a scalar, then the output type is the type of `sys2`. Examples ------- @@ -162,9 +162,9 @@ sys2: scalar, StateSpace, or TransferFunction The feedback plant (often a feedback controller). sign: scalar - The sign of feedback. sign = -1 indicates negative feedback, and sign = 1 - indicates positive feedback. sign is an optional argument; it assumes a - value of -1 if not specified. + The sign of feedback. `sign` = -1 indicates negative feedback, and + `sign` = 1 indicates positive feedback. `sign` is an optional argument; it + assumes a value of -1 if not specified. Returns ------- @@ -173,8 +173,8 @@ Raises ------ ValueError - if sys1 does not have as many inputs as sys2 has outputs, or if sys2 - does not have as many inputs as sys1 has outputs + if `sys1` does not have as many inputs as `sys2` has outputs, or if + `sys2` does not have as many inputs as `sys1` has outputs NotImplementedError if an attempt is made to perform a feedback on a MIMO TransferFunction object @@ -187,11 +187,11 @@ Notes ---- This function is a wrapper for the feedback function in the StateSpace and - TransferFunction classes. It calls TransferFunction.feedback if sys1 is a - TransferFunction object, and StateSpace.feedback if sys1 is a StateSpace - object. If sys1 is a scalar, then it is converted to sys2's type, and the - corresponding feedback function is used. If sys1 and sys2 are both scalars, - then TransferFunction.feedback is used. + TransferFunction classes. It calls TransferFunction.feedback if `sys1` is a + TransferFunction object, and StateSpace.feedback if `sys1` is a StateSpace + object. If `sys1` is a scalar, then it is converted to `sys2`'s type, and + the corresponding feedback function is used. If `sys1` and `sys2` are both + scalars, then TransferFunction.feedback is used. """ Modified: branches/control-0.4a/src/matlab.py =================================================================== --- branches/control-0.4a/src/matlab.py 2011-02-08 22:16:00 UTC (rev 77) +++ branches/control-0.4a/src/matlab.py 2011-02-08 22:16:06 UTC (rev 78) @@ -274,7 +274,7 @@ C: numpy matrix or matrix-like object D: numpy matrix or matrix-like object sys: StateSpace or TransferFunction object - ss accepts a set of A, B, C, D matrices or sys. + ss accepts a set of `A`, `B`, `C`, `D` matrices or `sys`. Returns ------- @@ -321,7 +321,7 @@ num: vector, or list of lists of vectors den: vector, or list of lists of vectors sys: StateSpace or TransferFunction object - tf accepts a num and den, or sys. + tf accepts a `num` and `den`, or `sys``. Returns ------- @@ -330,9 +330,9 @@ Raises ------ ValueError - if num and den have invalid or unequal dimensions + if `num` and `den` have invalid or unequal dimensions TypeError - if num or den are of incorrect type + if `num` or `den` are of incorrect type See Also -------- @@ -342,9 +342,9 @@ Notes -------- - num[i][j] is the vector of polynomial coefficients of the transfer function - numerator from the (j+1)st output to the (i+1)st input. den[i][j] works the - same way. + `num`[`i`][`j`] is the vector of polynomial coefficients of the transfer + function numerator from the (`j`+1)st output to the (`i`+1)st input. + `den`[`i`][`j`] works the same way. Examples -------- @@ -382,7 +382,7 @@ C: numpy matrix or matrix-like object D: numpy matrix or matrix-like object sys: StateSpace object - ss accepts a set of A, B, C, D matrices or a StateSpace object. + ss accepts a set of `A`, `B`, `C`, `D` matrices, or `sys`. Returns ------- @@ -394,7 +394,7 @@ if matrix sizes are not self-consistent, or if an invalid number of arguments is passed in TypeError - if sys is not a StateSpace object + if `sys` is not a StateSpace object See Also -------- @@ -432,7 +432,7 @@ num: vector, or list of lists of vectors den: vector, or list of lists of vectors sys: TransferFunction object - tf2ss accepts num and den, or sys. + tf2ss accepts `num` and `den`, or `sys`. Returns ------- @@ -441,11 +441,11 @@ Raises ------ ValueError - if num and den have invalid or unequal dimensions, or if an invalid + if `num` and `den` have invalid or unequal dimensions, or if an invalid number of arguments is passed in TypeError - if num or den are of incorrect type, or if sys is not a TransferFunction - object + if `num` or `den` are of incorrect type, or if sys is not a + TransferFunction object See Also -------- @@ -455,9 +455,9 @@ Notes -------- - num[i][j] is the vector of polynomial coefficients of the transfer function - numerator from the (j+1)st output to the (i+1)st input. den[i][j] works the - same way. + `num`[`i`][`j`] is the vector of polynomial coefficients of the transfer + function numerator from the (`j`+1)st output to the (`i`+1)st input. + `den`[`i`][`j`] works the same way. Examples -------- @@ -481,35 +481,203 @@ raise ValueError("Needs 1 or 2 arguments; received %i." % len(args)) def rss(states=1, inputs=1, outputs=1): - """Create a stable continuous random state space object.""" + """ + Create a stable continuous random state space object. + Parameters + ---------- + states: integer + inputs: integer + outputs: integer + + Returns + ------- + sys: StateSpace object + + Raises + ------ + ValueError + if any input is not a positive integer + + See Also + -------- + drss + + Notes + ----- + If the number of states, inputs, or outputs is not specified, then the + missing numbers are assumed to be 1. The poles of the returned system will + always have a negative real part. + + """ + return rss_generate(states, inputs, outputs, 'c') def drss(states=1, inputs=1, outputs=1): - """Create a stable discrete random state space object.""" + """ + Create a stable discrete random state space object. + Parameters + ---------- + states: integer + inputs: integer + outputs: integer + + Returns + ------- + sys: StateSpace object + + Raises + ------ + ValueError + if any input is not a positive integer + + See Also + -------- + rss + + Notes + ----- + If the number of states, inputs, or outputs is not specified, then the + missing numbers are assumed to be 1. The poles of the returned system will + always have a magnitude less than 1. + + """ + return rss_generate(states, inputs, outputs, 'd') def pole(sys): - """Return system poles.""" + """ + Return system poles. + Parameters + ---------- + sys: StateSpace or TransferFunction object + + Returns + ------- + poles: ndarray + + Raises + ------ + NotImplementedError + when called on a TransferFunction object + + See Also + -------- + zero + + Notes + ----- + This function is a wrapper for StateSpace.pole and TransferFunction.pole. + + """ + return sys.pole() def zero(sys): - """Return system zeros.""" + """ + Return system zeros. + Parameters + ---------- + sys: StateSpace or TransferFunction object + + Returns + ------- + zeros: ndarray + + Raises + ------ + NotImplementedError + when called on a TransferFunction object or a MIMO StateSpace object + + See Also + -------- + pole + + Notes + ----- + This function is a wrapper for StateSpace.zero and TransferFunction.zero. + + """ + return sys.zero() def evalfr(sys, omega): - """Evaluate the transfer function of an LTI system at a single frequency - omega.""" + """ + Evaluate the transfer function of an LTI system at an angular frequency. + Parameters + ---------- + sys: StateSpace or TransferFunction object + omega: scalar + + Returns + ------- + fresp: ndarray + + See Also + -------- + freqresp + bode + + Notes + ----- + This function is a wrapper for StateSpace.evalfr and + TransferFunction.evalfr. + + Examples + -------- + >>> sys = rss(3, 2, 2) + >>> evalfr(sys, 1.) + array([[ 4.09376126 -6.2171555j , 23.71332080-35.24245284j], + [ 0.83405186 -1.82896006j, 8.10962251-12.66640309j]]) + This is the transfer function matrix evaluated at s = i. + + """ + return sys.evalfr(omega) def freqresp(sys, omega): - """Return the frequency response for an LTI object at a list of frequencies - omega.""" + """ + Frequency response of an LTI system at multiple angular frequencies. + Parameters + ---------- + sys: StateSpace or TransferFunction object + omega: list, tuple, or ndarray + + Returns + ------- + mag: ndarray + phase: ndarray + omega: list, tuple, or ndarray + + See Also + -------- + evalfr + bode + + Notes + ----- + This function is a wrapper for StateSpace.freqresp and + TransferFunction.freqresp. + + Examples + -------- + >>> sys = rss(3, 2, 2) + >>> mag, phase, omega = freqresp(sys, [0.1, 1., 10.]) + >>> mag[0, 1, :] + array([ 55.43747231, 42.47766549, 1.97225895]) + >>> phase[1, 0, :] + array([-0.12611087, -1.14294316, 2.5764547 ]) + This is the magnitude of the frequency response from the 2nd input to the + 1st output, and the phase (in radians) of the frequency response from the + 1st input to the 2nd output, for s = 0.1i, i, 10i. + + """ + return sys.freqresp(omega) # Bode plots Modified: branches/control-0.4a/src/statesp.py =================================================================== --- branches/control-0.4a/src/statesp.py 2011-02-08 22:16:00 UTC (rev 77) +++ branches/control-0.4a/src/statesp.py 2011-02-08 22:16:06 UTC (rev 78) @@ -68,8 +68,8 @@ """ -from numpy import angle, any, concatenate, cos, dot, empty, exp, eye, pi, \ - poly, poly1d, matrix, roots, sin, zeros +from numpy import angle, any, array, concatenate, cos, dot, empty, exp, eye, \ + pi, poly, poly1d, matrix, roots, sin, zeros from numpy.random import rand, randn from numpy.linalg import inv, det, solve from numpy.linalg.linalg import LinAlgError @@ -250,10 +250,10 @@ fresp = self.C * solve(omega * 1.j * eye(self.states) - self.A, self.B) + self.D - return fresp + return array(fresp) # Method for generating the frequency response of the system - def freqresp(self, omega=None): + def freqresp(self, omega): """Evaluate the system's transfer func. at a list of ang. frequencies. mag, phase, omega = self.freqresp(omega) @@ -294,10 +294,10 @@ den = poly1d(poly(self.A)) # Compute the numerator based on zeros #! TODO: This is currently limited to SISO systems - num = poly1d(\ - poly(self.A - dot(self.B, self.C)) + (self.D[0, 0] - 1) * den) + num = poly1d(poly(self.A - dot(self.B, self.C)) + ((self.D[0, 0] - 1) * + den)) - return (roots(num)) + return roots(num) # Feedback around a state space system def feedback(self, other, sign=-1): @@ -407,6 +407,17 @@ # Probability that D = 0. pDzero = 0.5 + # Check for valid input arguments. + if states < 1 or states % 1: + raise ValueError(("states must be a positive integer. states = %g." % + states)) + if inputs < 1 or inputs % 1: + raise ValueError(("inputs must be a positive integer. inputs = %g." % + inputs)) + if outputs < 1 or outputs % 1: + raise ValueError(("outputs must be a positive integer. outputs = %g." % + outputs)) + # Make some poles for A. Preallocate a complex array. poles = zeros(states) + zeros(states) * 0.j i = 0 Modified: branches/control-0.4a/src/xferfcn.py =================================================================== --- branches/control-0.4a/src/xferfcn.py 2011-02-08 22:16:00 UTC (rev 77) +++ branches/control-0.4a/src/xferfcn.py 2011-02-08 22:16:06 UTC (rev 78) @@ -106,14 +106,14 @@ if isinstance(data[i], (int, float, long, complex)): # Convert scalar to list of list of array. data[i] = [[array([data[i]])]] - elif isinstance(data[i], (list, tuple, ndarray)) and \ - isinstance(data[i][0], (int, float, long, complex)): + elif (isinstance(data[i], (list, tuple, ndarray)) and + isinstance(data[i][0], (int, float, long, complex))): # Convert array to list of list of array. data[i] = [[array(data[i])]] - elif isinstance(data[i], list) and \ - isinstance(data[i][0], list) and \ - isinstance(data[i][0][0], (list, tuple, ndarray)) and \ - isinstance(data[i][0][0][0], (int, float, long, complex)): + elif (isinstance(data[i], list) and + isinstance(data[i][0], list) and + isinstance(data[i][0][0], (list, tuple, ndarray)) and + isinstance(data[i][0][0][0], (int, float, long, complex))): # We might already have the right format. Convert the # coefficient vectors to arrays, if necessary. for j in range(len(data[i])): @@ -226,14 +226,12 @@ dashes = '-' * dashcount # Center the numerator or denominator - if (len(numstr) < dashcount): - numstr = ' ' * \ - int(round((dashcount - len(numstr))/2)) + \ - numstr - if (len(denstr) < dashcount): - denstr = ' ' * \ - int(round((dashcount - len(denstr))/2)) + \ - denstr + if len(numstr) < dashcount: + numstr = (' ' * int(round((dashcount - len(numstr))/2)) + + numstr) + if len(denstr) < dashcount: + denstr = (' ' * int(round((dashcount - len(denstr))/2)) + + denstr) outstr += "\n" + numstr + "\n" + dashes + "\n" + denstr + "\n" return outstr @@ -334,8 +332,8 @@ def __div__(self, other): """Divide two LTI objects.""" - if self.inputs > 1 or self.outputs > 1 or \ - other.inputs > 1 or other.outputs > 1: + 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.") @@ -351,8 +349,8 @@ def __rdiv__(self, other): """Reverse divide two LTI objects.""" - if self.inputs > 1 or self.outputs > 1 or \ - other.inputs > 1 or other.outputs > 1: + if (self.inputs > 1 or self.outputs > 1 or + other.inputs > 1 or other.outputs > 1): raise NotImplementedError("TransferFunction.__rdiv__ is currently \ implemented only for SISO systems.") @@ -371,13 +369,13 @@ for i in range(self.outputs): for j in range(self.inputs): - out[i][j] = polyval(self.num[i][j], omega * 1.j) / \ - polyval(self.den[i][j], omega * 1.j) + out[i][j] = (polyval(self.num[i][j], omega * 1.j) / + polyval(self.den[i][j], omega * 1.j)) return out # Method for generating the frequency response of the system - def freqresp(self, omega=None): + def freqresp(self, omega): """Evaluate a transfer function at a list of angular frequencies. mag, phase, omega = self.freqresp(omega) @@ -395,8 +393,8 @@ for i in range(self.outputs): for j in range(self.inputs): - fresp = map(lambda w: polyval(self.num[i][j], w * 1.j) / \ - polyval(self.den[i][j], w * 1.j), omega) + fresp = map(lambda w: (polyval(self.num[i][j], w * 1.j) / + polyval(self.den[i][j], w * 1.j)), omega) fresp = array(fresp) mag[i, j] = abs(fresp) @@ -407,20 +405,22 @@ def pole(self): """Compute the poles of a transfer function.""" - pass + raise NotImplementedError("TransferFunction.pole is not implemented \ +yet.") def zero(self): """Compute the zeros of a transfer function.""" - pass + raise NotImplementedError("TransferFunction.zero is not implemented \ +yet.") def feedback(self, other, sign=-1): """Feedback interconnection between two LTI objects.""" other = convertToTransferFunction(other) - if self.inputs > 1 or self.outputs > 1 or \ - other.inputs > 1 or other.outputs > 1: + if (self.inputs > 1 or self.outputs > 1 or + other.inputs > 1 or other.outputs > 1): # TODO: MIMO feedback raise NotImplementedError("TransferFunction.feedback is currently \ only implemented for SISO functions.") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |