Código fuente para simulacionHandler

""" 
Archivo para el manejo de la función de simulación de sistemas de control, sirve de intermediario entre la interfaz grafica y la clase creada para manejar la simulación en una hilo distinto, esto es debido al tiempo que puede llegar a tomar cada simulación
"""

from rutinas.metodos_RK import (runge_kutta2, runge_kutta3, runge_kutta4, runge_kutta5,
                                heun3, ralston3, SSPRK3, ralston4, tres_octavos4,
                                bogacki_shampine23, fehlberg45, cash_karp45, dopri54, norm)

from rutinas.rutinas_fuzzy import FuzzyController
from rutinas.rutinas_simulacion import *
from rutinas.rutinas_rk import *
from PySide2 import QtGui, QtWidgets

import numpy as np

import json


[documentos]def SimulacionHandler(self): """ Función principal para el manejo de la funcionalida de simulación de sistemas de control, se crean las señales a ejecutar cuando se interactúa con los widgets incluyendo las validaciones de entradas """ self.main.progressBar.hide() self.main.controller1Frame.hide() self.main.controller2Frame.hide() self.main.kpFrame.show() self.main.kiFrame.show() self.main.kdFrame.show() self.main.simularButton.clicked.connect(lambda: calcular_simulacion(self)) self.main.tfradioButton4.toggled.connect(lambda: simulacion_stacked_to_tf(self)) self.main.ssradioButton4.toggled.connect(lambda: simulacion_stacked_to_ss(self)) self.main.loadController1.clicked.connect(lambda: get_pathcontroller1(self)) self.main.loadController2.clicked.connect(lambda: get_pathcontroller2(self)) self.main.esquemaSimulacion.currentIndexChanged.connect(lambda: accion_esquema_selector(self)) self.main.defaultConfiguration.clicked.connect(lambda: restablecer_configuracion(self)) # Validaciones de entradas self.main.tfnumEdit4.editingFinished.connect(lambda: tfnum_validator(self)) self.main.tfdemEdit4.editingFinished.connect(lambda: tfdem_validator(self)) self.main.tfdelayEdit4.editingFinished.connect(lambda: tfdelay_validator(self)) self.main.tfperiodoEdit4.editingFinished.connect(lambda: tfperiodo_validator(self)) self.main.ssAEdit4.editingFinished.connect(lambda: ssA_validator(self)) self.main.ssBEdit4.editingFinished.connect(lambda: ssB_validator(self)) self.main.ssCEdit4.editingFinished.connect(lambda: ssC_validator(self)) self.main.ssDEdit4.editingFinished.connect(lambda: ssD_validator(self)) self.main.ssdelayEdit4.editingFinished.connect(lambda: ssdelay_validator(self)) self.main.ssperiodoEdit4.editingFinished.connect(lambda: ssperiodo_validator(self)) self.main.tiempoSimulacion.editingFinished.connect(lambda: tiempo_validator(self)) self.main.escalonSimulacion.editingFinished.connect(lambda: escalon_validator(self)) self.main.escalonAvanzado.editingFinished.connect(lambda: escalonAvanzado_validator(self)) self.main.padeOrder.editingFinished.connect(lambda: pade_validator(self)) self.main.rtolLineEdit.editingFinished.connect(lambda: rtol_validator(self)) self.main.atolLineEdit.editingFinished.connect(lambda: atol_validator(self)) self.main.maxStepIncr.editingFinished.connect(lambda: maxstep_validator(self)) self.main.minStepDecr.editingFinished.connect(lambda: minstep_validator(self)) self.main.safetyFactor.editingFinished.connect(lambda: safetyFactor_validator(self)) self.main.numSensor.editingFinished.connect(lambda: sensornum_validator(self)) self.main.demSensor.editingFinished.connect(lambda: sensordem_validator(self)) self.main.numAccionador.editingFinished.connect(lambda: accionadornum_validator(self)) self.main.demAccionador.editingFinished.connect(lambda: accionadordem_validator(self)) self.main.inferiorSaturador.editingFinished.connect(lambda: inferiorSaturador_validator(self)) self.main.superiorSaturador.editingFinished.connect(lambda: superiorSaturador_validator(self)) self.main.kpSimulacion.editingFinished.connect(lambda: kp_validator(self)) self.main.kiSimulacion.editingFinished.connect(lambda: ki_validator(self)) self.main.kdSimulacion.editingFinished.connect(lambda: kd_validator(self)) self.main.NSimulacion.editingFinished.connect(lambda: N_validator(self)) restablecer_configuracion(self)
[documentos]def tfnum_validator(self): """ Validación del numerador de la función de transferencia """ try: _ = json.loads(self.main.tfnumEdit4.text()) except ValueError: self.error_dialog.setInformativeText( "Formato no valido, los coeficientes deben estar entre corchetes y separados por comas.\n i.g., [1, 2, 3]" ) self.error_dialog.exec_() self.main.tfnumEdit4.setFocus() return
[documentos]def tfdem_validator(self): """ Validación del denominador de la función de transferencia """ try: _ = json.loads(self.main.tfdemEdit4.text()) except ValueError: self.error_dialog.setInformativeText( "Formato no valido, los coeficientes deben estar entre corchetes y separados por comas.\n i.g., [1, 2, 3]" ) self.error_dialog.exec_() self.main.tfdemEdit4.setFocus() return
[documentos]def tfdelay_validator(self): """ Validación del delay de la función de transferencia """ try: _ = float(self.main.tfdelayEdit4.text()) if _ < 0: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Delay no valido, debe ser un numero real mayor o igual que cero") self.error_dialog.exec_() self.main.tfdelayEdit4.setFocus() return
[documentos]def tfperiodo_validator(self): """ Validación del periodo de muestreo de la función de transferencia """ try: _ = float(self.main.tfperiodoEdit4.text()) if _ <= 0: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Periodo de muestreo no valido, debe ser un numero real mayor que cero") self.error_dialog.exec_() self.main.tfperiodoEdit4.setFocus() return
[documentos]def ssA_validator(self): """ Validación de la matriz de estados de la ecuación de espacio de estados """ try: _ = json.loads(self.main.ssAEdit4.text()) except ValueError: self.error_dialog.setInformativeText( "Formato no valido, las matrices deben estar definidas entre corchetes con cada fila delimitada por otro par de corchetes y separadas entre si por comas, cada valor deberá ir separado por coma.\n i.g., [[1, 1], [1, -1]]" ) self.error_dialog.exec_() self.main.ssAEdit4.setFocus() return
[documentos]def ssB_validator(self): """ Validación de la matriz de entrada de la ecuación de espacio de estados """ try: _ = json.loads(self.main.ssBEdit4.text()) except ValueError: self.error_dialog.setInformativeText( "Formato no valido, las matrices deben estar definidas entre corchetes con cada fila delimitada por otro par de corchetes y separadas entre si por comas, cada valor deberá ir separado por coma.\n i.g., [[1, 1], [1, -1]]" ) self.error_dialog.exec_() self.main.ssBEdit4.setFocus() return
[documentos]def ssC_validator(self): """ Validación de la matriz de salida de la ecuación de espacio de estados """ try: _ = json.loads(self.main.ssCEdit4.text()) except ValueError: self.error_dialog.setInformativeText( "Formato no valido, las matrices deben estar definidas entre corchetes con cada fila delimitada por otro par de corchetes y separadas entre si por comas, cada valor deberá ir separado por coma.\n i.g., [[1, 1], [1, -1]]" ) self.error_dialog.exec_() self.main.ssCEdit4.setFocus() return
[documentos]def ssD_validator(self): """ Validación de la matriz de transmisión directa de la ecuación de espacio de estados """ try: _ = json.loads(self.main.ssDEdit4.text()) except ValueError: self.error_dialog.setInformativeText( "Formato no valido, las matrices deben estar definidas entre corchetes con cada fila delimitada por otro par de corchetes y separadas entre si por comas, cada valor deberá ir separado por coma.\n i.g., [[1, 1], [1, -1]]" ) self.error_dialog.exec_() self.main.ssDEdit4.setFocus() return
[documentos]def ssdelay_validator(self): """ Validación del delay de la ecuación de espacio de estados """ try: _ = float(self.main.ssdelayEdit4.text()) if _ < 0: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Delay no valido, debe ser un numero real mayor o igual que cero") self.error_dialog.exec_() self.main.ssdelayEdit4.setFocus() return
[documentos]def ssperiodo_validator(self): """ Validación del periodo de muestreo de la ecuación de espacio de estados """ try: _ = float(self.main.ssperiodoEdit4.text()) if _ <= 0: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Periodo de muestreo no valido, debe ser un numero real mayor que cero") self.error_dialog.exec_() self.main.ssperiodoEdit4.setFocus() return
[documentos]def tiempo_validator(self): """ Validación del tiempo de simulación """ try: _ = float(self.main.tiempoSimulacion.text()) if _ <= 0: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Tiempo no valido, debe ser un numero real mayor que cero") self.error_dialog.exec_() self.main.tiempoSimulacion.setFocus() return
[documentos]def escalon_validator(self): """ Validación del escalon simple """ try: _ = float(self.main.escalonSimulacion.text()) except ValueError: self.error_dialog.setInformativeText( "Tiempo no valido, debe ser un numero real mayor que cero") self.error_dialog.exec_() self.main.escalonSimulacion.setFocus() return
[documentos]def escalonAvanzado_validator(self): """ Validación del escalon avanzado """ try: _ = json.loads(self.main.escalonAvanzado.text()) if len(_) % 2 != 0: self.error_dialog.setInformativeText( "Escalón avanzado no valido, debe contener una cantidad par de valores con formato: \n [valor1, tiempo1, valor2, tiempo2, ..., valor_n, tiempo_n]") self.error_dialog.exec_() self.main.escalonAvanzado.setFocus() return for i in range(1, len(_) + 1, 2): for j in range(1, len(_) + 1, 2): if j <= i: continue elif _[i] > _[j]: self.error_dialog.setInformativeText( "Escalón avanzado no valido, los valores de tiempo deben cumplir la siguiente condición: \n tiempo1 <= tiempo2 <= tiempo3 <= ... <= tiempo_n") self.error_dialog.exec_() self.main.escalonAvanzado.setFocus() return except ValueError: self.error_dialog.setInformativeText( "Formato no valido, los valores y tiempos deben estar entre corchetes y separados por comas.\n i.g., [1, 2, 0.5, 4, 0.25, 8]") self.error_dialog.exec_() self.main.escalonAvanzado.setFocus() return
[documentos]def pade_validator(self): """ Validación del orden del pade """ try: _ = int(self.main.padeOrder.text()) if _ < 0: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Orden del pade no valido, debe ser un numero entero mayor o igual que cero") self.error_dialog.exec_() self.main.padeOrder.setFocus() return
[documentos]def rtol_validator(self): """ Validación de la tolerancia relativa """ try: _ = float(self.main.rtolLineEdit.text()) if _ <= 0: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Tolerancia relativa no valida, debe ser un numero real mayor que cero, se puede expresar en notación científica\n i.g., 1e-3") self.error_dialog.exec_() self.main.rtolLineEdit.setFocus() return
[documentos]def atol_validator(self): """ Validación de la tolerancia absoluta """ try: _ = float(self.main.atolLineEdit.text()) if _ <= 0: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Tolerancia absoluta no valida, debe ser un numero real mayor que cero, se puede expresar en notación científica\n i.g., 3e-6") self.error_dialog.exec_() self.main.atolLineEdit.setFocus() return
[documentos]def maxstep_validator(self): """ Validación del incremento máximo de paso """ try: _ = float(self.main.maxStepIncr.text()) if _ <= 1: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Incremento máximo de paso no valido, debe ser un numero real mayor que 1" ) self.error_dialog.exec_() self.main.maxStepIncr.setFocus() return
[documentos]def minstep_validator(self): """ Validación del decremento mínimo de paso """ try: _ = float(self.main.minStepDecr.text()) if _ <= 0 or _ >=1: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Decremento mínimo de paso no valido, debe ser un numero real menor que 1 y mayor que cero") self.error_dialog.exec_() self.main.minStepDecr.setFocus() return
[documentos]def safetyFactor_validator(self): """ Validación del factor de seguridad """ try: _ = float(self.main.safetyFactor.text()) if _ <= 0 or _ >= 1: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Factor de seguridad no valido, debe ser un numero real menor que 1 y mayor que cero" ) self.error_dialog.exec_() self.main.safetyFactor.setFocus() return
[documentos]def sensornum_validator(self): """ Validación del numerador de la función de transferencia correspondiente al sensor """ try: _ = json.loads(self.main.numSensor.text()) except ValueError: self.error_dialog.setInformativeText( "Formato no valido, los coeficientes deben estar entre corchetes y separados por comas.\n i.g., [1, 2, 3]" ) self.error_dialog.exec_() self.main.numSensor.setFocus() return
[documentos]def sensordem_validator(self): """ Validación del denominador de la función de transferencia correspondiente al sensor """ try: _ = json.loads(self.main.demSensor.text()) except ValueError: self.error_dialog.setInformativeText( "Formato no valido, los coeficientes deben estar entre corchetes y separados por comas.\n i.g., [1, 2, 3]" ) self.error_dialog.exec_() self.main.demSensor.setFocus() return
[documentos]def accionadornum_validator(self): """ Validación del numerador de la función de transferencia correspondiente al accionador """ try: _ = json.loads(self.main.numAccionador.text()) except ValueError: self.error_dialog.setInformativeText( "Formato no valido, los coeficientes deben estar entre corchetes y separados por comas.\n i.g., [1, 2, 3]" ) self.error_dialog.exec_() self.main.numAccionador.setFocus() return
[documentos]def accionadordem_validator(self): """ Validación del denominador de la función de transferencia correspondiente al accionador """ try: _ = json.loads(self.main.demAccionador.text()) except ValueError: self.error_dialog.setInformativeText( "Formato no valido, los coeficientes deben estar entre corchetes y separados por comas.\n i.g., [1, 2, 3]" ) self.error_dialog.exec_() self.main.demAccionador.setFocus() return
[documentos]def inferiorSaturador_validator(self): """ Validación del limite inferior del saturador """ try: _ = float(self.main.inferiorSaturador.text()) except ValueError: self.error_dialog.setInformativeText( "Limite inferior no valido, debe ser un numero real") self.error_dialog.exec_() self.main.inferiorSaturador.setFocus() return
[documentos]def superiorSaturador_validator(self): """ Validación del limite superior del saturador """ try: _ = float(self.main.superiorSaturador.text()) except ValueError: self.error_dialog.setInformativeText( "Limite superior no valido, debe ser un numero real") self.error_dialog.exec_() self.main.superiorSaturador.setFocus() return
[documentos]def kp_validator(self): """ Validación de la ganancia proporcional """ try: _ = float(self.main.kpSimulacion.text()) if _ < 0: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Ganancia kp no valida, debe ser un numero real mayor o igual que cero") self.error_dialog.exec_() self.main.kpSimulacion.setFocus() return
[documentos]def ki_validator(self): """ Validación de la ganancia integral """ try: _ = float(self.main.kiSimulacion.text()) if _ < 0: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Ganancia ki no valida, debe ser un numero real mayor o igual que cero") self.error_dialog.exec_() self.main.kiSimulacion.setFocus() return
[documentos]def kd_validator(self): """ Validación de la ganancia derivativa """ try: _ = float(self.main.kdSimulacion.text()) if _ < 0: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Ganancia kd no valida, debe ser un numero real mayor o igual que cero") self.error_dialog.exec_() self.main.kdSimulacion.setFocus() return
[documentos]def N_validator(self): """ Validación del valor N """ try: _ = float(self.main.NSimulacion.text()) if _ < 0: raise ValueError except ValueError: self.error_dialog.setInformativeText( "Valor de N no valido, debe ser un numero real mayor o igual que cero") self.error_dialog.exec_() self.main.NSimulacion.setFocus() return
[documentos]def calcular_simulacion(self): """ Función para inicializar el QThread y realizar los calculos de la simulación """ num = json.loads(self.main.numSensor.text()) dem = json.loads(self.main.demSensor.text()) # Validación de función propia para el sensor if len(num) > len(dem) and self.main.sensorCheck.isChecked(): self.error_dialog.setInformativeText( "Función de transferencia del sensor impropia, el numerador debe ser de un grado menor o igual al del denominador") self.error_dialog.exec_() self.main.toolBox.setCurrentIndex(2) return num = json.loads(self.main.numAccionador.text()) dem = json.loads(self.main.demAccionador.text()) # Validación de función propia para el accionador if len(num) > len(dem) and self.main.accionadorCheck.isChecked(): self.error_dialog.setInformativeText( "Función de transferencia del accionador impropia, el numerador debe ser de un grado menor o igual al del denominador") self.error_dialog.exec_() self.main.toolBox.setCurrentIndex(2) return lim_inf = float(self.main.inferiorSaturador.text()) lim_sup = float(self.main.superiorSaturador.text()) # Validación de limites validos para el saturador if lim_inf >= lim_sup and self.main.saturadorCheck.isChecked(): self.error_dialog.setInformativeText( "Limites del saturador del accionador inválidos, el limite inferior debe ser menor que el limite superior" ) self.error_dialog.exec_() self.main.toolBox.setCurrentIndex(2) return # Validación de selección de archivo para el controlador difuso if len(self.main.pathController1.text( )) < 1 and self.main.esquemaSimulacion.currentIndex() in [1, 2, 3, 4, 5, 6, 7, 8]: self.error_dialog.setInformativeText( "Debe seleccionar un archivo valido para cargar el controlador difuso") self.error_dialog.exec_() self.main.toolBox.setCurrentIndex(3) return # Validación de selección de archivo para el controlador difuso 2 (PD) if len(self.main.pathController2.text( )) < 1 and self.main.esquemaSimulacion.currentIndex() in [4]: self.error_dialog.setInformativeText( "Debe seleccionar un archivo valido para cargar el controlador difuso 2") self.error_dialog.exec_() self.main.toolBox.setCurrentIndex(3) return system_ss = 0 if (self.main.tfdiscretocheckBox4.isChecked() and self.main.SimulacionstackedWidget.currentIndex() == 0): self.dt = json.loads(self.main.tfperiodoEdit4.text()) elif (self.main.ssdiscretocheckBox4.isChecked() and self.main.SimulacionstackedWidget.currentIndex() == 1): self.dt = json.loads(self.main.ssperiodoEdit4.text()) else: self.dt = 0 if self.main.SimulacionstackedWidget.currentIndex() == 0: # caso: Función de transferencia num = json.loads(self.main.tfnumEdit4.text()) dem = json.loads(self.main.tfdemEdit4.text()) # Validación de función propia if len(num) > len(dem): self.error_dialog.setInformativeText( "Función de transferencia impropia, el numerador debe ser de un grado menor o igual al del denominador") self.error_dialog.exec_() self.main.ssdelayEdit1.setFocus() return system = system_creator_tf(self, num, dem) else: # caso: Ecuación de espacio de estados A = json.loads(self.main.ssAEdit4.text()) B = json.loads(self.main.ssBEdit4.text()) C = json.loads(self.main.ssCEdit4.text()) D = json.loads(self.main.ssDEdit4.text()) system = system_creator_ss(self, A, B, C, D) if not self.main.escalonCheck.isChecked(): escalon = float(self.main.escalonSimulacion.text()) else: escalon = json.loads(self.main.escalonAvanzado.text()) # Configuración del solver rk_base, metodo_adaptativo, solver_config = configuration_data(self) # Lista a enviar al QThread con toda la información necesaria list_info = [ self.main.esquemaSimulacion.currentIndex(), system, float(self.main.tiempoSimulacion.text()), self.dt, escalon, self.main.sensorCheck.isChecked(), self.main.accionadorCheck.isChecked(), self.main.saturadorCheck.isChecked(), [ self.main.kpSimulacion.text(), self.main.kiSimulacion.text(), self.main.kdSimulacion.text(), self.main.NSimulacion.text() ], [self.main.pathController1.text(), self.main.pathController2.text()], rk_base, metodo_adaptativo, solver_config, self.main.filtroCheck.isChecked() ] # Instanciación del objeto QThread self.thread = SimpleThread(self, plot_final_results, update_progresBar_function, error_gui, list_info) # Inicio del proceso de simulación self.thread.start()
[documentos]def simulacion_stacked_to_tf(self): """ Función para cambiar de ecuación de espacio de estados a función de transferencia """ self.main.SimulacionstackedWidget.setCurrentIndex(0)
[documentos]def simulacion_stacked_to_ss(self): """ Función para cambiar de función de transferencia a ecuación de espacio de estados """ self.main.SimulacionstackedWidget.setCurrentIndex(1)
[documentos]def get_pathcontroller1(self): """ Función para obtener la dirección al archivo del controlador difuso """ path_cargar = QtWidgets.QFileDialog.getOpenFileName(filter="JSON/FIS (*.json *.fis)") self.main.pathController1.setText(path_cargar[0])
[documentos]def get_pathcontroller2(self): """ Función para obtener la dirección al archivo del controlador difuso 2 (PD) """ path_cargar = QtWidgets.QFileDialog.getOpenFileName(filter="JSON/FIS (*.json *.fis)") self.main.pathController2.setText(path_cargar[0])
[documentos]def configuration_data(self): """ Función para cambiar la configuración del solver a utilizar :return: Datos necesarios para el solver :rtype: tuple(function, function, list[function, int, float, float, float, float, float]) """ rtol = float(self.main.rtolLineEdit.text()) atol = float(self.main.atolLineEdit.text()) max_step_inc = float(self.main.maxStepIncr.text()) min_step_dec = float(self.main.minStepDecr.text()) safety_factor = float(self.main.safetyFactor.text()) # Seleccion entre método explicito y embebido if self.main.solverMethod.currentIndex() <= 8: metodo_adaptativo = rk_doble_paso_adaptativo else: metodo_adaptativo = rk_embebido_adaptativo # Metodos y orden if self.main.solverMethod.currentIndex() == 0: rk_metodo = runge_kutta2 rk_base = rk_metodo ordenq = 2 elif self.main.solverMethod.currentIndex() == 1: rk_metodo = runge_kutta3 rk_base = rk_metodo ordenq = 3 elif self.main.solverMethod.currentIndex() == 2: rk_metodo = heun3 rk_base = rk_metodo ordenq = 3 elif self.main.solverMethod.currentIndex() == 3: rk_metodo = ralston3 rk_base = rk_metodo ordenq = 3 elif self.main.solverMethod.currentIndex() == 4: rk_metodo = SSPRK3 rk_base = rk_metodo ordenq = 3 elif self.main.solverMethod.currentIndex() == 5: rk_metodo = runge_kutta4 rk_base = rk_metodo ordenq = 4 elif self.main.solverMethod.currentIndex() == 6: rk_metodo = tres_octavos4 rk_base = rk_metodo ordenq = 4 elif self.main.solverMethod.currentIndex() == 7: rk_metodo = ralston4 rk_base = rk_metodo ordenq = 4 elif self.main.solverMethod.currentIndex() == 8: rk_metodo = runge_kutta5 rk_base = rk_metodo ordenq = 5 elif self.main.solverMethod.currentIndex() == 9: rk_metodo = bogacki_shampine23 rk_base = ralston3 ordenq = 2 elif self.main.solverMethod.currentIndex() == 10: rk_metodo = fehlberg45 rk_base = runge_kutta4 ordenq = 4 elif self.main.solverMethod.currentIndex() == 11: rk_metodo = cash_karp45 rk_base = runge_kutta4 ordenq = 4 elif self.main.solverMethod.currentIndex() == 12: rk_metodo = dopri54 rk_base = runge_kutta5 ordenq = 4 return rk_base, metodo_adaptativo, [rk_metodo, ordenq, rtol, atol, max_step_inc, min_step_dec, safety_factor]
[documentos]def restablecer_configuracion(self): """ Función para restablecer la configuración avanzada por defecto """ self.main.padeOrder.setText('10') self.main.filtroCheck.setChecked(False) self.main.solverMethod.setCurrentIndex(12) self.main.rtolLineEdit.setText('1e-4') self.main.atolLineEdit.setText('1e-6') self.main.maxStepIncr.setText('5') self.main.minStepDecr.setText('0.2') self.main.safetyFactor.setText('0.9')
[documentos]def accion_esquema_selector(self): """ Función para mostrar los widgets indicados en función del esquema seleccionado """ self.main.controller1Frame.hide() self.main.controller2Frame.hide() self.main.kpFrame.hide() self.main.kiFrame.hide() self.main.kdFrame.hide() index = self.main.esquemaSimulacion.currentIndex() self.main.tabSimulation.setCurrentIndex(0) if index == 0: # PID Clásico self.main.controller1Frame.hide() self.main.controller2Frame.hide() self.main.kpFrame.show() self.main.kiFrame.show() self.main.kdFrame.show() self.main.kdCheck.show() self.main.kiCheck.show() self.main.NFrame.show() self.main.NSpacer.show() if self.main.kdCheck.isChecked(): self.main.NSimulacion.setEnabled(True) else: self.main.NSimulacion.setDisabled(True) self.main.esquemaSimulacionGraph.setPixmap( QtGui.QPixmap(":/imagenes/imagenes/pidClasico.png")) if index in [1, 2, 3, 7]: # PID difuso, PI difuso, PD difuso, Programador de ganancias self.main.controller1Frame.show() self.main.controller2Frame.hide() self.main.kpFrame.hide() self.main.kiFrame.hide() self.main.kdFrame.hide() self.main.NSimulacion.setEnabled(True) self.main.NFrame.show() self.main.NSpacer.hide() if index == 1: # PID difuso self.main.esquemaSimulacionGraph.setPixmap( QtGui.QPixmap(":/imagenes/imagenes/pidDifuso.png")) if index == 2: # PI difuso self.main.esquemaSimulacionGraph.setPixmap( QtGui.QPixmap(":/imagenes/imagenes/piDifuso.png")) if index == 3: # PD difuso self.main.esquemaSimulacionGraph.setPixmap( QtGui.QPixmap(":/imagenes/imagenes/pdDifuso.png")) if index == 7: # Programador de ganancias self.main.esquemaSimulacionGraph.setPixmap( QtGui.QPixmap(":/imagenes/imagenes/GainScheduler.png")) if index == 4: # PI difuso + PD difuso self.main.controller1Frame.show() self.main.controller2Frame.show() self.main.kpFrame.hide() self.main.kiFrame.hide() self.main.kdFrame.hide() self.main.NSimulacion.setEnabled(True) self.main.NFrame.show() self.main.NSpacer.hide() self.main.esquemaSimulacionGraph.setPixmap( QtGui.QPixmap(":/imagenes/imagenes/pipdDifuso.png")) if index == 5: # PI difuso + D Clásico self.main.controller1Frame.show() self.main.controller2Frame.hide() self.main.kpFrame.hide() self.main.kiFrame.hide() self.main.kdFrame.show() self.main.kdCheck.hide() self.main.kdCheck.setChecked(True) self.main.kdSimulacion.setEnabled(True) self.main.NSimulacion.setEnabled(True) self.main.NFrame.show() self.main.NSpacer.hide() self.main.esquemaSimulacionGraph.setPixmap( QtGui.QPixmap(":/imagenes/imagenes/piplusDDifuso.png")) if index == 6: # PD difuso + I Clásico self.main.controller1Frame.show() self.main.controller2Frame.hide() self.main.kpFrame.hide() self.main.kiFrame.show() self.main.kdFrame.hide() self.main.kiCheck.hide() self.main.kiCheck.setChecked(True) self.main.kiSimulacion.setEnabled(True) self.main.NSimulacion.setEnabled(True) self.main.NFrame.show() self.main.NSpacer.hide() self.main.esquemaSimulacionGraph.setPixmap( QtGui.QPixmap(":/imagenes/imagenes/pdplusIDifuso.png")) if index == 8: # PID Clásico + Difuso simple self.main.controller1Frame.show() self.main.controller2Frame.hide() self.main.kpFrame.show() self.main.kiFrame.show() self.main.kdFrame.show() self.main.kdCheck.show() self.main.kiCheck.show() self.main.NSimulacion.setEnabled(True) self.main.NFrame.show() self.main.NSpacer.show() self.main.NSimulacion.setEnabled(True) self.main.esquemaSimulacionGraph.setPixmap( QtGui.QPixmap(":/imagenes/imagenes/pidplusDifuso.png"))
[documentos]def update_progresBar_function(self, value): """ Función para actualizar la barra de progreso de la simulación, esta función es utilizada por el QThread :param value: Valor en porcentaje del progreso :type value: float """ self.main.progressBar.setValue(value)
[documentos]def error_gui(self, error): """ Función para mostrar los errores que pudiesen ocurrir durante la simulación, esta función es utilizada por el QThread :param error: Indicador del error :type error: int """ self.main.progressBar.setValue(0) self.main.progressBar.hide() self.main.principalTab.setEnabled(True) if error == 0: self.error_dialog.setInformativeText("Error inesperado") self.error_dialog.exec_() if error == 1: self.error_dialog.setInformativeText("No se permiten salidas negadas en los controladores") self.error_dialog.exec_() if error == 2: self.error_dialog.setInformativeText( "Controlador no valido para el esquema seleccionado") self.error_dialog.exec_()
[documentos]def plot_final_results(self, result): """ Función para graficar los resultados finales de la simulación :param result: Lista con los resultados obtenidos :type result: list """ self.main.simulacionGraph.canvas.axes1.clear() # Limitando los resultados para evitar problemas con matplotlib result[1] = np.clip(result[1], -1e300, 1e300) result[2] = np.clip(result[2], -1e300, 1e300) # Distinción entre continuo y discreto para y(t) if result[4]: self.main.simulacionGraph.canvas.axes1.step(result[0], result[1], where="mid", label='Vp') else: self.main.simulacionGraph.canvas.axes1.plot(result[0], result[1], label='Vp') # Setpoint self.main.simulacionGraph.canvas.axes1.plot(result[0], result[3], linestyle='--', label='setpoint', alpha=0.5) self.main.simulacionGraph.canvas.axes1.grid(color="lightgray") self.main.simulacionGraph.canvas.axes1.legend() self.main.simulacionGraph.canvas.draw() self.main.simulacionGraph.canvas.axes2.clear() # Distinción entre continuo y discreto para la señal de control if result[4]: self.main.simulacionGraph.canvas.axes2.step(result[0], result[2], '#2ca02c', where="mid", label='señal de control') else: self.main.simulacionGraph.canvas.axes2.plot(result[0], result[2], '#2ca02c', label='señal de control') self.main.simulacionGraph.canvas.axes2.grid(color="lightgray") self.main.simulacionGraph.canvas.axes2.legend() self.main.simulacionGraph.canvas.draw() self.main.simulacionGraph.toolbar.update() self.main.progressBar.setValue(0) self.main.progressBar.hide() self.main.principalTab.setEnabled(True) self.main.tabSimulation.setCurrentIndex(1)