def impulse_response(sys, T=None, X0=0., input=0, output=None, transpose=False): # pylint: disable=W0622 """Impulse response of a linear system If the system has multiple inputs or outputs (MIMO), one input has to be selected for the simulation. Optionally, one output may be selected. The parameters `input` and `output` do this. All other inputs are set to 0, all other outputs are ignored. For information on the **shape** of parameters `T`, `X0` and return values `T`, `yout`, see :ref:`time-series-convention`. Parameters ---------- sys: StateSpace, TransferFunction LTI system to simulate T: array-like object, optional Time vector (argument is autocomputed if not given) X0: array-like object or number, optional Initial condition (default = 0) Numbers are converted to constant arrays with the correct shape. input: int Index of the input that will be used in this simulation. output: int Index of the output that will be used in this simulation. Set to None to not trim outputs transpose: bool If True, transpose all input and output arrays (for backward compatibility with MATLAB and scipy.signal.lsim) Returns ------- T: array Time values of the output yout: array Response of the system See Also -------- ForcedReponse, initial_response, step_response Examples -------- >>> T, yout = impulse_response(sys, T, X0) """ sys = _get_ss_simo(sys, input, output) # System has direct feedthrough, can't simulate impulse response numerically if np.any(sys.D != 0) and isctime(sys): warnings.warn('System has direct feedthrough: ``D != 0``. The infinite ' 'impulse at ``t=0`` does not appear in the output. \n' 'Results may be meaningless!') # create X0 if not given, test if X0 has correct shape. # Must be done here because it is used for computations here. n_states = sys.A.shape[0] X0 = _check_convert_array(X0, [(n_states,), (n_states, 1)], 'Parameter ``X0``: \n', squeeze=True) # Compute new X0 that contains the impulse # We can't put the impulse into U because there is no numerical # representation for it (infinitesimally short, infinitely high). # See also: http://www.mathworks.com/support/tech-notes/1900/1901.html B = np.asarray(sys.B).squeeze() new_X0 = B + X0 # Compute T and U, no checks necessary, they will be checked in lsim if T is None: T = _default_response_times(sys.A, 100) U = np.zeros_like(T) T, yout, _xout = forced_response( sys, T, U, new_X0, transpose=transpose) return T, yout
def step_response(sys, T=None, X0=0., input=None, output=None, transpose=False): # pylint: disable=W0622 """Step response of a linear system If the system has multiple inputs or outputs (MIMO), one input has to be selected for the simulation. Optionally, one output may be selected. The parameters `input` and `output` do this. All other inputs are set to 0, all other outputs are ignored. For information on the **shape** of parameters `T`, `X0` and return values `T`, `yout`, see :ref:`time-series-convention`. Parameters ---------- sys: StateSpace, or TransferFunction LTI system to simulate T: array-like object, optional Time vector (argument is autocomputed if not given) X0: array-like or number, optional Initial condition (default = 0) Numbers are converted to constant arrays with the correct shape. input: int Index of the input that will be used in this simulation. output: int Index of the output that will be used in this simulation. Set to None to not trim outputs transpose: bool If True, transpose all input and output arrays (for backward compatibility with MATLAB and scipy.signal.lsim) Returns ------- T: array Time values of the output yout: array Response of the system See Also -------- forced_response, initial_response, impulse_response Examples -------- >>> T, yout = step_response(sys, T, X0) """ sys = _get_ss_simo(sys, input, output) if T is None: if isctime(sys): T = _default_response_times(sys.A, 100) else: # For discrete time, use integers tvec = _default_response_times(sys.A, 100) T = range(int(np.ceil(max(tvec)))) U = np.ones_like(T) T, yout, _xout = forced_response(sys, T, U, X0, transpose=transpose) return T, yout
def initial_response(sys, T=None, X0=0., input=0, output=None, transpose=False): # pylint: disable=W0622 """Initial condition response of a linear system If the system has multiple outputs (MIMO), optionally, one output may be selected. If no selection is made for the output, all outputs are given. For information on the **shape** of parameters `T`, `X0` and return values `T`, `yout`, see :ref:`time-series-convention`. Parameters ---------- sys: StateSpace, or TransferFunction LTI system to simulate T: array-like object, optional Time vector (argument is autocomputed if not given) X0: array-like object or number, optional Initial condition (default = 0) Numbers are converted to constant arrays with the correct shape. input: int Ignored, has no meaning in initial condition calculation. Parameter ensures compatibility with step_response and impulse_response output: int Index of the output that will be used in this simulation. Set to None to not trim outputs transpose: bool If True, transpose all input and output arrays (for backward compatibility with MATLAB and scipy.signal.lsim) Returns ------- T: array Time values of the output yout: array Response of the system See Also -------- forced_response, impulse_response, step_response Examples -------- >>> T, yout = initial_response(sys, T, X0) """ sys = _get_ss_simo(sys, input, output) # Create time and input vectors; checking is done in forced_response(...) # The initial vector X0 is created in forced_response(...) if necessary if T is None: T = _default_response_times(sys.A, 100) U = np.zeros_like(T) T, yout, _xout = forced_response(sys, T, U, X0, transpose=transpose) return T, yout
def step_info(sys, T=None, SettlingTimeThreshold=0.02, RiseTimeLimits=(0.1, 0.9)): ''' Step response characteristics (Rise time, Settling Time, Peak and others). Parameters ---------- sys: StateSpace, or TransferFunction LTI system to simulate T: array-like object, optional Time vector (argument is autocomputed if not given) SettlingTimeThreshold: float value, optional Defines the error to compute settling time (default = 0.02) RiseTimeLimits: tuple (lower_threshold, upper_theshold) Defines the lower and upper threshold for RiseTime computation Returns ------- S: a dictionary containing: RiseTime: Time from 10% to 90% of the steady-state value. SettlingTime: Time to enter inside a default error of 2% SettlingMin: Minimum value after RiseTime SettlingMax: Maximum value after RiseTime Overshoot: Percentage of the Peak relative to steady value Undershoot: Percentage of undershoot Peak: Absolute peak value PeakTime: time of the Peak SteadyStateValue: Steady-state value See Also -------- step, lsim, initial, impulse Examples -------- >>> info = step_info(sys, T) ''' sys = _get_ss_simo(sys) if T is None: if isctime(sys): T = _default_response_times(sys.A, 1000) else: # For discrete time, use integers tvec = _default_response_times(sys.A, 1000) T = range(int(np.ceil(max(tvec)))) T, yout = step_response(sys, T) # Steady state value InfValue = yout[-1] # RiseTime tr_lower_index = (np.where(yout >= RiseTimeLimits[0] * InfValue)[0])[0] tr_upper_index = (np.where(yout >= RiseTimeLimits[1] * InfValue)[0])[0] RiseTime = T[tr_upper_index] - T[tr_lower_index] # SettlingTime sup_margin = (1. + SettlingTimeThreshold) * InfValue inf_margin = (1. - SettlingTimeThreshold) * InfValue # find Steady State looking for the first point out of specified limits for i in reversed(range(T.size)): if((yout[i] <= inf_margin) | (yout[i] >= sup_margin)): SettlingTime = T[i + 1] break # Peak PeakIndex = np.abs(yout).argmax() PeakValue = yout[PeakIndex] PeakTime = T[PeakIndex] SettlingMax = (yout).max() SettlingMin = (yout[tr_upper_index:]).min() # I'm really not very confident about UnderShoot: UnderShoot = yout.min() OverShoot = 100. * (yout.max() - InfValue) / (InfValue - yout[0]) # Return as a dictionary S = { 'RiseTime': RiseTime, 'SettlingTime': SettlingTime, 'SettlingMin': SettlingMin, 'SettlingMax': SettlingMax, 'Overshoot': OverShoot, 'Undershoot': UnderShoot, 'Peak': PeakValue, 'PeakTime': PeakTime, 'SteadyStateValue': InfValue } return S
def initial_response(sys, T=None, X0=0., input=0, output=0, transpose=False, **keywords): #pylint: disable=W0622 """Initial condition response of a linear system If the system has multiple inputs or outputs (MIMO), one input and one output have to be selected for the simulation. The parameters `input` and `output` do this. All other inputs are set to 0, all other outputs are ignored. For information on the **shape** of parameters `T`, `X0` and return values `T`, `yout` see: :ref:`time-series-convention` Parameters ---------- sys: StateSpace, or TransferFunction LTI system to simulate T: array-like object, optional Time vector (argument is autocomputed if not given) X0: array-like object or number, optional Initial condition (default = 0) Numbers are converted to constant arrays with the correct shape. input: int Index of the input that will be used in this simulation. output: int Index of the output that will be used in this simulation. transpose: bool If True, transpose all input and output arrays (for backward compatibility with MATLAB and scipy.signal.lsim) **keywords: Additional keyword arguments control the solution algorithm for the differential equations. These arguments are passed on to the function :func:`lsim`, which in turn passes them on to :func:`scipy.integrate.odeint`. See the documentation for :func:`scipy.integrate.odeint` for information about these arguments. Returns ------- T: array Time values of the output yout: array Response of the system See Also -------- forced_response, impulse_response, step_response Examples -------- >>> T, yout = initial_response(sys, T, X0) """ sys = _convertToStateSpace(sys) sys = _mimo2siso(sys, input, output, warn_conversion=True) # Create time and input vectors; checking is done in forced_response(...) # The initial vector X0 is created in forced_response(...) if necessary if T is None: T = _default_response_times(sys.A, 100) U = np.zeros_like(T) T, yout, _xout = forced_response(sys, T, U, X0, transpose=transpose, **keywords) return T, yout
def step_response(sys, T=None, X0=0., input=None, output=None, transpose=False, return_x=False, squeeze=True): # pylint: disable=W0622 """Step response of a linear system If the system has multiple inputs or outputs (MIMO), one input has to be selected for the simulation. Optionally, one output may be selected. The parameters `input` and `output` do this. All other inputs are set to 0, all other outputs are ignored. For information on the **shape** of parameters `T`, `X0` and return values `T`, `yout`, see :ref:`time-series-convention`. Parameters ---------- sys: StateSpace, or TransferFunction LTI system to simulate T: array-like object, optional Time vector (argument is autocomputed if not given) X0: array-like or number, optional Initial condition (default = 0) Numbers are converted to constant arrays with the correct shape. input: int Index of the input that will be used in this simulation. output: int Index of the output that will be used in this simulation. Set to None to not trim outputs transpose: bool If True, transpose all input and output arrays (for backward compatibility with MATLAB and scipy.signal.lsim) return_x: bool If True, return the state vector (default = False). squeeze: bool, optional (default=True) If True, remove single-dimensional entries from the shape of the output. For single output systems, this converts the output response to a 1D array. Returns ------- T: array Time values of the output yout: array Response of the system xout: array Individual response of each x variable See Also -------- forced_response, initial_response, impulse_response Examples -------- >>> T, yout = step_response(sys, T, X0) """ sys = _get_ss_simo(sys, input, output) if T is None: if isctime(sys): T = _default_response_times(sys.A, 100) else: # For discrete time, use integers tvec = _default_response_times(sys.A, 100) T = range(int(np.ceil(max(tvec)))) U = np.ones_like(T) T, yout, xout = forced_response(sys, T, U, X0, transpose=transpose, squeeze=squeeze) if return_x: return T, yout, xout return T, yout
def impulse_response(sys, T=None, X0=0., input=0, output=None, transpose=False, return_x=False): # pylint: disable=W0622 """Impulse response of a linear system If the system has multiple inputs or outputs (MIMO), one input has to be selected for the simulation. Optionally, one output may be selected. The parameters `input` and `output` do this. All other inputs are set to 0, all other outputs are ignored. For information on the **shape** of parameters `T`, `X0` and return values `T`, `yout`, see :ref:`time-series-convention`. Parameters ---------- sys: StateSpace, TransferFunction LTI system to simulate T: array-like object, optional Time vector (argument is autocomputed if not given) X0: array-like object or number, optional Initial condition (default = 0) Numbers are converted to constant arrays with the correct shape. input: int Index of the input that will be used in this simulation. output: int Index of the output that will be used in this simulation. Set to None to not trim outputs transpose: bool If True, transpose all input and output arrays (for backward compatibility with MATLAB and scipy.signal.lsim) return_x: bool If True, return the state vector (default = False). Returns ------- T: array Time values of the output yout: array Response of the system xout: array Individual response of each x variable See Also -------- forced_response, initial_response, step_response Examples -------- >>> T, yout = impulse_response(sys, T, X0) """ sys = _get_ss_simo(sys, input, output) # System has direct feedthrough, can't simulate impulse response numerically if np.any(sys.D != 0) and isctime(sys): warnings.warn( 'System has direct feedthrough: ``D != 0``. The infinite ' 'impulse at ``t=0`` does not appear in the output. \n' 'Results may be meaningless!') # create X0 if not given, test if X0 has correct shape. # Must be done here because it is used for computations here. n_states = sys.A.shape[0] X0 = _check_convert_array(X0, [(n_states, ), (n_states, 1)], 'Parameter ``X0``: \n', squeeze=True) # Compute T and U, no checks necessary, they will be checked in lsim if T is None: T = _default_response_times(sys.A, 100) U = np.zeros_like(T) # Compute new X0 that contains the impulse # We can't put the impulse into U because there is no numerical # representation for it (infinitesimally short, infinitely high). # See also: http://www.mathworks.com/support/tech-notes/1900/1901.html if isctime(sys): B = np.asarray(sys.B).squeeze() new_X0 = B + X0 else: new_X0 = X0 U[0] = 1. T, yout, _xout = forced_response(sys, T, U, new_X0, transpose=transpose) if return_x: return T, yout, _xout return T, yout
def initial_response(sys, T=None, X0=0., input=0, output=None, transpose=False, return_x=False): # pylint: disable=W0622 """Initial condition response of a linear system If the system has multiple outputs (MIMO), optionally, one output may be selected. If no selection is made for the output, all outputs are given. For information on the **shape** of parameters `T`, `X0` and return values `T`, `yout`, see :ref:`time-series-convention`. Parameters ---------- sys: StateSpace, or TransferFunction LTI system to simulate T: array-like object, optional Time vector (argument is autocomputed if not given) X0: array-like object or number, optional Initial condition (default = 0) Numbers are converted to constant arrays with the correct shape. input: int Ignored, has no meaning in initial condition calculation. Parameter ensures compatibility with step_response and impulse_response output: int Index of the output that will be used in this simulation. Set to None to not trim outputs transpose: bool If True, transpose all input and output arrays (for backward compatibility with MATLAB and scipy.signal.lsim) return_x: bool If True, return the state vector (default = False). Returns ------- T: array Time values of the output yout: array Response of the system xout: array Individual response of each x variable See Also -------- forced_response, impulse_response, step_response Examples -------- >>> T, yout = initial_response(sys, T, X0) """ sys = _get_ss_simo(sys, input, output) # Create time and input vectors; checking is done in forced_response(...) # The initial vector X0 is created in forced_response(...) if necessary if T is None: T = _default_response_times(sys.A, 100) U = np.zeros_like(T) T, yout, _xout = forced_response(sys, T, U, X0, transpose=transpose) if return_x: return T, yout, _xout return T, yout
def step_info(sys, T=None, SettlingTimeThreshold=0.02, RiseTimeLimits=(0.1, 0.9)): ''' Step response characteristics (Rise time, Settling Time, Peak and others). Parameters ---------- sys: StateSpace, or TransferFunction LTI system to simulate T: array-like object, optional Time vector (argument is autocomputed if not given) SettlingTimeThreshold: float value, optional Defines the error to compute settling time (default = 0.02) RiseTimeLimits: tuple (lower_threshold, upper_theshold) Defines the lower and upper threshold for RiseTime computation Returns ------- S: a dictionary containing: RiseTime: Time from 10% to 90% of the steady-state value. SettlingTime: Time to enter inside a default error of 2% SettlingMin: Minimum value after RiseTime SettlingMax: Maximum value after RiseTime Overshoot: Percentage of the Peak relative to steady value Undershoot: Percentage of undershoot Peak: Absolute peak value PeakTime: time of the Peak SteadyStateValue: Steady-state value See Also -------- step, lsim, initial, impulse Examples -------- >>> info = step_info(sys, T) ''' sys = _get_ss_simo(sys) if T is None: if isctime(sys): T = _default_response_times(sys.A, 1000) else: # For discrete time, use integers tvec = _default_response_times(sys.A, 1000) T = range(int(np.ceil(max(tvec)))) T, yout = step_response(sys, T) # Steady state value InfValue = yout[-1] # RiseTime tr_lower_index = (np.where(yout >= RiseTimeLimits[0] * InfValue)[0])[0] tr_upper_index = (np.where(yout >= RiseTimeLimits[1] * InfValue)[0])[0] RiseTime = T[tr_upper_index] - T[tr_lower_index] # SettlingTime sup_margin = (1. + SettlingTimeThreshold) * InfValue inf_margin = (1. - SettlingTimeThreshold) * InfValue # find Steady State looking for the first point out of specified limits for i in reversed(range(T.size)): if ((yout[i] <= inf_margin) | (yout[i] >= sup_margin)): SettlingTime = T[i + 1] break # Peak PeakIndex = np.abs(yout).argmax() PeakValue = yout[PeakIndex] PeakTime = T[PeakIndex] SettlingMax = (yout).max() SettlingMin = (yout[tr_upper_index:]).min() # I'm really not very confident about UnderShoot: UnderShoot = yout.min() OverShoot = 100. * (yout.max() - InfValue) / (InfValue - yout[0]) # Return as a dictionary S = { 'RiseTime': RiseTime, 'SettlingTime': SettlingTime, 'SettlingMin': SettlingMin, 'SettlingMax': SettlingMax, 'Overshoot': OverShoot, 'Undershoot': UnderShoot, 'Peak': PeakValue, 'PeakTime': PeakTime, 'SteadyStateValue': InfValue } return S
def initial_response(sys, T=None, X0=0., input=0, output=None, transpose=False, **keywords): #pylint: disable=W0622 """Initial condition response of a linear system If the system has multiple inputs or outputs (MIMO), one input and one output have to be selected for the simulation. The parameters `input` and `output` do this. All other inputs are set to 0, all other outputs are ignored. For information on the **shape** of parameters `T`, `X0` and return values `T`, `yout` see: :ref:`time-series-convention` Parameters ---------- sys: StateSpace, or TransferFunction LTI system to simulate T: array-like object, optional Time vector (argument is autocomputed if not given) X0: array-like object or number, optional Initial condition (default = 0) Numbers are converted to constant arrays with the correct shape. input: int Index of the input that will be used in this simulation. output: int Index of the output that will be used in this simulation. Set to None to not trim outputs transpose: bool If True, transpose all input and output arrays (for backward compatibility with MATLAB and scipy.signal.lsim) **keywords: Additional keyword arguments control the solution algorithm for the differential equations. These arguments are passed on to the function :func:`lsim`, which in turn passes them on to :func:`scipy.integrate.odeint`. See the documentation for :func:`scipy.integrate.odeint` for information about these arguments. Returns ------- T: array Time values of the output yout: array Response of the system See Also -------- forced_response, impulse_response, step_response Examples -------- >>> T, yout = initial_response(sys, T, X0) """ sys = _convertToStateSpace(sys) if output == None: sys = _mimo2simo(sys, input, warn_conversion=False) else: sys = _mimo2siso(sys, input, output, warn_conversion=False) # Create time and input vectors; checking is done in forced_response(...) # The initial vector X0 is created in forced_response(...) if necessary if T is None: T = _default_response_times(sys.A, 100) U = np.zeros_like(T) T, yout, _xout = forced_response(sys, T, U, X0, transpose=transpose, **keywords) return T, yout