改进初学者的PID-微分冲击
最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettbeauregard.com/blog/2011/04/improving-the-beginner%E2%80%99s-pid-derivative-kick/
1、问题
这个修改将稍微调整微分项。其目标是消除一种被称为“微分冲击”的现象。
上图说明了问题。由于error = Setpoint-Input,设定值的任何变化都会导致偏差的瞬时变化。这种变化的导数是无穷大(实际上,由于dt不是0,它只是一个非常大的数字。)这个数字被输入PID方程,这导致输出中出现不希望的峰值。幸运的是,有一种简单的方法可以摆脱这种情况。
2、解决方案
事实证明,当设定值发生变化时,偏差的导数等于输入的负导数。这最终成为一个完美的解决方案。我们减去(Kd *输入的导数)而不是添加(Kd *偏差的导数)。这被称为使用“基于测量的微分”。
3、代码
1 /*working variables*/ 2 unsigned long lastTime; 3 double Input,Output,Setpoint; 4 double errSum,lastInput; 5 double kp,ki,kd; 6 int SampleTime = 1000; //1 sec 7 void Compute() 8 { 9 unsigned long now = millis(); 10 int timeChange = (now - lastTime); 11 if(timeChange>=SampleTime) 12 { 13 /*Compute all the working error variables*/ 14 double error = Setpoint - Input; 15 errSum += error; 16 double dInput = (Input - lastInput); 17 18 /*Compute PID Output*/ 19 Output = kp * error + ki * errSum - kd * dInput; 20 21 /*Remember some variables for next time*/ 22 lastInput = Input; 23 lastTime = now; 24 } 25 } 26 27 void SetTunings(double Kp,double Ki,double Kd) 28 { 29 double SampleTimeInSec = ((double)SampleTime)/1000; 30 kp = Kp; 31 ki = Ki * SampleTimeInSec; 32 kd = Kd / SampleTimeInSec; 33 } 34 35 void SetSampleTime(int NewSampleTime) 36 { 37 if (NewSampleTime > 0) 38 { 39 double ratio = (double)NewSampleTime 40 / (double)SampleTime; 41 ki *= ratio; 42 kd /= ratio; 43 SampleTime = (unsigned long)NewSampleTime; 44 } 45 }
这里的修改非常简单。我们用-dInput替换+ dError。我们现在需要记住lastInput,而不是记住lastError
4、结果
以下是这些修改对我们的影响。请注意,输入看起来仍然相同。所以我们得到相同的性能,但是每次设定点改变时我们都不会发出巨大的输出尖峰。
这也许没什么大不了的。这完全取决于应用程序对输出峰值有多敏感。但在我看来,没有冲击就不需要做更多的工作,所以为什么不把事情做好呢?
欢迎关注:
原文地址:https://www.cnblogs.com/foxclever/p/11219274.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- ggplot2 核密度图和直方图
- 喜欢的歌曲不在一个平台怎么办?你需要一个自己专属的音乐播放器
- ggplot_QQ图和ECDF
- tidyverse evaluation
- 下载歌曲的时候嫌麻烦?打造专属你的音乐下载器
- Tidyverse补充
- 抖音关键词热度搜索小程序(附源码)
- python自定义函数基础
- Python-科学计算-pandas-13-列名/删除列/替换nan
- python小程序,45行代码实现可切换版代码雨(附源码)
- R海拾遗-stringr
- stringr2
- Kubernetes 无状态应用的一般特征
- 一段简单的代码,能让所有GIF图实现时光倒流
- 你喜欢的女主播颜值多少分,今天带你测试虎牙直播女主播的颜值