bool Microsimulator::Lane_Change (Msim_Vehicle *vehicle_ptr) { int dir, cell, lane, new_cell, new_lane, vehicle, best_out; bool use_flag, permit_flag; Travel_Plan_Data *plan_ptr, *plan2_ptr; Msim_Vehicle *veh2_ptr; Veh_Type_Data *veh_type_ptr; Grid_Data *grid_ptr; Travel_Leg_Data *leg_ptr, *leg2_ptr; if (vehicle_ptr->Lane_Change () == 0 || vehicle_ptr->Dir () == 0) return (false); lane = vehicle_ptr->Lane (); //--- check for lane changes ---- plan_ptr = vehicle_ptr->Travel_Plan (); if (plan_ptr == NULL) return (false); leg_ptr = plan_ptr->Travel_Leg (vehicle_ptr->Leg ()); if (leg_ptr == NULL) return (false); dir = vehicle_ptr->Dir (); grid_ptr = grid_data [dir]; if (grid_ptr == NULL) return (false); cell = new_cell = vehicle_ptr->Cell (); veh_type_ptr = veh_type_data [vehicle_ptr->Type ()]; if (vehicle_ptr->Blocked ()) { new_lane = (leg_ptr->Out_Best_Low () + leg_ptr->Out_Best_High ()) / 2; if (lane <= new_lane) { if (Cell_Use (cell+1, lane+1, grid_ptr, veh_type_ptr->Use ())) { new_lane = lane + 1; } else { new_lane = lane - 1; } } else if (Cell_Use (cell+1, lane-1, grid_ptr, veh_type_ptr->Use ())) { new_lane = lane - 1; } else { new_lane = lane + 1; } } else if (lane <= leg_ptr->Out_Best_Low () && lane < leg_ptr->Out_Best_High ()) { new_lane = lane + 1; } else if (lane >= leg_ptr->Out_Best_High () && lane > leg_ptr->Out_Best_Low ()) { new_lane = lane - 1; } else if (lane <= leg_ptr->Out_Lane_Low () && lane < leg_ptr->Out_Lane_High ()) { new_lane = lane + 1; } else if (lane >= leg_ptr->Out_Lane_High () && lane > leg_ptr->Out_Lane_Low ()) { new_lane = lane - 1; } else if (lane > 1) { new_lane = lane - 1; } else { new_lane = lane + 1; } //---- check the target lane ---- if (new_lane < 1 || new_lane > grid_ptr->Lanes ()) return (false); vehicle = grid_ptr->Data (cell, new_lane); if (vehicle < 0) return (false); if (vehicle > 0 && vehicle_ptr->Lane_Change () > 1) return (false); use_flag = false; if (!Cell_Use (cell, new_lane, grid_ptr, veh_type_ptr->Use ())) { if (cell == grid_ptr->Cell_Out ()) { use_flag = true; } else { return (false); } } //---- check the vehicle status ---- if (vehicle > 0) { veh2_ptr = vehicle_data [vehicle]; if (veh2_ptr == NULL) return (false); if (veh2_ptr->Dir () == 0) return (false); if (veh2_ptr->Status () == 0 || !veh2_ptr->Move_Flag ()) { if (veh2_ptr->Reserve () == 0 && grid_ptr->To_Data (cell, new_lane) == 0) { veh2_ptr->Reserve (plan_ptr->Vehicle ()); } //---- check for the front of a multi-cell vehicle ---- if (veh2_ptr->Lane_Change () == 0) return (false); if (veh2_ptr->Num_Cells () > 1 && veh2_ptr->Cell () != cell) return (false); if (vehicle_ptr->Num_Cells () > 1 && veh2_ptr->Speed () > 0) return (false); //---- check the relative speeds ---- if (vehicle_ptr->Speed () > max_swap_speed) return (false); if (veh2_ptr->Speed () > max_swap_speed) return (false); if (abs (vehicle_ptr->Speed () - veh2_ptr->Speed ()) > max_swap_diff) return (false); //---- attempt to swap positions ---- if (vehicle_ptr->Num_Cells () == 1 && veh2_ptr->Num_Cells () == 1) { //--- check for lane changes ---- plan2_ptr = veh2_ptr->Travel_Plan (); if (plan2_ptr == NULL) return (false); leg2_ptr = plan2_ptr->Travel_Leg (veh2_ptr->Leg ()); if (leg2_ptr == NULL) return (false); if (new_lane <= leg2_ptr->Out_Best_Low () && new_lane < leg2_ptr->Out_Best_High ()) { best_out = new_lane + 1; } else if (new_lane >= leg2_ptr->Out_Best_High () && new_lane > leg2_ptr->Out_Best_Low ()) { best_out = new_lane - 1; } else if (new_lane <= leg2_ptr->Out_Lane_Low () && new_lane < leg2_ptr->Out_Lane_High ()) { best_out = new_lane + 1; } else if (new_lane >= leg2_ptr->Out_Lane_High () && new_lane > leg2_ptr->Out_Lane_Low ()) { best_out = new_lane - 1; } else if (new_lane > 1) { best_out = new_lane - 1; } else { best_out = new_lane + 1; } if (best_out != lane) return (false); //--- exchange positions ---- grid_ptr->Data (cell, lane, plan2_ptr->Vehicle ()); grid_ptr->Data (cell, new_lane, plan_ptr->Vehicle ()); veh2_ptr->Lane (lane); veh2_ptr->Move_Flag (true); veh2_ptr->Lane_Change (0); vehicle_ptr->Lane (new_lane); vehicle_ptr->Move_Flag (true); vehicle_ptr->Lane_Change (0); if (veh2_ptr->Reserve () == plan_ptr->Vehicle ()) { veh2_ptr->Reserve (0); } nswap += 2; return (true); } //---- try to move the vehicle diagonally ----- if (cell == grid_ptr->Cells () || permit_none) return (false); vehicle_ptr->Lane (new_lane); min_speed = 0; if (!Check_Ahead (vehicle_ptr) || max_speed == 0) { vehicle_ptr->Lane (lane); return (false); } new_cell = cell + 1; } } //---- check the merge ---- vehicle_ptr->Cell (new_cell); vehicle_ptr->Lane (new_lane); if (!Check_Behind (vehicle_ptr) || !Check_Ahead (vehicle_ptr) || (use_flag && max_speed == 0)) { vehicle_ptr->Cell (cell); vehicle_ptr->Lane (lane); return (false); } //---- check the permissive behavior ---- vehicle = grid_ptr->Data (new_cell-1, new_lane); if (vehicle > 0) { if (permit_all) { permit_flag = true; } else if (permit_none) { permit_flag = false; } else { permit_flag = (random.Probability () <= permission_prob [grid_ptr->Type ()]); } if (permit_flag) { vehicle_ptr->Reserve (vehicle); } else { vehicle_ptr->Cell (cell); vehicle_ptr->Lane (lane); veh2_ptr = vehicle_data [vehicle]; if (veh2_ptr == NULL) return (false); if (veh2_ptr->Status () == 1 && !veh2_ptr->Move_Flag ()) { veh2_ptr->Status (0); veh2_ptr->Waiting (veh2_ptr->Waiting () - 10 * steps_per_second); dir = veh2_ptr->Dir (); cell = veh2_ptr->Cell (); lane = veh2_ptr->Lane (); grid_ptr = grid_data [dir]; if (grid_ptr == NULL) return (false); grid_ptr->To_Data (cell, lane, 0); next_vehicle = vehicle; } return (false); } } //---- move the vehicle ---- if (vehicle_ptr->Num_Cells () > 1) { vehicle_ptr->Cell (cell); vehicle_ptr->Lane (lane); vehicle_ptr->To_Dir (dir); vehicle_ptr->To_Cell (new_cell); vehicle_ptr->To_Lane (new_lane); Move_Veh_Cells (vehicle_ptr, true); } else { grid_ptr->Data (cell, lane, 0); grid_ptr->Data (new_cell, new_lane, plan_ptr->Vehicle ()); } vehicle_ptr->Move_Flag (true); vehicle_ptr->Lane_Change (0); nrequired++; return (true); }
int Sim_Node_Process::Sum_Path (Sim_Dir_Ptr sim_dir_ptr, int lane, int cell, Travel_Step &step) { int cells, num_cells, sum_speed, num_lanes, num_veh, best_weight, weight; int speed, max_cell, dir_index, traveler, from_lane, from_index, l, high, low; Dir_Data *dir_ptr; Sim_Plan_Ptr sim_plan_ptr; Sim_Leg_Ptr leg_ptr, next_ptr; Sim_Park_Ptr sim_park_ptr; Sim_Travel_Ptr sim_travel_ptr; //---- initial conditions ---- num_cells = sim->Offset_Cell (sim->param.look_ahead); sum_speed = num_lanes = num_veh = 0; speed = step.sim_travel_ptr->Speed (); sim_plan_ptr = step.sim_travel_ptr->Get_Plan (); //---- get the plan data ---- leg_ptr = step.sim_leg_ptr; next_ptr = sim_plan_ptr->Get_Next (leg_ptr); dir_index = leg_ptr->Index (); max_cell = sim_dir_ptr->Max_Cell (); if (next_ptr != 0 && next_ptr->Type () == PARKING_ID) { sim_park_ptr = &sim->sim_park_array [next_ptr->Index ()]; if (sim_park_ptr->Type () != BOUNDARY) { if (sim_dir_ptr->Dir () == 0) { max_cell = sim->Offset_Cell (sim_park_ptr->Offset_AB ()); } else { max_cell = sim->Offset_Cell (sim_park_ptr->Offset_BA ()); } } } for (cells=1; cells <= num_cells; cells++) { cell++; //---- move forward ---- if (cell > max_cell) { //---- set the exit speed ---- if (leg_ptr->Max_Speed () < speed) { speed = leg_ptr->Max_Speed (); } //---- check the exit lane ---- if (lane < leg_ptr->Out_Lane_Low ()) { num_lanes += leg_ptr->Out_Lane_Low () - lane; lane = leg_ptr->Out_Lane_Low (); speed = 0; } else if (lane > leg_ptr->Out_Lane_High ()) { num_lanes += lane - leg_ptr->Out_Lane_High (); lane = leg_ptr->Out_Lane_High (); speed = 0; } from_lane = lane; from_index = dir_index; if (next_ptr == 0 || next_ptr->Type () != DIR_ID) break; dir_index = next_ptr->Index (); sim_dir_ptr = &sim->sim_dir_array [dir_index]; if (sim_dir_ptr->Method () < MESOSCOPIC) break; leg_ptr = next_ptr; //---- find the best connection ---- lane = -1; best_weight = 0; low = leg_ptr->In_Lane_Low (); high = leg_ptr->In_Lane_High (); for (l=low; l < high; l++) { weight = 0; if (sim_dir_ptr->Thru_Link (l) == from_index && sim_dir_ptr->Thru_Lane (l) == from_lane) { weight += sim->param.connect_lane_weight; } if (Cell_Use (sim_dir_ptr, l, 0, step)) { weight += sim->param.lane_use_weight; } if (l >= leg_ptr->In_Best_Low () && l <= leg_ptr->In_Best_High ()) { weight += sim->param.connect_lane_weight; } if (weight > best_weight) { lane = l; best_weight = weight; } } if (lane < 0) break; cell = 0; next_ptr = sim_plan_ptr->Get_Next (leg_ptr); max_cell = sim_dir_ptr->Max_Cell (); if (next_ptr != 0 && next_ptr->Type () == PARKING_ID) { sim_park_ptr = &sim->sim_park_array [next_ptr->Index ()]; if (sim_park_ptr->Type () != BOUNDARY) { if (sim_dir_ptr->Dir () == 0) { max_cell = sim->Offset_Cell (sim_park_ptr->Offset_AB ()); } else { max_cell = sim->Offset_Cell (sim_park_ptr->Offset_BA ()); } } } } //---- check the use restrictions ---- if (!Cell_Use (sim_dir_ptr, lane, cell, step)) { if (lane > 0) { while (lane > 0) { num_lanes++; if (Cell_Use (sim_dir_ptr, --lane, cell, step)) break; } } else { while (lane < (sim_dir_ptr->Lanes () - 1)) { num_lanes++; if (Cell_Use (sim_dir_ptr, ++lane, cell, step)) break; } } speed = 0; } else { //---- check the cell availability ----- traveler = sim_dir_ptr->Get (lane, cell); if (traveler == -1) { //---- pocket lane ---- dir_ptr = &sim->dir_array [dir_index]; if (lane <= dir_ptr->Left ()) { while (lane <= dir_ptr->Left ()) { num_lanes++; if (sim_dir_ptr->Get (++lane, cell) >= 0) break; } } else { while (lane >= (dir_ptr->Left () + dir_ptr->Lanes ())) { num_lanes++; if (sim_dir_ptr->Get (--lane, cell) >= 0) break; } } speed = 0; } else { //---- accelerate ---- speed += step.veh_type_ptr->Max_Accel (); if (speed > step.veh_type_ptr->Max_Speed ()) { speed = step.veh_type_ptr->Max_Speed (); } if (speed > sim_dir_ptr->Speed ()) { speed = sim_dir_ptr->Speed (); } //---- check the vehicle speed ---- traveler = abs (traveler); if (traveler > 1) { sim_travel_ptr = &sim->sim_travel_array [traveler]; if (sim_travel_ptr->Speed () < speed) { speed = sim_travel_ptr->Speed (); } num_veh++; } } } sum_speed += speed - step.Delay (); } sim->Offset_Cell (sum_speed); sum_speed = DTOI (sum_speed * sim->param.time_factor - num_lanes * sim->param.lane_factor - num_veh * sim->param.veh_factor); return (sum_speed); }
bool Sim_Method::Cell_Use (Travel_Step &step) { int lane, lanes, cell; Sim_Dir_Ptr sim_dir_ptr; Sim_Lane_Ptr lane_ptr = 0; Cell_Data cell_rec = step.sim_veh_ptr->front (); if (cell_rec.Index () == step.Dir_Index ()) { if (step.sim_dir_ptr == 0) { step.sim_dir_ptr = &exe->sim_dir_array [cell_rec.Index ()]; } sim_dir_ptr = step.sim_dir_ptr; } else { sim_dir_ptr = &exe->sim_dir_array [cell_rec.Index ()]; } if (sim_dir_ptr->Method () != MESOSCOPIC) return (true); lanes = sim_dir_ptr->Lanes (); cell = cell_rec.Cell (); for (lane = 0; lane < lanes; lane++) { lane_ptr = sim_dir_ptr->Lane (lane); if (Cell_Use (lane_ptr, lane, cell, step)) return (true); } Dtime max_time = exe->step + param.max_wait_time; if (use_update_time < max_time) { int i, index, num; Lane_Use_Data *use_ptr; Lane_Use_Period *period_ptr; Link_Dir_Data *use_index; Use_Type use = step.veh_type_ptr->Use (); int veh_type = step.sim_veh_ptr->Type (); int type = step.sim_traveler_ptr->Type (); Dir_Data *dir_ptr = &exe->dir_array [cell_rec.Index ()]; index = dir_ptr->First_Lane_Use (); if (index < 0) goto use_error; for (period_ptr = &exe->use_period_array [index]; ; period_ptr = &exe->use_period_array [++index]) { if (period_ptr->Start () >= use_update_time && period_ptr->Start () <= max_time) break; if (period_ptr->Periods () == 0) goto use_error; } num = period_ptr->Records (); index = period_ptr->Index (); for (i=0; i < num; i++, index++) { use_index = &exe->use_period_index [index]; use_ptr = &exe->lane_use_array [use_index->Link ()]; if (use_ptr->Offset () > 0 || use_ptr->Length () > 0) { int offset = cell * param.cell_size; if (use_ptr->Offset () > offset || offset > (use_ptr->Offset () + use_ptr->Length ())) continue; } if (use_ptr->Type () == PROHIBIT) { if (!Use_Permission (use_ptr->Use (), use)) { if (veh_type >= 0 && use_ptr->Min_Veh_Type () >= 0) { if (veh_type < use_ptr->Min_Veh_Type () || veh_type > use_ptr->Max_Veh_Type ()) { if (type > 0 && use_ptr->Min_Traveler () > 0) { if (type < use_ptr->Min_Traveler () || type > use_ptr->Max_Traveler ()) return (true); } else { return (true); } } } else if (type > 0 && use_ptr->Min_Traveler () > 0) { if (type < use_ptr->Min_Traveler () || type > use_ptr->Max_Traveler ()) return (true); } else { return (true); } } } else { if (Use_Permission (use_ptr->Use (), use)) { if (veh_type >= 0 && use_ptr->Min_Veh_Type () >= 0) { if (veh_type >= use_ptr->Min_Veh_Type () && veh_type <= use_ptr->Max_Veh_Type ()) { if (type > 0 && use_ptr->Min_Traveler () > 0) { if (type >= use_ptr->Min_Traveler () && type <= use_ptr->Max_Traveler ()) return (true); } else { return (true); } } } else if (type > 0 && use_ptr->Min_Traveler () > 0) { if (type >= use_ptr->Min_Traveler () && type <= use_ptr->Max_Traveler ()) return (true); } else { return (true); } } } } } use_error: step.Problem (USE_PROBLEM); step.Status (1); return (false); }