53
53
54
54
"""
55
55
56
+ from functools import reduce
56
57
import numpy as np
58
+ from warnings import warn
57
59
from . import xferfcn as tf
58
60
from . import statesp as ss
59
61
from . import frdata as frd
62
+ from .iosys import InputOutputSystem
60
63
61
64
__all__ = ['series' , 'parallel' , 'negate' , 'feedback' , 'append' , 'connect' ]
62
65
@@ -68,12 +71,13 @@ def series(sys1, *sysn):
68
71
69
72
Parameters
70
73
----------
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.
73
76
74
77
Returns
75
78
-------
76
- out : scalar, StateSpace, or TransferFunction
79
+ out : scalar, array, or :class:`InputOutputSystem`
80
+ Series interconnection of the systems.
77
81
78
82
Raises
79
83
------
@@ -83,14 +87,15 @@ def series(sys1, *sysn):
83
87
84
88
See Also
85
89
--------
86
- parallel
87
- feedback
90
+ append, feedback, interconnect, negate, parallel
88
91
89
92
Notes
90
93
-----
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`.
94
99
95
100
If both systems have a defined timebase (dt = 0 for continuous time,
96
101
dt > 0 for discrete time), then the timebase for both systems must
@@ -112,8 +117,7 @@ def series(sys1, *sysn):
112
117
(2, 1, 5)
113
118
114
119
"""
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 )
117
121
118
122
119
123
def parallel (sys1 , * sysn ):
@@ -123,12 +127,13 @@ def parallel(sys1, *sysn):
123
127
124
128
Parameters
125
129
----------
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.
128
132
129
133
Returns
130
134
-------
131
- out : scalar, StateSpace, or TransferFunction
135
+ out : scalar, array, or :class:`InputOutputSystem`
136
+ Parallel interconnection of the systems.
132
137
133
138
Raises
134
139
------
@@ -137,8 +142,7 @@ def parallel(sys1, *sysn):
137
142
138
143
See Also
139
144
--------
140
- series
141
- feedback
145
+ append, feedback, interconnect, negate, series
142
146
143
147
Notes
144
148
-----
@@ -167,8 +171,7 @@ def parallel(sys1, *sysn):
167
171
(3, 4, 7)
168
172
169
173
"""
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 )
172
175
173
176
174
177
def negate (sys ):
@@ -177,17 +180,23 @@ def negate(sys):
177
180
178
181
Parameters
179
182
----------
180
- sys : StateSpace, TransferFunction or FRD
183
+ sys: scalar, array, or :class:`InputOutputSystem`
184
+ I/O systems to negate.
181
185
182
186
Returns
183
187
-------
184
- out : StateSpace or TransferFunction
188
+ out : scalar, array, or :class:`InputOutputSystem`
189
+ Negated system.
185
190
186
191
Notes
187
192
-----
188
193
This function is a wrapper for the __neg__ function in the StateSpace and
189
194
TransferFunction classes. The output type is the same as the input type.
190
195
196
+ See Also
197
+ --------
198
+ append, feedback, interconnect, parallel, series
199
+
191
200
Examples
192
201
--------
193
202
>>> G = ct.tf([2], [1, 1])
@@ -202,24 +211,23 @@ def negate(sys):
202
211
return - sys
203
212
204
213
#! TODO: expand to allow sys2 default to work in MIMO case?
214
+ #! TODO: allow renaming of signals (for all bdalg operations)
205
215
def feedback (sys1 , sys2 = 1 , sign = - 1 ):
206
- """
207
- Feedback interconnection between two I/O systems.
216
+ """Feedback interconnection between two I/O systems.
208
217
209
218
Parameters
210
219
----------
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.
215
222
sign: scalar
216
223
The sign of feedback. `sign` = -1 indicates negative feedback, and
217
224
`sign` = 1 indicates positive feedback. `sign` is an optional
218
225
argument; it assumes a value of -1 if not specified.
219
226
220
227
Returns
221
228
-------
222
- out : StateSpace or TransferFunction
229
+ out : scalar, array, or :class:`InputOutputSystem`
230
+ Feedback interconnection of the systems.
223
231
224
232
Raises
225
233
------
@@ -232,17 +240,14 @@ def feedback(sys1, sys2=1, sign=-1):
232
240
233
241
See Also
234
242
--------
235
- series
236
- parallel
243
+ append, interconnect, negate, parallel, series
237
244
238
245
Notes
239
246
-----
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.
246
251
247
252
Examples
248
253
--------
@@ -254,57 +259,55 @@ def feedback(sys1, sys2=1, sign=-1):
254
259
255
260
"""
256
261
# Allow anything with a feedback function to call that function
262
+ # TODO: rewrite to allow __rfeedback__
257
263
try :
258
264
return sys1 .feedback (sys2 , sign )
259
- except AttributeError :
265
+ except ( AttributeError , TypeError ) :
260
266
pass
261
267
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 )):
276
281
sys1 = tf ._convert_to_transfer_function (sys1 )
277
- elif isinstance (sys2 , ss .StateSpace ):
278
- sys1 = ss ._convert_to_statespace (sys1 )
279
282
elif isinstance (sys2 , frd .FRD ):
280
283
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 )
284
286
285
287
return sys1 .feedback (sys2 , sign )
286
288
287
289
def append (* sys ):
288
290
"""append(sys1, sys2, [..., sysn])
289
291
290
- Group models by appending their inputs and outputs.
292
+ Group LTI state space models by appending their inputs and outputs.
291
293
292
294
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.
296
296
297
297
Parameters
298
298
----------
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.
302
301
303
302
Returns
304
303
-------
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
308
311
309
312
Examples
310
313
--------
@@ -329,6 +332,10 @@ def append(*sys):
329
332
def connect (sys , Q , inputv , outputv ):
330
333
"""Index-based interconnection of an LTI system.
331
334
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
+
332
339
The system `sys` is a system typically constructed with `append`, with
333
340
multiple inputs and outputs. The inputs and outputs are connected
334
341
according to the interconnection matrix `Q`, and then the final inputs and
@@ -340,8 +347,8 @@ def connect(sys, Q, inputv, outputv):
340
347
341
348
Parameters
342
349
----------
343
- sys : StateSpace or TransferFunction
344
- System to be connected
350
+ sys : :class:`InputOutputSystem`
351
+ System to be connected.
345
352
Q : 2D array
346
353
Interconnection matrix. First column gives the input to be connected.
347
354
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):
356
363
357
364
Returns
358
365
-------
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
361
372
362
373
Examples
363
374
--------
@@ -369,12 +380,14 @@ def connect(sys, Q, inputv, outputv):
369
380
370
381
Notes
371
382
-----
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.
376
386
377
387
"""
388
+ # TODO: maintain `connect` for use in MATLAB submodule (?)
389
+ warn ("`connect` is deprecated; use `interconnect`" , DeprecationWarning )
390
+
378
391
inputv , outputv , Q = \
379
392
np .atleast_1d (inputv ), np .atleast_1d (outputv ), np .atleast_1d (Q )
380
393
# check indices
0 commit comments