Rearrange methods defined on Scenario that're only for the sim crate

This commit is contained in:
Dustin Carlino 2022-01-28 11:51:34 +00:00
parent 231acf47a2
commit 3f8689b9ea
5 changed files with 149 additions and 142 deletions

View File

@ -114,7 +114,7 @@ impl SimFlags {
opts.run_name = scenario.scenario_name.clone();
}
let mut sim = Sim::new(&map, opts);
scenario.instantiate(&mut sim, &map, &mut rng, timer);
sim.instantiate(&scenario, &map, &mut rng, timer);
(map, sim, rng)
} else if self.load.contains("/raw_maps/") || self.load.contains("/maps/") {

View File

@ -11,7 +11,6 @@ pub(crate) use self::spawner::{StartTripArgs, TripSpec};
mod activity_model;
mod generator;
mod load;
mod scenario;
mod spawner;
/// Need to explain this trick -- basically keeps consistency between two different simulations when

View File

@ -28,6 +28,7 @@ use crate::{
};
mod queries;
mod scenario;
// TODO Do something else.
const BLIND_RETRY_TO_SPAWN: Duration = Duration::const_seconds(5.0);

View File

@ -1,6 +1,7 @@
use std::collections::{BTreeMap, HashSet, VecDeque};
use anyhow::Result;
use rand::seq::SliceRandom;
use rand::{Rng, SeedableRng};
use rand_xorshift::XorShiftRng;
@ -9,7 +10,7 @@ use geom::{Distance, Pt2D, Speed};
use map_model::{
BuildingID, Map, OffstreetParking, PathConstraints, PathRequest, Position, RoadID,
};
use synthpop::{Scenario, TripEndpoint, TripMode};
use synthpop::{PersonSpec, Scenario, TripEndpoint, TripMode};
use crate::make::fork_rng;
use crate::{
@ -17,43 +18,49 @@ use crate::{
VehicleType, BIKE_LENGTH, MAX_CAR_LENGTH, MIN_CAR_LENGTH,
};
impl Scenario {
pub fn instantiate(&self, sim: &mut Sim, map: &Map, rng: &mut XorShiftRng, timer: &mut Timer) {
self.instantiate_without_retries(sim, map, rng, true, timer);
impl Sim {
pub fn instantiate(
&mut self,
scenario: &Scenario,
map: &Map,
rng: &mut XorShiftRng,
timer: &mut Timer,
) {
self.instantiate_without_retries(scenario, map, rng, true, timer);
}
/// If retry_if_no_room is false, any vehicles that fail to spawn because of something else in
/// the way will just wind up as cancelled trips.
pub fn instantiate_without_retries(
&self,
sim: &mut Sim,
&mut self,
scenario: &Scenario,
map: &Map,
rng: &mut XorShiftRng,
retry_if_no_room: bool,
timer: &mut Timer,
) {
// Any case where map edits could change the calls to the RNG, we have to fork.
sim.set_run_name(self.scenario_name.clone());
self.set_run_name(scenario.scenario_name.clone());
timer.start(format!("Instantiating {}", self.scenario_name));
timer.start(format!("Instantiating {}", scenario.scenario_name));
if let Some(ref routes) = self.only_seed_buses {
if let Some(ref routes) = scenario.only_seed_buses {
for route in map.all_transit_routes() {
if routes.contains(&route.long_name) {
sim.seed_bus_route(route);
self.seed_bus_route(route);
}
}
} else {
// All of them
for route in map.all_transit_routes() {
sim.seed_bus_route(route);
self.seed_bus_route(route);
}
}
timer.start_iter("trips for People", self.people.len());
timer.start_iter("trips for People", scenario.people.len());
let mut parked_cars: Vec<(Vehicle, BuildingID)> = Vec::new();
let mut schedule_trips = Vec::new();
for p in &self.people {
for p in &scenario.people {
timer.next();
if let Err(err) = p.check_schedule() {
@ -61,8 +68,8 @@ impl Scenario {
}
let (vehicle_specs, cars_initially_parked_at, vehicle_foreach_trip) =
p.get_vehicles(rng);
let person = sim.new_person(p.orig_id, Scenario::rand_ped_speed(rng), vehicle_specs);
get_vehicles(p, rng);
let person = self.new_person(p.orig_id, rand_ped_speed(rng), vehicle_specs);
for (idx, b) in cars_initially_parked_at {
parked_cars.push((person.vehicles[idx].clone(), b));
}
@ -92,151 +99,138 @@ impl Scenario {
// parked_cars is stable over map edits, so don't fork.
parked_cars.shuffle(rng);
seed_parked_cars(parked_cars, sim, map, rng, timer);
seed_parked_cars(parked_cars, self, map, rng, timer);
sim.spawn_trips(schedule_trips, map, timer);
timer.stop(format!("Instantiating {}", self.scenario_name));
self.spawn_trips(schedule_trips, map, timer);
timer.stop(format!("Instantiating {}", scenario.scenario_name));
}
}
fn get_vehicles(
&self,
rng: &mut XorShiftRng,
) -> (
Vec<VehicleSpec>,
Vec<(usize, BuildingID)>,
Vec<Option<usize>>,
) {
let mut vehicle_specs = Vec::new();
let mut cars_initially_parked_at = Vec::new();
let mut vehicle_foreach_trip = Vec::new();
fn get_vehicles(
person: &PersonSpec,
rng: &mut XorShiftRng,
) -> (
Vec<VehicleSpec>,
Vec<(usize, BuildingID)>,
Vec<Option<usize>>,
) {
let mut vehicle_specs = Vec::new();
let mut cars_initially_parked_at = Vec::new();
let mut vehicle_foreach_trip = Vec::new();
let mut bike_idx = None;
// For each indexed car, is it parked somewhere, or off-map?
let mut car_locations: Vec<(usize, Option<BuildingID>)> = Vec::new();
let mut bike_idx = None;
// For each indexed car, is it parked somewhere, or off-map?
let mut car_locations: Vec<(usize, Option<BuildingID>)> = Vec::new();
// TODO If the trip is cancelled, this should be affected...
for trip in &self.trips {
let use_for_trip = match trip.mode {
TripMode::Walk | TripMode::Transit => None,
TripMode::Bike => {
if bike_idx.is_none() {
bike_idx = Some(vehicle_specs.len());
vehicle_specs.push(Scenario::rand_bike(rng));
}
bike_idx
// TODO If the trip is cancelled, this should be affected...
for trip in &person.trips {
let use_for_trip = match trip.mode {
TripMode::Walk | TripMode::Transit => None,
TripMode::Bike => {
if bike_idx.is_none() {
bike_idx = Some(vehicle_specs.len());
vehicle_specs.push(rand_bike(rng));
}
TripMode::Drive => {
let need_parked_at = match trip.origin {
TripEndpoint::Bldg(b) => Some(b),
_ => None,
};
bike_idx
}
TripMode::Drive => {
let need_parked_at = match trip.origin {
TripEndpoint::Bldg(b) => Some(b),
_ => None,
};
// Any available cars in the right spot?
let idx = if let Some(idx) = car_locations
.iter()
.find(|(_, parked_at)| *parked_at == need_parked_at)
.map(|(idx, _)| *idx)
{
idx
} else {
// Need a new car, starting in the right spot
let idx = vehicle_specs.len();
vehicle_specs.push(Scenario::rand_car(rng));
if let Some(b) = need_parked_at {
cars_initially_parked_at.push((idx, b));
}
idx
};
// Where does this car wind up?
car_locations.retain(|(i, _)| idx != *i);
match trip.destination {
TripEndpoint::Bldg(b) => {
car_locations.push((idx, Some(b)));
}
TripEndpoint::Border(_) | TripEndpoint::SuddenlyAppear(_) => {
car_locations.push((idx, None));
}
// Any available cars in the right spot?
let idx = if let Some(idx) = car_locations
.iter()
.find(|(_, parked_at)| *parked_at == need_parked_at)
.map(|(idx, _)| *idx)
{
idx
} else {
// Need a new car, starting in the right spot
let idx = vehicle_specs.len();
vehicle_specs.push(rand_car(rng));
if let Some(b) = need_parked_at {
cars_initially_parked_at.push((idx, b));
}
idx
};
Some(idx)
// Where does this car wind up?
car_locations.retain(|(i, _)| idx != *i);
match trip.destination {
TripEndpoint::Bldg(b) => {
car_locations.push((idx, Some(b)));
}
TripEndpoint::Border(_) | TripEndpoint::SuddenlyAppear(_) => {
car_locations.push((idx, None));
}
}
};
vehicle_foreach_trip.push(use_for_trip);
}
// For debugging
if false {
let mut n = vehicle_specs.len();
if bike_idx.is_some() {
n -= 1;
Some(idx)
}
if n > 1 {
println!("Someone needs {} cars", n);
}
}
(
vehicle_specs,
cars_initially_parked_at,
vehicle_foreach_trip,
)
};
vehicle_foreach_trip.push(use_for_trip);
}
fn rand_car(rng: &mut XorShiftRng) -> VehicleSpec {
let length = Scenario::rand_dist(rng, MIN_CAR_LENGTH, MAX_CAR_LENGTH);
VehicleSpec {
vehicle_type: VehicleType::Car,
length,
max_speed: None,
// For debugging
if false {
let mut n = vehicle_specs.len();
if bike_idx.is_some() {
n -= 1;
}
if n > 1 {
println!("Someone needs {} cars", n);
}
}
fn rand_bike(rng: &mut XorShiftRng) -> VehicleSpec {
let max_speed = Some(Scenario::rand_speed(
rng,
Speed::miles_per_hour(8.0),
map_model::MAX_BIKE_SPEED,
));
VehicleSpec {
vehicle_type: VehicleType::Bike,
length: BIKE_LENGTH,
max_speed,
}
}
(
vehicle_specs,
cars_initially_parked_at,
vehicle_foreach_trip,
)
}
pub fn rand_dist(rng: &mut XorShiftRng, low: Distance, high: Distance) -> Distance {
assert!(high > low);
Distance::meters(rng.gen_range(low.inner_meters()..high.inner_meters()))
fn rand_car(rng: &mut XorShiftRng) -> VehicleSpec {
let length = rand_dist(rng, MIN_CAR_LENGTH, MAX_CAR_LENGTH);
VehicleSpec {
vehicle_type: VehicleType::Car,
length,
max_speed: None,
}
}
fn rand_speed(rng: &mut XorShiftRng, low: Speed, high: Speed) -> Speed {
assert!(high > low);
Speed::meters_per_second(
rng.gen_range(low.inner_meters_per_second()..high.inner_meters_per_second()),
)
fn rand_bike(rng: &mut XorShiftRng) -> VehicleSpec {
let max_speed = Some(rand_speed(
rng,
Speed::miles_per_hour(8.0),
map_model::MAX_BIKE_SPEED,
));
VehicleSpec {
vehicle_type: VehicleType::Bike,
length: BIKE_LENGTH,
max_speed,
}
}
pub fn rand_ped_speed(rng: &mut XorShiftRng) -> Speed {
Scenario::rand_speed(
rng,
Speed::miles_per_hour(2.0),
map_model::MAX_WALKING_SPEED,
)
}
pub fn rand_dist(rng: &mut XorShiftRng, low: Distance, high: Distance) -> Distance {
assert!(high > low);
Distance::meters(rng.gen_range(low.inner_meters()..high.inner_meters()))
}
pub fn count_parked_cars_per_bldg(&self) -> Counter<BuildingID> {
let mut per_bldg = Counter::new();
// Pass in a dummy RNG
let mut rng = XorShiftRng::seed_from_u64(0);
for p in &self.people {
let (_, cars_initially_parked_at, _) = p.get_vehicles(&mut rng);
for (_, b) in cars_initially_parked_at {
per_bldg.inc(b);
}
}
per_bldg
}
fn rand_speed(rng: &mut XorShiftRng, low: Speed, high: Speed) -> Speed {
assert!(high > low);
Speed::meters_per_second(
rng.gen_range(low.inner_meters_per_second()..high.inner_meters_per_second()),
)
}
pub fn rand_ped_speed(rng: &mut XorShiftRng) -> Speed {
rand_speed(
rng,
Speed::miles_per_hour(2.0),
map_model::MAX_WALKING_SPEED,
)
}
fn seed_parked_cars(
@ -360,7 +354,20 @@ fn find_spot_near_building(
}
}
impl TripEndpoint {
pub fn count_parked_cars_per_bldg(scenario: &Scenario) -> Counter<BuildingID> {
let mut per_bldg = Counter::new();
// Pass in a dummy RNG
let mut rng = XorShiftRng::seed_from_u64(0);
for p in &scenario.people {
let (_, cars_initially_parked_at, _) = get_vehicles(p, &mut rng);
for (_, b) in cars_initially_parked_at {
per_bldg.inc(b);
}
}
per_bldg
}
/*impl TripEndpoint {
/// Figure out a single PathRequest that goes between two TripEndpoints. Assume a single mode
/// the entire time -- no walking to a car before driving, for instance. The result probably
/// won't be exactly what would happen on a real trip between the endpoints because of this
@ -466,4 +473,4 @@ impl TripEndpoint {
TripEndpoint::SuddenlyAppear(pos) => pos.pt(map),
}
}
}
}*/

View File

@ -161,7 +161,7 @@ impl Scenario {
impl PersonSpec {
/// Verify that a person's trips make sense
fn check_schedule(&self) -> Result<()> {
pub fn check_schedule(&self) -> Result<()> {
if self.trips.is_empty() {
bail!("Person ({:?}) has no trips at all", self.orig_id);
}