pid.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. from utils import *
  2. class PID:
  3. def __init__(self, kp=0, ki=0, kd=0, dt=1, target=1, Kc=0, Ti=0, Td=0, Ts=0, debug=False):
  4. self.Kp = kp # discrete pid kp
  5. self.Ki = ki # discrete pid ki
  6. self.Kd = kd # discrete pid kd
  7. self.T = dt # discrete pid frequency time.
  8. self.Ti = Ti # takahashi ti
  9. self.Td = Td # takahashi td
  10. self.Ts = Ts # takahashi ts
  11. self.Kc = Kc # takahashi kc
  12. self.target = target # pid set point
  13. self.prev_feedback = 0
  14. self.feedback_hist = [0, 0]
  15. self.f_hist = [0]
  16. self.error_hist = [0, 0]
  17. self.debug=debug
  18. def pid(self, feedback):
  19. ret = (self.Kp * self.proportional(feedback)) + (self.Ki * self.integral(feedback)) + (self.Kd * self.derivative(feedback))
  20. self.feedback_hist+=[feedback]
  21. self.prev_feedback=feedback
  22. return ret
  23. def discrete_pid(self, feedback, debug=True):
  24. k1 = self.Kp + self.Ki + self.Kd
  25. k2 = -1 * self.Kp - 2 * self.Kd
  26. k3 = self.Kd
  27. err = self.proportional(feedback)
  28. #if debug:
  29. #print("pid::f-1: {}".format(self.f_hist[-1]))
  30. #print("pid::err: {}".format(err))
  31. #print("pid::err-1: {}".format(self.error_hist[-1]))
  32. #print("pid::err-2: {}".format(self.error_hist[-2]))
  33. #print("pid::k1: {}".format(k1))
  34. #print("pid::k2: {}".format(k2))
  35. #print("pid::k3: {}".format(k3))
  36. ret = self.f_hist[-1] + k1 * err + k2 * self.error_hist[-1] + k3 * self.error_hist[-2]
  37. self.error_hist+=[err]
  38. self.feedback_hist+=[feedback]
  39. return ret
  40. def takahashi(self, feedback, debug=True):
  41. err = self.proportional(feedback)
  42. ret = self.f_hist[-1] + self.Kc * (self.feedback_hist[-1] - feedback + self.Ts * err/ self.Ti + self.Td / self.Ts * (2*self.feedback_hist[-1] - feedback - self.feedback_hist[-2]))
  43. self.error_hist+=[err]
  44. self.feedback_hist+=[feedback]
  45. return ret
  46. def pid_clipped(self, feedback, controller=CONTROLLER_TYPE_DISCRETE, debug=True):
  47. pid_value = None
  48. if controller == CONTROLLER_TYPE_TAKAHASHI:
  49. pid_value = self.takahashi(feedback, debug)
  50. elif controller == CONTROLLER_TYPE_DISCRETE:
  51. pid_value = self.discrete_pid(feedback, debug)
  52. else:
  53. pid_value = self.pid(feedback)
  54. if pid_value <= 0.0:
  55. pid_value = F_MIN
  56. elif pid_value >= 1:
  57. pid_value = F_MAX
  58. if self.integral(feedback) == 0 and len(self.feedback_hist) >=3 and self.feedback_hist[-1] == 0 and self.feedback_hist[-2] == 0 and self.feedback_hist[-3] == 0:
  59. pid_value = 0.9**self.zero_lead_hist()
  60. self.f_hist+=[pid_value]
  61. return pid_value
  62. def zero_lead_hist(self):
  63. count = 0
  64. length = len(self.feedback_hist)
  65. for i in range(0,length):
  66. if self.feedback_hist[length-(i+1)]==0:
  67. count+=1
  68. else:
  69. return count
  70. return count
  71. def error(self, feedback):
  72. return feedback - self.target
  73. def proportional(self, feedback):
  74. return self.error(feedback)
  75. def integral(self, feedback):
  76. return sum(self.feedback_hist[-10:]) + feedback
  77. def derivative(self, feedback):
  78. return (self.error(self.prev_feedback) - self.error(feedback)) / self.T
  79. def write_feedback(self, lead_hist_file):
  80. if len(self.feedback_hist)==0:
  81. return
  82. buf = ''
  83. buf+=str(self.feedback_hist[0])
  84. buf+=','
  85. for i in self.feedback_hist[1:]:
  86. buf+=str(i)+','
  87. with open(lead_hist_file, "w+") as f:
  88. f.write(buf)
  89. def write_fval(self, f_hist_file):
  90. if len(self.f_hist)==0:
  91. return
  92. buf = ''
  93. buf+=str(self.f_hist[0])
  94. buf+=','
  95. for i in self.f_hist[1:]:
  96. buf+=str(i)+','
  97. with open(f_hist_file, "w+") as f:
  98. f.write(buf)
  99. def write(self, lead_hist_file='leads.hist', f_hist_file='f.hist'):
  100. self.write_feedback(lead_hist_file)
  101. self.write_fval(f_hist_file)
  102. def acc(self):
  103. return sum(np.array(self.feedback_hist)==1)/float(len(self.feedback_hist))