【学习草稿】pid控制基础实现--往水桶注水

pid

1)非常通俗易懂的PID控制(1)https://zhuanlan.zhihu.com/p/37515841
球场上运动至指定地点(比例控制):有图【很直观的帮助理解】&有文字分析
2)初识PID-搞懂PID概念 https://zhuanlan.zhihu.com/p/74131690
【重点】数据有错误,但是跟着分析模拟了用p、pi、pid调控往水桶加水的过程
3)PID控制算法原理(抛弃公式,从本质上真正理解PID控制) https://zhuanlan.zhihu.com/p/39573490
看2)的时候 有时会看看3)帮助理解
在这里插入图片描述
在这里插入图片描述
其中r(t)表示给定输入值,c(t)表示实际输出值,e(t)表示信号偏差量=r(t)-c(t),u(t)表示修正量。 ------- https://www.cnblogs.com/cv-pr/p/4785195.html PID控制原理和算法。
PID调节器是一种线性调节器,它将给定值r(t)与实际输出值c(t)的偏差e(t)的比例§、积分(I)、微分(D)通过线性组合构成控制量u(t),对控制对象进行控制。
在这里插入图片描述

代码实现与绘图:python3+matplotlib

import matplotlib.pyplot as plt
print(list(range(1,5))) # python3
# 参考  https://zhuanlan.zhihu.com/p/74131690
# (1)有个水桶,需要时刻保持1m 的高度,目前水桶里有0.2m 的水
# 采用P(比例) 的方法加水:即每次测量与1m 的误差,并加入与误差成比例的水量
# 比如设Kp=0.5.
# 第一次,误差是 1-0.2=0.8m,那么加入水量是 Kp*0.8= 0.4mtarget = 1
now = 0.2
kp = 0.5error_list = [0]
uk_list = [0]
now_list = [0.2]
add_num = 0
while add_num < 30:error = target-nowerror_list.append(error)uk = kp*error # 基于误差输出add_num += 1 uk_list.append(uk)now = now + uknow_list.append(now)x=list(range(len(now_list)))
y=now_list
# 绘制折线图
plt.plot(x, y, label='Data Line')
# 绘制纵坐标线
plt.axhline(y=1, color='gray', linestyle='--')
# 绘制数据标记
for i in range(len(x)):# 绘制散点图plt.scatter(x[i], y[i], s=10, marker='o', color='red')# 用于标注文字,注释文本内容+被注释的坐标点+。。。# plt.annotate((x[i], y[i]), (x[i] + 0.1, y[i] - 0.051))
# 设置图表标题和标签
plt.title("kp = 0.5")
plt.xlabel("Adjustment times")
plt.ylabel("water level/m")
# 显示图表,得到一个带数据标记的折线图
plt.legend()
plt.show()print("error_list={}, len(error_list)={}".format(error_list, len(error_list)))
print("uk_list={}, len(uk_list)={}".format(uk_list, len(uk_list)))
print("now_list={}, len(now_list)={}".format(now_list, len(now_list)))

在这里插入图片描述

# (2) 新任务: 有个水桶,但桶底漏了个洞,仍需保持1m 的高度,
# 目前水桶里有0.2m 的水,但每次加水都会流出0.1m.
# 这个例子就接近我们实际工程的例子了,比如电机摩擦的阻力,损耗.
# 【】第一次仍是使用P (比例控制) u= Kp* e
target = 1
now = 0.2
kp = 0.5#1.9 #1 # 0.5error_list = [0]
uk_list = [0]
now_list = [0.2]
add_num = 0
while add_num < 60:error = target-nowerror_list.append(error)uk = kp*error # 基于误差输出add_num += 1 uk_list.append(uk)now = now + uk - 0.1now_list.append(now)x=list(range(len(now_list)))
y=now_list
# 绘制折线图
plt.plot(x, y, label='Data Line')
# 绘制纵坐标线
plt.axhline(y=1, color='gray', linestyle='--')
# 绘制数据标记
for i in range(len(x)):# 绘制散点图plt.scatter(x[i], y[i], s=10, marker='o', color='red')# 用于标注文字,注释文本内容+被注释的坐标点+。。。# plt.annotate((x[i], y[i]), (x[i] + 0.1, y[i] - 0.051))
# 设置图表标题和标签
plt.title("kp = 0.5")
plt.xlabel("Adjustment times")
plt.ylabel("water level/m")
# 显示图表,得到一个带数据标记的折线图
plt.legend()
plt.show()print("error_list={}, len(error_list)={}".format(error_list, len(error_list)))
print("uk_list={}, len(uk_list)={}".format(uk_list, len(uk_list)))
print("now_list={}, len(now_list)={}".format(now_list, len(now_list)))

在这里插入图片描述

# (2) 新任务: 有个水桶,但桶底漏了个洞,仍需保持1m 的高度,
# 目前水桶里有0.2m 的水,但每次加水都会流出0.1m.
# 这个例子就接近我们实际工程的例子了,比如电机摩擦的阻力,损耗.
# 【】第一次仍是使用P (比例控制) u= Kp* e
target = 1
now = 0.2
kp = 1 #1.9 #1 # 0.5error_list = [0]
uk_list = [0]
now_list = [0.2]
add_num = 0
while add_num < 60:error = target-nowerror_list.append(error)uk = kp*error # 基于误差输出add_num += 1 uk_list.append(uk)now = now + uk - 0.1now_list.append(now)x=list(range(len(now_list)))
y=now_list
# 绘制折线图
plt.plot(x, y, label='Data Line')
# 绘制纵坐标线
plt.axhline(y=1, color='gray', linestyle='--')
# 绘制数据标记
for i in range(len(x)):# 绘制散点图plt.scatter(x[i], y[i], s=10, marker='o', color='red')# 用于标注文字,注释文本内容+被注释的坐标点+。。。# plt.annotate((x[i], y[i]), (x[i] + 0.1, y[i] - 0.051))
# 设置图表标题和标签
plt.title("kp = 1")
plt.xlabel("Adjustment times")
plt.ylabel("water level/m")
# 显示图表,得到一个带数据标记的折线图
plt.legend()
plt.show()print("error_list={}, len(error_list)={}".format(error_list, len(error_list)))
print("uk_list={}, len(uk_list)={}".format(uk_list, len(uk_list)))
print("now_list={}, len(now_list)={}".format(now_list, len(now_list)))

在这里插入图片描述

# (2) 新任务: 有个水桶,但桶底漏了个洞,仍需保持1m 的高度,
# 目前水桶里有0.2m 的水,但每次加水都会流出0.1m.
# 这个例子就接近我们实际工程的例子了,比如电机摩擦的阻力,损耗.
# 【】第一次仍是使用P (比例控制) u= Kp* e
target = 1
now = 0.2
kp = 1.9 #1.9 #1 # 0.5error_list = [0]
uk_list = [0]
now_list = [0.2]
add_num = 0
while add_num < 60:error = target-nowerror_list.append(error)uk = kp*error # 基于误差输出add_num += 1 uk_list.append(uk)now = now + uk - 0.1now_list.append(now)x=list(range(len(now_list)))
y=now_list
# 绘制折线图
plt.plot(x, y, label='Data Line')
# 绘制纵坐标线
plt.axhline(y=1, color='gray', linestyle='--')
# 绘制数据标记
for i in range(len(x)):# 绘制散点图plt.scatter(x[i], y[i], s=10, marker='o', color='red')# 用于标注文字,注释文本内容+被注释的坐标点+。。。# plt.annotate((x[i], y[i]), (x[i] + 0.1, y[i] - 0.051))
# 设置图表标题和标签
plt.title("kp = 1.9")
plt.xlabel("Adjustment times")
plt.ylabel("water level/m")
# 显示图表,得到一个带数据标记的折线图
plt.legend()
plt.show()print("error_list={}, len(error_list)={}".format(error_list, len(error_list)))
print("uk_list={}, len(uk_list)={}".format(uk_list, len(uk_list)))
print("now_list={}, len(now_list)={}".format(now_list, len(now_list)))

在这里插入图片描述

# 结论: 比例控制引入了稳态误差,且无法消除.
#       比例常数增大可以减小稳态误差,但如果太大则引起系统震荡,不稳定.
# 为了消除稳态误差,第二次加入积分,使用PI(比例积分控制) 
# 积分控制就是将历史误差全部加起来乘以积分常数.target = 1
now = 0.2
kp = 0.5
ki = 0.5error_list = [0]
uk_list = [0]
now_list = [0.2]
add_num = 0
history_error_list = [0]
ukp_list = [0]
uki_list = [0]
while add_num < 30:error = target-nowerror_list.append(error)ukp = kp*error # 比例部分ukp_list.append(ukp)history_error=sum(error_list)history_error_list.append(history_error)uki = ki*history_error #积分部分uki_list.append(uki)add_num += 1uk = ukp + uki #基于误差输出uk_list.append(uk)now = now + uk - 0.1now_list.append(now)x=list(range(len(now_list)))
y=now_list
# 绘制折线图
plt.plot(x, y, label='Data Line')
# 绘制纵坐标线
plt.axhline(y=1, color='gray', linestyle='--')
# 绘制数据标记
for i in range(len(x)):# 绘制散点图plt.scatter(x[i], y[i], s=10, marker='o', color='red')# 用于标注文字,注释文本内容+被注释的坐标点+。。。# plt.annotate((x[i], y[i]), (x[i] + 0.1, y[i] - 0.051))
# 设置图表标题和标签
plt.title("kp = 0.5, ki = 0.5")
plt.xlabel("Adjustment times")
plt.ylabel("water level/m")
# 显示图表,得到一个带数据标记的折线图
plt.legend()
plt.show()    print("error_list={}, len(error_list)={}".format(error_list, len(error_list)))
print("ukp_list={}, len(ukp_list)={}".format(ukp_list, len(ukp_list)))
print("uki_list={}, len(uki_list)={}".format(uki_list, len(uki_list)))
print("uk_list={}, len(uk_list)={}".format(uk_list, len(uk_list)))
print("now_list={}, len(now_list)={}".format(now_list, len(now_list)))

在这里插入图片描述

# 引入积分可以消除稳态误差,但会增加超调,且Ki 增大,超调量也增大.
# 为了消除超调,我们引入微分作用target = 1
now = 0.2
kp = 0.5
ki = 0.5
kd = 0.3error_list = [0]
uk_list = [0]
now_list = [0.2]
add_num = 0
history_error_list = [0]
ukp_list = [0]
uki_list = [0]
ukd_list = [0]
while add_num < 30:error = target-nowerror_list.append(error)ukp = kp*error # 比例部分ukp_list.append(ukp)history_error=sum(error_list)history_error_list.append(history_error)uki = ki*history_error #积分部分uki_list.append(uki)if add_num==0:diff_error=0else:diff_error=error_list[-1]-error_list[-2]ukd = kd*diff_error # 微分部分ukd_list.append(ukd)add_num += 1uk = ukp + uki + ukd #基于误差输出uk_list.append(uk)now = now + uk - 0.1now_list.append(now)x=list(range(len(now_list)))
y=now_list
# 绘制折线图
plt.plot(x, y, label='Data Line')
# 绘制纵坐标线
plt.axhline(y=1, color='gray', linestyle='--')
# 绘制数据标记
for i in range(len(x)):# 绘制散点图plt.scatter(x[i], y[i], s=10, marker='o', color='red')# 用于标注文字,注释文本内容+被注释的坐标点+。。。# plt.annotate((x[i], y[i]), (x[i] + 0.1, y[i] - 0.051))
# 设置图表标题和标签
plt.title("kp = 0.5, ki = 0.5, kd = 0.3 ")
plt.xlabel("Adjustment times")
plt.ylabel("water level/m")
# 显示图表,得到一个带数据标记的折线图
plt.legend()
plt.show()       print("error_list={}, len(error_list)={}".format(error_list, len(error_list)))
print("ukp_list={}, len(ukp_list)={}".format(ukp_list, len(ukp_list)))
print("uki_list={}, len(uki_list)={}".format(uki_list, len(uki_list)))
print("ukd_list={}, len(ukd_list)={}".format(ukd_list, len(ukd_list)))
print("uk_list={}, len(uk_list)={}".format(uk_list, len(uk_list)))
print("now_list={}, len(now_list)={}".format(now_list, len(now_list)))

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/217344.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL-03-索引

索引是提高MySQL查询性能的一个重要途径&#xff0c;但过多的索引可能会导致过高的磁盘使用率以及过高的内存占用&#xff0c;从而影响应用程序的整体性能。应当尽量避免事后才想起添加索引&#xff0c;因为事后可能需要监控大量的SQL才能定位到问题所在&#xff0c;而且添加索…

【问题思考总结】多维随机变量函数的分布的两种情况的计算方法【离连/连连】

问题 今天做李六第一套的时候发现&#xff0c;有的时候&#xff0c;面对这种第二问的题&#xff0c;很自然地就想到了Fz&#xff08;z&#xff09;&#xff0c;然后进行化简&#xff0c;但是有的时候&#xff0c;像这道题&#xff0c;就突然发现P{XY<z}是一个非常复杂的形式…

The Bridge:从临床数据到临床应用(预测模型总结)

The Bridge:从临床数据到临床应用&#xff08;预测模型总结&#xff09; 如果说把临床预测模型比作临床数据和临床应用之间的一座“桥梁”&#xff0c;那它应该包括这样几个环节&#xff1a;模型的构建和评价、模型的概率矫正、模型决策阈值的确定和模型的局部再评价。 模型的构…

【从浅识到熟知Linux】基本指令之date和cal

&#x1f388;归属专栏&#xff1a;从浅学到熟知Linux &#x1f697;个人主页&#xff1a;Jammingpro &#x1f41f;每日一句&#xff1a;一篇又一篇&#xff0c;学写越上头。好像真的上头了~~ 文章前言&#xff1a;本文介绍date和cal指令用法并给出示例和截图。 文章目录 date…

为什么别人能做好CSGO游戏搬砖,而你不能?

CSGO搬砖日常出货更新 做Steam游戏搬砖的门槛很低&#xff0c;以至于这两年不断有小白涌入市场&#xff0c;想要在饰品市场中分一杯羹。这个项目是很简单&#xff0c;但想要站稳脚跟&#xff0c;有稳定收入的第一步就得搞清楚项目逻辑。 首先你得搞清楚&#xff0c;steam搬砖盈…

搜索引擎---项目测试

一)项目背景: 首先介绍一下项目:项目的目标是实现一个基于JAVAAPI的站内搜索引擎 java官方文档是在学习java语言中不可或缺的权威资料&#xff0c;相比于各种网站的Java资料&#xff0c;官方文档无论是语言表达还是组织方式都要更加全面和准确&#xff0c;因为没有人比作者更加…

数据结构与算法编程题24

中序遍历非递归算法 #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std;typedef char ElemType; #define ERROR 0 #define OK 1 #define Maxsize 100 #define STR_SIZE 1024typedef struct BiTNode {ElemType data;BiTNode* lchild, * rchild; }B…

从零到Kafka:万字带你体验Spring Boot整合消息驱动的奇妙之旅

Spring Boot与Kafka从零开始整合指南 准备工作创建项目 Spring Boot与Kafka的初次邂逅配置生产者消费者模拟测试 消息处理生产者发送消息消费者处理消息自定义序列化器 主页传送门&#xff1a;&#x1f4c0; 传送 准备工作 Spring boot: &#xff5c; 基于Spring的开源框架&a…

Python UI自动化 —— pytest常用运行参数解析、pytest执行顺序解析

pytest常用Console参数&#xff1a; -v 用于显示每个测试函数的执行结果-q 只显示整体测试结果-s 用于显示测试函数中print()函数输出-x 在第一个错误或失败的测试中立即退出-m 只运行带有装饰器配置的测试用例-k 通过表达式运行指定的测试用例-h 帮助 首先来看什么参数都没加…

【接口技术】实验2:基本I/O实验

实验2 基本I/O实验 一、实验目的 1&#xff1a;掌握I/O端口地址译码电路的工作原理。 2&#xff1a;掌握简单并行接口的工作原理及使用方法。 二、实验内容 1&#xff1a;I/O端口地址译码实验 I/O地址译码电路不仅与地址信号有关&#xff0c;而且与控制信号有关。参加译码…