PID算法详解及实例分析

2023-05-16

1.PID算法入门

PID算法算是控制领域最经典,最重要,也是最实用的算法了。所谓的PID,指的是proportion,integration,differentiation,比例,积分,微分。
因此,PID是结合了比例积分微分三个模块于一身的控制算法。

先看公式:
u ( t ) = K p ( e ( t ) + 1 T i ∫ 0 t e ( t ) d t + T d d e ( t ) d t ) u(t) = K_p\left(e(t) + \frac{1}{T_i} \int_{0}^{t}e(t)dt + T_d \frac{de(t)}{dt}\right) u(t)=Kp(e(t)+Ti10te(t)dt+Tddtde(t))
如果公式看不懂,没关系,我们先往后面走,回头再分析公式。

2.通过实例对PID进行理解

为了更好了解PID算法,我们选取一个例子进行分析,这个例子在很多地方被使用,我们也选过来作为例子进行分析。

小明现在有一个任务:有个水桶,水桶的水位高度需要时刻保持1m,目前水桶的水是0.2m,小命采用比例的方式加水(即P),即每次测量与1m 的误差,并加入与误差成比例的水量。

K p = 0.5 K_p = 0.5 Kp=0.5
第一次的误差:1-0.2=0.8,于是加入的水为0.50.8=0.4,此时桶内水0.6。
第二次的误差:1-0.6=0.4,于是加入的水为0.5
0.6=0.3,此时桶内水0.9。
第三次的误差:1-0.9=0.1,于是加入的水为0.5*0.1=0.05,此时桶内水0.95。
以此类推,不断加下去,通过P控制就可以将水加满到1,完美!

3.积分环节

上面的比例环节,貌似就可以解决问题。但是实际中没有这么理想的情况,比如水桶有个洞,每次加水都会流出0.1m。这个时候就比较接近真实情况了,比如系统的各种摩擦力,阻力什么的。

如果我们还是用上面的比例控制(P环节)
第一次的误差:1-0.2=0.8,于是加入的水为0.50.8=0.4,此时桶内水0.6-0.1=0.5。
第二次的误差:1-0.5=0.5,于是加入的水为0.5
0.5=0.25,此时桶内水0。5+0.25-0.1=0.65。
第三次的误差:1-0.65=0.35,于是加入的水为0.5*0.35=0.175,此时桶内水0.65+0.175-0.1=0.725。

我们多算几次以后发现,水位最终会在0.8m处稳定。如果反推一下,我们也很好理解:当误差为0.2m时,每次加水量为0.1,漏掉的也是0.1,正好加的等于漏掉的。

这就是系统稳定误差的概念。

关于系统稳态误差,引用胡寿松老爷子自动控制原理一书中的描述:

控制系统的稳态误差,是系统控制准确度的一种度量,通常称为稳态性能。在控制系统设计中,稳态误差是一项重要的技术指标,对于一个实际的控制系统,由于系统结构,输入作用的类型(控制量或扰动量) ,输入函数的形式(阶跃,斜坡或加速度)不同,控制系统的稳态输出不可能在任何情况下与输入量一致,也不可能在任何形式的扰动作用下都能准确地恢复到平衡位置。此外,控制系统中不可避免的存在摩擦,间隙,不灵敏区,零位输出等非线性因素,都会造成附加稳态误差。因此,控制系统的稳态误差是不可避免的,控制系统设计的任务之一,就是尽量减小系统的稳态误差,或者使稳态误差小于某一容许值。显然,只有当系统稳定时,研究稳态误差才有意义。对于不稳定系统而言,根本不存在研究稳态误差的可能性。

为了消除稳态误差,我们的做法就是引入积分项,就是PID中的I,积分控制就是将历史误差累加起来再乘以积分常数,即
1 T i ∫ 0 t e ( t ) d t \frac{1}{T_i} \int_{0}^{t}e(t)dt Ti10te(t)dt

前面的例子,我们还是设置为Kp=0.5,Ki= 0.3。
第一次,误差为0.8, 比例部分 Kp0.8=0.4, 积分部分 Ki(e(1))= 0.24,加入水量u为0.4+0.24=0.64. 最终水位0.2+0.64-0.1= 0.74m
第二次,误差为0.26,比例部分Kp0.26=0.13,积分部分Kp*(e(1)+e(2))= 0.318,加入水量u为 0.13+0.318=0.448.最终水位 0.74+0.448-0.1=1.088m。

如果这样一直下去,最终会到达一个稳定值。

4.微分环节

前面我们已经分析了,积分环节能消除稳态误差,但是积分环境又会带来另外一个问题:积分环节会带来超调量。而且随着Ki值的变大,超调量也会边大。
所谓的超调量,是指峰值超过终止的比例。从直观上来说,超调量对应的对就是波峰位置。波峰越高,超调量越大。

为了消减超调,我们引入微分运算,也就PID中的D。
上面的例子,我们假设Kp=0.5,Ki= 0.5,Kd=0.3。

第一次: 误差为0.8, 比例部分 Kp0.8=0.4, 积分部分 Ki(e(1))= 0.24,微分部分 =0 (因为没加水前水位差就是0.8) 加入水量u为0.4+0.4=0.8. 最终水位0.2+0.8-0.1= 0.9m

第二次: 误差为0.1,比例部分Kp0.1=0.5,积分部分Kp(e(1)+e(2))= 0.45,微分部分为Kd*(e(2)-e(1))加入水量u为 0.5+0.45-0.21=0.29.最终水位 0.9+0.29-0.1=1.09m

最后我们计算发现,引入微分运算以后,超调量比之前有减小。

5.PID各模块小结

比例部分P:
比例环节的作用是对偏差瞬间作出反应。偏差一旦产生控制器立即产生控制作用, 使控制量向减少偏差的方向变化。 控制作用的强弱取决于比例系数Kp, 比例系数Kp越大,控制作用越强, 则过渡过程越快, 控制过程的静态偏差也就越小; 但是Kp越大,也越容易产生振荡, 破坏系统的稳定性。 故而, 比例系数Kp选择必须恰当, 才能过渡时间少, 静差小而又稳定的效果。

积分部分I:
从积分部分的数学表达式可以知道, 只要存在偏差, 则它的控制作用就不断的增加; 只有在偏差e(t)=0时, 它的积分才能是一个常数,控制作用才是一个不会增加的常数。 可见,积分部分可以消除系统的偏差。
积分环节的调节作用虽然会消除静态误差,但也会降低系统的响应速度,增加系统的超调量。积分常数Ti越大,积分的积累作用越弱,这时系统在过渡时不会产生振荡; 但是增大积分常数Ti会减慢静态误差的消除过程,消除偏差所需的时间也较长, 但可以减少超调量,提高系统的稳定性。

微分部分D:
实际的控制系统除了希望消除静态误差外,还要求加快调节过程。在偏差出现的瞬间,或在偏差变化的瞬间, 不但要对偏差量做出立即响应(比例环节的作用), 而且要根据偏差的变化趋势预先给出适当的纠正。为了实现这一作用,可在 PI 控制器的基础上加入微分环节,形成 PID 控制器。
微分环节的作用使阻止偏差的变化。它是根据偏差的变化趋势(变化速度)进行控制。偏差变化的越快,微分控制器的输出就越大,并能在偏差值变大之前进行修正。微分作用的引入, 将有助于减小超调量, 克服振荡, 使系统趋于稳定, 特别对髙阶系统非常有利, 它加快了系统的跟踪速度。但微分的作用对输入信号的噪声很敏感,对那些噪声较大的系统一般不用微分, 或在微分起作用之前先对输入信号进行滤波。

6.系统稳定性判断

前面提到了系统稳定性的问题,顺便我们复习一下系统稳定性判据。
同样来自胡寿松老爷子自动控制原理一书

线性系统稳定的充分必要条件是:闭环系统特征方程的所有跟具有负实部,或者说,闭环传递函数的极点均位于s左半平面。

劳斯-赫尔维茨稳定性判据:
根据稳定的充分必要条件判别线性系统的稳定性,假设线性系统的特征方程为
D ( s ) = a 0 s 0 + a 1 s 1 + a 2 s 2 + ⋯ + a n − 1 s n − 1 = 0 , a 0 > 0 D(s) = a_0s^0 + a_1s^1 + a_2s^2 +\cdots + a_{n-1}s^{n-1} = 0, a_0 > 0 D(s)=a0s0+a1s1+a2s2++an1sn1=0,a0>0

即线性系统稳定的必要条件是,在特征方程中,各项系数均为正数。

7.PID的简单实例实现

假设我们的采样间隔为T,那么在第K个T时刻:
偏差err(K) = rin(K) - rout(K)
积分环节用加和的方式表示, err(1) + err(2) + … + err(K)
微分的环节则用斜率的形式表示, [err(K) - err(K-1)] / T

#include <iostream>

using namespace std;

struct _pid{
    float SetSpeed; //定义设定值
    float ActualSpeed; //定义实际值
    float err; //定义偏差值
    float err_last; //定义上一个偏差值
    float Kp,Ki,Kd; //定义比例、积分、微分系数
    float voltage; //定义电压值(控制执行器的变量)
    float integral; //定义积分值
}pid;

void PID_init(){
    printf("PID_init begin \n");
    pid.SetSpeed=0.0;
    pid.ActualSpeed=0.0;
    pid.err=0.0;
    pid.err_last=0.0;
    pid.voltage=0.0;
    pid.integral=0.0;
    pid.Kp=0.2;
    pid.Ki=0.015;
    pid.Kd=0.2;
    printf("PID_init end \n");
}

float PID_realize(float speed){
    pid.SetSpeed=speed;
    pid.err=pid.SetSpeed-pid.ActualSpeed;
    pid.integral+=pid.err;
    pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
    pid.err_last=pid.err;
    pid.ActualSpeed=pid.voltage*1.0;
    return pid.ActualSpeed;
}

int run_pid(){
    printf("System begin \n");
    PID_init();
    int count=0;
    while(count<1000) {
        float actual_speed=PID_realize(200.0);
        printf("count is: %d, actual_speed is: %f\n", count, actual_speed);
        count++;
    }
    return 0;
}

int main(int argc, char const *argv[])
{
    run_pid();
    return 0;
}

代码的最终输出为

System begin 
PID_init begin 
PID_init end 
count is: 0, actual_speed is: 83.000000
count is: 1, actual_speed is: 11.554998
count is: 2, actual_speed is: 59.559681
count is: 3, actual_speed is: 28.175407
count is: 4, actual_speed is: 52.907417
count is: 5, actual_speed is: 38.944157
...
count is: 996, actual_speed is: 199.999435
count is: 997, actual_speed is: 199.999451
count is: 998, actual_speed is: 199.999466
count is: 999, actual_speed is: 199.999481

上述代码,模拟的就是通过PID算法,将速度最终控制在200的场景。

参考文献

1.https://zhuanlan.zhihu.com/p/74131690
2.https://www.cxyzjd.com/article/weibo1230123/80812211
3.https://zhuanlan.zhihu.com/p/41425508

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PID算法详解及实例分析 的相关文章

  • PX4 gazebo仿真 2023.4.13更新

    前言 想实现px4仿真 xff0c 考虑使用gazebo仿真 去PX4官网看一眼先 xff0c 官网提到后面如果要用ROS xff0c 直接配置ROS就好了 xff0c 不然会不兼容 xff0c 那么就按官网步骤走 官网步骤 结果第一步就失
  • PX4 & gazebo仿真 offboard模式无法起飞解决思路

    前言 我用最新版PX4固件 xff0c offboard模式飞机无法起飞 xff0c 网上有一种说法是固件版本的问题 xff0c 让用旧一点的版本 添加链接描述 这个链接描述的情况和我的一模一样 xff0c 所以我肯定是按这个方法尝试的 旧
  • 数字图传VS模拟图传 图传技术知识 2023.3.6更新

    引言 在研究无人机小半年了 xff0c 多次听到数字图传和模拟图传字眼 xff0c 一直都是一知半解 xff0c 这次整体了解一下并加以 整理 数字图传 数字图传 xff1a 指数字化的图像信号经信源编码和信道编码 xff0c 通过数字信道
  • 069-线性系统的可控性和可观测性

    对一个线性系统 xff0c 需要判定其可控性或者可观测性 xff0c 才能对其进行求解 或者说的狭义一点 xff0c 在一个卡尔曼滤波模型中 xff0c 只有判定了其可控性 xff0c 才能知晓状态向量X中多少个状态是可观测的 比如X中原有
  • 滴水石穿

    不积跬步 xff0c 无以至千里 xff1b 不积小流 xff0c 无以成江海 1 hashcode相等两个类一定相等吗 equals呢 相反呢 hashcode相等 xff0c 两个类不一定相等 xff1b equals相等 xff0c
  • C++编程——友元

    文章目录 1 友元的概念2 友元的三种实现2 1 全局函数做友元2 2 类做友元2 3 成员函数做友元 1 友元的概念 友元目的是让一个函数或者类访问另一个类中的私有成员 有一个非常生动的例子 xff0c 就是家中会有客厅和卧室 xff0c
  • C++编程——多态

    文章目录 1 多态的基本概念1 1 函数地址早绑定1 2 地址晚绑定 2 多态的原理3 多态的优点与案例3 1 多态的优点3 2 计算器实现案例 4 纯虚函数与抽象类5 虚析构与纯虚析构5 1 虚析构实现5 2 纯虚析构实现 多态的知识结构
  • 自动驾驶常用数据集KITTI使用指南之一——图像雷达数据融合

    对于自动驾驶环境感知算法的初学者而言 xff0c 一辆搭载各类传感器的自动驾驶汽车或者数据采集平台并没有那么重要 xff0c 甚至 xff0c 由于国外早期自动驾驶研究学者的严谨态度 xff0c 一些公开的数据集比自己采集的数据集在同步性
  • 笔试题

    杭州公交云笔试题 输入一个字符串用逗号隔开 xff0c 找出其中最大的连续递增个数 例如 xff1a 1 xff0c 2 xff0c 3 xff0c 1 xff0c 1 xff0c 1 返回3 import java util public
  • C++STL迭代器

    迭代器 1 迭代器 xff1a 类中类 xff0c 通过运算符的重载 xff0c 用类中类的对象遍历容器 2 迭代器分类 xff1a xff08 1 xff09 正向迭代器 xff1a iterator xff08 begin end xf
  • Dockerfile详细解析(四)——环境变量

    环境变量 xff08 Environment replacement xff09 环境变量 xff08 使用 ENV 表达式声明 xff09 也可以被用在某些确定的指令中作为变量被Dockerfile解释出来 Escapes 也被处理为类似
  • STM32 FreeRTOS系列教程(一)FreeRTOS简介

    参考资料 xff1a 正点原子STM32F4 FreeRTOS开发手册 V1 1 野火FreeRTOS 内核实现与应用开发实战 基于STM32 学习RTOS的意义 当我们进入嵌入式这个领域的时候 xff0c 往往首先接触的都是单片机编程 x
  • 关于句柄表的一些文章

    文章链接 1 gt Windows内核情景分析 3 4 1 Windows 进程的句柄表 2 gt Windows 句柄表格式 3 gt Windows句柄表分配算法分析 4 gt 浅谈Windows句柄表 5 gt 句柄啊 3层表啊 Ex
  • 一天实现ros环境搭建和yolov3tiny算法系列(一)之WIN10+Ubuntu20.04的双系统实现

    这几天因为参加无人机比赛 xff0c 我负责算法部分 xff0c 被搭建环境折磨的头都要秃了 xff0c 写这个文章 xff0c 只是想让大家只要按照步骤 xff0c 能够在最短的时间内搭建起环境 xff0c 愿天下没有再被搭建ros 43
  • 容器的老祖宗LXC和Docker的关系

    一 什么是LXC xff1f LXC xff08 Linux Container的缩写 xff09 是一个基于Linux内核的容器虚拟化技术 xff0c 它提供了一种轻量级 快速 简便的方式来创建和管理系统容器 与传统虚拟化技术不同 xff
  • ROS系列教程一:工作空间及功能包创建

    前言 分享一下ROS开发的基础教程 xff0c 全部自己手敲 xff0c 希望能帮到正在学习的你 ROS在WIKI上也有教程 xff0c 个人觉得太过臃肿 xff0c 可以简化点 xff0c 毕竟大家都赶着投胎 xff0c 哈哈哈哈哈 一
  • ROS系列教程二:自定义消息类型话题的发布及订阅

    个人学习记录 本节将结合自定义消息类型 xff08 msg xff09 来介绍一下怎么发布话题消息及订阅话题消息 xff0c 可以让大家更深刻地理解 一 功能包创建 进入上节课创建的my workspace工作目录下的src文件夹 xff0
  • 使用PX4FLOW的pixhawk悬停模式疑难杂症(一)驱动安装以及固件烧写

    最近博主在准备2021电赛的无人机赛题 xff0c 原定于2021 8 4举办的电赛延期 xff0c 对我来说并不是坏消息 xff0c 因为博主从7 26才把零件和pixhawk板子拿到手 xff0c 延期举办给了博主更多时间捣鼓 博主通过
  • 从安装到连接,教你如何连上Mysql数据库

    目录 前言 如何下载Mysql服务 xff1f 需要使用的软件 xff1f 如何连接数据库 xff1f 前言 这篇文章创作目的是为了帮助大家正确的安装mysql数据库以及软件的 xff0c 我会分为两个部分为大家解答 如何下载Mysql服务
  • 使用PX4FLOW的pixhawk悬停模式疑难杂症(二)BAD OPTFLOW HEALTH

    xff08 接上篇 使用PX4FLOW的pixhawk悬停模式疑难杂症 xff08 一 xff09 驱动安装以及固件烧写 xff09 3 博主遇到的第三个问题是 BAD OPTFLOW HEALTH 这个问题也是我在调试过程中遇到的最难的问

随机推荐