Skip to content

Commit 4f04f48

Browse files
committed
updated sphinx documentation + changed to LinearICSystem
1 parent ff4a351 commit 4f04f48

File tree

7 files changed

+99
-91
lines changed

7 files changed

+99
-91
lines changed

control/bdalg.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,13 @@ def connect(sys, Q, inputv, outputv):
326326
>>> Q = [[1, 2], [2, -1]] # negative feedback interconnection
327327
>>> sysc = connect(sys, Q, [2], [1, 2])
328328
329+
Notes
330+
-----
331+
The :func:`~control.interconnect` function in the
332+
:ref:`input/output systems <iosys-module>` module allows the use
333+
of named signals and provides an alternative method for
334+
interconnecting multiple systems.
335+
329336
"""
330337
inputv, outputv, Q = np.asarray(inputv), np.asarray(outputv), np.asarray(Q)
331338
# check indices

control/iosys.py

Lines changed: 50 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
from . import config
4343

4444
__all__ = ['InputOutputSystem', 'LinearIOSystem', 'NonlinearIOSystem',
45-
'InterconnectedSystem', 'input_output_response', 'find_eqpt',
46-
'linearize', 'ss2io', 'tf2io', 'interconnect']
45+
'InterconnectedSystem', 'LinearICSystem', 'input_output_response',
46+
'find_eqpt', 'linearize', 'ss2io', 'tf2io', 'interconnect']
4747

4848
# Define module default parameter values
4949
_iosys_defaults = {
@@ -110,8 +110,8 @@ class for a set of subclasses that are used to implement specific
110110
111111
Notes
112112
-----
113-
The `InputOuputSystem` class (and its subclasses) makes use of two special
114-
methods for implementing much of the work of the class:
113+
The :class:`~control.InputOuputSystem` class (and its subclasses) makes
114+
use of two special methods for implementing much of the work of the class:
115115
116116
* _rhs(t, x, u): compute the right hand side of the differential or
117117
difference equation for the system. This must be specified by the
@@ -137,8 +137,8 @@ def __init__(self, inputs=None, outputs=None, states=None, params={},
137137
The InputOutputSystem contructor is used to create an input/output
138138
object with the core information required for all input/output
139139
systems. Instances of this class are normally created by one of the
140-
input/output subclasses: :class:`~control.LinearIOSystem`,
141-
:class:`~control.NonlinearIOSystem`,
140+
input/output subclasses: :class:`~control.LinearICSystem`,
141+
:class:`~control.LinearIOSystem`, :class:`~control.NonlinearIOSystem`,
142142
:class:`~control.InterconnectedSystem`.
143143
144144
Parameters
@@ -242,10 +242,10 @@ def __mul__(sys2, sys1):
242242
np.zeros((sys2.ninputs, sys2.noutputs))]]
243243
))
244244

245-
# If both systems are linear, create LinearInterconnectedSystem
245+
# If both systems are linear, create LinearICSystem
246246
if isinstance(sys1, StateSpace) and isinstance(sys2, StateSpace):
247247
ss_sys = StateSpace.__mul__(sys2, sys1)
248-
return LinearInterconnectedSystem(newsys, ss_sys)
248+
return LinearICSystem(newsys, ss_sys)
249249

250250
# Return the newly created InterconnectedSystem
251251
return newsys
@@ -294,10 +294,10 @@ def __add__(sys1, sys2):
294294
newsys = InterconnectedSystem(
295295
(sys1, sys2), inplist=inplist, outlist=outlist)
296296

297-
# If both systems are linear, create LinearInterconnectedSystem
297+
# If both systems are linear, create LinearICSystem
298298
if isinstance(sys1, StateSpace) and isinstance(sys2, StateSpace):
299299
ss_sys = StateSpace.__add__(sys2, sys1)
300-
return LinearInterconnectedSystem(newsys, ss_sys)
300+
return LinearICSystem(newsys, ss_sys)
301301

302302
# Return the newly created InterconnectedSystem
303303
return newsys
@@ -315,10 +315,10 @@ def __neg__(sys):
315315
newsys = InterconnectedSystem(
316316
(sys,), dt=sys.dt, inplist=inplist, outlist=outlist)
317317

318-
# If the system is linear, create LinearInterconnectedSystem
318+
# If the system is linear, create LinearICSystem
319319
if isinstance(sys, StateSpace):
320320
ss_sys = StateSpace.__neg__(sys)
321-
return LinearInterconnectedSystem(newsys, ss_sys)
321+
return LinearICSystem(newsys, ss_sys)
322322

323323
# Return the newly created system
324324
return newsys
@@ -502,7 +502,7 @@ def feedback(self, other=1, sign=-1, params={}):
502502
if isinstance(self, StateSpace) and isinstance(other, StateSpace):
503503
# Special case: maintain linear systems structure
504504
ss_sys = StateSpace.feedback(self, other, sign=sign)
505-
return LinearInterconnectedSystem(newsys, ss_sys)
505+
return LinearICSystem(newsys, ss_sys)
506506

507507
# Return the newly created system
508508
return newsys
@@ -697,10 +697,10 @@ def __init__(self, updfcn, outfcn=None, inputs=None, outputs=None,
697697
name=None, **kwargs):
698698
"""Create a nonlinear I/O system given update and output functions.
699699
700-
Creates an `InputOutputSystem` for a nonlinear system by specifying a
701-
state update function and an output function. The new system can be a
702-
continuous or discrete time system (Note: discrete-time systems not
703-
yet supported by most function.)
700+
Creates an :class:`~control.InputOutputSystem` for a nonlinear system
701+
by specifying a state update function and an output function. The new
702+
system can be a continuous or discrete time system (Note:
703+
discrete-time systems not yet supported by most function.)
704704
705705
Parameters
706706
----------
@@ -1284,15 +1284,16 @@ def set_output_map(self, output_map):
12841284
self.noutputs = output_map.shape[0]
12851285

12861286

1287-
class LinearInterconnectedSystem(InterconnectedSystem, LinearIOSystem):
1287+
class LinearICSystem(InterconnectedSystem, LinearIOSystem):
12881288
"""Interconnection of a set of linear input/output systems.
12891289
12901290
This class is used to implement a system that is an interconnection of
12911291
linear input/output systems. It has all of the structure of an
1292-
:class:`InterconnectedSystem`, but also maintains the requirement elements
1293-
of :class:`LinearIOSystem`, including the :class:`StateSpace` class
1294-
structure, allowing it to be passed to functions that expect a
1295-
:class:`StateSpace` system.
1292+
:class:`~control.InterconnectedSystem`, but also maintains the requirement
1293+
elements of :class:`~control.LinearIOSystem`, including the
1294+
:class:`StateSpace` class structure, allowing it to be passed to functions
1295+
that expect a :class:`StateSpace` system.
1296+
12961297
"""
12971298

12981299
def __init__(self, io_sys, ss_sys=None):
@@ -1755,7 +1756,7 @@ def linearize(sys, xeq, ueq=[], t=0, params={}, **kw):
17551756
"""Linearize an input/output system at a given state and input.
17561757
17571758
This function computes the linearization of an input/output system at a
1758-
given state and input value and returns a :class:`control.StateSpace`
1759+
given state and input value and returns a :class:`~control.StateSpace`
17591760
object. The eavaluation point need not be an equilibrium point.
17601761
17611762
Parameters
@@ -1840,10 +1841,11 @@ def interconnect(syslist, connections=[], inplist=[], outlist=[],
18401841
18411842
This function creates a new system that is an interconnection of a set of
18421843
input/output systems. If all of the input systems are linear I/O systems
1843-
(type `LinearIOSystem`) then the resulting system will be a linear
1844-
interconnected I/O system (type `LinearInterconnectedSystem`) with the
1845-
appropriate inputs, outputs, and states. Otherwise, an interconnected I/O
1846-
system (type `InterconnectedSystem`) will be created.
1844+
(type :class:`~control.LinearIOSystem`) then the resulting system will be
1845+
a linear interconnected I/O system (type :class:`~control.LinearICSystem`)
1846+
with the appropriate inputs, outputs, and states. Otherwise, an
1847+
interconnected I/O system (type :class:`~control.InterconnectedSystem`)
1848+
will be created.
18471849
18481850
Parameters
18491851
----------
@@ -1895,8 +1897,8 @@ def interconnect(syslist, connections=[], inplist=[], outlist=[],
18951897
the system input connects to only one subsystem input, a single input
18961898
specification can be given (without the inner list).
18971899
1898-
If omitted, the input map can be specified using the `set_input_map`
1899-
method.
1900+
If omitted, the input map can be specified using the
1901+
:func:`~control.InterconnectedSystem.set_input_map` method.
19001902
19011903
outlist : list of output connections, optional
19021904
List of connections for how the outputs from the subsystems are mapped
@@ -1910,8 +1912,8 @@ def interconnect(syslist, connections=[], inplist=[], outlist=[],
19101912
then those signals are added together (multiplying by the any gain
19111913
term) to form the system output.
19121914
1913-
If omitted, the output map can be specified using the `set_output_map`
1914-
method.
1915+
If omitted, the output map can be specified using the
1916+
:func:`~control.InterconnectedSystem.set_output_map` method.
19151917
19161918
inputs : int, list of str or None, optional
19171919
Description of the system inputs. This can be given as an integer
@@ -1951,17 +1953,17 @@ def interconnect(syslist, connections=[], inplist=[], outlist=[],
19511953
19521954
Example
19531955
-------
1954-
P = control.LinearIOSystem(
1955-
ct.rss(2, 2, 2, strictly_proper=True), name='P')
1956-
C = control.LinearIOSystem(control.rss(2, 2, 2), name='C')
1957-
S = control.InterconnectedSystem(
1958-
[P, C],
1959-
connections = [
1960-
['P.u[0]', 'C.y[0]'], ['P.u[1]', 'C.y[0]'],
1961-
['C.u[0]', '-P.y[0]'], ['C.u[1]', '-P.y[1]']],
1962-
inplist = ['C.u[0]', 'C.u[1]'],
1963-
outlist = ['P.y[0]', 'P.y[1]'],
1964-
)
1956+
>>> P = control.LinearIOSystem(
1957+
>>> ct.rss(2, 2, 2, strictly_proper=True), name='P')
1958+
>>> C = control.LinearIOSystem(control.rss(2, 2, 2), name='C')
1959+
>>> S = control.InterconnectedSystem(
1960+
>>> [P, C],
1961+
>>> connections = [
1962+
>>> ['P.u[0]', 'C.y[0]'], ['P.u[1]', 'C.y[0]'],
1963+
>>> ['C.u[0]', '-P.y[0]'], ['C.u[1]', '-P.y[1]']],
1964+
>>> inplist = ['C.u[0]', 'C.u[1]'],
1965+
>>> outlist = ['P.y[0]', 'P.y[1]'],
1966+
>>> )
19651967
19661968
Notes
19671969
-----
@@ -1973,10 +1975,11 @@ def interconnect(syslist, connections=[], inplist=[], outlist=[],
19731975
check your use of tuples.
19741976
19751977
In addition to its use for general nonlinear I/O systems, the
1976-
`interconnect` function allows linear systems to be interconnected using
1977-
named signals (compared with the `connect` function, which uses signal
1978-
indicies) and to be treated as both a `StateSpace` system as well as an
1979-
`InputOutputSystem`.
1978+
:func:`~control.interconnect` function allows linear systems to be
1979+
interconnected using named signals (compared with the
1980+
:func:`~control.connect` function, which uses signal indicies) and to be
1981+
treated as both a :class:`~control.StateSpace` system as well as an
1982+
:class:`~control.InputOutputSystem`.
19801983
19811984
"""
19821985
newsys = InterconnectedSystem(
@@ -1986,6 +1989,6 @@ def interconnect(syslist, connections=[], inplist=[], outlist=[],
19861989

19871990
# If all subsystems are linear systems, maintain linear structure
19881991
if all([isinstance(sys, LinearIOSystem) for sys in syslist]):
1989-
return LinearInterconnectedSystem(newsys, None)
1992+
return LinearICSystem(newsys, None)
19901993

19911994
return newsys

control/tests/iosys_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,7 +1293,7 @@ def test_linear_interconnection():
12931293
['sys2.y[1]'],
12941294
['sys2.u[1]']])
12951295
assert isinstance(nl_connect, ios.InterconnectedSystem)
1296-
assert not isinstance(nl_connect, ios.LinearInterconnectedSystem)
1296+
assert not isinstance(nl_connect, ios.LinearICSystem)
12971297

12981298
# Now take its linearization
12991299
ss_connect = nl_connect.linearize(0, 0)
@@ -1313,7 +1313,7 @@ def test_linear_interconnection():
13131313
['sys2.y[1]'],
13141314
['sys2.u[1]']])
13151315
assert isinstance(io_connect, ios.InterconnectedSystem)
1316-
assert isinstance(io_connect, ios.LinearInterconnectedSystem)
1316+
assert isinstance(io_connect, ios.LinearICSystem)
13171317
assert isinstance(io_connect, ios.LinearIOSystem)
13181318
assert isinstance(io_connect, ct.StateSpace)
13191319

control/xferfcn.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ def returnScipySignalLTI(self, strict=True):
809809
continuous (0) or discrete (True or > 0).
810810
False:
811811
if `tfobject.dt` is None, continuous time
812-
:class:`scipy.signal.lti`objects are returned
812+
:class:`scipy.signal.lti` objects are returned
813813
814814
Returns
815815
-------

doc/classes.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,17 @@ these directly.
1616
TransferFunction
1717
StateSpace
1818
FrequencyResponseData
19-
~iosys.InputOutputSystem
19+
InputOutputSystem
2020

2121
Input/output system subclasses
2222
==============================
23-
.. currentmodule:: control.iosys
24-
2523
Input/output systems are accessed primarily via a set of subclasses
2624
that allow for linear, nonlinear, and interconnected elements:
2725

2826
.. autosummary::
2927
:toctree: generated/
3028

29+
InterconnectedSystem
30+
LinearICSystem
3131
LinearIOSystem
3232
NonlinearIOSystem
33-
InterconnectedSystem

doc/control.rst

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,12 @@ Nonlinear system support
139139
.. autosummary::
140140
:toctree: generated/
141141

142-
~iosys.find_eqpt
143-
~iosys.linearize
144-
~iosys.input_output_response
145-
~iosys.ss2io
146-
~iosys.tf2io
142+
find_eqpt
143+
interconnect
144+
linearize
145+
input_output_response
146+
ss2io
147+
tf2io
147148
flatsys.point_to_point
148149

149150
.. _utility-and-conversions:

doc/iosys.rst

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@
44
Input/output systems
55
********************
66

7-
.. automodule:: control.iosys
8-
:no-members:
9-
:no-inherited-members:
10-
117
Module usage
128
============
139

@@ -40,16 +36,16 @@ equation) and and output function (computes the outputs from the state)::
4036
io_sys = NonlinearIOSystem(updfcn, outfcn, inputs=M, outputs=P, states=N)
4137

4238
More complex input/output systems can be constructed by using the
43-
:class:`~control.InterconnectedSystem` class, which allows a collection of
44-
input/output subsystems to be combined with internal connections between the
45-
subsystems and a set of overall system inputs and outputs that link to the
46-
subsystems::
39+
:func:`~control.interconnect` function, which allows a collection of
40+
input/output subsystems to be combined with internal connections
41+
between the subsystems and a set of overall system inputs and outputs
42+
that link to the subsystems::
4743

48-
steering = ct.InterconnectedSystem(
49-
(plant, controller), name='system',
50-
connections=(('controller.e', '-plant.y')),
51-
inplist=('controller.e'), inputs='r',
52-
outlist=('plant.y'), outputs='y')
44+
steering = ct.interconnect(
45+
[plant, controller], name='system',
46+
connections=[['controller.e', '-plant.y']],
47+
inplist=['controller.e'], inputs='r',
48+
outlist=['plant.y'], outputs='y')
5349

5450
Interconnected systems can also be created using block diagram manipulations
5551
such as the :func:`~control.series`, :func:`~control.parallel`, and
@@ -160,19 +156,19 @@ The input to the controller is `u`, consisting of the vector of hare and lynx
160156
populations followed by the desired lynx population.
161157

162158
To connect the controller to the predatory-prey model, we create an
163-
`InterconnectedSystem`:
159+
:class:`~control.InterconnectedSystem`:
164160

165161
.. code-block:: python
166162
167-
io_closed = control.InterconnectedSystem(
168-
(io_predprey, io_controller), # systems
169-
connections=(
170-
('predprey.u', 'control.y[0]'),
171-
('control.u1', 'predprey.H'),
172-
('control.u2', 'predprey.L')
173-
),
174-
inplist=('control.Ld'),
175-
outlist=('predprey.H', 'predprey.L', 'control.y[0]')
163+
io_closed = control.interconnect(
164+
[io_predprey, io_controller], # systems
165+
connections=[
166+
['predprey.u', 'control.y[0]'],
167+
['control.u1', 'predprey.H'],
168+
['control.u2', 'predprey.L']
169+
],
170+
inplist=['control.Ld'],
171+
outlist=['predprey.H', 'predprey.L', 'control.y[0]']
176172
)
177173
178174
Finally, we simulate the closed loop system:
@@ -200,18 +196,20 @@ Input/output system classes
200196
---------------------------
201197
.. autosummary::
202198

203-
InputOutputSystem
204-
InterconnectedSystem
205-
LinearIOSystem
206-
NonlinearIOSystem
199+
~control.InputOutputSystem
200+
~control.InterconnectedSystem
201+
~control.LinearICSystem
202+
~control.LinearIOSystem
203+
~control.NonlinearIOSystem
207204

208205
Input/output system functions
209206
-----------------------------
210207
.. autosummary::
211208

212-
find_eqpt
213-
linearize
214-
input_output_response
215-
ss2io
216-
tf2io
209+
~control.find_eqpt
210+
~control.linearize
211+
~control.input_output_response
212+
~control.interconnect
213+
~control.ss2io
214+
~control.tf2io
217215

0 commit comments

Comments
 (0)