def execute(self): # Realimentando a malha sysFechada = con.feedback(self.sys, 1) # Resposta ao degrau [self.xout, self.yout] = con.step_response(sysFechada, const.TEMPO_CALCULO) # "Alterando" amplitude do degrau self.yout = self.yout * const.SP # Pegando as informações sobre o sistema info = con.step_info(sysFechada, self.xout) # Pegando o valor de estado estacionário self.valorEstacionario = info['SteadyStateValue'] * const.SP # Ponto de acomodação self.tempo_acomodacao = info['SettlingTime'] self.valor_acomodacao = accommodationPoint(self.yout, self.valorEstacionario) # Overshoot self.overshootX = info['PeakTime'] self.overshootY = info['Peak'] * const.SP self.overshoot = info['Overshoot'] # Erro em regime permanente self.erroRegimePermanente = errorCalculate(const.SP, self.valorEstacionario)
def execute(self): # Resposta ao degrau [self.xout, self.yout] = con.step_response(self.sys, const.TEMPO) # Pegando as informações do sistema info = con.step_info(self.sys, self.xout) # "Alterando" amplitude do degrau self.yout = self.yout * self.VALOR_ENTRADA # Pegando o valor de estado estacionário self.valorEstacionario = info['SteadyStateValue'] * self.VALOR_ENTRADA # Ponto de acomodação self.tempo_acomodacao = info['SettlingTime'] self.valor_acomodacao = accommodationPoint(self.yout, self.valorEstacionario) # Overshoot self.overshootX = info['PeakTime'] self.overshootY = info['Peak'] * self.VALOR_ENTRADA self.overshoot = info['Overshoot'] # Erro em regime permanente self.erroRegimePermanente = errorCalculate(self.VALOR_ENTRADA, self.valorEstacionario)
def KpKi(sys): # Pegando os valores do OVERSHOOT e Tempo de acomodação desejados mp = const.OVERSHOOT ts = const.TS # Resposta ao degrau [xout, yout] = con.step_response(sys, const.TEMPO) # "Alterando" amplitude do degrau yout = yout * const.SP # Pegando as informações sobre o sistema info = con.step_info(sys, xout) # Pegando o valor de estado estacionário valorEstacionario = info['SteadyStateValue'] * const.SP # Calculando valor de K e tall k = K(const.SP, valorEstacionario) tal = tall(yout, valorEstacionario, const.TEMPO_AMOSTRAGEM) # Calculando valores de Kp e Ki kp, ki = calculateKpKi(mp, ts, k, tal) return kp, ki
def step_report(sys: Union[ct.TransferFunction, sp.Expr], output: bool = True) -> Dict[str, float]: """ Return a step report from your system in a symbolic or polynomial form (TransferFunction or Symbolic) :param sys: your system :param output: If you want to print your output to stdout :return: a dict with props: RiseTime, SettlingTime, SettlingMin, SettlingMax, Overshoot, Undershoot, Peak, PeakTime, SteadyStateValue """ if type(sys) is ct.TransferFunction: tf = sys else: tf = core.symbolic_transfer_function(sys) info = ct.step_info(tf) if output: print("Rise Time: %.3f" % info["RiseTime"]) print("Settling Time: %.3f" % info["SettlingTime"]) print("Settling Min: %.3f" % info["SettlingMin"]) print("Settling Max: %.3f" % info["SettlingMax"]) print("Overshoot: %.3f" % info["Overshoot"]) print("Undershoot: %.3f" % info["Undershoot"]) print("Peak: %.3f" % info["Peak"]) print("Peak time: %.3f" % info["PeakTime"]) print("Steady State Value: %.3f" % info["SteadyStateValue"]) return info
def stepinfo(sys, display=False, T=None, SettlingTimeThreshold=0.05, RiseTimeLimits=(0.1, 0.9)): T_max = get_T_max([sys], T=None, N=200) if T is None: if ctl.isctime(sys): T = np.linspace(0, T_max, 200) else: # For discrete time, use integers T = np.arange(0, T_max, sys.dt) info = ctl.step_info(sys, T, SettlingTimeThreshold=0.05, RiseTimeLimits=(0.1, 0.9)) if display == True: for keys, values in info.items(): print("{} :\t{:.5f}".format(keys, values)) print() return info
def calculating_params(self, populations): calculatedParams = [] for population in populations: kp = population[0] ti = population[1] td = population[2] G = kp * control.tf([ti * td, ti, 1], [ti, 0]) F = control.tf(1, [1, 6, 11, 6, 0]) system = control.feedback(control.series(G, F), 1) t = [] i = 0 while i < 100: t.append(i) i += 0.01 try: systemInfo = control.step_info(system) except IndexError: calculatedParams.append([10000000, 1, 100, 200]) continue T, output = control.step_response(system, T=t) ISE = round(sum((output - 1)**2), 2) timeRise = round(systemInfo['RiseTime'], 2) timeSettle = round(systemInfo['SettlingTime'], 2) overshoot = round(systemInfo['Overshoot'], 2) calculatedParams.append([ISE, timeRise, timeSettle, overshoot]) return calculatedParams
def compute_ise(Kp, Ti, Td): g = Kp * TransferFunction([Ti * Td, Ti, 1], [Ti, 0]) sys = feedback(series(g, F), 1) sys_info = step_info(sys) _, y = step_response(sys, T) ise = sum((y - 1)**2) t_r = sys_info['RiseTime'] t_s = sys_info['SettlingTime'] m_p = sys_info['Overshoot'] return ise, t_r, t_s, m_p
def q1_perfFNC(Kp, Ti, Td): G = Kp * TransferFunction([Ti * Td, Ti, 1], [Ti, 0]) sys = feedback(series(G, F), 1) sysinf = step_info(sys) T, y = step_response(sys, T=t) # return ISE, t_r, t_s, M_p return sum(( y - 1)**2), sysinf['RiseTime'], sysinf['SettlingTime'], sysinf['Overshoot']
def evaluate(chrom): Kp, Ki, Kd = chrom G_c = control.tf([Kp], [1]) + control.tf([Ki], [1, 0]) + control.tf([Kd, 0], [1]) OLTF = T2V * G_c CLTF = control.feedback(OLTF) try: stepi = control.step_info(CLTF) st = stepi['SettlingTime'] **2 + (1-stepi['SteadyStateValue'])**2 return st except: return 1e300
def test(): Kp, Ki, Kd = [72.94491673, 193.26606581, 2.0693249] G_c = control.tf([Kp], [1]) + control.tf([Ki], [1, 0]) + control.tf([Kd, 0], [1]) OLTF = T2V * G_c CLTF = control.feedback(OLTF) t = np.linspace(0, 5, 200) t, y = control.step_response(CLTF, t) print(control.step_info(CLTF, SettlingTimeThreshold=0.05)) plt.title("Step Response") plt.plot(t, y) plt.grid() plt.show()
def q1_perfFNC(Kp, Ti, Td): G = Kp * TransferFunction([Ti * Td, Ti, 1], [Ti, 0]) F = TransferFunction(1, [1, 6, 11, 6, 0]) sys = feedback(series(G, F), 1) sysinf = step_info(sys) t = [] i = 0 while i < 100: t.append(i) i += 0.01 T, y = step_response(sys, T=t) ISE = sum((y - 1)**2) t_r = sysinf['RiseTime'] t_s = sysinf['SettlingTime'] M_p = sysinf['Overshoot'] return ISE, t_r, t_s, M_p
def execute(self): # Calculando os valores dos ganhos self.kp, self.ki = KpKi(self.sys) # Criando a função de transferência auxiliar sysAux = con.TransferFunction([1, 0], [1, -1], const.TEMPO_AMOSTRAGEM) # Criando a transferência do controlador sysControlador = sysAux * self.ki * const.TEMPO_AMOSTRAGEM + self.kp # Realimentando a malha sysGanhoIntegral = con.feedback(sysControlador * self.sys, 1) # Resposta ao degrau [self.xout, self.yout] = con.step_response(sysGanhoIntegral, const.TEMPO_CALCULO) # "Alterando" amplitude do degrau self.yout = self.yout * const.SP # Pegando as informações sobre o sistema info = con.step_info(sysGanhoIntegral, self.xout) # Pegando o valor de estado estacionário self.valorEstacionario = info['SteadyStateValue'] * const.SP # Ponto de acomodação self.tempo_acomodacao = info['SettlingTime'] self.valor_acomodacao = accommodationPoint(self.yout, self.valorEstacionario) # Overshoot self.overshootX = info['PeakTime'] self.overshootY = info['Peak'] * const.SP self.overshoot = info['Overshoot'] # Erro em regime permanente self.erroRegimePermanente = errorCalculate(const.SP, self.valorEstacionario)
def test_lead_compensator(self): s = sp.var("s") sys = 10/s/(s+1) expected_controller = core.symbolic_transfer_function((0.2953*s + 0.3249)/(0.3196*s + 1)) controller = design.lead_compensator_with_root_placing(sys, 16.3, 2.67, -1.1) self.assertLessEqual(np.mean(np.array(expected_controller.num) - np.array(controller.num)), 1e-3) self.assertLessEqual(np.mean(np.array(expected_controller.den) - np.array(controller.den)), 1e-3) expected_po = 20 expected_ts = 5 controller = design.lead_compensator_with_root_placing(sys, expected_po, expected_ts, -1, auto_tune=True) feedback_sys = ct.feedback(controller*core.symbolic_transfer_function(sys), 1) info = ct.step_info(feedback_sys) self.assertLessEqual(info["SettlingTime"] - expected_ts, 1e-2) self.assertLessEqual(info["Overshoot"] - expected_po, 1e-2)
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-') plt.plot(T2, degrau, 'r-') plt.grid() print(plt.show())
def step_info(arg1, arg2): return control.step_info(arg1, T=arg2)
import control as con import matplotlib.pyplot as plt import numpy as np num = np.array([1, 2]) den = np.array([1, 1]) sys = con.TransferFunction(num, den) time_simulation = np.arange(0, 15, 0.5, dtype=float) [xout, yout] = con.step_response(sys, time_simulation) information = con.step_info(sys) print(information) plt.figure() plt.plot(xout, yout) plt.show()
def lead_compensator_with_root_placing( g: Union[sp.Expr, ct.TransferFunction], po: float, ts: float, compensator_zero: float = -1, auto_tune: bool = False, tune_range: Tuple[float, float] = (-1, 1), tune_values: int = 100, report: bool = False) -> ct.TransferFunction: """ This function construct a lead compensator based on root locus placing :param g: Your plant transfer function :param po: Percentage Overshoot :param ts: Time Settling :param compensator_zero: Fixed zero for the compensator (must be negative) :param auto_tune: If you want to execute a simple algorithm to find near optimal zero based on your params :param tune_range: Tuple with two relative bounds for the tuner (default: (-4, 4)) :param tune_values: Total of values to search :param report: If you want to print a report of the design construction :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" % (psi, wn)) d_poles = core.construct_poles(psi, wn) if report: print("desired poles:") for d_p in d_poles: print("%.2f + %.2fi" % (d_p.real, d_p.imag)) pd = d_poles[0] poles_angles = [] for pole in sys.pole(): angle = np.angle(pd - pole) * 180 / np.pi if angle < 0: angle = 360 - angle poles_angles.append(angle) zeros_angles = [] for zero in sys.zero(): angle = np.angle(pd - zero) * 180 / np.pi if angle < 0: angle = 360 - angle zeros_angles.append(angle) plant_angle = sum(zeros_angles) - sum(poles_angles) compensator_angle = -180 - plant_angle if report: print("compensator expected angle= %.2f" % compensator_angle) # compensator_zero: # fixed value for your compensator fixed_zero = compensator_zero if auto_tune: # simple algorithm to search the best near zero if report: print("---") print( "auto tuning zero compensator in range (%.2f, %.2f) with %d steps" % (compensator_zero + tune_range[0], compensator_zero + tune_range[1], tune_values)) print("expected - ts: %.2f | po: %.2f" % (ts, po)) errors: [float] = [] zero_tests = np.linspace(compensator_zero + tune_range[0], compensator_zero + tune_range[1], tune_values) for i, z in enumerate(zero_tests): try: z_angle = np.angle(pd - z) * 180 / np.pi p_angle = z_angle - compensator_angle d_pole = pd.imag / np.tan(p_angle * np.pi / 180) p = pd.real - d_pole g_t = core.symbolic_transfer_function((s - z) / (s - p)) g_t_pd_e = g_t.horner(pd)[0][0] # expecting a siso model sys_pd_e = sys.horner(pd)[0][0] # expecting a siso model kc = 1 / np.abs(g_t_pd_e) / np.abs(sys_pd_e) comp = kc * g_t f_sys = ct.feedback(comp * sys) step_report = ct.step_info(f_sys) g_ts = step_report["SettlingTime"] g_po = step_report["Overshoot"] if report: print("step %d) zero: %.6f | ts: %.2f | po: %.2f" % (i, z, g_ts, g_po)) err = .4 * (po - g_po)**2 + .6 * ( ts - g_ts)**2 # compute quadratic error errors.append(err) except: errors.append(np.inf) continue fixed_zero = zero_tests[np.argmin(errors)] if report: print("---") compensator_zero_angle = np.angle(pd - fixed_zero) * 180 / np.pi if report: print("fixed zero= %.6f | angle= %.2fdeg" % (fixed_zero, compensator_zero_angle)) # angle condition pole_angle = compensator_zero_angle - compensator_angle # calculated value for your compensator dist_pole = pd.imag / np.tan(pole_angle * np.pi / 180) compensator_pole = pd.real - dist_pole if report: print("calculated pole= %.2f + %.2fi | angle= %.2fdeg" % (compensator_pole.real, compensator_pole.imag, pole_angle)) # finally we can to calculate the kc of our controller # module condition g1 = (s - fixed_zero) / (s - compensator_pole) g1_sys = core.symbolic_transfer_function(g1) g1_pd_evaluated = g1_sys.horner(pd)[0][0] # expecting a siso model sys_pd_evaluated = sys.horner(pd)[0][0] # expecting a siso model kc = 1 / np.abs(g1_pd_evaluated) / np.abs(sys_pd_evaluated) if report: print("found 'kc' constant = %.2f" % kc) final_compensator = kc * g1_sys return final_compensator
def step_report(self, time: list = None) -> Dict[str, float]: return ct.step_info(self.full_system(), time)
import control as con import control.matlab as ctl import numpy as np import matplotlib.pyplot as plt controlador = ctl.tf([0.1, 5], [1, 0]) missilDinamica = ctl.tf([100, 100], [1, 2, 100]) print("Controlador = ", controlador) print("Dinâmica do Missil = ", missilDinamica) Ls = ctl.series(controlador, missilDinamica) print("L(s) = ", Ls) Hss = ctl.tf([1], [1]) Ts = ctl.feedback(Ls, Hss, sign=-1) print("T(s) = ", Ts) yout, T = ctl.step(Ts, 3, 0) info = con.step_info(Ts, 3) print(info) plt.plot(T, yout, '-k') plt.show()
#R y L del grafico R = 0.386 L = 0.9 #Ziegler-Nichols kp = 1.2 / (R * L) ki = kp / (2 * L) kd = kp * (L / 2) print(kp, ki, kd) #Funcion del controlador num_d = [kd, kp, ki] den_d = [1, 0] D = control.TransferFunction(num_d, den_d) #Funcion lazo abierto H = control.feedback(G * D) #Grafico T = np.arange(0, 10, 0.05) T, yout = control.step_response(H, T) plt.title('Salida del sistema H(s)') plt.xlabel("Tiempo (s)") plt.ylabel("Salida y(t)") plt.plot(T, yout) plt.show() print(control.step_info(H))
C2 = control.TransferFunction([1, 0.136], [1, 0.05]) H2 = control.feedback(G * C1 * C2 * K) #[rlist2, klist2] = control.rlocus( # H2, plotstr='-', Plot=True, PrintGain=True, grid=False) #plt.show() t = np.arange(0, 30, 0.05) T2, yout2 = control.step_response(H2, t) plt.plot(T2, yout2) plt.xlabel('Tiempo [s]'), plt.ylabel('Salida') plt.title('Respuesta a entrada en escalon - Compensador 2') plt.show() #comparacion t = np.arange(0, 30, 0.05) T1, yout1 = control.step_response(H1, t) T2, yout2 = control.step_response(H2, t) plt.plot(T1, yout1, label='Compensador C1') plt.plot(T2, yout2, label='Compensador C1 + C2') plt.xlabel('Tiempo [s]'), plt.ylabel('Salida') plt.title('Respuesta a entrada en escalon - Comparacion') plt.legend(loc="center left", bbox_to_anchor=( 1, 0.5 )) #se genera un key de manera de identificar cada simulacion segun color plt.tight_layout() #se ajusta legend al ancho de la pantalla plt.show() print(control.step_info(H1)) print(control.step_info(H2))