pid.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. #ifndef _PID_SOURCE_
  2. #define _PID_SOURCE_
  3. #include <iostream>
  4. #include <cmath>
  5. #include <QDebug>
  6. #include "pid.h"
  7. using namespace std;
  8. #define STAGE_INIT (0)
  9. #define STAGE_LOW (1)
  10. #define STAGE_MID (2)
  11. #define STAGE_HIGH (3)
  12. class PIDImpl
  13. {
  14. public:
  15. PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki);
  16. PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI);
  17. PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxStep);
  18. ~PIDImpl();
  19. double calculate( double setpoint, double pv );
  20. double calculate_v2( double setpoint, double pv );
  21. void reset();
  22. private:
  23. double _dt;
  24. double _max;
  25. double _min;
  26. double _Kp;
  27. double _Kd;
  28. double _Ki;
  29. double _pre_error;
  30. double _integral;
  31. double _maxI;
  32. double _maxStep;
  33. double _pre_output;
  34. double _start_pv;
  35. double _critical_output;
  36. int _stage;
  37. };
  38. PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki)
  39. {
  40. pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki);
  41. }
  42. PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI)
  43. {
  44. pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki,maxI);
  45. }
  46. PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxStep)
  47. {
  48. pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki,maxI, maxStep);
  49. }
  50. double PID::calculate( double setpoint, double pv )
  51. {
  52. return pimpl->calculate(setpoint,pv);
  53. }
  54. double PID::calculate_v2( double setpoint, double pv )
  55. {
  56. return pimpl->calculate_v2(setpoint,pv);
  57. }
  58. void PID::reset()
  59. {
  60. return pimpl->reset();
  61. }
  62. PID::~PID()
  63. {
  64. delete pimpl;
  65. }
  66. /**
  67. * Implementation
  68. */
  69. PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki) :
  70. _dt(dt),
  71. _max(max),
  72. _min(min),
  73. _Kp(Kp),
  74. _Kd(Kd),
  75. _Ki(Ki),
  76. _pre_error(0),
  77. _integral(0)
  78. {
  79. _maxI = 0;
  80. _maxStep = 0;
  81. _pre_output = 0;
  82. _start_pv = 0;
  83. _critical_output = 0;
  84. _stage = STAGE_INIT;
  85. }
  86. /**
  87. * Implementation
  88. */
  89. PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI) :
  90. _dt(dt),
  91. _max(max),
  92. _min(min),
  93. _Kp(Kp),
  94. _Kd(Kd),
  95. _Ki(Ki),
  96. _pre_error(0),
  97. _integral(0),
  98. _maxI(maxI)
  99. {
  100. _maxStep = 0;
  101. _pre_output = 0;
  102. _start_pv = 0;
  103. _critical_output = 0;
  104. _stage = STAGE_INIT;
  105. }
  106. /**
  107. * Implementation
  108. */
  109. PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxStep) :
  110. _dt(dt),
  111. _max(max),
  112. _min(min),
  113. _Kp(Kp),
  114. _Kd(Kd),
  115. _Ki(Ki),
  116. _pre_error(0),
  117. _integral(0),
  118. _maxI(maxI),
  119. _maxStep(maxStep)
  120. {
  121. _pre_output = 0;
  122. _start_pv = 0;
  123. _critical_output = 0;
  124. _stage = STAGE_INIT;
  125. }
  126. double PIDImpl::calculate( double setpoint, double pv )
  127. {
  128. // Calculate error
  129. double error = setpoint - pv;
  130. // Proportional term
  131. double Pout = _Kp * error;
  132. // Integral term
  133. _integral += error * _dt;
  134. double Iout = _Ki * _integral;
  135. //积分限幅
  136. if(_maxI > 0){
  137. if(Iout > _maxI){
  138. Iout = _maxI;
  139. }else if(Iout < -_maxI){
  140. Iout = -_maxI;
  141. }
  142. }
  143. // Derivative term
  144. double derivative = (error - _pre_error) / _dt;
  145. double Dout = _Kd * derivative;
  146. qDebug("calculate : pOut : %f, Iout: %f, Dout: %f ", Pout, Iout, Dout);
  147. // Calculate total output
  148. //double output = Pout + Iout + Dout;
  149. double output = Pout + Iout ;//+ Dout;
  150. // Restrict to max/min
  151. if( output > _max )
  152. output = _max;
  153. else if( output < _min )
  154. output = _min;
  155. // Save error to previous error
  156. _pre_error = error;
  157. if(_maxStep > 0){
  158. if(output - _pre_output > _maxStep){
  159. output = _pre_output + _maxStep;
  160. } else if(_pre_output - output > _maxStep){
  161. output = _pre_output - _maxStep;
  162. }
  163. }
  164. _pre_output = output;
  165. return output;
  166. }
  167. double PIDImpl::calculate_v2( double setpoint, double pv )
  168. {
  169. // Calculate error
  170. double error = setpoint - pv;
  171. // Proportional term
  172. double Pout = _Kp * error;
  173. // Integral term
  174. _integral += error * _dt;
  175. double Iout = _Ki * _integral;
  176. // Derivative term
  177. double derivative = (error - _pre_error) / _dt;
  178. double Dout = _Kd * derivative;
  179. qDebug("calculate_V2 : pOut : %f, Iout: %f, Dout: %f ", Pout, Iout, Dout);
  180. // Calculate total output
  181. //double output = Pout + Iout + Dout;
  182. double output = Pout + Iout ;//+ Dout;
  183. // Restrict to max/min
  184. if( output > _max )
  185. output = _max;
  186. else if( output < _min )
  187. output = _min;
  188. // Save error to previous error
  189. _pre_error = error;
  190. //belows add by avansguo
  191. if(STAGE_INIT == _stage){
  192. _start_pv = pv;
  193. _stage = STAGE_LOW;
  194. }else{
  195. if(pv < _start_pv){
  196. _start_pv = pv;
  197. qDebug("calculate _start_pv: %f ", _start_pv);
  198. }
  199. }
  200. if(_critical_output < 1.0){
  201. if(derivative <= (-0.02)){ //压力开始增加了,记录前值作为临界值
  202. _critical_output = _pre_output;
  203. qDebug("calculate _critical_output: %f ", _critical_output);
  204. }
  205. }
  206. double _distance = 0;
  207. if(setpoint - _start_pv < 0.5){
  208. _distance = 1;
  209. }else{
  210. _distance = error/(setpoint - _start_pv);
  211. }
  212. if(_distance <= 0.2){
  213. output = _critical_output + (_distance+0.1)*( _pre_output - _critical_output);
  214. }else if((_distance > 0.2) &&(_distance <= 0.5)){
  215. if(derivative > (-0.02)){ //压力不变或在下降
  216. }else if(derivative < (-0.2)){
  217. output = _pre_output+Dout;
  218. _integral = output;
  219. }{
  220. output = _pre_output;
  221. _integral = output;
  222. }
  223. }else{
  224. if(derivative < (-0.2)){
  225. output = _pre_output+Dout;
  226. _integral = output;
  227. }else if(derivative > (-0.02)){ //压力不变或在下降
  228. //解决当 开始压力与初始压力差距太小, 积分太慢的问题
  229. if(output-_pre_output < 2){
  230. output = _pre_output+2;
  231. _integral = output;
  232. }
  233. }else{
  234. output = _pre_output;
  235. _integral = output;
  236. }
  237. //
  238. }
  239. _pre_output = output;
  240. return output;
  241. }
  242. void PIDImpl::reset()
  243. {
  244. _pre_error = 0;
  245. _integral = 0;
  246. _pre_output = 0;
  247. _start_pv = 0;
  248. _critical_output = 0;
  249. _stage = STAGE_INIT;
  250. }
  251. PIDImpl::~PIDImpl()
  252. {
  253. }
  254. #endif