of 20
8/4/2019 Chris Atkinson - How to Make an S-Function
1/20
How To Make an S-Function
Chris Atkinson
Aero 400 - Flight Simulation
8/4/2019 Chris Atkinson - How to Make an S-Function
2/20
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)
8/4/2019 Chris Atkinson - How to Make an S-Function
3/20
Simulink model for the x-axis of one
wheel in the landing gear model
8/4/2019 Chris Atkinson - How to Make an S-Function
4/20
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
8/4/2019 Chris Atkinson - How to Make an S-Function
5/20
Introduction to C++
Variablesdouble y;
const int SIZE = 10;
bool z = true;
Arraysdouble 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;
8/4/2019 Chris Atkinson - How to Make an S-Function
6/20
Ifif(x>3 && x
8/4/2019 Chris Atkinson - How to Make an S-Function
7/20
Whilewhile(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
else
answer = double(x);
return answer;
}
8/4/2019 Chris Atkinson - How to Make an S-Function
8/20
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.
8/4/2019 Chris Atkinson - How to Make an S-Function
9/20
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 timesstatic void mdlInitializeSampleTimes(SimStruct *S)
Initialize conditions
Initializes anything you need it to (variables, read in file, etc.)static void mdlInitializeConditions(SimStruct *S)
8/4/2019 Chris Atkinson - How to Make an S-Function
10/20
Start model
Runs when you start the model running
static void mdlStart(SimStruct *S)
OutputsRuns 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)
8/4/2019 Chris Atkinson - How to Make an S-Function
11/20
Simulink FunctionsFunctions 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);
8/4/2019 Chris Atkinson - How to Make an S-Function
12/20
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];
8/4/2019 Chris Atkinson - How to Make an S-Function
13/20
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 timedouble time=ssGetT(S);
8/4/2019 Chris Atkinson - How to Make an S-Function
14/20
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 bereported 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);
8/4/2019 Chris Atkinson - How to Make an S-Function
15/20
Reading in From a File
#include
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>data[number++]; // Reads in data
input.ignore(N_IGNORE,'\n'); // Ignores any comments
input.eatwhite(); // Ignores any white space
}input.close();
}
8/4/2019 Chris Atkinson - How to Make an S-Function
16/20
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);
}
8/4/2019 Chris Atkinson - How to Make an S-Function
17/20
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
8/4/2019 Chris Atkinson - How to Make an S-Function
18/20
Example: Converting gravity to body
coordinatesdouble 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);
8/4/2019 Chris Atkinson - How to Make an S-Function
19/20
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
8/4/2019 Chris Atkinson - How to Make an S-Function
20/20
Putting Your S-Function into a Model