@@ -210,6 +210,9 @@ def forced_response(sys, T=None, U=0., X0=0., transpose=False,
210210
211211 T : array_like, optional for discrete LTI `sys`
212212 Time steps at which the input is defined; values must be evenly spaced.
213+ If None, `U` must be given and and `len(U)` time steps of sys.dt are
214+ simulated. If sys.dt is None or True (undetermined time step), a dt
215+ of 1.0 is assumed.
213216
214217 U : array_like or float, optional
215218 Input array giving input at each time `T`
@@ -245,7 +248,7 @@ def forced_response(sys, T=None, U=0., X0=0., transpose=False,
245248 squeeze=True, remove single-dimensional entries from the shape of
246249 the output even if the system is not SISO. If squeeze=False, keep
247250 the output as a 2D array (indexed by the output number and time)
248- even if the system is SISO. The default value can be overruled by
251+ even if the system is SISO. The default value can be overridden by
249252 config.defaults['control.squeeze_time_response'].
250253
251254 Returns
@@ -310,10 +313,11 @@ def forced_response(sys, T=None, U=0., X0=0., transpose=False,
310313 if U is not None :
311314 U = np .asarray (U )
312315 if T is not None :
316+ # T must be array-like
313317 T = np .asarray (T )
314318
315319 # Set and/or check time vector in discrete time case
316- if isdtime (sys , strict = True ):
320+ if isdtime (sys ):
317321 if T is None :
318322 if U is None :
319323 raise ValueError ('Parameters ``T`` and ``U`` can\' t both be'
@@ -323,29 +327,28 @@ def forced_response(sys, T=None, U=0., X0=0., transpose=False,
323327 n_steps = U .shape [0 ]
324328 else :
325329 n_steps = U .shape [1 ]
326- T = np .array (range (n_steps )) * (1 if sys .dt is True else sys .dt )
330+ dt = 1. if sys .dt in [True , None ] else sys .dt
331+ T = np .array (range (n_steps )) * dt
327332 else :
328333 # Make sure the input vector and time vector have same length
329334 # TODO: allow interpolation of the input vector
330335 if (U .ndim == 1 and U .shape [0 ] != T .shape [0 ]) or \
331336 (U .ndim > 1 and U .shape [1 ] != T .shape [0 ]):
332337 ValueError ('Pamameter ``T`` must have same elements as'
333338 ' the number of columns in input array ``U``' )
339+ else :
340+ if T is None :
341+ raise ValueError ('Parameter ``T`` is mandatory for continuous '
342+ 'time systems.' )
334343
335344 # Test if T has shape (n,) or (1, n);
336- # T must be array-like and values must be increasing.
337- # The length of T determines the length of the input vector.
338- if T is None :
339- if not isdtime (sys , strict = True ):
340- errmsg_ctime = 'is mandatory for continuous time systems, '
341- raise ValueError ('Parameter ``T`` ' + errmsg_ctime + 'must be '
342- 'array-like, and contain (strictly monotonic) '
343- 'increasing numbers.' )
344345 T = _check_convert_array (T , [('any' ,), (1 , 'any' )],
345346 'Parameter ``T``: ' , squeeze = True ,
346347 transpose = transpose )
348+
349+ # equally spaced also implies strictly monotonic increase
347350 dt = T [1 ] - T [0 ]
348- if not np .allclose (T [ 1 :] - T [:- 1 ], dt ):
351+ if not np .allclose (np . diff ( T ), np . full_like ( T [:- 1 ], dt ) ):
349352 raise ValueError ("Parameter ``T``: time values must be "
350353 "equally spaced." )
351354 n_steps = T .shape [0 ] # number of simulation steps
0 commit comments