Está en la página 1de 20

How To Make an S-Function

Chris Atkinson Aero 400 - Flight Simulation

S-Functions
Used to create a block that runs C++ code in Simulink Reasons you need to write an S-Function
Your Simulink model is too complex You need to read in from or write to a file You need to access hardware (AD or DA cards) You need to access external programs (3DLinx)

Simulink model for the x-axis of one wheel in the landing gear model

Equivalent Code in C++


xWPos[i]+=vWheel[0]*dt; xPos=xWPos[i]+offset[i]*cos(angle+rotation[i]); if(xAlreadySliding[i] || yAlreadySliding[i]) Fmax=Fkenitic; else Fmax=Fstatic; FWheel[0]=-kx[i]*(xPos-xWheelPos[i])-bx[i]*vWheel[0]; xSliding=false; if(brake<fabs(FWheel[0])) { FWheel[0]=-brake*Sgn(vWheel[0]); xSliding=false; xWheelPos[i]=xPos; } if(Fmax<fabs(FWheel[0])) { FWheel[0]=-Fkenitic*Sgn(vWheel[0]); xSliding=true; xWheelPos[i]=xPos; }

Introduction to C++
Variables
double y; const int SIZE = 10; bool z = true;

Arrays
double a[SIZE], b[SIZE][SIZE]; a[2] = 3.0; b[2][3] = y/2.0;

Strings (Character arrays)


char s[100] = Chris; (stored as C h r i s \0 You need one extra character for the \0) typedef char String[100]; String s = Chris;

If
if(x>3 && x<-5) { z = false; y = 3.0; } else if(!z || x==8) { x = 6; } else { x += 5; }

For
for(int i = 0; i<10; i++) { a[i] = 5.0; }

While
while(i>2) i-=10.0;

Functions
// Prototype (You need the semicolon) double CalculateSomething(int x, double y);

double CalculateSomething(int x, double y) { double answer; if(x>3) answer = sin(y); // #include <math.h> else answer = double(x); return answer; }

Starting an S-Function
Open a pre-existing S-Function in Visual C++ and save a copy with a new name like Test.cpp Change this line to have the same name as the file name
#define S_FUNCTION_NAME Test

Now you have the general format so all you have to do is change the code to make it do what you want it to do.

Callback Functions
Functions that you write and Simulink calls to run your code
Initialize sizes
Sets the number and sizes of the output and input ports static void mdlInitializeSizes(SimStruct *S)

Initialize sample times


Sets the number and type of the sample times static void mdlInitializeSampleTimes(SimStruct *S)

Initialize conditions
Initializes anything you need it to (variables, read in file, etc.) static void mdlInitializeConditions(SimStruct *S)

Start model
Runs when you start the model running static void mdlStart(SimStruct *S)

Outputs
Runs each time step to calculate the outputs of the block static void mdlOutputs(SimStruct *S, int_T tid)

Terminate
Runs when you stop the model static void mdlTerminate(SimStruct *S)

Simulink Functions
Functions that you can call to get information or set up stuff
Initializing sizes
Set the number of input ports and set the with of each port if (!ssSetNumInputPorts(S, 2)) return; ssSetInputPortWidth(S, 0, 1); ssSetInputPortWidth(S, 1, 1); Set the number of output ports and set the with of each port if (!ssSetNumOutputPorts(S,1)) return; ssSetOutputPortWidth(S, 0, 1);

Initializing sample times


Set the number and type of sample times ssSetNumSampleTimes(S, 1); ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME); ssSetOffsetTime(S, 0, FIXED_IN_MINOR_STEP_OFFSET);

Inputs Read in numbers from the inputs to the block InputRealPtrsType inPtrs1 = ssGetInputPortRealSignalPtrs(S,0); InputRealPtrsType inPtrs2 = ssGetInputPortRealSignalPtrs(S,1); double x = *inPtrs1[0]; double y = *inPtrs2[0];

Outputs
Write the results to the outputs of the block real_T *out = ssGetOutputPortRealSignal(S,0); out[0]=x+y;

Other
Get the step size double dt=ssGetStepSize(S); Get the simulation time double time=ssGetT(S);

Parameters (users can type parameters into a text box in Simulink)


Setup the number of parameters ssSetNumSFcnParams(S, 0); if(ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return; // Parameter mismatch will be reported by Simulink Read in the parameter as a string mxGetString(ssGetSFcnParam(S,0),fname,N_STRING);

Printing to the Simulink window


printf(Hello!\n); printf(The altitude is %f ft.\n, altitude);

Reading in From a File


#include <fstream.h> void ReadFile(double data[MAX_NUMBER], const string filename) { const int N_IGNORE=1000; ifstream input; input.open(filename); number=0; input.eatwhite(); while(!input.eof() && number<MAX_NUMBER) { input>>data[number++]; // Reads in data input.ignore(N_IGNORE,'\n'); // Ignores any comments input.eatwhite(); // Ignores any white space } input.close(); }

Transformation Matrix
// Calculates the transformation matrix from body to earth // coordinates from the given Euler angles. void Transformation(double answer[3][3], double psi, double theta, double phi) { answer[0][0]=cos(psi)*cos(theta); answer[0][1]=sin(psi)*cos(theta); answer[0][2]=-sin(theta); answer[1][0]=cos(psi)*sin(theta)*sin(phi)-sin(psi)*cos(phi); answer[1][1]=sin(psi)*sin(theta)*sin(phi)+cos(psi)*cos(phi); answer[1][2]=cos(theta)*sin(phi); answer[2][0]=cos(psi)*sin(theta)*cos(phi)+sin(psi)*sin(phi); answer[2][1]=sin(psi)*sin(theta)*cos(phi)-cos(psi)*sin(phi); answer[2][2]=cos(theta)*cos(phi); }

Matrix Multiplication
// Multiplies a 3x3 matrix by a 3 element vector. void Multiply(double answer[3], const double A[3][3], const double B[3]) { for(int i=0; i<3; i++) { answer[i]=0.0; for(int j=0; j<3; j++) { answer[i]+=A[j][i]*B[j]; } } }

Example: Converting gravity to body coordinates


double earthToBody[3][3], bodyToEarth[3][3]; double fgEarth[3], fgBody[3]; // Transformation from Body to Earth coordinates Transformation(bodyToEarth,psi,theta,phi); Transpose(earthToBody,bodyToEarth); fgEarth[0]=0.0; fgEarth[1]=0.0; fgEarth[2]=g*mass; Multiply(fgBody, earthToBody, fgEarth);

Compiling Your S-Function


You cant compile an S-Function with Visual C++ directly, because it has to access Matlab libraries. Compile Through Matlab using the Visual C++ compiler
Setup mex >> mex -setup It will ask you if you want it to search for compilers It should find Visual C++ if it is installed Just type in the number for Visual C++ Compile >> mex Test.cpp >> It will probably give you a list of compiler errors If not, it will make Test.dll

Putting Your S-Function into a Model

También podría gustarte