|
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.
|