Skip to content

Commit 58c7f85

Browse files
committed
Merge pull request #60 from cwrowley/docs
Reorganize and improve documentation
2 parents 88a7d01 + 01ff7ac commit 58c7f85

37 files changed

Lines changed: 504 additions & 511 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ build.log
1111
*.egg-info/
1212
.coverage
1313
doc/_build
14+
doc/generated

control/__init__.py

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,9 @@
3939
#
4040
# $Id$
4141

42-
"""Control System Library
43-
44-
The Python Control System Library (control) provides common functions
42+
"""
43+
The Python Control Systems Library :mod:`control` provides common functions
4544
for analyzing and designing feedback control systems.
46-
47-
Common functions
48-
----------------
49-
tf create a transfer function from num, den coefficients
50-
ss create a state space system from A, B, C, D matrices
51-
pzk create a transfer function from pole, zero, gain
52-
frd create a system description as frequency response
53-
bode generate a Bode plot for a linear I/O system
54-
nyquist generate a Nyquist plot for a linear I/O system
55-
lqr linear quadratic regulator
56-
lqe linear quadratic estimator
5745
"""
5846

5947
# Import functions from within the control system library
@@ -66,9 +54,10 @@
6654
from .lti import issiso, timebase, timebaseEqual, isdtime, isctime
6755
from .margins import stability_margins, phase_crossover_frequencies
6856
from .mateqn import lyap, dlyap, care, dare
69-
from .modelsimp import hsvd, modred, balred, era, markov
57+
from .modelsimp import hsvd, modred, balred, era, markov, minreal
7058
from .nichols import nichols_plot, nichols
7159
from .phaseplot import phase_plot, box_grid
60+
from .pzmap import pzmap
7261
from .rlocus import root_locus
7362
from .statefbk import place, lqr, ctrb, obsv, gram, acker
7463
from .statesp import StateSpace

control/bdalg.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ def append(*sys):
252252
system given; if you mix state-space systems and gain matrices,
253253
make sure the gain matrices are not first.
254254
255-
Parameters.
256-
-----------
255+
Parameters
256+
----------
257257
sys1, sys2, ... sysn: StateSpace or Transferfunction
258258
LTI systems to combine
259259
@@ -290,8 +290,8 @@ def connect(sys, Q, inputv, outputv):
290290
291291
Note: to have this work, inputs and outputs start counting at 1!!!!
292292
293-
Parameters.
294-
-----------
293+
Parameters
294+
----------
295295
sys: StateSpace Transferfunction
296296
System to be connected
297297
Q: 2d array

control/canonical.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from numpy.linalg import inv
1111

1212

13-
def canonical_form(xsys, form):
13+
def canonical_form(xsys, form='reachable'):
1414
"""Convert a system into canonical form
1515
1616
Parameters
@@ -20,15 +20,15 @@ def canonical_form(xsys, form):
2020
form : String
2121
Canonical form for transformation. Chosen from:
2222
* 'reachable' - reachable canonical form
23-
* 'observable' - observable canonical form
23+
* 'observable' - observable canonical form [not implemented]
2424
* 'modal' - modal canonical form [not implemented]
2525
26-
Outputs
26+
Returns
2727
-------
2828
zsys : StateSpace object
2929
System in desired canonical form, with state 'z'
3030
T : matrix
31-
Coordinate transformation matrix, z = T*x
31+
Coordinate transformation matrix, z = T * x
3232
"""
3333

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

4242
# Reachable canonical form
4343
def reachable_form(xsys):
44+
"""Convert a system into reachable canonical form
45+
46+
Parameters
47+
----------
48+
xsys : StateSpace object
49+
System to be transformed, with state `x`
50+
51+
Returns
52+
-------
53+
zsys : StateSpace object
54+
System in reachable canonical form, with state `z`
55+
T : matrix
56+
Coordinate transformation: z = T * x
57+
"""
4458
# Check to make sure we have a SISO system
4559
if not issiso(xsys):
4660
raise ControlNotImplemented(

control/ctrlutil.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def unwrap(angle, period=2*pi):
7979

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

8484
def db2mag(db):
8585
"""Convert a gain in decibels (dB) to a magnitude

control/frdata.py

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -78,20 +78,17 @@
7878
from numpy import angle, array, empty, ones, \
7979
real, imag, matrix, absolute, eye, linalg, where, dot
8080
from scipy.interpolate import splprep, splev
81-
from .lti import Lti
81+
from .lti import LTI
8282

83-
class FRD(Lti):
84-
"""The FRD class represents (measured?) frequency response
85-
TF instances and functions.
83+
class FRD(LTI):
84+
"""A class for models defined by Frequency Response Data (FRD)
8685
87-
The FRD class is derived from the Lti parent class. It is used
88-
throughout the python-control library to represent systems in frequency
89-
response data form.
86+
The FRD class is used to represent systems in frequency response data form.
9087
91-
The main data members are 'omega' and 'fresp'. omega is a 1D
92-
array with the frequency points of the response. fresp is a 3D array,
93-
with the first dimension corresponding to the outputs of the FRD,
94-
the second dimension corresponding to the inputs, and the 3rd dimension
88+
The main data members are 'omega' and 'fresp', where `omega` is a 1D
89+
array with the frequency points of the response, and `fresp` is a 3D array,
90+
with the first dimension corresponding to the output index of the FRD,
91+
the second dimension corresponding to the input index, and the 3rd dimension
9592
corresponding to the frequency points in omega.
9693
For example,
9794
@@ -107,7 +104,7 @@ class FRD(Lti):
107104
epsw = 1e-8
108105

109106
def __init__(self, *args, **kwargs):
110-
"""Construct a transfer function.
107+
"""Construct an FRD object
111108
112109
The default constructor is FRD(d, w), where w is an iterable of
113110
frequency points, and d is the matching frequency data.
@@ -118,16 +115,14 @@ def __init__(self, *args, **kwargs):
118115
To call the copy constructor, call FRD(sys), where sys is a
119116
FRD object.
120117
121-
To construct frequency response data for an existing Lti
118+
To construct frequency response data for an existing LTI
122119
object, other than an FRD, call FRD(sys, omega)
123120
124-
125-
126121
"""
127122
smooth = kwargs.get('smooth', False)
128123

129124
if len(args) == 2:
130-
if not isinstance(args[0], FRD) and isinstance(args[0], Lti):
125+
if not isinstance(args[0], FRD) and isinstance(args[0], LTI):
131126
# not an FRD, but still a system, second argument should be
132127
# the frequency range
133128
otherlti = args[0]
@@ -179,7 +174,7 @@ def __init__(self, *args, **kwargs):
179174
w=1.0/(absolute(self.fresp[i, j, :])+0.001), s=0.0)
180175
else:
181176
self.ifunc = None
182-
Lti.__init__(self, self.fresp.shape[1], self.fresp.shape[0])
177+
LTI.__init__(self, self.fresp.shape[1], self.fresp.shape[0])
183178

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

462-
elif isinstance(sys, Lti):
457+
elif isinstance(sys, LTI):
463458
omega.sort()
464459
fresp = empty((sys.outputs, sys.inputs, len(omega)), dtype=complex)
465460
for k, w in enumerate(omega):

control/freqplot.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ def nyquist_plot(syslist, omega=None, Plot=True, color='b',
184184
185185
Parameters
186186
----------
187-
syslist : list of Lti
187+
syslist : list of LTI
188188
List of linear input/output systems (single system is OK)
189189
omega : freq_range
190190
Range of frequencies (list or bounds) in rad/sec
@@ -281,7 +281,7 @@ def gangof4_plot(P, C, omega=None):
281281
282282
Parameters
283283
----------
284-
P, C : Lti
284+
P, C : LTI
285285
Linear input/output systems (process and control)
286286
omega : array
287287
Range of frequencies (list or bounds) in rad/sec
@@ -344,7 +344,7 @@ def default_frequency_range(syslist):
344344
345345
Parameters
346346
----------
347-
syslist : list of Lti
347+
syslist : list of LTI
348348
List of linear input/output systems (single system is OK)
349349
350350
Returns

control/lti.py

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
"""lti.py
22
3-
The Lti module contains the Lti parent class to the child classes StateSpace
3+
The lti module contains the LTI parent class to the child classes StateSpace
44
and TransferFunction. It is designed for use in the python-control library.
55
66
Routines in this module:
77
8-
Lti.__init__
8+
LTI.__init__
99
isdtime()
1010
isctime()
1111
timebase()
@@ -14,10 +14,10 @@
1414

1515
from numpy import absolute, real
1616

17-
class Lti:
18-
"""Lti is a parent class to linear time invariant control (LTI) objects.
17+
class LTI:
18+
"""LTI is a parent class to linear time-invariant (LTI) system objects.
1919
20-
Lti is the parent to the StateSpace and TransferFunction child
20+
LTI is the parent to the StateSpace and TransferFunction child
2121
classes. It contains the number of inputs and outputs, and the
2222
timebase (dt) for the system.
2323
@@ -30,32 +30,10 @@ class Lti:
3030
* dt > 0 Discrete time system with sampling time dt
3131
* dt = True Discrete time system with unspecified sampling time
3232
33-
When to Lti systems are combined, there timebases much match. A system
33+
When two LTI systems are combined, their timebases much match. A system
3434
with timebase None can be combined with a system having a specified
3535
timebase, and the result will have the timebase of the latter system.
3636
37-
The StateSpace and TransferFunction child classes contain several common
38-
"virtual" functions. These are:
39-
40-
__init__
41-
copy
42-
__str__
43-
__neg__
44-
__add__
45-
__radd__
46-
__sub__
47-
__rsub__
48-
__mul__
49-
__rmul__
50-
__div__
51-
__rdiv__
52-
evalfr
53-
freqresp
54-
pole
55-
zero
56-
feedback
57-
returnScipySignalLti
58-
5937
"""
6038

6139
def __init__(self, inputs=1, outputs=1, dt=None):
@@ -112,25 +90,25 @@ def damp(self):
11290
def issiso(sys, strict=False):
11391
if isinstance(sys, (int, float, complex)) and not strict:
11492
return True
115-
elif not isinstance(sys, Lti):
116-
raise ValueError("Object is not an Lti system")
93+
elif not isinstance(sys, LTI):
94+
raise ValueError("Object is not an LTI system")
11795

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

12199
# Return the timebase (with conversion if unspecified)
122100
def timebase(sys, strict=True):
123-
"""Return the timebase for an Lti system
101+
"""Return the timebase for an LTI system
124102
125103
dt = timebase(sys)
126104
127105
returns the timebase for a system 'sys'. If the strict option is
128106
set to False, dt = True will be returned as 1.
129107
"""
130-
# System needs to be either a constant or an Lti system
108+
# System needs to be either a constant or an LTI system
131109
if isinstance(sys, (int, float, complex)):
132110
return None
133-
elif not isinstance(sys, Lti):
111+
elif not isinstance(sys, LTI):
134112
raise ValueError("Timebase not defined")
135113

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

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

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

208186
# Check for a transfer function or state space object
209-
if isinstance(sys, Lti):
187+
if isinstance(sys, LTI):
210188
return sys.isctime(strict)
211189

212190
# Got passed something we don't recognize

control/margins.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def _polysqr(pol):
7474

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

0 commit comments

Comments
 (0)