Salida del controlador Simulador Pytón PID [CERRADO] -- python campo con python-3.x campo con simulation campo con matplotlib camp codereview Relacionados El problema

Python PID simulator controller output [closed]


-4
vote

problema

Español
cerrado. Esta pregunta es off-topic . Actualmente no está aceptando respuestas.

¿Quieres mejorar esta pregunta? Actualizar la pregunta por lo que es on-topic para el intercambio de pila de revisión de código.

cerrado hace 4 años .

Mejorar esta pregunta

He escrito un pedazo de código (en PY3) que grájica el valor del controlador del controlador PID . Esto es de modo que al cambiar los distintos controladores SUB (P / I / D) puedo visualizar cómo cambia el gráfico. He escrito el siguiente código, pero teniendo dificultades en el algoritmo PID y obteniendo un valor de controlador correcto. Puede ejecutar el código tal como está, y debe emitir un gráfico. El código funciona correctamente según lo previsto.

   #!/usr/bin/python3  import random from decimal import * import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import pandas as pd import numpy as np import os  # SOURCE: http://blog.nikmartin.com/2012/11/process-control-for-dummies-like-me.html  y_data = [] x_data = [] error_value_data = [] current_value_data = [] controller_output_data = [] proportional_value_data = [] integral_value_data = [] derivative_value_data = [] setpoint_value_data = [] process_value_data = []  OUTGOING_FILES_DIRECTORY = "/some/dir/in/your/computer"  def create_offset(setpoint_value):     offset_value = random.randint(-128, 128)     offset_value_incrementation = float(offset_value / 100)     return setpoint_value - offset_value_incrementation   def Pt_controller(process_error_value, Pgain_value):     Pt = process_error_value * Pgain_value     return Pt   def It_controller(It, process_error_value, Igain_value):     It = It + process_error_value     It = It * Igain_value     return It   def Dt_controller(current_control_output_value, previous_control_output_value, derivative_gain_value):     Dt = (current_control_output_value - previous_control_output_value) * derivative_gain_value     # print(current_control_output_value, previous_control_output_value, Dt)     return Dt  def process_error(setpoint_value, current_value):     return setpoint_value - current_value  def pid_controller(proportional_value, integral_value, derivative_value):     pid_output = derivative_value + (proportional_value + integral_value)     return pid_output  def graph_line_data(x_value, error_value, proportional_value, integral_value, derivative_value, setpoint_value, process_value, PID_value):      if max(x_value) > 500:         width = max(x_value)/200     else:         width = 10     height = 5     plt.figure(figsize=(width, height), dpi=100)      # Choose which data     plt.plot(x_value, PID_value, '#FF4500')     # plt.plot(x_value, error_value, 'r')     # plt.plot(x_value, proportional_value, '#9F00A0')     # plt.plot(x_value, integral_value, 'green')     # plt.plot(x_value, derivative_value, '#00BBFF')     plt.plot(x_value, setpoint_value, 'k--')     # plt.plot(x_value, process_value, 'b')      plt.xlabel('Iteration Count')     plt.ylabel('Output')     plt.title('PID Controller (P=0.82, I=0.155, D=0.45)')      plt.legend(['PID Controller Output', 'Set point'], loc='upper right')     # plt.legend(['PID Controller Output'], loc='upper right')      # plt.legend(['PID Controller Output', 'Error Value', 'Integral Value'], loc='upper right')      # plt.legend(['PID', 'Error Value', 'Proportional Value', 'Integral Value',     #            'Derivative Value', 'Set point', 'Process Value'], loc='upper right')      png_filename = "Steady_PID_Simulation"      output_file_path = os.path.join(OUTGOING_FILES_DIRECTORY, png_filename)      plt.savefig(output_file_path)      print("Finished creating: " + png_filename + ".png")     def pid_simulator():     # set point     setpoint_value = 0      # gain values          # P = 0.82 / I = 0.15 / D = 0.40     proportional_gain_value = 0.82     integral_gain_value = 0.155     derivative_gain_value = 0.45      # initialisation values     derivative_value = 1     controller_output_value = 0     integral_value = 0     x_value = 0     number_of_iterations = 200      while x_value < number_of_iterations:         x_value += 1          process_value = setpoint_value          error_value = process_value - setpoint_value          if x_value == number_of_iterations / 5:             setpoint_value = 100         if x_value == number_of_iterations / 2:             setpoint_value = -300         if x_value == 6 * (number_of_iterations / 10):             setpoint_value = -200         if x_value == 7 * (number_of_iterations / 10):             setpoint_value = -250         if x_value == (number_of_iterations - (number_of_iterations / 5)):             setpoint_value = 0          # PROPORTIONAL         proportional_value = Pt_controller(process_value, proportional_gain_value)          # INTEGRAL         integral_value = It_controller(integral_value, process_value, integral_gain_value)          # CONTROLLER OUTPUT         previous_controller_output_value = controller_output_value         controller_output_value = proportional_value + integral_value + derivative_value          # DERIVATIVE         derivative_value = Dt_controller(controller_output_value, previous_controller_output_value, derivative_gain_value)         # derivative_value = 0.25 * derivative_value          # print(integral_value)         # print(number_of_iterations - x_value)         x_data.append(x_value)         controller_output_data.append(controller_output_value)         error_value_data.append(error_value)         integral_value_data.append(integral_value)         setpoint_value_data.append(setpoint_value)         process_value_data.append(process_value)         derivative_value_data.append(derivative_value)         proportional_value_data.append(proportional_value)      graph_line_data(x_data, error_value_data, proportional_value_data, integral_value_data, derivative_value_data,                     setpoint_value_data, process_value_data, controller_output_data)     def main():     pid_simulator()    if __name__ == "__main__":     main()   

Los rendimientos de salida: Salida PID constante

Original en ingles

I have written a piece of code (in Py3) that graphs out the controller value of PID controller. This is so that by changing the various sub controllers (P/I/D) I can visualise how the graph changes. I've written the following code, but having difficulty in the PID algorithm, and obtaining a correct controller value. You can run the code as is, and it should output a graph. The code works correctly as intended.

 #!/usr/bin/python3  import random from decimal import * import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import pandas as pd import numpy as np import os  # SOURCE: http://blog.nikmartin.com/2012/11/process-control-for-dummies-like-me.html  y_data = [] x_data = [] error_value_data = [] current_value_data = [] controller_output_data = [] proportional_value_data = [] integral_value_data = [] derivative_value_data = [] setpoint_value_data = [] process_value_data = []  OUTGOING_FILES_DIRECTORY = "/some/dir/in/your/computer"  def create_offset(setpoint_value):     offset_value = random.randint(-128, 128)     offset_value_incrementation = float(offset_value / 100)     return setpoint_value - offset_value_incrementation   def Pt_controller(process_error_value, Pgain_value):     Pt = process_error_value * Pgain_value     return Pt   def It_controller(It, process_error_value, Igain_value):     It = It + process_error_value     It = It * Igain_value     return It   def Dt_controller(current_control_output_value, previous_control_output_value, derivative_gain_value):     Dt = (current_control_output_value - previous_control_output_value) * derivative_gain_value     # print(current_control_output_value, previous_control_output_value, Dt)     return Dt  def process_error(setpoint_value, current_value):     return setpoint_value - current_value  def pid_controller(proportional_value, integral_value, derivative_value):     pid_output = derivative_value + (proportional_value + integral_value)     return pid_output  def graph_line_data(x_value, error_value, proportional_value, integral_value, derivative_value, setpoint_value, process_value, PID_value):      if max(x_value) > 500:         width = max(x_value)/200     else:         width = 10     height = 5     plt.figure(figsize=(width, height), dpi=100)      # Choose which data     plt.plot(x_value, PID_value, '#FF4500')     # plt.plot(x_value, error_value, 'r')     # plt.plot(x_value, proportional_value, '#9F00A0')     # plt.plot(x_value, integral_value, 'green')     # plt.plot(x_value, derivative_value, '#00BBFF')     plt.plot(x_value, setpoint_value, 'k--')     # plt.plot(x_value, process_value, 'b')      plt.xlabel('Iteration Count')     plt.ylabel('Output')     plt.title('PID Controller\n(P=0.82, I=0.155, D=0.45)')      plt.legend(['PID Controller Output', 'Set point'], loc='upper right')     # plt.legend(['PID Controller Output'], loc='upper right')      # plt.legend(['PID Controller Output', 'Error Value', 'Integral Value'], loc='upper right')      # plt.legend(['PID', 'Error Value', 'Proportional Value', 'Integral Value',     #            'Derivative Value', 'Set point', 'Process Value'], loc='upper right')      png_filename = "Steady_PID_Simulation"      output_file_path = os.path.join(OUTGOING_FILES_DIRECTORY, png_filename)      plt.savefig(output_file_path)      print("Finished creating: " + png_filename + ".png")     def pid_simulator():     # set point     setpoint_value = 0      # gain values          # P = 0.82 / I = 0.15 / D = 0.40     proportional_gain_value = 0.82     integral_gain_value = 0.155     derivative_gain_value = 0.45      # initialisation values     derivative_value = 1     controller_output_value = 0     integral_value = 0     x_value = 0     number_of_iterations = 200      while x_value < number_of_iterations:         x_value += 1          process_value = setpoint_value          error_value = process_value - setpoint_value          if x_value == number_of_iterations / 5:             setpoint_value = 100         if x_value == number_of_iterations / 2:             setpoint_value = -300         if x_value == 6 * (number_of_iterations / 10):             setpoint_value = -200         if x_value == 7 * (number_of_iterations / 10):             setpoint_value = -250         if x_value == (number_of_iterations - (number_of_iterations / 5)):             setpoint_value = 0          # PROPORTIONAL         proportional_value = Pt_controller(process_value, proportional_gain_value)          # INTEGRAL         integral_value = It_controller(integral_value, process_value, integral_gain_value)          # CONTROLLER OUTPUT         previous_controller_output_value = controller_output_value         controller_output_value = proportional_value + integral_value + derivative_value          # DERIVATIVE         derivative_value = Dt_controller(controller_output_value, previous_controller_output_value, derivative_gain_value)         # derivative_value = 0.25 * derivative_value          # print(integral_value)         # print(number_of_iterations - x_value)         x_data.append(x_value)         controller_output_data.append(controller_output_value)         error_value_data.append(error_value)         integral_value_data.append(integral_value)         setpoint_value_data.append(setpoint_value)         process_value_data.append(process_value)         derivative_value_data.append(derivative_value)         proportional_value_data.append(proportional_value)      graph_line_data(x_data, error_value_data, proportional_value_data, integral_value_data, derivative_value_data,                     setpoint_value_data, process_value_data, controller_output_data)     def main():     pid_simulator()    if __name__ == "__main__":     main() 

The output yields: Steady PID output

           
         
         

Lista de respuestas

6
 
vote

Quiero comenzar esta revisión explícitamente diciendo que i no tiene un conocimiento profundo cuando se trata de matplotlib pero le daré un Pruebe de todos modos


Tenga en cuenta que acabo de revisar el código tal como está, manteniendo la misma lógica / funcionalidad que tiene en este momento.


Importaciones no utilizadas

No importa los módulos que no está usando ( decimal , pandas , 9988776655544333 ).

Importaciones Agrupación

de PEP8 que es la Guía oficial de estilo Python:

Las importaciones deben agruparse en el siguiente orden:

  1. Importaciones de la biblioteca estándar
  2. Importaciones de terceros relacionadas
  3. Aplicación local / Biblioteca Importaciones específicas

importaciones refactored

  import os import random  import matplotlib import matplotlib.pyplot as plt   

espaciado (un aspecto pequeño que hace una gran diferencia)

  • Debería tener dos nuevas líneas después de cada método

      def method_1()     ...   def method_2()     ...   
  • Utilice las reglas de nombres de la función: minúsculas con las palabras separadas por los guiones bajos según sea necesario para mejorar la legibilidad. Pt_controller() debe ser pt_controller()

  • La misma regla que la anterior puede (y debe) también se aplicará a los nombres de variables

  • intenta adherirse con una longitud máxima de máximo 120 caracteres

sobre el código

  • trata de no crear variables que se usan solo una vez. En su lugar, puede devolver directamente el resultado.
  • No use variables globales Si no es necesario (más, no cree variables inútiles a menos que esté usandolas: por ejemplo, 99887776655443388 y 99887766555443391 Lista nunca utilizado)
  • no abuses de comentarios. En su lugar, hay la doctras . Más, los comentarios de depuración son buenos, pero asegúrese de llevarlos ( hice esto )
  • Usted usó decimal0 ¡Es muy bueno!
  • Tienes algunos números mágicos que me mudaría en la parte superior del programa para que pueda cambiarlos fácilmente si es necesario

Código revisado:

  decimal1  

Estoy seguro de que decimal2 puede mejorarse aún más, pero eso es todo el tiempo que tengo conmigo ahora mismo.

 

I want to start this review by explicitly saying that I don't have a deep knowledge when it comes to matplotlib but I'll give it a try anyway


Have in mind that I just reviewed the code as is, keeping the same logic / functionality it has at the moment.


Unused imports

Don't import modules you're not using (decimal, pandas, numpy).

Imports grouping

From PEP8 which is the official Python style guide:

Imports should be grouped in the following order:

  1. standard library imports
  2. related third party imports
  3. local application/library specific imports

Refactored imports

import os import random  import matplotlib import matplotlib.pyplot as plt 

Spacing (a small aspect making a huge difference)

  • you should have two new lines after each method

    def method_1()     ...   def method_2()     ... 
  • use the function naming rules: lowercase with words separated by underscores as necessary to improve readability. Pt_controller() should be pt_controller()

  • the same rule as above can (and should) also be applied to variable names

  • try to stick with a max length of maximum 120 characters

About the code

  • try not to create variables which are used only once. Instead you can directly return the result.
  • don't use global variables if it's not necessary (more, don't create useless variables unless you're using them: e.g y_data and current_value_data list are never used)
  • don't abuse comments. Instead, there're the docstrings. More, debug comments are good, but make sure you take them out (I did this)
  • you used if __name__ == "__main__": which is very good !
  • you have some magic numbers which I'd move at the top of the program so that you can easily change them if necessary

Revised code:

import os import random  import matplotlib import matplotlib.pyplot as plt  PNG_FILENAME = "Steady_PID_Simulation1.png" OUTGOING_FILES_DIRECTORY = "C:\\Main\\Projects\\Python\\untitled" OUTPUT_FILE_PATH = os.path.join(OUTGOING_FILES_DIRECTORY, PNG_FILENAME)  DPI = 100 MAX_VALUE = 500 PLOT_COLOR = '#FF4500'  PROPORTIONAL_GAIN_VALUE = 0.82 INTEGRAL_GAIN_VALUE = 0.155 DERIVATIVE_GAIN_VALUE = 0.45   def create_offset(set_point_value):     """Docstring here (what does the function do)"""     offset_value = random.randint(-128, 128)     offset_value_incrementation = float(offset_value / 100)      return set_point_value - offset_value_incrementation   def pt_controller(process_error_value, p_gain_value):     """Docstring here (what does the function do)"""     return process_error_value * p_gain_value   def it_controller(it, process_error_value, i_gain_value):     """Docstring here (what does the function do)"""     it = it + process_error_value     it = it * i_gain_value     return it   def dt_controller(current_control_output_value, previous_control_output_value, derivative_gain_value):     """Docstring here (what does the function do)"""     return (current_control_output_value - previous_control_output_value) * derivative_gain_value   def process_error(set_point_value, current_value):     """Docstring here (what does the function do)"""     return set_point_value - current_value   def pid_controller(proportional_value, integral_value, derivative_value):     """Docstring here (what does the function do)"""     return derivative_value + (proportional_value + integral_value)   def get_width_and_height(x_value, weight=10, height=5):     """Docstring here (what does the function do)"""     return (max(x_value)/200, height) if max(x_value) > MAX_VALUE else (weight, height)   def graph_line_data(x_value, error_value, proportional_value, integral_value, derivative_value, setpoint_value,                     process_value, PID_value):     """Docstring here (what does the function do)"""      width, height = get_width_and_height(x_value)      plt.figure(figsize=(width, height), dpi=DPI)      plt.plot(x_value, PID_value, PLOT_COLOR)     plt.plot(x_value, setpoint_value, 'k--')      plt.xlabel('Iteration Count')     plt.ylabel('Output')     plt.title('PID Controller\n(P={}, I={}, D={})'.format(PROPORTIONAL_GAIN_VALUE,                                                           INTEGRAL_GAIN_VALUE,                                                           DERIVATIVE_GAIN_VALUE))      plt.legend(['PID Controller Output', 'Set point'], loc='upper right')     plt.savefig(OUTPUT_FILE_PATH)      print("Finished creating: {}".format(PNG_FILENAME))   def pid_simulator():     """Docstring here (what does the function do)"""     set_point_value, controller_output_value, integral_value, derivative_value, number_of_iterations = 0, 0, 0, 1, 200      x_data, error_value_data, controller_output_data, proportional_value_data = [], [], [], []     integral_value_data, derivative_value_data, setpoint_value_data, process_value_data = [], [], [], []      for x_value, _ in enumerate(range(number_of_iterations)):         process_value = set_point_value         error_value = process_value - set_point_value          if x_value == number_of_iterations / 5:             set_point_value = 100         if x_value == number_of_iterations / 2:             set_point_value = -300         if x_value == 6 * (number_of_iterations / 10):             set_point_value = -200         if x_value == 7 * (number_of_iterations / 10):             set_point_value = -250         if x_value == (number_of_iterations - (number_of_iterations / 5)):             set_point_value = 0          proportional_value = pt_controller(process_value, PROPORTIONAL_GAIN_VALUE)         integral_value = it_controller(integral_value, process_value, INTEGRAL_GAIN_VALUE)          previous_controller_output_value = controller_output_value         controller_output_value = proportional_value + integral_value + derivative_value          derivative_value = dt_controller(controller_output_value,                                          previous_controller_output_value,                                          DERIVATIVE_GAIN_VALUE)          x_data.append(x_value)         controller_output_data.append(controller_output_value)         error_value_data.append(error_value)         integral_value_data.append(integral_value)         setpoint_value_data.append(set_point_value)         process_value_data.append(process_value)         derivative_value_data.append(derivative_value)         proportional_value_data.append(proportional_value)      graph_line_data(x_data, error_value_data, proportional_value_data, integral_value_data, derivative_value_data,                     setpoint_value_data, process_value_data, controller_output_data)   def main():     matplotlib.use('Agg', warn=False)      pid_simulator()   if __name__ == "__main__":     main() 

I'm sure pid_simulator() can be improved even more but that's all the time that I have with me right now.

 
 

Relacionados problema

5  Evolución de la red social  ( Social network evolution ) 
Estoy escribiendo un pedazo de código que modela la evolución de una red social. La idea es que cada persona está asignada a un nodo y relaciones entre las pe...

8  Programa Python para verificar si un conjunto de puntos está en tierra o en el mar  ( Python program to check if a set of points is at land or at sea ) 
He escrito un programa que divide un área geográfica en células con tamaño 0.002 grados longitud por 0.001 grados latitud, y verifique cada celda ya sea q...

5  Evaluando una serie de polinomios legendra  ( Evaluating a series of legendre polynomials ) 
La siguiente función representa el potencial electrostático, en coordenadas esféricas, debido a un anillo de carga $ Q = 1 $ y RADIUS $ R = 1 $, colocado ...

5  Automatizar un conjunto A de informes semanales, incluidos los gráficos y la entrega de informes  ( Automating a set a of weekly reports including graphs and delivery of reports ) 
He estado escribiendo código para automatizar algunos informes semanales. Tuve Ayuda sobre el desbordamiento de la pila . Tengo código que funciona en su may...

12  Tweets de transmisión en vivo y trazando su valor sentimental en colores en un mapa del mundo  ( Live streaming tweets and plot its sentimental value in colors on a world map ) 
Quiero tener a alguien revisar y ayudarme a obtener buenas ideas sobre cómo mejorar mi proyecto actual. Toda la información sobre el proyecto está en el sig...

5  Probabilidad de evento usando el límite central del teorema + resultados de trazado  ( Probability of event using central limit theorem plotting results ) 
He estado haciendo un curso de udemy llamado: "Estadísticas para la ciencia de los datos" y decidí resolver una de las tareas con Python para matar a dos pája...

3  Trazando muchas imágenes a la vez en matplotlib  ( Plotting many images at once in matplotlib ) 
Estoy usando numpy y matplotlib para hacer una simulación estadística. La simulación en sí misma es bastante rápida gracias a la vectorización nompy, sin ...

2  Datos de lectura y lectura de archivos binarios  ( Binary file reading and plotting data ) 
Este código lee el archivo binario. Los datos de lectura se convierten en valores firmados y se trazan si el usuario lo quiere. los datos se ven a continua...

13  Numérica para un cálculo de teoría de juegos usando la utilidad esperada  ( Numerics for a game theory calculation using expected utility ) 
Estoy tratando de replicar los resultados de Bruce B. de Mesquita (BDM) en la teoría del juego político para la predicción. Sobre la base de dónde se encuentr...

7  Salida de parcelas de dispersión [cerrada]  ( Outputting scatter plots ) 
cerrado. Esta pregunta es off-topic . Actualmente no está aceptando respuestas. ¿Quieres ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos