mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-29 17:34:58 +03:00
make TripSpawner a temporary setup object, not something permanently stored in Sim
This commit is contained in:
parent
f20b7912eb
commit
d852d69535
@ -20,7 +20,8 @@ use rand::seq::SliceRandom;
|
|||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
use sim::{
|
use sim::{
|
||||||
BorderSpawnOverTime, DrivingGoal, OriginDestination, Scenario, SidewalkSpot, Sim, TripSpec,
|
BorderSpawnOverTime, DrivingGoal, OriginDestination, Scenario, SidewalkSpot, Sim, TripSpawner,
|
||||||
|
TripSpec,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SMALL_DT: Duration = Duration::const_seconds(0.1);
|
const SMALL_DT: Duration = Duration::const_seconds(0.1);
|
||||||
@ -270,14 +271,16 @@ impl State for AgentSpawner {
|
|||||||
if self.maybe_goal.is_some() && app.per_obj.left_click(ctx, "end the agent here") {
|
if self.maybe_goal.is_some() && app.per_obj.left_click(ctx, "end the agent here") {
|
||||||
let mut rng = app.primary.current_flags.sim_flags.make_rng();
|
let mut rng = app.primary.current_flags.sim_flags.make_rng();
|
||||||
let sim = &mut app.primary.sim;
|
let sim = &mut app.primary.sim;
|
||||||
|
let mut spawner = sim.make_spawner();
|
||||||
let err = schedule_trip(
|
let err = schedule_trip(
|
||||||
&self.from,
|
&self.from,
|
||||||
self.maybe_goal.take().unwrap().0,
|
self.maybe_goal.take().unwrap().0,
|
||||||
map,
|
map,
|
||||||
sim,
|
sim,
|
||||||
|
&mut spawner,
|
||||||
&mut rng,
|
&mut rng,
|
||||||
);
|
);
|
||||||
sim.spawn_all_trips(map, &mut Timer::new("spawn trip"), false);
|
sim.flush_spawner(spawner, map, &mut Timer::new("spawn trip"), false);
|
||||||
sim.normal_step(map, SMALL_DT);
|
sim.normal_step(map, SMALL_DT);
|
||||||
app.recalculate_current_selection(ctx);
|
app.recalculate_current_selection(ctx);
|
||||||
if let Some(e) = err {
|
if let Some(e) = err {
|
||||||
@ -309,6 +312,7 @@ pub fn spawn_agents_around(i: IntersectionID, app: &mut App) {
|
|||||||
let map = &app.primary.map;
|
let map = &app.primary.map;
|
||||||
let sim = &mut app.primary.sim;
|
let sim = &mut app.primary.sim;
|
||||||
let mut rng = app.primary.current_flags.sim_flags.make_rng();
|
let mut rng = app.primary.current_flags.sim_flags.make_rng();
|
||||||
|
let mut spawner = sim.make_spawner();
|
||||||
|
|
||||||
if map.all_buildings().is_empty() {
|
if map.all_buildings().is_empty() {
|
||||||
println!("No buildings, can't pick destinations");
|
println!("No buildings, can't pick destinations");
|
||||||
@ -332,7 +336,7 @@ pub fn spawn_agents_around(i: IntersectionID, app: &mut App) {
|
|||||||
if vehicle_spec.length > lane.length() {
|
if vehicle_spec.length > lane.length() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
sim.time(),
|
sim.time(),
|
||||||
TripSpec::CarAppearing {
|
TripSpec::CarAppearing {
|
||||||
start_pos: Position::new(
|
start_pos: Position::new(
|
||||||
@ -346,11 +350,12 @@ pub fn spawn_agents_around(i: IntersectionID, app: &mut App) {
|
|||||||
ped_speed: Scenario::rand_ped_speed(&mut rng),
|
ped_speed: Scenario::rand_ped_speed(&mut rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if lane.is_sidewalk() {
|
} else if lane.is_sidewalk() {
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
sim.time(),
|
sim.time(),
|
||||||
TripSpec::JustWalking {
|
TripSpec::JustWalking {
|
||||||
start: SidewalkSpot::suddenly_appear(
|
start: SidewalkSpot::suddenly_appear(
|
||||||
@ -365,12 +370,13 @@ pub fn spawn_agents_around(i: IntersectionID, app: &mut App) {
|
|||||||
ped_speed: Scenario::rand_ped_speed(&mut rng),
|
ped_speed: Scenario::rand_ped_speed(&mut rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sim.spawn_all_trips(map, &mut timer, false);
|
sim.flush_spawner(spawner, map, &mut timer, false);
|
||||||
sim.normal_step(map, SMALL_DT);
|
sim.normal_step(map, SMALL_DT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +385,8 @@ fn schedule_trip(
|
|||||||
src: &Source,
|
src: &Source,
|
||||||
raw_goal: Goal,
|
raw_goal: Goal,
|
||||||
map: &Map,
|
map: &Map,
|
||||||
sim: &mut Sim,
|
sim: &Sim,
|
||||||
|
spawner: &mut TripSpawner,
|
||||||
rng: &mut XorShiftRng,
|
rng: &mut XorShiftRng,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
match src {
|
match src {
|
||||||
@ -406,7 +413,7 @@ fn schedule_trip(
|
|||||||
map.should_use_transit(start.sidewalk_pos, goal.sidewalk_pos)
|
map.should_use_transit(start.sidewalk_pos, goal.sidewalk_pos)
|
||||||
{
|
{
|
||||||
println!("Using {} from {} to {}", route, stop1, stop2);
|
println!("Using {} from {} to {}", route, stop1, stop2);
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
sim.time(),
|
sim.time(),
|
||||||
TripSpec::UsingTransit {
|
TripSpec::UsingTransit {
|
||||||
start,
|
start,
|
||||||
@ -417,10 +424,11 @@ fn schedule_trip(
|
|||||||
ped_speed,
|
ped_speed,
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("Not using transit");
|
println!("Not using transit");
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
sim.time(),
|
sim.time(),
|
||||||
TripSpec::JustWalking {
|
TripSpec::JustWalking {
|
||||||
start,
|
start,
|
||||||
@ -428,6 +436,7 @@ fn schedule_trip(
|
|||||||
ped_speed,
|
ped_speed,
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -446,7 +455,7 @@ fn schedule_trip(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
sim.time(),
|
sim.time(),
|
||||||
TripSpec::UsingBike {
|
TripSpec::UsingBike {
|
||||||
start: SidewalkSpot::building(*b, map),
|
start: SidewalkSpot::building(*b, map),
|
||||||
@ -455,6 +464,7 @@ fn schedule_trip(
|
|||||||
ped_speed: Scenario::rand_ped_speed(rng),
|
ped_speed: Scenario::rand_ped_speed(rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@ -476,7 +486,7 @@ fn schedule_trip(
|
|||||||
match src {
|
match src {
|
||||||
Source::Drive(from) => {
|
Source::Drive(from) => {
|
||||||
if let Some(start_pos) = TripSpec::spawn_car_at(*from, map) {
|
if let Some(start_pos) = TripSpec::spawn_car_at(*from, map) {
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
sim.time(),
|
sim.time(),
|
||||||
TripSpec::CarAppearing {
|
TripSpec::CarAppearing {
|
||||||
start_pos,
|
start_pos,
|
||||||
@ -485,13 +495,14 @@ fn schedule_trip(
|
|||||||
ped_speed: Scenario::rand_ped_speed(rng),
|
ped_speed: Scenario::rand_ped_speed(rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Some(format!("Can't make a car appear at {:?}", from));
|
return Some(format!("Can't make a car appear at {:?}", from));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Source::WalkFromBldgThenMaybeUseCar(b) => {
|
Source::WalkFromBldgThenMaybeUseCar(b) => {
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
sim.time(),
|
sim.time(),
|
||||||
TripSpec::MaybeUsingParkedCar {
|
TripSpec::MaybeUsingParkedCar {
|
||||||
start_bldg: *b,
|
start_bldg: *b,
|
||||||
@ -499,6 +510,7 @@ fn schedule_trip(
|
|||||||
ped_speed: Scenario::rand_ped_speed(rng),
|
ped_speed: Scenario::rand_ped_speed(rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::make::TripSpawner;
|
||||||
use crate::{
|
use crate::{
|
||||||
CarID, DrivingGoal, ParkingSpot, PersonID, SidewalkSpot, Sim, TripSpec, VehicleSpec,
|
CarID, DrivingGoal, ParkingSpot, PersonID, SidewalkSpot, Sim, TripSpec, VehicleSpec,
|
||||||
VehicleType, BIKE_LENGTH, MAX_CAR_LENGTH, MIN_CAR_LENGTH,
|
VehicleType, BIKE_LENGTH, MAX_CAR_LENGTH, MIN_CAR_LENGTH,
|
||||||
@ -104,6 +105,8 @@ impl Scenario {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut spawner = sim.make_spawner();
|
||||||
|
|
||||||
// Don't let two pedestrians starting from one building use the same car.
|
// Don't let two pedestrians starting from one building use the same car.
|
||||||
let mut reserved_cars: HashSet<CarID> = HashSet::new();
|
let mut reserved_cars: HashSet<CarID> = HashSet::new();
|
||||||
|
|
||||||
@ -115,16 +118,24 @@ impl Scenario {
|
|||||||
timer.start_iter("SpawnOverTime each agent", s.num_agents);
|
timer.start_iter("SpawnOverTime each agent", s.num_agents);
|
||||||
for _ in 0..s.num_agents {
|
for _ in 0..s.num_agents {
|
||||||
timer.next();
|
timer.next();
|
||||||
s.spawn_agent(rng, sim, &mut reserved_cars, &neighborhoods, map, timer);
|
s.spawn_agent(
|
||||||
|
rng,
|
||||||
|
sim,
|
||||||
|
&mut spawner,
|
||||||
|
&mut reserved_cars,
|
||||||
|
&neighborhoods,
|
||||||
|
map,
|
||||||
|
timer,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.start_iter("BorderSpawnOverTime", self.border_spawn_over_time.len());
|
timer.start_iter("BorderSpawnOverTime", self.border_spawn_over_time.len());
|
||||||
for s in &self.border_spawn_over_time {
|
for s in &self.border_spawn_over_time {
|
||||||
timer.next();
|
timer.next();
|
||||||
s.spawn_peds(rng, sim, &neighborhoods, map, timer);
|
s.spawn_peds(rng, &mut spawner, &neighborhoods, map, sim, timer);
|
||||||
s.spawn_cars(rng, sim, &neighborhoods, map, timer);
|
s.spawn_cars(rng, &mut spawner, &neighborhoods, map, sim, timer);
|
||||||
s.spawn_bikes(rng, sim, &neighborhoods, map, timer);
|
s.spawn_bikes(rng, &mut spawner, &neighborhoods, map, sim, timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut individ_parked_cars: Vec<(BuildingID, usize)> = Vec::new();
|
let mut individ_parked_cars: Vec<(BuildingID, usize)> = Vec::new();
|
||||||
@ -140,10 +151,10 @@ impl Scenario {
|
|||||||
for t in &self.population.individ_trips {
|
for t in &self.population.individ_trips {
|
||||||
timer.next();
|
timer.next();
|
||||||
let spec = t.trip.clone().to_trip_spec(rng);
|
let spec = t.trip.clone().to_trip_spec(rng);
|
||||||
sim.schedule_trip(t.depart, spec, map);
|
spawner.schedule_trip(t.depart, spec, map, sim);
|
||||||
}
|
}
|
||||||
|
|
||||||
sim.spawn_all_trips(map, timer, true);
|
sim.flush_spawner(spawner, map, timer, true);
|
||||||
timer.stop(format!("Instantiating {}", self.scenario_name));
|
timer.stop(format!("Instantiating {}", self.scenario_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,7 +316,8 @@ impl SpawnOverTime {
|
|||||||
fn spawn_agent(
|
fn spawn_agent(
|
||||||
&self,
|
&self,
|
||||||
rng: &mut XorShiftRng,
|
rng: &mut XorShiftRng,
|
||||||
sim: &mut Sim,
|
sim: &Sim,
|
||||||
|
spawner: &mut TripSpawner,
|
||||||
reserved_cars: &mut HashSet<CarID>,
|
reserved_cars: &mut HashSet<CarID>,
|
||||||
neighborhoods: &HashMap<String, FullNeighborhoodInfo>,
|
neighborhoods: &HashMap<String, FullNeighborhoodInfo>,
|
||||||
map: &Map,
|
map: &Map,
|
||||||
@ -331,7 +343,7 @@ impl SpawnOverTime {
|
|||||||
{
|
{
|
||||||
reserved_cars.insert(parked_car.vehicle.id);
|
reserved_cars.insert(parked_car.vehicle.id);
|
||||||
let spot = parked_car.spot;
|
let spot = parked_car.spot;
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
spawn_time,
|
spawn_time,
|
||||||
TripSpec::UsingParkedCar {
|
TripSpec::UsingParkedCar {
|
||||||
start: SidewalkSpot::building(from_bldg, map),
|
start: SidewalkSpot::building(from_bldg, map),
|
||||||
@ -340,6 +352,7 @@ impl SpawnOverTime {
|
|||||||
ped_speed: Scenario::rand_ped_speed(rng),
|
ped_speed: Scenario::rand_ped_speed(rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -366,7 +379,7 @@ impl SpawnOverTime {
|
|||||||
true
|
true
|
||||||
};
|
};
|
||||||
if ok {
|
if ok {
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
spawn_time,
|
spawn_time,
|
||||||
TripSpec::UsingBike {
|
TripSpec::UsingBike {
|
||||||
start: SidewalkSpot::building(from_bldg, map),
|
start: SidewalkSpot::building(from_bldg, map),
|
||||||
@ -375,6 +388,7 @@ impl SpawnOverTime {
|
|||||||
ped_speed: Scenario::rand_ped_speed(rng),
|
ped_speed: Scenario::rand_ped_speed(rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -395,7 +409,7 @@ impl SpawnOverTime {
|
|||||||
if let Some((stop1, stop2, route)) =
|
if let Some((stop1, stop2, route)) =
|
||||||
map.should_use_transit(start_spot.sidewalk_pos, goal.sidewalk_pos)
|
map.should_use_transit(start_spot.sidewalk_pos, goal.sidewalk_pos)
|
||||||
{
|
{
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
spawn_time,
|
spawn_time,
|
||||||
TripSpec::UsingTransit {
|
TripSpec::UsingTransit {
|
||||||
start: start_spot,
|
start: start_spot,
|
||||||
@ -406,12 +420,13 @@ impl SpawnOverTime {
|
|||||||
ped_speed: Scenario::rand_ped_speed(rng),
|
ped_speed: Scenario::rand_ped_speed(rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
spawn_time,
|
spawn_time,
|
||||||
TripSpec::JustWalking {
|
TripSpec::JustWalking {
|
||||||
start: start_spot,
|
start: start_spot,
|
||||||
@ -419,6 +434,7 @@ impl SpawnOverTime {
|
|||||||
ped_speed: Scenario::rand_ped_speed(rng),
|
ped_speed: Scenario::rand_ped_speed(rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -431,9 +447,10 @@ impl BorderSpawnOverTime {
|
|||||||
fn spawn_peds(
|
fn spawn_peds(
|
||||||
&self,
|
&self,
|
||||||
rng: &mut XorShiftRng,
|
rng: &mut XorShiftRng,
|
||||||
sim: &mut Sim,
|
spawner: &mut TripSpawner,
|
||||||
neighborhoods: &HashMap<String, FullNeighborhoodInfo>,
|
neighborhoods: &HashMap<String, FullNeighborhoodInfo>,
|
||||||
map: &Map,
|
map: &Map,
|
||||||
|
sim: &Sim,
|
||||||
timer: &mut Timer,
|
timer: &mut Timer,
|
||||||
) {
|
) {
|
||||||
if self.num_peds == 0 {
|
if self.num_peds == 0 {
|
||||||
@ -461,7 +478,7 @@ impl BorderSpawnOverTime {
|
|||||||
if let Some((stop1, stop2, route)) =
|
if let Some((stop1, stop2, route)) =
|
||||||
map.should_use_transit(start.sidewalk_pos, goal.sidewalk_pos)
|
map.should_use_transit(start.sidewalk_pos, goal.sidewalk_pos)
|
||||||
{
|
{
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
spawn_time,
|
spawn_time,
|
||||||
TripSpec::UsingTransit {
|
TripSpec::UsingTransit {
|
||||||
start: start.clone(),
|
start: start.clone(),
|
||||||
@ -472,12 +489,13 @@ impl BorderSpawnOverTime {
|
|||||||
ped_speed: Scenario::rand_ped_speed(rng),
|
ped_speed: Scenario::rand_ped_speed(rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
spawn_time,
|
spawn_time,
|
||||||
TripSpec::JustWalking {
|
TripSpec::JustWalking {
|
||||||
start: start.clone(),
|
start: start.clone(),
|
||||||
@ -485,6 +503,7 @@ impl BorderSpawnOverTime {
|
|||||||
ped_speed: Scenario::rand_ped_speed(rng),
|
ped_speed: Scenario::rand_ped_speed(rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -493,9 +512,10 @@ impl BorderSpawnOverTime {
|
|||||||
fn spawn_cars(
|
fn spawn_cars(
|
||||||
&self,
|
&self,
|
||||||
rng: &mut XorShiftRng,
|
rng: &mut XorShiftRng,
|
||||||
sim: &mut Sim,
|
spawner: &mut TripSpawner,
|
||||||
neighborhoods: &HashMap<String, FullNeighborhoodInfo>,
|
neighborhoods: &HashMap<String, FullNeighborhoodInfo>,
|
||||||
map: &Map,
|
map: &Map,
|
||||||
|
sim: &Sim,
|
||||||
timer: &mut Timer,
|
timer: &mut Timer,
|
||||||
) {
|
) {
|
||||||
if self.num_cars == 0 {
|
if self.num_cars == 0 {
|
||||||
@ -521,7 +541,7 @@ impl BorderSpawnOverTime {
|
|||||||
.pick_driving_goal(PathConstraints::Car, map, &neighborhoods, rng, timer)
|
.pick_driving_goal(PathConstraints::Car, map, &neighborhoods, rng, timer)
|
||||||
{
|
{
|
||||||
let vehicle = Scenario::rand_car(rng);
|
let vehicle = Scenario::rand_car(rng);
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
spawn_time,
|
spawn_time,
|
||||||
TripSpec::CarAppearing {
|
TripSpec::CarAppearing {
|
||||||
start_pos: Position::new(*lanes.choose(rng).unwrap(), vehicle.length),
|
start_pos: Position::new(*lanes.choose(rng).unwrap(), vehicle.length),
|
||||||
@ -530,6 +550,7 @@ impl BorderSpawnOverTime {
|
|||||||
ped_speed: Scenario::rand_ped_speed(rng),
|
ped_speed: Scenario::rand_ped_speed(rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -538,9 +559,10 @@ impl BorderSpawnOverTime {
|
|||||||
fn spawn_bikes(
|
fn spawn_bikes(
|
||||||
&self,
|
&self,
|
||||||
rng: &mut XorShiftRng,
|
rng: &mut XorShiftRng,
|
||||||
sim: &mut Sim,
|
spawner: &mut TripSpawner,
|
||||||
neighborhoods: &HashMap<String, FullNeighborhoodInfo>,
|
neighborhoods: &HashMap<String, FullNeighborhoodInfo>,
|
||||||
map: &Map,
|
map: &Map,
|
||||||
|
sim: &Sim,
|
||||||
timer: &mut Timer,
|
timer: &mut Timer,
|
||||||
) {
|
) {
|
||||||
if self.num_bikes == 0 {
|
if self.num_bikes == 0 {
|
||||||
@ -566,7 +588,7 @@ impl BorderSpawnOverTime {
|
|||||||
.pick_driving_goal(PathConstraints::Bike, map, &neighborhoods, rng, timer)
|
.pick_driving_goal(PathConstraints::Bike, map, &neighborhoods, rng, timer)
|
||||||
{
|
{
|
||||||
let bike = Scenario::rand_bike(rng);
|
let bike = Scenario::rand_bike(rng);
|
||||||
sim.schedule_trip(
|
spawner.schedule_trip(
|
||||||
spawn_time,
|
spawn_time,
|
||||||
TripSpec::CarAppearing {
|
TripSpec::CarAppearing {
|
||||||
start_pos: Position::new(*lanes.choose(rng).unwrap(), bike.length),
|
start_pos: Position::new(*lanes.choose(rng).unwrap(), bike.length),
|
||||||
@ -575,6 +597,7 @@ impl BorderSpawnOverTime {
|
|||||||
ped_speed: Scenario::rand_ped_speed(rng),
|
ped_speed: Scenario::rand_ped_speed(rng),
|
||||||
},
|
},
|
||||||
map,
|
map,
|
||||||
|
sim,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
CarID, Command, CreateCar, CreatePedestrian, DrivingGoal, ParkingSimState, ParkingSpot,
|
CarID, Command, CreateCar, CreatePedestrian, DrivingGoal, ParkingSimState, ParkingSpot,
|
||||||
PedestrianID, Scheduler, SidewalkPOI, SidewalkSpot, TripLeg, TripManager, TripStart,
|
PedestrianID, Scheduler, SidewalkPOI, SidewalkSpot, Sim, TripLeg, TripManager, TripStart,
|
||||||
VehicleSpec, MAX_CAR_LENGTH,
|
VehicleSpec, VehicleType, MAX_CAR_LENGTH,
|
||||||
};
|
};
|
||||||
use abstutil::Timer;
|
use abstutil::Timer;
|
||||||
use geom::{Speed, Time, EPSILON_DIST};
|
use geom::{Speed, Time, EPSILON_DIST};
|
||||||
@ -50,28 +50,84 @@ pub enum TripSpec {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Clone)]
|
// This structure is created temporarily by a Scenario or to interactively spawn agents.
|
||||||
|
// TODO The API isn't great. Passing in Sim and having to use friend methods is awkward.
|
||||||
|
// Alternatives could be somehow consuming Sim temporarily and spitting it back out at the end
|
||||||
|
// (except the interactive spawner would have to mem::replace with a blank Sim?), or just queueing
|
||||||
|
// up commands and doing them at the end while holding onto &Sim.
|
||||||
pub struct TripSpawner {
|
pub struct TripSpawner {
|
||||||
parked_cars_claimed: BTreeSet<CarID>,
|
parked_cars_claimed: BTreeSet<CarID>,
|
||||||
trips: Vec<(Time, Option<PedestrianID>, Option<CarID>, TripSpec)>,
|
trips: Vec<(Time, Option<PedestrianID>, Option<CarID>, TripSpec)>,
|
||||||
|
pub car_id_counter: usize,
|
||||||
|
pub ped_id_counter: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TripSpawner {
|
impl TripSpawner {
|
||||||
pub fn new() -> TripSpawner {
|
pub fn new(car_id_counter: usize, ped_id_counter: usize) -> TripSpawner {
|
||||||
TripSpawner {
|
TripSpawner {
|
||||||
parked_cars_claimed: BTreeSet::new(),
|
parked_cars_claimed: BTreeSet::new(),
|
||||||
trips: Vec::new(),
|
trips: Vec::new(),
|
||||||
|
car_id_counter,
|
||||||
|
ped_id_counter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn schedule_trip(
|
pub fn schedule_trip(
|
||||||
|
&mut self,
|
||||||
|
start_time: Time,
|
||||||
|
spec: TripSpec,
|
||||||
|
map: &Map,
|
||||||
|
sim: &Sim,
|
||||||
|
) -> (Option<PedestrianID>, Option<CarID>) {
|
||||||
|
let (ped_id, car_id) = match spec {
|
||||||
|
TripSpec::CarAppearing {
|
||||||
|
ref vehicle_spec,
|
||||||
|
ref goal,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let car = CarID(self.car_id_counter, vehicle_spec.vehicle_type);
|
||||||
|
self.car_id_counter += 1;
|
||||||
|
let ped = match goal {
|
||||||
|
DrivingGoal::ParkNear(_) => {
|
||||||
|
let id = PedestrianID(self.ped_id_counter);
|
||||||
|
self.ped_id_counter += 1;
|
||||||
|
Some(id)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
(ped, Some(car))
|
||||||
|
}
|
||||||
|
TripSpec::UsingParkedCar { .. }
|
||||||
|
| TripSpec::MaybeUsingParkedCar { .. }
|
||||||
|
| TripSpec::JustWalking { .. }
|
||||||
|
| TripSpec::UsingTransit { .. } => {
|
||||||
|
let id = PedestrianID(self.ped_id_counter);
|
||||||
|
self.ped_id_counter += 1;
|
||||||
|
(Some(id), None)
|
||||||
|
}
|
||||||
|
TripSpec::UsingBike { .. } => {
|
||||||
|
let ped = PedestrianID(self.ped_id_counter);
|
||||||
|
self.ped_id_counter += 1;
|
||||||
|
let car = CarID(self.car_id_counter, VehicleType::Bike);
|
||||||
|
self.car_id_counter += 1;
|
||||||
|
(Some(ped), Some(car))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.inner_schedule_trip(start_time, ped_id, car_id, spec, map, sim);
|
||||||
|
|
||||||
|
(ped_id, car_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Maybe collapse this in the future
|
||||||
|
fn inner_schedule_trip(
|
||||||
&mut self,
|
&mut self,
|
||||||
start_time: Time,
|
start_time: Time,
|
||||||
ped_id: Option<PedestrianID>,
|
ped_id: Option<PedestrianID>,
|
||||||
car_id: Option<CarID>,
|
car_id: Option<CarID>,
|
||||||
spec: TripSpec,
|
spec: TripSpec,
|
||||||
map: &Map,
|
map: &Map,
|
||||||
parking: &ParkingSimState,
|
sim: &Sim,
|
||||||
) {
|
) {
|
||||||
// TODO We'll want to repeat this validation when we spawn stuff later for a second leg...
|
// TODO We'll want to repeat this validation when we spawn stuff later for a second leg...
|
||||||
match &spec {
|
match &spec {
|
||||||
@ -106,7 +162,12 @@ impl TripSpawner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TripSpec::UsingParkedCar { spot, .. } => {
|
TripSpec::UsingParkedCar { spot, .. } => {
|
||||||
let car_id = parking.get_car_at_spot(*spot).unwrap().vehicle.id;
|
let car_id = sim
|
||||||
|
.spawner_parking()
|
||||||
|
.get_car_at_spot(*spot)
|
||||||
|
.unwrap()
|
||||||
|
.vehicle
|
||||||
|
.id;
|
||||||
if self.parked_cars_claimed.contains(&car_id) {
|
if self.parked_cars_claimed.contains(&car_id) {
|
||||||
panic!(
|
panic!(
|
||||||
"A TripSpec wants to use {}, which is already claimed",
|
"A TripSpec wants to use {}, which is already claimed",
|
||||||
@ -179,12 +240,12 @@ impl TripSpawner {
|
|||||||
self.trips.push((start_time, ped_id, car_id, spec));
|
self.trips.push((start_time, ped_id, car_id, spec));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn_all(
|
pub fn finalize(
|
||||||
&mut self,
|
mut self,
|
||||||
map: &Map,
|
map: &Map,
|
||||||
parking: &ParkingSimState,
|
|
||||||
trips: &mut TripManager,
|
trips: &mut TripManager,
|
||||||
scheduler: &mut Scheduler,
|
scheduler: &mut Scheduler,
|
||||||
|
parking: &ParkingSimState,
|
||||||
timer: &mut Timer,
|
timer: &mut Timer,
|
||||||
retry_if_no_room: bool,
|
retry_if_no_room: bool,
|
||||||
) {
|
) {
|
||||||
@ -469,10 +530,6 @@ impl TripSpawner {
|
|||||||
scheduler.finalize_batch();
|
scheduler.finalize_batch();
|
||||||
timer.stop("finalize spawned trips");
|
timer.stop("finalize spawned trips");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_done(&self) -> bool {
|
|
||||||
self.trips.is_empty()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TripSpec {
|
impl TripSpec {
|
||||||
|
@ -30,7 +30,6 @@ pub struct Sim {
|
|||||||
intersections: IntersectionSimState,
|
intersections: IntersectionSimState,
|
||||||
transit: TransitSimState,
|
transit: TransitSimState,
|
||||||
trips: TripManager,
|
trips: TripManager,
|
||||||
spawner: TripSpawner,
|
|
||||||
scheduler: Scheduler,
|
scheduler: Scheduler,
|
||||||
time: Time,
|
time: Time,
|
||||||
car_id_counter: usize,
|
car_id_counter: usize,
|
||||||
@ -107,7 +106,6 @@ impl Sim {
|
|||||||
),
|
),
|
||||||
transit: TransitSimState::new(),
|
transit: TransitSimState::new(),
|
||||||
trips: TripManager::new(),
|
trips: TripManager::new(),
|
||||||
spawner: TripSpawner::new(),
|
|
||||||
scheduler,
|
scheduler,
|
||||||
time: Time::START_OF_DAY,
|
time: Time::START_OF_DAY,
|
||||||
car_id_counter: 0,
|
car_id_counter: 0,
|
||||||
@ -125,62 +123,31 @@ impl Sim {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn schedule_trip(
|
pub fn make_spawner(&self) -> TripSpawner {
|
||||||
&mut self,
|
TripSpawner::new(self.car_id_counter, self.ped_id_counter)
|
||||||
start_time: Time,
|
|
||||||
spec: TripSpec,
|
|
||||||
map: &Map,
|
|
||||||
) -> (Option<PedestrianID>, Option<CarID>) {
|
|
||||||
let (ped_id, car_id) = match spec {
|
|
||||||
TripSpec::CarAppearing {
|
|
||||||
ref vehicle_spec,
|
|
||||||
ref goal,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let car = CarID(self.car_id_counter, vehicle_spec.vehicle_type);
|
|
||||||
self.car_id_counter += 1;
|
|
||||||
let ped = match goal {
|
|
||||||
DrivingGoal::ParkNear(_) => {
|
|
||||||
let id = PedestrianID(self.ped_id_counter);
|
|
||||||
self.ped_id_counter += 1;
|
|
||||||
Some(id)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
(ped, Some(car))
|
|
||||||
}
|
|
||||||
TripSpec::UsingParkedCar { .. }
|
|
||||||
| TripSpec::MaybeUsingParkedCar { .. }
|
|
||||||
| TripSpec::JustWalking { .. }
|
|
||||||
| TripSpec::UsingTransit { .. } => {
|
|
||||||
let id = PedestrianID(self.ped_id_counter);
|
|
||||||
self.ped_id_counter += 1;
|
|
||||||
(Some(id), None)
|
|
||||||
}
|
|
||||||
TripSpec::UsingBike { .. } => {
|
|
||||||
let ped = PedestrianID(self.ped_id_counter);
|
|
||||||
self.ped_id_counter += 1;
|
|
||||||
let car = CarID(self.car_id_counter, VehicleType::Bike);
|
|
||||||
self.car_id_counter += 1;
|
|
||||||
(Some(ped), Some(car))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.spawner
|
|
||||||
.schedule_trip(start_time, ped_id, car_id, spec, map, &self.parking);
|
|
||||||
(ped_id, car_id)
|
|
||||||
}
|
}
|
||||||
|
pub fn flush_spawner(
|
||||||
pub fn spawn_all_trips(&mut self, map: &Map, timer: &mut Timer, retry_if_no_room: bool) {
|
&mut self,
|
||||||
self.spawner.spawn_all(
|
spawner: TripSpawner,
|
||||||
|
map: &Map,
|
||||||
|
timer: &mut Timer,
|
||||||
|
retry_if_no_room: bool,
|
||||||
|
) {
|
||||||
|
self.car_id_counter = spawner.car_id_counter;
|
||||||
|
self.ped_id_counter = spawner.ped_id_counter;
|
||||||
|
spawner.finalize(
|
||||||
map,
|
map,
|
||||||
&self.parking,
|
|
||||||
&mut self.trips,
|
&mut self.trips,
|
||||||
&mut self.scheduler,
|
&mut self.scheduler,
|
||||||
|
&self.parking,
|
||||||
timer,
|
timer,
|
||||||
retry_if_no_room,
|
retry_if_no_room,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// TODO Friend method pattern :(
|
||||||
|
pub(crate) fn spawner_parking(&self) -> &ParkingSimState {
|
||||||
|
&self.parking
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_free_spots(&self, l: LaneID) -> Vec<ParkingSpot> {
|
pub fn get_free_spots(&self, l: LaneID) -> Vec<ParkingSpot> {
|
||||||
self.parking.get_free_spots(l)
|
self.parking.get_free_spots(l)
|
||||||
@ -372,9 +339,6 @@ impl Sim {
|
|||||||
// Advances time as minimally as possible, also limited by max_dt.
|
// Advances time as minimally as possible, also limited by max_dt.
|
||||||
fn minimal_step(&mut self, map: &Map, max_dt: Duration) {
|
fn minimal_step(&mut self, map: &Map, max_dt: Duration) {
|
||||||
self.step_count += 1;
|
self.step_count += 1;
|
||||||
if !self.spawner.is_done() {
|
|
||||||
panic!("Forgot to call spawn_all_trips");
|
|
||||||
}
|
|
||||||
|
|
||||||
let max_time = if let Some(t) = self.scheduler.peek_next_time() {
|
let max_time = if let Some(t) = self.scheduler.peek_next_time() {
|
||||||
if t > self.time + max_dt {
|
if t > self.time + max_dt {
|
||||||
@ -815,10 +779,6 @@ impl Sim {
|
|||||||
"- trips: {} bytes",
|
"- trips: {} bytes",
|
||||||
abstutil::prettyprint_usize(abstutil::serialized_size_bytes(&self.trips))
|
abstutil::prettyprint_usize(abstutil::serialized_size_bytes(&self.trips))
|
||||||
);
|
);
|
||||||
println!(
|
|
||||||
"- spawner: {} bytes",
|
|
||||||
abstutil::prettyprint_usize(abstutil::serialized_size_bytes(&self.spawner))
|
|
||||||
);
|
|
||||||
println!(
|
println!(
|
||||||
"- scheduler: {} bytes",
|
"- scheduler: {} bytes",
|
||||||
abstutil::prettyprint_usize(abstutil::serialized_size_bytes(&self.scheduler))
|
abstutil::prettyprint_usize(abstutil::serialized_size_bytes(&self.scheduler))
|
||||||
@ -868,7 +828,7 @@ impl Sim {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_done(&self) -> bool {
|
pub fn is_done(&self) -> bool {
|
||||||
self.spawner.is_done() && self.trips.is_done()
|
self.trips.is_done()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
|
Loading…
Reference in New Issue
Block a user