bundling all map edits together

This commit is contained in:
Dustin Carlino 2018-10-02 14:36:04 -07:00
parent bbfe00ce63
commit 7b718b4621
17 changed files with 176 additions and 131 deletions

2
.gitignore vendored
View File

@ -3,7 +3,7 @@
*.swp *.swp
editor/editor_state editor/editor_state
editor/road_edits.json editor/map_edits.json
data/input/* data/input/*
data/maps/*.abst data/maps/*.abst

View File

@ -22,7 +22,11 @@ pub struct ControlMap {
} }
impl ControlMap { impl ControlMap {
pub fn new(map: &Map) -> ControlMap { pub fn new(
map: &Map,
stop_signs: &BTreeMap<IntersectionID, ModifiedStopSign>,
traffic_signals: &BTreeMap<IntersectionID, ModifiedTrafficSignal>,
) -> ControlMap {
let mut ctrl = ControlMap { let mut ctrl = ControlMap {
traffic_signals: HashMap::new(), traffic_signals: HashMap::new(),
stop_signs: HashMap::new(), stop_signs: HashMap::new(),
@ -38,11 +42,18 @@ impl ControlMap {
} }
} }
for (i, s) in traffic_signals {
ctrl.traffic_signals.get_mut(i).unwrap().load_savestate(s);
}
for (i, s) in stop_signs {
ctrl.stop_signs.get_mut(i).unwrap().load_savestate(s);
}
ctrl ctrl
} }
pub fn get_traffic_signals_savestate(&self) -> HashMap<IntersectionID, ModifiedTrafficSignal> { pub fn get_traffic_signals_savestate(&self) -> BTreeMap<IntersectionID, ModifiedTrafficSignal> {
let mut h = HashMap::new(); let mut h = BTreeMap::new();
for (i, s) in &self.traffic_signals { for (i, s) in &self.traffic_signals {
if let Some(state) = s.get_savestate() { if let Some(state) = s.get_savestate() {
h.insert(*i, state); h.insert(*i, state);
@ -51,8 +62,8 @@ impl ControlMap {
h h
} }
pub fn get_stop_signs_savestate(&self) -> HashMap<IntersectionID, ModifiedStopSign> { pub fn get_stop_signs_savestate(&self) -> BTreeMap<IntersectionID, ModifiedStopSign> {
let mut h = HashMap::new(); let mut h = BTreeMap::new();
for (i, s) in &self.stop_signs { for (i, s) in &self.stop_signs {
if let Some(state) = s.get_savestate() { if let Some(state) = s.get_savestate() {
h.insert(*i, state); h.insert(*i, state);
@ -60,19 +71,6 @@ impl ControlMap {
} }
h h
} }
pub fn load_savestate(
&mut self,
traffic_signals: &HashMap<IntersectionID, ModifiedTrafficSignal>,
stop_signs: &HashMap<IntersectionID, ModifiedStopSign>,
) {
for (i, s) in traffic_signals {
self.traffic_signals.get_mut(i).unwrap().load_savestate(s);
}
for (i, s) in stop_signs {
self.stop_signs.get_mut(i).unwrap().load_savestate(s);
}
}
} }
// General problem: TurnIDs change as code does. Serialized state is kinda tied to code version. // General problem: TurnIDs change as code does. Serialized state is kinda tied to code version.

View File

@ -257,3 +257,23 @@ current TreeMenu:
Back up and think about ideal for these background controls... Back up and think about ideal for these background controls...
## Managing different map edits
Should be simple -- I want to bundle together map edits as named things, to
prep for A/B tests. But loading a different set of edits could be kind of
tough...
- new control map state has to propagate to intersection editors.
- easy fix: pass them mut ref from control map every tick. then just have to reload control map.
- road edits have to propogate
- theres a way to do that live right now, but it's kind of brittle and funky. probably safer to load from scratch.
- but then have to reload things like steepness visualizer plugin... actually, just that, seemingly.
- er, but also the hider plugin -- it holds onto laneIDs, which may change!
Alright, I think this is the sequence of things to do:
1) make a few plugins less stateful anyway, by taking refs to map/control map stuff instead of caching stuff. thats useful regardless.
- but wait, then road editor kind of cant work, because mut borrow edits from map while holding immutable lane/road refs. theyre really indep things, so cant store together.
2) make it possible to completely reload UI and everything from scratch, from a plugin. rationale: it'd be nice to switch maps from inside the editor anyway. not necessary, but useful.
3) make road edits propogate correctly, and somehow have a strategy for ensuring nothing is forgotten. impl today is VERY incomplete.

View File

@ -1,20 +1,23 @@
use control::ControlMap; use control::ControlMap;
use ezgui::UserInput; use ezgui::UserInput;
use map_model::{EditReason, Edits, LaneID, LaneType, Map}; use map_model::{EditReason, LaneID, LaneType, Map, RoadEdits};
use objects::{EDIT_MAP, ID}; use objects::{EDIT_MAP, ID};
use piston::input::Key; use piston::input::Key;
use plugins::Colorizer; use plugins::Colorizer;
use render::DrawMap; use render::DrawMap;
use sim::Sim; use sim::Sim;
pub enum RoadEditor { pub struct RoadEditor {
Inactive(Edits), edits: RoadEdits,
Active(Edits), active: bool,
} }
impl RoadEditor { impl RoadEditor {
pub fn new(edits: Edits) -> RoadEditor { pub fn new(edits: RoadEdits) -> RoadEditor {
RoadEditor::Inactive(edits) RoadEditor {
edits,
active: false,
}
} }
pub fn event( pub fn event(
@ -26,63 +29,60 @@ impl RoadEditor {
control_map: &ControlMap, control_map: &ControlMap,
sim: &mut Sim, sim: &mut Sim,
) -> bool { ) -> bool {
let mut new_state: Option<RoadEditor> = None; // TODO a bit awkward that we can't pull this info from RoadEdits easily
// TODO a bit awkward that we can't pull this info from Edits easily
let mut changed: Option<(LaneID, LaneType)> = None; let mut changed: Option<(LaneID, LaneType)> = None;
match self { if !self.active && selected.is_none() {
RoadEditor::Inactive(edits) => match selected { if input.unimportant_key_pressed(Key::E, EDIT_MAP, "Start editing roads") {
None => { self.active = true;
if input.unimportant_key_pressed(Key::E, EDIT_MAP, "Start editing roads") { }
// TODO cloning edits sucks! want to consume self }
new_state = Some(RoadEditor::Active(edits.clone())); if self.active {
} if input.key_pressed(Key::Return, "stop editing roads") {
} self.active = false;
_ => {} } else if let Some(ID::Lane(id)) = selected {
}, let lane = map.get_l(id);
RoadEditor::Active(edits) => { let road = map.get_r(lane.parent);
if input.key_pressed(Key::Return, "stop editing roads") { let reason = EditReason::BasemapWrong; // TODO be able to choose
new_state = Some(RoadEditor::Inactive(edits.clone()));
} else if let Some(ID::Lane(id)) = selected {
let lane = map.get_l(id);
let road = map.get_r(lane.parent);
let reason = EditReason::BasemapWrong; // TODO be able to choose
if lane.lane_type != LaneType::Sidewalk { if lane.lane_type != LaneType::Sidewalk {
if lane.lane_type != LaneType::Driving if lane.lane_type != LaneType::Driving
&& input.key_pressed(Key::D, "make this a driving lane") && input.key_pressed(Key::D, "make this a driving lane")
{
if self
.edits
.change_lane_type(reason, road, lane, LaneType::Driving)
{ {
if edits.change_lane_type(reason, road, lane, LaneType::Driving) { changed = Some((lane.id, LaneType::Driving));
changed = Some((lane.id, LaneType::Driving));
}
} }
if lane.lane_type != LaneType::Parking }
&& input.key_pressed(Key::P, "make this a parking lane") if lane.lane_type != LaneType::Parking
&& input.key_pressed(Key::P, "make this a parking lane")
{
if self
.edits
.change_lane_type(reason, road, lane, LaneType::Parking)
{ {
if edits.change_lane_type(reason, road, lane, LaneType::Parking) { changed = Some((lane.id, LaneType::Parking));
changed = Some((lane.id, LaneType::Parking));
}
} }
if lane.lane_type != LaneType::Biking }
&& input.key_pressed(Key::B, "make this a bike lane") if lane.lane_type != LaneType::Biking
&& input.key_pressed(Key::B, "make this a bike lane")
{
if self
.edits
.change_lane_type(reason, road, lane, LaneType::Biking)
{ {
if edits.change_lane_type(reason, road, lane, LaneType::Biking) { changed = Some((lane.id, LaneType::Biking));
changed = Some((lane.id, LaneType::Biking));
}
} }
if input.key_pressed(Key::Backspace, "delete this lane") { }
if edits.delete_lane(road, lane) { if input.key_pressed(Key::Backspace, "delete this lane") {
warn!( if self.edits.delete_lane(road, lane) {
"Have to reload the map from scratch to pick up this change!" warn!("Have to reload the map from scratch to pick up this change!");
);
}
} }
} }
} }
} }
};
if let Some(s) = new_state {
*self = s;
} }
if let Some((id, new_type)) = changed { if let Some((id, new_type)) = changed {
let intersections = map.get_l(id).intersections(); let intersections = map.get_l(id).intersections();
@ -114,17 +114,11 @@ impl RoadEditor {
} }
} }
match self { self.active
RoadEditor::Inactive(_) => false,
_ => true,
}
} }
pub fn get_edits(&self) -> &Edits { pub fn get_edits(&self) -> &RoadEdits {
match self { &self.edits
RoadEditor::Inactive(edits) => edits,
RoadEditor::Active(edits) => edits,
}
} }
} }

View File

@ -5,7 +5,6 @@
use abstutil; use abstutil;
use colors::{ColorScheme, Colors}; use colors::{ColorScheme, Colors};
use control::ControlMap; use control::ControlMap;
use control::{ModifiedStopSign, ModifiedTrafficSignal};
use ezgui::{Canvas, EventLoopMode, GfxCtx, Text, ToggleableLayer, UserInput, BOTTOM_LEFT, GUI}; use ezgui::{Canvas, EventLoopMode, GfxCtx, Text, ToggleableLayer, UserInput, BOTTOM_LEFT, GUI};
use flame; use flame;
use graphics::types::Color; use graphics::types::Color;
@ -37,8 +36,7 @@ use plugins::warp::WarpState;
use plugins::Colorizer; use plugins::Colorizer;
use render::{DrawMap, RenderOptions}; use render::{DrawMap, RenderOptions};
use sim; use sim;
use sim::Sim; use sim::{MapEdits, Sim};
use std::collections::HashMap;
use std::process; use std::process;
// TODO ideally these would be tuned kind of dynamically based on rendering speed // TODO ideally these would be tuned kind of dynamically based on rendering speed
@ -77,13 +75,12 @@ impl UIWrapper {
let logs = DisplayLogs::new(); let logs = DisplayLogs::new();
flame::start("setup"); flame::start("setup");
let (map, edits, control_map, sim) = sim::load( let (map, control_map, sim) = sim::load(
load, load,
scenario_name, scenario_name,
rng_seed, rng_seed,
Some(sim::Tick::from_seconds(30)), Some(sim::Tick::from_seconds(30)),
); );
let extra_shapes = if let Some(path) = kml { let extra_shapes = if let Some(path) = kml {
kml::load(&path, &map.get_gps_bounds()).expect("Couldn't load extra KML shapes") kml::load(&path, &map.get_gps_bounds()).expect("Couldn't load extra KML shapes")
} else { } else {
@ -98,6 +95,7 @@ impl UIWrapper {
flame::dump_stdout(); flame::dump_stdout();
let steepness_viz = SteepnessVisualizer::new(&map); let steepness_viz = SteepnessVisualizer::new(&map);
let road_editor = RoadEditor::new(map.get_road_edits().clone());
let mut ui = UI { let mut ui = UI {
// TODO organize this by section // TODO organize this by section
@ -107,6 +105,7 @@ impl UIWrapper {
sim, sim,
steepness_viz, steepness_viz,
road_editor,
sim_ctrl: SimController::new(), sim_ctrl: SimController::new(),
layers: ToggleableLayers::new(), layers: ToggleableLayers::new(),
@ -123,7 +122,6 @@ impl UIWrapper {
osm_classifier: OsmClassifier::new(), osm_classifier: OsmClassifier::new(),
traffic_signal_editor: TrafficSignalEditor::new(), traffic_signal_editor: TrafficSignalEditor::new(),
stop_sign_editor: StopSignEditor::new(), stop_sign_editor: StopSignEditor::new(),
road_editor: RoadEditor::new(edits),
color_picker: ColorPicker::new(), color_picker: ColorPicker::new(),
geom_validator: Validator::new(), geom_validator: Validator::new(),
turn_cycler: TurnCyclerState::new(), turn_cycler: TurnCyclerState::new(),
@ -143,8 +141,6 @@ impl UIWrapper {
ui.canvas.cam_x = state.cam_x; ui.canvas.cam_x = state.cam_x;
ui.canvas.cam_y = state.cam_y; ui.canvas.cam_y = state.cam_y;
ui.canvas.cam_zoom = state.cam_zoom; ui.canvas.cam_zoom = state.cam_zoom;
ui.control_map
.load_savestate(&state.traffic_signals, &state.stop_signs);
} }
_ => { _ => {
warn!("Couldn't load editor_state or it's for a different map, so just centering initial view"); warn!("Couldn't load editor_state or it's for a different map, so just centering initial view");
@ -384,15 +380,21 @@ impl UI {
cam_x: self.canvas.cam_x, cam_x: self.canvas.cam_x,
cam_y: self.canvas.cam_y, cam_y: self.canvas.cam_y,
cam_zoom: self.canvas.cam_zoom, cam_zoom: self.canvas.cam_zoom,
traffic_signals: self.control_map.get_traffic_signals_savestate(),
stop_signs: self.control_map.get_stop_signs_savestate(),
}; };
// TODO maybe make state line up with the map, so loading from a new map doesn't break // TODO maybe make state line up with the map, so loading from a new map doesn't break
abstutil::write_json("editor_state", &state).expect("Saving editor_state failed"); abstutil::write_json("editor_state", &state).expect("Saving editor_state failed");
abstutil::write_json("color_scheme", &self.cs).expect("Saving color_scheme failed"); abstutil::write_json("color_scheme", &self.cs).expect("Saving color_scheme failed");
abstutil::write_json("road_edits.json", self.road_editor.get_edits()) abstutil::write_json(
.expect("Saving road_edits.json failed"); "map_edits.json",
info!("Saved editor_state, color_scheme, and road_edits.json"); &MapEdits {
edits_name: "nameless".to_string(),
map_name: self.map.get_name().to_string(),
road_edits: self.road_editor.get_edits().clone(),
stop_signs: self.control_map.get_stop_signs_savestate(),
traffic_signals: self.control_map.get_traffic_signals_savestate(),
},
).expect("Saving map_edits.json failed");
info!("Saved editor_state, color_scheme, and map_edits.json");
process::exit(0); process::exit(0);
} }
@ -538,9 +540,6 @@ pub struct EditorState {
pub cam_x: f64, pub cam_x: f64,
pub cam_y: f64, pub cam_y: f64,
pub cam_zoom: f64, pub cam_zoom: f64,
pub traffic_signals: HashMap<IntersectionID, ModifiedTrafficSignal>,
pub stop_signs: HashMap<IntersectionID, ModifiedStopSign>,
} }
pub struct ToggleableLayers { pub struct ToggleableLayers {

View File

@ -44,7 +44,7 @@ fn main() {
log::set_max_level(LevelFilter::Debug); log::set_max_level(LevelFilter::Debug);
log::set_logger(&LOG_ADAPTER).unwrap(); log::set_logger(&LOG_ADAPTER).unwrap();
let (map, _, control_map, mut sim) = sim::load( let (map, control_map, mut sim) = sim::load(
flags.load.clone(), flags.load.clone(),
flags.scenario_name, flags.scenario_name,
flags.rng_seed, flags.rng_seed,

View File

@ -4,14 +4,14 @@ use {Lane, LaneType, Road, RoadID};
// TODO bring in the intersection modifications from the control crate here. for now, road edits // TODO bring in the intersection modifications from the control crate here. for now, road edits
// are here, since map construction maybe needs to know these? // are here, since map construction maybe needs to know these?
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Edits { pub struct RoadEdits {
// TODO detect when we wind up editing back to the original thing // TODO detect when we wind up editing back to the original thing
pub(crate) roads: BTreeMap<RoadID, RoadEdit>, pub(crate) roads: BTreeMap<RoadID, RoadEdit>,
} }
impl Edits { impl RoadEdits {
pub fn new() -> Edits { pub fn new() -> RoadEdits {
Edits { RoadEdits {
roads: BTreeMap::new(), roads: BTreeMap::new(),
} }
} }

View File

@ -34,7 +34,7 @@ mod turn;
pub use area::{Area, AreaID, AreaType}; pub use area::{Area, AreaID, AreaType};
pub use building::{Building, BuildingID, FrontPath}; pub use building::{Building, BuildingID, FrontPath};
pub use bus_stop::{BusRoute, BusStop, BusStopID}; pub use bus_stop::{BusRoute, BusStop, BusStopID};
pub use edits::{EditReason, Edits}; pub use edits::{EditReason, RoadEdits};
pub use intersection::{Intersection, IntersectionID}; pub use intersection::{Intersection, IntersectionID};
pub use lane::{Lane, LaneID, LaneType, PARKING_SPOT_LENGTH}; pub use lane::{Lane, LaneID, LaneType, PARKING_SPOT_LENGTH};
pub use map::Map; pub use map::Map;

View File

@ -1,4 +1,4 @@
use edits::Edits; use edits::RoadEdits;
use lane::LaneType; use lane::LaneType;
use raw_data; use raw_data;
use road::RoadID; use road::RoadID;
@ -75,7 +75,7 @@ impl LaneSpec {
} }
} }
pub(crate) fn get_lane_specs(r: &raw_data::Road, id: RoadID, edits: &Edits) -> Vec<LaneSpec> { pub(crate) fn get_lane_specs(r: &raw_data::Road, id: RoadID, edits: &RoadEdits) -> Vec<LaneSpec> {
let (side1_types, side2_types) = if let Some(e) = edits.roads.get(&id) { let (side1_types, side2_types) = if let Some(e) = edits.roads.get(&id) {
info!("Using edits for {}", id); info!("Using edits for {}", id);
(e.forwards_lanes.clone(), e.backwards_lanes.clone()) (e.forwards_lanes.clone(), e.backwards_lanes.clone())

View File

@ -1,7 +1,7 @@
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0 // Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
use abstutil; use abstutil;
use edits::Edits; use edits::RoadEdits;
use flame; use flame;
use geom::{Bounds, HashablePt2D, PolyLine, Pt2D}; use geom::{Bounds, HashablePt2D, PolyLine, Pt2D};
use make; use make;
@ -30,10 +30,11 @@ pub struct Map {
bounds: Bounds, bounds: Bounds,
name: String, name: String,
road_edits: RoadEdits,
} }
impl Map { impl Map {
pub fn new(path: &str, edits: &Edits) -> Result<Map, Error> { pub fn new(path: &str, road_edits: RoadEdits) -> Result<Map, Error> {
// TODO I think I want something a bit different than flame: // TODO I think I want something a bit different than flame:
// - Print as each phase occurs // - Print as each phase occurs
// - Print with nicely formatted durations // - Print with nicely formatted durations
@ -48,14 +49,15 @@ impl Map {
.into_string() .into_string()
.unwrap(), .unwrap(),
data, data,
edits, road_edits,
)) ))
} }
pub fn create_from_raw(name: String, data: raw_data::Map, edits: &Edits) -> Map { pub fn create_from_raw(name: String, data: raw_data::Map, road_edits: RoadEdits) -> Map {
let bounds = data.get_gps_bounds(); let bounds = data.get_gps_bounds();
let mut m = Map { let mut m = Map {
name, name,
road_edits,
bounds, bounds,
roads: Vec::new(), roads: Vec::new(),
lanes: Vec::new(), lanes: Vec::new(),
@ -108,7 +110,7 @@ impl Map {
let i2 = pt_to_intersection[&HashablePt2D::from(road_center_pts.last_pt())]; let i2 = pt_to_intersection[&HashablePt2D::from(road_center_pts.last_pt())];
// TODO move this to make/lanes.rs too // TODO move this to make/lanes.rs too
for lane in make::get_lane_specs(r, road_id, edits) { for lane in make::get_lane_specs(r, road_id, &m.road_edits) {
let id = LaneID(counter); let id = LaneID(counter);
counter += 1; counter += 1;
@ -394,6 +396,10 @@ impl Map {
&self.name &self.name
} }
pub fn get_road_edits(&self) -> &RoadEdits {
&self.road_edits
}
pub fn all_bus_stops(&self) -> &BTreeMap<BusStopID, BusStop> { pub fn all_bus_stops(&self) -> &BTreeMap<BusStopID, BusStop> {
&self.bus_stops &self.bus_stops
} }

25
sim/src/edits.rs Normal file
View File

@ -0,0 +1,25 @@
use control::{ModifiedStopSign, ModifiedTrafficSignal};
use map_model::{IntersectionID, RoadEdits};
use std::collections::BTreeMap;
#[derive(Serialize, Deserialize)]
pub struct MapEdits {
pub edits_name: String,
pub map_name: String,
pub road_edits: RoadEdits,
pub stop_signs: BTreeMap<IntersectionID, ModifiedStopSign>,
pub traffic_signals: BTreeMap<IntersectionID, ModifiedTrafficSignal>,
}
impl MapEdits {
pub fn new() -> MapEdits {
MapEdits {
edits_name: "unnamed".to_string(),
map_name: "TODO".to_string(), // TODO er
road_edits: RoadEdits::new(),
stop_signs: BTreeMap::new(),
traffic_signals: BTreeMap::new(),
}
}
}

View File

@ -2,10 +2,10 @@ use abstutil;
use control::ControlMap; use control::ControlMap;
use flame; use flame;
use geom::Polygon; use geom::Polygon;
use map_model::{BuildingID, BusRoute, BusStopID, Edits, LaneID, Map}; use map_model::{BuildingID, BusRoute, BusStopID, LaneID, Map};
use rand::Rng; use rand::Rng;
use std::collections::VecDeque; use std::collections::VecDeque;
use {CarID, Event, PedestrianID, RouteID, Scenario, Sim, Tick}; use {CarID, Event, MapEdits, PedestrianID, RouteID, Scenario, Sim, Tick};
// Convenience method to setup everything. // Convenience method to setup everything.
pub fn load( pub fn load(
@ -13,8 +13,9 @@ pub fn load(
scenario_name: String, scenario_name: String,
rng_seed: Option<u8>, rng_seed: Option<u8>,
savestate_every: Option<Tick>, savestate_every: Option<Tick>,
) -> (Map, Edits, ControlMap, Sim) { ) -> (Map, ControlMap, Sim) {
let edits: Edits = abstutil::read_json("road_edits.json").unwrap_or(Edits::new()); // TODO read a specific one
let edits: MapEdits = abstutil::read_json("map_edits.json").unwrap_or(MapEdits::new());
if input.contains("data/save/") { if input.contains("data/save/") {
info!("Resuming from {}", input); info!("Resuming from {}", input);
@ -23,17 +24,17 @@ pub fn load(
flame::end("read sim savestate"); flame::end("read sim savestate");
// TODO assuming the relative path :( // TODO assuming the relative path :(
let map_path = format!("../data/maps/{}.abst", sim.map_name); let map_path = format!("../data/maps/{}.abst", sim.map_name);
let map = let map = Map::new(&map_path, edits.road_edits.clone())
Map::new(&map_path, &edits).expect(&format!("Couldn't load map from {}", map_path)); .expect(&format!("Couldn't load map from {}", map_path));
let control_map = ControlMap::new(&map); let control_map = ControlMap::new(&map, &edits.stop_signs, &edits.traffic_signals);
(map, edits, control_map, sim) (map, control_map, sim)
} else if input.contains("data/scenarios/") { } else if input.contains("data/scenarios/") {
info!("Seeding the simulation from scenario {}", input); info!("Seeding the simulation from scenario {}", input);
let scenario: Scenario = abstutil::read_json(&input).expect("loading scenario failed"); let scenario: Scenario = abstutil::read_json(&input).expect("loading scenario failed");
let map_path = format!("../data/maps/{}.abst", scenario.map_name); let map_path = format!("../data/maps/{}.abst", scenario.map_name);
let map = let map = Map::new(&map_path, edits.road_edits.clone())
Map::new(&map_path, &edits).expect(&format!("Couldn't load map from {}", map_path)); .expect(&format!("Couldn't load map from {}", map_path));
let control_map = ControlMap::new(&map); let control_map = ControlMap::new(&map, &edits.stop_signs, &edits.traffic_signals);
let mut sim = Sim::new( let mut sim = Sim::new(
&map, &map,
scenario.scenario_name.clone(), scenario.scenario_name.clone(),
@ -41,15 +42,15 @@ pub fn load(
savestate_every, savestate_every,
); );
scenario.instantiate(&mut sim, &map); scenario.instantiate(&mut sim, &map);
(map, edits, control_map, sim) (map, control_map, sim)
} else { } else {
info!("Loading map {}", input); info!("Loading map {}", input);
let map = Map::new(&input, &edits).expect("Couldn't load map"); let map = Map::new(&input, edits.road_edits.clone()).expect("Couldn't load map");
let control_map = ControlMap::new(&map); let control_map = ControlMap::new(&map, &edits.stop_signs, &edits.traffic_signals);
flame::start("create sim"); flame::start("create sim");
let sim = Sim::new(&map, scenario_name, rng_seed, savestate_every); let sim = Sim::new(&map, scenario_name, rng_seed, savestate_every);
flame::end("create sim"); flame::end("create sim");
(map, edits, control_map, sim) (map, control_map, sim)
} }
} }

View File

@ -33,6 +33,7 @@ extern crate serde_derive;
mod macros; mod macros;
mod driving; mod driving;
mod edits;
mod events; mod events;
mod helpers; mod helpers;
mod instrument; mod instrument;
@ -51,6 +52,7 @@ mod walking;
use abstutil::Cloneable; use abstutil::Cloneable;
use dimensioned::si; use dimensioned::si;
pub use edits::MapEdits;
pub use events::Event; pub use events::Event;
use geom::{Angle, Pt2D}; use geom::{Angle, Pt2D};
pub use helpers::load; pub use helpers::load;

View File

@ -5,7 +5,7 @@ extern crate sim;
#[test] #[test]
fn aorta_model_completes() { fn aorta_model_completes() {
let (map, _, control_map, mut sim) = sim::load( let (map, control_map, mut sim) = sim::load(
"../data/maps/small.abst".to_string(), "../data/maps/small.abst".to_string(),
"aorta_model_completes".to_string(), "aorta_model_completes".to_string(),
Some(42), Some(42),

View File

@ -5,7 +5,7 @@ extern crate sim;
#[test] #[test]
fn serialization() { fn serialization() {
let (map, _, _, mut sim) = sim::load( let (map, _, mut sim) = sim::load(
"../data/maps/small.abst".to_string(), "../data/maps/small.abst".to_string(),
"serialization".to_string(), "serialization".to_string(),
Some(42), Some(42),
@ -22,7 +22,7 @@ fn serialization() {
#[test] #[test]
fn from_scratch() { fn from_scratch() {
println!("Creating two simulations"); println!("Creating two simulations");
let (map, _, control_map, mut sim1) = sim::load( let (map, control_map, mut sim1) = sim::load(
"../data/maps/small.abst".to_string(), "../data/maps/small.abst".to_string(),
"from_scratch_1".to_string(), "from_scratch_1".to_string(),
Some(42), Some(42),
@ -49,7 +49,7 @@ fn from_scratch() {
#[test] #[test]
fn with_savestating() { fn with_savestating() {
println!("Creating two simulations"); println!("Creating two simulations");
let (map, _, control_map, mut sim1) = sim::load( let (map, control_map, mut sim1) = sim::load(
"../data/maps/small.abst".to_string(), "../data/maps/small.abst".to_string(),
"with_savestating_1".to_string(), "with_savestating_1".to_string(),
Some(42), Some(42),

View File

@ -5,6 +5,7 @@ extern crate map_model;
extern crate sim; extern crate sim;
use map_model::LaneID; use map_model::LaneID;
use std::collections::BTreeMap;
// TODO refactor a few more things to make these more succinct? // TODO refactor a few more things to make these more succinct?
@ -62,7 +63,7 @@ fn setup(
map: map_model::Map, map: map_model::Map,
) -> (map_model::Map, control::ControlMap, sim::Sim) { ) -> (map_model::Map, control::ControlMap, sim::Sim) {
let rng_seed = 123; let rng_seed = 123;
let control_map = control::ControlMap::new(&map); let control_map = control::ControlMap::new(&map, &BTreeMap::new(), &BTreeMap::new());
let sim = sim::Sim::new(&map, scenario_name.to_string(), Some(rng_seed), None); let sim = sim::Sim::new(&map, scenario_name.to_string(), Some(rng_seed), None);
(map, control_map, sim) (map, control_map, sim)
} }
@ -71,7 +72,6 @@ fn setup(
fn make_test_map() -> map_model::Map { fn make_test_map() -> map_model::Map {
use dimensioned::si; use dimensioned::si;
use map_model::{raw_data, LaneType}; use map_model::{raw_data, LaneType};
use std::collections::BTreeMap;
let left = geom::LonLat::new(100.0, 50.0); let left = geom::LonLat::new(100.0, 50.0);
let right = geom::LonLat::new(200.0, 50.0); let right = geom::LonLat::new(200.0, 50.0);
@ -116,7 +116,7 @@ fn make_test_map() -> map_model::Map {
areas: Vec::new(), areas: Vec::new(),
coordinates_in_world_space: true, coordinates_in_world_space: true,
}, },
&map_model::Edits::new(), map_model::RoadEdits::new(),
); );
assert_eq!(map.all_roads().len(), 1); assert_eq!(map.all_roads().len(), 1);

View File

@ -5,7 +5,7 @@ extern crate sim;
#[test] #[test]
fn bus_reaches_stops() { fn bus_reaches_stops() {
let (map, _, control_map, mut sim) = sim::load( let (map, control_map, mut sim) = sim::load(
"../data/maps/small.abst".to_string(), "../data/maps/small.abst".to_string(),
"bus_reaches_stops".to_string(), "bus_reaches_stops".to_string(),
Some(42), Some(42),
@ -33,7 +33,7 @@ fn bus_reaches_stops() {
// TODO this test is strictly more complicated than bus_reaches_stops, should it subsume it? // TODO this test is strictly more complicated than bus_reaches_stops, should it subsume it?
#[test] #[test]
fn ped_uses_bus() { fn ped_uses_bus() {
let (map, _, control_map, mut sim) = sim::load( let (map, control_map, mut sim) = sim::load(
"../data/maps/small.abst".to_string(), "../data/maps/small.abst".to_string(),
"bus_reaches_stops".to_string(), "bus_reaches_stops".to_string(),
Some(42), Some(42),