@@ -192,33 +192,32 @@ def __init__(self, *args, **kwargs):
192192 #
193193 # Process positional arguments
194194 #
195- # TODO: Move all of this into the ss() factory function
196- # TODO: Use standard processing order for I/O systems
195+
197196 if len (args ) == 4 :
198197 # The user provided A, B, C, and D matrices.
199- ( A , B , C , D ) = args
198+ A , B , C , D = args
200199
201200 elif len (args ) == 5 :
202201 # Discrete time system
203- ( A , B , C , D , dt ) = args
202+ A , B , C , D , dt = args
204203 if 'dt' in kwargs :
205204 warn ("received multiple dt arguments, "
206205 "using positional arg dt = %s" % dt )
207206 kwargs ['dt' ] = dt
208207 args = args [:- 1 ]
209208
210209 elif len (args ) == 1 :
211- # Use the copy constructor.
210+ # Use the copy constructor
212211 if not isinstance (args [0 ], StateSpace ):
213212 raise TypeError (
214- "The one-argument constructor can only take in a "
215- "StateSpace object. Received %s. " % type (args [0 ]))
213+ "the one-argument constructor can only take in a "
214+ "StateSpace object; received %s" % type (args [0 ]))
216215 A = args [0 ].A
217216 B = args [0 ].B
218217 C = args [0 ].C
219218 D = args [0 ].D
220- dt = args [ 0 ]. dt
221- # TODO: copy the remaining attributes
219+ if 'dt' not in kwargs :
220+ kwargs [ 'dt' ] = args [ 0 ]. dt
222221
223222 else :
224223 raise TypeError (
@@ -691,7 +690,6 @@ def __mul__(self, other):
691690
692691 # Right multiplication of two state space systems (series interconnection)
693692 # Just need to convert LH argument to a state space object
694- # TODO: __rmul__ only works for special cases (??)
695693 def __rmul__ (self , other ):
696694 """Right multiply two LTI objects (serial connection)."""
697695 from .xferfcn import TransferFunction
@@ -720,7 +718,7 @@ def __rmul__(self, other):
720718
721719 # TODO: general __truediv__ requires descriptor system support
722720 def __truediv__ (self , other ):
723- """Division of state space systems byTFs , FRDs, scalars, and arrays"""
721+ """Division of state space systems by TFs , FRDs, scalars, and arrays"""
724722 if not isinstance (other , (LTI , InputOutputSystem )):
725723 return self * (1 / other )
726724 else :
@@ -1522,11 +1520,6 @@ def ss(*args, **kwargs):
15221520 Convert a linear system into space system form. Always creates a
15231521 new system, even if sys is already a state space system.
15241522
1525- ``ss(updfcn, outfcn)``
1526- Create a nonlinear input/output system with update function ``updfcn``
1527- and output function ``outfcn``. See :class:`NonlinearIOSystem` for
1528- more information.
1529-
15301523 ``ss(A, B, C, D)``
15311524 Create a state space system from the matrices of its state and
15321525 output equations:
@@ -1585,9 +1578,7 @@ def ss(*args, **kwargs):
15851578
15861579 See Also
15871580 --------
1588- tf
1589- ss2tf
1590- tf2ss
1581+ tf, ss2tf, tf2ss
15911582
15921583 Examples
15931584 --------
@@ -1601,10 +1592,12 @@ def ss(*args, **kwargs):
16011592 >>> sys2 = ct.ss(sys_tf)
16021593
16031594 """
1604- # See if this is a nonlinear I/O system
1595+ # See if this is a nonlinear I/O system (legacy usage)
16051596 if len (args ) > 0 and (hasattr (args [0 ], '__call__' ) or args [0 ] is None ) \
16061597 and not isinstance (args [0 ], (InputOutputSystem , LTI )):
16071598 # Function as first (or second) argument => assume nonlinear IO system
1599+ warn ("use nlsys() to create nonlinear I/O System" ,
1600+ PendingDeprecationWarning )
16081601 return NonlinearIOSystem (* args , ** kwargs )
16091602
16101603 elif len (args ) == 4 or len (args ) == 5 :
@@ -1644,8 +1637,8 @@ def tf2ss(*args, **kwargs):
16441637 The function accepts either 1 or 2 parameters:
16451638
16461639 ``tf2ss(sys)``
1647- Convert a linear system into space space form. Always creates
1648- a new system, even if sys is already a StateSpace object .
1640+ Convert a transfer function into space space form. Equivalent to
1641+ `ss( sys)` .
16491642
16501643 ``tf2ss(num, den)``
16511644 Create a state space system from its numerator and denominator
@@ -1710,15 +1703,8 @@ def tf2ss(*args, **kwargs):
17101703 _convert_to_statespace (TransferFunction (* args )), ** kwargs )
17111704
17121705 elif len (args ) == 1 :
1713- sys = args [0 ]
1714- if not isinstance (sys , TransferFunction ):
1715- raise TypeError ("tf2ss(sys): sys must be a TransferFunction "
1716- "object." )
1717- return StateSpace (
1718- _convert_to_statespace (
1719- sys ,
1720- use_prefix_suffix = not sys ._generic_name_check ()),
1721- ** kwargs )
1706+ return ss (* args , ** kwargs )
1707+
17221708 else :
17231709 raise ValueError ("Needs 1 or 2 arguments; received %i." % len (args ))
17241710
@@ -1946,8 +1932,8 @@ def summing_junction(
19461932
19471933 Examples
19481934 --------
1949- >>> P = ct.tf2io (1, [1, 0], inputs='u', outputs='y')
1950- >>> C = ct.tf2io (10, [1, 1], inputs='e', outputs='u')
1935+ >>> P = ct.tf (1, [1, 0], inputs='u', outputs='y')
1936+ >>> C = ct.tf (10, [1, 1], inputs='e', outputs='u')
19511937 >>> sumblk = ct.summing_junction(inputs=['r', '-y'], output='e')
19521938 >>> T = ct.interconnect([P, C, sumblk], inputs='r', outputs='y')
19531939 >>> T.ninputs, T.noutputs, T.nstates
@@ -2031,6 +2017,9 @@ def _parse_list(signals, signame='input', prefix='u'):
20312017 return StateSpace (
20322018 ss_sys , inputs = input_names , outputs = output_names , name = name )
20332019
2020+ #
2021+ # Utility functions
2022+ #
20342023
20352024def _ssmatrix (data , axis = 1 ):
20362025 """Convert argument to a (possibly empty) 2D state space matrix.
@@ -2104,7 +2093,6 @@ def _f2s(f):
21042093 return s
21052094
21062095
2107- # TODO: add discrete time check
21082096def _convert_to_statespace (sys , use_prefix_suffix = False ):
21092097 """Convert a system to state space form (if needed).
21102098
@@ -2126,8 +2114,8 @@ def _convert_to_statespace(sys, use_prefix_suffix=False):
21262114 # Make sure the transfer function is proper
21272115 if any ([[len (num ) for num in col ] for col in sys .num ] >
21282116 [[len (num ) for num in col ] for col in sys .den ]):
2129- raise ValueError ("Transfer function is non-proper; can't "
2130- "convert to StateSpace system. " )
2117+ raise ValueError ("transfer function is non-proper; can't "
2118+ "convert to StateSpace system" )
21312119
21322120 try :
21332121 from slycot import td04ad
@@ -2163,9 +2151,6 @@ def _convert_to_statespace(sys, use_prefix_suffix=False):
21632151 if sys .ninputs != 1 or sys .noutputs != 1 :
21642152 raise TypeError ("No support for MIMO without slycot" )
21652153
2166- # TODO: do we want to squeeze first and check dimenations?
2167- # I think this will fail if num and den aren't 1-D after
2168- # the squeeze
21692154 A , B , C , D = \
21702155 sp .signal .tf2ss (squeeze (sys .num ), squeeze (sys .den ))
21712156 newsys = StateSpace (A , B , C , D , sys .dt )
@@ -2187,7 +2172,7 @@ def _convert_to_statespace(sys, use_prefix_suffix=False):
21872172 except Exception :
21882173 raise TypeError ("Can't convert given type to StateSpace system." )
21892174
2190- # TODO: add discrete time option
2175+
21912176def _rss_generate (
21922177 states , inputs , outputs , cdtype , strictly_proper = False , name = None ):
21932178 """Generate a random state space.
@@ -2310,8 +2295,6 @@ def _rss_generate(
23102295 return StateSpace (* ss_args , name = name )
23112296
23122297
2313- # Convert a MIMO system to a SISO system
2314- # TODO: add discrete time check
23152298def _mimo2siso (sys , input , output , warn_conversion = False ):
23162299 # pylint: disable=W0622
23172300 """
@@ -2416,8 +2399,8 @@ def _mimo2simo(sys, input, warn_conversion=False):
24162399 # Y = C*X + D*U
24172400 new_B = sys .B [:, input :input + 1 ]
24182401 new_D = sys .D [:, input :input + 1 ]
2419- sys = StateSpace (sys . A , new_B , sys . C , new_D , sys . dt ,
2420- name = sys .name ,
2421- inputs = sys .input_labels [input ], outputs = sys .output_labels )
2402+ sys = StateSpace (
2403+ sys . A , new_B , sys . C , new_D , sys . dt , name = sys .name ,
2404+ inputs = sys .input_labels [input ], outputs = sys .output_labels )
24222405
24232406 return sys
0 commit comments