SlideShare a Scribd company logo
Summer Internship 2010
Development of a
MATLAB/Simulink - Toolbox for
Distributed Simulation
Author:
James Dianics
Supervisor:
Prof. Dr.-Ing. Reinhard
Finsterwalder
July 30, 2010
Abstract
This report gives an overview of the development of a distributed simulation toolbox for
Matlab/Simulink. The project was developed as a sub-project to the MASTER program
which is designed to be a student built flight simulator for education and research. The
model dynamics for the flight simulator has been built and implemented in the Mat-
lab/Simulink environment. A toolbox to allow for the real time communication between
systems is necessary. This project specifically is to build the UDP solution of the dis-
tributed simulation toolbox which will contain the ability to transmit via Singlecast,
Multicast and Broadcast. The creation of the toolbox was accomplished in two phases;
the development of test applications in C++, and then the development of the UDPSend
and UDPReceive S-functions for Matlab.
Contents
1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.1 Project MASTER . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Distributed Simulation . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3 Universal Datagram Protocol (UDP) . . . . . . . . . . . . . . . . 2
2 Programming UDP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3 C++ Test Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.1 Developed Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.2 Sample Server Application in C++ . . . . . . . . . . . . . . . . . 8
4 Matlab/Simulink Toolbox . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4.1 Outline of UDPSend S-Function . . . . . . . . . . . . . . . . . . . 11
4.2 Outline of UDPReceive S-Function . . . . . . . . . . . . . . . . . 12
4.3 Creating a Library of S-Function Blocks . . . . . . . . . . . . . . 13
4.4 Masking the Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4.5 Example Simulink Models using Distributed Simulation Toolbox . 16
5 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
6 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
7 Appendix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
7.1 socket.h and socket.cpp . . . . . . . . . . . . . . . . . . . . . . . . 18
7.2 udpsocket.h and udpsocket.cpp . . . . . . . . . . . . . . . . . . . 20
7.3 S-Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1
1 Introduction
1.1 Project MASTER
The MASTER project was started in 2001 at the University of the Federal Armed Forces
Munich, Germany. The purpose of the MASTER project is the development of a modular
vehicle simulator with exchangeable cockpit modules for education and research appli-
cation. Thus ”MASTER” is an acronym which stands for Modular Advanced Simulator
Technology for Education and Research. MASTER has been structured so that the ma-
jority of the work will be accomplished by student projects.
1.2 Distributed Simulation
In the development of a large simulation or application a single computer’s resources are
often insufficient. Distributed computing allows for either parallel computing on a single
machine with multiple cores or among many nodes in a network; either solution provides
an increased amount of hardware resources resulting in better application performance.
1.3 Universal Datagram Protocol (UDP)
There are two commonly used communication protocols, Transmission Control Protocol
(TCP) and Universal Datagram Protocol (UDP). TCP is commonly used for streaming
data between two clients such as a web browser and web server. The main points of TCP
that were of a concern are that TCP utilizes error checking and creates a buffer waiting
for delayed data before releasing the packet, both of these functions delay the speed of
the data but give a more reliable signal.
UDP does not utilize error checking and by definition is unreliable. This attribute can
be beneficial if used correctly because it allows for less signal delay because of the lack of
processing on the network that needs to be done before receiving a signal. One must be
careful about its application and understand that packets could be missing, duplicated or
arrive out of order. Another benefit of UDP is that it is capable of Singlecast, Multicast,
and Broadcast transmissions where as TCP is only capable of Singlecast. Singlecast is
the typical single client single server transmission. Multicast is located on a different
IP range and theoretically a single client can send a message to an unlimited number of
listening servers.
UDP is best used during real-time applications where speed is required. This could be
during VoIP, IP-TV or applications such as Skype where lost packets could mean a smear
in the picture but the overall quality of the picture shall remain good if the connection
is decent. UDP was chosen for the MASTER project because of the need for real-time
communication and varying transmission capabilities.
2
Figure 1: Route Sequences Potential Receivers(Yellow)
Figure 2: Singlecast
Figure 3: Multicast
Figure 4: Broadcast
2 Programming UDP
Windows sockets 2 (Winsock2) is an API that allows for programmers to easily create
networking functions for applications. In order to create networking ability only a few
windows socket functions are necessary.
struct WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
WSADATA is a structure that is required to define the functionality of the windows socket
and the function WSAStartup takes a pointer to the structure and initializes the socket
in the windows operating system. This is necessary for every socket ran on a windows
system. When the socket is closed conversely WSACleanup(); needs to be used to delete
and free the socket on the windows system.
3
To create a socket a call
s = socket(AF_INET,SOCK_DGRAM,0);
Where AF INET is the address family associated with TCP and UDP type protocols.
SOCK DGRAM is a connectionless type protocol for UDP transmission. Thus the socket
being created here is defined for UDP connectionless use.
To set where the socket is listening(server side) or where the socket is sending datagrams
(client side) the SOCKADDR IN structure needs to be defined.
memset (&addr,0,sizeof(SOCKADDR_IN));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr=inet_addr(IP);
Where the memory at the structures location is cleared and set with the family, port, and
IP address in that respective order. To accomplish communication there are four basic
functions for TCP and UDP.
TCP utilizes connections and thus uses different functions for sending and receiving data
send() and recv()
UDP is connectionless and uses
sendto() and recvfrom()
because the client and server is not strictly defined before this function.
sendto ( s , buffer , sizeof ( buffer ) , 0 ,(SOCKADDR∗)&addr , sizeof (SOCKADDR IN) ) ;
recvfrom ( s , buffer , sizeof ( buffer ) ,0 ,NULL,NULL) ;
When finished with the socket use
closesocket(s);
Combined together this would be the most basic of UDP programming required to get a
simple application running using Winsock2.
4
3 C++ Test Application
Before the development of the Matlab/Simulink distributed simulation toolbox two test
applications were built using Microsoft’s Visual C++ application development studio.
The applications were designed to meet the requirements that needed to be met in the
Matlab environment. Requirements for the Client
• The client shall utilize UDP protocol
• The client shall send arrays of data
• The client shall be able to send all data in byte format
• The client shall be able to send Singlecast, Multicast and Broadcast transmissions
• The client shall be able to send in real-time
Requirements for the Server
• The server shall utilize UDP protocol.
• The server shall receive datagram packets and be able to unpack them into a spec-
ified data type.
• The server shall be able to join Multicast groups.
• The server shall be able to receive Singlecast and Broadcast Transmissions.
• The server shall be able to receive transmission in real-time
Requirements for packet transmission protocol
• The packet shall contain a 3 integer header in byte format.
• The header shall contain information about the size of the packet, the data type of
the data contained and the number of elements contained in the array being sent
or received.
• Preceding the header the data array shall be contained in a byte format.
Figure 5: Packet Protocol
5
Data types that the classes currently support were included due to their definition by
Matlab/Simulink
Figure 6: Matlab/Simulink Data Types
Two classes were developed to handle the socket and UDP functions to meet the require-
ments of the project. Two classes were developed so that a TCPsocket class could later
be developed extending the socket class.
6
3.1 Developed Classes
Figure 7: Class Diagram
Use of the two classes to develop a UDP server or client is fairly straightforward.
The socket class defines two socket structures and stores them as protected variables.
• addr
• s
The socket class also contains two functions.
• bind(): Connect the socket to a port
• close(): Closes a socket
The udpsocket class utilizes the windows socket functions and the developed protocol to
send and receive data
• create(): Creates a udpsocket object
• setdest(): Sets the destination port and IP
• joinmulticast(): Joins a multi-cast group at a specific IP
• pack(): packs an array of data into the previously discussed protocol
• send(): Sends a package on the udpsocket
• startthread(): Sets a parameter to prepare for receivethread
• receivethread(): starts another thread to fill data buffers from the incoming signal
7
• getdata(): returns the data from the receivethread() function, size, type, elements,
and package
• endthread(): prepares the thread for closing and deleting
• closethread(): closes the thread
• getaddr(): gets the SOCKADDR IN structure from the socket class
The template function compile accepts an unknown data type to convert the UDP pro-
tocol byte form back to a designated data type (float, int, etc...)
template <class Unk>
void compile (char*message,int size,Unk* &data)
{
byte *temp,*temp2,*temp3;
temp3 = new byte[size];
temp = (byte*)message;
for (int i = 0; i<(size/sizeof(Unk)); i++)
{
temp2 = temp+12+i*sizeof(Unk);
memcpy(temp3+sizeof(Unk)*i,temp2,sizeof(Unk));
}
data = (Unk*)temp3;
3.2 Sample Server Application in C++
All of this is complied into the main thread to make an example server in
c++...
int main (int argc, char *argv[])
{
printf("UDP servern");
UDPsocket s;
char message[256];
int size,type;
if(s.create())
{
s.close();
printf("Error on createn");
return 1;
}
if(s.bind())
{
8
s.close();
printf("error on bindn");
system ("PAUSE");
return 1;
}
if(s.joinmulticast())
{
printf("Error on joinmulticastn");
s.close();
return 1;
}
Here the UDPsocket object is created and the required variables are declared
to obtain a message and compile it. The socket is created, bound, and joined
to a multi-cast IP all with error checking.
Next the receivethread function is intialized with the startthread() function
call and a while loop is ran to get data from the buffers.
s.startthread();
s.getdata(message,size,type,message_len)
if(message_len>0&&size>0)
{
switch(type)
{
case INT:
{
int * data = new int[size/sizeof(int)];
compile(message,size,data);
for(int i = 0;i<size/sizeof(int);i++)
{printf("%in",data[i]);
cout << data[i] << endl;
}
delete data;
break;
}
If the message length is greater than 0 (meaning that a message has been
received) a switch structure is used to determine the data type based on the
type received and the data is compiled and read out. The data type has been
enumerated in the socket class.
s.endthread();
s.closethread();
s.close();
9
When the server is finished the thread listening on the socket is ended and
closed and the socket is then closed.
4 Matlab/Simulink Toolbox
MATLAB is a well known and widely used technical computing software package. To-
gether with Simulink one can simulate and do model-based design for multi domain sys-
tems. To allow for the communication of multiple computers in the Matlab and Simulink
environment the C++ test applications were translated into S-functions.
S-functions in general are a computer language description of a single Simulink block.
S-functions can be written in many languages ( C++, C, Fortran etc) and then compiled
into a MEX (Matlab Executable) file which is implemented in Simulink.
Understanding how Simulink and S-functions work is important when beginning to build
a Simulink block. In a very simple explanation the block accepts at every time step,
calculates a result, and sends an output.
Figure 8: Simulink Engine
10
Every S - Function follows a strict structure the most basic template includes these 4
main functions.
static void m d l I n i t i a l i z e S i z e s ( SimStruct ∗S)}
static void mdlInitializeSampleTimes ( SimStruct ∗S)
static void mdlStart ( SimStruct ∗S)
static void mdlOutputs ( SimStruct ∗S)
static void mdlTerminate ( SimStruct ∗S)
4.1 Outline of UDPSend S-Function
mdlInitializeSizes
1. Set the number of parameters(3 for the send block)
2. Set the input port width and data type (1 input with inherited width and data
type)
3. Set number of output ports (0 outputs)
mdlInitializeSampleTimes
1. Set sample times
mdlStart
1. Get parameters from the block
2. Create a UDPsocket object
3. Based upon parameters set the destination to send the data
4. Save the socket in the PWork Vector for later use
mdlOutputs
1. Get UDPsocket object from PWork Vector
2. Based upon data type pack and send the data
mdlTerminate
1. Get UDPsocket object from PWork vector
2. Close and delete the socket
11
Every S-function has inputs and outputs which are defined during the initialization.
With the UDPsend block it is initialized to have a single input with data type and width
inherited from the driving block. MDLstart is only ran at the beginning of the simulation
here is where the socket is opened and set using the parameters provided by the user.
The output function will be ran at every time step and is being used to send the data
from. Terminate is only ran at the end of the simulation and this is where we simply
close and delete the UDP socket object from memory.
4.2 Outline of UDPReceive S-Function
mdlInitializeSizes
1. Set the number of parameters (5 for the receive block)
2. Set the input port width and data type (0 inputs)
3. Set number of output ports (1 output)
4. Set OutputPortWidth with the Elements parameter
5. Set OutputPortDataType withe the Data Type parameter
mdlInitializeSampleTimes
1. Set sample times
mdlStart
1. Get parameters from the block and check if the IP parameter is a string
2. Create a UDPsocket object
3. Bind the socket to the port based on the parameter
4. Based upon a parameter join a Multicast group or listen on broadcast
5. start the receivethread with s.startthread() function
6. Save the socket in the PWork Vector for later use
mdlOutputs
1. Get UDPsocket object from PWork Vector
2. s.getdata(message,size,type,message length) to gather data
3. If a message is received use a switch structure on type to compile
4. obtain pointer to the output port real T *y = (real T*)ssGetOutputPortSignal(S,0)
5. copy the compiled data to the output port
12
mdlTerminate
1. Get UDPsocket object from PWork vector
2. s.endthread()
3. s.closethread()
4. Close and delete the socket
4.3 Creating a Library of S-Function Blocks
Before a S-function can be used it needs to be compiled into a MEX file. This requires
linking all of the necessary files so that Matlab can create an executable for its environ-
ment. In the Matlab command prompt compile the send and receive functions developed
during this project using the following two commands.
• mex UDPSend.cpp udpsocket.cpp WS2 32.lib socket.cpp
• mex UDPReceive.cpp udpsocket.cpp WS2 32.lib socket.cpp
Once successfully compiled in the Matlab environment a library can easily be built.
1. Open a new simulink model
2. Add two new S-functions to the model from the User-Defined Functions library
3. Open the S-function parameters by double clicking
4. Under S-Function name: insert UDPSend in one and UDPReceive in the
other
5. Select File ... New ... Library
6. Drag both created S-Functions to the new library
7. Save the Library file (.mdl) in its on folder in the Matlab path
8. In this new folder create a new .m file ”slblocks”
The slblocks.m file gives Simulink a reference of how label and use the library. In a short
example it tells it what folder the files are in and how to name the library.
function blkStruct = slblocks
% Specify that the product should appear in the library browser
% and be cached in its repository
Browser.Library = ’UDPCommBlocks’;
Browser.Name = ’UDP Communication Blocks’;
blkStruct.Browser = Browser;
Is all that is necessary to be included in the .m file.
13
4.4 Masking the Blocks
To add a mask to the block open the .mdl library file created holding the blocks
1. Unlock the Library by selecting Edit ... Unlock Library in the library window
2. right click on the block and select Mask S-Function...
3. Proceed to the Parameters tab
4. Add a new Parameter
• Prompt is the title that will show up in the mask
• Variable is the variable that will be passed to the S-Function
• Type is the type of input from the user
5. Once all parameters are defined in the mask they need to be passed to the S-
Function
6. Right click again on the block and select Look Under Mask
7. Add the parameter variables to the parameters list
8. block description and other documentation can be handled within the other tabs
14
Figure 9: S-Function Mask Editor
Figure 10: S-Functions Parameters
15
4.5 Example Simulink Models using Distributed Simulation Tool-
box
Figure 11: S-Function UDPSend - Transmitting position and orientation data from the
flight model to the visualization engine
16
Figure 12: S-Function UDPReceive - Receiving position and orientation data in the
visualization engine
5 Results
A Matlab/Simulink Distributed Simulation Toolbox was successfully developed using
the UDP transmission protocol. The send and receive blocks are able to send arrays
of all Matlab data types using Singlecast, Multicast or Broadcast transmissions. Some
problems arose while writing the receive S-Function from the developed C++ test ap-
plication. Originally a blocking socket was used to receive data in the test application
but would crash Simulink when implemented as a S-Function. As a temporary solution
a non-blocking socket was used to successfully complete the S-Function. While testing
the S- Function, strange behavior was observed where data was still is received after
the send model had stopped running; this was attributed to the non-blocking socket
building a buffer on the network. The final solution was found by creating a separate
thread to operate a blocking socket that would listen for incoming messages, this thread
could run continuously without delaying Simulink and is the final successful solution. The
distributed simulation toolbox could be further improved by also implementing other net-
work protocols into separate blocks, notably TCP could be useful in other applications
where error checking is necessary. The UDP blocks could also be improved by adding the
ability to send structures or user created data types.
17
6 References
Anonymous (2010). Writing S-Functions. The
Mathworks Inc., Natick, USA.
Anonymous (2010). MathWorks - MATLAB and Simulink for Technical Computing.
<http://www.mathworks.com/>.
Anonymous (2010). Windows Sockets 2 [online].
<http://msdn.microsoft.com/enus/
library/ms740673(VS.85).aspx>.
7 Appendix
7.1 socket.h and socket.cpp
socket.h
#ifndef SOCKET H
#define SOCKET H
#include <winsock2 . h>
#include <ws2tcpip . h>
c l a s s Socket
{
public :
enum datatype
{
DOUBLE = 1 ,
SINGLE = 2 ,
BOOLEAN = 9 ,
INT8 =3,
UINT8=4,
INT16 = 5 ,
UINT16 = 6 ,
INT32 = 7 ,
UINT32 = 8 ,
};
Socket ( ) ;
˜ Socket ( ) ;
int c l o s e ( ) ;
int bind ( int port =12345);
protected :
18
SOCKET s ;
SOCKADDR IN addr ;
};
#endif
socket.cpp
#include ” socket . h”
Socket : : Socket ()
{
WSADATA wsaData ;
WSAStartup(MAKEWORD(2 ,2) ,& wsaData ) ;
}
Socket : : ˜ Socket ()
{
WSACleanup ( ) ;
}
int Socket : : c l o s e ()
{
i f ( clos esocket ( s)==SOCKET ERROR)
{
return 1;
}
return 0;
}
int Socket : : bind ( int port )
{
memset (&addr ,0 , sizeof (SOCKADDR IN) ) ;
addr . s in fa mi ly = AF INET;
addr . sin port = htons ( port ) ;
addr . sin addr . s addr=INADDR ANY;
i f ( : : bind ( s , (SOCKADDR∗)&addr ,
sizeof (SOCKADDR IN)) == SOCKET ERROR)
{
return 1;
}
return 0;
}
19
7.2 udpsocket.h and udpsocket.cpp
udpsocket.h
#ifndef UDPSOCKET H
#define UDPSOCKET H
#include ” socket . h”
#include <windows . h>
#include <process . h>
c l a s s UDPsocket : public Socket
{
public :
UDPsocket ( ) ;
˜UDPsocket ( ) ;
int create ( ) ;
SOCKADDR IN getaddr (){ return addr ;}
SOCKET getsocket (){ return s ; }
int joinmulticast (char∗ IP=” 2 2 6 . 0 . 0 . 1 ” ) ;
void setdest (char∗ IP=” 2 2 6 . 0 . 0 . 1 ” , int port = 12345);
int send ( void∗ buffer , int b u f f e r l e n ) ;
unsigned char∗ pack ( void∗ number , int type , int s i z e ) ;
static long WINAPI receivethread (LPVOID Param ) ;
void getdata (char ∗msg , int &size , int &type , int &msg len ) ;
void startthread ( ) ;
void endthread ( ) ;
void closethread ( ) ;
private :
};
#endif
udpsocket.cpp
#include "UDPsocket.h"
#include "simstruc.h"
SOCKET s = INVALID_SOCKET;
int g_message_len=0,g_size=0,g_type=0;
char g_buffer[2000];
HANDLE rthread=0;
int param;
UDPsocket::UDPsocket ()
{
}
20
UDPsocket::~UDPsocket ()
{
}
int UDPsocket::create ()
{
s = socket(AF_INET, SOCK_DGRAM,0);
::s=s;
if (s==INVALID_SOCKET)
{
return 1;
}
return 0;
}
int UDPsocket::joinmulticast(char* IP)
{
struct ip_mreq mreq;
memset (&mreq,0,sizeof(IP_MREQ));
mreq.imr_interface.s_addr = INADDR_ANY;
mreq.imr_multiaddr.s_addr = inet_addr(IP);
if(setsockopt (s,IPPROTO_IP,IP_ADD_MEMBERSHIP,
(const char*)&mreq,sizeof(IP_MREQ)) == SOCKET_ERROR)
{
return 1;
}
return 0;
}
void UDPsocket::setdest(char* IP, int port)
{
memset (&addr,0,sizeof(SOCKADDR_IN));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr=inet_addr(IP);
}
int UDPsocket::send(void* buffer, int bufferlen)
{
sendto(s,(char*)buffer,bufferlen,0,(SOCKADDR*)
&addr,sizeof(SOCKADDR_IN));
return 0;
}
unsigned char* UDPsocket::pack(void* number,int type,int size)
{
int x;
switch(type)
{
21
case Socket::DOUBLE:
{x = sizeof(real_T);
break;
}
case Socket::SINGLE:
{x = sizeof(real32_T);
break;
}
case Socket::BOOLEAN:
{ x = sizeof(boolean_T);
break;
}
case Socket::INT8:
{
x = sizeof(int8_T);
break;
}
case Socket::UINT8:
{
x = sizeof(uint8_T);
break;
}
case Socket::INT16:
{
x = sizeof(int16_T);
break;
}
case Socket::UINT16:
{
x = sizeof(uint16_T);
break;
}
case Socket::INT32:
{
x = sizeof(int32_T);
break;
}
case Socket::UINT32:
{
x = sizeof(uint32_T);
break;
}
}
size = size + 12;
byte* packet = new byte[size];
byte* total,*elements,*typ;
int e = (size-12)/x;
22
elements = (byte*)&e;
total = (byte*)&size;
typ = (byte*)&type;
memcpy(packet,total,sizeof(int));
memcpy(packet+sizeof(int),elements,sizeof(int));
memcpy(packet+2*sizeof(int),typ,sizeof(int));
for(int i = 0;i<e;i++)
{ byte* temp;
temp = (byte*)number+x*i;
memcpy(packet+(sizeof(int)*3)+(i*x),temp,x);
}
send(packet,size);
return packet;
}
long WINAPI UDPsocket::receivethread(LPVOID Param)
{
while(param==1)
{
if(::s!=INVALID_SOCKET)
{
g_message_len = recvfrom(::s,g_buffer,
sizeof(g_buffer),0,NULL,NULL);
int * package = (int*)g_buffer;
g_size = package[0]-12;
g_type = package[2];
}
}
g_message_len = 0;
g_size = 0;
g_type = 0;
return 0;
}
void UDPsocket::getdata(char *msg, int &size, int &type, int &msg_len)
{
memcpy(msg,g_buffer,g_message_len);
size = g_size;
type = g_type;
msg_len = g_message_len;
}
void UDPsocket::startthread()
{ param =1;
rthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)
receivethread,&param,0,NULL);
}
void UDPsocket::endthread()
{
23
param = 0;
}
void UDPsocket::closethread()
{
CloseHandle(rthread);
}
7.3 S-Functions
UDPSend
#define S_FUNCTION_NAME UDPSend_gen
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
#include <WinSock2.h>
#include <stdio.h>
#include "udpsocket.h"
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 3);
//Parameter 1 :: IP to broadcast to
//Parameter 2 :: Port
//Parameter 3:: Broadcast Type
// Parameter mismatch will be reported by Simulink
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S))
{
return;
}
// 1 input that is dynamically_sized with direct feedthrough
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED);
ssSetInputPortDataType(S,0,DYNAMICALLY_TYPED);
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S,0)) return;
//one sample time initialized below
ssSetNumSampleTimes(S, 1);
// Reserve place for C++ object Socket
ssSetNumPWork(S, 1);
24
ssSetOptions(S,
SS_OPTION_WORKS_WITH_CODE_REUSE |
SS_OPTION_EXCEPTION_FREE_CODE);
}
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}
#define MDL_START
static void mdlStart(SimStruct *S)
{
const real_T * brdc = mxGetPr(ssGetSFcnParam(S,2));
//check if ip is a string else report error
if(brdc[0]==2||brdc[0]==1)
{
if (!mxIsChar(ssGetSFcnParam(S,0)) ||
(mxGetM(ssGetSFcnParam(S,0)) != 1 ) ) {
ssSetErrorStatus(S,"First Parameter must be a string");
return;
}
}
//Find Size of String
mwSize buflen= mxGetN(ssGetSFcnParam(S,0))*sizeof(mxChar)+1;
char* IP;
IP = (char*)mxMalloc(buflen);
//write the parameter to the string IP
mxGetString(ssGetSFcnParam(S,0),IP,buflen);
//get port from the second parameter
const real_T * port = mxGetPr(ssGetSFcnParam(S,1));
//Create and setdest of socket
UDPsocket * s= new UDPsocket();
s->create();
if(brdc[0]==3)
{
setsockopt(s->getsocket(),SOL_SOCKET,
SO_BROADCAST,"1",sizeof(char));
s->setdest("255.255.255.255",port[0]);
}
else
{
s->setdest(IP,port[0]);
}
25
//Deallocate the string formed with mxgetstring()
mxFree(IP);
//save socket to be used later in PWork vector
ssGetPWork(S)[0]=s;
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
int elements,size;
const char * tname;
//Get Socket from PWork vector
UDPsocket *s = static_cast<UDPsocket*>(ssGetPWork(S)[0]);
DTypeId inpt = ssGetInputPortDataType(S,0);
size = ssGetDataTypeSize(S,inpt);
elements = ssGetCurrentInputPortWidth(S,0);
size = elements*size;
tname = ssGetDataTypeName(S,inpt);
int_T id = ssGetDataTypeId(S,tname);
//Get Pointer to data from input port
boolean_T c = ssGetInputPortRequiredContiguous(S,0);
if(c)
{
real_T * ptr = (real_T*)ssGetInputPortSignal(S,0);
s->pack((void*)ptr,id,size);
}
else
{
InputPtrsType ptr = ssGetInputPortSignalPtrs(S,0);
switch(id+1)
{
case Socket::DOUBLE:
{
InputRealPtrsType u = (InputRealPtrsType)ptr;
s->pack((void*)*u,id,size);
break;
}
case Socket::SINGLE:
{
InputReal32PtrsType u = (InputReal32PtrsType)ptr;
26
s->pack((void*)*u,id,size);
break;
}
case Socket::INT8:
{
InputInt8PtrsType u = (InputInt8PtrsType)ptr;
s->pack((void*)*u,id,size);
break;
}
case Socket::UINT8:
{
InputUInt8PtrsType u = (InputUInt8PtrsType)ptr;
s->pack((void*)*u,id,size);
break;
}
case Socket::INT16:
{
InputInt16PtrsType u = (InputInt16PtrsType)ptr;
s->pack((void*)*u,id,size);
break;
}
case Socket::UINT16:
{
InputUInt16PtrsType u = (InputUInt16PtrsType)ptr;
s->pack((void*)*u,id,size);
break;
}
case Socket::INT32:
{
InputInt32PtrsType u = (InputInt32PtrsType)ptr;
s->pack((void*)*u,id,size);
break;
}
case Socket::UINT32:
{
InputUInt32PtrsType u = (InputUInt32PtrsType)ptr;
s->pack((void*)*u,id,size);
break;
}
case Socket::BOOLEAN:
{
InputBooleanPtrsType u = (InputBooleanPtrsType)ptr;
s->pack((void*)*u,id,size);
break;
}
}
27
}
}
static void mdlTerminate(SimStruct *S)
{
UDPsocket *s = static_cast<UDPsocket*>(ssGetPWork(S)[0]);
s->close();
delete s;
}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif
UDPReceive
#define S_FUNCTION_NAME UDPReceive_gen
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
#include <WinSock2.h>
#include <stdio.h>
#include "udpsocket.h"
#include <process.h>
template <class Unk>
void compile (char*messages,int sizes,Unk* &data)
{
byte *temp,*temp2,*temp3;
temp3 = new byte[sizes];
temp = (byte*)messages;
for (int i = 0; i<(sizes/sizeof(Unk)); i++)
{
temp2 = temp+12+i*sizeof(Unk);
memcpy(temp3+sizeof(Unk)*i,temp2,sizeof(Unk));
}
data = (Unk*)temp3;
//delete temp3;
}
28
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 5);
//Parameter 1:: IP address as string
//Parameter 2:: Port
//Parameter 3:: DataType 0-8
//Parameter 4:: Number of elements
//Parameter 5:: Broadcast type
// Parameter mismatch will be reported by Simulink
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}
const real_T * dtype = mxGetPr(ssGetSFcnParam(S,2));
const real_T * elem = mxGetPr(ssGetSFcnParam(S,3));
if (!ssSetNumInputPorts(S, 0)) return;
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, elem[0]);
ssSetOutputPortDataType(S,0,(dtype[0]-1));
ssSetNumSampleTimes(S, 1);
// Reserve place for C++ object
ssSetNumPWork(S, 1);
ssSetOptions(S,0);
}
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}
#define MDL_START
static void mdlStart(SimStruct *S)
{
//check if ip is a string else report error
if (!mxIsChar(ssGetSFcnParam(S,0)) ||
(mxGetM(ssGetSFcnParam(S,0)) != 1 ) ) {
ssSetErrorStatus(S,"First Parameter must be a string");
29
return;
}
//Find Size of String
mwSize buflen= mxGetN(ssGetSFcnParam(S,0))*sizeof(mxChar)+1;
char* IP;
IP = (char*)mxMalloc(buflen);
//write the parameter to the string IP
mxGetString(ssGetSFcnParam(S,0),IP,buflen);
//get port from the second parameter
const real_T * port = mxGetPr(ssGetSFcnParam(S,1));
//get broadcast type
const real_T * brdc = mxGetPr(ssGetSFcnParam(S,4));
UDPsocket *s = new UDPsocket();
if(s->create())
{
s->close();
ssPrintf("Error on createn");
system ("PAUSE");
}
if(s->bind(port[0]))
{
s->close();
ssPrintf("error on bindn");
system ("PAUSE");
}
int btype = (int)brdc[0];
switch(btype)
{
case 1:
{
if(s->joinmulticast(IP))
{
ssPrintf("Error on joinmulticastn");
system ("PAUSE");
s->close();
}
break;
}
case 3:
{
setsockopt(s->getsocket(),SOL_SOCKET,SO_BROADCAST,"1",sizeof(char));
break;
}
30
}
mxFree(IP);
s->startthread();
ssGetPWork(S)[0]=s;
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
UDPsocket *s = static_cast<UDPsocket*>(ssGetPWork(S)[0]);
char message[2000];
int message_len=0;
int size=0, type=0;
s->getdata(message,size,type,message_len);
if(message_len >0&&size>0)
{
switch(type+1)
{
case Socket::DOUBLE:
{
real_T * data = new real_T[size/sizeof(real_T)];
compile(message,size,data);
real_T *y =(real_T*)ssGetOutputPortSignal(S,0);
memcpy(y, data, size);
delete data;
break;
}
case Socket::SINGLE:
{
real32_T * data = new real32_T[size/sizeof(real32_T)];
compile(message,size,data);
real32_T *y = (real32_T*)ssGetOutputPortSignal(S,0);
memcpy(y, data, size);
delete data;
break;
}
31
case Socket::INT8:
{
int8_T *data = new int8_T[size/sizeof(int8_T)];
compile(message,size,data);
int8_T *y = (int8_T*)ssGetOutputPortSignal(S,0);
memcpy(y, data, size);
delete data;
break;
}
case Socket::UINT8:
{
uint8_T *data = new uint8_T[size/sizeof(uint8_T)];
compile(message,size,data);
uint8_T *y = (uint8_T*)ssGetOutputPortSignal(S,0);
memcpy(y, data, size);
delete data;
break;
}
case Socket::INT16:
{
int16_T *data = new int16_T[size/sizeof(int16_T)];
compile(message,size,data);
int16_T *y = (int16_T*)ssGetOutputPortSignal(S,0);
memcpy(y, data, size);
delete data;
break;
}
case Socket::UINT16:
{
uint16_T *data = new uint16_T[size/sizeof(uint16_T)];
compile(message,size,data);
uint16_T *y = (uint16_T*)ssGetOutputPortSignal(S,0);
memcpy(y, data, size);;
delete data;
break;
}
case Socket::INT32:
{
int32_T *data = new int32_T[size/sizeof(int32_T)];
compile(message,size,data);
int32_T *y = (int32_T*)ssGetOutputPortSignal(S,0);
memcpy(y, data, size);
delete data;
break;
}
case Socket::UINT32:
{
uint32_T *data = new uint32_T[size/sizeof(uint32_T)];
32
compile(message,size,data);
uint32_T *y = (uint32_T*)ssGetOutputPortSignal(S,0);
memcpy(y, data, size);
delete data;
break;
}
case Socket::BOOLEAN:
{
boolean_T *data = new boolean_T[size/sizeof(boolean_T)];
compile(message,size,data);
boolean_T *y = (boolean_T*)ssGetOutputPortSignal(S,0);
memcpy(y, data, size);
delete data;
break;
}
}
}
}
static void mdlTerminate(SimStruct *S)
{
UDPsocket *s = static_cast<UDPsocket*>(ssGetPWork(S)[0]);
s->endthread();
s->closethread();
s->close();
delete s;
}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif
33

More Related Content

Viewers also liked

Actividad: Soy yo, es mi autorretrato
Actividad: Soy yo, es mi autorretratoActividad: Soy yo, es mi autorretrato
Actividad: Soy yo, es mi autorretrato
Norma Soria Espriella
 
Lantana Reserve
Lantana ReserveLantana Reserve
Lantana Reserve
mike_walker
 
Неслышащий да увидит
Неслышащий да увидитНеслышащий да увидит
Неслышащий да увидит
Moscow Digital
 
Europe changes the world magazine assignment
Europe changes the world   magazine assignmentEurope changes the world   magazine assignment
Europe changes the world magazine assignmentHeatherP
 
2016 West Region Accounting Meeting
2016 West Region Accounting Meeting2016 West Region Accounting Meeting
2016 West Region Accounting Meeting
Tayah Lin Butler, MBA
 
TO Mentor Training
TO Mentor TrainingTO Mentor Training
TO Mentor Training
janestrohm
 
Testes unitários como ferramentas de design de código
Testes unitários como ferramentas de design de códigoTestes unitários como ferramentas de design de código
Testes unitários como ferramentas de design de código
Paula Grangeiro
 
Project Experience3
Project Experience3Project Experience3
Project Experience3ajith k
 
Asia lr survey for sharing
Asia lr survey for sharingAsia lr survey for sharing
Asia lr survey for sharing
SUN Civil Society Network
 
Stratégie Responsabilité Sociétale des Entreprises (RSE) et marchés publics
Stratégie Responsabilité Sociétale des Entreprises (RSE) et marchés publics Stratégie Responsabilité Sociétale des Entreprises (RSE) et marchés publics
Stratégie Responsabilité Sociétale des Entreprises (RSE) et marchés publics
Frédéric Grevey
 
Literacy rate and culture no whatch saying
Literacy rate and culture  no whatch sayingLiteracy rate and culture  no whatch saying
Literacy rate and culture no whatch saying
marypardee
 
數位廣告媒體企劃與配置Part 1
數位廣告媒體企劃與配置Part 1數位廣告媒體企劃與配置Part 1
數位廣告媒體企劃與配置Part 1
MinMax Digital Consulting 關鍵數位行銷
 
La responsabilité sociale et environnementale des entreprises
La responsabilité sociale et environnementale des entreprisesLa responsabilité sociale et environnementale des entreprises
La responsabilité sociale et environnementale des entreprises
Institut de recherche sur la Résolution Non-violente des Conflits
 
Eurpean Exploration And Empire Building
Eurpean Exploration And Empire BuildingEurpean Exploration And Empire Building
Eurpean Exploration And Empire BuildingHeatherP
 
Office365 groups from the ground up - SPTechCon Boston
Office365 groups from the ground up - SPTechCon BostonOffice365 groups from the ground up - SPTechCon Boston
Office365 groups from the ground up - SPTechCon Boston
Drew Madelung
 
How to conduct an anti-money laundering (AML) system assessment
How to conduct an anti-money laundering (AML) system assessmentHow to conduct an anti-money laundering (AML) system assessment
How to conduct an anti-money laundering (AML) system assessment
Keith Furst
 
Projet pilote office 365
Projet pilote office 365Projet pilote office 365
Projet pilote office 365
Odile Dupont
 

Viewers also liked (20)

Actividad: Soy yo, es mi autorretrato
Actividad: Soy yo, es mi autorretratoActividad: Soy yo, es mi autorretrato
Actividad: Soy yo, es mi autorretrato
 
THE COTTON ROAD - FOLDER
THE COTTON ROAD - FOLDERTHE COTTON ROAD - FOLDER
THE COTTON ROAD - FOLDER
 
Lantana Reserve
Lantana ReserveLantana Reserve
Lantana Reserve
 
Неслышащий да увидит
Неслышащий да увидитНеслышащий да увидит
Неслышащий да увидит
 
Europe changes the world magazine assignment
Europe changes the world   magazine assignmentEurope changes the world   magazine assignment
Europe changes the world magazine assignment
 
2016 West Region Accounting Meeting
2016 West Region Accounting Meeting2016 West Region Accounting Meeting
2016 West Region Accounting Meeting
 
TO Mentor Training
TO Mentor TrainingTO Mentor Training
TO Mentor Training
 
Testes unitários como ferramentas de design de código
Testes unitários como ferramentas de design de códigoTestes unitários como ferramentas de design de código
Testes unitários como ferramentas de design de código
 
Project Experience3
Project Experience3Project Experience3
Project Experience3
 
Portfolio Samples
Portfolio SamplesPortfolio Samples
Portfolio Samples
 
Asia lr survey for sharing
Asia lr survey for sharingAsia lr survey for sharing
Asia lr survey for sharing
 
Stratégie Responsabilité Sociétale des Entreprises (RSE) et marchés publics
Stratégie Responsabilité Sociétale des Entreprises (RSE) et marchés publics Stratégie Responsabilité Sociétale des Entreprises (RSE) et marchés publics
Stratégie Responsabilité Sociétale des Entreprises (RSE) et marchés publics
 
Literacy rate and culture no whatch saying
Literacy rate and culture  no whatch sayingLiteracy rate and culture  no whatch saying
Literacy rate and culture no whatch saying
 
數位廣告媒體企劃與配置Part 1
數位廣告媒體企劃與配置Part 1數位廣告媒體企劃與配置Part 1
數位廣告媒體企劃與配置Part 1
 
La responsabilité sociale et environnementale des entreprises
La responsabilité sociale et environnementale des entreprisesLa responsabilité sociale et environnementale des entreprises
La responsabilité sociale et environnementale des entreprises
 
Eurpean Exploration And Empire Building
Eurpean Exploration And Empire BuildingEurpean Exploration And Empire Building
Eurpean Exploration And Empire Building
 
【MMdc 分享】消費行為分析_SmartM 電子商務行銷X開店菁英班
【MMdc 分享】消費行為分析_SmartM 電子商務行銷X開店菁英班【MMdc 分享】消費行為分析_SmartM 電子商務行銷X開店菁英班
【MMdc 分享】消費行為分析_SmartM 電子商務行銷X開店菁英班
 
Office365 groups from the ground up - SPTechCon Boston
Office365 groups from the ground up - SPTechCon BostonOffice365 groups from the ground up - SPTechCon Boston
Office365 groups from the ground up - SPTechCon Boston
 
How to conduct an anti-money laundering (AML) system assessment
How to conduct an anti-money laundering (AML) system assessmentHow to conduct an anti-money laundering (AML) system assessment
How to conduct an anti-money laundering (AML) system assessment
 
Projet pilote office 365
Projet pilote office 365Projet pilote office 365
Projet pilote office 365
 

Similar to UDP Report

WiMAX implementation in ns3
WiMAX implementation in ns3WiMAX implementation in ns3
WiMAX implementation in ns3
Mustafa Khaleel
 
Cnd labguide
Cnd labguideCnd labguide
Cnd labguide
Yahye159
 
An Introduction to OMNeT++ 6.0
An Introduction to OMNeT++ 6.0An Introduction to OMNeT++ 6.0
An Introduction to OMNeT++ 6.0
Alpen-Adria-Universität
 
ESL report
ESL reportESL report
ESL report
Express News
 
Network Analyzer and Report Generation Tool for NS-2 using TCL Script
Network Analyzer and Report Generation Tool for NS-2 using TCL ScriptNetwork Analyzer and Report Generation Tool for NS-2 using TCL Script
Network Analyzer and Report Generation Tool for NS-2 using TCL Script
IRJET Journal
 
Google app engine
Google app engineGoogle app engine
Google app engine
Suraj Mehta
 
The Network Ip Address Scheme
The Network Ip Address SchemeThe Network Ip Address Scheme
The Network Ip Address Scheme
Erin Rivera
 
Network simulator 2 a simulation tool for linux
Network simulator 2 a simulation tool for linuxNetwork simulator 2 a simulation tool for linux
Network simulator 2 a simulation tool for linux
Pratik Joshi
 
Dsp lab manual 15 11-2016
Dsp lab manual 15 11-2016Dsp lab manual 15 11-2016
Dsp lab manual 15 11-2016
Gopinath.B.L Naidu
 
NP-lab-manual.docx
NP-lab-manual.docxNP-lab-manual.docx
NP-lab-manual.docx
RaviRajput416403
 
NP-lab-manual (1).pdf
NP-lab-manual (1).pdfNP-lab-manual (1).pdf
NP-lab-manual (1).pdf
RaviRajput416403
 
NP-lab-manual.pdf
NP-lab-manual.pdfNP-lab-manual.pdf
NP-lab-manual.pdf
RaviRajput416403
 
Mini Project- Dual Processor Computation
Mini Project- Dual Processor ComputationMini Project- Dual Processor Computation
IT6511 Networks Laboratory
IT6511 Networks LaboratoryIT6511 Networks Laboratory
IT6511 Networks Laboratory
gayathridevprasad
 
Rodrigo Almeida - Microkernel development from project to implementation
Rodrigo Almeida - Microkernel development from project to implementationRodrigo Almeida - Microkernel development from project to implementation
Rodrigo Almeida - Microkernel development from project to implementation
Felipe Prado
 
Computernetworkingkurosech9 091011003335-phpapp01
Computernetworkingkurosech9 091011003335-phpapp01Computernetworkingkurosech9 091011003335-phpapp01
Computernetworkingkurosech9 091011003335-phpapp01AislanSoares
 
Project final report
Project final reportProject final report
Project final report
ALIN BABU
 

Similar to UDP Report (20)

WiMAX implementation in ns3
WiMAX implementation in ns3WiMAX implementation in ns3
WiMAX implementation in ns3
 
GCF
GCFGCF
GCF
 
Cnd labguide
Cnd labguideCnd labguide
Cnd labguide
 
An Introduction to OMNeT++ 6.0
An Introduction to OMNeT++ 6.0An Introduction to OMNeT++ 6.0
An Introduction to OMNeT++ 6.0
 
ESL report
ESL reportESL report
ESL report
 
Network Analyzer and Report Generation Tool for NS-2 using TCL Script
Network Analyzer and Report Generation Tool for NS-2 using TCL ScriptNetwork Analyzer and Report Generation Tool for NS-2 using TCL Script
Network Analyzer and Report Generation Tool for NS-2 using TCL Script
 
Cisco project ideas
Cisco   project ideasCisco   project ideas
Cisco project ideas
 
Google app engine
Google app engineGoogle app engine
Google app engine
 
The Network Ip Address Scheme
The Network Ip Address SchemeThe Network Ip Address Scheme
The Network Ip Address Scheme
 
Brandtzaeg master
Brandtzaeg masterBrandtzaeg master
Brandtzaeg master
 
Network simulator 2 a simulation tool for linux
Network simulator 2 a simulation tool for linuxNetwork simulator 2 a simulation tool for linux
Network simulator 2 a simulation tool for linux
 
Dsp lab manual 15 11-2016
Dsp lab manual 15 11-2016Dsp lab manual 15 11-2016
Dsp lab manual 15 11-2016
 
NP-lab-manual.docx
NP-lab-manual.docxNP-lab-manual.docx
NP-lab-manual.docx
 
NP-lab-manual (1).pdf
NP-lab-manual (1).pdfNP-lab-manual (1).pdf
NP-lab-manual (1).pdf
 
NP-lab-manual.pdf
NP-lab-manual.pdfNP-lab-manual.pdf
NP-lab-manual.pdf
 
Mini Project- Dual Processor Computation
Mini Project- Dual Processor ComputationMini Project- Dual Processor Computation
Mini Project- Dual Processor Computation
 
IT6511 Networks Laboratory
IT6511 Networks LaboratoryIT6511 Networks Laboratory
IT6511 Networks Laboratory
 
Rodrigo Almeida - Microkernel development from project to implementation
Rodrigo Almeida - Microkernel development from project to implementationRodrigo Almeida - Microkernel development from project to implementation
Rodrigo Almeida - Microkernel development from project to implementation
 
Computernetworkingkurosech9 091011003335-phpapp01
Computernetworkingkurosech9 091011003335-phpapp01Computernetworkingkurosech9 091011003335-phpapp01
Computernetworkingkurosech9 091011003335-phpapp01
 
Project final report
Project final reportProject final report
Project final report
 

UDP Report

  • 1. Summer Internship 2010 Development of a MATLAB/Simulink - Toolbox for Distributed Simulation Author: James Dianics Supervisor: Prof. Dr.-Ing. Reinhard Finsterwalder July 30, 2010
  • 2. Abstract This report gives an overview of the development of a distributed simulation toolbox for Matlab/Simulink. The project was developed as a sub-project to the MASTER program which is designed to be a student built flight simulator for education and research. The model dynamics for the flight simulator has been built and implemented in the Mat- lab/Simulink environment. A toolbox to allow for the real time communication between systems is necessary. This project specifically is to build the UDP solution of the dis- tributed simulation toolbox which will contain the ability to transmit via Singlecast, Multicast and Broadcast. The creation of the toolbox was accomplished in two phases; the development of test applications in C++, and then the development of the UDPSend and UDPReceive S-functions for Matlab.
  • 3. Contents 1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.1 Project MASTER . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 Distributed Simulation . . . . . . . . . . . . . . . . . . . . . . . . 2 1.3 Universal Datagram Protocol (UDP) . . . . . . . . . . . . . . . . 2 2 Programming UDP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 C++ Test Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 3.1 Developed Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.2 Sample Server Application in C++ . . . . . . . . . . . . . . . . . 8 4 Matlab/Simulink Toolbox . . . . . . . . . . . . . . . . . . . . . . . . . . 10 4.1 Outline of UDPSend S-Function . . . . . . . . . . . . . . . . . . . 11 4.2 Outline of UDPReceive S-Function . . . . . . . . . . . . . . . . . 12 4.3 Creating a Library of S-Function Blocks . . . . . . . . . . . . . . 13 4.4 Masking the Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . 14 4.5 Example Simulink Models using Distributed Simulation Toolbox . 16 5 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 6 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 7 Appendix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 7.1 socket.h and socket.cpp . . . . . . . . . . . . . . . . . . . . . . . . 18 7.2 udpsocket.h and udpsocket.cpp . . . . . . . . . . . . . . . . . . . 20 7.3 S-Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 1
  • 4. 1 Introduction 1.1 Project MASTER The MASTER project was started in 2001 at the University of the Federal Armed Forces Munich, Germany. The purpose of the MASTER project is the development of a modular vehicle simulator with exchangeable cockpit modules for education and research appli- cation. Thus ”MASTER” is an acronym which stands for Modular Advanced Simulator Technology for Education and Research. MASTER has been structured so that the ma- jority of the work will be accomplished by student projects. 1.2 Distributed Simulation In the development of a large simulation or application a single computer’s resources are often insufficient. Distributed computing allows for either parallel computing on a single machine with multiple cores or among many nodes in a network; either solution provides an increased amount of hardware resources resulting in better application performance. 1.3 Universal Datagram Protocol (UDP) There are two commonly used communication protocols, Transmission Control Protocol (TCP) and Universal Datagram Protocol (UDP). TCP is commonly used for streaming data between two clients such as a web browser and web server. The main points of TCP that were of a concern are that TCP utilizes error checking and creates a buffer waiting for delayed data before releasing the packet, both of these functions delay the speed of the data but give a more reliable signal. UDP does not utilize error checking and by definition is unreliable. This attribute can be beneficial if used correctly because it allows for less signal delay because of the lack of processing on the network that needs to be done before receiving a signal. One must be careful about its application and understand that packets could be missing, duplicated or arrive out of order. Another benefit of UDP is that it is capable of Singlecast, Multicast, and Broadcast transmissions where as TCP is only capable of Singlecast. Singlecast is the typical single client single server transmission. Multicast is located on a different IP range and theoretically a single client can send a message to an unlimited number of listening servers. UDP is best used during real-time applications where speed is required. This could be during VoIP, IP-TV or applications such as Skype where lost packets could mean a smear in the picture but the overall quality of the picture shall remain good if the connection is decent. UDP was chosen for the MASTER project because of the need for real-time communication and varying transmission capabilities. 2
  • 5. Figure 1: Route Sequences Potential Receivers(Yellow) Figure 2: Singlecast Figure 3: Multicast Figure 4: Broadcast 2 Programming UDP Windows sockets 2 (Winsock2) is an API that allows for programmers to easily create networking functions for applications. In order to create networking ability only a few windows socket functions are necessary. struct WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); WSADATA is a structure that is required to define the functionality of the windows socket and the function WSAStartup takes a pointer to the structure and initializes the socket in the windows operating system. This is necessary for every socket ran on a windows system. When the socket is closed conversely WSACleanup(); needs to be used to delete and free the socket on the windows system. 3
  • 6. To create a socket a call s = socket(AF_INET,SOCK_DGRAM,0); Where AF INET is the address family associated with TCP and UDP type protocols. SOCK DGRAM is a connectionless type protocol for UDP transmission. Thus the socket being created here is defined for UDP connectionless use. To set where the socket is listening(server side) or where the socket is sending datagrams (client side) the SOCKADDR IN structure needs to be defined. memset (&addr,0,sizeof(SOCKADDR_IN)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr=inet_addr(IP); Where the memory at the structures location is cleared and set with the family, port, and IP address in that respective order. To accomplish communication there are four basic functions for TCP and UDP. TCP utilizes connections and thus uses different functions for sending and receiving data send() and recv() UDP is connectionless and uses sendto() and recvfrom() because the client and server is not strictly defined before this function. sendto ( s , buffer , sizeof ( buffer ) , 0 ,(SOCKADDR∗)&addr , sizeof (SOCKADDR IN) ) ; recvfrom ( s , buffer , sizeof ( buffer ) ,0 ,NULL,NULL) ; When finished with the socket use closesocket(s); Combined together this would be the most basic of UDP programming required to get a simple application running using Winsock2. 4
  • 7. 3 C++ Test Application Before the development of the Matlab/Simulink distributed simulation toolbox two test applications were built using Microsoft’s Visual C++ application development studio. The applications were designed to meet the requirements that needed to be met in the Matlab environment. Requirements for the Client • The client shall utilize UDP protocol • The client shall send arrays of data • The client shall be able to send all data in byte format • The client shall be able to send Singlecast, Multicast and Broadcast transmissions • The client shall be able to send in real-time Requirements for the Server • The server shall utilize UDP protocol. • The server shall receive datagram packets and be able to unpack them into a spec- ified data type. • The server shall be able to join Multicast groups. • The server shall be able to receive Singlecast and Broadcast Transmissions. • The server shall be able to receive transmission in real-time Requirements for packet transmission protocol • The packet shall contain a 3 integer header in byte format. • The header shall contain information about the size of the packet, the data type of the data contained and the number of elements contained in the array being sent or received. • Preceding the header the data array shall be contained in a byte format. Figure 5: Packet Protocol 5
  • 8. Data types that the classes currently support were included due to their definition by Matlab/Simulink Figure 6: Matlab/Simulink Data Types Two classes were developed to handle the socket and UDP functions to meet the require- ments of the project. Two classes were developed so that a TCPsocket class could later be developed extending the socket class. 6
  • 9. 3.1 Developed Classes Figure 7: Class Diagram Use of the two classes to develop a UDP server or client is fairly straightforward. The socket class defines two socket structures and stores them as protected variables. • addr • s The socket class also contains two functions. • bind(): Connect the socket to a port • close(): Closes a socket The udpsocket class utilizes the windows socket functions and the developed protocol to send and receive data • create(): Creates a udpsocket object • setdest(): Sets the destination port and IP • joinmulticast(): Joins a multi-cast group at a specific IP • pack(): packs an array of data into the previously discussed protocol • send(): Sends a package on the udpsocket • startthread(): Sets a parameter to prepare for receivethread • receivethread(): starts another thread to fill data buffers from the incoming signal 7
  • 10. • getdata(): returns the data from the receivethread() function, size, type, elements, and package • endthread(): prepares the thread for closing and deleting • closethread(): closes the thread • getaddr(): gets the SOCKADDR IN structure from the socket class The template function compile accepts an unknown data type to convert the UDP pro- tocol byte form back to a designated data type (float, int, etc...) template <class Unk> void compile (char*message,int size,Unk* &data) { byte *temp,*temp2,*temp3; temp3 = new byte[size]; temp = (byte*)message; for (int i = 0; i<(size/sizeof(Unk)); i++) { temp2 = temp+12+i*sizeof(Unk); memcpy(temp3+sizeof(Unk)*i,temp2,sizeof(Unk)); } data = (Unk*)temp3; 3.2 Sample Server Application in C++ All of this is complied into the main thread to make an example server in c++... int main (int argc, char *argv[]) { printf("UDP servern"); UDPsocket s; char message[256]; int size,type; if(s.create()) { s.close(); printf("Error on createn"); return 1; } if(s.bind()) { 8
  • 11. s.close(); printf("error on bindn"); system ("PAUSE"); return 1; } if(s.joinmulticast()) { printf("Error on joinmulticastn"); s.close(); return 1; } Here the UDPsocket object is created and the required variables are declared to obtain a message and compile it. The socket is created, bound, and joined to a multi-cast IP all with error checking. Next the receivethread function is intialized with the startthread() function call and a while loop is ran to get data from the buffers. s.startthread(); s.getdata(message,size,type,message_len) if(message_len>0&&size>0) { switch(type) { case INT: { int * data = new int[size/sizeof(int)]; compile(message,size,data); for(int i = 0;i<size/sizeof(int);i++) {printf("%in",data[i]); cout << data[i] << endl; } delete data; break; } If the message length is greater than 0 (meaning that a message has been received) a switch structure is used to determine the data type based on the type received and the data is compiled and read out. The data type has been enumerated in the socket class. s.endthread(); s.closethread(); s.close(); 9
  • 12. When the server is finished the thread listening on the socket is ended and closed and the socket is then closed. 4 Matlab/Simulink Toolbox MATLAB is a well known and widely used technical computing software package. To- gether with Simulink one can simulate and do model-based design for multi domain sys- tems. To allow for the communication of multiple computers in the Matlab and Simulink environment the C++ test applications were translated into S-functions. S-functions in general are a computer language description of a single Simulink block. S-functions can be written in many languages ( C++, C, Fortran etc) and then compiled into a MEX (Matlab Executable) file which is implemented in Simulink. Understanding how Simulink and S-functions work is important when beginning to build a Simulink block. In a very simple explanation the block accepts at every time step, calculates a result, and sends an output. Figure 8: Simulink Engine 10
  • 13. Every S - Function follows a strict structure the most basic template includes these 4 main functions. static void m d l I n i t i a l i z e S i z e s ( SimStruct ∗S)} static void mdlInitializeSampleTimes ( SimStruct ∗S) static void mdlStart ( SimStruct ∗S) static void mdlOutputs ( SimStruct ∗S) static void mdlTerminate ( SimStruct ∗S) 4.1 Outline of UDPSend S-Function mdlInitializeSizes 1. Set the number of parameters(3 for the send block) 2. Set the input port width and data type (1 input with inherited width and data type) 3. Set number of output ports (0 outputs) mdlInitializeSampleTimes 1. Set sample times mdlStart 1. Get parameters from the block 2. Create a UDPsocket object 3. Based upon parameters set the destination to send the data 4. Save the socket in the PWork Vector for later use mdlOutputs 1. Get UDPsocket object from PWork Vector 2. Based upon data type pack and send the data mdlTerminate 1. Get UDPsocket object from PWork vector 2. Close and delete the socket 11
  • 14. Every S-function has inputs and outputs which are defined during the initialization. With the UDPsend block it is initialized to have a single input with data type and width inherited from the driving block. MDLstart is only ran at the beginning of the simulation here is where the socket is opened and set using the parameters provided by the user. The output function will be ran at every time step and is being used to send the data from. Terminate is only ran at the end of the simulation and this is where we simply close and delete the UDP socket object from memory. 4.2 Outline of UDPReceive S-Function mdlInitializeSizes 1. Set the number of parameters (5 for the receive block) 2. Set the input port width and data type (0 inputs) 3. Set number of output ports (1 output) 4. Set OutputPortWidth with the Elements parameter 5. Set OutputPortDataType withe the Data Type parameter mdlInitializeSampleTimes 1. Set sample times mdlStart 1. Get parameters from the block and check if the IP parameter is a string 2. Create a UDPsocket object 3. Bind the socket to the port based on the parameter 4. Based upon a parameter join a Multicast group or listen on broadcast 5. start the receivethread with s.startthread() function 6. Save the socket in the PWork Vector for later use mdlOutputs 1. Get UDPsocket object from PWork Vector 2. s.getdata(message,size,type,message length) to gather data 3. If a message is received use a switch structure on type to compile 4. obtain pointer to the output port real T *y = (real T*)ssGetOutputPortSignal(S,0) 5. copy the compiled data to the output port 12
  • 15. mdlTerminate 1. Get UDPsocket object from PWork vector 2. s.endthread() 3. s.closethread() 4. Close and delete the socket 4.3 Creating a Library of S-Function Blocks Before a S-function can be used it needs to be compiled into a MEX file. This requires linking all of the necessary files so that Matlab can create an executable for its environ- ment. In the Matlab command prompt compile the send and receive functions developed during this project using the following two commands. • mex UDPSend.cpp udpsocket.cpp WS2 32.lib socket.cpp • mex UDPReceive.cpp udpsocket.cpp WS2 32.lib socket.cpp Once successfully compiled in the Matlab environment a library can easily be built. 1. Open a new simulink model 2. Add two new S-functions to the model from the User-Defined Functions library 3. Open the S-function parameters by double clicking 4. Under S-Function name: insert UDPSend in one and UDPReceive in the other 5. Select File ... New ... Library 6. Drag both created S-Functions to the new library 7. Save the Library file (.mdl) in its on folder in the Matlab path 8. In this new folder create a new .m file ”slblocks” The slblocks.m file gives Simulink a reference of how label and use the library. In a short example it tells it what folder the files are in and how to name the library. function blkStruct = slblocks % Specify that the product should appear in the library browser % and be cached in its repository Browser.Library = ’UDPCommBlocks’; Browser.Name = ’UDP Communication Blocks’; blkStruct.Browser = Browser; Is all that is necessary to be included in the .m file. 13
  • 16. 4.4 Masking the Blocks To add a mask to the block open the .mdl library file created holding the blocks 1. Unlock the Library by selecting Edit ... Unlock Library in the library window 2. right click on the block and select Mask S-Function... 3. Proceed to the Parameters tab 4. Add a new Parameter • Prompt is the title that will show up in the mask • Variable is the variable that will be passed to the S-Function • Type is the type of input from the user 5. Once all parameters are defined in the mask they need to be passed to the S- Function 6. Right click again on the block and select Look Under Mask 7. Add the parameter variables to the parameters list 8. block description and other documentation can be handled within the other tabs 14
  • 17. Figure 9: S-Function Mask Editor Figure 10: S-Functions Parameters 15
  • 18. 4.5 Example Simulink Models using Distributed Simulation Tool- box Figure 11: S-Function UDPSend - Transmitting position and orientation data from the flight model to the visualization engine 16
  • 19. Figure 12: S-Function UDPReceive - Receiving position and orientation data in the visualization engine 5 Results A Matlab/Simulink Distributed Simulation Toolbox was successfully developed using the UDP transmission protocol. The send and receive blocks are able to send arrays of all Matlab data types using Singlecast, Multicast or Broadcast transmissions. Some problems arose while writing the receive S-Function from the developed C++ test ap- plication. Originally a blocking socket was used to receive data in the test application but would crash Simulink when implemented as a S-Function. As a temporary solution a non-blocking socket was used to successfully complete the S-Function. While testing the S- Function, strange behavior was observed where data was still is received after the send model had stopped running; this was attributed to the non-blocking socket building a buffer on the network. The final solution was found by creating a separate thread to operate a blocking socket that would listen for incoming messages, this thread could run continuously without delaying Simulink and is the final successful solution. The distributed simulation toolbox could be further improved by also implementing other net- work protocols into separate blocks, notably TCP could be useful in other applications where error checking is necessary. The UDP blocks could also be improved by adding the ability to send structures or user created data types. 17
  • 20. 6 References Anonymous (2010). Writing S-Functions. The Mathworks Inc., Natick, USA. Anonymous (2010). MathWorks - MATLAB and Simulink for Technical Computing. <http://www.mathworks.com/>. Anonymous (2010). Windows Sockets 2 [online]. <http://msdn.microsoft.com/enus/ library/ms740673(VS.85).aspx>. 7 Appendix 7.1 socket.h and socket.cpp socket.h #ifndef SOCKET H #define SOCKET H #include <winsock2 . h> #include <ws2tcpip . h> c l a s s Socket { public : enum datatype { DOUBLE = 1 , SINGLE = 2 , BOOLEAN = 9 , INT8 =3, UINT8=4, INT16 = 5 , UINT16 = 6 , INT32 = 7 , UINT32 = 8 , }; Socket ( ) ; ˜ Socket ( ) ; int c l o s e ( ) ; int bind ( int port =12345); protected : 18
  • 21. SOCKET s ; SOCKADDR IN addr ; }; #endif socket.cpp #include ” socket . h” Socket : : Socket () { WSADATA wsaData ; WSAStartup(MAKEWORD(2 ,2) ,& wsaData ) ; } Socket : : ˜ Socket () { WSACleanup ( ) ; } int Socket : : c l o s e () { i f ( clos esocket ( s)==SOCKET ERROR) { return 1; } return 0; } int Socket : : bind ( int port ) { memset (&addr ,0 , sizeof (SOCKADDR IN) ) ; addr . s in fa mi ly = AF INET; addr . sin port = htons ( port ) ; addr . sin addr . s addr=INADDR ANY; i f ( : : bind ( s , (SOCKADDR∗)&addr , sizeof (SOCKADDR IN)) == SOCKET ERROR) { return 1; } return 0; } 19
  • 22. 7.2 udpsocket.h and udpsocket.cpp udpsocket.h #ifndef UDPSOCKET H #define UDPSOCKET H #include ” socket . h” #include <windows . h> #include <process . h> c l a s s UDPsocket : public Socket { public : UDPsocket ( ) ; ˜UDPsocket ( ) ; int create ( ) ; SOCKADDR IN getaddr (){ return addr ;} SOCKET getsocket (){ return s ; } int joinmulticast (char∗ IP=” 2 2 6 . 0 . 0 . 1 ” ) ; void setdest (char∗ IP=” 2 2 6 . 0 . 0 . 1 ” , int port = 12345); int send ( void∗ buffer , int b u f f e r l e n ) ; unsigned char∗ pack ( void∗ number , int type , int s i z e ) ; static long WINAPI receivethread (LPVOID Param ) ; void getdata (char ∗msg , int &size , int &type , int &msg len ) ; void startthread ( ) ; void endthread ( ) ; void closethread ( ) ; private : }; #endif udpsocket.cpp #include "UDPsocket.h" #include "simstruc.h" SOCKET s = INVALID_SOCKET; int g_message_len=0,g_size=0,g_type=0; char g_buffer[2000]; HANDLE rthread=0; int param; UDPsocket::UDPsocket () { } 20
  • 23. UDPsocket::~UDPsocket () { } int UDPsocket::create () { s = socket(AF_INET, SOCK_DGRAM,0); ::s=s; if (s==INVALID_SOCKET) { return 1; } return 0; } int UDPsocket::joinmulticast(char* IP) { struct ip_mreq mreq; memset (&mreq,0,sizeof(IP_MREQ)); mreq.imr_interface.s_addr = INADDR_ANY; mreq.imr_multiaddr.s_addr = inet_addr(IP); if(setsockopt (s,IPPROTO_IP,IP_ADD_MEMBERSHIP, (const char*)&mreq,sizeof(IP_MREQ)) == SOCKET_ERROR) { return 1; } return 0; } void UDPsocket::setdest(char* IP, int port) { memset (&addr,0,sizeof(SOCKADDR_IN)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr=inet_addr(IP); } int UDPsocket::send(void* buffer, int bufferlen) { sendto(s,(char*)buffer,bufferlen,0,(SOCKADDR*) &addr,sizeof(SOCKADDR_IN)); return 0; } unsigned char* UDPsocket::pack(void* number,int type,int size) { int x; switch(type) { 21
  • 24. case Socket::DOUBLE: {x = sizeof(real_T); break; } case Socket::SINGLE: {x = sizeof(real32_T); break; } case Socket::BOOLEAN: { x = sizeof(boolean_T); break; } case Socket::INT8: { x = sizeof(int8_T); break; } case Socket::UINT8: { x = sizeof(uint8_T); break; } case Socket::INT16: { x = sizeof(int16_T); break; } case Socket::UINT16: { x = sizeof(uint16_T); break; } case Socket::INT32: { x = sizeof(int32_T); break; } case Socket::UINT32: { x = sizeof(uint32_T); break; } } size = size + 12; byte* packet = new byte[size]; byte* total,*elements,*typ; int e = (size-12)/x; 22
  • 25. elements = (byte*)&e; total = (byte*)&size; typ = (byte*)&type; memcpy(packet,total,sizeof(int)); memcpy(packet+sizeof(int),elements,sizeof(int)); memcpy(packet+2*sizeof(int),typ,sizeof(int)); for(int i = 0;i<e;i++) { byte* temp; temp = (byte*)number+x*i; memcpy(packet+(sizeof(int)*3)+(i*x),temp,x); } send(packet,size); return packet; } long WINAPI UDPsocket::receivethread(LPVOID Param) { while(param==1) { if(::s!=INVALID_SOCKET) { g_message_len = recvfrom(::s,g_buffer, sizeof(g_buffer),0,NULL,NULL); int * package = (int*)g_buffer; g_size = package[0]-12; g_type = package[2]; } } g_message_len = 0; g_size = 0; g_type = 0; return 0; } void UDPsocket::getdata(char *msg, int &size, int &type, int &msg_len) { memcpy(msg,g_buffer,g_message_len); size = g_size; type = g_type; msg_len = g_message_len; } void UDPsocket::startthread() { param =1; rthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) receivethread,&param,0,NULL); } void UDPsocket::endthread() { 23
  • 26. param = 0; } void UDPsocket::closethread() { CloseHandle(rthread); } 7.3 S-Functions UDPSend #define S_FUNCTION_NAME UDPSend_gen #define S_FUNCTION_LEVEL 2 #include "simstruc.h" #include <WinSock2.h> #include <stdio.h> #include "udpsocket.h" static void mdlInitializeSizes(SimStruct *S) { ssSetNumSFcnParams(S, 3); //Parameter 1 :: IP to broadcast to //Parameter 2 :: Port //Parameter 3:: Broadcast Type // Parameter mismatch will be reported by Simulink if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) { return; } // 1 input that is dynamically_sized with direct feedthrough if (!ssSetNumInputPorts(S, 1)) return; ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED); ssSetInputPortDataType(S,0,DYNAMICALLY_TYPED); ssSetInputPortDirectFeedThrough(S, 0, 1); if (!ssSetNumOutputPorts(S,0)) return; //one sample time initialized below ssSetNumSampleTimes(S, 1); // Reserve place for C++ object Socket ssSetNumPWork(S, 1); 24
  • 27. ssSetOptions(S, SS_OPTION_WORKS_WITH_CODE_REUSE | SS_OPTION_EXCEPTION_FREE_CODE); } static void mdlInitializeSampleTimes(SimStruct *S) { ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME); ssSetOffsetTime(S, 0, 0.0); } #define MDL_START static void mdlStart(SimStruct *S) { const real_T * brdc = mxGetPr(ssGetSFcnParam(S,2)); //check if ip is a string else report error if(brdc[0]==2||brdc[0]==1) { if (!mxIsChar(ssGetSFcnParam(S,0)) || (mxGetM(ssGetSFcnParam(S,0)) != 1 ) ) { ssSetErrorStatus(S,"First Parameter must be a string"); return; } } //Find Size of String mwSize buflen= mxGetN(ssGetSFcnParam(S,0))*sizeof(mxChar)+1; char* IP; IP = (char*)mxMalloc(buflen); //write the parameter to the string IP mxGetString(ssGetSFcnParam(S,0),IP,buflen); //get port from the second parameter const real_T * port = mxGetPr(ssGetSFcnParam(S,1)); //Create and setdest of socket UDPsocket * s= new UDPsocket(); s->create(); if(brdc[0]==3) { setsockopt(s->getsocket(),SOL_SOCKET, SO_BROADCAST,"1",sizeof(char)); s->setdest("255.255.255.255",port[0]); } else { s->setdest(IP,port[0]); } 25
  • 28. //Deallocate the string formed with mxgetstring() mxFree(IP); //save socket to be used later in PWork vector ssGetPWork(S)[0]=s; } static void mdlOutputs(SimStruct *S, int_T tid) { int elements,size; const char * tname; //Get Socket from PWork vector UDPsocket *s = static_cast<UDPsocket*>(ssGetPWork(S)[0]); DTypeId inpt = ssGetInputPortDataType(S,0); size = ssGetDataTypeSize(S,inpt); elements = ssGetCurrentInputPortWidth(S,0); size = elements*size; tname = ssGetDataTypeName(S,inpt); int_T id = ssGetDataTypeId(S,tname); //Get Pointer to data from input port boolean_T c = ssGetInputPortRequiredContiguous(S,0); if(c) { real_T * ptr = (real_T*)ssGetInputPortSignal(S,0); s->pack((void*)ptr,id,size); } else { InputPtrsType ptr = ssGetInputPortSignalPtrs(S,0); switch(id+1) { case Socket::DOUBLE: { InputRealPtrsType u = (InputRealPtrsType)ptr; s->pack((void*)*u,id,size); break; } case Socket::SINGLE: { InputReal32PtrsType u = (InputReal32PtrsType)ptr; 26
  • 29. s->pack((void*)*u,id,size); break; } case Socket::INT8: { InputInt8PtrsType u = (InputInt8PtrsType)ptr; s->pack((void*)*u,id,size); break; } case Socket::UINT8: { InputUInt8PtrsType u = (InputUInt8PtrsType)ptr; s->pack((void*)*u,id,size); break; } case Socket::INT16: { InputInt16PtrsType u = (InputInt16PtrsType)ptr; s->pack((void*)*u,id,size); break; } case Socket::UINT16: { InputUInt16PtrsType u = (InputUInt16PtrsType)ptr; s->pack((void*)*u,id,size); break; } case Socket::INT32: { InputInt32PtrsType u = (InputInt32PtrsType)ptr; s->pack((void*)*u,id,size); break; } case Socket::UINT32: { InputUInt32PtrsType u = (InputUInt32PtrsType)ptr; s->pack((void*)*u,id,size); break; } case Socket::BOOLEAN: { InputBooleanPtrsType u = (InputBooleanPtrsType)ptr; s->pack((void*)*u,id,size); break; } } 27
  • 30. } } static void mdlTerminate(SimStruct *S) { UDPsocket *s = static_cast<UDPsocket*>(ssGetPWork(S)[0]); s->close(); delete s; } #ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */ #include "simulink.c" /* MEX-file interface mechanism */ #else #include "cg_sfun.h" /* Code generation registration function */ #endif UDPReceive #define S_FUNCTION_NAME UDPReceive_gen #define S_FUNCTION_LEVEL 2 #include "simstruc.h" #include <WinSock2.h> #include <stdio.h> #include "udpsocket.h" #include <process.h> template <class Unk> void compile (char*messages,int sizes,Unk* &data) { byte *temp,*temp2,*temp3; temp3 = new byte[sizes]; temp = (byte*)messages; for (int i = 0; i<(sizes/sizeof(Unk)); i++) { temp2 = temp+12+i*sizeof(Unk); memcpy(temp3+sizeof(Unk)*i,temp2,sizeof(Unk)); } data = (Unk*)temp3; //delete temp3; } 28
  • 31. static void mdlInitializeSizes(SimStruct *S) { ssSetNumSFcnParams(S, 5); //Parameter 1:: IP address as string //Parameter 2:: Port //Parameter 3:: DataType 0-8 //Parameter 4:: Number of elements //Parameter 5:: Broadcast type // Parameter mismatch will be reported by Simulink if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) { return; } const real_T * dtype = mxGetPr(ssGetSFcnParam(S,2)); const real_T * elem = mxGetPr(ssGetSFcnParam(S,3)); if (!ssSetNumInputPorts(S, 0)) return; if (!ssSetNumOutputPorts(S,1)) return; ssSetOutputPortWidth(S, 0, elem[0]); ssSetOutputPortDataType(S,0,(dtype[0]-1)); ssSetNumSampleTimes(S, 1); // Reserve place for C++ object ssSetNumPWork(S, 1); ssSetOptions(S,0); } static void mdlInitializeSampleTimes(SimStruct *S) { ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME); ssSetOffsetTime(S, 0, 0.0); } #define MDL_START static void mdlStart(SimStruct *S) { //check if ip is a string else report error if (!mxIsChar(ssGetSFcnParam(S,0)) || (mxGetM(ssGetSFcnParam(S,0)) != 1 ) ) { ssSetErrorStatus(S,"First Parameter must be a string"); 29
  • 32. return; } //Find Size of String mwSize buflen= mxGetN(ssGetSFcnParam(S,0))*sizeof(mxChar)+1; char* IP; IP = (char*)mxMalloc(buflen); //write the parameter to the string IP mxGetString(ssGetSFcnParam(S,0),IP,buflen); //get port from the second parameter const real_T * port = mxGetPr(ssGetSFcnParam(S,1)); //get broadcast type const real_T * brdc = mxGetPr(ssGetSFcnParam(S,4)); UDPsocket *s = new UDPsocket(); if(s->create()) { s->close(); ssPrintf("Error on createn"); system ("PAUSE"); } if(s->bind(port[0])) { s->close(); ssPrintf("error on bindn"); system ("PAUSE"); } int btype = (int)brdc[0]; switch(btype) { case 1: { if(s->joinmulticast(IP)) { ssPrintf("Error on joinmulticastn"); system ("PAUSE"); s->close(); } break; } case 3: { setsockopt(s->getsocket(),SOL_SOCKET,SO_BROADCAST,"1",sizeof(char)); break; } 30
  • 33. } mxFree(IP); s->startthread(); ssGetPWork(S)[0]=s; } static void mdlOutputs(SimStruct *S, int_T tid) { UDPsocket *s = static_cast<UDPsocket*>(ssGetPWork(S)[0]); char message[2000]; int message_len=0; int size=0, type=0; s->getdata(message,size,type,message_len); if(message_len >0&&size>0) { switch(type+1) { case Socket::DOUBLE: { real_T * data = new real_T[size/sizeof(real_T)]; compile(message,size,data); real_T *y =(real_T*)ssGetOutputPortSignal(S,0); memcpy(y, data, size); delete data; break; } case Socket::SINGLE: { real32_T * data = new real32_T[size/sizeof(real32_T)]; compile(message,size,data); real32_T *y = (real32_T*)ssGetOutputPortSignal(S,0); memcpy(y, data, size); delete data; break; } 31
  • 34. case Socket::INT8: { int8_T *data = new int8_T[size/sizeof(int8_T)]; compile(message,size,data); int8_T *y = (int8_T*)ssGetOutputPortSignal(S,0); memcpy(y, data, size); delete data; break; } case Socket::UINT8: { uint8_T *data = new uint8_T[size/sizeof(uint8_T)]; compile(message,size,data); uint8_T *y = (uint8_T*)ssGetOutputPortSignal(S,0); memcpy(y, data, size); delete data; break; } case Socket::INT16: { int16_T *data = new int16_T[size/sizeof(int16_T)]; compile(message,size,data); int16_T *y = (int16_T*)ssGetOutputPortSignal(S,0); memcpy(y, data, size); delete data; break; } case Socket::UINT16: { uint16_T *data = new uint16_T[size/sizeof(uint16_T)]; compile(message,size,data); uint16_T *y = (uint16_T*)ssGetOutputPortSignal(S,0); memcpy(y, data, size);; delete data; break; } case Socket::INT32: { int32_T *data = new int32_T[size/sizeof(int32_T)]; compile(message,size,data); int32_T *y = (int32_T*)ssGetOutputPortSignal(S,0); memcpy(y, data, size); delete data; break; } case Socket::UINT32: { uint32_T *data = new uint32_T[size/sizeof(uint32_T)]; 32
  • 35. compile(message,size,data); uint32_T *y = (uint32_T*)ssGetOutputPortSignal(S,0); memcpy(y, data, size); delete data; break; } case Socket::BOOLEAN: { boolean_T *data = new boolean_T[size/sizeof(boolean_T)]; compile(message,size,data); boolean_T *y = (boolean_T*)ssGetOutputPortSignal(S,0); memcpy(y, data, size); delete data; break; } } } } static void mdlTerminate(SimStruct *S) { UDPsocket *s = static_cast<UDPsocket*>(ssGetPWork(S)[0]); s->endthread(); s->closethread(); s->close(); delete s; } #ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */ #include "simulink.c" /* MEX-file interface mechanism */ #else #include "cg_sfun.h" /* Code generation registration function */ #endif 33