sumo.c 14.6 KB
Newer Older
1
/*******************************************************************************
nikaeinn's avatar
nikaeinn committed
2
3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

nikaeinn's avatar
nikaeinn committed
5
6
7
8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9
10


nikaeinn's avatar
nikaeinn committed
11
12
13
14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

nikaeinn's avatar
nikaeinn committed
16
17
18
19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
    included in this distribution in the file called "COPYING". If not,
    see <http://www.gnu.org/licenses/>.
20
21

  Contact Information
nikaeinn's avatar
nikaeinn committed
22
23
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
nikaeinn's avatar
nikaeinn committed
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

*******************************************************************************/

/*! \file sumo.c
* \brief The OMG interface to SUMO (Simulation of Urban Mobility)
* \author  S. Uppoor, J. Harri
* \date 2012
* \version 0.1
* \company INRIA, Eurecom
* \email: sandesh.uppor@inria.fr, haerri@eurecom.fr
* \note
* \warning
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <time.h>
#include <math.h>
#include <string.h>
#include <signal.h>

#include "sumo.h"

#include "client_traci_OMG.h"
53
#include "assertions.h"
54
55


56
57
58
int
start_sumo_generator (omg_global_param omg_param_list)
{
59
60

  char sumo_line[300];
61
62
  int n_id;
  static int id = 0;
63

64
  // sprintf(sumo_line, "%s -c %s  -b %d -e %d --remote-port %d --step-length %d -v ",omg_param_list.sumo_command, omg_param_list.sumo_config, omg_param_list.sumo_start, omg_param_list.sumo_end, omg_param_list.sumo_port, omg_param_list.sumo_step);
65

66
  sprintf (sumo_line, "%s -c %s ", omg_param_list.sumo_command,
67
           omg_param_list.sumo_config);
68
69
70

  printf ("%s\n", sumo_line);

71
72
  if ((pid = fork ()) == 0) {
    // Start SUMO in the child process
Cedric Roux's avatar
Cedric Roux committed
73
    if (system (sumo_line)) ;  /* this if for no gcc warnings */
74
75
    //childs addresss space
  }
76
77

  //still in the parent process
78

79
  // Talk to SUMO
80
81

  targetTime = 1;
82
83

  departed = NULL;
84
85
  arrived = NULL;

86
  // switch on error to return to OAI
87
88
89
  handshake (omg_param_list.sumo_host, omg_param_list.sumo_port);

  init (omg_param_list.sumo_end - omg_param_list.sumo_start);
90

91
  int max_node_SUMO = 100;  //commandGetMaxSUMONodesVariable(); TODO method not implemented in TraCI server..must find another solution
92
93

  // printf("received Number of nodes %d\n", max_node_SUMO);
94
95

  // create the OAI/SUMO ID manager
96
97
98
99
  id_manager = create_IDManager ();

  node_struct *node = NULL;
  mobility_struct *mobility = NULL;
100

101
  active_nodes = NULL;    // container to return a subset of only ACTIVE OAI nodes in SUMO
102
103
104
105

  last_update_time = 0.0;

  // just check for faulty values
106
  if (omg_param_list.nodes <= 0) {
107
#ifdef STANDALONE
108
    printf ("Number of nodes has not been set\n");
109
#else
110
    LOG_W (OMG, "Number of nodes has not been set\n");
111
#endif
112
113
114
    return (-1);
  }

115
116
#ifdef STANDALONE
  printf ("Number of OAI-equipped nodes in SUMO has been set to %d\n",
117
          omg_param_list.nodes);
118
  printf ("Number of SUMO simulated nodes has been set to %d\n",
119
          max_node_SUMO);
120
121
#else
  LOG_I (OMG, "Number of OAI-equipped nodes in SUMO has been set to %d\n",
122
         omg_param_list.nodes);
123
  LOG_I (OMG, "Number of SUMO simulated nodes has been set to %d\n",
124
         max_node_SUMO);
125
#endif
126

127
  // check and match number of nodes in mobility file provided
128
  if (omg_param_list.nodes > max_node_SUMO) {
129
#ifdef STANDALONE
130
    printf ("Not all OAI nodes will be moving according to SUMO.\n");
131
#else
132
    LOG_I (OMG, "Not all OAI nodes will be moving according to SUMO.\n");
133
#endif
134
  } else {
135
#ifdef STANDALONE
136
    printf ("OAI nodes will be mapped to a subset of SUMO nodes\n");
137
#else
138
    LOG_I (OMG, "OAI nodes will be mapped to a subset of SUMO nodes\n");
139
#endif
140
  }
141

142
  if (omg_param_list.nodes_type == eNB) {
143
#ifdef STANDALONE
144
    printf ("Node type has been set to eNB\n");
145
#else
146
    LOG_I (OMG, "Node type has been set to eNB\n");
147
#endif
148
  } else if (omg_param_list.nodes_type == UE) {
149
150

#ifdef STANDALONE
151
    printf ("Node type has been set to UE\n");
152
#else
153
    LOG_I (OMG, "Node type has been set to UE\n");
154
#endif
155
  }
156

157
  for (n_id = id; n_id < omg_param_list.nodes + id; n_id++) {
158

159
160
161
162
163
164
165
    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;
166

167
168
169
    // 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
170

171
172
    node_vector_end[SUMO] =
      (node_list *) add_entry (node, node_vector_end[SUMO]);
173

174
175
176
    if (node_vector[SUMO] == NULL)
      node_vector[SUMO] = node_vector_end[SUMO];
  }
177
178
179

  id += omg_param_list.nodes;

180
  update_IDs ();    // update the mapping between departed and arrived nodes in SUMO.
181
182

  return (0);
183
184
}

185
186
187
188
189
190
191
192
193
194
void
update_IDs (void)
{
#ifdef STANDALONE
  printf ("Updating the ID mapping between SUMO and OAI\n");
#else
  LOG_D (OMG, "Updating the ID mapping between SUMO and OAI\n");
#endif
  string_list *tmp_arrived, *tmp_departed;

195
196
197
198
  if (arrived == NULL) {
    printf ("arrived vehicles is NULL \n");
    return;
  }
199
200
201
202

  tmp_arrived = arrived;
  tmp_departed = departed;

203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
  if (departed == NULL) {
    printf ("departed vehicles is NULL \n");
    return;
  }

  if (tmp_departed->string != NULL) {
    // char *tmp_string = malloc (sizeof (strlen (tmp_departed->string)));
    char *tmp_string = malloc( strlen(tmp_departed->string) + 1 );
    strcpy (tmp_string, tmp_departed->string);
    //printf("OMG - 2 head is not null and value is: %s\n",tmp_string);
    int OAI_ID = get_oaiID_by_SUMO (tmp_string, id_manager);

    if (OAI_ID == -1) {
      if (!activate_and_map (tmp_string)) {
        // printf("Reached the Maximum of OAI nodes to be mapped to SUMO\n");
        // LOG_I(OMG, "Reached the Maximum of OAI nodes to be mapped to SUMO\n");
        free( tmp_string );
        return;   // stopping mapping as the maximum of OAI nodes has been reached;
      }
222

223
    }
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243

    free( tmp_string );
  }

  while (tmp_departed->next != NULL) {
    // printf("OMG - 2 main is not null \n");
    //char tmp_string [strlen(tmp_departed->string)];
    //char *tmp_string = malloc (sizeof (strlen (tmp_departed->string)));
    char *tmp_string = malloc( strlen(tmp_departed->string) + 1 );
    strcpy (tmp_string, tmp_departed->string);
    //char *tmp_string = tmp_departed->string;
    int OAI_ID = get_oaiID_by_SUMO (tmp_string, id_manager);

    if (OAI_ID == -1) {
      if (!activate_and_map (tmp_string)) {
        //printf("Reached the Maximum of OAI nodes to be mapped to SUMO\n");
        //LOG_I(OMG, "Reached the Maximum of OAI nodes to be mapped to SUMO\n");
        free( tmp_string );
        return;   // stopping mapping as the maximum of OAI nodes has been reached;
      }
244
    }
245

246
247
248
    free( tmp_string );
    tmp_departed = tmp_departed->next;
  }
249

250
  departed = clear_string_list (departed);
251

252
253
254
  if (tmp_arrived->string != NULL) {
    char *tmp_string = tmp_arrived->string;
    //printf("OMG - 3 head is not null and value is: %s\n",tmp_arrived->string);
255

256
257
258
    if (!desactivate_and_unmap (tmp_string)) {
      printf ("Could not locate the OAI node ID %s \n", tmp_string);
      //LOG_I(OMG, "Could not locate the OAI node ID %s \n", tmp_string);
259
    }
260
261
262
263
264
265
266
267
268

  }

  while (tmp_arrived->next != NULL) {
    char *tmp_string = tmp_arrived->string;

    if (!desactivate_and_unmap (tmp_string)) {
      printf ("Could not locate the OAI node\n");
      // LOG_I(OMG, "Could not locate the OAI node\n");
269
    }
270
271
272
273

    tmp_arrived = tmp_arrived->next;
  }

274
  arrived = clear_string_list (arrived);
275
276
277

}

278
279
280
281
282
283
284
285
286
287
288
bool
desactivate_and_unmap (char *sumo_id)
{
#ifdef STANDALONE
  printf ("desactivating node %s \n", sumo_id);
#else
  LOG_I (OMG, "desactivating node %s \n", sumo_id);
#endif
  int OAI_ID = get_oaiID_by_SUMO (sumo_id, id_manager);
  remove_oaiID_by_SUMO (sumo_id, id_manager);

289
290
291
292
293
294
295
296
297
298
299
300
301
302
  if (OAI_ID != -1) {
    //TODO generalize to UE and eNB (must change the method)

    // FIXME! wrong use of node_vector
    // FIXME node_vector is declared with MAX_NUM_NODE_TYPES elements, but here we are indexing with SUMO from enum mobility_types
    node_struct *node = find_node (node_vector[SUMO], OAI_ID, UE);

    if (node == NULL)
      node = find_node (node_vector[SUMO], OAI_ID, eNB);

    if (node != NULL) {
      node->mobile = 0; // this node is now inactive;
      active_nodes = remove_node_entry (node, active_nodes);
      return true;
303
304
    }

305
306
  }

307
308
#ifdef STANDALONE
  printf
309
310
  ("Could not desactive an OAI node, as the SUMO-OAI mapping could not be found for the SUMO node ID %s \n",
   sumo_id);
311
312
#else
  LOG_I (OMG,
313
314
         "Could not desactive an OAI node, as the SUMO-OAI mapping could not be found for the SUMO node ID %s \n",
         sumo_id);
315
316
317
#endif

  return false;
318
319
320
}


321
322
323
324
325
326
327
328
329
bool
activate_and_map (char *sumo_id)
{
  MapPtr map = create_map ();
#ifdef STANDALONE
  printf ("activating node %s \n", sumo_id);
#else
  LOG_I (OMG, "activating node %s \n", sumo_id);
#endif
330
331
  // TODO: So far, only UE can be SUMO mobile, but could change
  AssertFatal( false, "node_vector array has only MAX_NUM_NODE_TYPES (=3) elements, but indexing here with SUMO (=4)");
nikaeinn's avatar
nikaeinn committed
332
  node_struct *active_node = get_first_inactive_OAI_node (node_vector[SUMO], UE);
333

334
335
336
  if (active_node != NULL) {
    // found an inactive OAI node; will be mapped to SUMO
    active_node->mobile = 1;  // now node is active in SUMO
337

338
339
340
341
342
343
    active_nodes = add_entry (active_node, active_nodes);

    map->oai_id = active_node->id;
    // map->sumo_id = malloc (sizeof ((int) strlen (sumo_id)));
    map->sumo_id = malloc( strlen(sumo_id) + 1 );
    strcpy (map->sumo_id, sumo_id);
344
345

#ifdef STANDALONE
346
347
    printf ("added a mapping between oai ID:  %d and SUMO ID: %s \n",
            map->oai_id, map->sumo_id);
348
#else
349
350
    LOG_I (OMG, "added a mapping between oai ID:  %d and SUMO ID: %s \n",
           map->oai_id, map->sumo_id);
351
352
#endif

353
354
355
356
    // TODO fusion the two lists...leads to data inconsistency
    // FIXME adding the same memory region to two lists => crash at free() time
    id_manager->map_sumo2oai =
      add_map_entry (map, id_manager->map_sumo2oai);
357

358
    id_manager->map_oai2sumo = add_map_entry (map, id_manager->map_oai2sumo); //map_sumo2oai
359

360
    return true;
361

362
  }
363

364
  else {
365
#ifdef STANDALONE
366
367
    printf
    ("All OAI Nodes are already active in SUMO; cannot control this SUMO node in OAI\n");
368
#else
369
370
    LOG_I (OMG,
           "All OAI Nodes are already active in SUMO; cannot control this SUMO node in OAI\n");
371
#endif
372
373
    return false;
  }
374
}
375
376


377
378
379
void
update_sumo_nodes (double cur_time)
{
380
381
382
383
384
  if ((cur_time - last_update_time) < MIN_SUMO_STEP) {
    // the min time interval for SUMO must be 100ms or more
    printf ("--------Update Step too small--------\n");
    return;
  }
385

386
  last_update_time = cur_time;  // keeps track of the last update time to get the update interval
387
388

  // commandSimulationStep(1.0);// Advance the SUMO simulation by cur_time units
389
390


391
  commandSimulationStep (cur_time); // Advance the SUMO simulation by cur_time units
392
393

  LOG_I (OMG, "--------Updated SUMO positions by %f [ms]--------\n",
394
395
         cur_time);
  update_IDs ();    // both are in the  traCI client
396
397
398
399


}

400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
void
update_sumo_positions (node_struct * node)
{



#ifdef STANDALONE
  printf ("--------GET SUMO Mobility for a single node--------\n");
#else
  LOG_D (OMG, "--------GET SUMO Mobility for a single node--------\n");
#endif

  Map_list tmp = id_manager->map_oai2sumo;
  char *sumo_id = get_sumo_entry (node->id, tmp);

415
416
417
418
419
  if (sumo_id != NULL) {
    //printf(" OAI ID is: %d and SUMO ID is %s \n",node->ID, sumo_id);
    GetPosition (node, sumo_id);
    GetSpeed (node, sumo_id);
  }
420
421
}

422
423
424
425
426
427
428
node_list *
get_sumo_positions_updated (double cur_time)
{


#ifdef STANDALONE
  printf
429
  ("--------GET SUMO Mobility for a group of ACTIVE OAI nodes--------\n");
430
431
#else
  LOG_I (OMG,
432
         "--------GET SUMO Mobility for a group of ACTIVE OAI nodes--------\n");
433
434
#endif

435
436
  // FIXME! wrong use of node_vector
  // FIXME node_vector is declared with MAX_NUM_NODE_TYPES elements, but here we are indexing with SUMO from enum mobility_types
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  if (node_vector[SUMO] != NULL) {
    node_list *tmp = node_vector[SUMO];

    while (tmp != NULL) {
      if ((tmp->node->generator == SUMO) && (tmp->node->mobile == 1)) {
        // OAI node MUST be active
        LOG_I (OMG, "found an active node with id %d \n",
               tmp->node->id);
        LOG_I (OMG, "Old Positions \n");
        //printf("Old Positions \n");
        display_node_position (tmp->node->id, tmp->node->generator,
                               tmp->node->type, tmp->node->mobile,
                               tmp->node->x_pos, tmp->node->y_pos);

        update_sumo_positions (tmp->node);

        //printf("New Positions \n");
        LOG_I (OMG, "New Positions \n");
        display_node_position (tmp->node->id, tmp->node->generator,
                               tmp->node->type, tmp->node->mobile,
                               tmp->node->x_pos, tmp->node->y_pos);
      }

      tmp = tmp->next;
461
    }
462
463
  }

464
465
466
  return active_nodes;
}

467
468
469
470
471
node_struct *
get_first_inactive_OAI_node (node_list * list, int node_type)
{
  node_list *current;

472
473
474
475
476
477
478
479
480
481
482
  if (list != NULL) {
    //start search
    current = list;

    while (current->next != NULL) {
      if ((current->node->mobile == 0)
          && (current->node->type == node_type)) {
        return current->node;
      }

      current = current->next;
483
    }
484
485
486
  }

  return NULL;      // all nodes are active already..reached the maximum number of OAI nodes
487
488
}

489
490
491
492
493
bool
stop_sumo_generator (void)
{
#ifdef STANDALONE
  printf
494
  (" --------Destructor for SUMO: closing the TraCI socket and killing SUMO ---- \n");
495
496
#else
  LOG_I (OMG,
497
         " --------Destructor for SUMO: closing the TraCI socket and killing SUMO ---- \n");
498
#endif
499
500
501
  commandClose ();    // closing the connection with SUMO via TraCI
  close_connection ();    // closing the socket connection
  kill (pid, SIGKILL);    // killing SUMO in case it could not close by itself
502
503
  return true;
}