/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /*! \file rwalk.c * \brief random walk mobility generator * \author S. Gashaw, N. Nikaein, J. Harri, M. Mahersi * \date 2014 * \version 0.1 * \company Eurecom * \email: * \note * \warning */ #include #include #include #include #include "rwalk.h" #include "steadystaterwp.h" int start_rwalk_generator (omg_global_param omg_param_list) { int id; static int n_id = 0; double cur_time = 0.0, pause_p, mean_pause, mean_travel; node_struct *node = NULL; mobility_struct *mobility = NULL; pair_struct *pair = NULL; srand (omg_param_list.seed + RWALK); mean_pause = (omg_param_list.max_sleep - omg_param_list.min_sleep) / 2; mean_travel = (omg_param_list.max_journey_time - omg_param_list.min_journey_time) / 2; pause_p = mean_pause / (mean_travel + mean_pause); LOG_I (OMG, "#RWALK 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 = RWALK; node->event_num = 0; place_rwalk_node (node); //initial positions pair = (pair_struct *) malloc (sizeof (struct pair_struct)); pair->b = node; // sleep_rwalk_node (pair, cur_time); //sleep //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[RWALK] = add_job (pair, job_vector_end[RWALK]); if (job_vector[RWALK] == NULL) job_vector[RWALK] = job_vector_end[RWALK]; job_vector_len[RWALK]++; } n_id += omg_param_list.nodes; if (job_vector[RWALK] == NULL) LOG_E (OMG, "[RWP] Job Vector is NULL\n"); return (0); } void place_rwalk_node (node_struct * node) { node->x_pos = (double) ((int) (randomgen (omg_param_list[node->type].min_x, omg_param_list[node->type].max_x) * 100)) / 100; node->mob->x_from = node->x_pos; node->mob->x_to = node->x_pos; node->y_pos = (double) ((int) (randomgen (omg_param_list[node->type].min_y, omg_param_list[node->type].max_y) * 100)) / 100; node->mob->y_from = node->y_pos; node->mob->y_to = node->y_pos; node->mob->speed = 0.0; node->mob->journey_time = 0.0; // LOG_D (OMG, " INITIALIZE RWALK NODE\n "); LOG_I (OMG, "#Initial position of node ID: %d type: %d (X = %.2f, Y = %.2f) speed = 0.0\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]++; } void sleep_rwalk_node (pair_struct * pair, double cur_time) { 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->event_num++; 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, "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, "to wake up at time: cur_time + sleep_duration : %.2f\n", // pair->a); } void move_rwalk_node (pair_struct * pair, double cur_time) { double distance, x_next, y_next, journeytime_next; int i = 0; double dx, dy, x_now, y_now; double alpha, distancex, distancey; node_struct *node; node = pair->b; //LOG_D (OMG, "MOVE RWALK NODE ID: %d\n", node->ID); 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; node->mob->speed = randomgen (omg_param_list[node->type].min_speed, omg_param_list[node->type].max_speed); node->mob->azimuth = randomgen (omg_param_list[node->type].min_azimuth, omg_param_list[node->type].max_azimuth); if (node->event_num == 0) { node->mob->journey_time = residualtime (omg_param_list[node->type]); node->event_num++; } else { node->mob->journey_time = randomgen (omg_param_list[node->type].min_journey_time, omg_param_list[node->type].max_journey_time); } distance = node->mob->speed * node->mob->journey_time; dx = distance * cos (node->mob->azimuth * M_PI / 180); dy = distance * sin (node->mob->azimuth * M_PI / 180); x_next = (double) ((int) ((node->mob->x_from + dx) * 100)) / 100; y_next = (double) ((int) ((node->mob->y_from + dy) * 100)) / 100; /* LOG_D(OMG,"#node %d X FROM %.2f x next %.2f Y FROM %.2f y next %.2f \n\n",node->id,node->mob->x_from,x_next, node->mob->y_from,y_next); */ alpha = (node->mob->azimuth * M_PI / 180); //in radian x_now = node->mob->x_from; y_now = node->mob->y_from; while (true) { if (x_next < omg_param_list[node->type].min_x) { distancex = (omg_param_list[node->type].min_x - x_now) / cos (alpha); } else if (x_next > omg_param_list[node->type].max_x) { distancex = (omg_param_list[node->type].max_x - x_now) / cos (alpha); } else { distancex = distance; } if (y_next < omg_param_list[node->type].min_y) { distancey = (omg_param_list[node->type].min_y - y_now) / sin (alpha); } else if (y_next > omg_param_list[node->type].max_y) { distancey = (omg_param_list[node->type].max_y - y_now) / sin (alpha); } else { distancey = distance; } if ((distancex == distance && distancey == distance)) break; if (distancey < distancex) { x_now = distancey * cos (alpha) + x_now; y_now = distancey * sin (alpha) + y_now; distance = distance - distancey; dx = distance * cos (2 * M_PI - alpha); dy = distance * sin (2 * M_PI - alpha); x_next = x_now + dx; y_next = y_now + dy; alpha = 2 * M_PI - alpha; } else if (distancex < distancey) { x_now = distancex * cos (alpha) + x_now; y_now = distancex * sin (alpha) + y_now; distance = distance - distancex; dx = distance * cos (M_PI - alpha); dy = distance * sin (M_PI - alpha); x_next = x_now + dx; y_next = y_now + dy; alpha = M_PI - alpha; } i++; } node->mob->x_to = x_next; node->mob->y_to = y_next; /*LOG_D(OMG,"#node %d x to %.2f y to %.2f \n\n",node->id,node->mob->x_to,node->mob->y_to); node->mob->start_journey = cur_time; */ journeytime_next = (double) ((int) (distance / node->mob->speed * 100)) / 100; pair->next_event_t = (double) ((int) ((node->mob->start_journey + journeytime_next) * 100)) / 100; if (node->event_num < 100) { event_sum[node->event_num] += node->mob->speed; events[node->event_num]++; node->event_num++; } } double residualtime (omg_global_param omg_param) { double u; u = randomgen (0, 1); if (u < (2 * omg_param.min_sleep / (omg_param.max_journey_time + omg_param.min_journey_time))) return u * (omg_param.max_journey_time + omg_param.min_journey_time) / 2; else return omg_param.max_journey_time - sqrtf ((1 - u) * (pow (omg_param.max_journey_time, 2) - pow (omg_param.min_sleep, 2))); } void update_rwalk_nodes (double cur_time) { int done = 0; job_list *tmp = job_vector[RWALK]; 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_rwalk_node (tmp->pair, cur_time); else move_rwalk_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_rwalk_node (tmp->pair, cur_time); else move_rwalk_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[RWALK] = quick_sort (job_vector[RWALK]); /////////// // LOG_D (OMG, "--------DISPLAY JOB LIST AFTER SORTING--------\n"); //display_job_list (job_vector[RWALK]); } void get_rwalk_positions_updated (double cur_time) { double x_now = 0.0, y_now = 0.0; double len, dx, dy; double distancex, distancey, alpha; double x_next, y_next; job_list *tmp = job_vector[RWALK]; while (tmp != NULL) { if (tmp->pair->b->mobile == 1 && tmp->pair->next_event_t >= cur_time) { len = tmp->pair->b->mob->speed * (cur_time - tmp->pair->b->mob->start_journey); dx = len * cos (tmp->pair->b->mob->azimuth * M_PI / 180); dy = len * sin (tmp->pair->b->mob->azimuth * M_PI / 180); x_next = (double) ((int) ((tmp->pair->b->mob->x_from + dx) * 100)) / 100; y_next = (double) ((int) ((tmp->pair->b->mob->y_from + dy) * 100)) / 100; alpha = (tmp->pair->b->mob->azimuth * M_PI / 180); //in radian x_now = tmp->pair->b->mob->x_from; y_now = tmp->pair->b->mob->y_from; while (true) { if (x_next < omg_param_list[tmp->pair->b->type].min_x) { distancex = (omg_param_list[tmp->pair->b->type].min_x - x_now) / cos (alpha); } else if (x_next > omg_param_list[tmp->pair->b->type].max_x) { distancex = (omg_param_list[tmp->pair->b->type].max_x - x_now) / cos (alpha); } else { distancex = len; } if (y_next < omg_param_list[tmp->pair->b->type].min_y) { distancey = (omg_param_list[tmp->pair->b->type].min_y - y_now) / sin (alpha); } else if (y_next > omg_param_list[tmp->pair->b->type].max_y) { distancey = (omg_param_list[tmp->pair->b->type].max_y - y_now) / sin (alpha); } else { distancey = len; } if (distancex == len && distancey == len) break; if (distancey < distancex) { x_now = distancey * cos (alpha) + x_now; y_now = distancey * sin (alpha) + y_now; len = len - distancey; dx = len * cos (2 * M_PI - alpha); dy = len * sin (2 * M_PI - alpha); x_next = x_now + dx; y_next = y_now + dy; alpha = 2 * M_PI - alpha; } else if (distancex < distancey) { x_now = distancex * cos (alpha) + x_now; y_now = distancex * sin (alpha) + y_now; len = len - distancex; dx = len * cos (M_PI - alpha); dy = len * sin (M_PI - alpha); x_next = x_now + dx; y_next = y_now + dy; alpha = M_PI - alpha; } } tmp->pair->b->x_pos = (double) ((int) (x_next * 100)) / 100; tmp->pair->b->y_pos = (double) ((int) (y_next * 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; } //if(tmp->pair->b->id==2 && ((int)(cur_time*1000)% 100)==0) //LOG_D (OMG, "%d %.2f %.2f \n\n",tmp->pair->b->id,tmp->pair->b->x_pos,tmp->pair->b->y_pos); tmp = tmp->next; } }