Skip to content

Commit

Permalink
Merge pull request #60 from cwrowley/docs
Browse files Browse the repository at this point in the history
Reorganize and improve documentation
  • Loading branch information
murrayrm committed Apr 26, 2015
2 parents 88a7d01 + 01ff7ac commit 58c7f85
Show file tree
Hide file tree
Showing 37 changed files with 504 additions and 511 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ build.log
*.egg-info/
.coverage
doc/_build
doc/generated
19 changes: 4 additions & 15 deletions control/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,9 @@
#
# $Id$

"""Control System Library
The Python Control System Library (control) provides common functions
"""
The Python Control Systems Library :mod:`control` provides common functions
for analyzing and designing feedback control systems.
Common functions
----------------
tf create a transfer function from num, den coefficients
ss create a state space system from A, B, C, D matrices
pzk create a transfer function from pole, zero, gain
frd create a system description as frequency response
bode generate a Bode plot for a linear I/O system
nyquist generate a Nyquist plot for a linear I/O system
lqr linear quadratic regulator
lqe linear quadratic estimator
"""

# Import functions from within the control system library
Expand All @@ -66,9 +54,10 @@
from .lti import issiso, timebase, timebaseEqual, isdtime, isctime
from .margins import stability_margins, phase_crossover_frequencies
from .mateqn import lyap, dlyap, care, dare
from .modelsimp import hsvd, modred, balred, era, markov
from .modelsimp import hsvd, modred, balred, era, markov, minreal
from .nichols import nichols_plot, nichols
from .phaseplot import phase_plot, box_grid
from .pzmap import pzmap
from .rlocus import root_locus
from .statefbk import place, lqr, ctrb, obsv, gram, acker
from .statesp import StateSpace
Expand Down
8 changes: 4 additions & 4 deletions control/bdalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ def append(*sys):
system given; if you mix state-space systems and gain matrices,
make sure the gain matrices are not first.
Parameters.
-----------
Parameters
----------
sys1, sys2, ... sysn: StateSpace or Transferfunction
LTI systems to combine
Expand Down Expand Up @@ -290,8 +290,8 @@ def connect(sys, Q, inputv, outputv):
Note: to have this work, inputs and outputs start counting at 1!!!!
Parameters.
-----------
Parameters
----------
sys: StateSpace Transferfunction
System to be connected
Q: 2d array
Expand Down
22 changes: 18 additions & 4 deletions control/canonical.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from numpy.linalg import inv


def canonical_form(xsys, form):
def canonical_form(xsys, form='reachable'):
"""Convert a system into canonical form
Parameters
Expand All @@ -20,15 +20,15 @@ def canonical_form(xsys, form):
form : String
Canonical form for transformation. Chosen from:
* 'reachable' - reachable canonical form
* 'observable' - observable canonical form
* 'observable' - observable canonical form [not implemented]
* 'modal' - modal canonical form [not implemented]
Outputs
Returns
-------
zsys : StateSpace object
System in desired canonical form, with state 'z'
T : matrix
Coordinate transformation matrix, z = T*x
Coordinate transformation matrix, z = T * x
"""

# Call the appropriate tranformation function
Expand All @@ -41,6 +41,20 @@ def canonical_form(xsys, form):

# Reachable canonical form
def reachable_form(xsys):
"""Convert a system into reachable canonical form
Parameters
----------
xsys : StateSpace object
System to be transformed, with state `x`
Returns
-------
zsys : StateSpace object
System in reachable canonical form, with state `z`
T : matrix
Coordinate transformation: z = T * x
"""
# Check to make sure we have a SISO system
if not issiso(xsys):
raise ControlNotImplemented(
Expand Down
2 changes: 1 addition & 1 deletion control/ctrlutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def unwrap(angle, period=2*pi):

def issys(obj):
"""Return True if an object is a system, otherwise False"""
return isinstance(obj, lti.Lti)
return isinstance(obj, lti.LTI)

def db2mag(db):
"""Convert a gain in decibels (dB) to a magnitude
Expand Down
33 changes: 14 additions & 19 deletions control/frdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,17 @@
from numpy import angle, array, empty, ones, \
real, imag, matrix, absolute, eye, linalg, where, dot
from scipy.interpolate import splprep, splev
from .lti import Lti
from .lti import LTI

class FRD(Lti):
"""The FRD class represents (measured?) frequency response
TF instances and functions.
class FRD(LTI):
"""A class for models defined by Frequency Response Data (FRD)
The FRD class is derived from the Lti parent class. It is used
throughout the python-control library to represent systems in frequency
response data form.
The FRD class is used to represent systems in frequency response data form.
The main data members are 'omega' and 'fresp'. omega is a 1D
array with the frequency points of the response. fresp is a 3D array,
with the first dimension corresponding to the outputs of the FRD,
the second dimension corresponding to the inputs, and the 3rd dimension
The main data members are 'omega' and 'fresp', where `omega` is a 1D
array with the frequency points of the response, and `fresp` is a 3D array,
with the first dimension corresponding to the output index of the FRD,
the second dimension corresponding to the input index, and the 3rd dimension
corresponding to the frequency points in omega.
For example,
Expand All @@ -107,7 +104,7 @@ class FRD(Lti):
epsw = 1e-8

def __init__(self, *args, **kwargs):
"""Construct a transfer function.
"""Construct an FRD object
The default constructor is FRD(d, w), where w is an iterable of
frequency points, and d is the matching frequency data.
Expand All @@ -118,16 +115,14 @@ def __init__(self, *args, **kwargs):
To call the copy constructor, call FRD(sys), where sys is a
FRD object.
To construct frequency response data for an existing Lti
To construct frequency response data for an existing LTI
object, other than an FRD, call FRD(sys, omega)
"""
smooth = kwargs.get('smooth', False)

if len(args) == 2:
if not isinstance(args[0], FRD) and isinstance(args[0], Lti):
if not isinstance(args[0], FRD) and isinstance(args[0], LTI):
# not an FRD, but still a system, second argument should be
# the frequency range
otherlti = args[0]
Expand Down Expand Up @@ -179,7 +174,7 @@ def __init__(self, *args, **kwargs):
w=1.0/(absolute(self.fresp[i, j, :])+0.001), s=0.0)
else:
self.ifunc = None
Lti.__init__(self, self.fresp.shape[1], self.fresp.shape[0])
LTI.__init__(self, self.fresp.shape[1], self.fresp.shape[0])

def __str__(self):
"""String representation of the transfer function."""
Expand Down Expand Up @@ -437,7 +432,7 @@ def _convertToFRD(sys, omega, inputs=1, outputs=1):
If sys is already an frd, and its frequency range matches or
overlaps the range given in omega then it is returned. If sys is
another Lti object or a transfer function, then it is converted to
another LTI object or a transfer function, then it is converted to
a frequency response data at the specified omega. If sys is a
scalar, then the number of inputs and outputs can be specified
manually, as in:
Expand All @@ -459,7 +454,7 @@ def _convertToFRD(sys, omega, inputs=1, outputs=1):
raise NotImplementedError(
"Frequency ranges of FRD do not match, conversion not implemented")

elif isinstance(sys, Lti):
elif isinstance(sys, LTI):
omega.sort()
fresp = empty((sys.outputs, sys.inputs, len(omega)), dtype=complex)
for k, w in enumerate(omega):
Expand Down
6 changes: 3 additions & 3 deletions control/freqplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def nyquist_plot(syslist, omega=None, Plot=True, color='b',
Parameters
----------
syslist : list of Lti
syslist : list of LTI
List of linear input/output systems (single system is OK)
omega : freq_range
Range of frequencies (list or bounds) in rad/sec
Expand Down Expand Up @@ -281,7 +281,7 @@ def gangof4_plot(P, C, omega=None):
Parameters
----------
P, C : Lti
P, C : LTI
Linear input/output systems (process and control)
omega : array
Range of frequencies (list or bounds) in rad/sec
Expand Down Expand Up @@ -344,7 +344,7 @@ def default_frequency_range(syslist):
Parameters
----------
syslist : list of Lti
syslist : list of LTI
List of linear input/output systems (single system is OK)
Returns
Expand Down
48 changes: 13 additions & 35 deletions control/lti.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"""lti.py
The Lti module contains the Lti parent class to the child classes StateSpace
The lti module contains the LTI parent class to the child classes StateSpace
and TransferFunction. It is designed for use in the python-control library.
Routines in this module:
Lti.__init__
LTI.__init__
isdtime()
isctime()
timebase()
Expand All @@ -14,10 +14,10 @@

from numpy import absolute, real

class Lti:
"""Lti is a parent class to linear time invariant control (LTI) objects.
class LTI:
"""LTI is a parent class to linear time-invariant (LTI) system objects.
Lti is the parent to the StateSpace and TransferFunction child
LTI is the parent to the StateSpace and TransferFunction child
classes. It contains the number of inputs and outputs, and the
timebase (dt) for the system.
Expand All @@ -30,32 +30,10 @@ class Lti:
* dt > 0 Discrete time system with sampling time dt
* dt = True Discrete time system with unspecified sampling time
When to Lti systems are combined, there timebases much match. A system
When two LTI systems are combined, their timebases much match. A system
with timebase None can be combined with a system having a specified
timebase, and the result will have the timebase of the latter system.
The StateSpace and TransferFunction child classes contain several common
"virtual" functions. These are:
__init__
copy
__str__
__neg__
__add__
__radd__
__sub__
__rsub__
__mul__
__rmul__
__div__
__rdiv__
evalfr
freqresp
pole
zero
feedback
returnScipySignalLti
"""

def __init__(self, inputs=1, outputs=1, dt=None):
Expand Down Expand Up @@ -112,25 +90,25 @@ def damp(self):
def issiso(sys, strict=False):
if isinstance(sys, (int, float, complex)) and not strict:
return True
elif not isinstance(sys, Lti):
raise ValueError("Object is not an Lti system")
elif not isinstance(sys, LTI):
raise ValueError("Object is not an LTI system")

# Done with the tricky stuff...
return sys.issiso()

# Return the timebase (with conversion if unspecified)
def timebase(sys, strict=True):
"""Return the timebase for an Lti system
"""Return the timebase for an LTI system
dt = timebase(sys)
returns the timebase for a system 'sys'. If the strict option is
set to False, dt = True will be returned as 1.
"""
# System needs to be either a constant or an Lti system
# System needs to be either a constant or an LTI system
if isinstance(sys, (int, float, complex)):
return None
elif not isinstance(sys, Lti):
elif not isinstance(sys, LTI):
raise ValueError("Timebase not defined")

# Return the sample time, with converstion to float if strict is false
Expand Down Expand Up @@ -181,7 +159,7 @@ def isdtime(sys, strict=False):
return True if not strict else False

# Check for a transfer function or state-space object
if isinstance(sys, Lti):
if isinstance(sys, LTI):
return sys.isdtime(strict)

# Got passed something we don't recognize
Expand All @@ -206,7 +184,7 @@ def isctime(sys, strict=False):
return True if not strict else False

# Check for a transfer function or state space object
if isinstance(sys, Lti):
if isinstance(sys, LTI):
return sys.isctime(strict)

# Got passed something we don't recognize
Expand Down
2 changes: 1 addition & 1 deletion control/margins.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def _polysqr(pol):

# Took the framework for the old function by
# Sawyer B. Fuller <minster@caltech.edu>, removed a lot of the innards
# and replaced with analytical polynomial functions for Lti systems.
# and replaced with analytical polynomial functions for LTI systems.
#
# idea for the frequency data solution copied/adapted from
# https://github.com/alchemyst/Skogestad-Python/blob/master/BODE.py
Expand Down
Loading

0 comments on commit 58c7f85

Please sign in to comment.