예제 #1
0
 def test_step_response_mimo(self, tsystem):
     """Test MIMO system, which contains ``siso_ss1`` twice."""
     sys = tsystem.sys
     t = tsystem.t
     yref = tsystem.ystep
     _t, y_00 = step_response(sys, T=t, input=0, output=0)
     _t, y_11 = step_response(sys, T=t, input=1, output=1)
     np.testing.assert_array_almost_equal(y_00, yref, decimal=4)
     np.testing.assert_array_almost_equal(y_11, yref, decimal=4)
예제 #2
0
 def test_step_response_return(self, tsystem):
     """Verify continuous and discrete time use same return conventions."""
     sysc = tsystem.sys
     sysd = c2d(sysc, 1)            # discrete time system
     Tvec = np.linspace(0, 10, 11)  # make sure to use integer times 0..10
     Tc, youtc = step_response(sysc, Tvec, input=0)
     Td, youtd = step_response(sysd, Tvec, input=0)
     np.testing.assert_array_equal(Tc.shape, Td.shape)
     np.testing.assert_array_equal(youtc.shape, youtd.shape)
예제 #3
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)
예제 #4
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)
예제 #5
0
    def test_step_robustness(self):
        "Test robustness os step_response against denomiantors: gh-240"
        # Create 2 input, 2 output system
        num =  [[[0], [1]],           [[1],    [0]]]

        den1 = [[[1], [1,1]],         [[1, 4], [1]]]
        sys1 = TransferFunction(num, den1)

        den2 = [[[1], [1e-10, 1, 1]], [[1, 4], [1]]]   # slight perturbation
        sys2 = TransferFunction(num, den2)

        t1, y1 = step_response(sys1, input=0, T=2, T_num=100)
        t2, y2 = step_response(sys2, input=0, T=2, T_num=100)
        np.testing.assert_array_almost_equal(y1, y2)
예제 #6
0
 def test_time_series_data_convention_2D(self, tsystem):
     """Allow input time as 2D array (output should be 1D)"""
     tin = np.array(np.linspace(0, 10, 100), ndmin=2)
     t, y = step_response(tsystem.sys, tin)
     assert isinstance(t, np.ndarray) and not isinstance(t, np.matrix)
     assert t.ndim == 1
     assert y.ndim == 1  # SISO returns "scalar" output
     assert t.shape == y.shape  # Allows direct plotting of output
예제 #7
0
    def test_step_nostates(self, dt):
        """Constant system, continuous and discrete time.

        gh-374 "Bug in step_response()"
        """
        sys = TransferFunction([1], [1], dt)
        t, y = step_response(sys)
        np.testing.assert_allclose(y, np.ones(len(t)))
예제 #8
0
def step(sys, T=None, X0=0., input=0, output=0, **keywords):
    '''
    Step 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.
    
    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.

    **keywords:
        Additional keyword arguments control the solution algorithm for the 
        differential equations. These arguments are passed on to the function
        :func:`control.forced_response`, 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
    -------
    yout: array
        Response of the system
    
    T: array
        Time values of the output

    See Also
    --------
    lsim, initial, impulse

    Examples
    --------
    >>> T, yout = step(sys, T, X0)
    '''
    T, yout = timeresp.step_response(sys, T, X0, input, output, 
                                   transpose = True, **keywords)
    return yout, T
예제 #9
0
def step(sys, T=None, X0=0., input=0, output=None, **keywords):
    '''
    Step 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.
    
    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.

    **keywords:
        Additional keyword arguments control the solution algorithm for the 
        differential equations. These arguments are passed on to the function
        :func:`control.forced_response`, 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
    -------
    yout: array
        Response of the system
    
    T: array
        Time values of the output

    See Also
    --------
    lsim, initial, impulse

    Examples
    --------
    >>> yout, T = step(sys, T, X0)
    '''
    T, yout = timeresp.step_response(sys, T, X0, input, output, 
                                   transpose = True, **keywords)
    return yout, T
예제 #10
0
 def test_step_response_siso(self, tsystem, kwargs):
     """Test SISO system step response"""
     sys = tsystem.sys
     t = tsystem.t
     yref = tsystem.ystep
     # SISO call
     out = step_response(sys, T=t, **kwargs)
     tout, yout = out[:2]
     assert len(out) == 3 if ('return_x', True) in kwargs.items() else 2
     np.testing.assert_array_almost_equal(tout, t)
     np.testing.assert_array_almost_equal(yout, yref, decimal=4)
예제 #11
0
    def test_step_info(self, tsystem, systype, time_2d, yfinal):
        """Test step info for SISO systems."""
        step_info_kwargs = tsystem.kwargs.get('step_info', {})
        if systype == "time response":
            # simulate long enough for steady state value
            tfinal = 3 * tsystem.step_info['SettlingTime']
            if np.isnan(tfinal):
                pytest.skip("test system does not settle")
            t, y = step_response(tsystem.sys, T=tfinal, T_num=5000)
            sysdata = y
            step_info_kwargs['T'] = t[np.newaxis, :] if time_2d else t
        else:
            sysdata = tsystem.sys
        if yfinal:
            step_info_kwargs['yfinal'] = tsystem.step_info['SteadyStateValue']

        info = step_info(sysdata, **step_info_kwargs)

        self.assert_step_info_match(tsystem.sys, info, tsystem.step_info)
예제 #12
0
    def test_step_info_mimo(self, tsystem, systype, yfinal):
        """Test step info for MIMO systems."""
        step_info_kwargs = tsystem.kwargs.get('step_info', {})
        if systype == "time response":
            tfinal = 3 * max([S['SettlingTime']
                              for Srow in tsystem.step_info for S in Srow])
            t, y = step_response(tsystem.sys, T=tfinal, T_num=5000)
            sysdata = y
            step_info_kwargs['T'] = t
        else:
            sysdata = tsystem.sys
        if yfinal:
            step_info_kwargs['yfinal'] = [[S['SteadyStateValue']
                                           for S in Srow]
                                          for Srow in tsystem.step_info]

        info_dict = step_info(sysdata, **step_info_kwargs)

        for i, row in enumerate(info_dict):
            for j, info in enumerate(row):
                self.assert_step_info_match(tsystem.sys,
                                            info, tsystem.step_info[i][j])
예제 #13
0
    def test_discrete_time_steps(self, tsystem):
        """Make sure rounding errors in sample time are handled properly

        These tests play around with the input time vector to make sure that
        small rounding errors don't generate spurious errors.

        gh-332
        """
        sys = tsystem.sys

        # Set up a time range and simulate
        T = np.arange(0, 100, 0.2)
        tout1, yout1 = step_response(sys, T)

        # Simulate every other time step
        T = np.arange(0, 100, 0.4)
        tout2, yout2 = step_response(sys, T)
        np.testing.assert_array_almost_equal(tout1[::2], tout2)
        np.testing.assert_array_almost_equal(yout1[::2], yout2)

        # Add a small error into some of the time steps
        T = np.arange(0, 100, 0.2)
        T[1:-2:2] -= 1e-12      # tweak second value and a few others
        tout3, yout3 = step_response(sys, T)
        np.testing.assert_array_almost_equal(tout1, tout3)
        np.testing.assert_array_almost_equal(yout1, yout3)

        # Add a small error into some of the time steps (w/ skipping)
        T = np.arange(0, 100, 0.4)
        T[1:-2:2] -= 1e-12      # tweak second value and a few others
        tout4, yout4 = step_response(sys, T)
        np.testing.assert_array_almost_equal(tout2, tout4)
        np.testing.assert_array_almost_equal(yout2, yout4)

        # Make sure larger errors *do* generate an error
        T = np.arange(0, 100, 0.2)
        T[1:-2:2] -= 1e-3      # change second value and a few others
        with pytest.raises(ValueError):
            step_response(sys, T)
예제 #14
0
 def test_squeeze_exception(self, fcn):
     sys = fcn(ct.rss(2, 1, 1))
     with pytest.raises(ValueError, match="Unknown squeeze value"):
         step_response(sys, squeeze=1)