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)
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
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()
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()
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