一、前言

近期在实际项目中使用到了PID控制算法,于是就该算法做一总结。

二、PID控制算法详解

2.1 比例控制算法

例子:
假设一个水缸,需要最终控制水缸的水位永远维持在1米的高度。

水位目标:T
当前水位:Tn
加水量:U
误差:error
error=T-Tn
比例控制系数:kp
U=kp∗errorU = k_p * errorU=kp​∗error
initial: T=1; Tn=0.2, error=1-0.2=0.8; kp=0.4

2.1.1 比例控制python简单示意

T=1
Tn=0.2
error=1-0.2
kp=0.4for t in range(1, 10):U = kp * errorTn += Uerror = T-Tnprint(f't={t} | add {U:.5f} => Tn={Tn:.5f} error={error:.5f}')"""
t=1 | add 0.32000 => Tn=0.52000 error=0.48000
t=2 | add 0.19200 => Tn=0.71200 error=0.28800
t=3 | add 0.11520 => Tn=0.82720 error=0.17280
t=4 | add 0.06912 => Tn=0.89632 error=0.10368
t=5 | add 0.04147 => Tn=0.93779 error=0.06221
t=6 | add 0.02488 => Tn=0.96268 error=0.03732
t=7 | add 0.01493 => Tn=0.97761 error=0.02239
t=8 | add 0.00896 => Tn=0.98656 error=0.01344
t=9 | add 0.00537 => Tn=0.99194 error=0.00806
"""

2.1.2 比例控制存在的一些问题

根据kp取值不同,系统最后都会达到1米,只不过kp大了达到的更快。不会有稳态误差。
若存在漏水情况,在相同情况下,经过多次加水后,水位会保持在0.75不在再变化,因为当U和漏水量一致的时候将保持不变——即稳态误差
U=kp∗error=0.1=>error=0.1/0.4=0.25U=k_p*error=0.1 => error = 0.1/0.4 = 0.25 U=kp​∗error=0.1=>error=0.1/0.4=0.25,所以误差永远保持在0.25

T=1
Tn=0.2
error=1-0.2
kp=0.4
extra_drop = 0.1for t in range(1, 100):U = kp * errorTn += U - extra_droperror = T-Tnprint(f't={t} | add {U:.5f} => Tn={Tn:.5f} error={error:.5f}')"""
t=95 | add 0.10000 => Tn=0.75000 error=0.25000
t=96 | add 0.10000 => Tn=0.75000 error=0.25000
t=97 | add 0.10000 => Tn=0.75000 error=0.25000
t=98 | add 0.10000 => Tn=0.75000 error=0.25000
t=99 | add 0.10000 => Tn=0.75000 error=0.25000
"""

实际情况中,这种类似水缸漏水的情况往往更加常见

  • 比如控制汽车运动,摩擦阻力就相当于是"漏水"
  • 控制机械臂、无人机的飞行,各类阻力和消耗相当于"漏水"

所以单独的比例控制,很多时候并不能满足要求

2.2 积分控制算法(消除稳态误差)

比例+积分控制算法:
U=kp∗error+ki∗∑errorU = k_p*error + k_i * \sum errorU=kp​∗error+ki​∗∑error

  • ∑error\sum error∑error: 误差累计
  • kik_iki​: 积分控制系数

2.2.1 python简单实现

T=1
Tn=0.2
error=1-0.2
kp=0.4
extra_drop = 0.1
ki=0.2
sum_error = 0for t in range(1, 20):sum_error += errorU = kp * error + ki * sum_errorTn += U - extra_droperror = T-Tnprint(f't={t} | add {U:.5f} => Tn={Tn:.5f} error={error:.5f}')"""
t=14 | add 0.10930 => Tn=0.97665 error=0.02335
t=15 | add 0.11025 => Tn=0.98690 error=0.01310
t=16 | add 0.10877 => Tn=0.99567 error=0.00433
t=17 | add 0.10613 => Tn=1.00180 error=-0.00180
t=18 | add 0.10332 => Tn=1.00512 error=-0.00512
t=19 | add 0.10097 => Tn=1.00608 error=-0.00608
"""

2.3 微分控制算法(减少控制中的震荡)

在越靠近目标的时候则加的越少。
U=kd∗(errort−errort−1)U=k_d*(error_t - error_{t-1})U=kd​∗(errort​−errort−1​)

  • kd: 微分控制系数
  • d_error/d_t ~= error_t - error_t_1:误差的变化

加入微分控制算法的python简单示意

令:kd=0.2; d_error = 当前时刻误差-前时刻误差

T=1
Tn=0.2
error=1-0.2
kp=0.4
extra_drop = 0.1ki=0.2
sum_error = 0kd=0.2
d_error = 0
error_n = 0
error_b = 0for t in range(1, 20):error_b = error_nerror_n = error# print(error_b1, error_b2)d_error = error_n - error_b if t >= 2 else 0sum_error += errorU = kp * error + ki * sum_error + kd * d_errorTn += U - extra_droperror = T-Tnprint(f't={t} | add {U:.5f} => Tn={Tn:.5f} error={error:.5f} | d_error: {d_error:.5f}')"""
t=14 | add 0.09690 => Tn=0.96053 error=0.03947 | d_error: 0.01319
t=15 | add 0.10402 => Tn=0.96455 error=0.03545 | d_error: 0.00310
t=16 | add 0.10808 => Tn=0.97263 error=0.02737 | d_error: -0.00402
t=17 | add 0.10951 => Tn=0.98214 error=0.01786 | d_error: -0.00808
t=18 | add 0.10899 => Tn=0.99113 error=0.00887 | d_error: -0.00951
t=19 | add 0.10727 => Tn=0.99840 error=0.00160 | d_error: -0.00899
"""

2.4 PID算法总结

pid = 比例控制(基本控制) + 积分控制(消除稳态误差)+微分控制(减少震荡)
U(t)=Kp∗errort+Ki∑i=0terrori+Kd∗(errort−errort−1)U(t) = K_p * error_t + K_i\sum_{i=0}^{t}error_i + K_d*(error_t - error_{t-1})U(t)=Kp​∗errort​+Ki​i=0∑t​errori​+Kd​∗(errort​−errort−1​)

  • KpK_pKp​:快速调整 比例控制P control能够提高系统的响应速度和稳态精度,抑制扰动对系统稳态的影响。但过大的比例控制容易导致系统超调和振荡,并且有可能使得系统变得不稳定。 纯比例控制并不能消除稳态误差,存在静差。
  • KiK_iKi​:准确到最终目标,积分控制能够消除0型系统对于常值输入信号和常值扰动造成的输出稳态误差,可以与P control一起组成PI control。积分控制的常数 根据系统所需的动态进去选取,并不会影响消除误差的效果,具有一定的鲁棒性。
  • KdK_dKd​: 稳步迭代, 微分器会对高频噪音有放大的效果

for kp_i in np.linspace(0, 1, 10):
pid_plot(kp=kp_i, ki=0.2, kd=0.2)

for ki_i in np.linspace(0, 1, 10):
pid_plot(kp=0.5, ki=ki_i, kd=0.2)

for kd_i in np.linspace(0, 1, 10):
pid_plot(kp=0.5, ki=0.2, kd=kd_i)

pid_plot(kp=0.65, ki=0.05, kd=0.5, print_flag=True)

三、牛顿法调参

损失函数采用:RMSE

from scipy import optimize
import matplotlib.pyplot as plt
import numpy as npdef pid_plot(args, plot_flag=True, print_flag=False):kp, ki, kd = argsT=1Tn=0.2error=1-0.2extra_drop = 0.1sum_error = 0d_error = 0error_n = 0error_b = 0Tn_list = []for t in range(1, 100):error_b = error_nerror_n = errord_error = error_n - error_b if t >= 2 else 0sum_error += errorU = kp * error + ki * sum_error + kd * d_errorTn += U - extra_droperror = T-TnTn_list.append(Tn)if print_flag:print(f't={t} | add {U:.5f} => Tn={Tn:.5f} error={error:.5f} | d_error: {d_error:.5f}')if plot_flag:plt.plot(Tn_list)plt.axhline(1, linestyle='--', color='darkred', alpha=0.8)plt.title(f'$K_p$={kp:.3f} $K_i$={ki:.3f} $K_d$={kd:.3f}')plt.ylim([0, max(Tn_list) + 0.2])plt.show()loss = np.sqrt(np.mean(np.square(np.ones_like(Tn_list) - np.array(Tn_list))))return lossboundaries=[(0, 2), (0, 2), (0, 2)]
res = optimize.fmin_l_bfgs_b(pid_plot, np.array([0.1, 0.1, 0.1]), args=(False, False), bounds = boundaries, approx_grad = True)pid_plot(res[0].tolist(), print_flag=True)
pid_plot([0.65, 0.05, 0.5], print_flag=True)
  • 牛顿法调参结果图示
  • 简单手动调参图示

PID原理及python简单实现与调参相关推荐

  1. 蒙版原理以及Python简单实现

    第一次发博客,就试试看的心态,不喜勿喷~ 蒙版可以将两张毫不相关的图片合成为一张图,其实就是使用蒙版mask对两张图片的像素做了加权平均处理的结果. 比如对于像素点(x1,y1,v1), (x2,y2 ...

  2. python朴素贝叶斯调参_邹博机器学习升级版II附讲义、参考书与源码下载(数学 xgboost lda hmm svm)...

    课程介绍 本课程特点是从数学层面推导最经典的机器学习算法,以及每种算法的示例和代码实现(Python).如何做算法的参数调试.以实际应用案例分析各种算法的选择等. 1.每个算法模块按照"原理 ...

  3. 随机森林原理_机器学习(29):随机森林调参实战(信用卡欺诈预测)

    点击"机器学习研习社","置顶"公众号 重磅干货,第一时间送达 回复[大礼包]送你机器学习资料与笔记 回顾 推荐收藏>机器学习文章集合:1-20 机器学习 ...

  4. python学习——超参数调参工具optuna

    感觉目前是适配于各种框架,机器学习框架,深度学习框架,都比较好用的一个调参框架 参考文献:1.https://github.com/optuna/optuna-examples 2.https://z ...

  5. 双向联想记忆网络的原理与python简单实现

    文章目录 原理 处理步骤 思考 源代码 1. 计算网络 2. 验证网络能力: 原理 联想记忆功能分为自联想和异联想,异联想也称为双向联想记忆,简写为BAM.BAM存储器可存储两组矢量,若有如下N维矢量 ...

  6. python模型调参三种方法

    1.机器学习常用三种调参方法:网格搜索.随机搜索和贝叶斯调参 2.网格搜索是遍历式搜索方法,效率较低,资源消耗多 3.网格搜索和随机搜索都没有考虑前面搜索的先验知识 4.贝叶斯调参的原理是贝叶斯优化, ...

  7. 随机森林实现及调参的R与Python对比——以泰坦尼克幸存者数据为例

    随机森林实现及调参 一.R语言 方法一.手动调参 方法二.网格调参 二.python 注:本博客数据仍采用决策树调参的泰坦尼克号数据,前奏(数据预处理)请参考☞ 决策树R&Python调参对比 ...

  8. 什么是陀螺仪的dr算法_PID控制器调参工具——DR-PID Tuning(Matlab GUI)

    介绍调参工具前,简单讨论一下PID控制器. 一.PID困境 受益于PID控制器的简单,我们在控制工程中往往首选PID. 受限于PID调参的困难,我们常常质疑PID控制器的性能平庸. 毕竟高大上的先进控 ...

  9. 一文掌握模型调参神器:Hyperopt

    hyperopt是一个Python库,主要使用 ①随机搜索算法 ②模拟退火算法 ③TPE算法 来对某个算法模型的最佳参数进行智能搜索,它的全称是Hyperparameter Optimization. ...

最新文章

  1. LeetCode之Sort List
  2. Android 获取手机的UUID
  3. vuepress侧边栏配置_vuepress的侧边栏怎么动态生成
  4. C/C++中退出线程的四种解决方法
  5. 安卓程序如何保证低内存下依然存在
  6. js map遍历 修改对象里面的值_js中那些方法不改变原来的数组对象
  7. 吴恩达作业1:逻辑回归实现猫的分类
  8. Memcached与Redis的区别和选择
  9. bzoj3390[Usaco2004 Dec]Bad Cowtractors牛的报复*
  10. 使用js调用摄像头拍照
  11. 【密码专栏】动手计算双线性对(上)
  12. 智工教育:公务员考试这些知识点你会背了吗?
  13. java html网页生成pdf文件,html 网页生成pdf 文件
  14. Web前端工程师的职业规划,助你走好前端路
  15. 基于Python的百度地图慧眼迁徙数据爬取
  16. 大学物理实验(二)气体比热容比的测定
  17. linux防ddos攻击脚本,Linux IPTables防DDOS攻击Shell脚本
  18. JavaScript知识点复习总结
  19. linux python 路径获取
  20. 均值不等式的来龙去脉

热门文章

  1. 解决ios浏览器视频无法播放问题
  2. 怎么画好一个项目甘特图(内附实用模板)
  3. layui-tree实现Ajax异步请求后动态添加html元素
  4. 不平衡数据采样_过度采样不平衡数据的5种打击技术
  5. 如何做出正确的选择-面对两难,如何做出“不后悔”的选择?
  6. 问责制Accountability
  7. Ubuntu 下安装 苹果主题界面Mac Sierra Theme
  8. Coursera课程答案分享
  9. java简单投票系统_基于SpringBoot的简约投票系统
  10. 制作一个USB可燃气体声光报警器