【智能车】模糊PID控制原理详解与代码实现

这篇具有很好参考价值的文章主要介绍了【智能车】模糊PID控制原理详解与代码实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

模糊PID控制


本文主要由三部分构成:模糊PID控制器的原理,模糊PID控制器C++的实现与测试。

一. 模糊PID原理

模糊PID控制流程如下图所示,把目标值 Xtarget 与输出值 Xout 的误差 ee 的变化率 de/dt 作为模糊控制器的输入,模糊控制器先对输入进行模糊化处理,接着进行模糊推理,最后把模糊推理的结果进行去模糊处理输出PID控制器的三个参数 kp, ki, kd,从而达到对PID控制器参数自适应整定的效果。
模糊pid,智能车,c语言,c++

根据以上的描述可知,模糊控制器主要由去模糊化,模糊推理以及去模糊三部分组成。以下将对三部分进行详细讲解。

1.1 模糊化

要实现模糊化首先需要对模糊化进行初始化,初始化包括论域的确定以及隶属度函数的确定。

1.1.1 论域

论域可以说是一个人为确定的范围,由于输入 e, de/dt,输出 kp, ki, kd 的范围各不相同,把输入映射到论域上更好统一处理。确定论域的范围后,需要对论域进行模糊分类,模糊分类即对论域进行划分。假设论域的范围为 [-3,3],把论域平均分为 5 等份,即 [-3, -2], [-2, -1], [-1, 0], [0, 1], [1, 2], [2, 3]。接着把每个端点进行等级划分,依次为: -3—>NB(负大), -2—>NM(负中), -1---->NS(负小), 0—>ZO(零), 1---->PS(正小), 2---->PM(正中), 3---->PB(正大)。假设输入e的范围为 [-10, 10],此刻 e 的值为 8,通过映射后的值为 2.4,2.4 在 [2, 3] 区间,则该点在正中与正大之间。示意图如下:

模糊pid,智能车,c语言,c++

1.1.2 隶属度函数的确定。

常见的隶属度函数有三角形隶属度函数,梯形隶属度函数,抛物线型隶属度函数。以最简单的三角性隶属度函数为例,形状如下图所示:

模糊pid,智能车,c语言,c++

由上图可知,隶属度函数的值域为 [0, 1]。若输入e经过映射后的值为 2.4,那么对应下图红线与绿线的值分别为 0.6,0.4, 这两个就是隶属度,表示该输入属于 PM 的概率为0.6,而属于 PB 的概率为0.4。所以隶属度也为概率。

模糊pid,智能车,c语言,c++

由上述论域和隶属度函数的讲解,可总结出模糊化的过程:区间映射,根据隶属度函数计算隶属度,流程图如下:

模糊pid,智能车,c语言,c++

1.2 模糊推理

模糊推理,即根据 e 与 de/dt 的隶属度进行查表得到输出的大小程度,即 NB,NS 等。所以模糊推理的核心工作是建立推理表。其中模糊PID常用的推理表如下图所示:

模糊pid,智能车,c语言,c++

模糊pid,智能车,c语言,c++
模糊pid,智能车,c语言,c++

以下以一个例子说明规则表的使用方法。

假设此刻的输入 e 为8,de/dt 为-12,而e的范围为[-10,10],de/dt 的范围为[-20,20]。则通过模糊化得到 e 的隶属度为0.6(PM)与0.4(PB),de/dt 的隶属度为0.8(NM)与0.2(NS),然后,对 e 与 de/dt 的隶属度进行两两组合,并进行查表,得到下表的关系:

模糊pid,智能车,c语言,c++

接着,计算各输出 Kp, Ki, Kd 的隶属度。

以Kp为例:

模糊pid,智能车,c语言,c++

同理 Ki, Kd 也计算隶属度。

最后进行个输出的隶属度进行整合,例如 Kp, 由上面计算可知,Kp 的隶属度为 0.8(ZO),0.12(NS),0.08(NM)。

1.3 去模糊

去模糊是根据模糊推理得到的各输出的隶属度算出输出在论域中的哪个值,然后根据区间映射关系,得到输出。

1.3.1 计算输出在论域中的值

以上面的例子进行阐述计算的过程。由上面可知,Kp 的隶属度为0.8(ZO),0.12(NS),0.08(NM), 而在论域讲解时,已经将 ZO 的值定为0,NS 的值定为-1,NM 的值定为-2。那么 Kp 的期望为:

模糊pid,智能车,c语言,c++

把期望作为 Kp 在论域的值,在确定 Kp 的范围后,根据区间映射公式,可得出 Kp 的输出值。

以上为模糊控制器的流程。

值得注意的是,输出的 Kp, Ki, Kd 为增量。在初始化时要确定输入与输出的范围(区间),用于进行区间映射。

2.1 C++实现模糊PID控制器

该本版隶属度函数为固定三角形隶属度函数论域固定为[-3, 3]

FuzzyPID.h

#ifndef FuzzyPID_H
#define FuzzyPID_H
class FuzzyPID
{
public:
    FuzzyPID();
    ~FuzzyPID();
    void Get_grad_membership(float erro, float erro_c);
    float Quantization(float maximum, float minimum, float x);
    float Inverse_quantization(float maximum, float minimum, float qvalues);
    void GetSumGrad();
    void GetOUT();
    float FuzzyPIDcontroller(float e_max, float e_min, float ec_max, float ec_min, float kp_max, float kp_min, float erro, float erro_c, float ki_max, float ki_min,float kd_max, float kd_min,float erro_pre, float errp_ppre);
    const int  num_area = 8; //划分区域个数
    //float e_max;  //误差做大值
    //float e_min;  //误差最小值
    //float ec_max;  //误差变化最大值
    //float ec_min;  //误差变化最小值
    //float kp_max, kp_min;
    float e_membership_values[7] = {-3,-2,-1,0,1,2,3}; //输入e的隶属值
    float ec_membership_values[7] = { -3,-2,-1,0,1,2,3 };//输入de/dt的隶属值
    float kp_menbership_values[7] = { -3,-2,-1,0,1,2,3 };//输出增量kp的隶属值
    float ki_menbership_values[7] = { -3,-2,-1,0,1,2,3 }; //输出增量ki的隶属值
    float kd_menbership_values[7] = { -3,-2,-1,0,1,2,3 };  //输出增量kd的隶属值
    float fuzzyoutput_menbership_values[7] = { -3,-2,-1,0,1,2,3 };

    //int menbership_values[7] = {-3,-};
    float kp;                       //PID参数kp
    float ki;                       //PID参数ki
    float kd;                       //PID参数kd
    float qdetail_kp;               //增量kp对应论域中的值
    float qdetail_ki;               //增量ki对应论域中的值
    float qdetail_kd;               //增量kd对应论域中的值
    float qfuzzy_output;  
    float detail_kp;                //输出增量kp
    float detail_ki;                //输出增量ki
    float detail_kd;                //输出增量kd
    float fuzzy_output;
    float qerro;                    //输入e对应论域中的值
    float qerro_c;                  //输入de/dt对应论域中的值
    float errosum;                  
    float e_gradmembership[2];      //输入e的隶属度
    float ec_gradmembership[2];     //输入de/dt的隶属度
    int e_grad_index[2];            //输入e隶属度在规则表的索引
    int ec_grad_index[2];           //输入de/dt隶属度在规则表的索引
    float gradSums[7] = {0,0,0,0,0,0,0};
    float KpgradSums[7] = { 0,0,0,0,0,0,0 };   //输出增量kp总的隶属度
    float KigradSums[7] = { 0,0,0,0,0,0,0 };   //输出增量ki总的隶属度
    float KdgradSums[7] = { 0,0,0,0,0,0,0 };   //输出增量kd总的隶属度
    int NB = -3, NM = -2, NS = -1, ZO = 0, PS = 1, PM = 2, PB = 3; //论域隶属值

    int  Kp_rule_list[7][7] = { {PB,PB,PM,PM,PS,ZO,ZO},     //kp规则表
                                {PB,PB,PM,PS,PS,ZO,NS},
                                {PM,PM,PM,PS,ZO,NS,NS},
                                {PM,PM,PS,ZO,NS,NM,NM},
                                {PS,PS,ZO,NS,NS,NM,NM},
                                {PS,ZO,NS,NM,NM,NM,NB},
                                {ZO,ZO,NM,NM,NM,NB,NB} };

    int  Ki_rule_list[7][7] = { {NB,NB,NM,NM,NS,ZO,ZO},     //ki规则表
                                {NB,NB,NM,NS,NS,ZO,ZO},
                                {NB,NM,NS,NS,ZO,PS,PS},
                                {NM,NM,NS,ZO,PS,PM,PM},
                                {NM,NS,ZO,PS,PS,PM,PB},
                                {ZO,ZO,PS,PS,PM,PB,PB},
                                {ZO,ZO,PS,PM,PM,PB,PB} };

    int  Kd_rule_list[7][7] = { {PS,NS,NB,NB,NB,NM,PS},    //kd规则表
                                {PS,NS,NB,NM,NM,NS,ZO},
                                {ZO,NS,NM,NM,NS,NS,ZO},
                                {ZO,NS,NS,NS,NS,NS,ZO},
                                {ZO,ZO,ZO,ZO,ZO,ZO,ZO},
                                {PB,NS,PS,PS,PS,PS,PB},
                                {PB,PM,PM,PM,PS,PS,PB} };

    int  Fuzzy_rule_list[7][7] = { {PB,PB,PB,PB,PM,ZO,ZO},  
                                   {PB,PB,PB,PM,PM,ZO,ZO},
                                   {PB,PM,PM,PS,ZO,NS,NM},
                                   {PM,PM,PS,ZO,NS,NM,NM},
                                   {PS,PS,ZO,NM,NM,NM,NB},
                                   {ZO,ZO,ZO,NM,NB,NB,NB},
                                   {ZO,NS,NB,NB,NB,NB,NB}};


//private:

};
#endif

FuzzyPID.cpp

#include "FuzzyPID.h"
FuzzyPID::FuzzyPID()  //构造函数
{
    kp = 0;
    ki = 0;
    kd = 0;
    fuzzy_output = 0;
    qdetail_kp = 0;
    qdetail_ki = 0;
    qdetail_kd = 0;
    qfuzzy_output = 0;
    errosum = 0;
}

FuzzyPID::~FuzzyPID()//析构函数
{
}

//输入e与de/dt隶属度计算函数///
void FuzzyPID::Get_grad_membership(float erro,float erro_c)  
{
    if (erro > e_membership_values[0] && erro < e_membership_values[6])
    {
        for (int i = 0; i < num_area - 2; i++)
        {
            if (erro >= e_membership_values[i] && erro <= e_membership_values[i + 1])
            {
                e_gradmembership[0] = -(erro - e_membership_values[i + 1]) / (e_membership_values[i + 1] - e_membership_values[i]);
                e_gradmembership[1] = 1+(erro - e_membership_values[i + 1]) / (e_membership_values[i + 1] - e_membership_values[i]);
                e_grad_index[0] = i;
                e_grad_index[1] = i + 1;
                break;
            }
        }
    }
    else
    {
        if (erro <= e_membership_values[0])
        {
            e_gradmembership[0] = 1;
            e_gradmembership[1] = 0;
            e_grad_index[0] = 0;
            e_grad_index[1] = -1;
        }
        else if (erro >= e_membership_values[6])
        {
            e_gradmembership[0] = 1;
            e_gradmembership[1] = 0;
            e_grad_index[0] = 6;
            e_grad_index[1] = -1;
        }
    }

    if (erro_c > ec_membership_values[0] && erro_c < ec_membership_values[6])
    {
        for (int i = 0; i < num_area - 2; i++)
        {
            if (erro_c >= ec_membership_values[i] && erro_c <= ec_membership_values[i + 1])
            {
                ec_gradmembership[0] = -(erro_c - ec_membership_values[i + 1]) / (ec_membership_values[i + 1] - ec_membership_values[i]);
                ec_gradmembership[1] = 1 + (erro_c - ec_membership_values[i + 1]) / (ec_membership_values[i + 1] - ec_membership_values[i]);
                ec_grad_index[0] = i;
                ec_grad_index[1] = i + 1;
                break;
            }
        }
    }
    else
    {
        if (erro_c <= ec_membership_values[0])
        {
            ec_gradmembership[0] = 1;
            ec_gradmembership[1] = 0;
            ec_grad_index[0] = 0;
            ec_grad_index[1] = -1;
        }
        else if (erro_c >= ec_membership_values[6])
        {
            ec_gradmembership[0] = 1;
            ec_gradmembership[1] = 0;
            ec_grad_index[0] = 6;
            ec_grad_index[1] = -1;
        }
    }

}

/获取输出增量kp,ki,kd的总隶属度/
void FuzzyPID::GetSumGrad()
{
    for (int i = 0; i <= num_area - 1; i++)
    {
        KpgradSums[i] = 0;
        KigradSums[i] = 0;
    KdgradSums[i] = 0;

    }
  for (int i=0;i<2;i++)
  {
      if (e_grad_index[i] == -1)
      {
       continue;
      }
      for (int j = 0; j < 2; j++)
      {
          if (ec_grad_index[j] != -1)
          {
              int indexKp = Kp_rule_list[e_grad_index[i]][ec_grad_index[j]] + 3;
              int indexKi = Ki_rule_list[e_grad_index[i]][ec_grad_index[j]] + 3;
              int indexKd = Kd_rule_list[e_grad_index[i]][ec_grad_index[j]] + 3;
              //gradSums[index] = gradSums[index] + (e_gradmembership[i] * ec_gradmembership[j])* Kp_rule_list[e_grad_index[i]][ec_grad_index[j]];
              KpgradSums[indexKp]= KpgradSums[indexKp] + (e_gradmembership[i] * ec_gradmembership[j]);
              KigradSums[indexKi] = KigradSums[indexKi] + (e_gradmembership[i] * ec_gradmembership[j]);
              KdgradSums[indexKd] = KdgradSums[indexKd] + (e_gradmembership[i] * ec_gradmembership[j]);
          }
          else
          {
            continue;
          }

      }
  }

}

计算输出增量kp,kd,ki对应论域值//
void FuzzyPID::GetOUT()
{
    for (int i = 0; i < num_area - 1; i++)
    {
        qdetail_kp += kp_menbership_values[i] * KpgradSums[i];
        qdetail_ki += ki_menbership_values[i] * KigradSums[i];
        qdetail_kd+= kd_menbership_values[i] * KdgradSums[i];
    }
}

//模糊PID控制实现函数/
float FuzzyPID::FuzzyPIDcontroller(float e_max, float e_min, float ec_max, float ec_min, float kp_max, float kp_min, float erro, float erro_c,float ki_max,float ki_min,float kd_max,float kd_min,float erro_pre,float errp_ppre)
{
    errosum += erro;
    //Arear_dipart(e_max, e_min, ec_max, ec_min, kp_max, kp_min,ki_max,ki_min,kd_max,kd_min);
    qerro = Quantization(e_max, e_min, erro);
    qerro_c = Quantization(ec_max, ec_min, erro_c);
    Get_grad_membership(qerro, qerro_c);
    GetSumGrad();
    GetOUT();
    detail_kp = Inverse_quantization(kp_max, kp_min, qdetail_kp);
    detail_ki = Inverse_quantization(ki_max, ki_min, qdetail_ki);
    detail_kd = Inverse_quantization(kd_max, kd_min, qdetail_kd);
    qdetail_kd = 0;
    qdetail_ki = 0;
    qdetail_kp = 0;
    /*if (qdetail_kp >= kp_max)
        qdetail_kp = kp_max;
    else if (qdetail_kp <= kp_min)
        qdetail_kp = kp_min;
    if (qdetail_ki >= ki_max)
        qdetail_ki = ki_max;
    else if (qdetail_ki <= ki_min)
        qdetail_ki = ki_min;
    if (qdetail_kd >= kd_max)
        qdetail_kd = kd_max;
    else if (qdetail_kd <= kd_min)
        qdetail_kd = kd_min;*/
    kp = kp + detail_kp;
    ki = ki + detail_ki;
    kd = kd + detail_kd;
    if (kp < 0)
        kp = 0;
    if (ki < 0)
        ki = 0;
    if (kd < 0)
        kd = 0;
    detail_kp = 0;
  detail_ki=0;
  detail_kd=0;
  float output = kp*(erro - erro_pre) + ki * erro + kd * (erro - 2 * erro_pre + errp_ppre);
    return output;
}

///区间映射函数///
float FuzzyPID::Quantization(float maximum,float minimum,float x)
{
    float qvalues= 6.0 *(x-minimum)/(maximum - minimum)-3;
    //float qvalues=6.0*()
    return qvalues;
   
    //qvalues[1] = 3.0 * ecerro / (maximum - minimum);
}

//反区间映射函数
float FuzzyPID::Inverse_quantization(float maximum, float minimum, float qvalues)
{
    float x = (maximum - minimum) *(qvalues + 3)/6 + minimum;
    return x;
}
测试模糊PID控制器:
#include <iostream>
#include "FuzzyPID.h"

int main()
{
    FuzzyPID myfuzzypid;
    float Target = 600;
    float actual = 0;
    float e_max =1000;
    float e_min = -1000;
    float ec_max = 800;
    float ec_min = -800;
    float kp_max =100;
    float kp_min = -100;
    float ki_max = 0.1;
    float ki_min = -0.1;
    float kd_max = 0.01;
    float kd_min = -0.01;
    float erro;
    float erro_c;
    float erro_pre = 0;
    float erro_ppre = 0;
    erro =Target - actual;
    erro_c = erro - erro_pre;
    for (int i = 0; i < 100; i++)
    {
        float u;
        u = myfuzzypid.FuzzyPIDcontroller(e_max, e_min, ec_max, ec_min, kp_max, kp_min, erro, \
                                          erro_c,ki_max,ki_min,kd_max,kd_min,erro_pre,erro_ppre);
        actual +=u;
        erro_ppre = erro_pre;
        erro_pre = erro;
        erro = Target - actual;
        erro_c= erro - erro_pre;
        std::cout << "i:" << i << "\t" << "Target:" << Target << "\t" << "Actual:" << actual  << std::endl;
    }
}

运行结果

模糊pid,智能车,c语言,c++

本文主要转载了模糊控制原理部分以及代码例程,为了方便管理与收藏发布到CSDN。

原文地址:https://www.codenong.com/cs105632129/文章来源地址https://www.toymoban.com/news/detail-786625.html

到了这里,关于【智能车】模糊PID控制原理详解与代码实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【物联网】C语言实现PID算法:原理、例子和代码详解

    PID(Proportional-Integral-Derivative)是一种常用的控制算法,广泛应用于工业控制系统中。本文将详细介绍PID算法的原理,并给出一个具体的例子和相应的C语言代码实现。 PID算法通过不断调整输出值,使得系统的实际值逐渐接近期望值。它由三个部分组成: 比例(P)、积分(

    2024年02月12日
    浏览(41)
  • 智能算法实现PID智能车控制系统

    PID控制是自动控制领域中产生最早,应用最广的一种控制方法。本文以论述PID参数先进整定方法开始,介绍了近几年得到的最新研究成果。接下来,从PID控制的结构形式实际控制工程需求和实现条件分析了PD控制的独特优点和理论依据。在众多的PID调整方法中,本文选择了内

    2024年02月08日
    浏览(43)
  • 【抗扰PID控制】干扰抑制PID控制器研究(Matlab代码实现)

    💥💥💞💞 欢迎来到本博客 ❤️❤️💥💥 🏆博主优势: 🌞🌞🌞 博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️ 座右铭: 行百里者,半于九十。 📋📋📋 本文目录如下: 🎁🎁🎁 目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码、Simulink、文

    2024年02月11日
    浏览(59)
  • 双容水箱液位模糊PID控制系统设计与仿真(Matlab/Simulink)

    前些天发现了十分不错的人工智能学习网站,通俗易懂,风趣幽默,没有广告,分享给大家,大家可以自行看看。(点击跳转人工智能学习资料) 微信公众号:创享日记 发送:双容模糊 获取完整无水印报告+仿真源文件+相关文献 双容水箱液位控制系统的设计与仿真 1、基于

    2024年02月07日
    浏览(49)
  • tb6612电机驱动软件开发(代码pid实现,调试,控制实现)

    代码工程 https://download.csdn.net/download/weixin_52849254/87879043?spm=1001.2014.3001.5501 这段代码是一个PID算法的实现,用于控制电机的位置和速度。代码中包含了以下主要内容: 定义了全局变量,包括四个PID结构体变量,分别用于左电机的位置控制、左电机的速度控制、右电机的速度控

    2024年02月08日
    浏览(50)
  • 超维空间S2无人机使用说明书——55、代码详解:基础PID算法控制无人机的跟随代码详解

    PID,即比例 Proportion、积分 Integral 和微分 Derivative 三个单词的缩写;比例积分微分控制,简称PID控制。 简单讲,根据给定值和实际输出值构成控制偏差,将偏差按比例、积分和微分通过线性组合构成控制量,对被控对象进行控制。 常规 PID 控制器作为一种线性控制器。 步骤

    2024年01月21日
    浏览(59)
  • 增强型PID-自适应-前馈-神经网络控制研究(Matlab代码实现)

    💥💥💞💞 欢迎来到本博客 ❤️❤️💥💥 🏆博主优势: 🌞🌞🌞 博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️ 座右铭: 行百里者,半于九十。 📋📋📋 本文目录如下: 🎁🎁🎁 目录 💥1 概述 📚2 运行结果 2.1 RBFNN_Optimized_hideen_node_20 ​2.2 RBFNN_Lat

    2024年02月01日
    浏览(50)
  • 【PID控制原理及其算法】

    本文以自己的学习过程总结而来,将自己的经验写出来以供大家一起学习,如有错误请多指教 PID就是比例、积分、微分,PID算法可以说是在自动控制原理中比较经典的一套算法,在现实生活中应用比较广泛。 常规的模拟 PID 控制系统原理框图如下图所示: 那么使用PID的目的

    2023年04月24日
    浏览(30)
  • 智能车PID控制详细介绍(普通PID、串级PID、改进PID)——适用于四轮车、三轮车、平衡车

    声明:该文是本人原创,后续将参与智能车相关书籍的写作,为了防止侵权只能先发图片版还请谅解,如有问题,敬请指出,欢迎讨论~~~~ 1 舵机组成及其工作原理 2 舵机PID控制策略 1 直流电机调速系统组成及其工作原理 2 电机PID控制策略 一、四轮电机控制 二、两轮平衡车与

    2023年04月23日
    浏览(42)
  • 麦克纳姆轮PID控制原理

    目录 前言 一、什么是麦克纳姆轮 二、运动原理 ​ 三、pid控制  一、什么是pid?  二、什么是串级PID? 三、麦克娜姆轮的控制思想 总结 目前很多大学生比赛里面经常都会出现麦克娜姆轮,并且麦克娜姆轮在工业上也应用挺广泛,例如物流搬小车。下面是我玩麦克娜姆轮的

    2024年02月02日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包