FuzzyPID

#include <stdio.h>

typedef struct FuzzyPID

{

       int  num_area ; //划分区域个数

    //float e_max;  //误差做大值

    //float e_min;  //误差最小值

    //float ec_max;  //误差变化最大值

    //float ec_min;  //误差变化最小值

    //float kp_max, kp_min;

    float e_membership_values[7] ; //输入e的隶属值

    float ec_membership_values[7] ;//输入de/dt的隶属值

    float kp_menbership_values[7] ;//输出增量kp的隶属值

    float ki_menbership_values[7] ; //输出增量ki的隶属值

    float kd_menbership_values[7] ;  //输出增量kd的隶属值

    float fuzzyoutput_menbership_values[7];

    //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] ;

    float KpgradSums[7];   //输出增量kp总的隶属度

    float KigradSums[7] ;   //输出增量ki总的隶属度

    float KdgradSums[7] ;   //输出增量kd总的隶属度

   

    int  Kp_rule_list[7][7];

    int  Ki_rule_list[7][7];

    int  Kd_rule_list[7][7];

    int  Fuzzy_rule_list[7][7];


 

    //private:

}FuzzyPID;

typedef struct

{

    float e_max ;//误差最大范围

    float e_min ;//误差最小

    float ec_max;//误差的微分范围

    float ec_min;//误差的微分范围

    float kp_max;//p的范围

    float kp_min;

    float ki_max ;//i的范围

    float ki_min;

    float kd_max;//d的范围

    float kd_min;

    float erro;//误差

    float erro_c;//误差的微分

    float erro_pre;//上一次的误差

    float erro_ppre;//上上次的误差

}range;//修改变量

typedef struct

{

    float erro;

    float erro_c;

    float erro_pre;

    float erro_ppre;


 

}Error;

#define NB -3

#define NM - 2

#define NS - 1

#define ZO 0

#define PS 1

#define PM 2

#define PB 3

int  Kp_rule[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[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[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[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} };

float values[7] = { -3,-2,-1,0,1,2,3 }; //输入e的隶属值

void FuzzyPID_Init(FuzzyPID* pid)  //构造函数

{

    int i, j;

    pid->num_area = 8;

    pid->kp = 0;

    pid->ki = 0;

    pid->kd = 0;

    pid->fuzzy_output = 0;

    pid->qdetail_kp = 0;

    pid->qdetail_ki = 0;

    pid->qdetail_kd = 0;

    pid->qfuzzy_output = 0;

    pid->errosum = 0;

    for ( i = 0; i < 7; i++)

    {

        for ( j = 0; j < 7; j++)

        {

            pid->Kp_rule_list[i][j] = Kp_rule[i][j];

            pid->Ki_rule_list[i][j] = Ki_rule[i][j];

            pid->Kd_rule_list[i][j] = Kd_rule[i][j];

            pid->Fuzzy_rule_list[i][j] = Fuzzy_rule[i][j];

        }

    }

    for ( i = 0; i < 7; i++)

    {

        pid->e_membership_values[i] = values[i];

        pid->ec_membership_values[i] = values[i];

        pid->kp_menbership_values[i] = values[i];

        pid->ki_menbership_values[i] = values[i];

        pid->kd_menbership_values[i] = values[i];

        pid->fuzzyoutput_menbership_values[i] = values[i];

        pid->gradSums[i] = 0;

        pid->KpgradSums[i] = 0;

        pid->KigradSums[i] = 0;

        pid->KdgradSums[i] = 0;

    }

}




 

//输入e与de/dt隶属度计算函数///

void Get_grad_membership(FuzzyPID* pid,float erro, float erro_c)

{

    int i;

    //当误差在这个范围

    if (erro > pid->e_membership_values[0] && erro < pid->e_membership_values[6])

    {

        //6个区域

        for ( i = 0; i < pid->num_area - 2; i++)

        {

            //如果误差在区间区域内

            if (erro >= pid->e_membership_values[i] && erro <= pid->e_membership_values[i + 1])

            {

                //e的隶属度

                //PM

                pid->e_gradmembership[0] = -(erro - pid->e_membership_values[i + 1]) / (pid->e_membership_values[i + 1] - pid->e_membership_values[i]);

                //PB

                pid->e_gradmembership[1] = 1 + (erro - pid->e_membership_values[i + 1]) / (pid->e_membership_values[i + 1] - pid->e_membership_values[i]);

                //记录是在哪两个区间内

                pid->e_grad_index[0] = i;

                pid->e_grad_index[1] = i + 1;

                break;

            }

        }

    }

    else

    {

        //如果误差的止小于等于论域的最小值

        if (erro <= pid->e_membership_values[0])

        {

            pid->e_gradmembership[0] = 1;

            pid->e_gradmembership[1] = 0;

            pid->e_grad_index[0] = 0;

            pid->e_grad_index[1] = -1;

        }//超出范围了

        else if (erro >= pid->e_membership_values[6])

        {

            pid->e_gradmembership[0] = 1;

            pid->e_gradmembership[1] = 0;

            pid->e_grad_index[0] = 6;

            pid->e_grad_index[1] = -1;

        }

    }

    //误差的微分

    if (erro_c > pid->ec_membership_values[0] && erro_c < pid->ec_membership_values[6])

    {

        for ( i = 0; i < pid->num_area - 2; i++)

        {

            if (erro_c >= pid->ec_membership_values[i] && erro_c <= pid->ec_membership_values[i + 1])

            {

                pid->ec_gradmembership[0] = -(erro_c - pid->ec_membership_values[i + 1]) / (pid->ec_membership_values[i + 1] - pid->ec_membership_values[i]);

                pid->ec_gradmembership[1] = 1 + (erro_c - pid->ec_membership_values[i + 1]) / (pid->ec_membership_values[i + 1] - pid->ec_membership_values[i]);

                pid->ec_grad_index[0] = i;

                pid->ec_grad_index[1] = i + 1;

                break;

            }

        }

    }

    else

    {

        if (erro_c <= pid->ec_membership_values[0])

        {

            pid->ec_gradmembership[0] = 1;

            pid->ec_gradmembership[1] = 0;

            pid->ec_grad_index[0] = 0;

            pid->ec_grad_index[1] = -1;

        }

        else if (erro_c >= pid->ec_membership_values[6])

        {

            pid->ec_gradmembership[0] = 1;

            pid->ec_gradmembership[1] = 0;

            pid->ec_grad_index[0] = 6;

            pid->ec_grad_index[1] = -1;

        }

    }

}

// //获取输出增量kp, ki, kd的总隶属度 /

void GetSumGrad(FuzzyPID* pid)

{

    int i,j;

    //划分八个区域

    for ( i = 0; i <= pid->num_area - 1; i++)

    {

        pid->KpgradSums[i] = 0;

        pid->KigradSums[i] = 0;

        pid->KdgradSums[i] = 0;

        //把PID的各个隶属值清零

    }

    for ( i = 0; i < 2; i++)//循环两次

    {

        if (pid->e_grad_index[i] == -1)//误差有没有爆表

        {

            continue;

        }

        for ( j = 0; j < 2; j++)//

        {

            if (pid->ec_grad_index[j] != -1)//误差的微分有没有爆表

            {

                int indexKp = pid->Kp_rule_list[pid->e_grad_index[i]][pid->ec_grad_index[j]] + 3;

                int indexKi = pid->Ki_rule_list[pid->e_grad_index[i]][pid->ec_grad_index[j]] + 3;

                int indexKd = pid->Kd_rule_list[pid->e_grad_index[i]][pid->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]];

                pid->KpgradSums[indexKp] = pid->KpgradSums[indexKp] + (pid->e_gradmembership[i] * pid->ec_gradmembership[j]);

                pid->KigradSums[indexKi] = pid->KigradSums[indexKi] + (pid->e_gradmembership[i] * pid->ec_gradmembership[j]);

                pid->KdgradSums[indexKd] = pid->KdgradSums[indexKd] + (pid->e_gradmembership[i] * pid->ec_gradmembership[j]);

            }

            else

            {

                continue;

            }

        }

    }

}

//计算输出增量kp, kd, ki对应论域值//

void GetOUT(FuzzyPID* pid)

{

    int i;

    for ( i = 0; i < pid->num_area - 1; i++)

    {

        pid->qdetail_kp +=pid->kp_menbership_values[i] * pid->KpgradSums[i];

        pid->qdetail_ki += pid->ki_menbership_values[i] * pid->KigradSums[i];

        pid->qdetail_kd += pid->kd_menbership_values[i] * pid->KdgradSums[i];

    }

}

///区间映射函数///

float 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 Inverse_quantization(float maximum, float minimum, float qvalues)

{

    float x = (maximum - minimum) * (qvalues + 3) / 6 + minimum;

    return x;

}

//模糊PID控制实现函数/

float FuzzyPIDcontroller(FuzzyPID* pid, range* rang, Error* error, float Target, float actual)

{

   

    error->erro_ppre = error->erro_pre;

    error->erro_pre = error->erro;

    error->erro = Target - actual;

    error->erro_c = error->erro - error->erro_pre;

    pid->errosum += error->erro;

    //Arear_dipart(e_max, e_min, ec_max, ec_min, kp_max, kp_min,ki_max,ki_min,kd_max,kd_min);

    pid->qerro = Quantization(rang->e_max, rang->e_min, error->erro);//区间映射

    pid->qerro_c = Quantization(rang->ec_max, rang->ec_min, error->erro_c);//区间映射

    //把他们缩小到0123范围内

    Get_grad_membership(pid,pid->qerro, pid->qerro_c);

    //获取输出增量kp, ki, kd的总隶属度

    GetSumGrad(pid);

    //计算输出增量kp, kd, ki对应论域值//

    GetOUT(pid);

    pid->detail_kp = Inverse_quantization(rang->kp_max, rang->kp_min, pid->qdetail_kp);

    pid->detail_ki = Inverse_quantization(rang->ki_max, rang->ki_min, pid->qdetail_ki);

    pid->detail_kd = Inverse_quantization(rang->kd_max, rang->kd_min, pid->qdetail_kd);

    pid->qdetail_kd = 0;

    pid->qdetail_ki = 0;

    pid->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;*/

    pid->kp = pid->kp + pid->detail_kp;

    pid->ki = pid->ki + pid->detail_ki;

    pid->kd  =pid->kd + pid->detail_kd;

    //确定范围

    if (pid->kp < 0)

        pid->kp = 0;

    if (pid->ki < 0)

        pid->ki = 0;

    if (pid->kd < 0)

        pid->kd = 0;

    pid->detail_kp = 0;

    pid->detail_ki = 0;

    pid->detail_kd = 0;

    //增量式PID

    float output = pid->kp * (error->erro - error->erro_pre) + pid->ki * error->erro + pid->kd * (error->erro - 2 * error->erro_pre + error->erro_ppre);

    return output;

}

range rang = { 40,-40,5,-5,100,-100,0.1,-0.1,0.01,-0.01 };

Error error = { 0,0,0,0 };

int main()

{

    FuzzyPID myfuzzypid;

    FuzzyPID_Init(&myfuzzypid);

    float Target =20;//目标值

    float actual = 0;//实际值

    for (int i = 0; i < 100; i++)

    {

        float u;

        u = FuzzyPIDcontroller(&myfuzzypid, &rang, &error, Target, actual);

        actual += u;

        printf("i:%d\tTarget:%f\tActual:%f\t\n",i,Target,actual);

        //std::cout << "i:" << i << "\t" << "Target:" << Target << "\t" << "Actual:" << actual << std::endl;

    }

}



 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT加载安装外围依赖库的翻译文件后翻译失败的现象分析:依赖库以饿汉式的形式暴露单例接口导致该现象的产生

1、前提说明 QtClassLibaryDll是动态库,QtWidgetsApplication4是应用程序。 首先明确:动态库以饿汉式的形式进行单例接口暴露; 然后,应用程序加载动态库的翻译文件并进行全局安装; // ...QTranslator* trans = new QTranslator();//qDebug() << trans->load(&quo…

大模型系列:提示词管理

既然大模型应用的编程范式是面向提示词的编程&#xff0c;需要建立一个全面且结构化的提示词库&#xff0c; 对提示词进行持续优化也是必不可少的&#xff0c;那么如何在大模型应用中更好的管理提示词呢&#xff1f; 1. 提示词回顾 提示词在本质上是向大型语言模型&#xff08…

​Chrome插件:React Developer Tools为React开发调试而生

React Developer Tools 是什么? 它是允许在Chrome和Firefox开发者工具中检查React组件层次结构的扩展插件。 插件源码下载 源码下载地址:GitHub - facebook/react-devtools at v3 下载完成以后执行红框中的代码,下载react-devtools 源码,源码如下图所示: 插件打包 当前n…

【C++】 ——【模板初阶】——基础详解

目录 1. 泛型编程 1.1 泛型编程的概念 1.2 泛型编程的历史与发展 1.3 泛型编程的优势 1.4 泛型编程的挑战 2. 函数模板 2.1 函数模板概念 2.2 函数模板格式 2.3 函数模板的原理 2.4 函数模板的实例化 2.5 模板参数的匹配原则 2.6 函数模板的特化 2.7 函数模板的使…

Linux CentOS 宝塔中禁用php8.2的eval函数详细图文教程

PHP_diseval_extension 这个方法是支持PHP8的, Suhosin禁用eval函数&#xff0c;不支持PHP8 一、安装 cd / git clone https://github.com/mk-j/PHP_diseval_extension.gitcd /PHP_diseval_extension/source/www/server/php/82/bin/phpize ./configure --with-php-config/ww…

美团校招机试 - 小美的平衡矩阵(20240309-T1)

题目来源 美团校招笔试真题_小美的平衡矩阵 题目描述 小美拿到了一个 n * n 的矩阵&#xff0c;其中每个元素是 0 或者 1。 小美认为一个矩形区域是完美的&#xff0c;当且仅当该区域内 0 的数量恰好等于 1 的数量。 现在&#xff0c;小美希望你回答有多少个 i * i 的完美…

C++操作系列(二):VSCode安装和配置C++开发环境

1. VSCode下载 进入VSCode的官网网页&#xff1a;Download Visual Studio Code - Mac, Linux, Windows 下载相应的版本&#xff1a; 2. 安装VSCode 安装到指定位置&#xff1a; 一路下一步&#xff0c;直至安装完成&#xff1a; 3. 安装C插件 3.1. 安装C/C 点击扩展图标&…

linux上git的使用

目录 1.测试是否安装有git 2.下载项目到本地 3.三板斧 1.将代码放在创建的目录中 2.提交改动到本地 3.提交代码到远端 4.注意点 以及补充内容 1.测试是否安装有git 如果输入git --help 会显示下面一大串那么就是已经安装&#xff0c;否则需要自行手动安装 yum install g…

Elasticsearch开启认证|为ES设置账号密码|ES账号密码设置|ES单机开启认证|ES集群开启认证

文章目录 前言单节点模式开启认证生成节点证书修改ES配置文件为内置账号添加密码Kibana修改配置验证 ES集群开启认证验证 前言 ES安装完成并运行&#xff0c;默认情况下是允许任何用户访问的&#xff0c;这样并不安全&#xff0c;可以为ES开启认证&#xff0c;设置账号密码。 …

【Python从入门到进阶】59、Pandas库中Series对象的操作(二)

接上篇《58、Pandas库中Series对象的操作(一)》 上一篇我们讲解了Pandas库中Series对象的基本概念、对象创建和操作&#xff0c;本篇我们来继续学习Series对象的运算、函数应用、时间序列操作&#xff0c;以及Series的案例实践。 一、Series对象的运算 1. 数值型数据的算术运…

ElasticSearch索引架构与存储

关于ES官网的介绍: Elasticsearch provides near real-time search and analytics for all types of data. Whether you have structured or unstructured text, numerical data, or geospatial data, Elasticsearch can efficiently store and index it in a way that support…

详细介绍MySQL的索引(下)

索引的使用 同一条数据在未创建索引的情况下耗时&#xff1a; nick字段是未创建索引的 select * from t_user WHERE nick 邹丽;SHOW PROFILES; 耗时为&#xff1a; user_account字段创建了唯一索引 select * from t_user WHERE user_account 13781945844;SHOW PROFILES;…

基于Vue3 + Typescript 封装 Element-Plus 组件

1. 课程简介 项目地址 git clone https://gitee.com/childe-jia/my-message.git 背景: 该课程是基于Vue3 Typescript Vite构建, 教会大家封装Element-Plus组件 具备能力: 最新的 Vue3 及相关技术组件的设计思想大厂的开发模式/代码规范 技术: Vue3 首次渲染 / diff 算法 …

5-linux文件路径与文件目录系统

目录 ①文件路径 目录跳转 绝对路径与相对路径 ②文件目录系统 目录系统组成 目录命名规则 命令补充 ls命令补充 file filename查看文件类型 less查看文本文件 ①文件路径 目录跳转 pwd:查看当前工作目录。 cd:改变目录。 ls:列出目录内容。 [root########## ~]# …

取证工作:怎样解锁 LUKS2 加密磁盘?

对于 LUKS2 密码进行恢复&#xff0c;Elcomsoft Distributed Password Recovery &#xff08;简称 EDPR&#xff09; 软件可以构建高性能集群&#xff0c;以更快地破解密码。EDPR 软件提供零开销的可扩展性&#xff0c;并支持 GPU 加速&#xff0c;以加快恢复速度。EDPR 可帮助…

下属无执行力,领导无能为力?用好这3大法则,打造一流行动力

下属无执行力&#xff0c;领导无能为力&#xff1f;用好这3大法则&#xff0c;打造一流行动力 第一个&#xff1a;漏斗法则 在沟通这个领域&#xff0c;有一个漏斗法则&#xff0c;意思就是指&#xff1a;如果你脑袋里面想表达的是100%&#xff0c;那你说出口的会只有80%&…

开发板以电脑为跳板连接互联网

标题 开发板以电脑为跳板连接互联网网络共享方式桥接方式 开发板以电脑为跳板连接互联网 分享下用网线直连电脑的开发板如何以电脑为跳板连接互联网的两个方法。 网络共享方式桥接方式 补充下&#xff0c;我的电脑连接的是无线网络&#xff0c;开发板和电脑是用网线进行连接的…

AI奏响未来乐章:音乐界的革命性变革

AI在创造还是毁掉音乐 引言 随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;正在逐渐渗透到我们生活的每一个角落&#xff0c;音乐领域也不例外。AI技术的引入&#xff0c;不仅为音乐创作、教育、体验带来了革命性的变革&#xff0c;更为整个音乐产业注入了…

昇思25天学习打卡营第7天|模型训练

模型训练 模型训练一般分为四个步骤&#xff1a; 构建数据集。定义神经网络模型。定义超参、损失函数及优化器。输入数据集进行训练与评估。 前面几天依次学习了前面几个步骤的操作&#xff0c;今天继续学习模型训练。 数据集和神经网络模型这个前面已经有详细的介绍。准确…

生成式AI如何赋能教育?商汤发布《2024生成式AI赋能教育未来》白皮书

生成式AI正在各个行业中展现出巨大的应用前景。在关系国计民生的教育行业&#xff0c;生成式AI能够催生哪些创新模式&#xff1f; 6月28日&#xff0c;商汤科技受邀参加2024中国AIGC应用与发展峰会&#xff0c;并在会上发布《2024生成式AI赋能教育未来》白皮书&#xff0c;提出…
最新文章