mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 01:15:12 +03:00
Rearrange methods defined on Scenario that're only for the sim crate
This commit is contained in:
parent
231acf47a2
commit
3f8689b9ea
@ -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/") {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user