Skip to content

Commit 86ebb1c

Browse files
committed
Merge pull request #41 from python-control/improve-docs
Improve docs
2 parents 770c4d7 + 4f6165a commit 86ebb1c

18 files changed

Lines changed: 270 additions & 133 deletions

.coveragerc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[run]
2+
source = control
3+
omit = control/tests/*
4+
5+
[report]
6+
exclude_lines =
7+
# Don't complain if tests don't hit defensive assertion code:
8+
raise AssertionError
9+
raise NotImplementedError
10+
11+
# Don't complain if non-runnable code isn't run:
12+
if 0:
13+
if __name__ == .__main__.:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ control/version.py
77
build.log
88
*.egg-info/
99
.coverage
10+
doc/_build

.travis.yml

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,36 @@
11
language: python
22
python:
33
- "2.7"
4-
- "3.2"
54
- "3.3"
5+
- "3.4"
6+
67
# install required system libraries
78
before_install:
89
- export DISPLAY=:99.0
910
- sh -e /etc/init.d/xvfb start
1011
- sudo apt-get update --fix-missing -qq
11-
- sudo apt-get build-dep python-scipy -qq
12-
# command to install dependencies from source
13-
# note, separating requirements so that travis
14-
# will get output in less than 5 min and won't
15-
# terminate, using q to keep build info to a
16-
# minumum for dependencies
12+
- sudo apt-get install gfortran liblapack-dev
13+
# use miniconda to install numpy/scipy, to avoid lengthy build from source
14+
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
15+
wget http://repo.continuum.io/miniconda/Miniconda-3.4.2-Linux-x86_64.sh -O miniconda.sh;
16+
else
17+
wget http://repo.continuum.io/miniconda/Miniconda3-3.4.2-Linux-x86_64.sh -O miniconda.sh;
18+
fi
19+
- bash miniconda.sh -b -p $HOME/miniconda
20+
- export PATH="$HOME/miniconda/bin:$PATH"
21+
- hash -r
22+
- conda config --set always_yes yes --set changeps1 no
23+
- conda update -q conda
24+
- conda info -a
25+
26+
# Install packages
1727
install:
18-
- while [[ 1 ]]; do echo "building deps"; sleep 300; done &
19-
- msg_pid=$!
20-
- pip install -q coverage
21-
- pip install -q coveralls
22-
- pip install -q nose
23-
- pip install -q numpy
24-
- pip install -q scipy
25-
- pip install -q slycot
26-
- pip install -q matplotlib
27-
- kill $msg_pid
28+
- conda install --yes python=$TRAVIS_PYTHON_VERSION coverage nose numpy scipy matplotlib pip
29+
- pip install coveralls
30+
- pip install slycot
2831

2932
# command to run tests
3033
script:
31-
- coverage run --source=control setup.py test
34+
- coverage run setup.py test
3235
after_success:
3336
- coveralls

control/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@
9393
# Exceptions
9494
from .exception import *
9595

96+
# Version information
97+
from control.version import full_version as __version__
98+
from control.version import git_revision as __git_revision__
99+
96100
# Import some of the more common (and benign) MATLAB shortcuts
97101
# By default, don't import conflicting commands here
98102
#! TODO (RMM, 4 Nov 2012): remove MATLAB dependencies from __init__.py

control/ctrlutil.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,10 @@
4141
# $Id$
4242

4343
# Packages that we need access to
44-
import scipy as sp
4544
from . import lti
4645

4746
# Specific functions that we use
48-
from scipy import pi
47+
from numpy import pi
4948

5049
# Utility function to unwrap an angle measurement
5150

control/freqplot.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def bode_plot(syslist, omega=None, dB=None, Hz=None, deg=None,
121121
#TODO: Add MIMO bode plots.
122122
raise NotImplementedError("Bode is currently only implemented for SISO systems.")
123123
else:
124-
if (omega == None):
124+
if omega is None:
125125
# Select a default range if none is provided
126126
omega = default_frequency_range(syslist)
127127

@@ -214,7 +214,7 @@ def nyquist_plot(syslist, omega=None, Plot=True, color='b',
214214
syslist = (syslist,)
215215

216216
# Select a default range if none is provided
217-
if (omega == None):
217+
if omega is None:
218218
#! TODO: think about doing something smarter for discrete
219219
omega = default_frequency_range(syslist)
220220

@@ -297,7 +297,7 @@ def gangof4_plot(P, C, omega=None):
297297

298298
# Select a default range if none is provided
299299
#! TODO: This needs to be made more intelligent
300-
if (omega == None):
300+
if omega is None:
301301
omega = default_frequency_range((P,C))
302302

303303
# Compute the senstivity functions

control/mateqn.py

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,21 @@
5151
def lyap(A,Q,C=None,E=None):
5252
""" X = lyap(A,Q) solves the continuous-time Lyapunov equation
5353
54-
A X + X A^T + Q = 0
54+
:math:`A X + X A^T + Q = 0`
5555
5656
where A and Q are square matrices of the same dimension.
5757
Further, Q must be symmetric.
5858
5959
X = lyap(A,Q,C) solves the Sylvester equation
6060
61-
A X + X Q + C = 0
61+
:math:`A X + X Q + C = 0`
6262
6363
where A and Q are square matrices.
6464
6565
X = lyap(A,Q,None,E) solves the generalized continuous-time
6666
Lyapunov equation
6767
68-
A X E^T + E X A^T + Q = 0
68+
:math:`A X E^T + E X A^T + Q = 0`
6969
7070
where Q is a symmetric matrix and A, Q and E are square matrices
7171
of the same dimension. """
@@ -88,10 +88,10 @@ def lyap(A,Q,C=None,E=None):
8888
if len(shape(Q)) == 1:
8989
Q = Q.reshape(1,Q.size)
9090

91-
if C != None and len(shape(C)) == 1:
91+
if C is not None and len(shape(C)) == 1:
9292
C = C.reshape(1,C.size)
9393

94-
if E != None and len(shape(E)) == 1:
94+
if E is not None and len(shape(E)) == 1:
9595
E = E.reshape(1,E.size)
9696

9797
# Determine main dimensions
@@ -106,7 +106,7 @@ def lyap(A,Q,C=None,E=None):
106106
m = size(Q,0)
107107

108108
# Solve standard Lyapunov equation
109-
if C==None and E==None:
109+
if C is None and E is None:
110110
# Check input data for consistency
111111
if shape(A) != shape(Q):
112112
raise ControlArgument("A and Q must be matrices of identical \
@@ -139,7 +139,7 @@ def lyap(A,Q,C=None,E=None):
139139
raise e
140140

141141
# Solve the Sylvester equation
142-
elif C != None and E==None:
142+
elif C is not None and E is None:
143143
# Check input data for consistency
144144
if size(A) > 1 and shape(A)[0] != shape(A)[1]:
145145
raise ControlArgument("A must be a quadratic matrix.")
@@ -170,7 +170,7 @@ def lyap(A,Q,C=None,E=None):
170170
raise e
171171

172172
# Solve the generalized Lyapunov equation
173-
elif C == None and E != None:
173+
elif C is None and E is not None:
174174
# Check input data for consistency
175175
if (size(Q) > 1 and shape(Q)[0] != shape(Q)[1]) or \
176176
(size(Q) > 1 and shape(Q)[0] != n) or \
@@ -233,21 +233,21 @@ def lyap(A,Q,C=None,E=None):
233233
def dlyap(A,Q,C=None,E=None):
234234
""" dlyap(A,Q) solves the discrete-time Lyapunov equation
235235
236-
A X A^T - X + Q = 0
236+
:math:`A X A^T - X + Q = 0`
237237
238238
where A and Q are square matrices of the same dimension. Further
239239
Q must be symmetric.
240240
241241
dlyap(A,Q,C) solves the Sylvester equation
242242
243-
A X Q^T - X + C = 0
243+
:math:`A X Q^T - X + C = 0`
244244
245245
where A and Q are square matrices.
246246
247247
dlyap(A,Q,None,E) solves the generalized discrete-time Lyapunov
248248
equation
249249
250-
A X A^T - E X E^T + Q = 0
250+
:math:`A X A^T - E X E^T + Q = 0`
251251
252252
where Q is a symmetric matrix and A, Q and E are square matrices
253253
of the same dimension. """
@@ -275,10 +275,10 @@ def dlyap(A,Q,C=None,E=None):
275275
if len(shape(Q)) == 1:
276276
Q = Q.reshape(1,Q.size)
277277

278-
if C != None and len(shape(C)) == 1:
278+
if C is not None and len(shape(C)) == 1:
279279
C = C.reshape(1,C.size)
280280

281-
if E != None and len(shape(E)) == 1:
281+
if E is not None and len(shape(E)) == 1:
282282
E = E.reshape(1,E.size)
283283

284284
# Determine main dimensions
@@ -293,7 +293,7 @@ def dlyap(A,Q,C=None,E=None):
293293
m = size(Q,0)
294294

295295
# Solve standard Lyapunov equation
296-
if C==None and E==None:
296+
if C is None and E is None:
297297
# Check input data for consistency
298298
if shape(A) != shape(Q):
299299
raise ControlArgument("A and Q must be matrices of identical \
@@ -322,7 +322,7 @@ def dlyap(A,Q,C=None,E=None):
322322
raise e
323323

324324
# Solve the Sylvester equation
325-
elif C != None and E==None:
325+
elif C is not None and E is None:
326326
# Check input data for consistency
327327
if size(A) > 1 and shape(A)[0] != shape(A)[1]:
328328
raise ControlArgument("A must be a quadratic matrix")
@@ -353,7 +353,7 @@ def dlyap(A,Q,C=None,E=None):
353353
raise e
354354

355355
# Solve the generalized Lyapunov equation
356-
elif C == None and E != None:
356+
elif C is None and E is not None:
357357
# Check input data for consistency
358358
if (size(Q) > 1 and shape(Q)[0] != shape(Q)[1]) or \
359359
(size(Q) > 1 and shape(Q)[0] != n) or \
@@ -414,7 +414,7 @@ def care(A,B,Q,R=None,S=None,E=None):
414414
""" (X,L,G) = care(A,B,Q,R=None) solves the continuous-time algebraic Riccati
415415
equation
416416
417-
A^T X + X A - X B R^-1 B^T X + Q = 0
417+
:math:`A^T X + X A - X B R^{-1} B^T X + Q = 0`
418418
419419
where A and Q are square matrices of the same dimension. Further,
420420
Q and R are a symmetric matrices. If R is None, it is set to the
@@ -425,7 +425,7 @@ def care(A,B,Q,R=None,S=None,E=None):
425425
(X,L,G) = care(A,B,Q,R,S,E) solves the generalized continuous-time
426426
algebraic Riccati equation
427427
428-
A^T X E + E^T X A - (E^T X B + S) R^-1 (B^T X E + S^T) + Q = 0
428+
:math:`A^T X E + E^T X A - (E^T X B + S) R^{-1} (B^T X E + S^T) + Q = 0`
429429
430430
where A, Q and E are square matrices of the same
431431
dimension. Further, Q and R are symmetric matrices. If R is None,
@@ -460,13 +460,13 @@ def care(A,B,Q,R=None,S=None,E=None):
460460
if len(shape(Q)) == 1:
461461
Q = Q.reshape(1,Q.size)
462462

463-
if R != None and len(shape(R)) == 1:
463+
if R is not None and len(shape(R)) == 1:
464464
R = R.reshape(1,R.size)
465465

466-
if S != None and len(shape(S)) == 1:
466+
if S is not None and len(shape(S)) == 1:
467467
S = S.reshape(1,S.size)
468468

469-
if E != None and len(shape(E)) == 1:
469+
if E is not None and len(shape(E)) == 1:
470470
E = E.reshape(1,E.size)
471471

472472
# Determine main dimensions
@@ -479,11 +479,11 @@ def care(A,B,Q,R=None,S=None,E=None):
479479
m = 1
480480
else:
481481
m = size(B,1)
482-
if R==None:
482+
if R is None:
483483
R = eye(m,m)
484484

485485
# Solve the standard algebraic Riccati equation
486-
if S==None and E==None:
486+
if S is None and E is None:
487487
# Check input data for consistency
488488
if size(A) > 1 and shape(A)[0] != shape(A)[1]:
489489
raise ControlArgument("A must be a quadratic matrix.")
@@ -564,7 +564,7 @@ def care(A,B,Q,R=None,S=None,E=None):
564564
return (X , w[:n] , G )
565565

566566
# Solve the generalized algebraic Riccati equation
567-
elif S != None and E != None:
567+
elif S is not None and E is not None:
568568
# Check input data for consistency
569569
if size(A) > 1 and shape(A)[0] != shape(A)[1]:
570570
raise ControlArgument("A must be a quadratic matrix.")
@@ -674,7 +674,7 @@ def dare(A,B,Q,R,S=None,E=None):
674674
""" (X,L,G) = dare(A,B,Q,R) solves the discrete-time algebraic Riccati
675675
equation
676676
677-
A^T X A - X - A^T X B (B^T X B + R)^-1 B^T X A + Q = 0
677+
:math:`A^T X A - X - A^T X B (B^T X B + R)^{-1} B^T X A + Q = 0`
678678
679679
where A and Q are square matrices of the same dimension. Further, Q
680680
is a symmetric matrix. The function returns the solution X, the gain
@@ -684,12 +684,11 @@ def dare(A,B,Q,R,S=None,E=None):
684684
(X,L,G) = dare(A,B,Q,R,S,E) solves the generalized discrete-time algebraic
685685
Riccati equation
686686
687-
A^T X A - E^T X E - (A^T X B + S) (B^T X B + R)^-1 (B^T X A + S^T) +
688-
+ Q = 0
687+
:math:`A^T X A - E^T X E - (A^T X B + S) (B^T X B + R)^{-1} (B^T X A + S^T) + Q = 0`
689688
690689
where A, Q and E are square matrices of the same dimension. Further, Q and
691690
R are symmetric matrices. The function returns the solution X, the gain
692-
matrix G = (B^T X B + R)^-1 (B^T X A + S^T) and the closed loop
691+
matrix :math:`G = (B^T X B + R)^{-1} (B^T X A + S^T)` and the closed loop
693692
eigenvalues L, i.e., the eigenvalues of A - B G , E.
694693
"""
695694
if S is not None or E is not None:
@@ -730,13 +729,13 @@ def dare_old(A,B,Q,R,S=None,E=None):
730729
if len(shape(Q)) == 1:
731730
Q = Q.reshape(1,Q.size)
732731

733-
if R != None and len(shape(R)) == 1:
732+
if R is not None and len(shape(R)) == 1:
734733
R = R.reshape(1,R.size)
735734

736-
if S != None and len(shape(S)) == 1:
735+
if S is not None and len(shape(S)) == 1:
737736
S = S.reshape(1,S.size)
738737

739-
if E != None and len(shape(E)) == 1:
738+
if E is not None and len(shape(E)) == 1:
740739
E = E.reshape(1,E.size)
741740

742741
# Determine main dimensions
@@ -751,7 +750,7 @@ def dare_old(A,B,Q,R,S=None,E=None):
751750
m = size(B,1)
752751

753752
# Solve the standard algebraic Riccati equation
754-
if S==None and E==None:
753+
if S is None and E is None:
755754
# Check input data for consistency
756755
if size(A) > 1 and shape(A)[0] != shape(A)[1]:
757756
raise ControlArgument("A must be a quadratic matrix.")
@@ -835,7 +834,7 @@ def dare_old(A,B,Q,R,S=None,E=None):
835834
return (X , w[:n] , G)
836835

837836
# Solve the generalized algebraic Riccati equation
838-
elif S != None and E != None:
837+
elif S is not None and E is not None:
839838
# Check input data for consistency
840839
if size(A) > 1 and shape(A)[0] != shape(A)[1]:
841840
raise ControlArgument("A must be a quadratic matrix.")

0 commit comments

Comments
 (0)