/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
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.
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.
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 .
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
/*! \file trace.c
* \brief The trace-based mobility model for OMG/OAI (mobility is statically imported from a file)
* \author S. Gashaw, N. Nikaein, J. Harri
* \date 2014
* \version 0.1
* \company EURECOM
* \email:
* \note
* \warning
*/
#include
#include
#include
#include
#include "trace.h"
#define FIXED 1
#define MOVING 0
extern hash_table_t **table;
extern node_info **list_head;
//check if the next input data is the same as the previous
int
start_trace_generator (omg_global_param omg_param_list)
{
double cur_time = 0.0;
int immobile = 0;
int node_number;
node_struct *node = NULL;
mobility_struct *mobility = NULL;
pair_struct *pair = NULL;
node_info *temp;
parse_data (omg_param_list.mobility_file, omg_param_list.nodes_type); //read mobility file
//LOG_I (OMG, "mobility file %s put in the table %p\n",omg_param_list.mobility_file, table);
node_number = get_number_of_nodes (omg_param_list.nodes_type);
if (node_number == 0)
LOG_E (OMG, "[TRACE] empty input file \n");
LOG_I (OMG, "TRACE mobility model for %d %d nodes\n", node_number,
omg_param_list.nodes_type);
temp = list_head[omg_param_list.nodes_type];
while (temp != NULL)
{
node_data *this_node =
get_next_data (table[omg_param_list.nodes_type], temp->g_id, DATA_AND_STATUS_CHANGE);
if (this_node == NULL)
{
LOG_E (OMG, "[TRACE] Unexpected empty data entry\n");
exit (-1);
}
node = create_node ();
mobility = create_mobility ();
node->id = temp->vid;
node->gid = temp->g_id;
/* if(this_node->type == -1) //if node type is given in the file set the defualt type UE
node->type = UE; */
node->type = omg_param_list.nodes_type;
node->generator = TRACE;
node->mob = mobility;
place_trace_node (node, this_node); //initial positions
if (this_node->visit == 1)
{
pair = (pair_struct *) malloc (sizeof (struct pair_struct));
pair->b = node;
if (this_node->time > cur_time)
{
schedule_trace_node (pair, this_node, cur_time);
}
else
{
if (this_node->x_pos == this_node->next->x_pos &&
this_node->y_pos == this_node->next->y_pos)
sleep_trace_node (pair, this_node, cur_time);
else
move_trace_node (pair, this_node, cur_time); //move
}
//LOG_I (OMG,
//"[TRACE] position of node ID: %d %d\n ",node->id, node->type);
}
else
{
temp = temp->next;
continue;
}
job_vector_end[TRACE] = add_job (pair, job_vector_end[TRACE]);
if (job_vector[TRACE] == NULL)
job_vector[TRACE] = job_vector_end[TRACE];
job_vector_len[TRACE]++;
temp = temp->next;
}
if (job_vector[TRACE] == NULL)
LOG_I (OMG, "[TRACE] Job Vector is NULL\n");
return 0;
}
void
place_trace_node (node_struct * node, node_data * n)
{
node_data *n_ptr = n;
node->x_pos = (double) n_ptr->x_pos;
node->mob->x_from = node->x_pos;
node->mob->x_to = node->x_pos;
node->y_pos = (double) n_ptr->y_pos;
node->mob->y_from = node->y_pos;
node->mob->y_to = node->y_pos;
node->mob->speed = n_ptr->speed;
node->mob->journey_time = 0.0;
// node->start_journey=(double) n_ptr->time; //time of initial position
// node->mob->target_time=(double) n_ptr->next->time; //time of next destination
LOG_I (OMG,
"[TRACE] Initial position of node ID: %d type: %d (X = %.2f, Y = %.2f) speed = %.2f \n ",
node->id, node->type, node->x_pos, node->y_pos, node->mob->speed);
node_vector_end[node->type] =
(node_list *) add_entry (node, node_vector_end[node->type]);
if (node_vector[node->type] == NULL)
node_vector[node->type] = node_vector_end[node->type];
node_vector_len[node->type]++;
}
void
move_trace_node (pair_struct * pair, node_data * n_data, double cur_time)
{
node_struct *node;
node = pair->b;
double cdistance, journeytime, speed;
double journeytime_next, distance;
node->mob->x_from = node->mob->x_to;
node->mob->y_from = node->mob->y_to;
node->mobile = 1;
node->mob->speed = n_data->speed;
node->mob->x_to = (double) n_data->next->x_pos;
node->mob->y_to = (double) n_data->next->y_pos;
node->mob->target_time = (double) n_data->next->time;
//if speed equals to zero compute the speed(i.e node was on sleep move it)
if (node->mob->speed == 0)
{
cdistance =
(double)
sqrtf
(pow (node->mob->x_from - node->mob->x_to, 2) +
pow (node->mob->y_from - node->mob->y_to, 2));
journeytime = node->mob->target_time - n_data->time;
speed = (double) cdistance / journeytime;
node->mob->speed = speed;
}
distance =
(double)
sqrtf
(pow (node->mob->x_from - node->mob->x_to, 2) +
pow (node->mob->y_from - node->mob->y_to, 2));
journeytime_next = (double) distance / node->mob->speed; //time to get to destination
/* LOG_D (OMG,
"[TRACE] mob->journey_time_next %.2f target time %.2f next time %.2f speed %.2f\n",
journeytime_next, node->mob->target_time, n_data->time,
node->mob->speed);*/
node->mob->start_journey = cur_time;
pair->next_event_t = cur_time + journeytime_next; //when to reach the destination
}
void
schedule_trace_node (pair_struct * pair, node_data * n_data, double cur_time)
{
node_struct *node = pair->b;
node->mobile = 3;
node->mob->start_journey = cur_time;
pair->next_event_t = n_data->time; //when to move this node
//LOG_D (OMG, "[TRACE] Node will wake up at time: %.2f\n", pair->next_event_t);
}
void
sleep_trace_node (pair_struct * pair, node_data * n_data, double cur_time)
{
double journeytime, distance;
node_struct *node = pair->b;
node->mobile = 0;
node->mob->speed = 0.0;
node->mob->x_from = node->mob->x_to;
node->mob->y_from = node->mob->y_to;
node->x_pos = node->mob->x_to;
node->y_pos = node->mob->y_to;
//sleep duration
/* */
if (n_data->x_pos == n_data->next->x_pos &&
n_data->y_pos == n_data->next->y_pos)
{
node->mob->sleep_duration = n_data->next->time - n_data->time;
LOG_D(OMG,"[TRACE] curretn and next lcoation are the same : sleep for %f\n",node->mob->sleep_duration);
}
else /* early arrival*/
{ //sleep case 2
//node->mob->sleep_duration = node->mob->target_time - (journeytime + node->mob->start_journey);
node->mob->sleep_duration = node->mob->target_time - pair->next_event_t;
LOG_D(OMG,"[TRACE] Early Arrival (target time > journeytime), sleep for %f target time was %f\n",node->mob->sleep_duration,node->mob->target_time);
}
node->mob->start_journey = cur_time;
pair->next_event_t = cur_time + node->mob->sleep_duration; //when to wake up
/*LOG_D (OMG, "#[TRACE] node: %d \tsleep duration : %.2f\n", node->id,
node->mob->sleep_duration);*/
}
void
update_trace_nodes (double cur_time)
{
job_list *tmp;
int done = 0;
node_data *node_n;
node_struct *my_node;
tmp = job_vector[TRACE];
if (tmp == NULL)
LOG_D (OMG, "[TRACE] last data for all nodes\n");
while (tmp != NULL && done != 1)
{ //1
my_node = tmp->pair->b;
node_n = get_next_data (table[my_node->type], my_node->gid, DATA_ONLY);
//case1:time to next event equals to current time
if (tmp->pair != NULL && tmp->pair->next_event_t >= cur_time - eps
&& tmp->pair->next_event_t <= cur_time )
{
if (node_n->next->next == NULL)
{
tmp->pair->b->x_pos = tmp->pair->b->mob->x_to;
tmp->pair->b->mob->x_from = tmp->pair->b->x_pos;
tmp->pair->b->y_pos = tmp->pair->b->mob->y_to;
tmp->pair->b->mob->y_from = tmp->pair->b->y_pos;
tmp->pair->b->mobile = 0;
tmp->pair->b->mob->speed = 0.0;
// LOG_D (OMG, "[TRACE] last data for all nodes\n");
tmp = tmp->next;
continue;
}
//LOG_D (OMG, "[TRACE] last data for all nodes\n");
if (my_node->mobile == 1)
{
if (my_node->mob->target_time > tmp->pair->next_event_t) //sleep node
{
sleep_trace_node (tmp->pair, node_n, cur_time);
}
else
{
node_n =
get_next_data (table[my_node->type], my_node->gid,
DATA_AND_STATUS_CHANGE);
if (node_n->x_pos == node_n->next->x_pos &&
node_n->y_pos == node_n->next->y_pos)
sleep_trace_node (tmp->pair, node_n, cur_time);
else
move_trace_node (tmp->pair, node_n, cur_time);
}
}
else if (my_node->mobile == 0)
{
node_n =
get_next_data (table[my_node->type], my_node->gid, DATA_AND_STATUS_CHANGE);
if (node_n->x_pos == node_n->next->x_pos &&
node_n->y_pos == node_n->next->y_pos)
sleep_trace_node (tmp->pair, node_n, cur_time);
else
move_trace_node (tmp->pair, node_n, cur_time);
}
else
{
node_n = get_next_data (table[my_node->type], my_node->gid, DATA_ONLY);
if (node_n->x_pos == node_n->next->x_pos &&
node_n->y_pos == node_n->next->y_pos)
sleep_trace_node (tmp->pair, node_n, cur_time);
else
move_trace_node (tmp->pair, node_n, cur_time);
}
}
//case2: current time is greater than the time to next event
else if (tmp->pair != NULL && cur_time > tmp->pair->next_event_t)
{
if (node_n->next->next == NULL)
{
tmp->pair->b->x_pos = tmp->pair->b->mob->x_to;
tmp->pair->b->mob->x_from = tmp->pair->b->x_pos;
tmp->pair->b->y_pos = tmp->pair->b->mob->y_to;
tmp->pair->b->mob->y_from = tmp->pair->b->y_pos;
tmp->pair->b->mobile = 0;
tmp->pair->b->mob->speed = 0.0;
// LOG_D (OMG, "[TRACE] last data for all nodes\n");
tmp = tmp->next;
continue;
}
while (cur_time >= tmp->pair->next_event_t)
{
if (node_n->next->next == NULL)
{
tmp->pair->b->x_pos = tmp->pair->b->mob->x_to;
tmp->pair->b->mob->x_from = tmp->pair->b->x_pos;
tmp->pair->b->y_pos = tmp->pair->b->mob->y_to;
tmp->pair->b->mob->y_from = tmp->pair->b->y_pos;
break;
}
if (my_node->mobile == 1)
{
if (my_node->mob->target_time > tmp->pair->next_event_t) //sleep node
{
sleep_trace_node (tmp->pair, node_n, cur_time);
}
else
{
node_n =
get_next_data (table[my_node->type], my_node->gid,
DATA_AND_STATUS_CHANGE);
if (node_n->x_pos == node_n->next->x_pos &&
node_n->y_pos == node_n->next->y_pos)
sleep_trace_node (tmp->pair, node_n, cur_time);
else
move_trace_node (tmp->pair, node_n, cur_time);
}
}
else if (my_node->mobile == 0)
{
node_n =
get_next_data (table[my_node->type], my_node->gid,
DATA_AND_STATUS_CHANGE);
if (node_n->x_pos == node_n->next->x_pos &&
node_n->y_pos == node_n->next->y_pos)
sleep_trace_node (tmp->pair, node_n, cur_time);
else
move_trace_node (tmp->pair, node_n, cur_time);
}
else
{
node_n = get_next_data (table[my_node->type], my_node->gid, DATA_ONLY);
if (node_n->x_pos == node_n->next->x_pos &&
node_n->y_pos == node_n->next->y_pos)
sleep_trace_node (tmp->pair, node_n, cur_time);
else
move_trace_node (tmp->pair, node_n, cur_time);
}
node_n = get_next_data (table[my_node->type], my_node->gid, DATA_ONLY);
if (node_n == NULL || node_n->next == NULL)
{
break;
}
} //2
}
//case3: current time less than the time to next event
else
{
done = 1; //quit the loop
}
tmp = tmp->next;
} //1
//sorting the new entries
//LOG_D (OMG, "--------DISPLAY JOB LIST--------\n"); //LOG_T
// display_job_list (Job_Vector);
job_vector[TRACE] = quick_sort (job_vector[TRACE]); ///////////
//LOG_D (OMG, "--------DISPLAY JOB LIST AFTER SORTING--------\n");
// display_job_list( job_vector[TRACE]);
}
void
get_trace_positions_updated (double cur_time)
{
double x_now = 0.0, y_now = 0.0;
double len, dx, dy;
job_list *tmp = job_vector[TRACE];
while (tmp != NULL)
{
if (tmp->pair->b->mobile == 1 && tmp->pair->next_event_t >= cur_time)
{
//printf("hiiiiiiiiiii \n");
len =
sqrtf (pow
(tmp->pair->b->mob->x_from -
tmp->pair->b->mob->x_to,
2) + pow (tmp->pair->b->mob->y_from -
tmp->pair->b->mob->y_to, 2));
if (len != 0)
{
dx =
fabs (tmp->pair->b->mob->x_from -
tmp->pair->b->mob->x_to) / len;
dy =
fabs (tmp->pair->b->mob->y_from -
tmp->pair->b->mob->y_to) / len;
//x coordinate
if (tmp->pair->b->mob->x_from < tmp->pair->b->mob->x_to)
{
x_now =
tmp->pair->b->mob->x_from +
(dx *
(tmp->pair->b->mob->speed *
(cur_time - tmp->pair->b->mob->start_journey)));
}
else
{
x_now =
tmp->pair->b->mob->x_from -
(dx *
(tmp->pair->b->mob->speed *
(cur_time - tmp->pair->b->mob->start_journey)));
}
//y coordinate
if (tmp->pair->b->mob->y_from < tmp->pair->b->mob->y_to)
{
y_now =
tmp->pair->b->mob->y_from +
(dy *
(tmp->pair->b->mob->speed *
(cur_time - tmp->pair->b->mob->start_journey)));
}
else
{
y_now =
tmp->pair->b->mob->y_from -
(dy *
(tmp->pair->b->mob->speed *
(cur_time - tmp->pair->b->mob->start_journey)));
}
tmp->pair->b->x_pos = (double) ((int) (x_now * 100)) / 100;
tmp->pair->b->y_pos = (double) ((int) (y_now * 100)) / 100;
}
else
{
tmp->pair->b->x_pos = tmp->pair->b->mob->x_to;
tmp->pair->b->y_pos = tmp->pair->b->mob->y_to;
}
}
tmp = tmp->next;
}
}
void
clear_list (void)
{
}