fupid.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import numpy as np
  2. import skfuzzy as fuzz
  3. import matplotlib.pyplot as plt
  4. #from mpl_toolkit.mplot3d import Axes3D
  5. from skfuzzy import control as ctrl
  6. import math
  7. class PIDController:
  8. def __init__(self, Kp, Ki, Kd):
  9. self.Kp = Kp
  10. self.Ki = Ki
  11. self.Kd = Kd
  12. self.last_error = 0
  13. self.integral = 0
  14. def control(self, error):
  15. output = self.Kp * error + self.Ki * self.integral + self.Kd * (error - self.last_error)
  16. self.integral += error
  17. self.last_error = error
  18. return output
  19. class TemperatureSystem:
  20. def __init__(self, target_temp):
  21. self.target_temp = target_temp
  22. self.current_temp = 0
  23. def update(self, control_singal):
  24. self.current_temp += control_singal * 1
  25. return self.current_temp
  26. def get_error(self):
  27. return self.target_temp - self.current_temp
  28. def train(controller,system, num_iterations):
  29. errors = []
  30. signal = []
  31. temp = []
  32. e = ctrl.Antecedent(np.arange(-80, 80, 1), 'e')
  33. del_e = ctrl.Antecedent(np.arange(-6, 6, 1), 'del_e')
  34. kp = ctrl.Consequent(np.arange(-0.8, 0.8, 0.01), 'kp')
  35. ki = ctrl.Consequent(np.arange(-0.1, 0.1, 0.005), 'ki')
  36. kd = ctrl.Consequent(np.arange(-0.1, 0.1, 0.005), 'kd')
  37. e['NB'] = fuzz.trimf(e.universe, [-80, -80, -40])
  38. e['NS'] = fuzz.trimf(e.universe, [-80, -40, 0])
  39. e['ZO'] = fuzz.trimf(e.universe, [-40, 0, 40])
  40. e['PS'] = fuzz.trimf(e.universe, [0, 40, 80])
  41. e['PB'] = fuzz.trimf(e.universe, [40, 80, 80])
  42. del_e['NB'] = fuzz.trimf(del_e.universe, [-6, -6, -3])
  43. del_e['NS'] = fuzz.trimf(del_e.universe, [-6, -3, 0])
  44. del_e['ZO'] = fuzz.trimf(del_e.universe, [-3, 0, 3])
  45. del_e['PS'] = fuzz.trimf(del_e.universe, [0, 3, 6])
  46. del_e['PB'] = fuzz.trimf(del_e.universe, [3, 6, 6])
  47. kp['NB'] = fuzz.trimf(kp.universe, [-0.8, -0.8, -0.4])
  48. kp['NS'] = fuzz.trimf(kp.universe, [-0.8, -0.4, 0])
  49. kp['ZO'] = fuzz.trimf(kp.universe, [-0.4, 0, 0.4])
  50. kp['PS'] = fuzz.trimf(kp.universe, [0, 0.4, 0.8])
  51. kp['PB'] = fuzz.trimf(kp.universe, [0.4, 0.8, 0.8])
  52. ki['NB'] = fuzz.trimf(ki.universe, [-0.02, -0.02, -0.01])
  53. ki['NS'] = fuzz.trimf(ki.universe, [-0.02, -0.01, 0])
  54. ki['ZO'] = fuzz.trimf(ki.universe, [-0.01, 0, 0.01])
  55. ki['PS'] = fuzz.trimf(ki.universe, [0, 0.01, 0.02])
  56. ki['PB'] = fuzz.trimf(ki.universe, [0.01, 0.02, 0.02])
  57. kd['NB'] = fuzz.trimf(kd.universe, [-0.02, -0.02, -0.01])
  58. kd['NS'] = fuzz.trimf(kd.universe, [-0.02, -0.01, 0])
  59. kd['ZO'] = fuzz.trimf(kd.universe, [-0.01, 0, 0.01])
  60. kd['PS'] = fuzz.trimf(kd.universe, [0, 0.01, 0.02])
  61. kd['PB'] = fuzz.trimf(kd.universe, [0.01, 0.02, 0.02])
  62. rule1 = ctrl.Rule((e['NB'] & del_e['NB']) | (e['PS'] & del_e['PB']), kp['PB'])
  63. rule2 = ctrl.Rule((e['NB'] & del_e['NS']) | (e['NB'] & del_e['ZO']) | (e['NB'] & del_e['PS']) | (e['NS'] & del_e['NS']) | (e['NS'] & del_e['ZO']) | (e['ZO'] & del_e['NS']) | (e['PB'] & del_e['NS']) | (e['PB'] & del_e['ZO']) | (e['PB'] & del_e['PS']), kp['NS'])
  64. rule3 = ctrl.Rule((e['NB'] & del_e['PB']) | (e['NS'] & del_e['PS']) | (e['ZO'] & del_e['ZO']) | (e['PS'] & del_e['NS']) | (e['PB'] & del_e['NB']), kp['ZO'])
  65. rule4 = ctrl.Rule((e['NS'] & del_e['NB']) | (e['NS'] & del_e['PB']) | (e['ZO'] & del_e['NB']) | (e['ZO'] & del_e['PS']) | (e['ZO'] & del_e['PB']) | (e['PS'] & del_e['NB']) | (e['PS'] & del_e['ZO']) | (e['PS'] & del_e['PS']), kp['PS'])
  66. rule5 = ctrl.Rule((e['PB'] & del_e['PB']), kp['NB'])
  67. rule6 = ctrl.Rule((e['PS'] & del_e['PB']) | (e['PB'] & del_e['PB']), ki['PB'])
  68. rule7 = ctrl.Rule((e['NB'] & del_e['NS']) | (e['NB'] & del_e['ZO']) | (e['NB'] & del_e['PS']) | (e['NS'] & del_e['NS']) | (e['NS'] & del_e['ZO'])| (e['ZO'] & del_e['NB']) | (e['ZO'] & del_e['NS']) | (e['PS'] & del_e['NB']), ki['NS'])
  69. rule8 = ctrl.Rule((e['NB'] & del_e['PB']) | (e['NS'] & del_e['PS']) | (e['ZO'] & del_e['ZO']) | (e['PS'] & del_e['NS']) | (e['PB'] & del_e['NB']), ki['ZO'])
  70. rule9 = ctrl.Rule((e['NS'] & del_e['PB']) | (e['ZO'] & del_e['PS']) | (e['ZO'] & del_e['PB']) | (e['PS'] & del_e['ZO']) | (e['PS'] & del_e['PS']) | (e['PB'] & del_e['NS']) | (e['PB'] & del_e['ZO'])| (e['PB'] & del_e['PS']), ki['PS'])
  71. rule10 = ctrl.Rule((e['NB'] & del_e['NB'])|(e['NS'] & del_e['NB']), ki['NB'])
  72. rule11 = ctrl.Rule((e['PB'] & del_e['NB']) | (e['PB'] & del_e['PB']), kd['PB'])
  73. rule12 = ctrl.Rule((e['NS'] & del_e['NS']) | (e['NS'] & del_e['ZO']) | (e['NS'] & del_e['PS']) | (e['ZO'] & del_e['NS']) | (e['ZO'] & del_e['ZO'])| (e['ZO'] & del_e['PS']), kd['NS'])
  74. rule13 = ctrl.Rule((e['NS'] & del_e['NB']) | (e['NS'] & del_e['PB']) | (e['ZO'] & del_e['NB'])| (e['ZO'] & del_e['PB']) | (e['PS'] & del_e['NB']) | (e['PS'] & del_e['NS'])| (e['PS'] & del_e['ZO'])| (e['PS'] & del_e['PS'])| (e['PS'] & del_e['PB']), kd['ZO'])
  75. rule14 = ctrl.Rule((e['NS'] & del_e['PB']) | (e['ZO'] & del_e['PS']) | (e['ZO'] & del_e['PB']) | (e['PS'] & del_e['ZO']) | (e['PS'] & del_e['PS']) | (e['PB'] & del_e['NS']) | (e['PB'] & del_e['ZO'])| (e['PB'] & del_e['PS']), kd['PS'])
  76. rule15 = ctrl.Rule((e['NB'] & del_e['NS'])|(e['NB'] & del_e['ZO'])|(e['NB'] & del_e['PS']), kd['NB'])
  77. sys = ctrl.ControlSystem([rule1, rule2, rule3, rule4, rule5,rule6, rule7, rule8, rule9, rule10, rule11, rule12, rule13, rule14, rule15])
  78. fu = ctrl.ControlSystemSimulation(sys)
  79. for _ in range(num_iterations):
  80. error = system.get_error()
  81. fu.input['e']=error
  82. fu.input['del_e']= error-controller.last_error
  83. fu.compute()
  84. controller.Kp += fu.output['kp']
  85. controller.Ki += fu.output['ki']
  86. controller.Kd += fu.output['kd']
  87. print("KP:",controller.Kp,"KI:",controller.Ki,"KD:",controller.Kd,"error:",error,"del_error:",error-controller.last_error)
  88. control_signal = controller.control(error)
  89. # system.update(control_signal)
  90. temp.append(system.update(control_signal))
  91. errors.append(error)
  92. signal.append(control_signal)
  93. return temp
  94. #controller.input['e']=20
  95. #controller.input['del_e']=2
  96. #controller.compute()
  97. #p=controller.output['kp']
  98. #print(p)
  99. #upsampled = np.linspace(-10,10,21)
  100. #x,y=np.meshgrid(upsampled,upsampled)
  101. #z=np.zeros_like(x)
  102. #pp=[]
  103. #for i in range(0,10):
  104. # for j in range(-10,10):
  105. # controller.input['e']=x[i,j]
  106. # controller.input['del_e']=y[i,j]
  107. # controller.compute()
  108. # z[i,j]=controller.output['kp']
  109. # pp.append(z[i,j])
  110. #fig = plt.figure(figsize=(10,10))
  111. #ax = fig.add_subplot(111,projection='3d')
  112. #surf = ax.plot_surface(x,y,z,rstride=1,cstride=1,cmap='viridis',linewidth=0.4,antialiased=True)
  113. #ax.view_init(30,200)
  114. #plt.show()
  115. target_temp = 30
  116. pid_controller = PIDController(0.4,0,0)
  117. temperature_system = TemperatureSystem(target_temp)
  118. temp = train(pid_controller,temperature_system, 10)
  119. plt.plot(temp, 'ro--', linewidth=2, markersize=6, label="fuzzy") # 簡化後的程式碼
  120. plt.xlabel('Time')
  121. plt.ylabel('temp')
  122. plt.title('ML PID control')
  123. plt.legend()
  124. plt.show()