Example #1
0
def ref_perfect_const_plot(G, R, wr, w_start=-2, w_end=2, axlim=None,
                           points=1000, plot_type='all'):
    """
    Use these plots to determine the constraints for perfect control in terms
    of combined reference changes. Equation 6.52 (p241) calculates the
    minimal requirement for input saturation to check in terms of set point
    tracking. A more tighter bounds is calculated with equation 6.53 (p241).

    Parameters
    ----------
    G : tf
        Plant transfer function.
    R : numpy matrix (n x n)
        Reference changes (usually diagonal with all elements larger than 1)
    wr : float
        Frequency up to witch reference tracking is required
    type_eq : string
        Type of plot:

        =========      ==================================
        plot_type      Type of plot
        =========      ==================================
        minimal        Minimal requirement, equation 6.52
        tighter        Tighter requirement, equation 6.53
        allo           All requirements
        =========      ==================================

    Returns
    -------
    Plot : matplotlib figure

    Note
    ----
    All the plots in this function needs to be larger than 1 for perfect
    control, otherwise input saturation will occur.
    """

    s, w, axlim = df.frequency_plot_setup(axlim, w_start, w_end, points)

    lab1 = '$\sigma_{min} (G(jw))$'
    bound1 = [utils.sigmas(G(si), 'min') for si in s]
    lab2 = '$\sigma_{min} (R^{-1}G(jw))$'
    bound2 = [utils.sigmas(numpy.linalg.pinv(R) * G(si), 'min') for si in s]

    if plot_type == 'all':
        plt.loglog(w, bound1, label=lab1)
        plt.loglog(w, bound2, label=lab2)
    elif plot_type == 'minimal':
        plt.loglog(w, bound1, label=lab1)
    elif plot_type == 'tighter':
        plt.loglog(w, bound2, label=lab2)

    else:
        raise ValueError('Invalid plot_type parameter.')

    mm = bound1 + bound2 + [1]  # ensures that whole graph is visible
    plt.loglog([wr, wr], [0.5 * numpy.min(mm), 5 * numpy.max(mm)],
               'r', ls=':', label='Ref tracked')
    plt.loglog([w[0], w[-1]], [1, 1], 'r', label='Bound')
    plt.legend()
Example #2
0
def uncertAnalisys():
    #Aditive uncertainty Function ==============================        
    def WA(s):
        K = 9
        ta1 = 1./0.35
        Wa = K/((ta1*s + 1))
        return(np.abs(Wa))
    #Multiplicative uncertainty Function =======================        
    def WM(s):
        tm1 = 1./0.09
        tm2 = 1./0.25
        Wm = (tm1*s + 0.2)/((tm2*s + 1))
        return(np.abs(Wm))
    def M(s):
        Ma = -WA(s) * Kc(s) * S(s)
        Mm = -WM(s) * T(s)
        return(Ma, Mm)
    w = np.logspace(-3,0,1000)
    Mat = np.zeros((len(w)))
    Mmt = np.zeros((len(w)))
    Su = np.zeros((len(w)))
    Tu = np.zeros((len(w)))
    WI = np.zeros((len(w)))
    for i in range(len(w)):
        Ma, Mm = M(w[i]*1j)
        Mat[i] = utils.sigmas(Ma)[0]
        Mmt[i] = utils.sigmas(Mm)[0]
        WI[i] = np.abs(WM(w[i]*1j))
        Su[i] = utils.sigmas(S(w[i]*1j))[0]
        Tu[i] = utils.sigmas(T(w[i]*1j))[0]
    plt.figure(8)
    plt.clf()
    plt.subplot(211)
    plt.semilogx(w, Mmt, 'r-', label = 'Multiplicative W$_O$')
    plt.semilogx(w, Mat, 'b-', label = 'Additive W$_A$')
    plt.axvline(wB_, color='blue', ls=':', lw='2')
    plt.text(wB_*1.1, np.max(Mmt)*0.9, 'req wB', color='blue')
    plt.axhline(1.0, color='blue', ls = ':', lw='2')
    plt.ylabel('Magnitude')
    plt.xlabel('Frequency [rad/s)]')
    plt.axis([None, None, None, None])
    plt.grid(True)
    plt.legend(loc='upper left', fontsize = 12, ncol=5)
    plt.subplot(212)
    plt.loglog(w, Tu, 'r-')
    plt.loglog(w, 1/WI, 'k:', lw='2')
    plt.ylabel('Magnitude')
    plt.xlabel('Frequency [rad/s)]')
    plt.axis([None, None, None, None])
    plt.text(0.2, np.max(Tu), '|T|$_{(not RS)}$', color='red')
#    plt.text(0.11, np.max(Tu)*0.4, '|T|$_{(RS)}$', color='green')
    plt.text(0.01, 5, '1/|W$_I$|')
    plt.grid(True)
    fig = plt.gcf()
    BG = fig.patch
    BG.set_facecolor('white')
    fig.subplots_adjust(bottom=0.2) 
    fig.subplots_adjust(top=0.9) 
    fig.subplots_adjust(left=0.2) 
    fig.subplots_adjust(right=0.9)   
def ref_perfect_const_plot(G, R, wr, w_start=-2, w_end=2, axlim=None,
                           points=1000, plot_type='all'):
    """
    Use these plots to determine the constraints for perfect control in terms
    of combined reference changes. Equation 6.52 (p241) calculates the
    minimal requirement for input saturation to check in terms of set point
    tracking. A more tighter bounds is calculated with equation 6.53 (p241).

    Parameters
    ----------
    G : tf
        Plant transfer function.
    R : numpy matrix (n x n)
        Reference changes (usually diagonal with all elements larger than 1)
    wr : float
        Frequency up to witch reference tracking is required
    type_eq : string
        Type of plot:

        =========      ==================================
        plot_type      Type of plot
        =========      ==================================
        minimal        Minimal requirement, equation 6.52
        tighter        Tighter requirement, equation 6.53
        allo           All requirements
        =========      ==================================

    Returns
    -------
    Plot : matplotlib figure

    Note
    ----
    All the plots in this function needs to be larger than 1 for perfect
    control, otherwise input saturation will occur.
    """

    s, w, axlim = df.frequency_plot_setup(axlim, w_start, w_end, points)

    lab1 = '$\sigma_{min} (G(jw))$'
    bound1 = [utils.sigmas(G(si), 'min') for si in s]
    lab2 = '$\sigma_{min} (R^{-1}G(jw))$'
    bound2 = [utils.sigmas(numpy.linalg.pinv(R) * G(si), 'min') for si in s]

    if plot_type == 'all':
        plt.loglog(w, bound1, label=lab1)
        plt.loglog(w, bound2, label=lab2)
    elif plot_type == 'minimal':
        plt.loglog(w, bound1, label=lab1)
    elif plot_type == 'tighter':
        plt.loglog(w, bound2, label=lab2)

    else:
        raise ValueError('Invalid plot_type parameter.')

    mm = bound1 + bound2 + [1]  # ensures that whole graph is visible
    plt.loglog([wr, wr], [0.5 * numpy.min(mm), 5 * numpy.max(mm)],
               'r', ls=':', label='Ref tracked')
    plt.loglog([w[0], w[-1]], [1, 1], 'r', label='Bound')
    plt.legend()
Example #4
0
    def subbode(A, text, crossover, labB, labP):
        Sv = numpy.zeros((len(w), dim), dtype=complex)
        f = False
        wA = 0
        for i in range(len(w)):
            Sv[i, :] = utils.sigmas(G(s[i]))
            if not f:
                if (labB == 'wC' and Sv[i, -1] < 1) or (labB == 'wB' and Sv[i, 0] > 0.707):
                    wA = w[i]
                    f = True
        ymin = numpy.min(Sv[:, -1])

        if not sv_all:
            plt.loglog(w, Sv[:, 0], 'b', label=('$\sigma_{max}(%s)$') % labP)
            plt.loglog(w, Sv[:, -1], 'g', label=('$\sigma_{min}(%s)$') % labP)
        else:
            for j in range(dim):
                plt.loglog(w, Sv[:, j], label=('$\sigma_{%s}(%s)$' % (j, labP)))
        plt.axhline(crossover, ls=':', lw=2, color='r')
        if text:
            plt.axvline(wA, ls=':', lw=2, color='r')
            plt.text(wA*1.1, ymin*1.1, labB, color='r')
        plt.axis(axlim)
        plt.grid()
        plt.xlabel('Frequency [rad/unit time]')
        plt.ylabel('$\sigma$')
        plt.legend()
        return wA
Example #5
0
def input_acceptable_const_plot(G, Gd, w_start=-2, w_end=2, axlim=None,
                                points=1000, modified=False):
    """
    Subbplots for input constraints for accepatable control. Applies equation
    6.55 (p241).

    Parameters
    ----------
    G : numpy matrix
        Plant model.
    Gd : numpy matrix
        Plant disturbance model.
    modified : boolean
        If true, the arguments in the equation are change to :math:`\sigma_1
        (G) + 1 \geq |u_i^H g_d|`. This is to avoid a negative log scale.

    Returns
    -------
    Plot : matplotlib figure

    Note
    ----
    This condition only holds for :math:`|u_i^H g_d|>1`.
    """

    s, w, axlim = df.frequency_plot_setup(axlim, w_start, w_end, points)

    freqresp = [G(si) for si in s]
    sig = numpy.array([utils.sigmas(Gfr) for Gfr in freqresp])
    one = numpy.ones(points)

    plot_No = 1

    dimGd = numpy.shape(Gd(0))[1]
    dimG = numpy.shape(G(0))[0]
    acceptable_control = numpy.zeros((dimGd, dimG, points))
    for j in range(dimGd):
        for i in range(dimG):
            for k in range(points):
                U, _, _ = utils.SVD(G(s[k]))
                acceptable_control[j, i, k] = numpy.abs(U[:, i].H *
                                                        Gd(s[k])[:, j])
            plt.subplot(dimG, dimGd, plot_No)
            if not modified:
                plt.loglog(w, sig[:, i],
                           label=('$\sigma_%s$' % (i + 1)))
                plt.plot(w, acceptable_control[j, i] - one,
                         label=('$|u_%s^H.g_{d%s}|-1$' % (i + 1, j + 1)))
            else:
                plt.loglog(w, sig[:, i] + one,
                           label=('$\sigma_%s+1$' % (i + 1)))
                plt.plot(w, acceptable_control[j, i],
                         label=('$|u_%s^H.g_{d%s}|$' % (i + 1, j + 1)))
                plt.loglog([w[0], w[-1]], [1, 1], 'r',
                           ls=':', label='Applicable')
            plt.xlabel('Frequency [rad/unit time]')
            plt.grid(True)
            plt.axis(axlim)
            plt.legend()
            plot_No += 1
Example #6
0
    def subbode(A, text, crossover, labB, labP):
        Sv = numpy.zeros((len(w), dim), dtype=complex)
        f = False
        wA = 0
        for i in range(len(w)):
            Sv[i, :] = utils.sigmas(G(s[i]))
            if not f:
                if ((labB == 'wC' and Sv[i, -1] < 1) or
                        (labB == 'wB' and Sv[i, 0] > 0.707)):
                    wA = w[i]
                    f = True
        ymin = numpy.min(Sv[:, -1])

        if not sv_all:
            plt.loglog(w, Sv[:, 0], 'b', label=('$\sigma_{max}(%s)$') % labP)
            plt.loglog(w, Sv[:, -1], 'g', label=('$\sigma_{min}(%s)$') % labP)
        else:
            for j in range(dim):
                plt.loglog(w, Sv[:, j],
                           label=('$\sigma_{%s}(%s)$' % (j, labP)))
        plt.axhline(crossover, ls=':', lw=2, color='r')
        if text:
            plt.axvline(wA, ls=':', lw=2, color='r')
            plt.text(wA*1.1, ymin*1.1, labB, color='r')
        # This function does not seem to do anything, since axlim is a list of
        # none values. See doc_func.py.frequency_spot_setup
        # plt.axis(axlim)
        plt.grid()
        plt.xlabel('Frequency [rad/unit time]')
        plt.ylabel('$\sigma$')
        plt.legend(loc=legend_loc)
        return wA
Example #7
0
    def subbode(A, text, crossover, labB, labP):
        Sv = numpy.zeros((len(w), dim), dtype=complex)
        f = False
        wA = 0
        for i in range(len(w)):
            Sv[i, :] = utils.sigmas(G(s[i]))
            if not f:
                if ((labB == 'wC' and Sv[i, -1] < 1)
                        or (labB == 'wB' and Sv[i, 0] > 0.707)):
                    wA = w[i]
                    f = True
        ymin = numpy.min(Sv[:, -1])

        if not sv_all:
            plt.loglog(w, Sv[:, 0], 'b', label=('$\sigma_{max}(%s)$') % labP)
            plt.loglog(w, Sv[:, -1], 'g', label=('$\sigma_{min}(%s)$') % labP)
        else:
            for j in range(dim):
                plt.loglog(w,
                           Sv[:, j],
                           label=('$\sigma_{%s}(%s)$' % (j, labP)))
        plt.axhline(crossover, ls=':', lw=2, color='r')
        if text:
            plt.axvline(wA, ls=':', lw=2, color='r')
            plt.text(wA * 1.1, ymin * 1.1, labB, color='r')
        plt.axis(axlim)
        plt.grid()
        plt.xlabel('Frequency [rad/unit time]')
        plt.ylabel('$\sigma$')
        plt.legend()
        return wA
def input_acceptable_const_plot(G, Gd, w_start=-2, w_end=2, axlim=None,
                                points=1000, modified=False):
    """
    Subplots for input constraints for acceptable control. Applies equation
    6.55 (p241).

    Parameters
    ----------
    G : numpy matrix
        Plant model.
    Gd : numpy matrix
        Plant disturbance model.
    modified : boolean
        If true, the arguments in the equation are changed to :math:`\sigma_1
        (G) + 1 \geq |u_i^H g_d|`. This is to avoid a negative log scale.

    Returns
    -------
    Plot : matplotlib figure

    Note
    ----
    This condition only holds for :math:`|u_i^H g_d|>1`.
    """

    s, w, axlim = df.frequency_plot_setup(axlim, w_start, w_end, points)

    freqresp = [G(si) for si in s]
    sig = numpy.array([utils.sigmas(Gfr) for Gfr in freqresp])
    one = numpy.ones(points)

    plot_No = 1

    dimGd = numpy.shape(Gd(0))[1]
    dimG = numpy.shape(G(0))[0]
    acceptable_control = numpy.zeros((dimGd, dimG, points))
    for j in range(dimGd):
        for i in range(dimG):
            for k in range(points):
                U, _, _ = utils.SVD(G(s[k]))
                acceptable_control[j, i, k] = numpy.abs(U[:, i].H *
                                                        Gd(s[k])[:, j])
            plt.subplot(dimG, dimGd, plot_No)
            if not modified:
                plt.loglog(w, sig[:, i],
                           label=('$\sigma_%s$' % (i + 1)))
                plt.plot(w, acceptable_control[j, i] - one,
                         label=('$|u_%s^H.g_{d%s}|-1$' % (i + 1, j + 1)))
            else:
                plt.loglog(w, sig[:, i] + one,
                           label=('$\sigma_%s+1$' % (i + 1)))
                plt.plot(w, acceptable_control[j, i],
                         label=('$|u_%s^H.g_{d%s}|$' % (i + 1, j + 1)))
                plt.loglog([w[0], w[-1]], [1, 1], 'r',
                           ls=':', label='Applicable')
            plt.xlabel('Frequency [rad/unit time]')
            plt.grid(True)
            plt.axis(axlim)
            plt.legend()
            plot_No += 1
Example #9
0
def distRej():
    w = np.logspace(-3,0,1000)
    S1 = np.zeros((len(w)))
    S2 = np.zeros((len(w)))
    Gd1 = np.zeros((len(w)))
    distCondNum = np.zeros((len(w)))
    condNum = np.zeros((len(w)))
    for i in range(len(w)):
        U, Sv, V = utils.SVD(S(w[i]*1j))
        S1[i] = Sv[0]                      #S = 1/|L + 1| 
        S2[i] = Sv[2]
        Gd1[i], distCondNum[i] = utils.distRej(G(w[i]*1j), Gd(w[i]*1j))
        condNum[i] = utils.sigmas(G(w[i]*1j),)[0]*utils.sigmas(la.inv(G(w[i]*1j)))[0]
    plt.figure(5)
    plt.clf()
    plt.subplot(211)
    plt.loglog(w, S1, 'r-', label = 'max $\sigma$S')
    plt.loglog(w, S2, 'r-', alpha = 0.4, label = 'min $\sigma$S')
    plt.loglog(w, Gd1, 'k-', label = '1/||Gd||$_2$')
    plt.axvline(wB, color='green')
    plt.ylabel('Magnitude')
    plt.xlabel('Frequency [rad/s)]')
    plt.text(wB*1.1, 0.015, 'wB = %s rad/s'%(np.round(wB,3)), color='green')
    plt.axis([None, None, None, 10])
    plt.grid(True)
    plt.legend(loc='upper left', fontsize = 12, ncol=5)
    fig = plt.gcf()
    BG = fig.patch
    BG.set_facecolor('white')
    plt.subplot(212)
    plt.semilogx(w, distCondNum, 'r-', label = 'Dist CondNum')
    plt.semilogx(w, condNum, 'k-', label = 'CondNum')
    plt.axvline(wB, color='green')
    plt.ylabel('Disturbance condtion number')
    plt.xlabel('Frequency [rad/s)]')
    plt.text(wB*1.1, 0.2, 'wB = %s rad/s'%(np.round(wB,3)), color='green')
    plt.axis([None, None, 0, None])
    plt.legend(loc='upper left', fontsize = 12, ncol=5)
    plt.grid(True)
    fig = plt.gcf()
    BG = fig.patch
    BG.set_facecolor('white')
    fig.subplots_adjust(bottom=0.2) 
    fig.subplots_adjust(top=0.9) 
    fig.subplots_adjust(left=0.2) 
    fig.subplots_adjust(right=0.9)
Example #10
0
def sv_plot(G, axlim=None, w_start=-2, w_end=2, points=100):
    '''
    Plot of Maximum and minimum singular values of a matirix
    
    Parameters
    ----------
    G : numpy array
        plant model or sensitivity function
              
    Returns
    -------
    fig(Max Min SV) : figure
        A figure of the maximum and minimum singular values of the matrix G
    
    Note
    ----
    Can be used with the plant matrix G and the sensitivity function S
    for controlability analysis
    '''

    if axlim is None:
        axlim = [None, None, None, None]

    w = numpy.logspace(w_start, w_end, points)
    s = w * 1j

    freqresp = map(G, s)

    plt.figure('Min Max SV')
    plt.clf()
    plt.gcf().set_facecolor('white')

    plt.semilogx(w, [utils.sigmas(Gfr)[0] for Gfr in freqresp],
                 label=('$\sigma$$_{MAX}$'),
                 color='blue')
    plt.semilogx(w, [utils.sigmas(Gfr)[-1] for Gfr in freqresp],
                 label=('$\sigma$$_{MIN}$'),
                 color='blue',
                 alpha=0.5)
    plt.xlabel('Frequency (rad/unit time)')

    plt.axhline(1., color='red', ls=':')
    plt.legend()
    plt.show()
    return
def sv_plot(G, axlim=[None, None, None, None], w_start=-2, w_end=2, points=100):
    '''
    Plot of Maximum and minimum singular values of a matirix
    
    Parameters
    ----------
    G : numpy array
        plant model or sensitivity function
              
    Returns
    -------
    fig(Max Min SV) : figure
        A figure of the maximum and minimum singular values of the matrix G
    
    Note
    ----
    Can be used with the plant matrix G and the sensitivity function S
    for controlability analysis
    '''
    w = numpy.logspace(w_start, w_end, points)
    s = w*1j    
    
    freqresp = map(G, s)
    
    plt.figure('Min Max SV')
    plt.clf()
    plt.gcf().set_facecolor('white')
    
    plt.semilogx(w, [utils.sigmas(Gfr)[0] for Gfr in freqresp], label=('$\sigma$$_{MAX}$'), color='blue')
    plt.semilogx(w, [utils.sigmas(Gfr)[-1] for Gfr in freqresp], label=('$\sigma$$_{MIN}$'), color='blue', alpha=0.5)
    plt.xlabel('Frequency (rad/unit time)')
    
    plt.axhline(1., color='red', ls=':')
    plt.legend()  
    plt.show()
    return
Example #12
0
I = np.asmatrix(np.identity(2))


def G(s):
        """process transfer matrix"""
        return 1 / ((s ** 2) + a ** 2) * np.matrix([[s - a ** 2, a * (s + 1)],
                                                    [-a * (s + 1), s - a ** 2]])


def K(s):
    """controller"""
    return I


def T(s):
    """this is a special case where T_I(s)= T(s) """
    return G(s) * K(s) * (I + G(s) * K(s)).I

frequency = np.logspace(-3, 2, 1000)
s = 1j * frequency

max_singular_value_of_T = [max(utils.sigmas(T(si))) for si in s]
mu_T = [max(np.abs(np.linalg.eigvals(T(si)))) for si in s]

plt.loglog(frequency, max_singular_value_of_T, 'b')
plt.loglog(frequency, mu_T, 'r')
plt.legend(('max_singular_value(T)', 'mu(T)'), 'best', shadow=False)
plt.xlabel('frequency')
plt.ylabel('Magnitude')
plt.show()
Example #13
0
def dis_rejctn_plot(G, Gd, S, axlim=None, w_start=-2, w_end=2, points=100):
    '''
    A subplot of disturbance conditition number to check for input saturation
    and a subplot of  to see if the disturbances fall withing the bounds on
    the singular values of S.
    Parameters
    ----------
    G : numpy array
        plant model
    
    Gd : numpy array
        plant disturbance model

    S : numpy array
        Sensitivity function
              
              
    Returns
    -------
    fig(Condition number and performance objective) : figure
        A figure of the disturbance condition number and the bounds imposed
        by the singular values.
    
    Note
    ----
    The disturbance condition number provides a measure of how a disturbance gd
    is aligned with the plant G. Alignment can vary between 1 and the condition
    number.
    
    For acceptable performance the singular values of S must fall below the
    inverse 2-norm of gd.
    '''

    if axlim is None:
        axlim = [None, None, None, None]

    w = numpy.logspace(w_start, w_end, points)
    s = w * 1j

    dim = numpy.shape(G(0))
    inv_norm_gd = numpy.zeros((dim[1], points))
    condtn_nm_gd = numpy.zeros((dim[1], points))
    for i in range(dim[1]):
        for k in range(points):
            inv_norm_gd[i, k], condtn_nm_gd[i, k] = utils.distRej(
                G(s[k]),
                Gd(s[k])[:, i])

    s_min = [utils.sigmas(S(s[i]))[-1] for i in range(points)]
    s_max = [utils.sigmas(S(s[i]))[0] for i in range(points)]

    plt.figure('Condition number and performance objective')
    plt.clf()
    plt.gcf().set_facecolor('white')

    plt.subplot(2, 1, 1)
    for i in range(dim[1]):
        plt.loglog(w,
                   condtn_nm_gd[i],
                   label=('$\gamma$$_{d%s}$(G)' % (i + 1)),
                   color='blue',
                   alpha=((i + 1.) / dim[1]))
    plt.axhline(1., color='red', ls=':')
    plt.axis(axlim)
    plt.ylabel('$\gamma$$_d$(G)')
    plt.axhline(1., color='red', ls=':')
    plt.legend()

    plt.subplot(2, 1, 2)
    for i in range(dim[1]):
        plt.loglog(w,
                   inv_norm_gd[i],
                   label=('1/||g$_{d%s}$||$_2$' % (i + 1)),
                   color='blue',
                   alpha=((i + 1.) / dim[1]))
    plt.loglog(w, s_min, label=('$\sigma$$_{MIN}$'), color='green')
    plt.loglog(w, s_max, label=('$\sigma$$_{MAX}$'), color='green', alpha=0.5)
    plt.xlabel('Frequency (rad/unit time)')
    plt.ylabel('1/||g$_d$||$_2$')
    plt.axhline(1., color='red', ls=':')
    plt.legend()

    plt.show()
    return
Example #14
0
def perfectControl():
    #For perfect cotnrol
    w = np.logspace(-3,0,1000)
    Gd1 = np.zeros((len(w)))
    Gd2 = np.zeros((len(w)))
    Gd3 = np.zeros((len(w)))
    for i in range(len(w)):
        Gt = G(w[i]*1j)                 #Gt just a temp assignmnet for G
        Gdt = Gd(w[i]*1j)               #Gdt just a temp assignmnet for Gd
#        Gd1[i] = la.norm(la.inv(Gt)*Gdt, ord=np.inf)
        Gd1[i] = utils.sigmas(la.inv(Gt)*Gdt)[0]
        Gd2[i] = utils.sigmas(la.inv(Gt)*Gdt)[1]
        Gd3[i] = utils.sigmas(la.inv(Gt)*Gdt)[2]
    plt.figure(6)
    plt.clf()
    plt.subplot(211)
    plt.semilogx(w, Gd1, 'r-', label = '|G$^{-1}$$_1$g$_d$|')
    plt.semilogx(w, Gd2, 'b-', label = '|G$^{-1}$$_2$g$_d$|')
    plt.semilogx(w, Gd3, 'k-', label = '|G$^{-1}$$_3$g$_d$|')
    plt.axvline(wB, color='green')
    plt.text(wB*1.1, np.max(Gd1), 'wB = %s rad/s'%(np.round(wB,3)), color='green')
    plt.ylabel('Magnitude')
    plt.xlabel('Frequency [rad/s)]')
    plt.axis([None, None, None, None])
    plt.grid(True)
    plt.legend(loc='upper left', fontsize = 12, ncol=1)
    fig = plt.gcf()
    BG = fig.patch
    BG.set_facecolor('white')
    fig.subplots_adjust(bottom=0.2) 
    fig.subplots_adjust(top=0.9) 
    fig.subplots_adjust(left=0.2) 
    fig.subplots_adjust(right=0.9)
    #For acceptable control
    S1 = np.zeros((len(w)))
    S2 = np.zeros((len(w)))
    S3 = np.zeros((len(w)))
    Gd1 = np.zeros((len(w)))
    Gd2 = np.zeros((len(w)))
    Gd3 = np.zeros((len(w)))
    for i in range(len(w)):
        U, Sv ,V = utils.SVD(G(w[i]*1j))
        Gdt = Gd(w[i]*1j)               #Gdt just a temp assignmnet for Gd
        S1[i] = Sv[0]
        S2[i] = Sv[1]
        S3[i] = Sv[2]
        Gd1[i] = np.max(np.abs(np.transpose(np.conj(U[0]))*Gdt) - 1)
        Gd2[i] = np.max(np.abs(np.transpose(np.conj(U[1]))*Gdt) - 1)
        Gd3[i] = np.max(np.abs(np.transpose(np.conj(U[2]))*Gdt) - 1)
    plt.subplot(212)
    plt.semilogx(w, S1, 'r-', label = '$\sigma$$_1$(G)')
    plt.semilogx(w, Gd1, 'r-', label = '|u$_1$$^H$g$_d$|', alpha = 0.4)
    plt.semilogx(w, S2, 'k-', label = '$\sigma$$_2$(G)')
    plt.semilogx(w, Gd2, 'k-', label = '|u$_2$$^H$g$_d$|', alpha = 0.4)
    plt.semilogx(w, S3, 'b-', label = '$\sigma$$_3$(G)')
    plt.semilogx(w, Gd3, 'b-', label = '|u$_3$$^H$g$_d$|', alpha = 0.4)
    plt.ylabel('Magnitude')
    plt.xlabel('Frequency [rad/s)]')
    plt.axis([None, None, None, None])
    plt.grid(True)
    plt.legend(loc='upper right', fontsize = 12)
    fig = plt.gcf()
    BG = fig.patch
    BG.set_facecolor('white')
    fig.subplots_adjust(bottom=0.2) 
    fig.subplots_adjust(top=0.9) 
    fig.subplots_adjust(left=0.2) 
    fig.subplots_adjust(right=0.9)   
Example #15
0
def dis_rejctn_plot(G,
                    Gd,
                    S=None,
                    w_start=-2,
                    w_end=2,
                    axlim=None,
                    points=1000):
    """
    A subplot of disturbance condition number to check for input saturation
    (equation 6.43, p238). Two more subplots indicate if the disturbances fall
    withing the bounds of S, applying equations 6.45 and 6.46 (p239).

    Parameters
    ----------
    G : numpy matrix
        Plant model.
    Gd : numpy matrix
        Plant disturbance model.
    S : numpy matrix
        Sensitivity function (optional, if available).
    # TODO test S condition
    Returns
    -------
    Plot : matplotlib figure

    Note
    ----
    The disturbance condition number provides a measure of how a disturbance gd
    is aligned with the plant G. Alignment can vary between 1 and the condition
    number.

    For acceptable performance the singular values of S must fall below the
    inverse 2-norm of gd.
    """

    s, w, axlim = df.frequency_plot_setup(axlim, w_start, w_end, points)

    dim = numpy.shape(Gd(0))[1]  # column count
    inv_norm_gd = numpy.zeros((dim, points))
    # row count
    yd = numpy.zeros((dim, points, numpy.shape(Gd(0))[0]), dtype=complex)
    condtn_nm_gd = numpy.zeros((dim, points))
    for i in range(dim):
        for k in range(points):
            inv_norm_gd[i, k], yd[i, k, :], condtn_nm_gd[i, k] = utils.distRej(
                G(s[k]),
                Gd(s[k])[:, i])

    if S is None:
        sub = 2
    else:
        sub = 3

    # Equation 6.43
    plt.subplot(sub, 1, 1)
    for i in range(dim):
        plt.loglog(w, condtn_nm_gd[i], label=('$\gamma_{d%s} (G)$' % (i + 1)))
    plt.axhline(1., color='red', ls=':')
    plt.axis(axlim)
    plt.xlabel('Frequency [rad/unit time]')
    plt.ylabel('$\gamma$$_d (G)$')
    plt.axhline(1., color='red', ls=':')
    plt.legend()

    # Equation 6.44
    plt.subplot(sub, 1, 2)
    for i in range(dim):
        plt.loglog(w, inv_norm_gd[i], label=('$1/||g_{d%s}||_2$' % (i + 1)))
        if S is not None:
            S_yd = numpy.array([
                numpy.linalg.norm(S(p) * yd[i, p, :].T, 2)
                for p in range(points)
            ])
            plt.loglog(w, S_yd, label='$||Sy_d||_2$')
    plt.axis(axlim)
    plt.xlabel('Frequency [rad/unit time]')
    plt.legend()

    if S is not None:  # subplot should not be repeated with S is not available
        # Equation 6.45
        plt.subplot(3, 1, 3)
        for i in range(dim):
            plt.loglog(w,
                       inv_norm_gd[i],
                       label=('$1/||g_{d%s}||_2$' % (i + 1)))
            s_min = numpy.array(
                [utils.sigmas(S(s[p]), 'min') for p in range(points)])
            s_max = numpy.array(
                [utils.sigmas(S(s[p]), 'max') for p in range(points)])
            plt.loglog(w, s_min, label='$\sigma_{min}$')
            plt.loglog(w, s_max, label='$\sigma_{max}$')
        plt.axis(axlim)
        plt.xlabel('Frequency [rad/unit time]')
        plt.legend()
Example #16
0
 def cndtn_nm(G):
     return (utils.sigmas(G)[0] / utils.sigmas(G)[-1])
Example #17
0
def dis_rejctn_plot(G, Gd, S=None, w_start=-2, w_end=2, axlim=None, points=1000):
    """
    A subplot of disturbance condition number to check for input saturation
    (equation 6.43, p238). Two more subplots indicate if the disturbances fall
    withing the bounds of S, applying equations 6.45 and 6.46 (p239).

    Parameters
    ----------
    G : numpy matrix
        Plant model.
    Gd : numpy matrix
        Plant disturbance model.
    S : numpy matrix
        Sensitivity function (optional, if available).
    # TODO test S condition
    Returns
    -------
    Plot : matplotlib figure

    Note
    ----
    The disturbance condition number provides a measure of how a disturbance gd
    is aligned with the plant G. Alignment can vary between 1 and the condition
    number.

    For acceptable performance the singular values of S must fall below the
    inverse 2-norm of gd.
    """

    s, w, axlim = df.frequency_plot_setup(axlim, w_start, w_end, points)

    dim = numpy.shape(Gd(0))[1]  # column count
    inv_norm_gd = numpy.zeros((dim, points))
    yd = numpy.zeros((dim, points, numpy.shape(Gd(0))[0]), dtype=complex)  # row count
    condtn_nm_gd = numpy.zeros((dim, points))
    for i in range(dim):
        for k in range(points):
            inv_norm_gd[i, k], yd[i, k, :], condtn_nm_gd[i, k] = utils.distRej(G(s[k]), Gd(s[k])[:, i])

    if S is None:
        sub = 2
    else:
        sub = 3

    # Equation 6.43
    plt.subplot(sub, 1, 1)
    for i in range(dim):
        plt.loglog(w, condtn_nm_gd[i], label=('$\gamma_{d%s} (G)$' % (i+1)))
    plt.axhline(1., color='red', ls=':')
    plt.axis(axlim)
    plt.xlabel('Frequency [rad/unit time]')
    plt.ylabel('$\gamma$$_d (G)$')
    plt.axhline(1., color='red', ls=':')
    plt.legend()

    # Equation 6.44
    plt.subplot(sub, 1, 2)
    for i in range(dim):
        plt.loglog(w, inv_norm_gd[i], label=('$1/||g_{d%s}||_2$' % (i+1)))
        if not S is None:
            S_yd = numpy.array([numpy.linalg.norm(S(p) * yd[i, p, :].T, 2) for p in range(points)])
            plt.loglog(w, S_yd, label='$||Sy_d||_2$')
    plt.axis(axlim)
    plt.xlabel('Frequency [rad/unit time]')
    plt.legend()

    if S is not None:  # this subplot should not be repeated with S is not available
        # Equation 6.45
        plt.subplot(3, 1, 3)
        for i in range(dim):
            plt.loglog(w, inv_norm_gd[i], label=('$1/||g_{d%s}||_2$' % (i+1)))
            s_min = numpy.array([utils.sigmas(S(s[p]), 'min') for p in range(points)])
            s_max = numpy.array([utils.sigmas(S(s[p]), 'max') for p in range(points)])
            plt.loglog(w, s_min, label='$\sigma_{min}$')
            plt.loglog(w, s_max, label='$\sigma_{max}$')
        plt.axis(axlim)
        plt.xlabel('Frequency [rad/unit time]')
        plt.legend()
Example #18
0
def condition_number(G):
    """Function to determine condition number"""
    sig = utils.sigmas(G)
    return max(sig) / min(sig)
Example #19
0
 def cndtn_nm(G):
     return utils.sigmas(G)[0]/utils.sigmas(G)[-1]
def condition_number(G):
    """Function to determine condition number"""
    sig = utils.sigmas(G)
    return max(sig) / min(sig)
def maxsigma(G):
    return max(utils.sigmas(G))
Example #22
0
def maxsigma(G):
    return max(utils.sigmas(G))
def dis_rejctn_plot(G, Gd, S, axlim=[None, None, None, None], w_start=-2, w_end=2, points=100):
    '''
    A subplot of disturbance conditition number to check for input saturation
    and a subplot of  to see if the disturbances fall withing the bounds on
    the singular values of S.
    Parameters
    ----------
    G : numpy array
        plant model
    
    Gd : numpy array
        plant disturbance model

    S : numpy array
        Sensitivity function
              
              
    Returns
    -------
    fig(Condition number and performance objective) : figure
        A figure of the disturbance condition number and the bounds imposed
        by the singular values.
    
    Note
    ----
    The disturbance condition number provides a measure of how a disturbance gd
    is aligned with the plant G. Alignment can vary between 1 and the condition
    number.
    
    For acceptable performance the singular values of S must fall below the
    inverse 2-norm of gd.
    '''
    w = numpy.logspace(w_start, w_end, points)
    s = w*1j
    
    dim = numpy.shape(G(0))    
    inv_norm_gd = numpy.zeros((dim[1],points))
    condtn_nm_gd = numpy.zeros((dim[1],points))
    for i in range(dim[1]):
        for k in range(points):
            inv_norm_gd[i,k], condtn_nm_gd[i,k] = utils.distRej(G(s[k]), Gd(s[k])[:,i])
                      
    s_min = [utils.sigmas(S(s[i]))[-1] for i in range(points)]
    s_max = [utils.sigmas(S(s[i]))[0] for i in range(points)]
    
    plt.figure('Condition number and performance objective')
    plt.clf()
    plt.gcf().set_facecolor('white')
    
    plt.subplot(2,1,1)
    for i in range(dim[1]):
        plt.loglog(w, condtn_nm_gd[i], label=('$\gamma$$_{d%s}$(G)' % (i+1)), color='blue', alpha=((i+1.)/dim[1]))
    plt.axhline(1., color='red', ls=':')  
    plt.axis(axlim)
    plt.ylabel('$\gamma$$_d$(G)')
    plt.axhline(1., color='red', ls=':')
    plt.legend()
    
    plt.subplot(2,1,2)
    for i in range(dim[1]):
        plt.loglog(w, inv_norm_gd[i], label=('1/||g$_{d%s}$||$_2$' % (i+1)), color='blue', alpha=((i+1.)/dim[1]))   
    plt.loglog(w, s_min, label=('$\sigma$$_{MIN}$'), color='green')
    plt.loglog(w, s_max, label=('$\sigma$$_{MAX}$'), color='green', alpha = 0.5)  
    plt.xlabel('Frequency (rad/unit time)')
    plt.ylabel('1/||g$_d$||$_2$')
    plt.axhline(1., color='red', ls=':')
    plt.legend()    
    
    plt.show()
    return