38
38
39
39
from .statesp import StateSpace , tf2ss
40
40
from .timeresp import _check_convert_array
41
- from .lti import isctime , isdtime , _find_timebase
41
+ from .lti import isctime , isdtime , common_timebase
42
+ from . import config
42
43
43
44
__all__ = ['InputOutputSystem' , 'LinearIOSystem' , 'NonlinearIOSystem' ,
44
45
'InterconnectedSystem' , 'input_output_response' , 'find_eqpt' ,
45
46
'linearize' , 'ss2io' , 'tf2io' ]
46
47
48
+ # Define module default parameter values
49
+ _iosys_defaults = {}
47
50
48
51
class InputOutputSystem (object ):
49
52
"""A class for representing input/output systems.
@@ -69,9 +72,11 @@ class for a set of subclasses that are used to implement specific
69
72
states : int, list of str, or None
70
73
Description of the system states. Same format as `inputs`.
71
74
dt : None, True or float, optional
72
- System timebase. None (default) indicates continuous time, True
73
- indicates discrete time with undefined sampling time, positive number
74
- is discrete time with specified sampling time.
75
+ System timebase. 0 (default) indicates continuous
76
+ time, True indicates discrete time with unspecified sampling
77
+ time, positive number is discrete time with specified
78
+ sampling time, None indicates unspecified timebase (either
79
+ continuous or discrete time).
75
80
params : dict, optional
76
81
Parameter values for the systems. Passed to the evaluation functions
77
82
for the system as default values, overriding internal defaults.
@@ -87,9 +92,11 @@ class for a set of subclasses that are used to implement specific
87
92
Dictionary of signal names for the inputs, outputs and states and the
88
93
index of the corresponding array
89
94
dt : None, True or float
90
- System timebase. None (default) indicates continuous time, True
91
- indicates discrete time with undefined sampling time, positive number
92
- is discrete time with specified sampling time.
95
+ System timebase. 0 (default) indicates continuous
96
+ time, True indicates discrete time with unspecified sampling
97
+ time, positive number is discrete time with specified
98
+ sampling time, None indicates unspecified timebase (either
99
+ continuous or discrete time).
93
100
params : dict, optional
94
101
Parameter values for the systems. Passed to the evaluation functions
95
102
for the system as default values, overriding internal defaults.
@@ -118,7 +125,7 @@ def name_or_default(self, name=None):
118
125
return name
119
126
120
127
def __init__ (self , inputs = None , outputs = None , states = None , params = {},
121
- dt = None , name = None ):
128
+ name = None , ** kwargs ):
122
129
"""Create an input/output system.
123
130
124
131
The InputOutputSystem contructor is used to create an input/output
@@ -143,10 +150,11 @@ def __init__(self, inputs=None, outputs=None, states=None, params={},
143
150
states : int, list of str, or None
144
151
Description of the system states. Same format as `inputs`.
145
152
dt : None, True or float, optional
146
- System timebase. None (default) indicates continuous
147
- time, True indicates discrete time with undefined sampling
153
+ System timebase. 0 (default) indicates continuous
154
+ time, True indicates discrete time with unspecified sampling
148
155
time, positive number is discrete time with specified
149
- sampling time.
156
+ sampling time, None indicates unspecified timebase (either
157
+ continuous or discrete time).
150
158
params : dict, optional
151
159
Parameter values for the systems. Passed to the evaluation
152
160
functions for the system as default values, overriding internal
@@ -162,9 +170,13 @@ def __init__(self, inputs=None, outputs=None, states=None, params={},
162
170
163
171
"""
164
172
# Store the input arguments
165
- self .params = params .copy () # default parameters
166
- self .dt = dt # timebase
167
- self .name = self .name_or_default (name ) # system name
173
+
174
+ # default parameters
175
+ self .params = params .copy ()
176
+ # timebase
177
+ self .dt = kwargs .get ('dt' , config .defaults ['control.default_dt' ])
178
+ # system name
179
+ self .name = self .name_or_default (name )
168
180
169
181
# Parse and store the number of inputs, outputs, and states
170
182
self .set_inputs (inputs )
@@ -210,9 +222,7 @@ def __mul__(sys2, sys1):
210
222
"inputs and outputs" )
211
223
212
224
# Make sure timebase are compatible
213
- dt = _find_timebase (sys1 , sys2 )
214
- if dt is False :
215
- raise ValueError ("System timebases are not compabile" )
225
+ dt = common_timebase (sys1 .dt , sys2 .dt )
216
226
217
227
inplist = [(0 ,i ) for i in range (sys1 .ninputs )]
218
228
outlist = [(1 ,i ) for i in range (sys2 .noutputs )]
@@ -464,12 +474,11 @@ def feedback(self, other=1, sign=-1, params={}):
464
474
"inputs and outputs" )
465
475
466
476
# Make sure timebases are compatible
467
- dt = _find_timebase (self , other )
468
- if dt is False :
469
- raise ValueError ("System timebases are not compabile" )
477
+ dt = common_timebase (self .dt , other .dt )
470
478
471
479
inplist = [(0 ,i ) for i in range (self .ninputs )]
472
480
outlist = [(0 ,i ) for i in range (self .noutputs )]
481
+
473
482
# Return the series interconnection between the systems
474
483
newsys = InterconnectedSystem ((self , other ), inplist = inplist , outlist = outlist ,
475
484
params = params , dt = dt )
@@ -580,10 +589,11 @@ def __init__(self, linsys, inputs=None, outputs=None, states=None,
580
589
states : int, list of str, or None, optional
581
590
Description of the system states. Same format as `inputs`.
582
591
dt : None, True or float, optional
583
- System timebase. None (default) indicates continuous
584
- time, True indicates discrete time with undefined sampling
592
+ System timebase. 0 (default) indicates continuous
593
+ time, True indicates discrete time with unspecified sampling
585
594
time, positive number is discrete time with specified
586
- sampling time.
595
+ sampling time, None indicates unspecified timebase (either
596
+ continuous or discrete time).
587
597
params : dict, optional
588
598
Parameter values for the systems. Passed to the evaluation
589
599
functions for the system as default values, overriding internal
@@ -650,7 +660,8 @@ class NonlinearIOSystem(InputOutputSystem):
650
660
651
661
"""
652
662
def __init__ (self , updfcn , outfcn = None , inputs = None , outputs = None ,
653
- states = None , params = {}, dt = None , name = None ):
663
+ states = None , params = {},
664
+ name = None , ** kwargs ):
654
665
"""Create a nonlinear I/O system given update and output functions.
655
666
656
667
Creates an `InputOutputSystem` for a nonlinear system by specifying a
@@ -702,10 +713,10 @@ def __init__(self, updfcn, outfcn=None, inputs=None, outputs=None,
702
713
operating in continuous or discrete time. It can have the
703
714
following values:
704
715
705
- * dt = None No timebase specified
706
- * dt = 0 Continuous time system
707
- * dt > 0 Discrete time system with sampling time dt
708
- * dt = True Discrete time with unspecified sampling time
716
+ * dt = 0: continuous time system (default)
717
+ * dt > 0: discrete time system with sampling period 'dt'
718
+ * dt = True: discrete time with unspecified sampling period
719
+ * dt = None: no timebase specified
709
720
710
721
name : string, optional
711
722
System name (used for specifying signals). If unspecified, a generic
@@ -722,6 +733,7 @@ def __init__(self, updfcn, outfcn=None, inputs=None, outputs=None,
722
733
self .outfcn = outfcn
723
734
724
735
# Initialize the rest of the structure
736
+ dt = kwargs .get ('dt' , config .defaults ['control.default_dt' ])
725
737
super (NonlinearIOSystem , self ).__init__ (
726
738
inputs = inputs , outputs = outputs , states = states ,
727
739
params = params , dt = dt , name = name
@@ -871,10 +883,10 @@ def __init__(self, syslist, connections=[], inplist=[], outlist=[],
871
883
operating in continuous or discrete time. It can have the
872
884
following values:
873
885
874
- * dt = None No timebase specified
875
- * dt = 0 Continuous time system
876
- * dt > 0 Discrete time system with sampling time dt
877
- * dt = True Discrete time with unspecified sampling time
886
+ * dt = 0: continuous time system (default)
887
+ * dt > 0: discrete time system with sampling period 'dt'
888
+ * dt = True: discrete time with unspecified sampling period
889
+ * dt = None: no timebase specified
878
890
879
891
name : string, optional
880
892
System name (used for specifying signals). If unspecified, a generic
@@ -888,20 +900,14 @@ def __init__(self, syslist, connections=[], inplist=[], outlist=[],
888
900
# Check to make sure all systems are consistent
889
901
self .syslist = syslist
890
902
self .syslist_index = {}
891
- dt = None
892
903
nstates = 0 ; self .state_offset = []
893
904
ninputs = 0 ; self .input_offset = []
894
905
noutputs = 0 ; self .output_offset = []
895
906
sysobj_name_dct = {}
896
907
sysname_count_dct = {}
897
908
for sysidx , sys in enumerate (syslist ):
898
909
# Make sure time bases are consistent
899
- # TODO: Use lti._find_timebase() instead?
900
- if dt is None and sys .dt is not None :
901
- # Timebase was not specified; set to match this system
902
- dt = sys .dt
903
- elif dt != sys .dt :
904
- raise TypeError ("System timebases are not compatible" )
910
+ dt = common_timebase (dt , sys .dt )
905
911
906
912
# Make sure number of inputs, outputs, states is given
907
913
if sys .ninputs is None or sys .noutputs is None or \
0 commit comments