Пример #1
0
    def testConvert(self):
        """Test state space to transfer function conversion."""
        verbose = self.debug
        from control.statesp import _mimo2siso
        
        #print __doc__

        # Machine precision for floats.
        eps = np.finfo(float).eps

        for states in range(1, self.maxStates):
            for inputs in range(1, self.maxIO):
                for outputs in range(1, self.maxIO):
                    # start with a random SS system and transform to TF then
                    # back to SS, check that the matrices are the same.
                    ssOriginal = matlab.rss(states, outputs, inputs)
                    if (verbose):
                        self.printSys(ssOriginal, 1)

                    # Make sure the system is not degenerate
                    Cmat = control.ctrb(ssOriginal.A, ssOriginal.B)
                    if (np.linalg.matrix_rank(Cmat) != states):
                        if (verbose):
                            print("  skipping (not reachable)")
                        continue
                    Omat = control.obsv(ssOriginal.A, ssOriginal.C)
                    if (np.linalg.matrix_rank(Omat) != states):
                        if (verbose):
                            print("  skipping (not observable)")
                        continue

                    tfOriginal = matlab.tf(ssOriginal)
                    if (verbose):
                        self.printSys(tfOriginal, 2)
                    
                    ssTransformed = matlab.ss(tfOriginal)
                    if (verbose):
                        self.printSys(ssTransformed, 3)

                    tfTransformed = matlab.tf(ssTransformed)
                    if (verbose):
                        self.printSys(tfTransformed, 4)

                    # Check to see if the state space systems have same dim
                    if (ssOriginal.states != ssTransformed.states):
                        print("WARNING: state space dimension mismatch: " + \
                            "%d versus %d" % \
                            (ssOriginal.states, ssTransformed.states))

                    # Now make sure the frequency responses match
                    # Since bode() only handles SISO, go through each I/O pair
                    # For phase, take sine and cosine to avoid +/- 360 offset
                    for inputNum in range(inputs):
                        for outputNum in range(outputs):
                            if (verbose):
                                print("Checking input %d, output %d" \
                                    % (inputNum, outputNum))
                            ssorig_mag, ssorig_phase, ssorig_omega = \
                                control.bode(_mimo2siso(ssOriginal, \
                                                        inputNum, outputNum), \
                                                 deg=False, Plot=False)
                            ssorig_real = ssorig_mag * np.cos(ssorig_phase)
                            ssorig_imag = ssorig_mag * np.sin(ssorig_phase)

                            #
                            # Make sure TF has same frequency response
                            #
                            num = tfOriginal.num[outputNum][inputNum]
                            den = tfOriginal.den[outputNum][inputNum]
                            tforig = control.tf(num, den)
                                                
                            tforig_mag, tforig_phase, tforig_omega = \
                                control.bode(tforig, ssorig_omega, \
                                                 deg=False, Plot=False)

                            tforig_real = tforig_mag * np.cos(tforig_phase)
                            tforig_imag = tforig_mag * np.sin(tforig_phase)
                            np.testing.assert_array_almost_equal( \
                                ssorig_real, tforig_real)
                            np.testing.assert_array_almost_equal( \
                                ssorig_imag, tforig_imag)

                            #
                            # Make sure xform'd SS has same frequency response
                            #
                            ssxfrm_mag, ssxfrm_phase, ssxfrm_omega = \
                                control.bode(_mimo2siso(ssTransformed, \
                                                        inputNum, outputNum), \
                                                 ssorig_omega, \
                                                 deg=False, Plot=False)
                            ssxfrm_real = ssxfrm_mag * np.cos(ssxfrm_phase)
                            ssxfrm_imag = ssxfrm_mag * np.sin(ssxfrm_phase)
                            np.testing.assert_array_almost_equal( \
                                ssorig_real, ssxfrm_real)
                            np.testing.assert_array_almost_equal( \
                                ssorig_imag, ssxfrm_imag)

                            #
                            # Make sure xform'd TF has same frequency response
                            #
                            num = tfTransformed.num[outputNum][inputNum]
                            den = tfTransformed.den[outputNum][inputNum]
                            tfxfrm = control.tf(num, den)
                            tfxfrm_mag, tfxfrm_phase, tfxfrm_omega = \
                                control.bode(tfxfrm, ssorig_omega, \
                                                 deg=False, Plot=False)
                            
                            tfxfrm_real = tfxfrm_mag * np.cos(tfxfrm_phase)
                            tfxfrm_imag = tfxfrm_mag * np.sin(tfxfrm_phase)
                            np.testing.assert_array_almost_equal( \
                                ssorig_real, tfxfrm_real)
                            np.testing.assert_array_almost_equal( \
                                ssorig_imag, tfxfrm_imag)
Пример #2
0
    def test_convert_MIMO_to_SISO(self):
        '''Convert mimo to siso systems'''
        #Test with our usual systems --------------------------------------------
        #SISO PT2 system
        As, Bs, Cs, Ds = self.make_SISO_mats()
        sys_siso = ss(As, Bs, Cs, Ds)
        #MIMO system that contains two independent copies of the SISO system above
        Am, Bm, Cm, Dm = self.make_MIMO_mats()
        sys_mimo = ss(Am, Bm, Cm, Dm)
        #    t, y = step(sys_siso)
        #    plot(t, y, label='sys_siso d=0')

        sys_siso_00 = _mimo2siso(sys_mimo,
                                 input=0,
                                 output=0,
                                 warn_conversion=False)
        sys_siso_11 = _mimo2siso(sys_mimo,
                                 input=1,
                                 output=1,
                                 warn_conversion=False)
        #print("sys_siso_00 ---------------------------------------------")
        #print(sys_siso_00)
        #print("sys_siso_11 ---------------------------------------------")
        #print(sys_siso_11)

        #gain of converted system and equivalent SISO system must be the same
        self.assert_systems_behave_equal(sys_siso, sys_siso_00)
        self.assert_systems_behave_equal(sys_siso, sys_siso_11)

        #Test with additional systems --------------------------------------------
        #They have crossed inputs and direct feedthrough
        #SISO system
        As = matrix([[-81.82, -45.45], [10., -1.]])
        Bs = matrix([[9.09], [0.]])
        Cs = matrix([[0, 0.159]])
        Ds = matrix([[0.02]])
        sys_siso = ss(As, Bs, Cs, Ds)
        #    t, y = step(sys_siso)
        #    plot(t, y, label='sys_siso d=0.02')
        #    legend(loc='best')

        #MIMO system
        #The upper left sub-system uses : input 0, output 1
        #The lower right sub-system uses: input 1, output 0
        Am = array([[-81.82, -45.45, 0, 0], [10, -1, 0, 0],
                    [0, 0, -81.82, -45.45], [
                        0,
                        0,
                        10,
                        -1,
                    ]])
        Bm = array([[9.09, 0], [0, 0], [0, 9.09], [0, 0]])
        Cm = array([[0, 0, 0, 0.159], [0, 0.159, 0, 0]])
        Dm = matrix([[0, 0.02], [0.02, 0]])
        sys_mimo = ss(Am, Bm, Cm, Dm)

        sys_siso_01 = _mimo2siso(sys_mimo,
                                 input=0,
                                 output=1,
                                 warn_conversion=False)
        sys_siso_10 = _mimo2siso(sys_mimo,
                                 input=1,
                                 output=0,
                                 warn_conversion=False)
        # print("sys_siso_01 ---------------------------------------------")
        # print(sys_siso_01)
        # print("sys_siso_10 ---------------------------------------------")
        # print(sys_siso_10)

        #gain of converted system and equivalent SISO system must be the same
        self.assert_systems_behave_equal(sys_siso, sys_siso_01)
        self.assert_systems_behave_equal(sys_siso, sys_siso_10)
Пример #3
0
def impulse_response(sys, T=None, X0=0., input=0, output=0,
                    transpose=False, **keywords):
    #pylint: disable=W0622
    """Impulse 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, 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
    --------
    ForcedReponse, initial_response, step_response

    Examples
    --------
    >>> T, yout = impulse_response(sys, T, X0) 
    """
    sys = _convertToStateSpace(sys) 
    sys = _mimo2siso(sys, input, output, warn_conversion=True)
    
    # 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, **keywords)
    return T, yout
Пример #4
0
    def testConvert(self):
        """Test state space to transfer function conversion."""
        verbose = self.debug

        # print __doc__

        # Machine precision for floats.
        # eps = np.finfo(float).eps

        for states in range(1, self.maxStates):
            for inputs in range(1, self.maxIO):
                for outputs in range(1, self.maxIO):
                    # start with a random SS system and transform to TF then
                    # back to SS, check that the matrices are the same.
                    ssOriginal = matlab.rss(states, outputs, inputs)
                    if (verbose):
                        self.printSys(ssOriginal, 1)

                    # Make sure the system is not degenerate
                    Cmat = ctrb(ssOriginal.A, ssOriginal.B)
                    if (np.linalg.matrix_rank(Cmat) != states):
                        if (verbose):
                            print("  skipping (not reachable)")
                        continue
                    Omat = obsv(ssOriginal.A, ssOriginal.C)
                    if (np.linalg.matrix_rank(Omat) != states):
                        if (verbose):
                            print("  skipping (not observable)")
                        continue

                    tfOriginal = matlab.tf(ssOriginal)
                    if (verbose):
                        self.printSys(tfOriginal, 2)

                    ssTransformed = matlab.ss(tfOriginal)
                    if (verbose):
                        self.printSys(ssTransformed, 3)

                    tfTransformed = matlab.tf(ssTransformed)
                    if (verbose):
                        self.printSys(tfTransformed, 4)

                    # Check to see if the state space systems have same dim
                    if (ssOriginal.states != ssTransformed.states):
                        print("WARNING: state space dimension mismatch: " + \
                            "%d versus %d" % \
                            (ssOriginal.states, ssTransformed.states))

                    # Now make sure the frequency responses match
                    # Since bode() only handles SISO, go through each I/O pair
                    # For phase, take sine and cosine to avoid +/- 360 offset
                    for inputNum in range(inputs):
                        for outputNum in range(outputs):
                            if (verbose):
                                print("Checking input %d, output %d" \
                                    % (inputNum, outputNum))
                            ssorig_mag, ssorig_phase, ssorig_omega = \
                                bode(_mimo2siso(ssOriginal, \
                                                        inputNum, outputNum), \
                                                 deg=False, plot=False)
                            ssorig_real = ssorig_mag * np.cos(ssorig_phase)
                            ssorig_imag = ssorig_mag * np.sin(ssorig_phase)

                            #
                            # Make sure TF has same frequency response
                            #
                            num = tfOriginal.num[outputNum][inputNum]
                            den = tfOriginal.den[outputNum][inputNum]
                            tforig = tf(num, den)

                            tforig_mag, tforig_phase, tforig_omega = \
                                bode(tforig, ssorig_omega, \
                                                 deg=False, plot=False)

                            tforig_real = tforig_mag * np.cos(tforig_phase)
                            tforig_imag = tforig_mag * np.sin(tforig_phase)
                            np.testing.assert_array_almost_equal( \
                                ssorig_real, tforig_real)
                            np.testing.assert_array_almost_equal( \
                                ssorig_imag, tforig_imag)

                            #
                            # Make sure xform'd SS has same frequency response
                            #
                            ssxfrm_mag, ssxfrm_phase, ssxfrm_omega = \
                                bode(_mimo2siso(ssTransformed, \
                                                        inputNum, outputNum), \
                                                 ssorig_omega, \
                                                 deg=False, plot=False)
                            ssxfrm_real = ssxfrm_mag * np.cos(ssxfrm_phase)
                            ssxfrm_imag = ssxfrm_mag * np.sin(ssxfrm_phase)
                            np.testing.assert_array_almost_equal( \
                            ssorig_real, ssxfrm_real)
                            np.testing.assert_array_almost_equal( \
                            ssorig_imag, ssxfrm_imag)
                            #
                            # Make sure xform'd TF has same frequency response
                            #
                            num = tfTransformed.num[outputNum][inputNum]
                            den = tfTransformed.den[outputNum][inputNum]
                            tfxfrm = tf(num, den)
                            tfxfrm_mag, tfxfrm_phase, tfxfrm_omega = \
                                bode(tfxfrm, ssorig_omega, \
                                                 deg=False, plot=False)

                            tfxfrm_real = tfxfrm_mag * np.cos(tfxfrm_phase)
                            tfxfrm_imag = tfxfrm_mag * np.sin(tfxfrm_phase)
                            np.testing.assert_array_almost_equal( \
                                ssorig_real, tfxfrm_real)
                            np.testing.assert_array_almost_equal( \
                                ssorig_imag, tfxfrm_imag)
Пример #5
0
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 test_convert_MIMO_to_SISO(self):
        '''Convert mimo to siso systems'''
        #Test with our usual systems --------------------------------------------
        #SISO PT2 system
        As, Bs, Cs, Ds = self.make_SISO_mats()
        sys_siso = ss(As, Bs, Cs, Ds)
        #MIMO system that contains two independent copies of the SISO system above
        Am, Bm, Cm, Dm = self.make_MIMO_mats()
        sys_mimo = ss(Am, Bm, Cm, Dm)
        #    t, y = step(sys_siso)
        #    plot(t, y, label='sys_siso d=0')

        sys_siso_00 = _mimo2siso(sys_mimo, input=0, output=0,
                                         warn_conversion=False)
        sys_siso_11 = _mimo2siso(sys_mimo, input=1, output=1,
                                         warn_conversion=False)
        #print("sys_siso_00 ---------------------------------------------")
        #print(sys_siso_00)
        #print("sys_siso_11 ---------------------------------------------")
        #print(sys_siso_11)

        #gain of converted system and equivalent SISO system must be the same
        self.assert_systems_behave_equal(sys_siso, sys_siso_00)
        self.assert_systems_behave_equal(sys_siso, sys_siso_11)

        #Test with additional systems --------------------------------------------
        #They have crossed inputs and direct feedthrough
        #SISO system
        As = matrix([[-81.82, -45.45],
                     [ 10.,    -1.  ]])
        Bs = matrix([[9.09],
                     [0.  ]])
        Cs = matrix([[0, 0.159]])
        Ds = matrix([[0.02]])
        sys_siso = ss(As, Bs, Cs, Ds)
        #    t, y = step(sys_siso)
        #    plot(t, y, label='sys_siso d=0.02')
        #    legend(loc='best')

        #MIMO system
        #The upper left sub-system uses : input 0, output 1
        #The lower right sub-system uses: input 1, output 0
        Am = array([[-81.82, -45.45,   0,      0   ],
                    [ 10,     -1,      0,      0   ],
                    [  0,      0,    -81.82, -45.45],
                    [  0,      0,     10,     -1,  ]])
        Bm = array([[9.09, 0   ],
                    [0   , 0   ],
                    [0   , 9.09],
                    [0   , 0   ]])
        Cm = array([[0, 0,     0, 0.159],
                    [0, 0.159, 0, 0    ]])
        Dm = matrix([[0,   0.02],
                     [0.02, 0  ]])
        sys_mimo = ss(Am, Bm, Cm, Dm)


        sys_siso_01 = _mimo2siso(sys_mimo, input=0, output=1,
                                         warn_conversion=False)
        sys_siso_10 = _mimo2siso(sys_mimo, input=1, output=0,
                                         warn_conversion=False)
        print("sys_siso_01 ---------------------------------------------")
        print(sys_siso_01)
        print("sys_siso_10 ---------------------------------------------")
        print(sys_siso_10)

        #gain of converted system and equivalent SISO system must be the same
        self.assert_systems_behave_equal(sys_siso, sys_siso_01)
        self.assert_systems_behave_equal(sys_siso, sys_siso_10)
Пример #7
0
    def testConvert(self, fixedseed, states, inputs, outputs):
        """Test state space to transfer function conversion.

        start with a random SS system and transform to TF then
        back to SS, check that the matrices are the same.
        """
        ssOriginal = rss(states, outputs, inputs)
        if verbose:
            self.printSys(ssOriginal, 1)

        # Make sure the system is not degenerate
        Cmat = ctrb(ssOriginal.A, ssOriginal.B)
        if (np.linalg.matrix_rank(Cmat) != states):
            pytest.skip("not reachable")
        Omat = obsv(ssOriginal.A, ssOriginal.C)
        if (np.linalg.matrix_rank(Omat) != states):
            pytest.skip("not observable")

        tfOriginal = tf(ssOriginal)
        if (verbose):
            self.printSys(tfOriginal, 2)

        ssTransformed = ss(tfOriginal)
        if (verbose):
            self.printSys(ssTransformed, 3)

        tfTransformed = tf(ssTransformed)
        if (verbose):
            self.printSys(tfTransformed, 4)

        # Check to see if the state space systems have same dim
        if (ssOriginal.nstates != ssTransformed.nstates) and verbose:
            print("WARNING: state space dimension mismatch: %d versus %d" %
                  (ssOriginal.nstates, ssTransformed.nstates))

        # Now make sure the frequency responses match
        # Since bode() only handles SISO, go through each I/O pair
        # For phase, take sine and cosine to avoid +/- 360 offset
        for inputNum in range(inputs):
            for outputNum in range(outputs):
                if (verbose):
                    print("Checking input %d, output %d"
                          % (inputNum, outputNum))
                ssorig_mag, ssorig_phase, ssorig_omega = \
                    bode(_mimo2siso(ssOriginal, inputNum, outputNum),
                         deg=False, plot=False)
                ssorig_real = ssorig_mag * np.cos(ssorig_phase)
                ssorig_imag = ssorig_mag * np.sin(ssorig_phase)

                #
                # Make sure TF has same frequency response
                #
                num = tfOriginal.num[outputNum][inputNum]
                den = tfOriginal.den[outputNum][inputNum]
                tforig = tf(num, den)

                tforig_mag, tforig_phase, tforig_omega = \
                    bode(tforig, ssorig_omega,
                         deg=False, plot=False)

                tforig_real = tforig_mag * np.cos(tforig_phase)
                tforig_imag = tforig_mag * np.sin(tforig_phase)
                np.testing.assert_array_almost_equal(
                    ssorig_real, tforig_real)
                np.testing.assert_array_almost_equal(
                    ssorig_imag, tforig_imag)

                #
                # Make sure xform'd SS has same frequency response
                #
                ssxfrm_mag, ssxfrm_phase, ssxfrm_omega = \
                    bode(_mimo2siso(ssTransformed,
                                    inputNum, outputNum),
                         ssorig_omega,
                         deg=False, plot=False)
                ssxfrm_real = ssxfrm_mag * np.cos(ssxfrm_phase)
                ssxfrm_imag = ssxfrm_mag * np.sin(ssxfrm_phase)
                np.testing.assert_array_almost_equal(
                    ssorig_real, ssxfrm_real, decimal=5)
                np.testing.assert_array_almost_equal(
                    ssorig_imag, ssxfrm_imag, decimal=5)

                # Make sure xform'd TF has same frequency response
                #
                num = tfTransformed.num[outputNum][inputNum]
                den = tfTransformed.den[outputNum][inputNum]
                tfxfrm = tf(num, den)
                tfxfrm_mag, tfxfrm_phase, tfxfrm_omega = \
                    bode(tfxfrm, ssorig_omega,
                         deg=False, plot=False)

                tfxfrm_real = tfxfrm_mag * np.cos(tfxfrm_phase)
                tfxfrm_imag = tfxfrm_mag * np.sin(tfxfrm_phase)
                np.testing.assert_array_almost_equal(
                    ssorig_real, tfxfrm_real, decimal=5)
                np.testing.assert_array_almost_equal(
                    ssorig_imag, tfxfrm_imag, decimal=5)
Пример #8
0
def impulse_response(sys,
                     T=None,
                     X0=0.,
                     input=0,
                     output=None,
                     transpose=False,
                     **keywords):
    #pylint: disable=W0622
    """Impulse 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, 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
    --------
    ForcedReponse, initial_response, step_response

    Examples
    --------
    >>> T, yout = impulse_response(sys, T, X0) 
    """
    sys = _convertToStateSpace(sys)
    if output == None:
        sys = _mimo2simo(sys, input, warn_conversion=True)
    else:
        sys = _mimo2siso(sys, input, output, warn_conversion=True)

    # 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, **keywords)
    return T, yout
Пример #9
0
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