Csharp/C#教程:c# 实现模糊PID控制算法分享

跑起来的效果看每个类的test方法,自己调用来测试

目的是看看哪个算法好用,移植的时候比较单纯没有研究懂算法,代码结构也没改动,只是移植到C#方便查看代码和测试,大家要拷贝也很方便,把整个类拷贝到.cs文件即可

这段算法在实际值低于目标值是工作正常,超过后会有问题,不知道如何调教

usingSystem; usingSystem.Collections.Generic; usingSystem.Diagnostics; usingSystem.Linq; usingSystem.Text; usingSystem.Threading.Tasks; namespaceFuzzyPID { classFuzzyPID { publicconstintN=7; doubletarget;//系统的控制目标 doubleactual;//采样获得的实际值 doublee;//误差 doublee_pre_1;//上一次的误差 doublee_pre_2;//上上次的误差 doublede;//误差的变化率 doubleemax;//误差基本论域上限 doubledemax;//误差辩化率基本论域的上限 doubledelta_Kp_max;//delta_kp输出的上限 doubledelta_Ki_max;//delta_ki输出上限 doubledelta_Kd_max;//delta_kd输出上限 doubleKe;//Ke=n/emax,量化论域为[-3,-2,-1,0,1,2,3] doubleKde;//Kde=n/demax,量化论域为[-3,-2,-1,0,1,2,3] doubleKu_p;//Ku_p=Kpmax/n,量化论域为[-3,-2,-1,0,1,2,3] doubleKu_i;//Ku_i=Kimax/n,量化论域为[-3,-2,-1,0,1,2,3] doubleKu_d;//Ku_d=Kdmax/n,量化论域为[-3,-2,-1,0,1,2,3] int[,]Kp_rule_matrix=newint[N,N];//Kp模糊规则矩阵 int[,]Ki_rule_matrix=newint[N,N];//Ki模糊规则矩阵 int[,]Kd_rule_matrix=newint[N,N];//Kd模糊规则矩阵 stringmf_t_e;//e的隶属度函数类型 stringmf_t_de;//de的隶属度函数类型 stringmf_t_Kp;//kp的隶属度函数类型 stringmf_t_Ki;//ki的隶属度函数类型 stringmf_t_Kd;//kd的隶属度函数类型 double[]e_mf_paras;//误差的隶属度函数的参数 double[]de_mf_paras;//误差的偏差隶属度函数的参数 double[]Kp_mf_paras;//kp的隶属度函数的参数 double[]Ki_mf_paras;//ki的隶属度函数的参数 double[]Kd_mf_paras;//kd的隶属度函数的参数 doubleKp; doubleKi; doubleKd; doubleA; doubleB; doubleC; publicFuzzyPID(doublee_max,doublede_max,doublekp_max,doubleki_max,doublekd_max,doubleKp0,doubleKi0,doubleKd0) { emax=e_max; demax=de_max; delta_Kp_max=kp_max; delta_Ki_max=ki_max; delta_Kd_max=kd_max; e=target-actual; 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); Kp=Kp0; Ki=Ki0; Kd=Kd0; A=Kp+Ki+Kd; B=-2*Kd-Kp; C=Kd; } //三角隶属度函数 doubletrimf(doublex,doublea,doubleb,doublec) { doubleu; if(x>=a&&x<=b) u=(x-a)/(b-a); elseif(x>b&&x<=c) u=(c-x)/(c-b); else u=0; returnu; } //正态隶属度函数 doublegaussmf(doublex,doubleave,doublesigma) { doubleu; if(sigma<0) { thrownewException("Ingaussmf,sigmamustlargerthan0"); } u=Math.Exp(-Math.Pow(((x-ave)/sigma),2)); returnu; } //梯形隶属度函数 doubletrapmf(doublex,doublea,doubleb,doublec,doubled) { doubleu; if(x>=a&&x<b) u=(x-a)/(b-a); elseif(x>=b&&x<c) u=1; elseif(x>=c&&x<=d) u=(d-x)/(d-c); else u=0; returnu; } //设置模糊规则Matrix publicvoidsetRuleMatrix(int[,]kp_m,int[,]ki_m,int[,]kd_m) { for(inti=0;i<N;i++) for(intj=0;j<N;j++) { Kp_rule_matrix[i,j]=kp_m[i,j]; Ki_rule_matrix[i,j]=ki_m[i,j]; Kd_rule_matrix[i,j]=kd_m[i,j]; } } //设置模糊隶属度函数的子函数 voidsetMf_sub(stringtype,double[]paras,intn) { intN_mf_e=0,N_mf_de=0,N_mf_Kp=0,N_mf_Ki=0,N_mf_Kd=0; switch(n) { case0: if(type=="trimf"||type=="gaussmf"||type=="trapmf") mf_t_e=type; else thrownewException("Typeofmembershipfunctionmustbe"trimf"or"gaussmf"or"trapmf""); if(mf_t_e=="trimf") N_mf_e=3; elseif(mf_t_e=="gaussmf") N_mf_e=2; elseif(mf_t_e=="trapmf") N_mf_e=4; e_mf_paras=newdouble[N*N_mf_e]; for(inti=0;i<N*N_mf_e;i++) e_mf_paras[i]=paras[i]; break; case1: if(type=="trimf"||type=="gaussmf"||type=="trapmf") mf_t_de=type; else thrownewException("Typeofmembershipfunctionmustbe"trimf"or"gaussmf"or"trapmf""); if(mf_t_de=="trimf") N_mf_de=3; elseif(mf_t_de=="gaussmf") N_mf_de=2; elseif(mf_t_de=="trapmf") N_mf_de=4; de_mf_paras=newdouble[N*N_mf_de]; for(inti=0;i<N*N_mf_de;i++) de_mf_paras[i]=paras[i]; break; case2: if(type=="trimf"||type=="gaussmf"||type=="trapmf") mf_t_Kp=type; else thrownewException("Typeofmembershipfunctionmustbe"trimf"or"gaussmf"or"trapmf""); if(mf_t_Kp=="trimf") N_mf_Kp=3; elseif(mf_t_Kp=="gaussmf") N_mf_Kp=2; elseif(mf_t_Kp=="trapmf") N_mf_Kp=4; Kp_mf_paras=newdouble[N*N_mf_Kp]; for(inti=0;i<N*N_mf_Kp;i++) Kp_mf_paras[i]=paras[i]; break; case3: if(type=="trimf"||type=="gaussmf"||type=="trapmf") mf_t_Ki=type; else thrownewException("Typeofmembershipfunctionmustbe"trimf"or"gaussmf"or"trapmf""); if(mf_t_Ki=="trimf") N_mf_Ki=3; elseif(mf_t_Ki=="gaussmf") N_mf_Ki=2; elseif(mf_t_Ki=="trapmf") N_mf_Ki=4; Ki_mf_paras=newdouble[N*N_mf_Ki]; for(inti=0;i<N*N_mf_Ki;i++) Ki_mf_paras[i]=paras[i]; break; case4: if(type=="trimf"||type=="gaussmf"||type=="trapmf") mf_t_Kd=type; else thrownewException("Typeofmembershipfunctionmustbe"trimf"or"gaussmf"or"trapmf""); if(mf_t_Kd=="trimf") N_mf_Kd=3; elseif(mf_t_Kd=="gaussmf") N_mf_Kd=2; elseif(mf_t_Kd=="trapmf") N_mf_Kd=4; Kd_mf_paras=newdouble[N*N_mf_Kd]; for(inti=0;i<N*N_mf_Kd;i++) Kd_mf_paras[i]=paras[i]; break; default:break; } } //设置模糊隶属度函数的类型和参数 publicvoidsetMf(stringmf_type_e,double[]e_mf, stringmf_type_de,double[]de_mf, stringmf_type_Kp,double[]Kp_mf, stringmf_type_Ki,double[]Ki_mf, stringmf_type_Kd,double[]Kd_mf) { setMf_sub(mf_type_e,e_mf,0); setMf_sub(mf_type_de,de_mf,1); setMf_sub(mf_type_Kp,Kp_mf,2); setMf_sub(mf_type_Ki,Ki_mf,3); setMf_sub(mf_type_Kd,Kd_mf,4); } //实现模糊控制 publicdoublerealize(doublet,doublea) { double[]u_e=newdouble[N], u_de=newdouble[N], u_u=newdouble[N]; int[]u_e_index=newint[3],u_de_index=newint[3];//假设一个输入最多激活3个模糊子集 doubledelta_Kp,delta_Ki,delta_Kd; doubledelta_u; target=t; actual=a; e=target-actual; de=e-e_pre_1; e=Ke*e; de=Kde*de; /*将误差e模糊化*/ intj=0; for(inti=0;i<N;i++) { if(mf_t_e=="trimf") u_e[i]=trimf(e,e_mf_paras[i*3],e_mf_paras[i*3+1],e_mf_paras[i*3+2]);//e模糊化,计算它的隶属度 elseif(mf_t_e=="gaussmf") u_e[i]=gaussmf(e,e_mf_paras[i*2],e_mf_paras[i*2+1]);//e模糊化,计算它的隶属度 elseif(mf_t_e=="trapmf") u_e[i]=trapmf(e,e_mf_paras[i*4],e_mf_paras[i*4+1],e_mf_paras[i*4+2],e_mf_paras[i*4+3]);//e模糊化,计算它的隶属度 if(u_e[i]!=0) u_e_index[j++]=i;//存储被激活的模糊子集的下标,可以减小计算量 } for(;j<3;j++)u_e_index[j]=0;//富余的空间填0 /*将误差变化率de模糊化*/ j=0; for(inti=0;i<N;i++) { if(mf_t_de=="trimf") u_de[i]=trimf(de,de_mf_paras[i*3],de_mf_paras[i*3+1],de_mf_paras[i*3+2]);//de模糊化,计算它的隶属度 elseif(mf_t_de=="gaussmf") u_de[i]=gaussmf(de,de_mf_paras[i*2],de_mf_paras[i*2+1]);//de模糊化,计算它的隶属度 elseif(mf_t_de=="trapmf") u_de[i]=trapmf(de,de_mf_paras[i*4],de_mf_paras[i*4+1],de_mf_paras[i*4+2],de_mf_paras[i*4+3]);//de模糊化,计算它的隶属度 if(u_de[i]!=0) u_de_index[j++]=i;//存储被激活的模糊子集的下标,可以减小计算量 } for(;j<3;j++)u_de_index[j]=0;//富余的空间填0 doubleden=0,num=0; /*计算delta_Kp和Kp*/ for(intm=0;m<3;m++) for(intn=0;n<3;n++) { num+=u_e[u_e_index[m]]*u_de[u_de_index[n]]*Kp_rule_matrix[u_e_index[m],u_de_index[n]]; den+=u_e[u_e_index[m]]*u_de[u_de_index[n]]; } delta_Kp=num/den; delta_Kp=Ku_p*delta_Kp; if(delta_Kp>=delta_Kp_max)delta_Kp=delta_Kp_max; elseif(delta_Kp<=-delta_Kp_max)delta_Kp=-delta_Kp_max; Kp+=delta_Kp; if(Kp<0)Kp=0; /*计算delta_Ki和Ki*/ den=0;num=0; for(intm=0;m<3;m++) for(intn=0;n<3;n++) { num+=u_e[u_e_index[m]]*u_de[u_de_index[n]]*Ki_rule_matrix[u_e_index[m],u_de_index[n]]; den+=u_e[u_e_index[m]]*u_de[u_de_index[n]]; } delta_Ki=num/den; delta_Ki=Ku_i*delta_Ki; if(delta_Ki>=delta_Ki_max)delta_Ki=delta_Ki_max; elseif(delta_Ki<=-delta_Ki_max)delta_Ki=-delta_Ki_max; Ki+=delta_Ki; if(Ki<0)Ki=0; /*计算delta_Kd和Kd*/ den=0;num=0; for(intm=0;m<3;m++) for(intn=0;n<3;n++) { num+=u_e[u_e_index[m]]*u_de[u_de_index[n]]*Kd_rule_matrix[u_e_index[m],u_de_index[n]]; den+=u_e[u_e_index[m]]*u_de[u_de_index[n]]; } delta_Kd=num/den; delta_Kd=Ku_d*delta_Kd; if(delta_Kd>=delta_Kd_max)delta_Kd=delta_Kd_max; elseif(delta_Kd<=-delta_Kd_max)delta_Kd=-delta_Kd_max; Kd+=delta_Kd; if(Kd<0)Kd=0; A=Kp+Ki+Kd; B=-2*Kd-Kp; C=Kd; delta_u=A*e+B*e_pre_1+C*e_pre_2; delta_u=delta_u/Ke; if(delta_u>=0.95*target)delta_u=0.95*target; elseif(delta_u<=-0.95*target)delta_u=-0.95*target; e_pre_2=e_pre_1; e_pre_1=e; returndelta_u; } voidshowMf(stringtype,double[]mf_paras) { inttab=0; if(type=="trimf") tab=2; elseif(type=="gaussmf") tab=1; elseif(type=="trapmf") tab=3; this.WriteLine($"函数类型:{mf_t_e}"); this.WriteLine("函数参数列表:"); double[]p=mf_paras; for(inti=0;i<N*(tab+1);i++) { this.Write(p[i]+""); if(i%(tab+1)==tab) this.Write("rn"); } } publicvoidshowInfo() { this.WriteLine("Infoofthisfuzzycontrollerisasfollowing:"); this.WriteLine($"基本论域e:[{-emax},{emax}]"); this.WriteLine($"基本论域de:[{-demax},{demax}]"); this.WriteLine($"基本论域delta_Kp:[{-delta_Kp_max},{delta_Kp_max}]"); this.WriteLine($"基本论域delta_Ki:[{-delta_Ki_max},{delta_Ki_max}]"); this.WriteLine($"基本论域delta_Kd:[{-delta_Kd_max},{delta_Kd_max}]"); this.WriteLine("误差e的模糊隶属度函数参数:"); showMf(mf_t_e,e_mf_paras); this.WriteLine("误差变化率de的模糊隶属度函数参数:"); showMf(mf_t_de,de_mf_paras); this.WriteLine("delta_Kp的模糊隶属度函数参数:"); showMf(mf_t_Kp,Kp_mf_paras); this.WriteLine("delta_Ki的模糊隶属度函数参数:"); showMf(mf_t_Ki,Ki_mf_paras); this.WriteLine("delta_Kd的模糊隶属度函数参数:"); showMf(mf_t_Kd,Kd_mf_paras); this.WriteLine("模糊规则表:"); this.WriteLine("delta_Kp的模糊规则矩阵"); for(inti=0;i<N;i++) { for(intj=0;j<N;j++) { this.Write(Kp_rule_matrix[i,j]); } this.Write("rn"); } this.WriteLine("delta_Ki的模糊规则矩阵");; for(inti=0;i<N;i++) { for(intj=0;j<N;j++) { this.WriteLine(Ki_rule_matrix[i,j]); } WriteEnd(); } this.WriteLine("delta_Kd的模糊规则矩阵");; for(inti=0;i<N;i++) { for(intj=0;j<N;j++) { this.WriteLine(Kd_rule_matrix[i,j]); } WriteEnd(); } this.WriteLine($"误差的量化比例因子Ke={Ke}"); this.WriteLine($"误差变化率的量化比例因子Kde={Kde}"); this.WriteLine($"输出的量化比例因子Ku_p={Ku_p}"); this.WriteLine($"输出的量化比例因子Ku_i={Ku_i}"); this.WriteLine($"输出的量化比例因子Ku_d={Ku_d}"); this.WriteLine($"设定目标target={target}"); this.WriteLine($"误差e={e}"); this.WriteLine($"Kp={Kp}"); this.WriteLine($"Ki={Ki}"); this.WriteLine($"Kd={Kd}"); WriteEnd(); } publicvoidWrite(objectstr) { Console.Write(str); } publicvoidWriteLine(objectstr) { Console.WriteLine(str); } publicvoidWriteEnd() { Console.Write("rn"); } publicstaticvoidtest() { intNB=-3; intNM=-2; intNS=-1; intZO=0; intPS=1; intPM=2; intPB=3; doubletarget=300; doubleactual=400; doubleu=0; int[,]deltaKpMatrix=newint[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=newint[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=newint[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}}; double[]e_mf_paras={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3}; double[]de_mf_paras={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3}; double[]Kp_mf_paras={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3}; double[]Ki_mf_paras={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3}; double[]Kd_mf_paras={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3}; varfuzzypid=newFuzzyPID(1500,1000,0.3,0.9,0.6,0.01,0.04,0.01); 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); for(inti=0;i<50;i++) { u=fuzzypid.realize(target,actual); actual+=u; Console.WriteLine($"{i}{target}{u}{actual}"); //if(i>19) //{ //target=300; //} } //fuzzypid.showInfo(); } } }

上述就是C#学习教程:c# 实现模糊PID控制算法分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/903559.html

(0)
上一篇 2021年10月21日
下一篇 2021年10月21日

精彩推荐