def graficado(valor_ajustado_de_la_deslizadera_del_tiempo, tamaño_impulso, tamaño_escalon, tamaño_rampa, boton_pulsado, G0): fig.clf() retardo = eval(input_del_retardo_en_la_ventana.get()) if boton_pulsado == 'Impulso': t, y = control.impulse_response( G0 * tamaño_impulso, T=(valor_ajustado_de_la_deslizadera_del_tiempo)) if boton_pulsado == 'Escalon': t, y = control.step_response( G0 * tamaño_escalon, T=(valor_ajustado_de_la_deslizadera_del_tiempo)) if boton_pulsado == 'Rampa': t, y = control.step_response( G0 * tamaño_rampa / s, T=(valor_ajustado_de_la_deslizadera_del_tiempo)) if boton_pulsado == 'Arbitraria': t, y, xout = control.forced_response(G0, T=(t_experimental), U=(u_experimental)) t_a_dibujar, y_a_dibujar = ajusta_el_retardo_segun_el_input_de_la_ventana( t, y, retardo) fig.add_subplot(111).plot(t_a_dibujar, y_a_dibujar) canvas.draw()
def pidplot1(num, den, kp, ki, kd): G = control.tf(num, den) if ki != 0: g2 = control.tf([kd, kp, ki], [1, 0]) else: g2 = control.tf([kd, kp], [1]) k = control.series(G, g2) v = control.feedback(k, 1) t1, y1 = control.step_response(G) t2, y2 = control.step_response(v) plt.plot(t2, y2, 'r', linewidth=1, label='G(s) with PID control') plt.grid(True) s = '(Kp=' + str(kp) + ',Ki=' + str(ki) + ',Kd=' + str(kd) + ')' plt.title('Time response of G(s) with PID control' + s) plt.xlabel('Time(sec)') plt.ylabel('Amplitude') if not os.path.isdir('static'): os.mkdir('static') else: # Remove old plot files for filename in glob.glob( os.path.join('static', 'pidcontrol', 'pidc1.png')): os.remove(filename) pidc1 = os.path.join('static', 'pidcontrol', 'pidc1.png') plt.savefig(pidc1) plt.clf() plt.cla() plt.close() return pidc1
def Controlador(X): #Atribuição dos paramentros Kp, Ki e Kd Kp = Kpi + X[0] / 100 Ki = Kii + X[1] / 100 Kd = Kdi + X[2] / 100 #Função Transferência dos termos do controlador P = Kp I = tf(Ki, [1, 0]) D = tf([Kd, 0], [0.1 * Kd, 1]) #União dos blocos PID C = parallel(P, I, D) # Função Transferência com o Controlador F = series(C, G) # Penalidade para o valor do sinal de Entrada na planta # ou seja penalidade para o sinal de Controle alto tc = feedback(C, G) _, yc = step_response(tc, time) if max(yc) > maxcontrolador: #SE1 = np.square(np.subtract(1,yc)) ISE = tdiv + max(yc) else: # Realizando a Integral do erro quadrado t1 = feedback(F, 1) _, y1 = step_response(t1, time) SE = np.square(np.subtract(1, y1)) ISE = np.sum(SE) return (ISE)
def test_response_copy(): # Generate some initial data to use sys_siso = ct.rss(4, 1, 1) response_siso = ct.step_response(sys_siso) siso_ntimes = response_siso.time.size sys_mimo = ct.rss(4, 2, 1) response_mimo = ct.step_response(sys_mimo) mimo_ntimes = response_mimo.time.size # Transpose response_mimo_transpose = response_mimo(transpose=True) assert response_mimo.outputs.shape == (2, 1, mimo_ntimes) assert response_mimo_transpose.outputs.shape == (mimo_ntimes, 2, 1) assert response_mimo.states.shape == (4, 1, mimo_ntimes) assert response_mimo_transpose.states.shape == (mimo_ntimes, 4, 1) # Squeeze response_siso_as_mimo = response_siso(squeeze=False) assert response_siso_as_mimo.outputs.shape == (1, 1, siso_ntimes) assert response_siso_as_mimo.states.shape == (4, 1, siso_ntimes) assert response_siso_as_mimo._legacy_states.shape == (4, siso_ntimes) response_mimo_squeezed = response_mimo(squeeze=True) assert response_mimo_squeezed.outputs.shape == (2, mimo_ntimes) assert response_mimo_squeezed.states.shape == (4, mimo_ntimes) assert response_mimo_squeezed._legacy_states.shape == (4, 1, mimo_ntimes) # Squeeze and transpose response_mimo_sqtr = response_mimo(squeeze=True, transpose=True) assert response_mimo_sqtr.outputs.shape == (mimo_ntimes, 2) assert response_mimo_sqtr.states.shape == (mimo_ntimes, 4) assert response_mimo_sqtr._legacy_states.shape == (mimo_ntimes, 4, 1) # Return_x t, y = response_mimo t, y = response_mimo() t, y, x = response_mimo(return_x=True) with pytest.raises(ValueError, match="too many"): t, y = response_mimo(return_x=True) with pytest.raises(ValueError, match="not enough"): t, y, x = response_mimo # Labels assert response_mimo.output_labels is None assert response_mimo.state_labels is None assert response_mimo.input_labels is None response = response_mimo( output_labels=['y1', 'y2'], input_labels='u', state_labels=["x[%d]" % i for i in range(4)]) assert response.output_labels == ['y1', 'y2'] assert response.state_labels == ['x[0]', 'x[1]', 'x[2]', 'x[3]'] assert response.input_labels == ['u'] # Unknown keyword with pytest.raises(ValueError, match="Unknown parameter(s)*"): response_bad_kw = response_mimo(input=0)
def testSimulation(self): T = range(100) U = np.sin(T) # For now, just check calling syntax # TODO: add checks on output of simulations tout, yout = step_response(self.siso_ss1d) tout, yout = step_response(self.siso_ss1d, T) tout, yout = impulse_response(self.siso_ss1d, T) tout, yout = impulse_response(self.siso_ss1d) tout, yout, xout = forced_response(self.siso_ss1d, T, U, 0) tout, yout, xout = forced_response(self.siso_ss2d, T, U, 0) tout, yout, xout = forced_response(self.siso_ss3d, T, U, 0)
def test_div(self): fb_sys = self.sys1 / (1 + self.sys1 * self.sys2) fb_m = self.m1 / self.m2 t, y2 = ps.step_response(fb_m) _, y1 = ctrl.step_response(fb_sys, t) self.assertTrue(np.allclose(y1, y2, rtol=1e-2), "feedback is broken") fb_sys = ctrl.feedback(self.sys1, 1) fb_m = self.m1 / 1 t, y2 = ps.step_response(fb_m) _, y1 = ctrl.step_response(fb_sys, t) self.assertTrue(np.allclose(y1, y2, rtol=1e1), "scalar feedback is" "broken")
def analyze_sys(sys,H): Go = sys*H Gc = control.feedback(Go) control.root_locus(Go) plt.figure() plt.title('system') t1,x1 = control.step_response(sys) plt.plot(t1,x1) plt.figure() plt.title('controlled system w/ step response') t2,x2 = control.step_response(Gc) print(x2) plt.plot(t2,x2)
def pt1(smooth, time): smoothed_df = pd.concat([pd.DataFrame(smooth, columns = ['smoothed']), \ pd.DataFrame(time, columns = ['time'])], axis = 1) steady_state = smooth[-1] #last element of the smoothed data is passed as steady state value standard_output = steady_state * (1 - np.exp(-1)) #case when t = time_constant in the eqn. ############################################################################# # standard_output = steady_state * (1 - e ^ (−t / time_constant)) # ############################################################################# delay = smoothed_df.time[smoothed_df.smoothed < 0.02].values[-1] #returns the time at which the step change occurs i.e a transition from 0 to some value. #Values lesser than 0.02 were treatred as zero. time_constant = smoothed_df.time[smoothed_df.index == abs(smoothed_df.smoothed - standard_output)\ .sort_values().index[0]].values[0] #derived from the equation of standard_output tf_pt1 = con.tf(steady_state, [time_constant, 1]) numerator, denominator = con.pade(delay, 1) delay_tf_pt1 = con.tf(numerator, denominator) t_pt1, yout_pt1 = con.step_response(tf_pt1 * delay_tf_pt1) #first order transfer function is given by ############################################################################### # steady_state * (e ^ - (delay * s)) # # transfer_function(s) = ------------------------------------ # # (time_constant * s + 1 ) # ############################################################################### return tf_pt1 * delay_tf_pt1, yout_pt1, t_pt1, delay, time_constant, steady_state, tf_pt1
def test_import_export(self): sys = ctrl.tf([1], [100, 1]) sim_duration = 2000 time = np.zeros(sim_duration) i = 0 while (i < sim_duration): time[i] = i i += 1 _, output = ctrl.step_response(sys, time) m = ps.FsrModel(output, t=time) # testing our model with a test signal test_sgnl_len = int(2500) u = np.zeros(test_sgnl_len) for i in range(test_sgnl_len): u[i] = 1 time = np.zeros(test_sgnl_len) for i in range(test_sgnl_len): time[i] = i _, comp, _ = ctrl.forced_response(sys, time, u) # 'rb' and 'wb' to avoid problems under Windows! with open("temp", "w") as fh: ps.export_csv(m, fh) with open("temp", "r") as fh: m = ps.import_csv(fh) os.remove("temp") _, y = ps.forced_response(m, time, u) self.assertTrue(np.allclose(y, comp, rtol=1e-2), "import/export broke")
def pidplot(nlg,dlg,nlh,dlh): G = control.tf(nlg,dlg) s1="(" s2="(" s=str(G) s=s.split('\n') s[1]=s[1].strip() s[3]=s[3].strip() s1=s1+s[1]+')' s2=s2+s[3]+')' t1,y1 =control.step_response(G) plt.plot(t1,y1,'b',linewidth=1,label='G(s)') plt.grid(True) plt.title('Time response of G(s)='+(s1)+'/'+(s2)) plt.xlabel('Time(sec)') plt.ylabel('Amplitude') if not os.path.isdir('static'): os.mkdir('static') else: # Remove old plot files for filename in glob.glob(os.path.join('static', 'Feedback','pidc.png')): os.remove(filename) pidc=os.path.join('static', 'Feedback' ,'pidc.png') plt.savefig(pidc) plt.clf() plt.cla() plt.close() return pidc
def plot_step(self, fig): if self.settings.is_step_default(): t, y = control.step_response(self.tf) else: tmax = self.settings.get_step_time_max() step = self.settings.get_step_step() t = np.arange(0, tmax, step) _, y = control.step_response(self.tf, t) fig.clf() ax = fig.add_subplot(1, 1, 1) ax.plot(t, y) ax.set_xlabel('Time') ax.set_ylabel('Amplitude (s)') return fig
def plot_loops(name, G_ol, G_cl): # type: (str, control.tf, control.tf) -> None """ Plot loops :param name: Name of axis :param G_ol: open loop transfer function :param G_cl: closed loop transfer function """ plt.figure() plt.plot(*control.step_response(G_cl, np.linspace(0, 1, 1000))) plt.title(name + ' step response') plt.grid() plt.figure() control.bode(G_ol) print('margins', control.margin(G_ol)) plt.subplot(211) plt.title(name + ' open loop bode plot') plt.figure() control.rlocus(G_ol, np.logspace(-2, 0, 1000)) for pole in G_cl.pole(): plt.plot(np.real(pole), np.imag(pole), 'rs') plt.title(name + ' root locus') plt.grid()
def pidplot1(nlg, dlg, nlh, dlh): G = control.tf(nlg, dlg) H = control.tf(nlh, dlh) s = str(H) s1 = "(" s2 = "(" s = s.split('\n') s[1] = s[1].strip() s[3] = s[3].strip() s1 = s1 + s[1] + ')' s2 = s2 + s[3] + ')' v = control.feedback(G, H) t2, y2 = control.step_response(v) plt.plot(t2, y2, 'r', linewidth=1, label='G(s) with Feedback H(s)') plt.grid(True) plt.title('Time response of G(s) with feedback H(s)=G(s)/(1+G(s)H(s))') plt.xlabel('Time(sec)') plt.ylabel('Amplitude') if not os.path.isdir('static'): os.mkdir('static') else: # Remove old plot files for filename in glob.glob( os.path.join('static', 'Feedback', 'pidc1.png')): os.remove(filename) pidc1 = os.path.join('static', 'Feedback', 'pidc1.png') plt.savefig(pidc1) plt.clf() plt.cla() plt.close() return pidc1
def creation_example(): """Example for creation of a FSR model with python-control.""" # creating a step response for our model sys = ctrl.tf([1], [100, 1]) sim_duration = 2000 time = np.arange(sim_duration) _, output = ctrl.step_response(sys, time) # creating the model model = ps.FsrModel(output, t=time) # creating a test input signal u = np.ones(sim_duration) for i in range(len(u)): if i < 500: u[i] = 0.001 * i # getting response from our model t1, y1 = ps.forced_response(model, time, u) # simulating a reference with control t2, y2, _ = ctrl.forced_response(sys, time, u) # show everything ax = plt.subplot(111) plt.plot(t1, y1, label="Model response") plt.plot(t2, y2, label="Reference response") plt.plot(t1, u, label="Input signal") ax.legend() plt.title("pystrem example") plt.show()
def Bode_Margin(sys, omega): w = omega mag, phaserad, w = ctrl.bode(sys, w) magdb = 20 * log(mag) phasedeg = phaserad * 180 / pi gm, pm, wg, wp = ctrl.margin(sys) a1 = f.add_subplot(221) a1.set_xscale("log") a1.plot(w, magdb) a1.plot(wp, 0, '.y') a1.text(wp, 0 + 25, "wc=%.2f" % wp) # a1.title = "Bode" # a1.ylabel = "Magnitude dB " # a1.xlabel = "Angular frequency" a2 = f.add_subplot(223) a2.set_xscale("log") a2.plot(w, phasedeg) a2.plot(wp, pm - 180, '.y') a2.text(wp, pm - 180 + 25, "phase=%.2f" % (pm - 180)) # a2.ylabel = "Phase (degree) " # a2.xlabel = "Angular frequency" a3 = f.add_subplot(122) sysF = sys / (1 + sys) T = np.arange(0, 30, 0.5) T, yout = ctrl.step_response(sysF, T) a3.plot(T, yout) # a3.title = "step response" # a3.xlabel = "time" # a3.ylabel = "Magnitude" return wp, pm
def test_response_transpose(self, nstate, nout, ninp, squeeze, ysh_in, ysh_no, xsh_in): sys = ct.rss(nstate, nout, ninp) T = np.linspace(0, 1, 8) # Step response - input indexed t, y, x = ct.step_response(sys, T, transpose=True, return_x=True, squeeze=squeeze) assert t.shape == (T.size, ) assert y.shape == ysh_in assert x.shape == xsh_in # Initial response - no input indexing t, y, x = ct.initial_response(sys, T, 1, transpose=True, return_x=True, squeeze=squeeze) assert t.shape == (T.size, ) assert y.shape == ysh_no assert x.shape == (T.size, sys.nstates)
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 test_forced_response_legacy(self): # Define a system for testing sys = ct.rss(2, 1, 1) T = np.linspace(0, 10, 10) U = np.sin(T) """Make sure that legacy version of forced_response works""" ct.config.use_legacy_defaults("0.8.4") # forced_response returns x by default t, y = ct.step_response(sys, T) t, y, x = ct.forced_response(sys, T, U) ct.config.use_legacy_defaults("0.9.0") # forced_response returns input/output by default t, y = ct.step_response(sys, T) t, y = ct.forced_response(sys, T, U) t, y, x = ct.forced_response(sys, T, U, return_x=True)
def step(tf_list=[], N=100, T=None, name=None): data = [] T_max = get_T_max(tf_list, T=T, N=N) for index, tf in enumerate(tf_list): if ctl.isctime(tf): T = np.linspace(0, T_max, N) line_shape = "linear" else: T = np.arange(0, T_max, tf.dt) line_shape = "hv" t, y = ctl.step_response(tf, T=T) tf_name = "tf {}".format(index + 1) data.append({ "x": np.ravel(t), "y": np.ravel(y), "name": tf_name, "mode": "lines", "showlegend": False, "line_shape": line_shape }) layout = default_layout("time (s)", "response", name) fig = go.Figure(data, layout=layout) return fig
def tr2(numG, denG, numH, denH): G = control.tf(numG, denG) H = control.tf(numH, denH) k = control.parallel(G, H) s1 = "(" s2 = "(" s = str(k) s = s.split('\n') s[1] = s[1].strip() s[3] = s[3].strip() s1 = s1 + s[1] + ')' s2 = s2 + s[3] + ')' t1, y1 = control.step_response(k) plt.plot(t1, y1, 'b', linewidth=1, label='G(s)') plt.grid(True) plt.title('Time response of Parallel Operation\n' + (s1) + '/' + (s2)) plt.xlabel('Time(sec)') plt.ylabel('Amplitude') if not os.path.isdir('static'): os.mkdir('static') else: # Remove old plot files for filename in glob.glob( os.path.join('static', 'SeriesParallel', 'sp2.png')): os.remove(filename) sp2 = os.path.join('static', 'SeriesParallel', 'sp2.png') plt.savefig(sp2) plt.clf() plt.cla() plt.close() return sp2
def grstep(sys, T=None): """get step response graphically Usage ===== grstep(sys) Inputs ------ sys: system """ if np.isscalar(T): if sys.isctime(): T = np.linspace(0, T) else: T = np.arange(0, T, sys.dt) t, y = ct.step_response(sys, T) if len(y.shape) == 2: N = y.shape[0] for n in range(0, N): plt.plot(t, y[n]) else: plt.plot(t, y) plt.grid() plt.show()
def classic(): # PI controller Kp = 1.5 Ki = 30. P = tf([Kp], [1]) I = tf([Ki], [1, 0]) Gc = parallel(P, I) # Power convertor Gpc = synthesize_2pole_filter(50, 0.707) # Plant Gp = tf([50], [1, 0]) # Sensor # если выбросить из петли становится лучше # "remove sensor lag" Gs = synthesize_1pole_filter(20) # Openloop Gol = series(series(Gc, Gpc), Gp) # Closed loop Gcl = feedback(Gol) ts, xs = step_response( Gcl ) grid() plot(ts, xs)
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 f(X): #F(Kp, Ki, Kd) #Obtendo as constantes a partir da entrada Kp = X[0] Ki = X[1] Kd = X[2] #Definindo as constantes do processo K = 2 CT = 4 s = ct.TransferFunction.s #Equação do sistema de Controle C = Kp + Ki / s + Kd * s #Equação do processo a ser controlado P = K / (CT * s + 1) #Fazendo a retroalimentação T = ct.TransferFunction.feedback(C * P, 1) tempo, resposta = ct.step_response(T) erro = [TARGET_VALUE - resp for resp in resposta] #Cálculo da integral de erro quadratico multiplicado pelo tempo # print(tempo) # print(erro) itse = np.sum(tempo * np.power(erro, 2)) return itse
def assignment2(Kc=Kc, Ki=Ki): #Kc has to be a list; Ki has to be a float # Defining the transfer functions sysgp = control.tf(4, [500, 2]) #Process sysgv = control.tf(2, [1, 10, 1]) #Valve sysgt = control.tf(2, 1) # Sensor syspi_list = [] # Loop to iterate among the different values of Kc for i in Kc: syspi = control.tf([i, i * Ki], [1, 0]) syspi_list.append(syspi) # Plotting the figures with the different values of Kc plt.figure() for i in range(len(syspi_list)): #Defining the closed loop syslc = control.feedback(syspi_list[i] * sysgv * sysgp, sysgt) consig = 1 / 2 # The setpoint is 0.5, because the sensor # transfer function is equal to 2 t, y = control.step_response(syslc, 200) error = np.abs(y - consig) # The error while achieving the setpoint plt.plot(t, y, label=f'Kc= {Kc[i]:.2f}') # plt.plot(t, error, label=f'Error para Kc={Kc[i]:.2f}') plt.title(f'Ki= {Ki:.4f}') plt.legend() plt.xlabel('Time (s)') plt.ylabel('Value') plt.show() return syspi_list
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 exercise_2(): # get unknown step response t, y = sr1.unknown_step() # plot unknown step response plt.figure() plt.grid(True) plt.xlabel("$t$ in s") plt.ylabel("$y(t)$") plt.plot(t, y) # create system k_s = 1.38 T = 1.1 T_t = 2.2 sys_2 = system_2(k_s, T, T_t) # plot system step response t = np.linspace(0, 50, 100) t, y = ctl.step_response(sys_2, t) plt.plot(t, y) # plot PID controlled system step response K_P = 1.2 * T / (k_s * T_t) K_I = 0.6 * T / (k_s * T_t**2) K_D = 0.6 * T / k_s t, y = sr1.unknown_step(K_P, K_I, K_D) plt.plot(t, y) # save plot plt.savefig("plots/step_response.png") plt.clf()
def pt2(smooth, time): def fourpoint(z): f1_zeta = 0.451465 + (0.066696 * z) + (0.013639 * z**2) f3_zeta = 0.800879 + (0.194550 * z) + (0.101784 * z**2) f6_zeta = 1.202664 + (0.288331 * z) + (0.530572 * z**2) f9_zeta = 1.941112 - (1.237235 * z) + (3.182373 * z**2) return f1_zeta, f3_zeta, f6_zeta, f9_zeta def method(): #the second method from the article is adopted, as the response/data handled strictly follows this method. zeta = np.sqrt( (np.log(overshoot)**2) / ((np.pi**2) + (np.log(overshoot)**2))) f1_zeta, f3_zeta, f6_zeta, f9_zeta = fourpoint(zeta) time_constant = (t9 - t1) / (f9_zeta - f1_zeta) #delay = t1 - time_constant*f1_zeta #based on article. delay = smoothed_df.time[smoothed_df.smoothed < 0.02].values[-1] return zeta, time_constant, delay smoothed_df = pd.concat([pd.DataFrame(smooth, columns = ['smoothed']), \ pd.DataFrame(time, columns = ['time'])], axis = 1) steady_state = smooth[-1] #ssn = steady state at n/10th instant of time ss1 = steady_state * 0.1 ss3 = steady_state * 0.3 ss6 = steady_state * 0.6 ss9 = steady_state * 0.9 #tn = time at n/10th instant t1 = smoothed_df.time[smoothed_df.index == abs( smoothed_df.smoothed - ss1).sort_values().index[0]].values[0] t3 = smoothed_df.time[smoothed_df.index == abs( smoothed_df.smoothed - ss3).sort_values().index[0]].values[0] t6 = smoothed_df.time[smoothed_df.index == abs( smoothed_df.smoothed - ss6).sort_values().index[0]].values[0] t9 = smoothed_df.time[smoothed_df.index == abs( smoothed_df.smoothed - ss9).sort_values().index[0]].values[0] peak = smoothed_df.smoothed.max() #returns the highest output in the response overshoot = (peak - steady_state) / steady_state #represented as Mp in article zeta, time_constant, delay = method() tf_pt2 = con.tf(steady_state, [time_constant**2, 2 * zeta * time_constant, 1]) n_2, d_2 = con.pade(delay, 1) delay_tf_pt2 = con.tf(n_2, d_2) t_pt2, yout_pt2 = con.step_response(tf_pt2 * delay_tf_pt2) #second order transfer function is given by ######################################################################################################## # steady_state * (e ^ - (delay * s)) # # transfer_function(s) = ---------------------------------------------------------------------- # # ((time_constant ^ 2) * (s ^ 2)) + (2 * zeta * time_constant * s) + 1 ) # ######################################################################################################## return tf_pt2 * delay_tf_pt2, yout_pt2, t_pt2, delay, time_constant, steady_state, zeta, tf_pt2
def plot_response(sys, T=None, U=0.0, impulse=True, step=True) -> None: if impulse: t, yout = control.impulse_response(sys, T=T, X0=U) plot_params(t, yout) if step: t, yout = control.step_response(sys, T=T, X0=U) plot_params(t, yout) return
def Q2_perfFCN(Kp, Ti, Td): G = Kp * tf([Ti * Td, Ti, 1.0], [Ti, 0]) sys = feedback(series(G,F),1) res = step_response(sys, t) ISE = sum((val - 1)**2 for val in res[1]) return (ISE,) + stepinfo(res)
def test_IT2_forced_response(self): sys = ctrl.tf([100], [50, 1000, 150, 0]) # IT2 _, o = ctrl.step_response(sys, self.time) m = ps.FsrModel(o, t=self.time, optimize=False) _, y = ps.forced_response(m, self.t, self.u) _, o, _ = ctrl.forced_response(sys, self.t, self.u) self.assertTrue(np.allclose(y, o, rtol=1e-2), "it2 response broke")
def analysis(): """Plot open-loop responses for various inputs""" g = plant() t = np.linspace(0, 10, 101) _, yu1 = step_response(g, t, input=0) _, yu2 = step_response(g, t, input=1) yu1 = yu1 yu2 = yu2 # linear system, so scale and sum previous results to get the # [1,-1] response yuz = yu1 - yu2 plt.figure(1) plt.subplot(1, 3, 1) plt.plot(t, yu1[0], label='$y_1$') plt.plot(t, yu1[1], label='$y_2$') plt.xlabel('time') plt.ylabel('output') plt.ylim([-1.1, 2.1]) plt.legend() plt.title('o/l response\nto input [1,0]') plt.subplot(1, 3, 2) plt.plot(t, yu2[0], label='$y_1$') plt.plot(t, yu2[1], label='$y_2$') plt.xlabel('time') plt.ylabel('output') plt.ylim([-1.1, 2.1]) plt.legend() plt.title('o/l response\nto input [0,1]') plt.subplot(1, 3, 3) plt.plot(t, yuz[0], label='$y_1$') plt.plot(t, yuz[1], label='$y_2$') plt.xlabel('time') plt.ylabel('output') plt.ylim([-1.1, 2.1]) plt.legend() plt.title('o/l response\nto input [1,-1]')
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
def step_opposite(g, t): """reponse to step of [-1,1]""" _, yu1 = step_response(g, t, input=0) _, yu2 = step_response(g, t, input=1) return yu1 - yu2
cls() Kt = 1.0 Jt = 1.0 # [?] u1 = tf([Kt], [1]) u2 = tf([1 / Jt], [1]) # fixme: как добавить сигнал шума? u12 = series(u1, u2) u3 = tf([1], [1, 0]) u4 = copy.deepcopy(u3) u34 = series(u3, u4) # похоже нельзя соединить аналоговую и дискретную u34_d0 = c2d(u3, Ts=0.5) u34_d = c2d(u3, Ts=0.5) print series(u34_d0, u34_d) u14 = series(u12, u34) print u14 ts, xs = step_response(u14) # print (c2d(u14, Ts=0.5)) plot(ts, xs) grid() show()
# #### additional code for comparision A, B, C, D = get_linear_ct_model(theStateAdmin, sys_output) # create a control system with the python-control-toolbox, see # https://github.com/python-control/python-control import control cs = control.StateSpace(A, B, C, D) # use default method (zero oder hold (zoh)) cs_dt = control.sample_system(cs, 0.05) # calculate step-response for first input __, yy_dt = control.step_response(cs_dt, T=tt, input=0) # in the time-discrete case the result is shortened by one value. -> repeat the last one. yy_dt = np.column_stack((yy_dt, yy_dt[:, -1])) # __, yy_dt = control.step_response(cs,T=tt, input=0) # #### end of additional code if __name__ == "__main__": pl.plot(tt, bo[SUM1], "b-", lw=3, label="$y_1$ (pyblocksim)") pl.plot(tt, bo[SUM2], "r-", lw=3, label="$y_2$ (pyblocksim)") # +1 because the step_response starts the step at t=0
# Define the system to use in simulation - in transfer function form here num = [2.*z*wn,wn**2]; den = [1,2.*z*wn,wn**2]; sys = control.tf(num,den); # Set up simulation parameters t = np.linspace(0,5,500) # time for simulation, 0-5s with 500 points in-between # run the simulation - utilize the built-in initial condition response function [T,yout] = control.step_response(sys,t) # Make the figure pretty, then plot the results # "pretty" parameters selected based on pdf output, not screen output # Many of these setting could also be made default by the .matplotlibrc file fig = figure(figsize=(6,4)) ax = gca() subplots_adjust(bottom=0.17,left=0.17,top=0.96,right=0.96) setp(ax.get_ymajorticklabels(),family='CMU Serif',fontsize=18) setp(ax.get_xmajorticklabels(),family='CMU Serif',fontsize=18) ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') ax.grid(True,linestyle=':',color='0.75') ax.set_axisbelow(True)
# 超调量 print("Mp (%): ", (yout.max() / yout[-1] - 1) * 100) # 峰值时间 print("Tp: ", t[numpy.argmax(yout)]) # 上升时间 print("Tr: ", t[next(i for i in range(0, len(yout) - 1) if yout[i] > yout[-1])]) # 调整时间 offset = 0.05 # 最大误差容许范围 print("Ts: ", t[next(len(yout) - i for i in range(2, len(yout) - 1) if abs(yout[-i] / yout[-1] - 1) > offset)]) # 化简分母 S = sympy.symbols('S') denominator = (S**2 + 0.6*S + 1) * (S**2 + 3*S + 9) * (S + 5) denominator = denominator.expand() # 化简表达式 denominator = sympy.poly(denominator, S).all_coeffs() # 转成多项式 list denominator = list(map(float, denominator)) # convert sympy.core.numbers.Float to float numerator = [45.] sys = control.matlab.tf(numerator, denominator) # 阶跃 T, yout = control.step_response(sys) step_info(T, yout) # 绘图 plot(T, yout) title("System Step Response") xlabel("time / sec") ylabel("response / value") show()
plt.semilogx(omega, 20 * np.log10(s1mag.flat), label='$S_1$') plt.semilogx(omega, 20 * np.log10(s2mag.flat), label='$S_2$') # -1 in logspace is inverse plt.semilogx(omega, -20 * np.log10(ws1mag.flat), label='$1/w_{P1}$') plt.semilogx(omega, -20 * np.log10(ws2mag.flat), label='$1/w_{P2}$') plt.ylim([-80, 10]) plt.xlim([1e-2, 1e2]) plt.xlabel('freq [rad/s]') plt.ylabel('mag [dB]') plt.legend() plt.title('Sensitivity and sensitivity weighting frequency responses') # time response time = np.linspace(0, 3, 201) _, y1 = step_response(t1, time) _, y2 = step_response(t2, time) # gd injects into the output (that is, g and gd are summed), and the # closed loop mapping from output disturbance->output is S. _, y1d = step_response(s1 * gd, time) _, y2d = step_response(s2 * gd, time) plt.figure(2) plt.subplot(1, 2, 1) plt.plot(time, y1, label='$y_1(t)$') plt.plot(time, y2, label='$y_2(t)$') plt.ylim([-0.1, 1.5]) plt.xlim([0, 3]) plt.xlabel('time [s]')
def plot_loops(name, G_ol, G_cl): """ Plot loops :param name: Name of axis :param G_ol: open loop transfer function :param G_cl: closed loop transfer function """ plt.figure() plt.plot(*control.step_response(G_cl, np.linspace(0, 1, 1000))) plt.title(name + ' step resposne') plt.grid() plt.figure() control.bode(G_ol) print('margins', control.margin(G_ol)) plt.subplot(211) plt.title(name + ' open loop bode plot') plt.figure() control.rlocus(G_ol, np.logspace(-2, 0, 1000)) for pole in G_cl.pole(): plt.plot(np.real(pole), np.imag(pole), 'rs') plt.title(name + ' root locus') plt.grid()