实现模糊控制器需要以下步骤:
确定模糊控制器的输入和输出量 设计模糊控制器的控制规则 确立模糊化和非模糊化的方法 选择模糊控制器的输入变量和输出变量的论域并确定模糊控制器的参数(如量化因子,比例因子等) 编制模糊控制算法的应用程序合理选择模糊控制算法的采样时间
本模糊控制器采用双输入单输出的形式,输入变量为误差e和误差的变化率de,输出为控制量u;e,de,u的量化论域范围为[-3,-2,-1,0,1,2,3],划分的模糊子集为:[NB,NM,NS,ZO,PS,PM,PB].基本论域的范围选取需要根据实际情况来确定上限值emax,demax,umax.
量化因子:Ke=3/emax, Kde=3/demax,
输出缩放因子:Ku=umax/3
为了减少计算量,e,de,u的隶属度函数都选用三角形隶属度函数。如下图所示:
模糊控制最重要的是要确定模糊控制规则,它可以通过专家经验获得,也可以通过采样数据获得,这里使用的模糊控制规则表如下;
在微处理器中实现模糊控制的一般采用离线查表的方法。首先模糊化输入到控制器中的e和de,计算他们的在每个模糊子集中的隶属度值,然后找出激活的模糊子集,存储起来,最后使用加权平均的方法计算输出值。具体的公式如下:
Zi为u的模糊隶属度函数的尖点所对应的横坐标值。
下面讲讲怎么用C++实现模糊控制器。
首先需要建立一个Fuzzy_controller的类:
class Fuzzy_controller { public: const static int N=7;//定义量化论域模糊子集的个数 private: float target;//系统的控制目标 float actual;//采样获得的实际值 float e; //误差 float e_pre; //上一次的误差 float de; //误差的变化率 float emax; //误差基本论域上限 float demax; //误差辩化率基本论域的上限 float umax; //输出的上限 float Ke; //Ke=n/emax,量化论域为[-3,-2,-1,0,1,2,3] float Kde; //Ke=n/demax,量化论域为[-3,-2,-1,0,1,2,3] float Ku; //Ke=umax/n,量化论域为[-3,-2,-1,0,1,2,3] int rule[N][N];//模糊规则表 string mf_t_e; //e的隶属度函数类型 string mf_t_de; //de的隶属度函数类型 string mf_t_u; //u的隶属度函数类型 float *e_mf_paras; //误差的隶属度函数的参数 float *de_mf_paras;//误差的偏差隶属度函数的参数 float *u_mf_paras; //输出的隶属度函数的参数 public: Fuzzy_controller(float e_max,float de_max,float u_max); ~Fuzzy_controller(); 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_u,float *u_mf); void setRule(int rulelist[N][N]); //设置模糊规则 float realize(float t,float a); //实现模糊控制 void showInfo(); //显示该模糊控制器的信息 void showMf(const string & type,float *mf_paras); //显示隶属度函数的信息 };
然后给出类方法的定义:
Fuzzy_controller::Fuzzy_controller(float e_max,float de_max,float u_max): target(0),actual(0),emax(e_max),demax(de_max),umax(u_max),e_mf_paras(NULL),de_mf_paras(NULL),u_mf_paras(NULL) { e=target-actual; e_pre=0; de=e-e_pre; Ke=(N/2)/emax; Kde=(N/2)/demax; Ku=umax/(N/2); mf_t_e="trimf"; mf_t_de="trimf"; mf_t_u="trimf"; } Fuzzy_controller::~Fuzzy_controller() { delete [] e_mf_paras; delete [] de_mf_paras; delete [] u_mf_paras; } //三角隶属度函数 float Fuzzy_controller::trimf(float x,float a,float b,float c) { float u; if(x>=a&&x<=b) u=(x-a)/(b-a); else if(x>b&&x<=c) u=(c-x)/(c-b); else u=0.0; return u; } //正态隶属度函数 float Fuzzy_controller::gaussmf(float x,float ave,float sigma) { float u; if(sigma<0) { cout<<"In gaussmf, sigma must larger than 0"<=a&&x=b&&x =c&&x<=d) u=(d-x)/(d-c); else u=0; return u; } //设置模糊规则 void Fuzzy_controller::setRule(int rulelist[N][N]) { for(int i=0;i =umax) u=umax; else if(u<=-umax) u=-umax; e_pre=e; return u; } void Fuzzy_controller::showMf(const string & type,float *mf_paras) { int tab; if(type=="trimf") tab=2; else if(type=="gaussmf") tab==1; else if(type=="trapmf") tab=3; cout<<"函数类型:"<<> 此模糊控制的类,允许用户使用不同的模糊隶属度函数,如三角型,正态分布型和梯形。但是需要相应的给出适当的函数参数。用户可以修改模糊控制规则表,以提高模糊控制器的性能。但是用户需要首先明确误差e,误差变化率de和输出u的最大范围,因为这里需要依据他们来确定量化因子和缩放因子,如果给出的范围不合适,则很难达到理想的控制效果。 下面是一个测试的例子,仅供参考: #include
int main()
{
float target=600;
float actual=0;
float u=0;
int ruleMatrix[7][7]={{NB,NB,NM,NM,NS,ZO,ZO},
{NB,NB,NM,NS,NS,ZO,PS},
{NM,NM,NM,NS,ZO,PS,PS},
{NM,NM,NS,ZO,PS,PM,PM},
{NS,NS,ZO,PS,PS,PM,PM},
{NS,ZO,PS,PM,PM,PM,PB},
{ZO,ZO,PM,PM,PM,PB,PB}};//模糊规则表
float e_mf_paras[21]={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3};//误差e的隶属度函数参数,这里隶属度函数为三角型,所以3个数据为一组
float de_mf_paras[21]={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3};//误差变化率de的模糊隶属度函数参数
float u_mf_paras[21]={-3,-3,-2,-3,-2,-1,-2,-1,0,-1,0,1,0,1,2,1,2,3,2,3,3};//输出量u的隶属度函数参数
Fuzzy_controller fuzzy(1000,650,500);//控制器初始化,设定误差,误差变化率,输出的最大值
fuzzy.setMf(“trimf”,e_mf_paras,”trimf”,de_mf_paras,”trimf”,u_mf_paras);//设定模糊隶属度函数
fuzzy.setRule(ruleMatrix);//设定模糊规则
cout<<”num target actual“<
{
u=fuzzy.realize(target,actual);
actual+=u;
cout< }
fuzzy.showInfo();
system(“pause“);
return 0;
}
运行结果:
这里设定的目标值为600,可见,控制器在运行到9次时就稳定在了600,控制效果比较好。