123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- import numpy as np
- import skfuzzy as fuzz
- import matplotlib.pyplot as plt
- #from mpl_toolkit.mplot3d import Axes3D
- from skfuzzy import control as ctrl
- import math
- class PIDController:
- def __init__(self, Kp, Ki, Kd):
- self.Kp = Kp
- self.Ki = Ki
- self.Kd = Kd
- self.last_error = 0
- self.integral = 0
- def control(self, error):
- output = self.Kp * error + self.Ki * self.integral + self.Kd * (error - self.last_error)
- self.integral += error
- self.last_error = error
- return output
- class TemperatureSystem:
- def __init__(self, target_temp):
- self.target_temp = target_temp
- self.current_temp = 0
- def update(self, control_singal):
- self.current_temp += control_singal * 1
- return self.current_temp
- def get_error(self):
- return self.target_temp - self.current_temp
- def train(controller,system, num_iterations):
- errors = []
- signal = []
- temp = []
- e = ctrl.Antecedent(np.arange(-80, 80, 1), 'e')
- del_e = ctrl.Antecedent(np.arange(-6, 6, 1), 'del_e')
- kp = ctrl.Consequent(np.arange(-0.8, 0.8, 0.01), 'kp')
- ki = ctrl.Consequent(np.arange(-0.1, 0.1, 0.005), 'ki')
- kd = ctrl.Consequent(np.arange(-0.1, 0.1, 0.005), 'kd')
- e['NB'] = fuzz.trimf(e.universe, [-80, -80, -40])
- e['NS'] = fuzz.trimf(e.universe, [-80, -40, 0])
- e['ZO'] = fuzz.trimf(e.universe, [-40, 0, 40])
- e['PS'] = fuzz.trimf(e.universe, [0, 40, 80])
- e['PB'] = fuzz.trimf(e.universe, [40, 80, 80])
- del_e['NB'] = fuzz.trimf(del_e.universe, [-6, -6, -3])
- del_e['NS'] = fuzz.trimf(del_e.universe, [-6, -3, 0])
- del_e['ZO'] = fuzz.trimf(del_e.universe, [-3, 0, 3])
- del_e['PS'] = fuzz.trimf(del_e.universe, [0, 3, 6])
- del_e['PB'] = fuzz.trimf(del_e.universe, [3, 6, 6])
- kp['NB'] = fuzz.trimf(kp.universe, [-0.8, -0.8, -0.4])
- kp['NS'] = fuzz.trimf(kp.universe, [-0.8, -0.4, 0])
- kp['ZO'] = fuzz.trimf(kp.universe, [-0.4, 0, 0.4])
- kp['PS'] = fuzz.trimf(kp.universe, [0, 0.4, 0.8])
- kp['PB'] = fuzz.trimf(kp.universe, [0.4, 0.8, 0.8])
- ki['NB'] = fuzz.trimf(ki.universe, [-0.02, -0.02, -0.01])
- ki['NS'] = fuzz.trimf(ki.universe, [-0.02, -0.01, 0])
- ki['ZO'] = fuzz.trimf(ki.universe, [-0.01, 0, 0.01])
- ki['PS'] = fuzz.trimf(ki.universe, [0, 0.01, 0.02])
- ki['PB'] = fuzz.trimf(ki.universe, [0.01, 0.02, 0.02])
- kd['NB'] = fuzz.trimf(kd.universe, [-0.02, -0.02, -0.01])
- kd['NS'] = fuzz.trimf(kd.universe, [-0.02, -0.01, 0])
- kd['ZO'] = fuzz.trimf(kd.universe, [-0.01, 0, 0.01])
- kd['PS'] = fuzz.trimf(kd.universe, [0, 0.01, 0.02])
- kd['PB'] = fuzz.trimf(kd.universe, [0.01, 0.02, 0.02])
- rule1 = ctrl.Rule((e['NB'] & del_e['NB']) | (e['PS'] & del_e['PB']), kp['PB'])
- 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'])
- 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'])
- 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'])
- rule5 = ctrl.Rule((e['PB'] & del_e['PB']), kp['NB'])
- rule6 = ctrl.Rule((e['PS'] & del_e['PB']) | (e['PB'] & del_e['PB']), ki['PB'])
- 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'])
- 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'])
- 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'])
- rule10 = ctrl.Rule((e['NB'] & del_e['NB'])|(e['NS'] & del_e['NB']), ki['NB'])
- rule11 = ctrl.Rule((e['PB'] & del_e['NB']) | (e['PB'] & del_e['PB']), kd['PB'])
- 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'])
- 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'])
- 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'])
- rule15 = ctrl.Rule((e['NB'] & del_e['NS'])|(e['NB'] & del_e['ZO'])|(e['NB'] & del_e['PS']), kd['NB'])
- sys = ctrl.ControlSystem([rule1, rule2, rule3, rule4, rule5,rule6, rule7, rule8, rule9, rule10, rule11, rule12, rule13, rule14, rule15])
- fu = ctrl.ControlSystemSimulation(sys)
- for _ in range(num_iterations):
- error = system.get_error()
- fu.input['e']=error
- fu.input['del_e']= error-controller.last_error
- fu.compute()
- controller.Kp += fu.output['kp']
- controller.Ki += fu.output['ki']
- controller.Kd += fu.output['kd']
- print("KP:",controller.Kp,"KI:",controller.Ki,"KD:",controller.Kd,"error:",error,"del_error:",error-controller.last_error)
- control_signal = controller.control(error)
- # system.update(control_signal)
- temp.append(system.update(control_signal))
- errors.append(error)
- signal.append(control_signal)
- return temp
- #controller.input['e']=20
- #controller.input['del_e']=2
- #controller.compute()
- #p=controller.output['kp']
- #print(p)
- #upsampled = np.linspace(-10,10,21)
- #x,y=np.meshgrid(upsampled,upsampled)
- #z=np.zeros_like(x)
- #pp=[]
- #for i in range(0,10):
- # for j in range(-10,10):
- # controller.input['e']=x[i,j]
- # controller.input['del_e']=y[i,j]
- # controller.compute()
- # z[i,j]=controller.output['kp']
- # pp.append(z[i,j])
- #fig = plt.figure(figsize=(10,10))
- #ax = fig.add_subplot(111,projection='3d')
- #surf = ax.plot_surface(x,y,z,rstride=1,cstride=1,cmap='viridis',linewidth=0.4,antialiased=True)
- #ax.view_init(30,200)
- #plt.show()
- target_temp = 30
- pid_controller = PIDController(0.4,0,0)
- temperature_system = TemperatureSystem(target_temp)
- temp = train(pid_controller,temperature_system, 10)
- plt.plot(temp, 'ro--', linewidth=2, markersize=6, label="fuzzy") # 簡化後的程式碼
- plt.xlabel('Time')
- plt.ylabel('temp')
- plt.title('ML PID control')
- plt.legend()
- plt.show()
|