@@ -209,8 +209,7 @@ def forced_response(sys, T=None, U=0., X0=0., transpose=False,
209209 LTI system to simulate
210210
211211 T : array_like, optional for discrete LTI `sys`
212- Time steps at which the input is defined; values must be evenly spaced
213- and start with 0.
212+ Time steps at which the input is defined; values must be evenly spaced.
214213
215214 If None, `U` must be given and `len(U)` time steps of sys.dt are
216215 simulated. If sys.dt is None or True (undetermined time step), a time
@@ -360,10 +359,10 @@ def forced_response(sys, T=None, U=0., X0=0., transpose=False,
360359 n_steps = T .shape [0 ] # number of simulation steps
361360
362361 # equally spaced also implies strictly monotonic increase,
363- dt = T [- 1 ] / (n_steps - 1 )
362+ dt = ( T [- 1 ] - T [ 0 ]) / (n_steps - 1 )
364363 if not np .allclose (np .diff (T ), dt ):
365- raise ValueError ("Parameter ``T`` must start with 0 and time values "
366- "must be equally spaced." )
364+ raise ValueError ("Parameter ``T``: time values must be equally "
365+ "spaced." )
367366
368367 # create X0 if not given, test if X0 has correct shape
369368 X0 = _check_convert_array (X0 , [(n_states ,), (n_states , 1 )],
@@ -426,6 +425,10 @@ def forced_response(sys, T=None, U=0., X0=0., transpose=False,
426425
427426 else :
428427 # Discrete type system => use SciPy signal processing toolbox
428+
429+ # sp.signal.dlsim assumes T[0] == 0
430+ spT = T - T [0 ]
431+
429432 if sys .dt is not True and sys .dt is not None :
430433 # Make sure that the time increment is a multiple of sampling time
431434
@@ -446,10 +449,10 @@ def forced_response(sys, T=None, U=0., X0=0., transpose=False,
446449 # T[-1] - T[0] < sys_dt * decimation * (n_steps - 1)
447450 # due to rounding errors.
448451 # https://github.com/scipyscipy/blob/v1.6.1/scipy/signal/ltisys.py#L3462
449- scipy_out_samples = int (np .floor (T [- 1 ] / sys_dt )) + 1
452+ scipy_out_samples = int (np .floor (spT [- 1 ] / sys_dt )) + 1
450453 if scipy_out_samples < n_steps :
451454 # parantheses: order of evaluation is important
452- T [- 1 ] = T [- 1 ] * (n_steps / (T [- 1 ] / sys_dt + 1 ))
455+ spT [- 1 ] = spT [- 1 ] * (n_steps / (spT [- 1 ] / sys_dt + 1 ))
453456
454457 else :
455458 sys_dt = dt # For unspecified sampling time, use time incr
@@ -459,7 +462,8 @@ def forced_response(sys, T=None, U=0., X0=0., transpose=False,
459462
460463 # Use signal processing toolbox for the discrete time simulation
461464 # Transpose the input to match toolbox convention
462- tout , yout , xout = sp .signal .dlsim (dsys , np .transpose (U ), T , X0 )
465+ tout , yout , xout = sp .signal .dlsim (dsys , np .transpose (U ), spT , X0 )
466+ tout = tout + T [0 ]
463467
464468 if not interpolate :
465469 # If dt is different from sys.dt, resample the output
@@ -472,8 +476,7 @@ def forced_response(sys, T=None, U=0., X0=0., transpose=False,
472476 xout = np .transpose (xout )
473477 yout = np .transpose (yout )
474478
475- return _process_time_response (sys , tout [:n_steps ], yout [:, :n_steps ],
476- xout [:, :n_steps ], transpose = transpose ,
479+ return _process_time_response (sys , tout , yout , xout , transpose = transpose ,
477480 return_x = return_x , squeeze = squeeze )
478481
479482
0 commit comments