def testSimulation(self): T = range(100) U = np.sin(T) # For now, just check calling syntax # TODO: add checks on output of simulations tout, yout = step_response(self.siso_ss1d) tout, yout = step_response(self.siso_ss1d, T) tout, yout = impulse_response(self.siso_ss1d, T) tout, yout = impulse_response(self.siso_ss1d) tout, yout, xout = forced_response(self.siso_ss1d, T, U, 0) tout, yout, xout = forced_response(self.siso_ss2d, T, U, 0) tout, yout, xout = forced_response(self.siso_ss3d, T, U, 0)
def testSimulation(self): T = range(100) U = np.sin(T) # For now, just check calling syntax # TODO: add checks on output of simulations tout, yout = step_response(self.siso_ss1d) tout, yout = step_response(self.siso_ss1d, T) tout, yout = impulse_response(self.siso_ss1d, T) tout, yout = impulse_response(self.siso_ss1d) tout, yout, xout = forced_response(self.siso_ss1d, T, U, 0) tout, yout, xout = forced_response(self.siso_ss2d, T, U, 0) tout, yout, xout = forced_response(self.siso_ss3d, T, U, 0)
def test_forced_response_mimo(self, tsystem, useT): """Test forced response of MIMO system""" # first system: initial value, second system: step response sys = tsystem.sys t = tsystem.t u = np.array([[0., 0, 0, 0, 0, 0, 0, 0, 0, 0], [1., 1, 1, 1, 1, 1, 1, 1, 1, 1]]) x0 = np.array([[.5], [1], [0], [0]]) yref = np.vstack([tsystem.yinitial, tsystem.ystep]) if useT: _t, yout = forced_response(sys, t, u, x0) else: _t, yout = forced_response(sys, U=u, X0=x0) np.testing.assert_array_almost_equal(yout, yref, decimal=4)
def test_forced_response_initial(self, tsystem, u): """Test forced response of SISO system as intitial response.""" sys = tsystem.sys t = tsystem.t x0 = tsystem.X0 yref = tsystem.yinitial if isinstance(sys, StateSpace): tout, yout = forced_response(sys, t, u, X0=x0) np.testing.assert_array_almost_equal(tout, t) np.testing.assert_array_almost_equal(yout, yref, decimal=4) else: with pytest.warns(UserWarning, match="Non-zero initial condition " "given for transfer function"): tout, yout = forced_response(sys, t, u, X0=x0)
def test_time_vector_interpolation(self, siso_dtf2, squeeze): """Test time vector handling in case of interpolation Interpolation of the input (to match scipy.signal.dlsim) gh-239, gh-295 """ sys = siso_dtf2.sys t = np.arange(0, 10, 1.) u = np.sin(t) x0 = 0 squeezekw = {} if squeeze is None else {"squeeze": squeeze} tout, yout = forced_response(sys, t, u, x0, interpolate=True, **squeezekw) if squeeze is False or sys.noutputs > 1: assert yout.shape[0] == sys.noutputs assert yout.shape[1] == tout.shape[0] else: assert yout.shape == tout.shape assert np.allclose(tout[1:] - tout[:-1], sys.dt)
def test_forced_response_T_U(self, tsystem, fr_kwargs, refattr): """Test documented forced_response behavior for parameters T and U.""" if refattr == 'yinitial': fr_kwargs['X0'] = tsystem.X0 t, y = forced_response(tsystem.sys, **fr_kwargs) np.testing.assert_allclose(t, tsystem.t) np.testing.assert_allclose(y, getattr(tsystem, refattr), rtol=1e-3)
def test_forced_response_step(self, tsystem): """Test forced response of SISO systems as step response""" sys = tsystem.sys t = tsystem.t u = np.ones_like(t, dtype=float) yref = tsystem.ystep tout, yout = forced_response(sys, t, u) np.testing.assert_array_almost_equal(tout, t) np.testing.assert_array_almost_equal(yout, yref, decimal=4)
def test_forced_response_initial(self, siso_ss1, u): """Test forced response of SISO system as intitial response""" sys = siso_ss1.sys t = siso_ss1.t x0 = np.array([[.5], [1.]]) yref = siso_ss1.yinitial tout, yout = forced_response(sys, t, u, X0=x0) np.testing.assert_array_almost_equal(tout, t) np.testing.assert_array_almost_equal(yout, yref, decimal=4)
def lsim(sys, U=0., T=None, X0=0., **keywords): ''' Simulate the output of a linear system. As a convenience for parameters `U`, `X0`: Numbers (scalars) are converted to constant arrays with the correct shape. The correct shape is inferred from arguments `sys` and `T`. Parameters ---------- sys: Lti (StateSpace, or TransferFunction) LTI system to simulate U: array-like or number, optional Input array giving input at each time `T` (default = 0). If `U` is ``None`` or ``0``, a special algorithm is used. This special algorithm is faster than the general algorithm, which is used otherwise. T: array-like Time steps at which the input is defined, numbers must be (strictly monotonic) increasing. X0: array-like or number, optional Initial condition (default = 0). **keywords: Additional keyword arguments control the solution algorithm for the differential equations. These arguments are passed on to the function :func:`scipy.integrate.odeint`. See the documentation for :func:`scipy.integrate.odeint` for information about these arguments. Returns ------- yout: array Response of the system. T: array Time values of the output. xout: array Time evolution of the state vector. See Also -------- step, initial, impulse Examples -------- >>> T, yout, xout = lsim(sys, U, T, X0) ''' T, yout, xout = timeresp.forced_response(sys, T, U, X0, transpose = True, **keywords) return yout, T, xout
def lsim(sys, U=0., T=None, X0=0., **keywords): ''' Simulate the output of a linear system. As a convenience for parameters `U`, `X0`: Numbers (scalars) are converted to constant arrays with the correct shape. The correct shape is inferred from arguments `sys` and `T`. Parameters ---------- sys: Lti (StateSpace, or TransferFunction) LTI system to simulate U: array-like or number, optional Input array giving input at each time `T` (default = 0). If `U` is ``None`` or ``0``, a special algorithm is used. This special algorithm is faster than the general algorithm, which is used otherwise. T: array-like Time steps at which the input is defined, numbers must be (strictly monotonic) increasing. X0: array-like or number, optional Initial condition (default = 0). **keywords: Additional keyword arguments control the solution algorithm for the differential equations. These arguments are passed on to the function :func:`scipy.integrate.odeint`. See the documentation for :func:`scipy.integrate.odeint` for information about these arguments. Returns ------- yout: array Response of the system. T: array Time values of the output. xout: array Time evolution of the state vector. See Also -------- step, initial, impulse Examples -------- >>> T, yout, xout = lsim(sys, U, T, X0) ''' T, yout, xout = timeresp.forced_response(sys, T, U, X0, transpose = True, **keywords) return yout, T, xout
def test_lsim_double_integrator(self, u, x0, xtrue): """Test forced response of double integrator""" # Note: scipy.signal.lsim fails if A is not invertible A = np.array([[0., 1.], [0., 0.]]) B = np.array([[0.], [1.]]) C = np.array([[1., 0.]]) D = 0. sys = StateSpace(A, B, C, D) t = np.linspace(0, 1, 10) _t, yout, xout = forced_response(sys, t, u, x0, return_x=True) np.testing.assert_array_almost_equal(xout, xtrue, decimal=6) ytrue = np.squeeze(np.asarray(C.dot(xtrue))) np.testing.assert_array_almost_equal(yout, ytrue, decimal=6)
def test_forced_response_invalid_c(self, tsystem): """Test invalid parameters.""" with pytest.raises(TypeError, match="StateSpace.*or.*TransferFunction"): forced_response("not a system") with pytest.raises(ValueError, match="T.*is mandatory for continuous"): forced_response(tsystem.sys) with pytest.raises(ValueError, match="time values must be equally " "spaced"): forced_response(tsystem.sys, [0, 0.1, 0.12, 0.4])
def test_forced_response_invalid_d(self, tsystem): """Test invalid parameters dtime with sys.dt > 0.""" with pytest.raises(ValueError, match="can't both be zero"): forced_response(tsystem.sys) with pytest.raises(ValueError, match="must have same elements"): forced_response(tsystem.sys, T=tsystem.t, U=np.random.randn(1, 12)) with pytest.raises(ValueError, match="must have same elements"): forced_response(tsystem.sys, T=tsystem.t, U=np.random.randn(12)) with pytest.raises(ValueError, match="must match sampling time"): forced_response(tsystem.sys, T=tsystem.t*0.9) with pytest.raises(ValueError, match="must be multiples of " "sampling time"): forced_response(tsystem.sys, T=tsystem.t*1.1) # but this is ok forced_response(tsystem.sys, T=tsystem.t*2)