def Pole(W): con.pzmap(W) plt.plot() plt.grid(True) plt.show() print('Оценка по распределению корней:') Pol = con.pole(W) # print(Pol) P = [] """ Показатель колебательности характеризует склонность системы к колебаниям: чем выше М, тем менее качественна система при прочих равных условиях. Считается допустимым, если 1,1 < М < 1,5. """ degreeovershoot_M = [] for i in Pol: k = complex(i) if k.real != 0: P.append(k.real) m = k.imag / k.real degreeovershoot_M.append(m) a_min = max(P) t_reg = abs(1 / a_min) overshooting = math.exp(math.pi / max(degreeovershoot_M)) psi = 1 - math.exp((-2) * math.pi / max(degreeovershoot_M)) print("a_min= ", a_min) print("Время пп: ", t_reg, " c") print("Степень колебательности: ", max(degreeovershoot_M)) print("Перерегулирование: ", overshooting) print("Степень затухания: ", psi)
def full_analyze(self): """ complex research definition :return: keys for handle changing regulator quality """ k = [] print("\n", "*" * 40, "\n" "STEP RESPONCE:\n") k.extend(self.get_trans_func()) print("\n", "*" * 40, "\n" "POLES ANALYZE:\n") poles, zeros = pzmap(self.w) if poles != []: k.extend(self.get_poles_analyze(poles)) else: print("Корней нет!!!") print("\n", "*" * 40, "\n" "BODE FUNCTION:\n") k.extend(self.get_bode_func()) return k
def pzmap(W): con.pzmap(W) plt.title("Расположение нулей на комплексной плоскости") plt.grid(True) plt.show()
def testPZmap(self, siso, subsys, mplcleanup): """Call pzmap()""" # pzmap(siso.ss1); not implemented # pzmap(siso.ss2); not implemented pzmap(getattr(siso, subsys)) pzmap(getattr(siso, subsys), plot=False)
# teta = 0.0 # np.arccos([eps]) # eps = np.cos(teta) ''' ################################################################################ # Input - S (ex: s=-2.5 + 2j) para verificar se cruza a LGR ################################################################################ ''' # x_s = -2.5 # real # y_s = 2 # complexo # teta = np.arctan(np.abs(y_s)/np.abs(x_s)) # eps = np.cos(teta) ################################################################################ # polos e zeros plotados ################################################################################ (p, z) = ctl.pzmap(G) print('polos =', p) print('zeros =', z) ################################################################################ # Lugar geometrico das raizes (LGR) ################################################################################ rlist, klist = ctl.rlocus(G) # rlist - lugar geometrico das raizes # klist - ganhos correspondentes # plotar linha baseada no LGR para achar interseção real = [] im = [] try: for j in range(len(rlist)): real.append(rlist[j][ramo].real)
# Expansao em fracoes parciais # caso nao haja multiplos polos: # B(s) R(1) R(2) R(n) # ---- = -------- + -------- + ... + -------- + K(s) # A(s) s - P(1) s - P(2) s - P(n) # print('-------------') print('EXPANSAO EM FRACOES PARCIAIS') B = K1 * Km * Kg A = [1, a + am, a * am, 0] [R, P, K] = sc.signal.residue(B, A) print('R =', R) print('P =', P) print('K =', K) # Plot dos polos e zeros PZMAP co.pzmap(Gtheta, grid=True) # Resposta Transitoria S = co.stepinfo(Gtheta) print('-------------') print('CARACTERISTICAS DA RESPOSTA TRANSITORIA DO SISTEMA') print('tempo de subida tr = ', '%.2f' % S['RiseTime'], 'seg') print('tempo de acomodacao ts = ', '%.2f' % S['SettlingTime'], 'seg') print('maximo sobresinal Mp = ', S['Overshoot']) print('valor de pico thetaomax = ', '%.2f' % S['Peak']) print('instante de pico tp = ', '%.2f' % S['PeakTime'], 'seg') print('valor de regime estacionario thetaoss = ', '%.2f' % S['SteadyStateValue']) # Resposta a degrau da planta plt.figure(2) thetao, t = co.step(Gtheta) plt.plot(t, thetao)
print(lastElem * 1.05, " ", lastElem * 0.95, " ", y[-k]) ind = k break ind = len(x) - ind #print("Точка пересечения с +-5 % ",x[ind]) print("время регулирования: ", x[ind]) else: print("система расходится, время регулирования не определить") #print("отношение последнего к предпоследнему",y[-1]/y[-2]) graph("Переходная функция", y, x, "Amplitude", "Time", "b") #_______________________________________________________________________________________________________________ w_den = ml.tf(w.den[0][0], [1]) crt = ml.pzmap(w_den) plt.close() #если берем от знаменателя - а от него берём чтобы считать только полюса, нужно [1] first_elem = crt[1] print("Значения полюсов передаточной функции:") minim = [] for ans in first_elem: print("анс ту____________________________________________т") print(ans) print(re(ans)) min_ans = re(first_elem[0]) minim.append(first_elem[0]) for i in range(1, len(first_elem)): if math.fabs(re(first_elem[i])) < math.fabs(min_ans): minim = [] minim.append(first_elem[i])
# Expansao em fracoes parciais # caso nao haja multiplos polos: # B(s) R(1) R(2) R(n) # ---- = -------- + -------- + ... + -------- + K(s) # A(s) s - P(1) s - P(2) s - P(n) # print('-------------') print('EXPANSAO EM FRACOES PARCIAIS') B = K1*Km*Kg; A = [1, a+am, a*am]; [R,P,K]=sc.signal.residue(B,A) print('R =',R) print('P =',P) print('K =',K) # Plot dos polos e zeros PZMAP co.pzmap(Gomega,grid=True) # Resposta Transitoria S=co.stepinfo(Gomega) print('-------------') print('CARACTERISTICAS DA RESPOSTA TRANSITORIA DO SISTEMA') print('tempo de subida tr = ','%.2f' % S['RiseTime'],'seg') print('tempo de acomodacao ts = ','%.2f' % S['SettlingTime'],'seg') print('maximo sobresinal Mp = ',S['Overshoot']) print('valor de pico omegaomax = ','%.2f' % S['Peak']) print('instante de pico tp = ','%.2f' % S['PeakTime'],'seg') print('valor de regime estacionario omegaoss = ','%.2f' % S['SteadyStateValue']) # Resposta a degrau da planta plt.figure(2) omegao, t = co.step(Gomega) plt.plot(t,omegao) plt.title('Resposta a degrau da planta')
#% Calculo dos polos da funcao de transferencia Gp print(co.pole(Gp)) #% #% Expansao em fracoes parciais #% caso nao haja multiplos polos: #% B(s) R(1) R(2) R(n) #% ---- = -------- + -------- + ... + -------- + K(s) #% A(s) s - P(1) s - P(2) s - P(n) #% B=K1*Km*Kg; A=[1,a+am,a*am,0] print(sympy.apart(Gp)) #% #% Plot dos polos e zeros de Gm #% co.pzmap(Gp) #% Resposta a entrada degrau do sistema tspan = np.linspace(0,10,int(10//0.02)) print(tspan) tspan = tspan.reshape(-1,1) y,t = co.step(Gp,tspan) plt.figure(2) plt.plot(t,y) plt.title("Step response") plt.xlabel("Tempo[s]") plt.ylabel("Amplitude") plt.grid() # ##% Caracteristicas da resposta a degrau #print(co.stepinfo(Gp))
def ZN_Method(): """ Функция исполнения метода Зиглера-Николса для подбора параметров регулятора :return: """ def is_on_border(poles): """ функция выявляет, есть ли во входящем массиве полюсов такие, которые находятся на границе устойчивости :param poles: полюса :return: true/false """ a = True counter = 1 print("Полюса плоскости: ") for pole in poles: if -0.001 < pole.real < 0: # корень в левой полуплоскости a = False print("Полюс ", counter, " : ", pole) counter += 1 print("Система на границе устойчивости" if not a else "По критерию полюсов система устойчива") return a def second_var(): """ Второй способ релизации метода Зиглера-Никольса :return: время западнывания tet, постоянную времени T и коэффициент передачи k """ # получает передаточную функцию объекта управления w = SchemeBody().get_scheme_solving() t = np.linspace(0, stop=100, num=2000) y1, t1 = step(w, t) y1 = list(y1) max_dif = 0 # номер элемента в списке, имеющего максимальную разницу с предыдущим nmd = 0 for num, yy in enumerate(y1[1:]): if (yy - y1[num]) > max_dif: max_dif, nmd = (yy - y1[num]), (num + 1) if y1[num - 1] < y1[num] > y1[ num + 1]: # дошли до первого максимума, отбой break # находим время запаздывания и постоянную времени через уравенение прямой tet = -y1[nmd] / (y1[nmd] - y1[nmd - 1]) * (t[nmd] - t[nmd - 1]) + t[nmd] T = (y1[-1] - y1[nmd]) / (y1[nmd] - y1[nmd - 1]) * (t[nmd] - t[nmd - 1]) + t[nmd] return tet, T, y1[num] Kk = 0 flag = True # создаем объект пропорционального регулятора с начальными параметрами regulator = ProportionalRegulator() # калибровка регулятора, поиск критического состояния САУ while flag: regulator.set_regulator_coefficients(k=Kk) # объект класса САУ grand_gear_function = SchemeBody( regs_w=regulator.get_TrFunc_proportional_regulator()) # передаточная функция САУ с регулятором w = grand_gear_function.get_scheme_solving() poles, zeros = pzmap(w, Plot=False) if size(poles) > 0: # есть ли корень на границе устойчивости flag = is_on_border(poles) if not flag: break Kk += 0.1 print("Кп: ", round(Kk, 3)) # находим период переходной характеристики Tt = plot_trans_func(w, toPlotTrans=True, toFindT=True) print("Период колебательной переходной характеристики: ", round(Tt, 6)) # создаем новый объект ПИД-регулятора regulator = PIDRegulator() # устанавливаем параметры по методу Зиглера-Николса regulator.set_regulator_coefficients(k=0.6 * Kk, Td=3 / 40 * Tt * Kk, Tu=1.2 * Kk / Tt) grand_gear_function = SchemeBody( regs_w=regulator.get_TrFunc_pid_regulator()) # передаточная функция САУ с регулятором w = grand_gear_function.get_scheme_solving() poles, zeros = pzmap(w, Plot=False) if is_sustainable(poles): plot_trans_func(w, toPlotTrans=True) print("Оценка регулирования составляет: ", sum(do_direct_method(w))) return else: print("Система неустойчива! применим другой метод") """ переходим к оценке по второму методу Зиглера-Никольса""" tet, Tt, Kk = second_var() # создаем новый объект ПИД-регулятора regulator2 = PIDRegulator() # устанавливаем параметры по методу Зиглера-Николса regulator2.set_regulator_coefficients(k=1.2 * Tt / (Kk * tet), Td=1.2 * Tt / Kk, Tu=0.6 * Tt / (Kk * tet**2)) grand_gear_function = SchemeBody( regs_w=regulator2.get_TrFunc_pid_regulator()) # передаточная функция САУ с регулятором w = grand_gear_function.get_scheme_solving() poles, zeros = pzmap(w, Plot=False) if is_sustainable(poles) and (0.15 < tet / Tt < 0.6): plot_trans_func(w, toPlotTrans=True) print("Оценка регулирования составляет: ", sum(do_direct_method(w))) else: print("Опять неудача!")
#% Polos e zeros de malha aberta #% print('Polos e zeros - GHw1') print(co.pole(GHw1)) print(co.zero(GHw1)) print('\nPolos e zeros - GHw2') print(co.pole(GHw2)) print(co.zero(GHw2)) print('\nPolos e zeros - GHw3') print(co.pole(GHw3)) print(co.zero(GHw3)) #% #% Plot com os polos e zeros de malha aberta #% co.pzmap(GHw1, title="GHw1") co.pzmap(GHw2, title="GHw2") co.pzmap(GHw3, title="GHw3") #plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.45) # # #plt.subplot(3,1,1) #co.pzmap(GHw1) #plt.title('m. aberta GHw1') ##axis equal # #plt.subplot(3,1,2) #co.pzmap(GHw2) #plt.title('m. aberta GHw2') ##axis equal
#% Calculo dos polos da funcao de transferencia Gm print(co.pole(Gomega)) #% #% Expansao em fracoes parciais #% caso nao haja multiplos polos: #% B(s) R(1) R(2) R(n) #% ---- = -------- + -------- + ... + -------- + K(s) #% A(s) s - P(1) s - P(2) s - P(n) #% B = K1 * Km * Kg A = [1, a + am, a * am] print(sympy.apart(Gomega)) #% #% Plot dos polos e zeros de Gm #% co.pzmap(Gomega) #% Resposta a entrada degrau do sistema tspan = np.linspace(0, 10, int(10 // 0.02)) print(tspan) tspan = tspan.reshape(-1, 1) y, t = co.step(Gomega, tspan) plt.figure(2) plt.plot(t, y) plt.title("Step response") plt.xlabel("Tempo[s]") plt.ylabel("Amplitude") plt.grid() ##% Caracteristicas da resposta a degrau print(co.stepinfo(Gomega))
#% Polos e zeros de maplha aberta #% print('Polos e zeros - GHp1') print(co.pole(GHp1)) print(co.zero(GHp1)) print('\nPolos e zeros - GHp2') print(co.pole(GHp2)) print(co.zero(GHp2)) print('\nPolos e zeros - GHp3') print(co.pole(GHp3)) print(co.zero(GHp3)) #% #% Plot com os polos e zeros de malha aberta #% co.pzmap(GHp1, title = "GHp1") co.pzmap(GHp2,title = "GHp2") co.pzmap(GHp3, title = "GHp3") #figure(1); #subplot(1,3,1); #pzplot(GHp1); #title('m. aberta GHp1'); #axis equal; #subplot(1,3,2); #pzplot(GHp2); #title('m. aberta GHp2'); #axis equal; #subplot(1,3,3); #pzplot(GHp3); #title('m. aberta GHp3');