From 70c1fae4f1d1ab0bdd6660c65f4c93a326cc6d1c Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Mon, 12 Nov 2018 15:42:28 -0800 Subject: [PATCH] encoding ability to go to a border node in scenarios --- editor/src/plugins/mod.rs | 19 ++++++++++++- editor/src/plugins/scenarios.rs | 10 +++---- map_model/src/intersection.rs | 8 ++++++ sim/src/helpers.rs | 8 +++--- sim/src/lib.rs | 3 ++- sim/src/scenario.rs | 47 +++++++++++++++++++++++++++------ 6 files changed, 74 insertions(+), 21 deletions(-) diff --git a/editor/src/plugins/mod.rs b/editor/src/plugins/mod.rs index 1b78f80d7b..1a246c334d 100644 --- a/editor/src/plugins/mod.rs +++ b/editor/src/plugins/mod.rs @@ -32,7 +32,10 @@ use downcast::Any; use ezgui::{Color, GfxCtx, WrappedWizard}; use map_model::{IntersectionID, Map}; use objects::{Ctx, ID}; -use sim::{ABTest, Neighborhood, NeighborhoodBuilder, Scenario, Tick, WeightedUsizeChoice}; +use sim::{ + ABTest, Neighborhood, NeighborhoodBuilder, OriginDestination, Scenario, Tick, + WeightedUsizeChoice, +}; use ui::PluginCtx; pub trait Plugin: Any { @@ -133,3 +136,17 @@ pub fn choose_intersection(wizard: &mut WrappedWizard, query: &str) -> Option Option { + let neighborhood = "Neighborhood"; + let border = "Border intersection"; + if wizard.choose_string(query, vec![neighborhood, border])? == neighborhood { + choose_neighborhood(map, wizard, query).map(|n| OriginDestination::Neighborhood(n)) + } else { + choose_intersection(wizard, query).map(|i| OriginDestination::Border(i)) + } +} diff --git a/editor/src/plugins/scenarios.rs b/editor/src/plugins/scenarios.rs index bb69f68936..a86ddc8d87 100644 --- a/editor/src/plugins/scenarios.rs +++ b/editor/src/plugins/scenarios.rs @@ -3,8 +3,8 @@ use map_model::Map; use objects::{Ctx, SIM_SETUP}; use piston::input::Key; use plugins::{ - choose_intersection, choose_neighborhood, input_tick, input_weighted_usize, load_scenario, - Plugin, PluginCtx, + choose_intersection, choose_neighborhood, choose_origin_destination, input_tick, + input_weighted_usize, load_scenario, Plugin, PluginCtx, }; use sim::{BorderSpawnOverTime, Neighborhood, Scenario, SeedParkedCars, SpawnOverTime}; @@ -151,11 +151,7 @@ fn edit_scenario(map: &Map, scenario: &mut Scenario, mut wizard: WrappedWizard) &mut wizard, "Where should the agents start?", )?, - go_to_neighborhood: choose_neighborhood( - map, - &mut wizard, - "Where should the agents go?", - )?, + goal: choose_origin_destination(map, &mut wizard, "Where should the agents go?")?, }); } x if x == spawn_border => { diff --git a/map_model/src/intersection.rs b/map_model/src/intersection.rs index 15526cfe55..0d938c5df1 100644 --- a/map_model/src/intersection.rs +++ b/map_model/src/intersection.rs @@ -59,6 +59,14 @@ impl Intersection { self.roads.len() == 2 } + pub fn get_incoming_lanes(&self, map: &Map, lt: LaneType) -> Vec { + self.incoming_lanes + .iter() + .filter(|l| map.get_l(**l).lane_type == lt) + .map(|l| *l) + .collect() + } + pub fn get_outgoing_lanes(&self, map: &Map, lt: LaneType) -> Vec { self.outgoing_lanes .iter() diff --git a/sim/src/helpers.rs b/sim/src/helpers.rs index 0a0e3281c7..c762d08353 100644 --- a/sim/src/helpers.rs +++ b/sim/src/helpers.rs @@ -4,8 +4,8 @@ use map_model::{BuildingID, BusRoute, BusStopID, LaneID, LaneType, Map, RoadID}; use spawn::WalkingEndpoint; use std::collections::{BTreeSet, VecDeque}; use { - BorderSpawnOverTime, CarID, Event, MapEdits, PedestrianID, RouteID, Scenario, SeedParkedCars, - Sim, SpawnOverTime, Tick, WeightedUsizeChoice, + BorderSpawnOverTime, CarID, Event, MapEdits, OriginDestination, PedestrianID, RouteID, + Scenario, SeedParkedCars, Sim, SpawnOverTime, Tick, WeightedUsizeChoice, }; #[derive(StructOpt, Debug, Clone)] @@ -223,7 +223,7 @@ impl Sim { start_tick: Tick::zero(), stop_tick: Tick::from_seconds(5), start_from_neighborhood: "_everywhere_".to_string(), - go_to_neighborhood: "_everywhere_".to_string(), + goal: OriginDestination::Neighborhood("_everywhere_".to_string()), }], border_spawn_over_time: map .all_incoming_borders() @@ -275,7 +275,7 @@ impl Sim { start_tick: Tick::zero(), stop_tick: Tick::from_seconds(5), start_from_neighborhood: "_everywhere_".to_string(), - go_to_neighborhood: "_everywhere_".to_string(), + goal: OriginDestination::Neighborhood("_everywhere_".to_string()), }], border_spawn_over_time: map .all_incoming_borders() diff --git a/sim/src/lib.rs b/sim/src/lib.rs index 111932e8a3..cabf888c12 100644 --- a/sim/src/lib.rs +++ b/sim/src/lib.rs @@ -61,7 +61,8 @@ pub use instrument::save_backtraces; use map_model::{BuildingID, LaneID, Trace, TurnID}; use rand::{RngCore, SeedableRng, XorShiftRng}; pub use scenario::{ - BorderSpawnOverTime, Neighborhood, NeighborhoodBuilder, Scenario, SeedParkedCars, SpawnOverTime, + BorderSpawnOverTime, Neighborhood, NeighborhoodBuilder, OriginDestination, Scenario, + SeedParkedCars, SpawnOverTime, }; pub use sim::{Benchmark, Sim, Summary}; pub use stats::SimStats; diff --git a/sim/src/scenario.rs b/sim/src/scenario.rs index 1624c97d90..6bb8612af7 100644 --- a/sim/src/scenario.rs +++ b/sim/src/scenario.rs @@ -19,6 +19,13 @@ pub struct Scenario { pub border_spawn_over_time: Vec, } +#[derive(Clone, Serialize, Deserialize, Debug)] +pub enum OriginDestination { + Neighborhood(String), + // TODO A serialized Scenario won't last well as the map changes... + Border(IntersectionID), +} + #[derive(Clone, Serialize, Deserialize, Debug)] pub struct SpawnOverTime { pub num_agents: usize, @@ -26,7 +33,7 @@ pub struct SpawnOverTime { pub start_tick: Tick, pub stop_tick: Tick, pub start_from_neighborhood: String, - pub go_to_neighborhood: String, + pub goal: OriginDestination, } #[derive(Clone, Serialize, Deserialize, Debug)] @@ -209,8 +216,13 @@ impl Scenario { if !neighborhoods.contains_key(&s.start_from_neighborhood) { panic!("Neighborhood {} isn't defined", s.start_from_neighborhood); } - if !neighborhoods.contains_key(&s.go_to_neighborhood) { - panic!("Neighborhood {} isn't defined", s.go_to_neighborhood); + match s.goal { + OriginDestination::Neighborhood(ref n) => { + if !neighborhoods.contains_key(n) { + panic!("Neighborhood {} isn't defined", n); + } + } + _ => {} } for _ in 0..s.num_agents { @@ -222,10 +234,6 @@ impl Scenario { .rng .choose(&bldgs_per_neighborhood[&s.start_from_neighborhood]) .unwrap(); - let to_bldg = *sim - .rng - .choose(&bldgs_per_neighborhood[&s.go_to_neighborhood]) - .unwrap(); // Will they drive or not? if let Some(parked_car) = sim @@ -234,6 +242,14 @@ impl Scenario { .into_iter() .find(|p| !reserved_cars.contains(&p.car)) { + // TODO need to change driving goals too + let to_bldg = match s.goal { + OriginDestination::Neighborhood(ref n) => { + *sim.rng.choose(&bldgs_per_neighborhood[n]).unwrap() + } + OriginDestination::Border(_) => BuildingID(42), + }; + reserved_cars.insert(parked_car.car); sim.spawner.start_trip_using_parked_car( spawn_time, @@ -245,11 +261,26 @@ impl Scenario { &mut sim.trips_state, ); } else { + let goal = match s.goal { + OriginDestination::Neighborhood(ref n) => { + WalkingEndpoint::Spot(SidewalkSpot::building( + *sim.rng.choose(&bldgs_per_neighborhood[n]).unwrap(), + map, + )) + } + // TODO get only element, and dont do this computation every iter + OriginDestination::Border(i) => WalkingEndpoint::Border( + i, + map.get_i(i).get_incoming_lanes(map, LaneType::Sidewalk)[0], + ), + }; + sim.spawner.start_trip_just_walking( spawn_time, map, WalkingEndpoint::Spot(SidewalkSpot::building(from_bldg, map)), - to_bldg, + BuildingID(42), // TODO tmp + //goal, &mut sim.trips_state, ); }