Skip to content

Commit d267fa2

Browse files
authored
initial release of I/O systems module (#301)
This PR introduces a new module for representing (nonlinear) input/output systems and support for simulation, linearization, and composition. The following features are supported: * Input/output systems can be created using the LinearIOSystem and NonlinearIOSystem classes, and I/O systems can be simulated in continuous and discrete time using the input_output_response() function, which is equivalent to the forced_response() function for LTI system. * Input/output systems can be composed using the existing series, parallel, and feedback functions, as well as using the * and + operators. In addition, the InterconnectedSystem class can be used to interconnect a collection of I/O subsystems, with functionality similar to the connect function in MATLAB. * Input/output systems and input/output signals can be named and Interconnections between I/O systems can be specified using system and signal names. * Input/output systems can be linearized about an equilibrium point using the linearize() function, which returns a LinearIOSystem object. The LinearIOSystem is derived from the StateSpace class, allowing all operations on linear systems to be applied to the linearized system. The find_eqpt() function can be used to find an equilibrium point for an input/output system. Documentation and examples are included to illustrate the use of the iosys module.
1 parent cda33a2 commit d267fa2

File tree

12 files changed

+3537
-13
lines changed

12 files changed

+3537
-13
lines changed

control/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
from .robust import *
6969
from .config import *
7070
from .sisotool import *
71+
from .iosys import *
7172

7273
# Exceptions
7374
from .exception import *

control/bdalg.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ def feedback(sys1, sys2=1, sign=-1):
224224
scalars, then TransferFunction.feedback is used.
225225
226226
"""
227+
# Allow anything with a feedback function to call that function
228+
try:
229+
return sys1.feedback(sys2, sign)
230+
except AttributeError:
231+
pass
227232

228233
# Check for correct input types.
229234
if not isinstance(sys1, (int, float, complex, np.number,

control/iosys.py

Lines changed: 1795 additions & 0 deletions
Large diffs are not rendered by default.

control/lti.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,28 @@ def timebaseEqual(sys1, sys2):
178178
else:
179179
return sys1.dt == sys2.dt
180180

181+
# Find a common timebase between two or more systems
182+
def _find_timebase(sys1, *sysn):
183+
"""Find the common timebase between systems, otherwise return False"""
184+
185+
# Create a list of systems to check
186+
syslist = [sys1]
187+
syslist.append(*sysn)
188+
189+
# Look for a common timebase
190+
dt = None
191+
192+
for sys in syslist:
193+
# Make sure time bases are consistent
194+
if (dt is None and sys.dt is not None) or \
195+
(dt is True and isdiscrete(sys)):
196+
# Timebase was not specified; set to match this system
197+
dt = sys.dt
198+
elif dt != sys.dt:
199+
return False
200+
return dt
201+
202+
181203
# Check to see if a system is a discrete time system
182204
def isdtime(sys, strict=False):
183205
"""
@@ -200,6 +222,15 @@ def isdtime(sys, strict=False):
200222
if isinstance(sys, LTI):
201223
return sys.isdtime(strict)
202224

225+
# Check to see if object has a dt object
226+
if hasattr(sys, 'dt'):
227+
# If no timebase is given, answer depends on strict flag
228+
if sys.dt == None:
229+
return True if not strict else False
230+
231+
# Look for dt > 0 (also works if dt = True)
232+
return sys.dt > 0
233+
203234
# Got passed something we don't recognize
204235
return False
205236

@@ -225,6 +256,13 @@ def isctime(sys, strict=False):
225256
if isinstance(sys, LTI):
226257
return sys.isctime(strict)
227258

259+
# Check to see if object has a dt object
260+
if hasattr(sys, 'dt'):
261+
# If no timebase is given, answer depends on strict flag
262+
if sys.dt is None:
263+
return True if not strict else False
264+
return sys.dt == 0
265+
228266
# Got passed something we don't recognize
229267
return False
230268

control/statesp.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class StateSpace(LTI):
115115
sampling time.
116116
"""
117117

118-
def __init__(self, *args):
118+
def __init__(self, *args, **kw):
119119
"""
120120
StateSpace(A, B, C, D[, dt])
121121
@@ -152,6 +152,9 @@ def __init__(self, *args):
152152
else:
153153
raise ValueError("Needs 1 or 4 arguments; received %i." % len(args))
154154

155+
# Process keyword arguments
156+
remove_useless = kw.get('remove_useless', True)
157+
155158
A, B, C, D = [_matrix(M) for M in (A, B, C, D)]
156159

157160
# TODO: use super here?
@@ -183,7 +186,7 @@ def __init__(self, *args):
183186
raise ValueError("C and D must have the same number of rows.")
184187

185188
# Check for states that don't do anything, and remove them.
186-
self._remove_useless_states()
189+
if remove_useless: self._remove_useless_states()
187190

188191
def _remove_useless_states(self):
189192
"""Check for states that don't do anything, and remove them.

0 commit comments

Comments
 (0)