def test_zero(self, fun, args): sys = fun(*args) np.testing.assert_allclose(sys.zeros(), 42) np.testing.assert_allclose(zeros(sys), 42) with pytest.warns(PendingDeprecationWarning): sys.zero() with pytest.warns(PendingDeprecationWarning): ct.zero(sys)
def rlocus(name, sys, kvect, k=None): if k is None: k = kvect[-1] sysc = control.feedback(sys * k, 1) closed_loop_poles = control.pole(sysc) res = control.rlocus(sys, kvect, Plot=False) for locus in res[0].T: plt.plot(np.real(locus), np.imag(locus)) p = control.pole(sys) z = control.zero(sys) marker_props = { 'markeredgecolor': 'r', 'markerfacecolor': 'none', 'markeredgewidth': 2, 'markersize': 10, 'linestyle': 'none' } plt.plot(np.real(p), np.imag(p), marker='x', label='pole', **marker_props) plt.plot(np.real(z), np.imag(z), marker='o', label='zero', **marker_props) plt.plot(np.real(closed_loop_poles), np.imag(closed_loop_poles), marker='s', label='closed loop pole', **marker_props) plt.legend(loc='best') plt.xlabel('real') plt.ylabel('imag') plt.grid(True) plt.title(name + ' root locus')
def test_full_order_compensator(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") A = np.array([[0., 1., 0., 0.], [0., -25., -0.98, 0.], [0., 0., 0., 1.], [0., 25., 10.78, 0.]]).astype('float') B = np.array([[0.], [0.5], [0.], [-0.5]]).astype('float') C = np.array([[1., 0., 0., 0.]]).astype('float') D = np.zeros((1, 1)).astype('float') desiredPolesCtrl = np.array([ -25., -4., np.complex(-2., 2. * np.sqrt(3)), np.complex(-2., -2. * np.sqrt(3)) ]) w0 = 5. desiredPolesObsv = np.roots( np.array([ 1.0, 2.613 * w0, (2. + np.sqrt(2)) * w0**2, 2.613 * w0**3, w0**4 ])) compensatorTF = fullOrderCompensator(A, B, C, D, desiredPolesCtrl, desiredPolesObsv) openLoopTF = control.ss2tf(control.StateSpace(A, B, C, D)) # poles are zeros of return difference poles = control.zero(1. + compensatorTF * openLoopTF) for p in poles: polePresent = any([ np.isclose(np.complex(p), np.complex(pt)) for pt in np.hstack([desiredPolesCtrl, desiredPolesObsv]) ]) self.assertTrue(polePresent)
def locate_poles(): """ Finds location of a system's zeros and poles """ n1 = np.array([1, 1]) n2 = np.array([1, 2]) d1 = np.array([1, 2j]) d2 = np.array([1, -2j]) d3 = np.array([1, 3]) numerator_g, denominator_g = np.array([6, 0, 1]), np.array([1, 3, 3, 1]) sys_g = ct.tf(numerator_g, denominator_g) zeros_g = ct.zero(sys_g) pole_g = ct.pole(sys_g) numerator_h = np.convolve(n1, n2) denominator_h = np.convolve(d1, np.convolve(d2, d3)) sys_h = ct.tf(numerator_h, denominator_h) sys_tf = sys_g / sys_h pzmap_sys = ct.pzmap(sys_tf) print(AsciiTable([['Poles and Zeros']]).table) data = [['Function', 'Result Ouput'], ['G(s)', sys_g], ['Zeros(g)', zeros_g], ['Pole(g)', pole_g], ['H(s)', sys_h], ['T(s)', sys_tf], ['Pzmap(s)', pzmap_sys]] print(AsciiTable(data).table)
def testMinrealBrute(self): # depending on the seed and minreal performance, a number of # reductions is produced. If random gen or minreal change, this # will be likely to fail nreductions = 0 for n, m, p in permutations(range(1, 6), 3): s = rss(n, p, m) sr = s.minreal() if s.states > sr.states: nreductions += 1 else: # Check to make sure that poles and zeros match # For poles, just look at eigenvalues of A np.testing.assert_array_almost_equal(np.sort(eigvals(s.A)), np.sort(eigvals(sr.A))) # For zeros, need to extract SISO systems for i in range(m): for j in range(p): # Extract SISO dynamixs from input i to output j s1 = ss(s.A, s.B[:, i], s.C[j, :], s.D[j, i]) s2 = ss(sr.A, sr.B[:, i], sr.C[j, :], sr.D[j, i]) # Check that the zeros match # Note: sorting doesn't work => have to do the hard way z1 = zero(s1) z2 = zero(s2) # Start by making sure we have the same # of zeros assert len(z1) == len(z2) # Make sure all zeros in s1 are in s2 for z in z1: # Find the closest zero TODO: find proper bounds assert min(abs(z2 - z)) <= 1e-7 # Make sure all zeros in s2 are in s1 for z in z2: # Find the closest zero assert min(abs(z1 - z)) <= 1e-7 # Make sure that the number of systems reduced is as expected # (Need to update this number if you change the seed at top of file) assert nreductions == 2
def plot_rlocus(self, fig): tf = self.tf if self.loop_type == 'ol' else self.tf_plant * self.tf_comp fig.clf() ax = fig.add_subplot(1, 1, 1) klist = np.linspace(500.0, 0, num=1000) rlist, _ = control.root_locus(tf, kvect=klist, Plot=False) rlist = np.vstack(rlist) poles = np.array(control.pole(tf)) ax.plot(np.real(poles), np.imag(poles), 'x') zeros = np.array(control.zero(tf)) if zeros.size > 0: ax.plot(np.real(zeros), np.imag(zeros), 'o') ax.plot(np.real(rlist), np.imag(rlist)) ax.axhline(0., linestyle=':', color='k', zorder=-20) ax.axvline(0., linestyle=':', color='k') ax.set_xlabel('Real axis') ax.set_ylabel('Imaginary axis') if not self.settings.is_rlocus_default(): zeta = self.settings.get_rlocus_zeta() wn = self.settings.get_rlocus_omega() x0 = -np.arccos(zeta) * wn if wn else ax.get_xlim()[0] xt = np.arange(x0, 0, 0.01) ax.plot(xt, -np.arccos(zeta) * xt, '--', linewidth=0.5, color='black') ax.plot(xt, np.arccos(zeta) * xt, '--', linewidth=0.5, color='black') x = np.arange(0, wn + 0.01, 0.01) y = np.sqrt(wn**2 - x**2) x = -np.concatenate([x, x[::-1]]) y = np.concatenate([y, -y[::-1]]) ax.plot(x, y, '--', linewidth=0.5, color='black') xmin = self.settings.get_rlocus_xmin() xmax = self.settings.get_rlocus_xmax() ymin = self.settings.get_rlocus_ymin() ymax = self.settings.get_rlocus_ymax() ax.set_xlim(xmin, xmax) ax.set_ylim(ymin, ymax) return fig
def TF_properties(self, window, key, entry1, entry2): transfer_function = self.get_TF(entry1, entry2) if key == "dcgain": dc_gain = co.dcgain(transfer_function) self.print_TF_props(window, dc_gain, "DC Gain:") elif key == "poles": poles = co.pole(transfer_function) self.print_TF_props(window, poles, "Poles:") elif key == "zeros": zeros = co.zero(transfer_function) self.print_TF_props(window, str(zeros), "Zeros:")
def time(tf): print "Poles: ", ctrl.pole(tf) print "Zeros: ", ctrl.zero(tf) dc = ctrl.dcgain(tf) print "DC gain: ", dc t, y = ctrl.step_response(tf) ys = filter(lambda l: l >= 0.98 * dc, y) i = np.ndarray.tolist(y).index(min(ys)) print "Ts: ", t[i] print "Overshoot: ", (max(y) / dc) - 1 i = np.ndarray.tolist(y).index(max(y)) print "Tr: ", t[i]
def test_reduced_order_compensator(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") A = np.array([[0., 1., 0., 0.], [0., -25., -0.98, 0.], [0., 0., 0., 1.], [0., 25., 10.78, 0.]]).astype('float') B = np.array([[0.], [0.5], [0.], [-0.5]]).reshape( (4, 1)).astype('float') C = np.array([[1., 0., 0., 0.]]).reshape((1, 4)).astype('float') D = np.zeros((1, 1)).astype('float') ### Controller ### desiredPolesCtrl = np.array([ -25., -4., np.complex(-2., 2. * np.sqrt(3)), np.complex(-2., -2. * np.sqrt(3)) ]) G = ch6_utils.bassGura(A, B, desiredPolesCtrl) G1 = G[0, 0].reshape((1, 1)) G2 = G[0, 1:].reshape((1, 3)) ### Observer ### desiredPolesObsv = np.roots( np.array([1.0, 2. * 5., 2. * 5.**2, 5.**3])) Aaa = np.array(A[0, 0]).reshape((1, 1)) Aau = np.array(A[0, 1:]).reshape((1, 3)) Aua = np.array(A[1:, 0]).reshape((3, 1)) Auu = np.array(A[1:, 1:]).reshape((3, 3)) Ba = np.array(B[0]).reshape((1, 1)) Bu = np.array(B[1:]).reshape((3, 1)) Ca = np.array([[1]]).reshape((1, 1)).astype('float') L, Gbb, H = ch7_utils.reducedOrderObserver(Aaa, Aau, Aua, Auu, Ba, Bu, Ca, desiredPolesObsv) ### Compensator ### F = Auu - L @ Aau Ar = F - H @ G2 Br = Ar @ L + Gbb - H @ G1 Cr = G2 Dr = G1 + G2 @ L sysD = control.StateSpace(Ar, Br, Cr, Dr) compensatorTF = control.ss2tf(sysD) sysplant = control.StateSpace(A, B, C, D) openLoopTF = control.ss2tf(sysplant) # poles are zeros of return difference poles = control.zero(1. + compensatorTF * openLoopTF) for p in poles: polePresent = any([ np.isclose(np.complex(p), np.complex(pt)) for pt in np.hstack([desiredPolesCtrl, desiredPolesObsv]) ]) self.assertTrue(polePresent)
def rootlocus(sys, kvect=None): if kvect is None: kvect = np.logspace(-3, 0, 1000) rlist, klist = control.rlocus(sys, plot=False, kvect=kvect) for root in rlist.T: plt.plot(np.real(root), np.imag(root)) plt.plot(np.real(root[-1]), np.imag(root[-1]), 'bs') for pole in control.pole(sys): plt.plot(np.real(pole), np.imag(pole), 'rx') for zero in control.zero(sys): plt.plot(np.real(zero), np.imag(zero), 'go') plt.grid() plt.xlabel('real') plt.ylabel('imag')
def question1(Gpr, plot=True): print(spacer + "Question 1" + spacer) # 1. POLES AND ZEROS poles = ct.pole(Gpr) zeros = ct.zero(Gpr) print("\t Poles of the system are {}, and zeroes are {}".format( poles, zeros)) # 2. PZ MAP H = 1 OLTF = Gpr * H plt.figure("Q1 - PZ map") ct.pzmap(OLTF) if plot: plt.show # 3. STABILITY stable = True for pole in poles: if (pole > 0): stable = False temp = "unstable" if (stable): temp = "stable" print("\t Since {} are the poles, the system is {}".format(poles, temp)) # 4. STEP RESPONSE t, c = ct.step_response(OLTF) end_value = c[c.size - 1] print("\t The end value of the OL step_response is {}".format(end_value)) plt.figure("Q1 - Step response") plt.plot(t, c) # plot asymptote x_coordinates = [t[0], t[t.size - 1]] y_coordinates = [end_value, end_value] plt.plot(x_coordinates, y_coordinates) if plot: plt.show() return OLTF
def stabilityRange(tfD, tfPlant, gain): """ numerically evaluate a range of gains, k, to see if the closed-loop system (k*tfD*tfPlant) / (1 + k*tfD*tfPlant) Inputs: tfD (control.TransferFunction) - compensator transfer function tfPlant (control.TransferFunction) - open loop system transfer function gain (numpy matrix/array, type=real) - range of gains to check Returns: tuple(min gain, max gain) defining stability interval if such an interval could be found, `None` otherwise Raises: """ stable = np.zeros_like(gain) for i, _k in enumerate(gain): rz = np.real(control.zero(1. + (_k * tfD) * tfPlant)) #print(rz.size) if rz.size > 0 and np.max(rz) < 0: stable[i] = 1. if len(gain[stable > 0]) > 1: return (gain[stable > 0][0], gain[stable > 0][-1]) return None
def time (tf, method = 'step', plot = False): print "=================================================================="; print "Poles: ", ctrl.pole (tf); print "Zeros: ", ctrl.zero (tf); dc = ctrl.dcgain (tf); print "DC gain: ", dc; if (method == 'step'): t, y = ctrl.step_response (tf); if (method == 'impulse'): t, y = ctrl.impulse_response (tf); ys = filter (lambda l: l >= 0.98 * dc, y); i = np.ndarray.tolist(y).index (min (ys)); print "Ts: ", t[i]; print "Overshoot: ", (max (y) / dc) - 1; i = np.ndarray.tolist(y).index (max (y)); print "Tr: ", t[i]; if (plot == True): p = Plotter ({'grid' : True}); p.plot ([(t, y)]); return t, y
P2 = 100e3 P3 = 500e3 A0 = 1e3 G = A0/((s/P1+1)*(s/P2+1)*(s/P3+1)) k =1 # Sistema realimentado H = G/(1+k*G) # Muestro ganancia lazo cerrado para comprobar resultado print(H) #Separo en parte real e imaginaria de los polos y ceros a lazo cerrado para hacer diagrama de polos y ceros x_polos = ctl.pole(H).real y_polos = ctl.pole(H).imag x_zeros = ctl.zero(H).real y_zeros = ctl.zero(H).imag fig = plt.figure() ax = fig.add_subplot(1,1,1) ax.scatter(x_polos,y_polos,marker="x") # ax.scatter(x_zeros, y_zeros, marker="o") ax.set_xlabel('sigma') ax.set_ylabel('jw') ax.set_title("Polos de la transferencia a lazo cerrado") # Hago la respuesta al escalón Tau_dominante = 1/min(abs(x_polos)) #El tau dominante es la inversa del polo más cerca del eje imaginario t_resp = 4* Tau_dominante tvec = np.linspace(0,t_resp,5000) #Vector de tiempos de 5k puntos de 0 a 4 veces el tau dominante
import control as co import numpy as np import matplotlib.pyplot as plt G1 = co.tf( [2, 5], [1, 2, 3]) # 2s + 5 / s^2 + 2s + 3 --- Provided only the coeficients G2 = 5 * co.tf(np.poly([-2, -5]), np.poly( [-4, -5, -9])) # Provided the 'zeros' and the 'poles' of the function # Algebrism is supported G3 = G1 + G2 G4 = G1 * G2 G5 = G1 / G2 G6 = G1 - G2 G7 = co.feedback(G1, G2) # Minimum Realization (Pole-Zero Cancellation) co.minreal(G2) # TF Properties print(co.dcgain(G6)) # DC Gain print(co.pole(G6)) # Pole for G6 print(co.zero(G6)) # Zero for G6
def _nq_serial_decomposition(system: "IdealSystem", q: StaticQuantizer, verbose: bool) -> Tuple["DynamicQuantizer", float]: """ Finds the stable and optimal dynamic quantizer for `system` using serial decomposition[1]_. Parameters ---------- system : IdealSystem q : StaticQuantizer T : int gain_wv : float verbose : bool dim : int Returns ------- (Q, E) : Tuple[DynamicQuantizer, float] """ if verbose: print("Trying to calculate quantizer using serial system decomposition...") tf = system.P.tf1 zeros_ = _ctrl.zero(tf) poles = _ctrl.pole(tf) unstable_zeros = [zero for zero in zeros_ if abs(zero) > 1] z = _ctrl.TransferFunction.z z.dt = tf.dt if len(unstable_zeros) == 0: n_time_delay = len([p for p in poles if p == 0]) # count pole-zero G = 1 / z**n_time_delay F = tf / G F_ss = _ctrl.tf2ss(F) B_F = matrix(F_ss.B) C_F = matrix(F_ss.C) E = abs(C_F @ B_F)[0, 0] * q.delta elif len(unstable_zeros) == 1: i = len(poles) - len(zeros_) # relative order if i < 1: return None, inf a = unstable_zeros[0] G = (z - a) / z**i F = _ctrl.minreal(tf / G, verbose=False) F_ss = _ctrl.tf2ss(F) B_F = matrix(F_ss.B) C_F = matrix(F_ss.C) E = (1 + abs(a)) * abs(C_F @ B_F)[0, 0] * q.delta else: return None, inf A_F = matrix(F_ss.A) D_F = matrix(F_ss.D) # check if (C_F @ B_F)[0, 0] == 0: if verbose: print("CF @ BF == 0 became true. Couldn't calculate by using serial system decomposition.") return None, inf if D_F[0, 0] != 0: if verbose: print("DF == 0 became true. Couldn't calculate by using serial system decomposition.") return None, inf Q = DynamicQuantizer( A=A_F, B=B_F, C=- 1 / (C_F @ B_F)[0, 0] * C_F @ A_F, q=q ) if verbose: print("Success!") return Q, E
import control as co import numpy as np import matplotlib.pyplot as plt G1 = co.tf([2,5],[1,2,3]) # 2s + 5 / s^2 + 2s + 3 --- Provided only the coeficients G2 = 5*co.tf(np.poly([-2,-5]), np.poly([-4,-5,-9])) # Provided the 'zeros' and the 'poles' of the function # Algebrism is supported G3 = G1+G2 G4 = G1*G2 G5 = G1/G2 G6 = G1-G2 G7 = co.feedback(G1,G2) # Minimum Realization (Pole-Zero Cancellation) co.minreal(G2) # TF Properties print(G1) print('DC Gain: '+ str(co.dcgain(G1))) # DC Gain print('Pole: ' + str(co.pole(G1))) # Pole for G6 print('Zero: ' + str(co.zero(G1))) # Zero for G6
def pid_with_root_placing(g: Union[sp.Expr, ct.TransferFunction], po: float, ts: float, report: bool = False) -> ct.TransferFunction: """ Function to create a PID controller based on root locus method, the controller is the form: Kc*(s+b)^2/s equivalent to Kp + Ki/s + Kd*s --- design params example ts = 11.5 # 11.5 seg po = 0.5 # 0.5% :param g: Your plant transfer function :param po: Percentage Overshoot :param ts: Time Settling :param report: If you want to print a report step by step :return: a TransferFunction controller """ s = sp.var("s") if isinstance(g, ct.TransferFunction): sys = g else: sys = core.symbolic_transfer_function(g) psi, wn = core.from_quality_to_psi_wn(po, ts) if report: print("psi=%.2f | wn=%.2f\n" % (psi, wn)) pds = core.construct_poles(psi, wn) pd = pds[0] # util pole in the (Re-, Im+) plane if report: print("desired pole: %.2f + %.2fi" % (pd.real, pd.imag)) # finding b with the angle condition poles_angles = [] for pole in [ *ct.pole(sys), 0 ]: # for each pole and added the pole generated for the PID integrator angle = np.angle(pd - pole) * 180 / np.pi if angle < 0: angle = 360 + angle poles_angles.append(angle) zeros_angles = [] for zero in ct.zero(sys): # for each pole angle = np.angle(pd - zero) * 180 / np.pi if angle < 0: angle = 360 + angle zeros_angles.append(angle) b_angle = -180 - (sum(zeros_angles) - sum(poles_angles)) b_angle = b_angle / 2 # because a == b in the PID controller form if report: print("positioned pole angle: %.2f" % b_angle) dist = pd.imag / np.tan(b_angle * np.pi / 180) b = pd.real - dist # finally, we have b if report: print("found 'b' constant = %.2f" % b) print("a = b, then a = %.2f too" % b) # finding Kc with module condition poles_dists = [] for pole in [ *ct.pole(sys), 0 ]: # for each pole and added the pole generated for the PID integrator poles_dists.append(np.abs(pd - pole)) zeros_dists = [] for zero in [ *ct.zero(sys), b, b ]: # for each pole added with our new zeros (from PID) calculated before zeros_dists.append(np.abs(pd - zero)) k = sys.num[0][0][-1] # assuming the basic form of a SISO system kc = np.prod(poles_dists) / k / np.prod(zeros_dists) if report: print("found 'kc' constant = %.2f" % kc) # defining PID constants kp = -2 * kc * b ki = kc * b**2 kd = kc if report: print("controller = %.2f * (s+%.2f)^2 / s" % (kc, b)) print("pid form = %.2f + %.2f/s + %.2f*s" % (kp, ki, kd)) c = kp + ki / s + kd * s pid = core.symbolic_transfer_function(c) return pid
import control as co import matplotlib.pyplot as plt s = co.tf('s') g = (s + 4) / (7 * s**2 + 3 * s - 1) g_poles = co.pole(g) g_zeros = co.zero(g) print('poles') for elem in g_poles: # print poles as a column vector for convenience print(f'{elem: .2f}') # Two floating points per print print('zeros') for elem in g_zeros: print(f'{elem: .2f}') g_map = co.pzmap(g, plot=True) plt.show()
# Função de transferência do sistema numG = np.array([25]) denG = np.array([1, 5, 0]) Ls = ctl.tf(numG, denG) print("L(s) = ", Ls) # malha de realimentação numH = np.array([1]) denH = np.array([1]) Hs = ctl.tf(numH, denH) print("H(s) = ", Hs) # Função de transferência de malha fechada Ts = ctl.feedback(ctl.series(Ls, 1), Hs, sign=-1) print("Função de transferência do sistema em malha fechada", Ts) print("Zeros: ", ctl.zero(Ts)) print("Polos: ", ctl.pole(Ts)) # Calculo da Resposta ao degrau Tsim = 3 T, yout = ctl.step_response(Ts, Tsim) infomation = ctl.step_info(Ts) print("Informações: ", infomation) # Calcular o degrau unitário T2 = np.linspace(-1, Tsim, 1000) degrau = np.ones_like(T2) degrau[T2 < 0] = 0 #plotar os resultados plt.plot(T, yout, 'k-')
PI = co.tf(np.poly(pid_zeros), np.poly(pid_poles)) print(G) print(PI) Gcl = co.feedback(0.0001 * G * PI) co.root_locus(Gcl, Plot=True, grid=False) Gcl = Gcl.minreal(tol=0.01) print(Gcl) #co.root_locus(Gcl, Plot=True, grid=False) PI = kC * PI Gcl = co.feedback(G * PI) Gcl = Gcl.minreal(tol=0.01) print(Gcl) print(co.pole(Gcl)) print(co.zero(Gcl)) poles_and_zeros = np.append(np.append(np.append(zeros, poles), s), np.conj(s)) ymin = np.min(np.imag(poles_and_zeros)) - 2 ymax = np.max(np.imag(poles_and_zeros)) + 2 xmin = np.min(np.real(poles_and_zeros)) - 2 xmax = np.max(np.real(poles_and_zeros)) + 2 plt.ylim(ymin, ymax) plt.xlim(xmin, xmax) for root in co.pole(Gcl): plt.plot(np.real(root), np.imag(root), color='red', marker='*') plt.text(np.real(root) + 0.1, np.imag(root) + (ymax - ymin) / 20 * (1 if np.imag(root) > 0 else -1), f'{root:.2f}',
def Controller(k): global alfa,beta N = [k,k*alfa,k*beta] D = [1,0] C = ctl.tf(N,D) zeros = np.roots(N) poles = np.roots(D) return C,zeros,poles ##DEFINE THE PLANT G = ctl.tf([1],[L*((M+m)-m),0,-(M+m)*g]) ##PLOT POLES AND ZEROS OF PLANT AND CONTROLLER open_poles = ctl.pole(G) open_zeros = ctl.zero(G) plt.plot(np.real(open_poles),np.imag(open_poles),'gx',label='Plant Open Loop Poles',markersize=15) plt.plot(np.real(open_zeros),np.imag(open_zeros),'go',label='Plant Zeros',markersize=10) C,zeros,poles = Controller(1) plt.plot(np.real(zeros),np.imag(zeros),'ro',label='Control Zeros',markersize=10) plt.plot(np.real(poles),np.imag(poles),'rx',label='Control Poles',markersize=15) ###LOOP ON K TO MAKE LOCUS k_vec = np.linspace(0,1000,1000) for k in k_vec: #print(k) C,zeros,poles = Controller(k) GCL = C*G/(1+C*G) poles = ctl.pole(GCL) plt.plot(np.real(poles),np.imag(poles),'b*') plt.legend()
import control import matplotlib.pyplot as plt import numpy as np num = [24] den = [1 , 17 , 32 , 30] sys = control.TransferFunction(num,den) # You can quickly control this by typing built-in magic commands in Spyder's IPython console, which I find faster than picking these from the preferences menu. Changes take immediate effect, without needing to restart Spyder or the kernel. # To switch to "automatic" (i.e. interactive) plots, type: # Escribir en la consola! %matplotlib auto # Escribir en la consola! %matplotlib inline para escribir en la consola control.bode_plot(sys) print(control.pole(sys)) print(control.zero(sys)) control.pzmap(sys) t, y = control.step_response(sys) plt.figure(3) plt.plot(t, y, 'r') plt.ylabel('Xp(t)') plt.xlabel('Xin(t)') print(control.tf2ss(sys))
plt.axvline(-4 / TS, color='r', linestyle='--') s = co.tf('s') g = (s + 1) / ((s - 1) * (s - 4)) h1 = 1 h2 = 1 / (s - 1) #b) k = 60 gf = co.feedback( k * pd_comp(-4.4) * g, h2, -1 ) # υπολογίζω τους πόλου και τα μηδενικά του κλειστού συστήματος με Κ = 60 και feedback=h2 poles = co.pole(gf) zeros = co.zero(gf) print(f"poles: {poles}") print(f"zeros: {zeros}") plt.figure(1) co.root_locus( pd_comp(-4.4) * g * h2, grid=False) # σχεδιάζω την γραφική παράστασή μου με pd_compensator plot_ts(2) plt.xlim(-15, 5) plt.plot(poles.real, poles.imag, 'rx') t = np.linspace(0, 3, 1000) t1, yout = co.step_response(gf, t) step_info(t1, yout)
num = [2.5] den = [1, 2, 0.5] G = cl.TransferFunction(num, den) # create Transfer Function H = cl.TransferFunction(1, 1) PI = cl.TransferFunction([Kp, Ki], [1, 0]) print(PID) F = cl.series(PI, G) sys = cl.feedback(F, H) # I = cl.feedback(G, H) # F = cl.series(PI, I) print(cl.pole(G)) #print pole print(cl.zero(G)) #print zero T = np.arange(0, 40, 0.05) # create bode plot # mag, phase, w = cl.bode(sys) # plot step response #T, yout = cl.step_response(I) #T, yout, xout = cl.forced_response(I, T, None, 1) #plt.plot(T, yout) # sine wave & square wave for generating reference signals amplitude = np.sin(T) u = signal.square(0.1 * np.pi * T) plt.plot(T, u)
c = (s + 3) / (s + 4) e = 1 / (s * ((s**2) + 1)) acp = co.parallel(c, a) bap = co.parallel(b, a) acbas = co.series(acp, bap) acbaef = co.feedback(acbas, e, +1) print(acbaef) g_poles = co.pole(acbaef) print("G poles") for elem in g_poles: print(f'{elem: .2f}') g_zeros = co.zero(acbaef) print("G zeros") for elem in g_zeros: print(f'{elem: .2f}') g1_map = co.pzmap(acbaef, plot=True) t = np.linspace(0, 25, 100) t1, stp = co.step_response(acbaef, t) t2, imp = co.impulse_response(acbaef, t) # Warning for infinite impulse at t=0 plt.figure(2) plt.plot(t1, stp) plt.title("Step Response") plt.ylabel("Amplitude") plt.xlabel("Time")
s = co.tf('s') g1 = (s + 2) / (5 * s**3 + 7 * s - 3) g2 = 1 / ((s**2 - 3 * s + 4) * (s + 8)) g12s = co.series(g1, g2) g12p = co.parallel(g1, g2) g12f = co.feedback(g1, g2, -1) print(g12s, g12p, g12f) # G1(s) g1_poles = co.pole(g1) print("g1 poles") for elem in g1_poles: print(f'{elem: .2f}') g1_zeros = co.zero(g1) print("g1 zero") for elem in g1_zeros: print(f'{elem: .2f}') # G2(s) g2_poles = co.pole(g2) print("g2 poles") for elem in g2_poles: print(f'{elem: .2f}') g2_zeros = co.zero(g2) print("g2 zero") for elem in g2_zeros: print(f'{elem: .2f}')