/******************************************************************************* 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@lists.eurecom.fr Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE *******************************************************************************/ /*! \file steadystaterwp.c * \brief random waypoint mobility generator * \author S. Gashaw, J. Harri, N. Nikaein, * \date 2014 * \version 0.1 * \company Eurecom * \email: * \note * \warning */ #include #include #include #include #include "omg.h" #include "steadystaterwp.h" #include "rwp.h" #define RESTIRICTED_RWP 1 #define CONNECTED_DOMAIN 2 int start_steadystaterwp_generator (omg_global_param omg_param_list) { static int n_id = 0; int id; double cur_time = 0.0, pause_p; node_struct *node = NULL; mobility_struct *mobility = NULL; pair_struct *pair = NULL; pause_p = pause_probability (omg_param_list); srand (omg_param_list.seed + RWP); LOG_I (OMG, "STEADY_RWP mobility model for %d %d nodes\n", omg_param_list.nodes, omg_param_list.nodes_type); for (id = n_id; id < (omg_param_list.nodes + n_id); id++) { node = create_node (); mobility = create_mobility (); node->id = id; node->type = omg_param_list.nodes_type; node->mob = mobility; node->generator = STEADY_RWP; node->event_num = 0; place_rwp_node (node); //initial positions pair = (pair_struct *) malloc (sizeof (struct pair_struct)); pair->b = node; //pause probability...some of the nodes start at pause & the other on move if (randomgen (0, 1) < pause_p) sleep_steadystaterwp_node (pair, cur_time); //sleep else move_steadystaterwp_node (pair, cur_time); job_vector_end[STEADY_RWP] = add_job (pair, job_vector_end[STEADY_RWP]); if (job_vector[STEADY_RWP] == NULL) job_vector[STEADY_RWP] = job_vector_end[STEADY_RWP]; job_vector_len[STEADY_RWP]++; } n_id += omg_param_list.nodes; if (job_vector[STEADY_RWP] == NULL) LOG_E (OMG, "[STEADY_RWP] Job Vector is NULL\n"); return (0); } /*********************************xxxxxx************************************/ void place_steadystaterwp_node (node_struct * node) { int loc_num; double block_xmin, block_ymin; if (grid == RESTIRICTED_RWP) { loc_num = (int) randomgen (0, omg_param_list[node->type].max_vertices); node->x_pos = (double) vertice_xpos (loc_num, omg_param_list[node->type]); node->y_pos = (double) vertice_ypos (loc_num, omg_param_list[node->type]); //LOG_D(OMG,"location number %d x pos %.2f y pos %.2f \n\n",loc_num,node->x_pos,node->y_pos); } else if (grid == CONNECTED_DOMAIN) { node->block_num = (int) randomgen (0, omg_param_list[node->type].max_block_num); block_xmin = area_minx (node->block_num, omg_param_list[node->type]); block_ymin = area_miny (node->block_num, omg_param_list[node->type]); node->x_pos = (double) ((int) (randomgen (block_xmin, xloc_div + block_xmin) * 100)) / 100; node->y_pos = (double) ((int) (randomgen (block_ymin, yloc_div + block_ymin) * 100)) / 100; } else { node->x_pos = (double) ((int) (randomgen (omg_param_list[node->type].min_x, omg_param_list[node->type].max_x) * 100)) / 100; node->y_pos = (double) ((int) (randomgen (omg_param_list[node->type].min_y, omg_param_list[node->type].max_y) * 100)) / 100; } node->mob->x_from = node->x_pos; node->mob->x_to = node->x_pos; node->mob->y_from = node->y_pos; node->mob->speed = 0.0; node->mob->journey_time = 0.0; LOG_I (OMG, "#[STEADY_RWP] Initial position of node ID: %d type: %d X = %.2f, Y = %.2f\n ", node->id, node->type, node->x_pos, node->y_pos); 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]++; //Initial_Node_Vector_len[RWP]++; } /*********************************xxxxxx************************************/ void sleep_steadystaterwp_node (pair_struct * pair, double cur_time) { //static int initial = 1; node_struct *node; 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; if (node->event_num == 0) { node->mob->sleep_duration = initial_pause (omg_param_list[node->type]); node->event_num++; } else { node->mob->sleep_duration = (double) ((int) (randomgen (omg_param_list[node->type].min_sleep, omg_param_list[node->type].max_sleep) * 100)) / 100; } // LOG_D (OMG, "[STEADY_RWP] node: %d \tsleep duration : %.2f\n", node->ID, // node->mob->sleep_duration); node->mob->start_journey = cur_time; pair->next_event_t = cur_time + node->mob->sleep_duration; //when to wake up // LOG_D (OMG, "[STEADY_RWP] wake up at time: cur_time + sleep_duration : %.2f\n", // pair->a); } void move_steadystaterwp_node (pair_struct * pair, double cur_time) { //static int initial = 1; double distance, journeytime_next, max_distance; double temp_x, temp_y, u1, u2; //int loc_num; double pr, block_xmin, block_ymin; //LOG_D (OMG, "[STEADY_RWP] move node: %d\n", node->ID); node_struct *node; node = pair->b; 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; node->mobile = 1; //initial move if (node->event_num == 0) { if (grid == CONNECTED_DOMAIN) { max_distance = 2 * yloc_div; /* sqrtf (pow (omg_param_list[node->type].max_x - omg_param_list[node->type].min_x, 2) + pow (omg_param_list[node->type].max_y - omg_param_list[node->type].min_y, 2)); */ while (true) { pr = randomgen (0, 1); if (pr <= 0.50) /*node->block_num = (int) randomgen (0, omg_param_list[node->type].max_block_num); */ node->block_num = (int) next_block (node->block_num, omg_param_list[node->type]); block_xmin = area_minx (node->block_num, omg_param_list[node->type]); block_ymin = area_miny (node->block_num, omg_param_list[node->type]); node->mob->x_to = (double) ((int) (randomgen (block_xmin, xloc_div + block_xmin) * 100)) / 100; node->mob->y_to = (double) ((int) (randomgen (block_ymin, yloc_div + block_ymin) * 100)) / 100; pr = randomgen (0, 1); if (pr <= 0.50) /*node->block_num = (int) randomgen (0, omg_param_list[node->type].max_block_num); */ node->block_num = (int) next_block (node->block_num, omg_param_list[node->type]); block_xmin = area_minx (node->block_num, omg_param_list[node->type]); block_ymin = area_miny (node->block_num, omg_param_list[node->type]); temp_x = (double) ((int) (randomgen (block_xmin, xloc_div + block_xmin) * 100)) / 100; temp_y = (double) ((int) (randomgen (block_ymin, yloc_div + block_ymin) * 100)) / 100; u1 = randomgen (0, 1); if (u1 < (sqrtf (pow (node->mob->x_to - temp_x, 2) + pow (node->mob->y_to - temp_y, 2)) / max_distance)) { u2 = randomgen (0, 1); distance = (double) ((int) (sqrtf (pow (temp_x - node->mob->x_to, 2) + pow (temp_y - node->mob->y_to, 2)) * 100)) / 100; node->mob->azimuth = atan2 (node->mob->y_to - node->mob->y_from, node->mob->x_to - node->mob->x_from); //radian node->mob->x_from = temp_x + u2 * distance * cos (node->mob->azimuth); node->mob->y_from = temp_y + u2 * distance * sin (node->mob->azimuth); break; } } } else { max_distance = sqrtf (pow (omg_param_list[node->type].max_x - omg_param_list[node->type].min_x, 2) + pow (omg_param_list[node->type].max_y - omg_param_list[node->type].min_y, 2)); while (true) { node->mob->x_to = (double) ((int) (randomgen (omg_param_list[node->type].min_x, omg_param_list[node->type].max_x) * 100)) / 100; node->mob->y_to = (double) ((int) (randomgen (omg_param_list[node->type].min_y, omg_param_list[node->type].max_y) * 100)) / 100; temp_x = (double) ((int) (randomgen (omg_param_list[node->type].min_x, omg_param_list[node->type].max_x) * 100)) / 100; temp_y = (double) ((int) (randomgen (omg_param_list[node->type].min_y, omg_param_list[node->type].max_y) * 100)) / 100; u1 = randomgen (0, 1); if (u1 < (sqrtf (pow (node->mob->x_to - temp_x, 2) + pow (node->mob->y_to - temp_y, 2)) / max_distance)) { u2 = randomgen (0, 1); node->mob->x_from = u2 * temp_x + (1 - u2) * node->mob->x_to; node->mob->y_from = u2 * temp_y + (1 - u2) * node->mob->y_to; break; } } } node->mob->speed = initial_speed (omg_param_list[node->type]); node->event_num++; distance = (double) ((int) (sqrtf (pow (node->mob->x_from - node->mob->x_to, 2) + pow (node->mob->y_from - node->mob->y_to, 2)) * 100)) / 100; } //for the next move else { if (grid == CONNECTED_DOMAIN) { pr = randomgen (0, 1); if (pr <= 0.50) /* node->block_num = (int) randomgen (0, omg_param_list[node->type].max_block_num); */ node->block_num = (int) next_block (node->block_num, omg_param_list[node->type]); block_xmin = area_minx (node->block_num, omg_param_list[node->type]); block_ymin = area_miny (node->block_num, omg_param_list[node->type]); node->mob->x_to = (double) ((int) (randomgen (block_xmin, xloc_div + block_xmin) * 100)) / 100; node->mob->y_to = (double) ((int) (randomgen (block_ymin, yloc_div + block_ymin) * 100)) / 100; distance = (double) ((int) (sqrtf (pow (node->mob->x_from - node->mob->x_to, 2) + pow (node->mob->y_from - node->mob->y_to, 2)) * 100)) / 100; node->mob->azimuth = atan2 (node->mob->y_to - node->mob->y_from, node->mob->x_to - node->mob->x_from); } else { node->mob->x_to = (double) ((int) (randomgen (omg_param_list[node->type].min_x, omg_param_list[node->type].max_x) * 100)) / 100; node->mob->y_to = (double) ((int) (randomgen (omg_param_list[node->type].min_y, omg_param_list[node->type].max_y) * 100)) / 100; distance = (double) ((int) (sqrtf (pow (node->mob->x_from - node->mob->x_to, 2) + pow (node->mob->y_from - node->mob->y_to, 2)) * 100)) / 100; } node->mob->speed = (double) ((int) (randomgen (omg_param_list[node->type].min_speed, omg_param_list[node->type].max_speed) * 100)) / 100; node->event_num++; } journeytime_next = (double) ((int) (distance / node->mob->speed * 100)) / 100; //duration to get to dest //LOG_D (OMG, "[STEADY_RWP] mob->journey_time_next %.2f\n", journeyTime_next); node->mob->start_journey = cur_time; //LOG_D (OMG, "[STEADY_RWP] start_journey %.2f\n", node->mob->start_journey); pair->next_event_t = cur_time + journeytime_next; //when to reach the destination // LOG_D (OMG, // "[STEADY_RWP] reaching the destination at time : start journey + journey_time next =%.2f\n", // pair->a); if (node->event_num < 100) { event_sum[node->event_num] += node->mob->speed; events[node->event_num]++; node->event_num++; } } double pause_probability (omg_global_param omg_param) { double alpha, delta; alpha = (omg_param.max_sleep + omg_param.min_sleep) * (omg_param.max_speed - omg_param.min_speed) / (2 * log (omg_param. max_speed / omg_param. min_speed)); delta = sqrtf (pow (omg_param.max_x - omg_param.min_x, 2) + pow (omg_param.max_y - omg_param.min_y, 2)); return alpha / (alpha + delta); } double initial_pause (omg_global_param omg_param) { double u; u = randomgen (0, 1); if (u < (2 * omg_param.min_sleep / (omg_param.max_sleep + omg_param.min_sleep))) return u * (omg_param.max_sleep + omg_param.min_sleep) / 2; else return omg_param.max_sleep - sqrtf ((1 - u) * (pow (omg_param.max_sleep, 2) - pow (omg_param.min_sleep, 2))); } double initial_speed (omg_global_param omg_param) { double u; u = randomgen (0, 1); return pow (omg_param.max_speed, u) / pow (omg_param.min_speed, u - 1); } /*update RWP nodes position*/ void update_steadystaterwp_nodes (double cur_time) { int done = 0; job_list *tmp = job_vector[STEADY_RWP]; node_struct *my_node; while (tmp != NULL && done == 0) { //case1:time to next event equals to current time if (tmp->pair != NULL && ((double) tmp->pair->next_event_t >= cur_time - omg_eps) && ((double) tmp->pair->next_event_t <= cur_time + omg_eps)) { my_node = tmp->pair->b; if (my_node->mobile == 1) sleep_rwp_node (tmp->pair, cur_time); else move_rwp_node (tmp->pair, cur_time); } //case2: current time is greater than the time to next event else if (tmp->pair != NULL && (cur_time - omg_eps) > tmp->pair->next_event_t) { my_node = tmp->pair->b; while (cur_time >= tmp->pair->next_event_t) { if (my_node->mobile == 1) sleep_rwp_node (tmp->pair, cur_time); else move_rwp_node (tmp->pair, cur_time); } } //case3: current time less than the time to next event else { done = 1; //quit the loop } tmp = tmp->next; } //sorting the new entries //LOG_D (OMG, "--------DISPLAY JOB LIST--------\n"); //LOG_T // display_job_list (job_vector); job_vector[STEADY_RWP] = quick_sort (job_vector[STEADY_RWP]); /////////// // LOG_D (OMG, "--------DISPLAY JOB LIST AFTER SORTING--------\n"); // display_job_list (job_vector[STEADY_RWP]); } void get_steadystaterwp_positions_updated (double cur_time) { double x_now = 0.0, y_now = 0.0; double len, dx, dy; job_list *tmp = job_vector[STEADY_RWP]; while (tmp != NULL) { if (tmp->pair->b->mobile == 1 && tmp->pair->next_event_t >= cur_time) { 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; //len } } 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; } }