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.mzph.cn/news/863773.shtml

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

相关文章

AI模型的奥运会:谁将在OlympicArena中夺冠?

获取本文论文原文PDF&#xff0c;请在公众号【AI论文解读】留言&#xff1a;论文解读 引言&#xff1a;AI模型的奥林匹克级评测 评估和比较不同AI模型的性能始终是一个核心话题。随着技术的不断进步&#xff0c;这些模型在处理复杂任务的能力上有了显著的提升。为了更精确地衡…

Vue3学习笔记<->创建第一个vue项目(2)

新建一个项目目录 找一个盘新建一个目录&#xff0c;我这里在D盘创建一个vuedemo目录作为项目存放的目录。使用idea打开目录。   单击ieda底部的按钮“Terminal”&#xff0c;打开命令行窗口&#xff0c;如果命令行窗口当前目录不是“vuedemo”&#xff0c;就切换到“vuedem…

基于FastApi框架的后端服务实践案例

去年在做大模型部署和服务开发研究过程中,接触到如何将大模型的对话封装成服务,供任何消费端调用,详见之前的大模型应用文章,之后,为了实现NLP分词和实体识别,也基于tornado框架编写了后端服务,详见那篇文章,最近在利用python在做后端数据处理过程中,发现从响应性能、…

python基础:操作字典

1、遍历整个字典的键-值对 items()方法返回一个键-值对列表&#xff0c;for 循环依次将每个键—值对存储到指定的两个变量中。 使用元组和列表遍历方法遍历字典&#xff1a; user_0 { username: efermi, first: enrico, last: fermi, } for key, value in user_0.items():p…

qt文件如何打包成一个独立的exe文件

QT官方给我们安装好了打包软件&#xff0c;就在你QT安装的位置 把这个在cmd打开C:\Qt\6.7.1\mingw_64\bin\windeployqt6.exe&#xff08;或复制地址&#xff09; 然后把要打包项目的exe复制到新的空文件夹&#xff0c;再复制他的地址 按回车后生成新文件 再下载打包软件&#…

spring04事务

jdbcTemplate使用 <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>6.0.4</version></dependency><dependency><groupId>mysql</group…

东方航空逆向

声明(lianxi a15018601872) 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; …

【AIGC】AnimateAnyone:AI赋予静态照片生命力的魔法

摘要&#xff1a; 在人工智能技术的不断进步中&#xff0c;AnimateAnyone项目以其创新性和易用性脱颖而出&#xff0c;成为GitHub上备受瞩目的AI项目之一。由阿里巴巴智能计算研究院开发的这一技术&#xff0c;允许用户通过提供一张静态照片&#xff0c;快速生成动态角色。本文…

Shiro 简单入门

Apache Shiro 是一个强大且灵活的 Java 安全框架&#xff0c;用于处理身份验证、授权、加密和会话管理等任务。Shiro 的设计目标是提供一种简单而直观的方式来处理安全问题&#xff0c;使开发人员能够轻松集成和管理应用程序的安全性。以下是对 Shiro 的详细讲解&#xff1a; …

Linux实用命令练习

目录 一、常用命令 二、系统命令 三、用户和组 四、权限 五、文件相关命令 六、查找 七、正则表达式 八、输入输出重定向 九、进程控制 十、其他命令 1、远程文件复制&#xff1a;scp 2、locate查找 3、which命令 4、设置或显示环境变量&#xff1a;export 5、修…

学习Symfony框架

学习Symfony框架&#xff0c;一个流行的PHP Web应用框架&#xff0c;你可以遵循以下几个步骤来逐步掌握它&#xff1a; ### 1. 了解Symfony框架 - **研究架构和理念**&#xff1a;了解Symfony的设计原则&#xff0c;如可重用组件、模块化、面向对象编程、以及MVC&#xff08;模…

YOLO-V1

一、YOLO-V1整体思想与网络架构 1.1 YOLO算法整体思路解读 YOLO-V1: 经典的one-stage方法 把检测问题转化成回归问题&#xff0c;一个CNN就搞定了&#xff01; 可以对视频进行实时检测&#xff0c;应用领域非常广&#xff01; 核心思想&#xff1a; 1、预测一张图像中有哪些物…

kafka 集群 Topic 之 Partion 数据写入分布原理设计(六)

kafka 集群 Topic 之 Partion 数据写入分布原理设计(六) 集群中假如有三个节点,分别ip为200,201,202 创建topic 为test,默认分区2,副本2,在写入消息 到topic时,数据就转的过程是什么,则 partition存储数据分布是如何分布的,各个节点数据如何同步 的,isr如何实现的?…

11_电子设计教程基础篇(磁性元件)

文章目录 前言一、电感1、原理2、种类1、制作工艺2、用途 3、参数1、测试条件2、电感量L3、品质因素Q4、直流电阻&#xff08;DCR&#xff09;5、额定电流6、谐振频率SRF&#xff08;Self Resonant Frequency&#xff09;7、磁芯损耗 4、应用与选型 二、共模电感1、原理2、参数…

《昇思25天学习打卡营第15天 | 昇思MindSpore基于MindSpore的红酒分类实验》

15天 本节学了通过MindSpore的完成红酒分类。 1.K近邻算法&#xff08;K-Nearest-Neighbor, KNN&#xff09;是一种用于分类和回归的非参数统计方法&#xff0c;是机器学习最基础的算法之一。 1.1分类问题 1.2回归问题 1.3距离的定义 2.数据处理 2.1 数据准备 2.2 数据读取与处…

动画重定向——当给一个人物模型用别人物的动画时,会遇到人物与动画不匹配问题,怎么解决呢?

每日一句&#xff1a;实践出真知&#xff0c;试错方确信 目录 最开始我想的原因&#xff01; 分析一下动画相关参数 Animator组件参数详解&#xff1a; 人物模型的导入设置参数&#xff1a; Skinned Mesh Renderer组件详解: Skinned Mesh Renderer工作原理 设置Skinned …

npm常用命令使用与事件案例

概述 npm&#xff08;Node Package Manager&#xff09;是一个JavaScript编程语言的包管理器&#xff0c;用于Node.js应用程序。它允许用户安装、共享和管理具有重复使用价值的代码&#xff08;包&#xff09;&#xff0c;这些代码可以是库、工具或应用程序。 npm常用命令详解…

AI大模型的崛起:第四次工业革命的前奏?

在当今这个信息爆炸的时代&#xff0c;人工智能&#xff08;AI&#xff09;大模型的崛起引起了广泛的关注和讨论。有人将其视为第四次工业革命的前奏&#xff0c;然而&#xff0c;这真的可能吗&#xff1f;本文将探讨这一问题&#xff0c;并对中国AI大模型的发展进行简要分析。…

MyBatis第一节

目录 1. 简介2. 配置3. doing3.1 创建一个表3.2 打开IDEA&#xff0c;创建一个maven项目3.3 导入依赖的jar包3.4 创建entity3.5 编写mapper映射文件(编写SQL)3.6 编写主配置文件3.7 编写接口3.8 测试 参考链接 1. 简介 它是一款半自动的ORM持久层框架&#xff0c;具有较高的SQ…

Qt:4.信号和槽

目录 1.信号源、信号和槽&#xff1a; 2.Qt类的继承关系&#xff1a; 3.自定义槽函数&#xff1a; 4.第一种信号和槽的连接的方法&#xff1a; 5.第二种信号和槽的连接的方法&#xff1a; 6.自定义信号&#xff1a; 7.发射信号&#xff1a; 8.信号和槽的传参&#xff1a;…