and follow the installation instructions at http://sumo.sourceforge.net/doc/current/docs/userdoc/Installing.html
- OMG will look for the SUMO and SUMO-GUI exectuable from this SUMO folder.
- SUMO/SCENARIOS is the default folder for SUMO scenarios. Please add all required scenario on that folder.
- OMG will launch SUMO with one single SUMO config file. Please regoup all your SUMO XML files (network, route et others) in one .cfg file. More details on the SUMO website.
- SUMO will be lauched using the following command
sumo -c scen.sumo.cfg -b 0 -e 1000 -v
or, if you want to enable TraCI server (here as example listening on port 8883). Please bear in mind that this launch will be blocking upon a TraCI client
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file socket_traci_OMG.c
* \brief The socket interface of TraCI to connect OAI to SUMO. A 'C' reimplementation of the TraCI version of simITS (F. Hrizi, fatma.hrizi@eurecom.fr)
* \author S. Uppoor
* \date 2012
* \version 0.1
* \company INRIA
* \email: sandesh.uppor@inria.fr
* \note
* \warning
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "socket_traci_OMG.h"
#include "storage_traci_OMG.h"
intconnection_(char*hoststr,intportno)
{
host=gethostbyname(hoststr);
printf("trying to connect to %s at the port %i \n",hoststr,portno);
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file socket_traci_OMG.h
* \brief The socket interface of TraCI to connect OAI to SUMO. A 'C' reimplementation of the TraCI version of simITS (F. Hrizi, fatma.hrizi@eurecom.fr)
* \author S. Uppoor
* \date 2012
* \version 0.1
* \company INRIA
* \email: sandesh.uppor@inria.fr
* \note
* \warning
*/
#ifndef SOCKET_TRACI_OMG_H
#define SOCKET_TRACI_OMG_H
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include "omg.h"
#include "storage_traci_OMG.h"
intsock,portno,msgLength;
structhostent*host;
structsockaddr_inserver_addr;
/**
* Global parameters defined in storage_traci_OMG.h
*/
externstorage*tracker;
externstorage*head;
externstorage*storageStart;
/**
* \fn connection_(char *,int)
* \brief Talks to SUMO by establishing connection
* \param Accepts host name and port number
*/
intconnection_(char*,int);
/**
* \fn sendExact(int);
* \brief Pack the data from storage to buf and write to socket
* \param Accepts command length
*/
voidsendExact(int);
/**
* \fn recieveExact(void);
* \brief Pack the data to storage from buf after reading from socket
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file storage_traci_OMG.c
* \brief The data storage object carrying data from/to SUMO. 'C' reimplementation of the TraCI version of simITS (F. Hrizi, fatma.hrizi@eurecom.fr)
* \author S. Uppoor
* \date 2012
* \version 0.2
* \company INRIA
* \email: sandesh.uppor@inria.fr
* \note 0.1 -> 0.2: (J. Harri) added reader and writer to String_list
* \warning
*/
#include <string.h>
#include "storage_traci_OMG.h"
//using namespace std
boolbigEndian;
voidreset()
{
tracker=NULL;
head=NULL;
descLen=0;
freeStorage(storageStart);// freeing the storage object
storageStart=NULL;
}
voidcheck_endianness()
{
//checking endianness
un.s=0x0102;
if(sizeof(short)==2){
if(un.c[0]==1&&un.c[1]==2)
bigEndian=true;
}
}
intstorageLength(storage*cur_ptr)
{
intcount=0;
while(cur_ptr!=NULL){
cur_ptr=cur_ptr->next;
count++;
}
return(count);
}
voidrearange()
{
//Since linked list is used, all data is appended to the last pointer,
// we face problem in sendExact(int cmdLength) in socket_traci_OMG.c
// since total length of the entire message is appended last
// storage = command + length(4 bytes) is changed to storage = length(4 bytes) + command
intpos=msgLength-4;
intcount=0;
storage*cur_ptr=NULL;
storage*temp_ptr=NULL;
storage*temp_pptr=NULL;
cur_ptr=storageStart;
while(count!=pos&&cur_ptr->next!=NULL){
temp_pptr=cur_ptr;
cur_ptr=cur_ptr->next;
count++;
}
temp_ptr=cur_ptr;
while(cur_ptr->next!=NULL){
cur_ptr=cur_ptr->next;
}
cur_ptr->next=storageStart;
storageStart=temp_ptr;
temp_pptr->next=NULL;
}
unsignedcharreadChar()
{
// if (tracker!=NULL)
// {
unsignedcharhd=tracker->item;
//printf("OMG char: %d \n",(int)hd);
tracker=tracker->next;
returnhd;
//}else
// {
// LOG_E(OMG, " Storage::readChar(): Tracker is NULL \n");
// unsigned char *error = NULL;
// return error; //
// }
}
voidwriteChar(unsignedcharvalue)
{
storage*temp;
temp=(storage*)malloc(sizeof(storage));
if(head==NULL){
head=temp;
head->next=NULL;
head->item=value;
storageStart=temp;//points to start of actual message
}else{
head->next=temp;
temp->next=NULL;
temp->item=value;
head=temp;
}
}
intreadByte()
{
inti=(int)(readChar());
if(i<128)returni;
elsereturn(i-256);
}
voidwriteByte(intvalue)
{
if(value<-128||value>127){
LOG_E(OMG," Storage::writeByte(): Invalid value, not in [-128, 127]\n");
}
writeChar((unsignedchar)((value+256)%256));
}
intreadUnsignedByte()
{
return(int)(readChar());
}
voidwriteUnsignedByte(intvalue)
{
if(value<0||value>255){
LOG_E(OMG," Storage::writeUnsignedByte(): Invalid value, not in [0, 255]\n");
}
writeChar(((unsignedchar)value));
}
// JNNOTE: had to change the behavior here, as tmp was always pointing at the end of the String and not at the beginning: accordingly, all strings where always '0'
char*readString()
{
inti=0;
intlen=readInt();
descLen=len;
char*tmp=(char*)malloc(sizeof(char)*(len));
char*ret=tmp;// JHNOTE: added a pointer pointing at the head of the String
//printf("OMG ready to readString of length %d \n",len);
for(;i<len;i++){
*tmp++=(char)readChar();
}
*tmp++='\0';// makes sure it's NUL terminated
//printf("OMG readString - %s \n",ret);
//printf("OMG readString - %s \n",tmp);
returnret;// the head is returned
}
voidwriteString(char*s)
{
intcount=0;
char*s_copy=s;
for(;*s!='\0';s++)
count++;
writeInt(count);
for(;*s_copy!='\0';s_copy++)
writeChar(*s_copy);
}
string_list*readStringList(string_list*vector)
{
inti=0;
intlen=readInt();
descLen=len;
string_list*entry=NULL;
for(;i<len;i++){
if(vector->string==NULL){
char*tmp=readString();
//printf("OMG - 1 SUMO ID: %s \n",tmp);
vector->string=tmp;//readString();
}else{
entry=(string_list*)malloc(sizeof(string_list));
char*tmp=readString();
//printf("OMG - SUMO ID: %s \n",tmp);
entry->string=tmp;//readString();
entry->next=NULL;
if(vector!=NULL){
string_list*tmp=vector;
while(tmp->next!=NULL){
tmp=tmp->next;
}
tmp->next=entry;
}
}
}
returnvector;
}
voidwriteStringList(string_list*vector)
{
intcount=0;
string_list*tmp=vector;
// JHNote: a better solution would be to save the pointer to the reference of this Int and replace the value with count at the end....
intmax_node_SUMO=100;//commandGetMaxSUMONodesVariable(); TODO method not implemented in TraCI server..must find another solution
// printf("received Number of nodes %d\n", max_node_SUMO);
// create the OAI/SUMO ID manager
id_manager=create_IDManager();
node_struct*node=NULL;
mobility_struct*mobility=NULL;
active_nodes=NULL;// container to return a subset of only ACTIVE OAI nodes in SUMO
last_update_time=0.0;
// just check for faulty values
if(omg_param_list.nodes<=0){
#ifdef STANDALONE
printf("Number of nodes has not been set\n");
#else
LOG_W(OMG,"Number of nodes has not been set\n");
#endif
return(-1);
}
#ifdef STANDALONE
printf("Number of OAI-equipped nodes in SUMO has been set to %d\n",
omg_param_list.nodes);
printf("Number of SUMO simulated nodes has been set to %d\n",
max_node_SUMO);
#else
LOG_I(OMG,"Number of OAI-equipped nodes in SUMO has been set to %d\n",
omg_param_list.nodes);
LOG_I(OMG,"Number of SUMO simulated nodes has been set to %d\n",
max_node_SUMO);
#endif
// check and match number of nodes in mobility file provided
if(omg_param_list.nodes>max_node_SUMO){
#ifdef STANDALONE
printf("Not all OAI nodes will be moving according to SUMO.\n");
#else
LOG_I(OMG,"Not all OAI nodes will be moving according to SUMO.\n");
#endif
}else{
#ifdef STANDALONE
printf("OAI nodes will be mapped to a subset of SUMO nodes\n");
#else
LOG_I(OMG,"OAI nodes will be mapped to a subset of SUMO nodes\n");
#endif
}
if(omg_param_list.nodes_type==eNB){
#ifdef STANDALONE
printf("Node type has been set to eNB\n");
#else
LOG_I(OMG,"Node type has been set to eNB\n");
#endif
}elseif(omg_param_list.nodes_type==UE){
#ifdef STANDALONE
printf("Node type has been set to UE\n");
#else
LOG_I(OMG,"Node type has been set to UE\n");
#endif
}
for(n_id=id;n_id<omg_param_list.nodes+id;n_id++){
node=create_node();
mobility=create_mobility();
node->mobile=0;// 0 means inactive in SUMO; 1 means active in SUMO; as long as a mapping between OAI-SUMO has not been created, nodes are inactive and do not move
node->id=n_id;// this is OAI ID, not SUMO
node->type=omg_param_list.nodes_type;// UE eNB...
node->generator=SUMO;// SUMO
node->mob=mobility;
// FIXME! wrong use of node_vector and node_vector_end
// FIXME node_vector_end is declared with MAX_NUM_NODE_TYPES elements, but here we are indexing with SUMO from enum mobility_types
// FIXME node_vector is declared with MAX_NUM_NODE_TYPES elements, but here we are indexing with SUMO from enum mobility_types
#define MIN_SUMO_STEP 100 // 100ms is the smallest allowed SUMO update step
/*! A global variable used to store the SUMO process ID to later kill it smoothly when OAI askes OMG to stop SUMO*/
pid_tpid;
/*! A sumo global variable representing the OMG-SUMO ID manager. It is created at the start_sumo_generator(void) and keep a mapping between SUMO and OAI IDs. */
IDManagerPtrid_manager;
/*! A Node_list intended to contain the list of OAI 'active' nodes in SUMO. replaces the return of the full Node_Vector when OAI requests the new positions of its nodes. The list is reset at each use, but the pointer to the respective nodes is just set to NULL*/
node_list*active_nodes;
/*! A global variable keeping track of the last update time of SUMO, to be used to get the update interval when update_sumo_nodes(cur_time) is called */
* \brief Start SUMO by setting the initial positions of each node then letting it sleep till it departs to its destination and add this job to the Job_Vector
* \param omg_param_list a structure that contains the main parameters needed to establish the random positions distribution
* \brief Update SUMO simulation time by x timesteps. After advancing the SUMO for the next timestep, SUMO will automatically update all nodes positions.
* Note that the SUMO positions are kept by SUMO. One need to specifically query SUMO to get them.
* \param cur_time a variable of type double that represents the current time
*/
voidupdate_sumo_nodes(doublecur_time);
/**
* \fn void get_sumo_positions(NodePtr node)
* \brief Get the current position and speed of a node from SUMO. Invokes TraCI
* \param node the pointer to a node we want to synch with SUMO.
* \brief Get the current position and speed of a list of nodes. First, OMG retrieves the list of ACTIVE nodes, and second it updates their position from SUMO. Invokes TraCI
* \param cur_time a variable of type double that represents the current time
* \return the list of ACTIVE OAI nodes, which positions have been updated by SUMO
* \brief Updates the mapping between SUMO and OAI nodes; Once a node departs in SUMO, it is mapped to a inactive OAI node. If none are found, the SUMO node will not have any mapping. Once a node arrives, the mapping is removed and the OAI node becomes inactive again. When an OAI node is inactive, it mobility parameters are invalid and MUST NOT be used/requested by OAI.
*/
voidupdate_IDs(void);
/**
* \fn bool desactive_and_unmap(char *sumo_id)
* \brief desactivates an OAI node as it is no longer in SUMO; will be recycled by a new SUMO node in the future;
* \param sumo_id the string representing the SUMO ID of the OAI node;
* \return true in case of success; false otherwise;
*/
booldesactivate_and_unmap(char*sumo_id);
/**
* \fn bool activate_and_map(void)
* \brief activated an OAI node as a SUMO node entered in SUMO; Conceptually, this represents adding a communication device (OAI) to a SUMO node;
* It will find the first inactive OAI node, activates it and add the sumo mapping;
* \param sumo_id the string representing the SUMO ID of the OAI node;
* \return true in case of success; false if the maximum of OAI node has been reached
*/
boolactivate_and_map(char*sumo_id);
/**
* \fn int stop_sumo_generator(void)
* \brief stops SUMO, stop the socket and kills SUMO process in the child domain.
* \return true in case of success; false otherwise