我在个人博客 F-16飞行器非线性Simulink模型 中,简单介绍了该F-16模型的主要情况、各个文件的功能等。
其中模型中的 F16_dyn.c 是最主要的调试文件,该文件由C语言完成,搭配S-Function使用,难点在于对C Mex S函数的理解和应用。在此对S函数进行一些简单的归纳分析:
首先看一下S函数的简介:
下面看一下该文件,其中有较详细的注释,程序以以下定义开头:
1
2#define S_FUNCTION_NAME F16_dyn #define S_FUNCTION_LEVEL 2
第一条指定了 S-function 的名字(F16_dyn),第二条指定了该 S-function 是按照 level 2 的格式进行编写的。
在定义了这两条之后,该程序包含了 simstruc.h 文件,这是一个头文件,它给出了SimStruct 数据结构的访问通道,以及MATLAB 应用程序接口(API)函数。
1
2
3
4
5
6
7
8
9
10/* include files */ #include <math.h> #include "simstruc.h" #include "aerodata/mexndinterp.c" #include "aerodata/hifi_f16_aerodata.c" /* hifi lookup tables */ #include "aerodata/lofi_f16_aerodata.c" /* lofi lookup tables */ #include "aerodata/ISA_atmos.c" /* ISA atmosphere model */ #include "aerodata/engine_model.c" /*engine model */
接下来是各种宏定义:包括输入量、状态量、状态量导数、系数、参数、常量。
下面看一下模型运行的过程:
下图所示为 Simulink 调用S-function 回调函数的顺序。实线框部分表示在模型初始化和/或每个仿真步长内需使用的回调函数;虚线框部分表示在初始化阶段和/或在仿真循环的一些或所有采样步长内使用的回调函数。
这里摘出几个需要特别注意的模块:
Simulink 调用 mdlInitializeSizes 来获取输入端口和输出端口的数量、端口宽度、以及S-function 所需的任何其它对象(诸如状态数量)等有关信息。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30/*=============================*/ /* Function: mdlInitalizeSizes */ /*=============================*/ static void mdlInitializeSizes(SimStruct *S) { ssSetNumSFcnParams(S, 1); /* Number of expected parameters */ ssSetNumContStates(S, 20); ssSetNumDiscStates(S, 0); ssSetNumInputPorts(S, 2); ssSetInputPortWidth(S, 0, 4); ssSetInputPortWidth(S, 1, 1); // ssSetInputPortWidth(S, 2, 1); /* ssSetInputPortDirectFeedThrough(S, 1, 1); */ ssSetNumOutputPorts(S, 2); ssSetOutputPortWidth(S, 0, 23); ssSetOutputPortWidth(S, 1, 3); ssSetNumSampleTimes(S, 1); ssSetNumRWork(S, 23); ssSetNumIWork(S, 0); ssSetNumPWork(S, 0); ssSetNumModes(S, 0); ssSetNumNonsampledZCs(S, 0); ssSetOptions(S, 0); }
在每个采样时间步长内,Simulink 调用mdlOutputs 来计算块的输出。 其中利用 data_output[i] 增加了变量的输出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25/*======================*/ /* Function: mdlOutputs */ /*======================*/ static void mdlOutputs(SimStruct *S, int_T tid) { real_T *x = ssGetContStates(S); real_T *y = ssGetOutputPortRealSignal(S, 0); int i; for (i = 0; i < ssGetNumContStates(S); i++) { y[i] = x[i]; /* outputs are the states */ } for(i=0; i<3; i++) { y[i+ssGetNumContStates(S)] = data_output[i]; } real_T *y1 = ssGetOutputPortRealSignal(S, 1); y1[0] = X_output; y1[1] = Y_output; y1[2] = Z_output; }
其次是变量的定义:
注意开始有输入端口的定义,需与 mdlInitializeSizes 中对应。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/*==========================*/ /* Function: mdlDerivatives */ /*==========================*/ #define MDL_DERIVATIVES #if defined(MDL_DERIVATIVES) static void mdlDerivatives(SimStruct *S) { real_T *x = ssGetContStates(S); real_T *dx = ssGetdX(S); InputRealPtrsType u = ssGetInputPortRealSignalPtrs(S, 0); InputRealPtrsType u1 = ssGetInputPortRealSignalPtrs(S, 1); // InputRealPtrsType u3 = ssGetInputPortRealSignalPtrs(S, 2); /* Declare a lot of variables */ 变量定义 /* end mdlDerivatives */ #endif
最后
以上就是端庄朋友最近收集整理的关于MATLAB S函数 之 C Mex S函数结构分析的全部内容,更多相关MATLAB内容请搜索靠谱客的其他文章。
发表评论 取消回复