35
Summer Internship 2010 Development of a MATLAB/Simulink - Toolbox for Distributed Simulation Author: James Dianics Supervisor: Prof. Dr.-Ing. Reinhard Finsterwalder July 30, 2010

UDP Report

Embed Size (px)

Citation preview

Page 1: UDP Report

Summer Internship 2010

Development of aMATLAB/Simulink - Toolbox for

Distributed Simulation

Author:James Dianics

Supervisor:Prof. Dr.-Ing. Reinhard

Finsterwalder

July 30, 2010

Page 2: UDP Report

Abstract

This report gives an overview of the development of a distributed simulation toolbox forMatlab/Simulink. The project was developed as a sub-project to the MASTER programwhich is designed to be a student built flight simulator for education and research. Themodel 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 betweensystems 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 UDPSendand UDPReceive S-functions for Matlab.

Page 3: UDP Report

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

Page 4: UDP Report

1 Introduction

1.1 Project MASTER

The MASTER project was started in 2001 at the University of the Federal Armed ForcesMunich, Germany. The purpose of the MASTER project is the development of a modularvehicle simulator with exchangeable cockpit modules for education and research appli-cation. Thus ”MASTER” is an acronym which stands for Modular Advanced SimulatorTechnology 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 areoften insufficient. Distributed computing allows for either parallel computing on a singlemachine with multiple cores or among many nodes in a network; either solution providesan 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 streamingdata between two clients such as a web browser and web server. The main points of TCPthat were of a concern are that TCP utilizes error checking and creates a buffer waitingfor delayed data before releasing the packet, both of these functions delay the speed ofthe data but give a more reliable signal.

UDP does not utilize error checking and by definition is unreliable. This attribute canbe beneficial if used correctly because it allows for less signal delay because of the lack ofprocessing on the network that needs to be done before receiving a signal. One must becareful about its application and understand that packets could be missing, duplicated orarrive 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 isthe typical single client single server transmission. Multicast is located on a differentIP range and theoretically a single client can send a message to an unlimited number oflistening servers.

UDP is best used during real-time applications where speed is required. This could beduring VoIP, IP-TV or applications such as Skype where lost packets could mean a smearin the picture but the overall quality of the picture shall remain good if the connectionis decent. UDP was chosen for the MASTER project because of the need for real-timecommunication and varying transmission capabilities.

2

Page 5: UDP Report

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 createnetworking functions for applications. In order to create networking ability only a fewwindows 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 socketand the function WSAStartup takes a pointer to the structure and initializes the socketin 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

Page 6: UDP Report

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 socketbeing 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, andIP address in that respective order. To accomplish communication there are four basicfunctions 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 , bu f f e r , s izeof ( b u f f e r ) , 0 , (SOCKADDR∗)&addr , s izeof (SOCKADDR IN) ) ;

recvfrom ( s , bu f f e r , s izeof ( b u f f e r ) , 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 asimple application running using Winsock2.

4

Page 7: UDP Report

3 C++ Test Application

Before the development of the Matlab/Simulink distributed simulation toolbox two testapplications were built using Microsoft’s Visual C++ application development studio.The applications were designed to meet the requirements that needed to be met in theMatlab 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 ofthe data contained and the number of elements contained in the array being sentor received.

• Preceding the header the data array shall be contained in a byte format.

Figure 5: Packet Protocol

5

Page 8: UDP Report

Data types that the classes currently support were included due to their definition byMatlab/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 laterbe developed extending the socket class.

6

Page 9: UDP Report

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 tosend 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

Page 10: UDP Report

• 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 inc++...

int main (int argc, char *argv[])

{

printf("UDP server\n");

UDPsocket s;

char message[256];

int size,type;

if(s.create())

{

s.close();

printf("Error on create\n");

return 1;

}

if(s.bind())

{

8

Page 11: UDP Report

s.close();

printf("error on bind\n");

system ("PAUSE");

return 1;

}

if(s.joinmulticast())

{

printf("Error on joinmulticast\n");

s.close();

return 1;

}

Here the UDPsocket object is created and the required variables are declaredto obtain a message and compile it. The socket is created, bound, and joinedto a multi-cast IP all with error checking.

Next the receivethread function is intialized with the startthread() functioncall 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("%i\n",data[i]);

cout << data[i] << endl;

}

delete data;

break;

}

If the message length is greater than 0 (meaning that a message has beenreceived) a switch structure is used to determine the data type based on thetype received and the data is compiled and read out. The data type has beenenumerated in the socket class.

s.endthread();

s.closethread();

s.close();

9

Page 12: UDP Report

When the server is finished the thread listening on the socket is ended andclosed 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 Simulinkenvironment 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 compiledinto a MEX (Matlab Executable) file which is implemented in Simulink.

Understanding how Simulink and S-functions work is important when beginning to builda 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

Page 13: UDP Report

Every S - Function follows a strict structure the most basic template includes these 4main functions.

stat ic void m d l I n i t i a l i z e S i z e s ( SimStruct ∗S)}

stat ic void mdlIn i t ia l i z eSampleTimes ( SimStruct ∗S)

stat ic void mdlStart ( SimStruct ∗S)

stat ic void mdlOutputs ( SimStruct ∗S)

stat ic 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 datatype)

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

Page 14: UDP Report

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 widthinherited from the driving block. MDLstart is only ran at the beginning of the simulationhere 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 datafrom. Terminate is only ran at the end of the simulation and this is where we simplyclose 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

Page 15: UDP Report

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 requireslinking 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 developedduring 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 theother

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 shortexample 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

Page 16: UDP Report

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

Page 17: UDP Report

Figure 9: S-Function Mask Editor

Figure 10: S-Functions Parameters

15

Page 18: UDP Report

4.5 Example Simulink Models using Distributed Simulation Tool-box

Figure 11: S-Function UDPSend - Transmitting position and orientation data from theflight model to the visualization engine

16

Page 19: UDP Report

Figure 12: S-Function UDPReceive - Receiving position and orientation data in thevisualization engine

5 Results

A Matlab/Simulink Distributed Simulation Toolbox was successfully developed usingthe UDP transmission protocol. The send and receive blocks are able to send arraysof all Matlab data types using Singlecast, Multicast or Broadcast transmissions. Someproblems 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 applicationbut would crash Simulink when implemented as a S-Function. As a temporary solutiona non-blocking socket was used to successfully complete the S-Function. While testingthe S- Function, strange behavior was observed where data was still is received afterthe send model had stopped running; this was attributed to the non-blocking socketbuilding a buffer on the network. The final solution was found by creating a separatethread to operate a blocking socket that would listen for incoming messages, this threadcould run continuously without delaying Simulink and is the final successful solution. Thedistributed simulation toolbox could be further improved by also implementing other net-work protocols into separate blocks, notably TCP could be useful in other applicationswhere error checking is necessary. The UDP blocks could also be improved by adding theability to send structures or user created data types.

17

Page 20: UDP Report

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{pub l i c :

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);

p ro tec ted :

18

Page 21: UDP Report

SOCKET s ;SOCKADDR IN addr ;

} ;

#endif

socket.cpp

#include ” socke t . h”

Socket : : Socket ( ){

WSADATA wsaData ;WSAStartup (MAKEWORD(2 ,2) ,& wsaData ) ;

}

Socket : : ˜ Socket ( ){

WSACleanup ( ) ;}

int Socket : : c l o s e ( ){

i f ( c l o s e s o c k e t ( s)==SOCKET ERROR){

return 1 ;}

return 0 ;}

int Socket : : bind ( int port ){

memset (&addr , 0 , s izeof (SOCKADDR IN) ) ;addr . s i n f a m i l y = AF INET ;addr . s i n p o r t = htons ( port ) ;addr . s i n addr . s addr=INADDR ANY;

i f ( : : bind ( s , (SOCKADDR∗)&addr ,s izeof (SOCKADDR IN) ) == SOCKET ERROR){

return 1 ;}return 0 ;

}

19

Page 22: UDP Report

7.2 udpsocket.h and udpsocket.cpp

udpsocket.h

#ifndef UDPSOCKET H#define UDPSOCKET H

#include ” socke t . h”#include <windows . h>#include <proce s s . h>

c l a s s UDPsocket : pub l i c Socket{

pub l i c :UDPsocket ( ) ;˜UDPsocket ( ) ;int c r e a t e ( ) ;SOCKADDR IN getaddr ( ){ return addr ;}SOCKET get so cke t ( ){ return s ; }int j o i n m u l t i c a s t ( char∗ IP=” 2 2 6 . 0 . 0 . 1 ” ) ;void s e t d e s t ( char∗ IP=” 2 2 6 . 0 . 0 . 1 ” , int port = 12345) ;int send ( void∗ bu f f e r , int b u f f e r l e n ) ;unsigned char∗ pack ( void∗ number , int type , int s i z e ) ;

stat ic long WINAPI r e c e i v e t h r e a d (LPVOID Param ) ;void getdata ( char ∗msg , int &s i z e , int &type , int &msg len ) ;void s t a r t t h r e a d ( ) ;

void endthread ( ) ;void c l o s e t h r e a d ( ) ;

p r i v a t e :

} ;#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

Page 23: UDP Report

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

Page 24: UDP Report

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

Page 25: UDP Report

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

Page 26: UDP Report

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

Page 27: UDP Report

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

Page 28: UDP Report

//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

Page 29: UDP Report

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

Page 30: UDP Report

}

}

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

Page 31: UDP Report

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

Page 32: UDP Report

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 create\n");

system ("PAUSE");

}

if(s->bind(port[0]))

{

s->close();

ssPrintf("error on bind\n");

system ("PAUSE");

}

int btype = (int)brdc[0];

switch(btype)

{

case 1:

{

if(s->joinmulticast(IP))

{

ssPrintf("Error on joinmulticast\n");

system ("PAUSE");

s->close();

}

break;

}

case 3:

{

setsockopt(s->getsocket(),SOL_SOCKET,SO_BROADCAST,"1",sizeof(char));

break;

}

30

Page 33: UDP Report

}

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

Page 34: UDP Report

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

Page 35: UDP Report

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