Esempio n. 1
0
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);
}
Esempio n. 2
0
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);	
}
Esempio n. 3
0
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);
}