Пример #1
0
def sv_dir_plot(G, plot_type, w_start=-2, w_end=2, axlim=None, points=1000):
    """
    Plot the input and output singular vectors associated with the minimum and
    maximum singular values.

    Parameters
    ----------
    G : matrix
        Plant model or sensitivity function.
    plot_type : string
        Type of plot.

        =========      ============================
        plot_type      Type of plot
        =========      ============================
        input          Plots input vectors
        output         Plots output vectors
        =========      ============================

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

    Note
    ----
    Can be used with the plant matrix G and the sensitivity function S
    for controlability analysis
    """

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

    freqresp = [G(si) for si in s]

    if plot_type == 'input':
        vec = numpy.array([V for _, _, V in map(utils.SVD, freqresp)])
        d = 'v'
    elif plot_type == 'output':
        vec = numpy.array([U for U, _, _ in map(utils.SVD, freqresp)])
        d = 'u'
    else:
        raise ValueError('Invalid plot_type parameter.')

    dim = numpy.shape(vec)[1]
    for i in range(dim):
        plt.subplot(dim*2, 1, 2*i + 1)
        plt.semilogx(w, abs(vec[:, i, 0]), label='$%s_{max}$' % d, lw=2)
        plt.semilogx(w, abs(vec[:, i, -1]), label='$%s_{min}$' % d, lw=2)
        plt.axhline(0, color='red', ls=':')
        plt.axis(axlim)
        plt.ylabel('$|{0}_{1}|$'.format(d, i + 1))
        plt.subplot(dim*2, 1, 2*i + 2)
        plt.semilogx(w, utils.phase(vec[:, i, 0], deg=True), label='$%s_{max}$' % d, lw=2)
        plt.semilogx(w, utils.phase(vec[:, i, -1], deg=True), label='$%s_{min}$' % d, lw=2)
        plt.axhline(0, color='red', ls=':')
        plt.axis(axlim)
        plt.ylabel(r'$\angle {0}_{1}$'.format(d, i + 1))

    plt.xlabel('Frequency [rad/unit time]')
Пример #2
0
def sv_dir_plot(G, plot_type, w_start=-2, w_end=2, axlim=None, points=1000):
    """
    Plot the input and output singular vectors associated with the minimum and
    maximum singular values.

    Parameters
    ----------
    G : matrix
        Plant model or sensitivity function.
    plot_type : string
        Type of plot.

        =========      ============================
        plot_type      Type of plot
        =========      ============================
        input          Plots input vectors
        output         Plots output vectors
        =========      ============================

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

    Note
    ----
    Can be used with the plant matrix G and the sensitivity function S
    for controlability analysis
    """

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

    freqresp = [G(si) for si in s]

    if plot_type == 'input':
        vec = numpy.array([V for _, _, V in map(utils.SVD, freqresp)])
        d = 'v'
    elif plot_type == 'output':
        vec = numpy.array([U for U, _, _ in map(utils.SVD, freqresp)])
        d = 'u'
    else:
        raise ValueError('Invalid plot_type parameter.')

    dim = numpy.shape(vec)[1]
    for i in range(dim):
        plt.subplot(dim*2, 1, 2*i + 1)
        plt.semilogx(w, abs(vec[:, i, 0]), label='$%s_{max}$' % d, lw=2)
        plt.semilogx(w, abs(vec[:, i, -1]), label='$%s_{min}$' % d, lw=2)
        plt.axhline(0, color='red', ls=':')
        plt.axis(axlim)
        plt.ylabel('$|{0}_{1}|$'.format(d, i + 1))
        plt.subplot(dim*2, 1, 2*i + 2)
        plt.semilogx(w, utils.phase(vec[:, i, 0], deg=True), label='$%s_{max}$' % d, lw=2)
        plt.semilogx(w, utils.phase(vec[:, i, -1], deg=True), label='$%s_{min}$' % d, lw=2)
        plt.axhline(0, color='red', ls=':')
        plt.axis(axlim)
        plt.ylabel(r'$\angle {0}_{1}$'.format(d, i + 1))

    plt.xlabel('Frequency [rad/unit time]')
Пример #3
0
def bodeclosedloop(G,
                   K,
                   w_start=-2,
                   w_end=2,
                   axlim=None,
                   points=1000,
                   margin=False):
    """ 
    Shows the bode plot for a controller model
    
    Parameters
    ----------
    G : tf
        Plant transfer function.     
    K : tf
        Controller transfer function.    
    margin : boolean
        Show the cross over frequencies on the plot (optional).
    """

    if axlim is None:
        axlim = [None, None, None, None]
    plt.gcf().set_facecolor('white')

    w = numpy.logspace(w_start, w_end, points)
    L = G(1j * w) * K(1j * w)
    S = utils.feedback(1, L)
    T = utils.feedback(L, 1)

    plt.subplot(2, 1, 1)
    plt.loglog(w, abs(L))
    plt.loglog(w, abs(S))
    plt.loglog(w, abs(T))
    plt.axis(axlim)
    plt.grid()
    plt.ylabel("Magnitude")
    plt.legend(["L", "S", "T"])

    if margin:
        plt.plot(w, 1 / numpy.sqrt(2) * numpy.ones(len(w)), linestyle='dotted')

    plt.subplot(2, 1, 2)
    plt.semilogx(w, utils.phase(L, deg=True))
    plt.semilogx(w, utils.phase(S, deg=True))
    plt.semilogx(w, utils.phase(T, deg=True))
    plt.axis(axlim)
    plt.grid()
    plt.ylabel("Phase")
    plt.xlabel("Frequency [rad/s]")
Пример #4
0
def Bode(G):
    """give the Bode plot along with GM and PM"""

    GM, PM, wc, w_180 = margins(G)

    # plotting of Bode plot and with corresponding freqeuncies for PM and GM
    w = np.logspace(-5, np.log(w_180), 1000)
    s = 1j*w

    plt.subplot(211)
    gains = np.abs(G(s))
    plt.loglog(w, gains)
    plt.loglog(wc*np.ones(2), [np.max(gains), np.min(gains)])
    plt.text(w_180, np.average([np.max(gains), np.min(gains)]), '<G(jw) = -180 Deg')
    plt.loglog(w_180*np.ones(2), [np.max(gains), np.min(gains)])
    plt.loglog(w, 1*np.ones(len(w)))

    # argument of G
    plt.subplot(212)
    phaseangle = phase(G(s), deg=True)
    plt.semilogx(w, phaseangle)
    plt.semilogx(wc*np.ones(2), [np.max(phaseangle), np.min(phaseangle)])
    plt.semilogx(w_180*np.ones(2), [-180, 0])
    plt.show()

    return GM, PM
Пример #5
0
def Bode(G):
    """give the Bode plot along with GM and PM"""

    GM, PM, wc, w_180 = margins(G)

    # plotting of Bode plot and with corresponding freqeuncies for PM and GM
    w = np.logspace(-5, np.log(w_180), 1000)
    s = 1j*w

    plt.subplot(211)
    gains = np.abs(G(s))
    plt.loglog(w, gains)
    plt.loglog(wc*np.ones(2), [np.max(gains), np.min(gains)])
    plt.text(w_180, np.average([np.max(gains), np.min(gains)]), '<G(jw) = -180 Deg')
    plt.loglog(w_180*np.ones(2), [np.max(gains), np.min(gains)])
    plt.loglog(w, 1*np.ones(len(w)))

    # argument of G
    plt.subplot(212)
    phaseangle = phase(G(s), deg=True)
    plt.semilogx(w, phaseangle)
    plt.semilogx(wc*np.ones(2), [np.max(phaseangle), np.min(phaseangle)])
    plt.semilogx(w_180*np.ones(2), [-180, 0])
    plt.show()

    return GM, PM
Пример #6
0
def bode(G, w_start=-2, w_end=2, axlim=None, points=1000, margin=False):
    """
    Shows the bode plot for a plant model

    Parameters
    ----------
    G : tf
        Plant transfer function.
    margin : boolean
        Show the cross over frequencies on the plot (optional).

    Returns
    -------
    GM : array containing a real number
        Gain margin.
    PM : array containing a real number
        Phase margin.
    Plot : matplotlib figure
    """

    if axlim is None:
        axlim = [None, None, None, None]
    plt.clf()
    plt.gcf().set_facecolor('white')

    GM, PM, wc, w_180 = utils.margins(G)

    # plotting of Bode plot and with corresponding frequencies for PM and GM
#    if ((w2 < numpy.log(w_180)) and margin):
#        w2 = numpy.log(w_180)
    w = numpy.logspace(w_start, w_end, points)
    s = 1j*w

    # Magnitude of G(jw)
    plt.subplot(2, 1, 1)
    gains = numpy.abs(G(s))
    plt.loglog(w, gains)
    if margin:
        plt.axvline(w_180, color='black')
        plt.text(w_180, numpy.average([numpy.max(gains), numpy.min(gains)]), r'$\angle$G(jw) = -180$\degree$')
    plt.axhline(1., color='red', linestyle='--')
    plt.axis(axlim)
    plt.grid()
    plt.ylabel('Magnitude')

    # Phase of G(jw)
    plt.subplot(2, 1, 2)
    phaseangle = utils.phase(G(s), deg=True)
    plt.semilogx(w, phaseangle)
    if margin:
        plt.axvline(wc, color='black')
        plt.text(wc, numpy.average([numpy.max(phaseangle), numpy.min(phaseangle)]), '|G(jw)| = 1')
    plt.axhline(-180., color='red', linestyle='--')
    plt.axis(axlim)
    plt.grid()
    plt.ylabel('Phase')
    plt.xlabel('Frequency [rad/unit time]')

    return GM, PM
Пример #7
0
def bode(G, w_start=-2, w_end=2, axlim=None, points=1000, margin=False):
    """
    Shows the bode plot for a plant model

    Parameters
    ----------
    G : tf
        Plant transfer function.
    margin : boolean
        Show the cross over frequencies on the plot (optional).

    Returns
    -------
    GM : array containing a real number
        Gain margin.
    PM : array containing a real number
        Phase margin.
    Plot : matplotlib figure
    """

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

    GM, PM, wc, w_180 = utils.margins(G)

    # plotting of Bode plot and with corresponding frequencies for PM and GM
    #    if ((w2 < numpy.log(w_180)) and margin):
    #        w2 = numpy.log(w_180)

    # Magnitude of G(jw)
    plt.subplot(2, 1, 1)
    gains = numpy.abs(G(s))
    plt.loglog(w, gains)
    if margin:
        plt.axvline(w_180, color='black')
        plt.text(w_180, numpy.average([numpy.max(gains),
                                       numpy.min(gains)]),
                 r'$\angle$G(jw) = -180$\degree$')
    plt.axhline(1., color='red', linestyle='--')
    plt.axis(axlim)
    plt.grid()
    plt.ylabel('Magnitude')

    # Phase of G(jw)
    plt.subplot(2, 1, 2)
    phaseangle = utils.phase(G(s), deg=True)
    plt.semilogx(w, phaseangle)
    if margin:
        plt.axvline(wc, color='black')
        plt.text(wc,
                 numpy.average([numpy.max(phaseangle),
                                numpy.min(phaseangle)]), '|G(jw)| = 1')
    plt.axhline(-180., color='red', linestyle='--')
    plt.axis(axlim)
    plt.grid()
    plt.ylabel('Phase')
    plt.xlabel('Frequency [rad/unit time]')

    return GM, PM
Пример #8
0
def bodeclosedloop(G, K, w_start=-2, w_end=2, axlim=None, points=1000, margin=False):
    """
    Shows the bode plot for a controller model

    Parameters
    ----------
    G : tf
        Plant transfer function.
    K : tf
        Controller transfer function.
    margin : boolean
        Show the cross over frequencies on the plot (optional).
    """

    if axlim is None:
        axlim = [None, None, None, None]
    plt.gcf().set_facecolor('white')

    w = numpy.logspace(w_start, w_end, points)
    L = G(1j*w) * K(1j*w)
    S = utils.feedback(1, L)
    T = utils.feedback(L, 1)

    plt.subplot(2, 1, 1)
    plt.loglog(w, abs(L))
    plt.loglog(w, abs(S))
    plt.loglog(w, abs(T))
    plt.axis(axlim)
    plt.grid()
    plt.ylabel("Magnitude")
    plt.legend(["L", "S", "T"])

    if margin:
        plt.plot(w, 1/numpy.sqrt(2) * numpy.ones(len(w)), linestyle='dotted')

    plt.subplot(2, 1, 2)
    plt.semilogx(w, utils.phase(L, deg=True))
    plt.semilogx(w, utils.phase(S, deg=True))
    plt.semilogx(w, utils.phase(T, deg=True))
    plt.axis(axlim)
    plt.grid()
    plt.ylabel("Phase")
    plt.xlabel("Frequency [rad/s]")
Пример #9
0
def Rule_7(w_start, w_end):
    # Rule 7 determining the phase of GGm at -180 deg.
    # This is solved visually from a plot.

    w = np.logspace(w_start, w_end, 1000)

    Pz = np.polymul(G()[0], Gm()[0])
    Pp = np.polymul(G()[1], Gm()[1])
    [w, h] = scs.freqs(Pz, Pp, w)

    plt.semilogx(w, (180 / np.pi) * (phase(h) + w * Time_Delay()))
    plt.show()
Пример #10
0
def Rule_7(w_start, w_end):
    # Rule 7 determining the phase of GGm at -180deg
    # this is solved visually from a plot

    w = np.logspace(w_start, w_end, 1000)

    Pz = np.polymul(G()[0], Gm()[0])
    Pp = np.polymul(G()[1], Gm()[1])
    [w, h] = scs.freqs(Pz, Pp, w)

    plt.semilogx(w, (180 / np.pi) * (phase(h) + w * Time_Delay()))
    plt.show()
Пример #11
0
def Bode_Parametrized(f="8/((s+8)*(s+1))", startBaseFreq=-5, endBaseFreq=37):
    """Give the Bode plot for a given plant f in string format (e.g. 8/((s+8)*(s+1))).
       If no argument is provided the example is the default value of f.
       The starting frequency and ending frequencies for the plot are provided as minFreq and maxFreq."""

    def mod(x):
        """to give the function to calculate |G(jw)| = 1"""
        return np.abs(G(f, x)) - 1

    # how to calculate the frequency at which |G(jw)| = 1
    wc = sc.optimize.fsolve(mod, 0.1)

    def arg(w):
        """function to calculate the phase angle at -180 deg"""
        return np.angle(G(f, w)) + np.pi

    # where the frequency is calculated where arg G(jw) = -180 deg
    w_180 = sc.optimize.fsolve(arg, -1)

    # Plotting of gain Bode plot
    w = np.logspace(startBaseFreq, endBaseFreq, num=1000)

    #Set up the plot
    fig = plt.figure()
    plt.subplot(211)
    plt.loglog(w, np.abs(G(f, w)))
    #Plot the line for the unit gain
    plt.loglog(w, np.ones(1000), 'r--')
    plt.ylabel("Magnitude")
    plt.title("Figure 2.2: Frequency response (Bode plots) of G(s) = " + f + "\n ", fontsize=12)  # \n for a newline so that it doesn't hog the top of the graph.
    #Set the axis to the w range - adds in some x-space otherwise, sucks...
    plt.xlim(10.0**startBaseFreq, 10.0**endBaseFreq)

    # Plotting of phase Bode plot
    plt.subplot(212)
    phaseangle = phase(G(f, w), deg=True)
    plt.semilogx(w, phaseangle)
    plt.semilogx(w, -180 * np.ones(1000), 'r--')
    #Set the axis to the w range - adds in some x-space otherwise, sucks...
    plt.xlim(10.0**startBaseFreq, 10.0**endBaseFreq)
    plt.ylabel("Phase")
    plt.xlabel("Frequency [rad/s]")

    plt.show()

    return fig
Пример #12
0
def Bode():
    """give the Bode plot along with GM and PM"""

    def mod(x):
        """to give the function to calculate |G(jw)| = 1"""
        return np.abs(G(x)) - 1

    # how to calculate the freqeuncy at which |G(jw)| = 1
    wc = sc.optimize.fsolve(mod, 0.1)

    def arg(w):
        """function to calculate the phase angle at -180 deg"""
        return np.angle(G(w)) + np.pi

    # where the freqeuncy is calculated where arg G(jw) = -180 deg
    w_180 = sc.optimize.fsolve(arg, -1)

    PM = np.angle(G(wc), deg=True) + 180
    GM = 1/(np.abs(G(w_180)))

    # plotting of Bode plot and with corresponding freqeuncies for PM and GM
    w = np.logspace(-5, np.log(w_180), 1000)
    plt.subplot(211)
    plt.loglog(w, np.abs(G(w)))
    plt.loglog(wc*np.ones(2), [np.max(np.abs(G(w))), np.min(np.abs(G(w)))])
    plt.text(w_180, np.average([np.max(np.abs(G(w))), np.min(np.abs(G(w)))]), '<G(jw) = -180 Deg')
    plt.loglog(w_180*np.ones(2), [np.max(np.abs(G(w))), np.min(np.abs(G(w)))])
    plt.loglog(w, 1*np.ones(len(w)))

    # argument of G
    plt.subplot(212)
    phaseangle = phase(G(w), deg=True)
    plt.semilogx(w, phaseangle)
    plt.semilogx(wc*np.ones(2), [np.max(phaseangle), np.min(phaseangle)])
    plt.semilogx(w_180*np.ones(2), [-180, 0])
    plt.show()

    return GM, PM
Пример #13
0
Kc = 0.05
#plant model
G = 3*(-2*s+1)/((10*s+1)*(5*s+1))
#Controller model
K = Kc*(10*s+1)*(5*s+1)/(s*(2*s+1)*(0.33*s+1))
#closed-loop transfer function
L = G*K

#magnitude and phase
plt.subplot(2, 1, 1)
plt.loglog(w, abs(L(wi)))
plt.loglog(w, np.ones_like(w))
plt.ylabel('Magnitude')

plt.subplot(2, 1, 2)
plt.semilogx(w, phase(L(wi), deg=True))
plt.semilogx(w, -180*np.ones_like(w))
plt.ylabel('Phase')
plt.xlabel('frequency (rad/s)')
plt.figure()

# From the figure we can calculate GM and PM,
# cross-over frequency wc and w180
# results:GM = 1/0.354 = 2.82
#         PM = -125.3 + 180 = 54 degC
#         w180 = 0.44
#         wc = 0.15

#Response to step in reference for loop shaping design
#y = Tr, r(t) = 1 for t > 0
Пример #14
0
s = w*1j
K = Kc*(1+1/(Tauc*s))
G = 3*(-2*(s)+1)/((10*s+1)*(5*s+1))
L = G*K
S = feedback(1, L)
T = feedback(L, 1)

plt.subplot(2, 1, 1)
plt.loglog(w, abs(L))
plt.loglog(w, abs(S))
plt.loglog(w, abs(T))
plt.ylabel("Magnitude")
plt.legend(["L", "S", "T"],
           bbox_to_anchor=(0, 1.01, 1, 0), loc=3, ncol=3)
plt.subplot(2, 1, 2)
plt.semilogx(w, phase(L, deg=True))
plt.semilogx(w, phase(S, deg=True))
plt.semilogx(w, phase(T, deg=True))
plt.ylabel("Phase")
plt.xlabel("Frequency [rad/s]")


# Calculate the frequency at which |L(jw)| = 1
wc = w[np.flatnonzero(np.abs(L) < 1)[0]]

# Calculate the frequency at which Angle[L(jw)] = -180


def Lu_180(w):
    s = w*1j
    G = 3*(-2*(s)+1)/((10*s+1)*(5*s+1))
Пример #15
0
w = np.logspace(-2, 1, 1000)
s = w*1j
kc = 0.05
#plant model
G = 3*(-2*s+1)/((10*s+1)*(5*s+1))
#Controller model
K = kc*(10*s+1)*(5*s+1)/(s*(2*s+1)*(0.33*s+1))
#closed-loop transfer function
L = G*K

#magnitude and phase
plt.subplot(2, 1, 1)
plt.loglog(w, abs(L))
plt.loglog(w, 1*np.ones(len(w)))
plt.ylabel('Magnitude')

plt.subplot(2, 1, 2)
plt.semilogx(w, phase(L, deg=True))
plt.semilogx(w, (-180)*np.ones(len(w)))
plt.ylabel('Phase')
plt.xlabel('frequency (rad/s)')
plt.show()

# From the figure we can calculate GM and PM,
# cross-over frequency wc and w180
# results:GM = 1/0.354 = 2.82
#         PM = -125.3 + 180 = 54 degC
#         w180 = 0.44
#         wc = 0.15
Пример #16
0
Kc = 1.25
tau1 = 1.5
K = Kc * (1 + 1 / (tau1 * s))
L = K * G
S = feedback(1, L)
T = feedback(L, 1)

#Bode magnitude and phase plot - Figure 2.15
plt.subplot(2, 1, 1)
plt.loglog(w, abs(L))
plt.loglog(w, abs(S))
plt.loglog(w, abs(T))
plt.ylabel("Magnitude")
plt.legend(["L", "S", "T"], bbox_to_anchor=(0, 1.01, 1, 0), loc=3, ncol=3)
plt.subplot(2, 1, 2)
plt.semilogx(w, phase(L, deg=True))
plt.semilogx(w, phase(S, deg=True))
plt.semilogx(w, phase(T, deg=True))
plt.semilogx(w, (-180) * np.ones(len(w)))
plt.ylabel("Phase")
plt.xlabel("Frequency [rad/s]")

# Calculate the frequency at which |L(jw)| = 1
wc = w[np.flatnonzero(np.abs(L) < 1)[0]]


# Calculate the frequency at which Angle[L(jw)] = -180
def Lu_180(w):
    s = w * 1j
    G = 4 / ((s - 1) * (0.02 * s + 1)**2)
    Kc = 1.25
Пример #17
0
Kc = 0.05
#plant model
G = 3 * (-2 * s + 1) / ((10 * s + 1) * (5 * s + 1))
#Controller model
K = Kc * (10 * s + 1) * (5 * s + 1) / (s * (2 * s + 1) * (0.33 * s + 1))
#closed-loop transfer function
L = G * K

#magnitude and phase
plt.subplot(2, 1, 1)
plt.loglog(w, abs(L(wi)))
plt.axhline(1)
plt.ylabel('Magnitude')

plt.subplot(2, 1, 2)
plt.semilogx(w, phase(L(wi), deg=True))
plt.axhline(-180)
plt.ylabel('Phase')
plt.xlabel('frequency (rad/s)')
plt.figure()

# From the figure we can calculate GM and PM,
# cross-over frequency wc and w180
# results:GM = 1/0.354 = 2.82
#         PM = -125.3 + 180 = 54 degC
#         w180 = 0.44
#         wc = 0.15

#Response to step in reference for loop shaping design
#y = Tr, r(t) = 1 for t > 0
Пример #18
0
 def G_GM(w):
     Pz = np.polymul(G()[0], Gm()[0])
     Pp = np.polymul(G()[1], Gm()[1])
     G_w = scs.freqs(Pz, Pp, w)[1]
     return np.abs(phase(G_w))-np.pi
Пример #19
0
def RULES(R, wr):


    # rule 1 wc>wd

    def Gd_mod_1(w):
        return np.abs(scs.freqs(Gd()[0], Gd()[1], w)[1])-1

    wd = sc.optimize.fsolve(Gd_mod_1, 10)

    wc_min_1 = wd


    # rule 2



    # rule 3



    # for perfect control

    def G_Gd_1(w):
        f = scs.freqs(G()[0], G()[1], w)[1]
        g = scs.freqs(Gd()[0], Gd()[1], w)[1]
        return np.abs(f)-np.abs(g)

    w_G_Gd = sc.optimize.fsolve(G_Gd_1, 0.001)

    plt.figure(1)
    if np.abs(scs.freqs(G()[0], G()[1], [w_G_Gd+0.0001])[1])>np.abs(scs.freqs(Gd()[0], Gd()[1], [w_G_Gd+0.0001])[1]):
        print "Acceptable control"
        print "control only at high frequencies", w_G_Gd, "< w < inf"

        w = np.logspace(-3, np.log10(w_G_Gd), 100)
        plt.loglog(w, np.abs(scs.freqs(G()[0], G()[1], w)[1]), 'r')
        plt.loglog(w, np.abs(scs.freqs(Gd()[0], Gd()[1], w)[1]), 'r.')

        max_p = np.max([np.abs(scs.freqs(G()[0], G()[1], w)[1]), np.abs(scs.freqs(Gd()[0], Gd()[1], w)[1])])

        w = np.logspace(np.log10(w_G_Gd), 5, 100)
        plt.loglog(w, np.abs(scs.freqs(G()[0], G()[1], w)[1]), 'b')
        plt.loglog(w, np.abs(scs.freqs(Gd()[0], Gd()[1], w)[1]), 'b.')

        min_p = np.min([np.abs(scs.freqs(G()[0], G()[1], w)[1]), np.abs(scs.freqs(Gd()[0], Gd()[1], w)[1])])

    if np.abs(scs.freqs(G()[0], G()[1], [w_G_Gd-0.0001])[1])>= np.abs(scs.freqs(Gd()[0], Gd()[1], [w_G_Gd-0.0001])[1]):
        print "Acceptable control"
        print "control up to frequency 0 < w < ", w_G_Gd

        w = np.logspace(-3, np.log10(w_G_Gd), 100)
        plt.loglog(w, np.abs(scs.freqs(G()[0], G()[1], w)[1]), 'b')
        plt.loglog(w, np.abs(scs.freqs(Gd()[0], Gd()[1], w)[1]), 'b.')

        max_p = np.max([np.abs(scs.freqs(G()[0], G()[1], w)[1]), np.abs(scs.freqs(Gd()[0], Gd()[1], w)[1])])

        w = np.logspace(np.log10(w_G_Gd), 5, 100)
        plt.loglog(w, np.abs(scs.freqs(G()[0], G()[1], w)[1]), 'r')
        plt.loglog(w, np.abs(scs.freqs(Gd()[0], Gd()[1], w)[1]), 'r.')


        min_p = np.min([np.abs(scs.freqs(G()[0], G()[1], w)[1]), np.abs(scs.freqs(Gd()[0], Gd()[1], w)[1])])


    plt.loglog(w_G_Gd*np.ones(2), [max_p, min_p], 'g')


    # rule 4



    # rule 5
    # critical freqeuncy of controller needs to smaller than
    wc_5 = Time_Delay()[0]/2.0000


    # rule 6
    # control over RHP zeros

    Pz_G_Gm = np.polymul(G()[0], Gm()[0])

    if len(Pz_G_Gm) == 1:
        wc_6 = wc_5
    else:
        Pz_roots = np.roots(Pz_G_Gm)
        print Pz_roots
        if np.real(np.max(Pz_roots))>0:

            if np.imag(np.min(Pz_roots)) == 0:
                # it the roots aren't imagenary
                # looking for the minimum values of the zeros = > results in the tightest control
                wc_6 = (np.min(np.abs(Pz_roots)))/2.000

            else:
                wc_6 = 0.8600*np.abs(np.min(Pz_roots))

        else:
            wc_6 = wc_5





    # rule 7


    def G_GM(w):
        Pz = np.polymul(G()[0], Gm()[0])
        Pp = np.polymul(G()[1], Gm()[1])
        G_w = scs.freqs(Pz, Pp, w)[1]
        return np.abs(phase(G_w))-np.pi

    w = np.logspace(-3, 3, 100)
    plt.figure(2)
    Pz = np.polymul(G()[0], Gm()[0])
    Pp = np.polymul(G()[1], Gm()[1])
    [w, h] = scs.freqs(Pz, Pp, w)

    plt.subplot(211)
    plt.loglog(w, np.abs(h))
    plt.subplot(212)
    plt.semilogx(w, phase(h))


    wc_7 = np.abs(sc.optimize.fsolve(G_GM, 10))

    w_vec = [wc_5, wc_6, wc_7]

    wc_min_everything = np.min(w_vec)

    print "  "
    print "maximum value of wc < ", wc_min_everything





    # rule 8
    # unstable RHP poles
    Poles_p = np.roots(G()[1])

    vec_p = [wc_min_1]

    for p in Poles_p:
        if np.real(p) > 0:
            vec_p.append(2*np.abs(p))


    wc_min_everything = np.max(vec_p)

    print "minimum value of wc > ", wc_min_everything

    plt.show()
Пример #20
0
 def phase(self):
     """Returns the current phase of the cursor
     """
     return utils.phase(self.angle)