模糊PID控制C++实现

PID大家都非常熟悉了,这里就不多谈了,模糊控制可以看一下B站的相关视频,比如这个【入门】智能控制 | 20分钟搞定模糊控制

下面的代码来自github,我主要对github的代码进行了一些修改,优化了结果。

main.cpp文件

#include
#include"fuzzy_PID.h"

#define NB -3
#define NM -2
#define NS -1
#define ZO 0
#define PS 1
#define PM 2
#define PB 3

int main()
{
    float target=600;
    float actual=0;
    float u=0;
    int deltaKpMatrix[7][7]={{PB,PB,PM,PM,PS,ZO,ZO},
                             {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 deltaKiMatrix[7][7]={{NB,NB,NM,NM,NS,ZO,ZO},
                             {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 deltaKdMatrix[7][7]={{PS,NS,NB,NB,NB,NM,PS},
                             {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}};
    float e_mf_paras[]={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3};
    float de_mf_paras[]={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3};
    float Kp_mf_paras[]={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3};
    float Ki_mf_paras[]={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3};
    float Kd_mf_paras[]={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3};
    FuzzyPID fuzzypid(1500,650,0.3,0.4,0.2,0.02,0.65,0.005);
    fuzzypid.setMf("trimf",e_mf_paras,"trimf",de_mf_paras,"trimf",Kp_mf_paras,"trimf",Ki_mf_paras,"trimf",Kd_mf_paras);
    fuzzypid.setRuleMatrix(deltaKpMatrix,deltaKiMatrix,deltaKdMatrix);
    cout<

fuzzy_PID.cpp文件

#include"fuzzy_PID.h"
#include

using std::exp;
using std::pow;

FuzzyPID::FuzzyPID(float e_max,float de_max,float kp_max,float ki_max,float kd_max,float Kp0,float Ki0,float Kd0):
target(0),actual(0),emax(e_max),demax(de_max),delta_Kp_max(kp_max),delta_Ki_max(ki_max),delta_Kd_max(kd_max),e_mf_paras(NULL),de_mf_paras(NULL),
Kp_mf_paras(NULL),Ki_mf_paras(NULL),Kd_mf_paras(NULL)
{
   e=target-actual;
   e_pre_1=0;
   e_pre_2=0;
   uu=0;
   de=e-e_pre_1;
   Ke=(N/2)/emax;
   Kde=(N/2)/demax;
   Ku_p=delta_Kp_max/(N/2);
   Ku_i=delta_Ki_max/(N/2);
   Ku_d=delta_Kd_max/(N/2);
   mf_t_e="No type";
   mf_t_de="No type";
   mf_t_Kp="No type";
   mf_t_Ki="No type";
   mf_t_Kd="No type";
   Kp=Kp0;
   Ki=Ki0;
   Kd=Kd0;
   A=Kp+Ki+Kd;
   B=-2*Kd-Kp;
   C=Kd;
}

FuzzyPID::FuzzyPID(float *fuzzyLimit,float *pidInitVal)
{
    target=0;
    actual=0;
    e=0;
    e_pre_1=0;
    e_pre_2=0;
    de=e-e_pre_1;
    emax=fuzzyLimit[0];
    demax=fuzzyLimit[1];
    delta_Kp_max=fuzzyLimit[2];
    delta_Ki_max=fuzzyLimit[3];
    delta_Kd_max=fuzzyLimit[4];
    Ke=(N/2)/emax;
    Kde=(N/2)/demax;
    Ku_p=delta_Kp_max/(N/2);
    Ku_i=delta_Ki_max/(N/2);
    Ku_d=delta_Kd_max/(N/2);
    mf_t_e="No type";
    mf_t_de="No type";
    mf_t_Kp="No type";
    mf_t_Ki="No type";
    mf_t_Kd="No type";
    e_mf_paras=NULL;
    de_mf_paras=NULL;
    Kp_mf_paras=NULL;
    Ki_mf_paras=NULL;
    Kd_mf_paras=NULL;

    Kp=pidInitVal[0];
    Ki=pidInitVal[1];
    Kd=pidInitVal[2];
    A=Kp+Ki+Kd;
    B=-2*Kd-Kp;
    C=Kd;
}

FuzzyPID::~FuzzyPID()
{
  delete [] e_mf_paras;
  delete [] de_mf_paras;
  delete [] Kp_mf_paras;
  delete [] Ki_mf_paras;
  delete [] Kd_mf_paras;
}
//三角隶属度函数
float FuzzyPID::trimf(float x,float a,float b,float c)
{
   float u;
   if(x>=a&&xb&&x=a&&x=b&&x=c&&x=delta_Kp_max)   delta_Kp=delta_Kp_max;
    else if(delta_Kp=delta_Ki_max)   delta_Ki=delta_Ki_max;
    else if(delta_Ki=delta_Kd_max)   delta_Kd=delta_Kd_max;
    else if(delta_Kd=0.95*target)delta_u=0.95*target;
    else if(delta_u#ifndef FUZZY_PID_H_
#define FUZZY_PID_H_
#include
#include
using std::string;
using std::cout;
using std::cin;
using std::endl;
class FuzzyPID
{
public:
    const static int N=7;
private:
    float target;  //系统的控制目标
    float actual;  //采样获得的实际值
    float e;       //误差
    float e_pre_1; //上一次的误差
    float e_pre_2; //上上次的误差
    float de;      //误差的变化率
    float emax;    //误差基本论域上限
    float demax;   //误差变化率基本论域的上限
    float delta_Kp_max;   //delta_kp输出的上限
    float delta_Ki_max;   //delta_ki输出上限
    float delta_Kd_max;   //delta_kd输出上限
    float Ke;      //Ke=n/emax,量化论域为[-3,-2,-1,0,1,2,3]
    float Kde;     //Kde=n/demax,量化论域为[-3,-2,-1,0,1,2,3]
    float Ku_p;    //Ku_p=Kpmax/n,量化论域为[-3,-2,-1,0,1,2,3]
    float Ku_i;    //Ku_i=Kimax/n,量化论域为[-3,-2,-1,0,1,2,3]
    float Ku_d;    //Ku_d=Kdmax/n,量化论域为[-3,-2,-1,0,1,2,3]
    int Kp_rule_matrix[N][N];//Kp模糊规则矩阵
    int Ki_rule_matrix[N][N];//Ki模糊规则矩阵
    int Kd_rule_matrix[N][N];//Kd模糊规则矩阵
    string mf_t_e;       //e的隶属度函数类型
    string mf_t_de;      //de的隶属度函数类型
    string mf_t_Kp;      //kp的隶属度函数类型
    string mf_t_Ki;      //ki的隶属度函数类型
    string mf_t_Kd;      //kd的隶属度函数类型
    float *e_mf_paras;//误差的隶属度函数的参数
    float *de_mf_paras;//误差的偏差隶属度函数的参数
    float *Kp_mf_paras; //kp的隶属度函数的参数
    float *Ki_mf_paras; //ki的隶属度函数的参数
    float *Kd_mf_paras; //kd的隶属度函数的参数
    float Kp;
    float Ki;
    float Kd;
    float A;
    float B;
    float C;
    float uu;
    void showMf(const string & type,float *mf_paras);      //显示隶属度函数的信息
    void setMf_sub(const string & type,float *paras,int n);//设置模糊隶属度函数的子函数
public:
    FuzzyPID(float e_max,float de_max,float kp_max,float ki_max,float kd_max,float Kp0,float Ki0,float Kd0);
    FuzzyPID(float *fuzzyLimit,float *pidInitVal);
    ~FuzzyPID();
    float trimf(float x,float a,float b,float c);          //三角隶属度函数
    float gaussmf(float x,float ave,float sigma);          //正态隶属度函数
    float trapmf(float x,float a,float b,float c,float d); //梯形隶属度函数
    void setMf(const string & mf_type_e,float *e_mf,
               const string & mf_type_de,float *de_mf,
               const string & mf_type_Kp,float *Kp_mf,
               const string & mf_type_Ki,float *Ki_mf,
               const string & mf_type_Kd,float *Kd_mf); //设置模糊隶属度函数的参数
    void setRuleMatrix(int kp_m[N][N],int ki_m[N][N],int kd_m[N][N]);  //设置模糊规则
    float realize(float t,float a);              //实现模糊控制
    void showInfo();                                      //显示该模糊控制器的信息

};

#endif

运行结果用python画图得到:

模糊PID控制C++实现
import matplotlib.pyplot as plt

data_all = []
f = open("test.txt",encoding = "utf-8")
line = f.readline()
while True:
    line = f.readline()
    if line:
        data = line.split(' ')[-1][:-1]
        data_all.append(float(data))
    else:
        break

data_all = data_all[:-1]

x = [i for i in range(len(data_all))]

plt.plot(x, data_all)
plt.xlabel('nums')
plt.ylabel('actual')
plt.show()

可以发现抖动比较明显,应该是隶属函数规则设计的问题,暂时还没有很好的解决办法。

Original: https://www.cnblogs.com/hitwherznchjy/p/16349860.html
Author: 静候佳茵
Title: 模糊PID控制C++实现

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/567909/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球