use micro_traffic_sim_core::geom::new_point;
use micro_traffic_sim_core::grid::{cell::Cell, road_network::GridRoads};
use micro_traffic_sim_core::agents::Vehicle;
use micro_traffic_sim_core::agents_types::AgentType;
use micro_traffic_sim_core::behaviour::BehaviourType;
use micro_traffic_sim_core::simulation::session::Session;
use micro_traffic_sim_core::simulation::grids_storage::GridsStorage;
use micro_traffic_sim_core::trips::trip::{Trip, TripType};
use micro_traffic_sim_core::verbose::init_logger;
use micro_traffic_sim_core::verbose::VerboseLevel;
use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
fn main() {
init_logger();
let mut grid = GridRoads::new();
let mut cell_positions: HashMap<i64, (f64, f64)> = HashMap::new();
for i in 1..=10 {
let forward = if i < 10 { i + 1 } else { -1 };
let right = if i == 10 { 11 } else { -1 };
let x = i as f64;
let y = 9.0;
cell_positions.insert(i, (x, y));
let cell = Cell::new(i)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(right)
.build();
grid.add_cell(cell);
}
for i in 11..=20 {
let forward = if i < 20 { i + 1 } else { -1 };
let x = i as f64;
let y = 8.0;
cell_positions.insert(i, (x, y));
let cell = Cell::new(i)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
}
for i in 1..=10 {
let cell_id = 100 + i;
let forward = if i < 10 { 100 + i + 1 } else { -1 };
let right = if i == 10 { 111 } else { -1 };
let x = i as f64;
let y = 6.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(right)
.build();
grid.add_cell(cell);
}
cell_positions.insert(111, (11.0, 5.5));
let cell = Cell::new(111)
.with_point(new_point(11.0, 5.5, None))
.with_speed_limit(3)
.with_forward_node(-1)
.with_left_node(112)
.with_right_node(-1)
.build();
grid.add_cell(cell);
for i in 12..=16 {
let cell_id = 100 + i;
let forward = if i < 16 { 100 + i + 1 } else { -1 };
let x = i as f64;
let y = 6.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
}
for i in 1..=10 {
let cell_id = 200 + i;
let forward = if i < 10 { 200 + i + 1 } else { -1 };
let right = if i == 10 { 211 } else { -1 };
let x = i as f64;
let y = 3.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(right)
.build();
grid.add_cell(cell);
}
cell_positions.insert(211, (11.0, 2.5));
let cell = Cell::new(211)
.with_point(new_point(11.0, 2.5, None))
.with_speed_limit(3)
.with_forward_node(212)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
cell_positions.insert(212, (12.0, 2.5));
let cell = Cell::new(212)
.with_point(new_point(12.0, 2.5, None))
.with_speed_limit(3)
.with_forward_node(-1)
.with_left_node(213)
.with_right_node(-1)
.build();
grid.add_cell(cell);
for i in 13..=16 {
let cell_id = 200 + i;
let forward = if i < 16 { 200 + i + 1 } else { -1 };
let x = i as f64;
let y = 3.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
}
for i in 1..=10 {
let cell_id = 300 + i;
let forward = if i < 10 { 300 + i + 1 } else { -1 };
let right = if i == 10 { 311 } else { -1 };
let x = i as f64;
let y = 0.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(right)
.build();
grid.add_cell(cell);
}
cell_positions.insert(311, (11.0, -0.5));
let cell = Cell::new(311)
.with_point(new_point(11.0, -0.5, None))
.with_speed_limit(3)
.with_forward_node(312)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
cell_positions.insert(312, (12.0, -0.5));
let cell = Cell::new(312)
.with_point(new_point(12.0, -0.5, None))
.with_speed_limit(3)
.with_forward_node(-1)
.with_left_node(313)
.with_right_node(-1)
.build();
grid.add_cell(cell);
for i in 13..=16 {
let cell_id = 300 + i;
let forward = if i < 16 { 300 + i + 1 } else { -1 };
let x = i as f64;
let y = 0.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
}
for i in 1..=5 {
let cell_id = 400 + i;
let forward = if i < 5 { 400 + i + 1 } else { -1 };
let right = if i == 5 { 406 } else { -1 };
let x = i as f64;
let y = -3.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(right)
.build();
grid.add_cell(cell);
}
for i in 6..=10 {
let cell_id = 400 + i;
let forward = if i < 10 { 400 + i + 1 } else { -1 };
let x = i as f64;
let y = -3.5;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
}
for i in 1..=5 {
let cell_id = 410 + i;
let forward = if i < 5 { 410 + i + 1 } else { -1 };
let left = if i == 5 { 406 } else { -1 };
let x = i as f64;
let y = -4.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(left)
.with_right_node(-1)
.build();
grid.add_cell(cell);
}
cell_positions.insert(501, (1.0, -7.0));
let cell = Cell::new(501)
.with_point(new_point(1.0, -7.0, None))
.with_speed_limit(3)
.with_forward_node(503)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
cell_positions.insert(502, (3.0, -6.0));
let cell = Cell::new(502)
.with_point(new_point(3.0, -6.0, None))
.with_speed_limit(3)
.with_forward_node(504)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
cell_positions.insert(503, (2.0, -7.0));
let cell = Cell::new(503)
.with_point(new_point(2.0, -7.0, None))
.with_speed_limit(3)
.with_forward_node(504)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
cell_positions.insert(504, (3.0, -7.0));
let cell = Cell::new(504)
.with_point(new_point(3.0, -7.0, None))
.with_speed_limit(3)
.with_forward_node(507)
.with_left_node(-1)
.with_right_node(505)
.build();
grid.add_cell(cell);
cell_positions.insert(505, (4.0, -7.0));
let cell = Cell::new(505)
.with_point(new_point(4.0, -7.0, None))
.with_speed_limit(3)
.with_forward_node(506)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
cell_positions.insert(506, (5.0, -7.0));
let cell = Cell::new(506)
.with_point(new_point(5.0, -7.0, None))
.with_speed_limit(3)
.with_forward_node(-1)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
cell_positions.insert(507, (3.0, -8.0));
let cell = Cell::new(507)
.with_point(new_point(3.0, -8.0, None))
.with_speed_limit(3)
.with_forward_node(509)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
cell_positions.insert(508, (2.0, -9.0));
let cell = Cell::new(508)
.with_point(new_point(2.0, -9.0, None))
.with_speed_limit(3)
.with_forward_node(509)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
for i in 9..=14 {
let cell_id = 500 + i;
let forward = if i < 14 { 500 + i + 1 } else { -1 };
let x = 3.0 + (i - 9) as f64 * 0.3;
let y = -9.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
}
for i in 1..=20 {
let cell_id = 600 + i;
let forward = if i < 15 {
600 + i + 1
} else if i == 15 {
-1 } else if i < 20 {
600 + i + 1 } else {
-1
};
let x = i as f64;
let y = -10.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(5)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
}
for i in 1..=4 {
let cell_id = 700 + i;
let forward = if i < 4 { 700 + i + 1 } else { -1 };
let right = if i == 4 { 709 } else { -1 };
let x = i as f64;
let y = -12.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(right)
.build();
grid.add_cell(cell);
}
for i in 5..=12 {
let cell_id = 700 + i;
let forward = if i < 12 { 700 + i + 1 } else { -1 };
let x = (i - 4) as f64;
let y = -13.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
}
for i in 1..=4 {
let cell_id = 712 + i;
let forward = if i < 4 { 712 + i + 1 } else { -1 };
let left = if i == 4 { 709 } else { -1 };
let x = i as f64;
let y = -14.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(left)
.with_right_node(-1)
.build();
grid.add_cell(cell);
}
for i in 1..=18 {
let cell_id = 800 + i;
let forward = if i < 18 { 800 + i + 1 } else { -1 };
let x = i as f64;
let y = -16.0;
cell_positions.insert(cell_id, (x, y));
let cell = Cell::new(cell_id)
.with_point(new_point(x, y, None))
.with_speed_limit(3)
.with_forward_node(forward)
.with_left_node(-1)
.with_right_node(-1)
.build();
grid.add_cell(cell);
}
let vehicles: Vec<Vehicle> = vec![
Vehicle::new(1)
.with_cell(3)
.with_tail_size(2, vec![1, 2])
.with_destination(20)
.with_speed(1)
.with_speed_limit(1)
.with_behaviour(BehaviourType::Aggressive)
.build(),
Vehicle::new(2)
.with_cell(103)
.with_tail_size(2, vec![101, 102])
.with_destination(116)
.with_speed(1)
.with_speed_limit(1)
.with_behaviour(BehaviourType::Aggressive)
.build(),
Vehicle::new(3)
.with_cell(203)
.with_tail_size(1, vec![202])
.with_destination(216)
.with_speed(1)
.with_speed_limit(1)
.with_behaviour(BehaviourType::Aggressive)
.build(),
Vehicle::new(4)
.with_cell(303)
.with_tail_size(2, vec![301, 302])
.with_destination(316)
.with_speed(1)
.with_speed_limit(1)
.with_behaviour(BehaviourType::Aggressive)
.build(),
Vehicle::new(5)
.with_cell(403)
.with_tail_size(2, vec![401, 402])
.with_destination(410)
.with_speed(1)
.with_speed_limit(1)
.with_behaviour(BehaviourType::Aggressive)
.build(),
Vehicle::new(6)
.with_cell(413)
.with_tail_size(2, vec![411, 412])
.with_destination(410)
.with_speed(1)
.with_speed_limit(1)
.with_behaviour(BehaviourType::Aggressive)
.build(),
Vehicle::new(7)
.with_cell(501)
.with_tail_size(1, vec![-1])
.with_destination(514)
.with_speed(1)
.with_speed_limit(1)
.with_behaviour(BehaviourType::Aggressive)
.build(),
Vehicle::new(8)
.with_cell(502)
.with_tail_size(5, vec![-1, -1, -1, -1, -1])
.with_destination(506)
.with_speed(1)
.with_speed_limit(1)
.with_behaviour(BehaviourType::Aggressive)
.build(),
Vehicle::new(9)
.with_cell(603)
.with_tail_size(2, vec![601, 602])
.with_destination(615)
.with_speed(3)
.with_speed_limit(3)
.with_behaviour(BehaviourType::Aggressive)
.build(),
Vehicle::new(10)
.with_cell(612)
.with_tail_size(2, vec![610, 611])
.with_destination(620)
.with_speed(1)
.with_speed_limit(1)
.with_behaviour(BehaviourType::Aggressive)
.build(),
Vehicle::new(11)
.with_cell(702)
.with_tail_size(2, vec![-1, 701])
.with_destination(712)
.with_speed(1)
.with_speed_limit(1)
.with_behaviour(BehaviourType::Aggressive)
.build(),
Vehicle::new(12)
.with_cell(707)
.with_tail_size(2, vec![705, 706])
.with_destination(712)
.with_speed(1)
.with_speed_limit(1)
.with_behaviour(BehaviourType::Aggressive)
.build(),
Vehicle::new(13)
.with_cell(714)
.with_tail_size(2, vec![-1, 713])
.with_destination(712)
.with_speed(1)
.with_speed_limit(1)
.with_behaviour(BehaviourType::Aggressive)
.build(),
];
let grids_storage = GridsStorage::new()
.with_vehicles_net(grid)
.build();
let mut session = Session::new(grids_storage, None);
session.set_verbose_level(VerboseLevel::None);
session.add_vehicles(vehicles);
let trip = Trip::new(801, 818, TripType::Constant)
.with_id(1)
.with_allowed_agent_type(AgentType::LargeBus)
.with_allowed_behaviour_type(BehaviourType::Aggressive)
.with_time(5)
.with_initial_speed(1)
.with_speed_limit(1)
.build();
session.add_trip(trip);
let out_dir = "examples/all-tail/";
write_cells_data(&cell_positions, out_dir);
write_edges_data(&session, &cell_positions, out_dir);
let time_sim = 25;
let mut num_steps = 0;
write_vehicle_step(&session, &cell_positions, 0, out_dir);
num_steps += 1;
for step in 1..time_sim {
match session.step() {
Ok(_) => {
write_vehicle_step(&session, &cell_positions, step as usize, out_dir);
num_steps += 1;
}
Err(e) => {
eprintln!("Error at step {}: {}", step, e);
break;
}
}
}
write_gnuplot_config(num_steps, out_dir);
println!("Simulation complete ({} steps). Data written to:", num_steps);
println!(" - cells.dat");
println!(" - edges.dat");
println!(" - vehicle_step_*.dat");
println!(" - config.gnu");
println!("\nRun 'gnuplot plot.gnu' to generate visualization");
}
fn write_cells_data(positions: &HashMap<i64, (f64, f64)>, out_dir: &str) {
let filename = format!("{}cells.dat", out_dir);
let mut file = File::create(&filename).expect("Failed to create cells.dat");
writeln!(file, "# CellID X Y").unwrap();
let mut sorted_ids: Vec<_> = positions.keys().collect();
sorted_ids.sort();
for cell_id in sorted_ids {
let (x, y) = positions[cell_id];
writeln!(file, "{} {:.1} {:.1}", cell_id, x, y).unwrap();
}
}
fn write_edges_data(session: &Session, positions: &HashMap<i64, (f64, f64)>, out_dir: &str) {
let filename = format!("{}edges.dat", out_dir);
let mut file = File::create(&filename).expect("Failed to create edges.dat");
writeln!(file, "# from_x from_y dx dy label").unwrap();
let mut sorted_ids: Vec<_> = positions.keys().collect();
sorted_ids.sort();
for cell_id in sorted_ids {
if let Some(cell) = session.get_cell(cell_id) {
let (from_x, from_y) = positions[cell_id];
let fwd_id = cell.get_forward_id();
if fwd_id >= 0 {
if let Some(&(to_x, to_y)) = positions.get(&fwd_id) {
let dx = to_x - from_x;
let dy = to_y - from_y;
writeln!(file, "{:.1} {:.1} {:.1} {:.1} F", from_x, from_y, dx, dy).unwrap();
}
}
let right_id = cell.get_right_id();
if right_id >= 0 {
if let Some(&(to_x, to_y)) = positions.get(&right_id) {
let dx = to_x - from_x;
let dy = to_y - from_y;
writeln!(file, "{:.1} {:.1} {:.1} {:.1} R", from_x, from_y, dx, dy).unwrap();
}
}
let left_id = cell.get_left_id();
if left_id >= 0 {
if let Some(&(to_x, to_y)) = positions.get(&left_id) {
let dx = to_x - from_x;
let dy = to_y - from_y;
writeln!(file, "{:.1} {:.1} {:.1} {:.1} L", from_x, from_y, dx, dy).unwrap();
}
}
}
}
}
fn write_vehicle_step(session: &Session, positions: &HashMap<i64, (f64, f64)>, step: usize, out_dir: &str) {
let filename = format!("{}vehicle_step_{:02}.dat", out_dir, step);
let mut file = File::create(&filename).expect("Failed to create vehicle step file");
writeln!(file, "# X Y VehicleID Type").unwrap();
for (_, vehicle) in session.get_vehicles() {
if let Some(&(x, y)) = positions.get(&vehicle.cell_id) {
writeln!(file, "{:.1} {:.1} {} head", x, y, vehicle.id).unwrap();
}
for tail_cell in &vehicle.tail_cells {
if *tail_cell > 0 {
if let Some(&(x, y)) = positions.get(tail_cell) {
writeln!(file, "{:.1} {:.1} {} tail", x, y, vehicle.id).unwrap();
}
}
}
}
}
fn write_gnuplot_config(num_steps: usize, out_dir: &str) {
let filename = format!("{}config.gnu", out_dir);
let mut file = File::create(&filename).expect("Failed to create config.gnu");
writeln!(file, "# Auto-generated gnuplot config").unwrap();
writeln!(file, "num_steps = {}", num_steps).unwrap();
}