Skip to content

Commit 5800513

Browse files
authored
Merge 0b3ae85 into bfdfbd5
2 parents bfdfbd5 + 0b3ae85 commit 5800513

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+2233
-2490
lines changed

control/__init__.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,32 +68,35 @@
6868

6969
# Import functions from within the control system library
7070
# Note: the functions we use are specified as __all__ variables in the modules
71+
72+
# Input/output system modules
73+
from .iosys import *
74+
from .nlsys import *
75+
from .lti import *
76+
from .statesp import *
77+
from .xferfcn import *
78+
from .frdata import *
79+
7180
from .bdalg import *
7281
from .delay import *
7382
from .descfcn import *
7483
from .dtime import *
7584
from .freqplot import *
76-
from .lti import *
7785
from .margins import *
7886
from .mateqn import *
7987
from .modelsimp import *
80-
from .iosys import *
8188
from .nichols import *
8289
from .phaseplot import *
8390
from .pzmap import *
8491
from .rlocus import *
8592
from .statefbk import *
86-
from .statesp import *
8793
from .stochsys import *
8894
from .timeresp import *
89-
from .xferfcn import *
9095
from .ctrlutil import *
91-
from .frdata import *
9296
from .canonical import *
9397
from .robust import *
9498
from .config import *
9599
from .sisotool import *
96-
from .nlsys import *
97100
from .passivity import *
98101

99102
# Exceptions

control/bdalg.py

Lines changed: 85 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,13 @@
5353
5454
"""
5555

56+
from functools import reduce
5657
import numpy as np
58+
from warnings import warn
5759
from . import xferfcn as tf
5860
from . import statesp as ss
5961
from . import frdata as frd
62+
from .iosys import InputOutputSystem
6063

6164
__all__ = ['series', 'parallel', 'negate', 'feedback', 'append', 'connect']
6265

@@ -68,12 +71,13 @@ def series(sys1, *sysn):
6871
6972
Parameters
7073
----------
71-
sys1 : scalar, StateSpace, TransferFunction, or FRD
72-
*sysn : other scalars, StateSpaces, TransferFunctions, or FRDs
74+
sys1, sys2, ..., sysn: scalar, array, or :class:`InputOutputSystem`
75+
I/O systems to combine.
7376
7477
Returns
7578
-------
76-
out : scalar, StateSpace, or TransferFunction
79+
out : scalar, array, or :class:`InputOutputSystem`
80+
Series interconnection of the systems.
7781
7882
Raises
7983
------
@@ -83,14 +87,15 @@ def series(sys1, *sysn):
8387
8488
See Also
8589
--------
86-
parallel
87-
feedback
90+
append, feedback, interconnect, negate, parallel
8891
8992
Notes
9093
-----
91-
This function is a wrapper for the __mul__ function in the StateSpace and
92-
TransferFunction classes. The output type is usually the type of `sys2`.
93-
If `sys2` is a scalar, then the output type is the type of `sys1`.
94+
This function is a wrapper for the __mul__ function in the appropriate
95+
:class:`NonlinearIOSystem`, :class:`StateSpace`,
96+
:class:`TransferFunction`, or other I/O system class. The output type
97+
is the type of `sys1` unless a more general type is required based on
98+
type type of `sys2`.
9499
95100
If both systems have a defined timebase (dt = 0 for continuous time,
96101
dt > 0 for discrete time), then the timebase for both systems must
@@ -112,8 +117,7 @@ def series(sys1, *sysn):
112117
(2, 1, 5)
113118
114119
"""
115-
from functools import reduce
116-
return reduce(lambda x, y:y*x, sysn, sys1)
120+
return reduce(lambda x, y: y * x, sysn, sys1)
117121

118122

119123
def parallel(sys1, *sysn):
@@ -123,12 +127,13 @@ def parallel(sys1, *sysn):
123127
124128
Parameters
125129
----------
126-
sys1 : scalar, StateSpace, TransferFunction, or FRD
127-
*sysn : other scalars, StateSpaces, TransferFunctions, or FRDs
130+
sys1, sys2, ..., sysn: scalar, array, or :class:`InputOutputSystem`
131+
I/O systems to combine.
128132
129133
Returns
130134
-------
131-
out : scalar, StateSpace, or TransferFunction
135+
out : scalar, array, or :class:`InputOutputSystem`
136+
Parallel interconnection of the systems.
132137
133138
Raises
134139
------
@@ -137,8 +142,7 @@ def parallel(sys1, *sysn):
137142
138143
See Also
139144
--------
140-
series
141-
feedback
145+
append, feedback, interconnect, negate, series
142146
143147
Notes
144148
-----
@@ -167,8 +171,7 @@ def parallel(sys1, *sysn):
167171
(3, 4, 7)
168172
169173
"""
170-
from functools import reduce
171-
return reduce(lambda x, y:x+y, sysn, sys1)
174+
return reduce(lambda x, y: x + y, sysn, sys1)
172175

173176

174177
def negate(sys):
@@ -177,17 +180,23 @@ def negate(sys):
177180
178181
Parameters
179182
----------
180-
sys : StateSpace, TransferFunction or FRD
183+
sys: scalar, array, or :class:`InputOutputSystem`
184+
I/O systems to negate.
181185
182186
Returns
183187
-------
184-
out : StateSpace or TransferFunction
188+
out : scalar, array, or :class:`InputOutputSystem`
189+
Negated system.
185190
186191
Notes
187192
-----
188193
This function is a wrapper for the __neg__ function in the StateSpace and
189194
TransferFunction classes. The output type is the same as the input type.
190195
196+
See Also
197+
--------
198+
append, feedback, interconnect, parallel, series
199+
191200
Examples
192201
--------
193202
>>> G = ct.tf([2], [1, 1])
@@ -202,24 +211,23 @@ def negate(sys):
202211
return -sys
203212

204213
#! TODO: expand to allow sys2 default to work in MIMO case?
214+
#! TODO: allow renaming of signals (for all bdalg operations)
205215
def feedback(sys1, sys2=1, sign=-1):
206-
"""
207-
Feedback interconnection between two I/O systems.
216+
"""Feedback interconnection between two I/O systems.
208217
209218
Parameters
210219
----------
211-
sys1 : scalar, StateSpace, TransferFunction, FRD
212-
The primary process.
213-
sys2 : scalar, StateSpace, TransferFunction, FRD
214-
The feedback process (often a feedback controller).
220+
sys1, sys2: scalar, array, or :class:`InputOutputSystem`
221+
I/O systems to combine.
215222
sign: scalar
216223
The sign of feedback. `sign` = -1 indicates negative feedback, and
217224
`sign` = 1 indicates positive feedback. `sign` is an optional
218225
argument; it assumes a value of -1 if not specified.
219226
220227
Returns
221228
-------
222-
out : StateSpace or TransferFunction
229+
out : scalar, array, or :class:`InputOutputSystem`
230+
Feedback interconnection of the systems.
223231
224232
Raises
225233
------
@@ -232,17 +240,14 @@ def feedback(sys1, sys2=1, sign=-1):
232240
233241
See Also
234242
--------
235-
series
236-
parallel
243+
append, interconnect, negate, parallel, series
237244
238245
Notes
239246
-----
240-
This function is a wrapper for the feedback function in the StateSpace and
241-
TransferFunction classes. It calls TransferFunction.feedback if `sys1` is a
242-
TransferFunction object, and StateSpace.feedback if `sys1` is a StateSpace
243-
object. If `sys1` is a scalar, then it is converted to `sys2`'s type, and
244-
the corresponding feedback function is used. If `sys1` and `sys2` are both
245-
scalars, then TransferFunction.feedback is used.
247+
This function is a wrapper for the `feedback` function in the I/O
248+
system classes. It calls sys1.feedback if `sys1` is an I/O system
249+
object. If `sys1` is a scalar, then it is converted to `sys2`'s type,
250+
and the corresponding feedback function is used.
246251
247252
Examples
248253
--------
@@ -254,57 +259,55 @@ def feedback(sys1, sys2=1, sign=-1):
254259
255260
"""
256261
# Allow anything with a feedback function to call that function
262+
# TODO: rewrite to allow __rfeedback__
257263
try:
258264
return sys1.feedback(sys2, sign)
259-
except AttributeError:
265+
except (AttributeError, TypeError):
260266
pass
261267

262-
# Check for correct input types.
263-
if not isinstance(sys1, (int, float, complex, np.number,
264-
tf.TransferFunction, ss.StateSpace, frd.FRD)):
265-
raise TypeError("sys1 must be a TransferFunction, StateSpace " +
266-
"or FRD object, or a scalar.")
267-
if not isinstance(sys2, (int, float, complex, np.number,
268-
tf.TransferFunction, ss.StateSpace, frd.FRD)):
269-
raise TypeError("sys2 must be a TransferFunction, StateSpace " +
270-
"or FRD object, or a scalar.")
271-
272-
# If sys1 is a scalar, convert it to the appropriate LTI type so that we can
273-
# its feedback member function.
274-
if isinstance(sys1, (int, float, complex, np.number)):
275-
if isinstance(sys2, tf.TransferFunction):
268+
# Check for correct input types
269+
if not isinstance(sys1, (int, float, complex, np.number, np.ndarray,
270+
InputOutputSystem)):
271+
raise TypeError("sys1 must be an I/O system, scalar, or array")
272+
elif not isinstance(sys2, (int, float, complex, np.number, np.ndarray,
273+
InputOutputSystem)):
274+
raise TypeError("sys2 must be an I/O system, scalar, or array")
275+
276+
# If sys1 is a scalar or ndarray, use the type of sys2 to figure
277+
# out how to convert sys1, using transfer functions whenever possible.
278+
if isinstance(sys1, (int, float, complex, np.number, np.ndarray)):
279+
if isinstance(sys2, (int, float, complex, np.number, np.ndarray,
280+
tf.TransferFunction)):
276281
sys1 = tf._convert_to_transfer_function(sys1)
277-
elif isinstance(sys2, ss.StateSpace):
278-
sys1 = ss._convert_to_statespace(sys1)
279282
elif isinstance(sys2, frd.FRD):
280283
sys1 = frd._convert_to_FRD(sys1, sys2.omega)
281-
else: # sys2 is a scalar.
282-
sys1 = tf._convert_to_transfer_function(sys1)
283-
sys2 = tf._convert_to_transfer_function(sys2)
284+
else:
285+
sys1 = ss._convert_to_statespace(sys1)
284286

285287
return sys1.feedback(sys2, sign)
286288

287289
def append(*sys):
288290
"""append(sys1, sys2, [..., sysn])
289291
290-
Group models by appending their inputs and outputs.
292+
Group LTI state space models by appending their inputs and outputs.
291293
292294
Forms an augmented system model, and appends the inputs and
293-
outputs together. The system type will be the type of the first
294-
system given; if you mix state-space systems and gain matrices,
295-
make sure the gain matrices are not first.
295+
outputs together.
296296
297297
Parameters
298298
----------
299-
sys1, sys2, ..., sysn: StateSpace or TransferFunction
300-
LTI systems to combine
301-
299+
sys1, sys2, ..., sysn: scalar, array, or :class:`StateSpace`
300+
I/O systems to combine.
302301
303302
Returns
304303
-------
305-
sys: LTI system
306-
Combined LTI system, with input/output vectors consisting of all
307-
input/output vectors appended
304+
out: :class:`StateSpace`
305+
Combined system, with input/output vectors consisting of all
306+
input/output vectors appended.
307+
308+
See Also
309+
--------
310+
interconnect, feedback, negate, parallel, series
308311
309312
Examples
310313
--------
@@ -329,6 +332,10 @@ def append(*sys):
329332
def connect(sys, Q, inputv, outputv):
330333
"""Index-based interconnection of an LTI system.
331334
335+
.. deprecated:: 0.10.0
336+
`connect` will be removed in a future version of python-control in
337+
favor of `interconnect`, which works with named signals.
338+
332339
The system `sys` is a system typically constructed with `append`, with
333340
multiple inputs and outputs. The inputs and outputs are connected
334341
according to the interconnection matrix `Q`, and then the final inputs and
@@ -340,8 +347,8 @@ def connect(sys, Q, inputv, outputv):
340347
341348
Parameters
342349
----------
343-
sys : StateSpace or TransferFunction
344-
System to be connected
350+
sys : :class:`InputOutputSystem`
351+
System to be connected.
345352
Q : 2D array
346353
Interconnection matrix. First column gives the input to be connected.
347354
The second column gives the index of an output that is to be fed into
@@ -356,8 +363,12 @@ def connect(sys, Q, inputv, outputv):
356363
357364
Returns
358365
-------
359-
sys: LTI system
360-
Connected and trimmed LTI system
366+
out : :class:`InputOutputSystem`
367+
Connected and trimmed I/O system.
368+
369+
See Also
370+
--------
371+
append, feedback, interconnect, negate, parallel, series
361372
362373
Examples
363374
--------
@@ -369,12 +380,14 @@ def connect(sys, Q, inputv, outputv):
369380
370381
Notes
371382
-----
372-
The :func:`~control.interconnect` function in the
373-
:ref:`input/output systems <iosys-module>` module allows the use
374-
of named signals and provides an alternative method for
375-
interconnecting multiple systems.
383+
The :func:`~control.interconnect` function in the :ref:`input/output
384+
systems <iosys-module>` module allows the use of named signals and
385+
provides an alternative method for interconnecting multiple systems.
376386
377387
"""
388+
# TODO: maintain `connect` for use in MATLAB submodule (?)
389+
warn("`connect` is deprecated; use `interconnect`", DeprecationWarning)
390+
378391
inputv, outputv, Q = \
379392
np.atleast_1d(inputv), np.atleast_1d(outputv), np.atleast_1d(Q)
380393
# check indices

control/config.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,18 +123,15 @@ def reset_defaults():
123123
from .sisotool import _sisotool_defaults
124124
defaults.update(_sisotool_defaults)
125125

126-
from .iosys import _namedio_defaults
127-
defaults.update(_namedio_defaults)
126+
from .iosys import _iosys_defaults
127+
defaults.update(_iosys_defaults)
128128

129129
from .xferfcn import _xferfcn_defaults
130130
defaults.update(_xferfcn_defaults)
131131

132132
from .statesp import _statesp_defaults
133133
defaults.update(_statesp_defaults)
134134

135-
from .nlsys import _iosys_defaults
136-
defaults.update(_iosys_defaults)
137-
138135
from .optimal import _optimal_defaults
139136
defaults.update(_optimal_defaults)
140137

@@ -300,7 +297,7 @@ def use_legacy_defaults(version):
300297
set_defaults('control', default_dt=None)
301298

302299
# changed iosys naming conventions
303-
set_defaults('namedio', state_name_delim='.',
300+
set_defaults('iosys', state_name_delim='.',
304301
duplicate_system_name_prefix='copy of ',
305302
duplicate_system_name_suffix='',
306303
linearized_system_name_prefix='',

0 commit comments

Comments
 (0)