Skip to content

Commit 31f6574

Browse files
committed
updated documentation, examples, unit tests
1 parent 4afda82 commit 31f6574

16 files changed

Lines changed: 270 additions & 430 deletions

control/nlsys.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -706,13 +706,18 @@ def __init__(self, syslist, connections=None, inplist=None, outlist=None,
706706
if outputs is None and outlist is not None:
707707
outputs = len(outlist)
708708

709-
# Create the I/O system
710-
# Note: don't use super() to override LinearICSystem/StateSpace MRO
711-
InputOutputSystem.__init__(
712-
self, inputs=inputs, outputs=outputs,
713-
states=states, dt=dt, name=name, **kwargs)
714-
# TODO: this should get initialized above
715-
self.params = {} if params is None else params.copy()
709+
# Create updfcn and outfcn
710+
def updfcn(t, x, u, params):
711+
self.update_params(params)
712+
return self._rhs(t, x, u)
713+
def outfcn(t, x, u, params):
714+
self.update_params(params)
715+
return self._out(t, x, u)
716+
717+
# Initialize NonlinearIOSystem object
718+
super().__init__(
719+
updfcn, outfcn, inputs=inputs, outputs=outputs,
720+
states=states, dt=dt, name=name, params=params, **kwargs)
716721

717722
# Convert the list of interconnections to a connection map (matrix)
718723
self.connect_map = np.zeros((ninputs, noutputs))

control/statesp.py

Lines changed: 0 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -2428,166 +2428,3 @@ def _mimo2simo(sys, input, warn_conversion=False):
24282428
inputs=sys.input_labels[input], outputs=sys.output_labels)
24292429

24302430
return sys
2431-
2432-
2433-
def tf2ss(*args, **kwargs):
2434-
"""tf2ss(sys)
2435-
2436-
Transform a transfer function to a state space system.
2437-
2438-
The function accepts either 1 or 2 parameters:
2439-
2440-
``tf2ss(sys)``
2441-
Convert a linear system into space space form. Always creates
2442-
a new system, even if sys is already a StateSpace object.
2443-
2444-
``tf2ss(num, den)``
2445-
Create a state space system from its numerator and denominator
2446-
polynomial coefficients.
2447-
2448-
For details see: :func:`tf`
2449-
2450-
Parameters
2451-
----------
2452-
sys : LTI (StateSpace or TransferFunction)
2453-
A linear system
2454-
num : array_like, or list of list of array_like
2455-
Polynomial coefficients of the numerator
2456-
den : array_like, or list of list of array_like
2457-
Polynomial coefficients of the denominator
2458-
2459-
Returns
2460-
-------
2461-
out : StateSpace
2462-
New linear system in state space form
2463-
2464-
Other Parameters
2465-
----------------
2466-
inputs, outputs : str, or list of str, optional
2467-
List of strings that name the individual signals of the transformed
2468-
system. If not given, the inputs and outputs are the same as the
2469-
original system.
2470-
name : string, optional
2471-
System name. If unspecified, a generic name <sys[id]> is generated
2472-
with a unique integer id.
2473-
2474-
Raises
2475-
------
2476-
ValueError
2477-
if `num` and `den` have invalid or unequal dimensions, or if an
2478-
invalid number of arguments is passed in
2479-
TypeError
2480-
if `num` or `den` are of incorrect type, or if sys is not a
2481-
TransferFunction object
2482-
2483-
See Also
2484-
--------
2485-
ss
2486-
tf
2487-
ss2tf
2488-
2489-
Examples
2490-
--------
2491-
>>> num = [[[1., 2.], [3., 4.]], [[5., 6.], [7., 8.]]]
2492-
>>> den = [[[9., 8., 7.], [6., 5., 4.]], [[3., 2., 1.], [-1., -2., -3.]]]
2493-
>>> sys1 = ct.tf2ss(num, den)
2494-
2495-
>>> sys_tf = ct.tf(num, den)
2496-
>>> sys2 = ct.tf2ss(sys_tf)
2497-
2498-
"""
2499-
2500-
from .xferfcn import TransferFunction
2501-
if len(args) == 2 or len(args) == 3:
2502-
# Assume we were given the num, den
2503-
return StateSpace(
2504-
_convert_to_statespace(TransferFunction(*args)), **kwargs)
2505-
2506-
elif len(args) == 1:
2507-
sys = args[0]
2508-
if not isinstance(sys, TransferFunction):
2509-
raise TypeError("tf2ss(sys): sys must be a TransferFunction "
2510-
"object.")
2511-
return StateSpace(
2512-
_convert_to_statespace(
2513-
sys,
2514-
use_prefix_suffix=not sys._generic_name_check()),
2515-
**kwargs)
2516-
else:
2517-
raise ValueError("Needs 1 or 2 arguments; received %i." % len(args))
2518-
2519-
2520-
def ssdata(sys):
2521-
"""
2522-
Return state space data objects for a system
2523-
2524-
Parameters
2525-
----------
2526-
sys : LTI (StateSpace, or TransferFunction)
2527-
LTI system whose data will be returned
2528-
2529-
Returns
2530-
-------
2531-
(A, B, C, D): list of matrices
2532-
State space data for the system
2533-
"""
2534-
ss = _convert_to_statespace(sys)
2535-
return ss.A, ss.B, ss.C, ss.D
2536-
2537-
2538-
def linfnorm(sys, tol=1e-10):
2539-
"""L-infinity norm of a linear system
2540-
2541-
Parameters
2542-
----------
2543-
sys : LTI (StateSpace or TransferFunction)
2544-
system to evalute L-infinity norm of
2545-
tol : real scalar
2546-
tolerance on norm estimate
2547-
2548-
Returns
2549-
-------
2550-
gpeak : non-negative scalar
2551-
L-infinity norm
2552-
fpeak : non-negative scalar
2553-
Frequency, in rad/s, at which gpeak occurs
2554-
2555-
For stable systems, the L-infinity and H-infinity norms are equal;
2556-
for unstable systems, the H-infinity norm is infinite, while the
2557-
L-infinity norm is finite if the system has no poles on the
2558-
imaginary axis.
2559-
2560-
See also
2561-
--------
2562-
slycot.ab13dd : the Slycot routine linfnorm that does the calculation
2563-
"""
2564-
2565-
if ab13dd is None:
2566-
raise ControlSlycot("Can't find slycot module 'ab13dd'")
2567-
2568-
a, b, c, d = ssdata(_convert_to_statespace(sys))
2569-
e = np.eye(a.shape[0])
2570-
2571-
n = a.shape[0]
2572-
m = b.shape[1]
2573-
p = c.shape[0]
2574-
2575-
if n == 0:
2576-
# ab13dd doesn't accept empty A, B, C, D;
2577-
# static gain case is easy enough to compute
2578-
gpeak = scipy.linalg.svdvals(d)[0]
2579-
# max svd is constant with freq; arbitrarily choose 0 as peak
2580-
fpeak = 0
2581-
return gpeak, fpeak
2582-
2583-
dico = 'C' if sys.isctime() else 'D'
2584-
jobe = 'I'
2585-
equil = 'S'
2586-
jobd = 'Z' if all(0 == d.flat) else 'D'
2587-
2588-
gpeak, fpeak = ab13dd(dico, jobe, equil, jobd, n, m, p, a, e, b, c, d, tol)
2589-
2590-
if dico=='D':
2591-
fpeak /= sys.dt
2592-
2593-
return gpeak, fpeak

control/tests/interconnect_test.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ def test_interconnect_docstring():
195195
T_ss = ct.ss(ct.feedback(P * C, 1))
196196

197197
# Test in a manner that recognizes that recognizes non-unique realization
198-
np.testing.assert_almost_equal(T.A, T_ss.A)
198+
np.testing.assert_almost_equal(
199+
np.sort(np.linalg.eig(T.A)[0]), np.sort(np.linalg.eig(T_ss.A)[0]))
199200
np.testing.assert_almost_equal(T.C @ T.B, T_ss.C @ T_ss.B)
200201
np.testing.assert_almost_equal(T.C @ T. A @ T.B, T_ss.C @ T_ss.A @ T_ss.B)
201202
np.testing.assert_almost_equal(T.D, T_ss.D)

doc/classes.fig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ Single
2222
2 1 0 2 1 7 50 -1 -1 0.000 0 0 7 0 1 2
2323
1 0 1.00 60.00 90.00
2424
7200 2850 8250 3150
25-
2 1 0 2 1 7 50 -1 -1 0.000 0 0 7 0 1 2
26-
1 0 1.00 60.00 90.00
27-
6525 2025 7050 2550
2825
2 1 0 2 1 7 50 -1 -1 0.000 0 0 7 0 1 2
2926
1 0 1.00 60.00 90.00
3027
7050 2850 7725 3450
@@ -37,12 +34,15 @@ Single
3734
2 1 0 2 1 7 50 -1 -1 0.000 0 0 -1 0 1 2
3835
1 0 1.00 60.00 90.00
3936
4350 2850 3450 3150
37+
2 1 0 2 1 7 50 -1 -1 0.000 0 0 7 0 1 2
38+
1 0 1.00 60.00 90.00
39+
6525 1950 7050 2550
4040
4 1 1 50 -1 16 12 0.0000 4 210 2115 4050 3675 InterconnectedSystem\001
4141
4 1 1 50 -1 16 12 0.0000 4 165 1605 7950 3675 TransferFunction\001
4242
4 1 1 50 -1 0 12 0.0000 4 150 345 7050 2775 LTI\001
4343
4 1 1 50 -1 16 12 0.0000 4 210 1830 5175 2775 NonlinearIOSystem\001
4444
4 1 1 50 -1 16 12 0.0000 4 210 1095 6150 3675 StateSpace\001
45-
4 1 1 50 -1 16 12 0.0000 4 210 1770 6300 1800 InputOutputSystem\001
4645
4 1 1 50 -1 16 12 0.0000 4 210 1500 5175 4575 LinearICSystem\001
4746
4 2 1 50 -1 16 12 0.0000 4 210 1035 3375 3225 FlatSystem\001
4847
4 0 1 50 -1 16 12 0.0000 4 165 420 8400 3225 FRD\001
48+
4 1 1 50 -1 16 12 0.0000 4 210 1770 6300 1875 InputOutputSystem\001

doc/classes.pdf

1 Byte
Binary file not shown.

doc/classes.rst

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ user should normally not need to instantiate these directly.
1414
:toctree: generated/
1515
:template: custom-class-template.rst
1616

17+
InputOutputSystem
1718
StateSpace
1819
TransferFunction
19-
InputOutputSystem
2020
FrequencyResponseData
21-
TimeResponseData
21+
NonlinearIOSystem
22+
InterconnectedSystem
23+
LinearICSystem
2224

2325
The following figure illustrates the relationship between the classes and
2426
some of the functions that can be used to convert objects from one class to
@@ -27,23 +29,6 @@ another:
2729
.. image:: classes.pdf
2830
:width: 800
2931

30-
|
31-
32-
Input/output system subclasses
33-
==============================
34-
Input/output systems are accessed primarily via a set of subclasses
35-
that allow for linear, nonlinear, and interconnected elements:
36-
37-
.. autosummary::
38-
:template: custom-class-template.rst
39-
:nosignatures:
40-
41-
InputOutputSystem
42-
InterconnectedSystem
43-
LinearICSystem
44-
LinearIOSystem
45-
NonlinearIOSystem
46-
4732
Additional classes
4833
==================
4934
.. autosummary::

doc/control.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ Time domain simulation
7070
impulse_response
7171
initial_response
7272
input_output_response
73-
step_response
7473
phase_plot
74+
step_response
75+
TimeResponseData
76+
7577

7678
Control system analysis
7779
=======================
@@ -147,9 +149,7 @@ Nonlinear system support
147149
find_eqpt
148150
linearize
149151
input_output_response
150-
ss2io
151152
summing_junction
152-
tf2io
153153
flatsys.point_to_point
154154

155155
Stochastic system support

doc/iosys.rst

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,6 @@ Module classes and functions
465465
~control.InputOutputSystem
466466
~control.InterconnectedSystem
467467
~control.LinearICSystem
468-
~control.LinearIOSystem
469468
~control.NonlinearIOSystem
470469

471470
.. autosummary::
@@ -475,6 +474,4 @@ Module classes and functions
475474
~control.linearize
476475
~control.input_output_response
477476
~control.interconnect
478-
~control.ss2io
479477
~control.summing_junction
480-
~control.tf2io

examples/cruise-control.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,8 @@ def motor_torque(omega, params={}):
131131
# Construct a PI controller with rolloff, as a transfer function
132132
Kp = 0.5 # proportional gain
133133
Ki = 0.1 # integral gain
134-
control_tf = ct.tf2io(
135-
ct.TransferFunction([Kp, Ki], [1, 0.01*Ki/Kp]),
136-
name='control', inputs='u', outputs='y')
134+
control_tf =ct.TransferFunction(
135+
[Kp, Ki], [1, 0.01*Ki/Kp], name='control', inputs='u', outputs='y')
137136

138137
# Construct the closed loop control system
139138
# Inputs: vref, gear, theta

examples/cruise.ipynb

Lines changed: 72 additions & 61 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)