matlab模糊控制移值到c,C/C++实现模糊控制,借助MATLAB辅助设计和fis.c文件 | 学步园...
上一篇文章
typedef struct fis_node {
int handle;
int load_param;
char name[STR_LEN];
char type[STR_LEN];
char andMethod[STR_LEN];
char orMethod[STR_LEN];
char impMethod[STR_LEN];
char aggMethod[STR_LEN];
char defuzzMethod[STR_LEN];
int userDefinedAnd;
int userDefinedOr;
int userDefinedImp;
int userDefinedAgg;
int userDefinedDefuzz;
int in_n;
int out_n;
int rule_n;
int **rule_list;
DOUBLE *rule_weight;
int *and_or;/* AND-OR indicator */
DOUBLE *firing_strength;
DOUBLE *rule_output;
/* Sugeno: output for each rules */
/* Mamdani: constrained output MF values of rules */
struct io_node **input;
struct io_node **output;
DOUBLE (*andFcn)(DOUBLE, DOUBLE);
DOUBLE (*orFcn)(DOUBLE, DOUBLE);
DOUBLE (*impFcn)(DOUBLE, DOUBLE);
DOUBLE (*aggFcn)(DOUBLE, DOUBLE);
DOUBLE (*defuzzFcn)();
DOUBLE *BigOutMfMatrix;/* used for Mamdani system only */
DOUBLE *BigWeightMatrix;/* used for Mamdani system only */
DOUBLE *mfs_of_rule;/* MF values in a rule */
DOUBLE *bias; /*bias, to be tuned when no rules are fired*/
int isbias;
struct fis_node *next;
} FIS;
上述的定义中,defuzzFcn这个指针函数的定义没有参数,而后面的Defuzzification methods都是带参数的,甚至第一个参数就是FIS结构体本身,如:
static DOUBLE defuzzCentroid(FIS *fis, int m, DOUBLE *mf, int numofpoints)
所以要修改这个定义,如下:
typedef struct fis_node FIS;
typedef struct fis_node {
int handle;
int load_param;
char name[STR_LEN];
char type[STR_LEN];
char andMethod[STR_LEN];
char orMethod[STR_LEN];
char impMethod[STR_LEN];
char aggMethod[STR_LEN];
char defuzzMethod[STR_LEN];
int userDefinedAnd;
int userDefinedOr;
int userDefinedImp;
int userDefinedAgg;
int userDefinedDefuzz;
int in_n;
int out_n;
int rule_n;
int **rule_list;
DOUBLE *rule_weight;
int *and_or;/* AND-OR indicator */
DOUBLE *firing_strength;
DOUBLE *rule_output;
/* Sugeno: output for each rules */
/* Mamdani: constrained output MF values of rules */
struct io_node **input;
struct io_node **output;
DOUBLE (*andFcn)(DOUBLE, DOUBLE);
DOUBLE (*orFcn)(DOUBLE, DOUBLE);
DOUBLE (*impFcn)(DOUBLE, DOUBLE);
DOUBLE (*aggFcn)(DOUBLE, DOUBLE);
//DOUBLE (*defuzzFcn)(); hemmingway 2013/01/02
DOUBLE (*defuzzFcn)(FIS *fis, int m, DOUBLE *mf, int numofpoints);
DOUBLE *BigOutMfMatrix;/* used for Mamdani system only */
DOUBLE *BigWeightMatrix;/* used for Mamdani system only */
DOUBLE *mfs_of_rule;/* MF values in a rule */
DOUBLE *bias; /*bias, to be tuned when no rules are fired*/
int isbias;
struct fis_node *next;
} FIS;
接下来是printf和double的宏定义问题,原先针对的是控制台程序,或者Linux下控制台,如果要把模糊控制用到MFC环境,需要修改这个宏定义,方便用到MFC界面程序中,修改过后如下所示:
/* Define portable printf and double */
#if defined(MATLAB_MEX_FILE)
# define PRINTF mexPrintf
# define DOUBLE real_T
#elif defined(__SIMSTRUC__)
# define PRINTF ssPrintf
# define DOUBLE real_T
#elif defined(_MSC_VER)
#define PRINTF odprintf
#include
#include
int _cdecl odprintf(const char* fmt, ...)
{
char buf[4096], *p=buf;
va_listargs;
intret = -1;
va_start(args, fmt);
ret = vsnprintf_s(p, sizeof(buf), _TRUNCATE, fmt, args);
p +=ret;
va_end(args);
while (p>buf && isspace(*p))
{
*--p = '\0';
*p++ = '\r';
*p++ = '\n';
*p = '\0';
}
OutputDebugStringA(buf);
return(ret);
}
#else
# define PRINTF printf
# define DOUBLE double
#endif
接下来修改一下fisError这个函数,里有有个exit(1); 在MFC界面程序中不需要这个的,需要修改一下:
static void fisError(char *msg)
{
#ifdef MATLAB_MEX_FILE
mexErrMsgTxt(msg);
#else
PRINTF("%s\n",msg);
#ifndef _MSC_VER
exit(1);
#endif
#endif
}
还有一个函数封装了fopen()函数打开文件,里面有个多余的定义语句, FILE *fopen(); 这个在C++中不支持,需要注释掉它:
/* an friendly interface to fopen() */
static FILE *fisOpenFile(char *file, char *mode)
{
FILE *fp /*, *fopen()*/;
if ((fp = fopen(file, mode)) == NULL){
PRINTF("The file %s cannot be opened.", file);
fisError("\n");
}
return(fp);
}
再就是fis.c文件后面的几个函数定义,使用 __STDC__ 宏支持了一种老旧的语法格式,如下所示:
/* return data matrix */
DOUBLE **
#ifdef __STDC__
returnDataMatrix(char *filename, int *row_n_p, int *col_n_p)
#else
returnDataMatrix(filename, row_n_p, col_n_p)
char *filename;
int *row_n_p;
int *col_n_p;
#endif
{
//code...
}
问题是MFC程序中 定义 __STDC__ 宏会出现错误的,而那种默认的老旧C语法格式C++中又不支持,所以所有这样定义的函数都要删掉那些多余的东西,如上面的函数改成这样:
/* return data matrix */
DOUBLE **returnDataMatrix(char *filename, int *row_n_p, int *col_n_p)
{
//code...
}
改完以后,没有错误了,用下面的语句将fis.c文件包含到一个CPP文件的时候,问题又来了,出现 fatal
error LNK1169: 找到一个或多个多重定义的符号,按照一般在网上搜索的解决方法是:在项目->属性->链接器->命令行->附加选项中加
/force这样没有错误了,但是还是有很多警告Warning Link 一大堆乱七八糟的警告,其实真正的方法是:在【解决方案资源管理器】中选中fis.c文件,单击右键的属性,打开fis.c属性页对话框,在【配置属性】->【常规】->【项类型】中,将这个配置为【C/C++
标头】,这样就没有什么问题了。
/*Start of the regular fis control*/
extern "C"{
#include "fis.c"
}
============================================
使用方法总结如下:
/*
* 这是修改过后的fis.c模糊推理系统库函数,可以移植C/C++环境使用,在VS2010的MFC环境经过测试
* 1、将fis.c文件拷贝到项目中;
* 2、修改VS2010的配置属性,项目->属性->C/C++->预处理器->预处理器定义,添加
* _CRT_SECURE_NO_WARNINGS
* 3、在【解决方案资源管理器】中选中fis.c文件,单击右键的属性
* 【配置属性】->【常规】->【项类型】,配置为【C/C++ 标头】
* 4、如果是C语言文件(*.c)使用
* #include "fis.c"
* 包含接口库文件;
* 5、如果是C++文件,使用
* extern "C"{
* #include "fis.c"
* }
* 包含库文件。
* 祝你使用愉快!
* hemmingway 2013/1/2
*/
修改过后的fis.c文件可以从这里下载:
http://download.csdn.net/detail/hemmingway/4953923