the great control layer merge

This commit is contained in:
Dustin Carlino 2018-11-30 12:36:27 -08:00
parent 609c731fa0
commit 4d7c1203a6
41 changed files with 268 additions and 461 deletions

View File

@ -3,7 +3,6 @@
members = [ members = [
"abstutil", "abstutil",
"analyze_code", "analyze_code",
"control",
"convert_osm", "convert_osm",
"editor", "editor",
"ezgui", "ezgui",

View File

@ -1,12 +0,0 @@
[package]
name = "control"
version = "0.1.0"
authors = ["Dustin Carlino <dabreegster@gmail.com>"]
[dependencies]
abstutil = { path = "../abstutil" }
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
log = "0.4.5"
map_model = { path = "../map_model" }
serde = "1.0"
serde_derive = "1.0"

View File

@ -1,95 +0,0 @@
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
extern crate abstutil;
extern crate dimensioned;
#[macro_use]
extern crate log;
extern crate map_model;
#[macro_use]
extern crate serde_derive;
#[macro_use]
mod macros;
mod stop_signs;
mod traffic_signals;
use map_model::{IntersectionID, IntersectionType, Map};
use std::collections::{BTreeMap, HashMap};
pub use stop_signs::ControlStopSign;
pub use traffic_signals::ControlTrafficSignal;
// TODO awful name
pub struct ControlMap {
pub traffic_signals: HashMap<IntersectionID, ControlTrafficSignal>,
pub stop_signs: HashMap<IntersectionID, ControlStopSign>,
// Note that border nodes belong in neither!
}
impl ControlMap {
pub fn new(
map: &Map,
stop_signs: BTreeMap<IntersectionID, ControlStopSign>,
traffic_signals: BTreeMap<IntersectionID, ControlTrafficSignal>,
) -> ControlMap {
let mut ctrl = ControlMap {
traffic_signals: HashMap::new(),
stop_signs: HashMap::new(),
};
for i in map.all_intersections() {
match i.intersection_type {
IntersectionType::StopSign => {
ctrl.stop_signs
.insert(i.id, ControlStopSign::new(map, i.id));
}
IntersectionType::TrafficSignal => {
ctrl.traffic_signals
.insert(i.id, ControlTrafficSignal::new(map, i.id));
}
IntersectionType::Border => {}
};
}
for (i, s) in stop_signs.into_iter() {
ctrl.stop_signs.insert(i, s);
}
for (i, s) in traffic_signals.into_iter() {
ctrl.traffic_signals.insert(i, s);
}
ctrl
}
pub fn get_changed_stop_signs(&self) -> BTreeMap<IntersectionID, ControlStopSign> {
let mut h: BTreeMap<IntersectionID, ControlStopSign> = BTreeMap::new();
for (i, s) in &self.stop_signs {
if s.is_changed() {
h.insert(*i, s.clone());
}
}
h
}
pub fn get_changed_traffic_signals(&self) -> BTreeMap<IntersectionID, ControlTrafficSignal> {
let mut h = BTreeMap::new();
for (i, s) in &self.traffic_signals {
if s.is_changed() {
h.insert(*i, s.clone());
}
}
h
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy, PartialOrd)]
pub enum TurnPriority {
// For stop signs: cars have to stop before doing this turn, and are accepted with the lowest priority.
// For traffic signals: can't do this turn at all.
Stop,
// Cars can do this immediately if there are no previously accepted conflicting turns.
Yield,
// These must be non-conflicting, and cars don't have to stop before doing this turn (unless a
// conflicting Yield has been accepted).
Priority,
}

View File

@ -1,37 +0,0 @@
// Call the log crate, but pre-set the target.
/*macro_rules! debug {
( $( $x:expr ),* ) => {
{
extern crate log;
log!(target: "control", log::Level::Debug, $( $x, )* );
}
}
}
macro_rules! info {
( $( $x:expr ),* ) => {
{
extern crate log;
log!(target: "control", log::Level::Info, $( $x, )* );
}
}
}*/
macro_rules! warn {
( $( $x:expr ),* ) => {
{
extern crate log;
log!(target: "control", log::Level::Warn, $( $x, )* );
}
}
}
/*macro_rules! error {
( $( $x:expr ),* ) => {
{
extern crate log;
log!(target: "control", log::Level::Error, $( $x, )* );
}
}
}*/

View File

@ -6,7 +6,6 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
[dependencies] [dependencies]
aabb-quadtree = "0.1.0" aabb-quadtree = "0.1.0"
abstutil = { path = "../abstutil" } abstutil = { path = "../abstutil" }
control = { path = "../control" }
counter = "0.4.3" counter = "0.4.3"
cpuprofiler = "0.0.3" cpuprofiler = "0.0.3"
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] } dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }

View File

@ -2,7 +2,6 @@
extern crate aabb_quadtree; extern crate aabb_quadtree;
extern crate abstutil; extern crate abstutil;
extern crate control;
extern crate counter; extern crate counter;
extern crate cpuprofiler; extern crate cpuprofiler;
extern crate dimensioned; extern crate dimensioned;

View File

@ -1,5 +1,4 @@
use colors::ColorScheme; use colors::ColorScheme;
use control::ControlMap;
use ezgui::Canvas; use ezgui::Canvas;
use geom::Pt2D; use geom::Pt2D;
use map_model::{AreaID, BuildingID, BusStopID, IntersectionID, LaneID, Map, ParcelID, TurnID}; use map_model::{AreaID, BuildingID, BusStopID, IntersectionID, LaneID, Map, ParcelID, TurnID};
@ -30,14 +29,14 @@ impl ID {
} }
} }
pub fn debug(&self, map: &Map, control_map: &ControlMap, sim: &mut Sim, draw_map: &DrawMap) { pub fn debug(&self, map: &Map, sim: &mut Sim, draw_map: &DrawMap) {
match *self { match *self {
ID::Lane(id) => { ID::Lane(id) => {
map.get_l(id).dump_debug(); map.get_l(id).dump_debug();
} }
ID::Intersection(id) => { ID::Intersection(id) => {
map.get_i(id).dump_debug(); map.get_i(id).dump_debug();
sim.debug_intersection(id, control_map); sim.debug_intersection(id, map);
} }
ID::Turn(id) => { ID::Turn(id) => {
map.get_t(id).dump_debug(map); map.get_t(id).dump_debug(map);
@ -102,7 +101,6 @@ impl ID {
pub struct Ctx<'a> { pub struct Ctx<'a> {
pub cs: &'a mut ColorScheme, pub cs: &'a mut ColorScheme,
pub map: &'a Map, pub map: &'a Map,
pub control_map: &'a ControlMap,
pub draw_map: &'a DrawMap, pub draw_map: &'a DrawMap,
pub canvas: &'a Canvas, pub canvas: &'a Canvas,
pub sim: &'a Sim, pub sim: &'a Sim,

View File

@ -44,7 +44,6 @@ impl Plugin for DebugObjectsState {
} else if ctx.input.key_pressed(Key::D, "debug") { } else if ctx.input.key_pressed(Key::D, "debug") {
id.debug( id.debug(
&ctx.primary.map, &ctx.primary.map,
&ctx.primary.control_map,
&mut ctx.primary.sim, &mut ctx.primary.sim,
&ctx.primary.draw_map, &ctx.primary.draw_map,
); );

View File

@ -1,10 +1,9 @@
use control::ControlMap;
use ezgui::{GfxCtx, Wizard, WrappedWizard}; use ezgui::{GfxCtx, Wizard, WrappedWizard};
use map_model::Map; use map_model::Map;
use objects::{Ctx, SIM_SETUP}; use objects::{Ctx, SIM_SETUP};
use piston::input::Key; use piston::input::Key;
use plugins::{choose_edits, Plugin, PluginCtx}; use plugins::{choose_edits, Plugin, PluginCtx};
use sim::{MapEdits, SimFlags}; use sim::SimFlags;
use ui::{PerMapUI, PluginsPerMap}; use ui::{PerMapUI, PluginsPerMap};
pub enum EditsManager { pub enum EditsManager {
@ -36,7 +35,6 @@ impl Plugin for EditsManager {
if manage_edits( if manage_edits(
&mut ctx.primary.current_flags, &mut ctx.primary.current_flags,
&ctx.primary.map, &ctx.primary.map,
&ctx.primary.control_map,
ctx.kml, ctx.kml,
&mut new_primary, &mut new_primary,
wizard.wrap(ctx.input), wizard.wrap(ctx.input),
@ -76,7 +74,6 @@ impl Plugin for EditsManager {
fn manage_edits( fn manage_edits(
current_flags: &mut SimFlags, current_flags: &mut SimFlags,
map: &Map, map: &Map,
control_map: &ControlMap,
kml: &Option<String>, kml: &Option<String>,
new_primary: &mut Option<(PerMapUI, PluginsPerMap)>, new_primary: &mut Option<(PerMapUI, PluginsPerMap)>,
mut wizard: WrappedWizard, mut wizard: WrappedWizard,
@ -93,14 +90,8 @@ fn manage_edits(
// Slow to create this every tick just to get the description? It's actually frozen once the // Slow to create this every tick just to get the description? It's actually frozen once the
// wizard is started... // wizard is started...
let mut edits = MapEdits { let mut edits = map.get_edits().clone();
edits_name: current_flags.edits_name.to_string(), edits.edits_name = edits.edits_name.clone();
map_name: map.get_name().to_string(),
road_edits: map.get_road_edits().clone(),
stop_signs: control_map.get_changed_stop_signs(),
traffic_signals: control_map.get_changed_traffic_signals(),
};
edits.road_edits.edits_name = edits.edits_name.clone();
match wizard match wizard
.choose_string(&format!("Manage {}", edits.describe()), choices)? .choose_string(&format!("Manage {}", edits.describe()), choices)?

View File

@ -15,17 +15,16 @@ impl RoadEditor {
impl Plugin for RoadEditor { impl Plugin for RoadEditor {
fn event(&mut self, ctx: PluginCtx) -> bool { fn event(&mut self, ctx: PluginCtx) -> bool {
let (input, selected, map, draw_map, control_map, sim) = ( let (input, selected, map, draw_map, sim) = (
ctx.input, ctx.input,
ctx.primary.current_selection, ctx.primary.current_selection,
&mut ctx.primary.map, &mut ctx.primary.map,
&mut ctx.primary.draw_map, &mut ctx.primary.draw_map,
&ctx.primary.control_map,
&mut ctx.primary.sim, &mut ctx.primary.sim,
); );
let mut edits = map.get_road_edits().clone(); let mut edits = map.get_edits().clone();
// 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;
if !self.active && selected.is_none() { if !self.active && selected.is_none() {
@ -93,10 +92,10 @@ impl Plugin for RoadEditor {
} }
} }
// TODO Pretty sure control map needs to recalculate based on the new turns // TODO Pretty sure control layer needs to recalculate based on the new turns
let old_type = map.get_l(id).lane_type; let old_type = map.get_l(id).lane_type;
map.edit_lane_type(id, new_type); map.edit_lane_type(id, new_type);
draw_map.edit_lane_type(id, map, control_map); draw_map.edit_lane_type(id, map);
sim.edit_lane_type(id, old_type, map); sim.edit_lane_type(id, old_type, map);
// Add turns back // Add turns back

View File

@ -81,10 +81,10 @@ impl Plugin for SimController {
self.last_step = Some(Instant::now()); self.last_step = Some(Instant::now());
self.benchmark = Some(primary.sim.start_benchmark()); self.benchmark = Some(primary.sim.start_benchmark());
} else if input.unimportant_key_pressed(Key::M, SIM, "run one step") { } else if input.unimportant_key_pressed(Key::M, SIM, "run one step") {
primary.sim.step(&primary.map, &primary.control_map); primary.sim.step(&primary.map);
primary.recalculate_current_selection = true; primary.recalculate_current_selection = true;
if let Some((s, _)) = secondary { if let Some((s, _)) = secondary {
s.sim.step(&s.map, &s.control_map); s.sim.step(&s.map);
} }
} }
} }
@ -118,10 +118,10 @@ impl Plugin for SimController {
// TODO https://gafferongames.com/post/fix_your_timestep/ // TODO https://gafferongames.com/post/fix_your_timestep/
let dt_s = elapsed_seconds(tick); let dt_s = elapsed_seconds(tick);
if dt_s >= TIMESTEP.value_unsafe / self.desired_speed { if dt_s >= TIMESTEP.value_unsafe / self.desired_speed {
primary.sim.step(&primary.map, &primary.control_map); primary.sim.step(&primary.map);
primary.recalculate_current_selection = true; primary.recalculate_current_selection = true;
if let Some((s, _)) = secondary { if let Some((s, _)) = secondary {
s.sim.step(&s.map, &s.control_map); s.sim.step(&s.map);
} }
self.last_step = Some(Instant::now()); self.last_step = Some(Instant::now());
} }

View File

@ -1,8 +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 control::TurnPriority;
use ezgui::Color; use ezgui::Color;
use map_model::IntersectionID; use map_model::{IntersectionID, TurnPriority};
use objects::{Ctx, ID}; use objects::{Ctx, ID};
use piston::input::Key; use piston::input::Key;
use plugins::{Plugin, PluginCtx}; use plugins::{Plugin, PluginCtx};
@ -29,14 +28,13 @@ impl StopSignEditor {
impl Plugin for StopSignEditor { impl Plugin for StopSignEditor {
fn event(&mut self, ctx: PluginCtx) -> bool { fn event(&mut self, ctx: PluginCtx) -> bool {
let input = ctx.input; let input = ctx.input;
let map = &ctx.primary.map; let map = &mut ctx.primary.map;
let control_map = &mut ctx.primary.control_map;
let selected = ctx.primary.current_selection; let selected = ctx.primary.current_selection;
if *self == StopSignEditor::Inactive { if *self == StopSignEditor::Inactive {
match selected { match selected {
Some(ID::Intersection(id)) => { Some(ID::Intersection(id)) => {
if control_map.stop_signs.contains_key(&id) if map.maybe_get_stop_sign(id).is_some()
&& input.key_pressed(Key::E, &format!("edit stop signs for {}", id)) && input.key_pressed(Key::E, &format!("edit stop signs for {}", id))
{ {
*self = StopSignEditor::Active(id); *self = StopSignEditor::Active(id);
@ -55,7 +53,8 @@ impl Plugin for StopSignEditor {
new_state = Some(StopSignEditor::Inactive); new_state = Some(StopSignEditor::Inactive);
} else if let Some(ID::Turn(id)) = selected { } else if let Some(ID::Turn(id)) = selected {
if id.parent == *i { if id.parent == *i {
let sign = &mut control_map.stop_signs.get_mut(i).unwrap(); let mut sign = map.get_stop_sign(*i).clone();
match sign.get_priority(id) { match sign.get_priority(id) {
TurnPriority::Priority => { TurnPriority::Priority => {
if input.key_pressed(Key::D2, "make this turn yield") { if input.key_pressed(Key::D2, "make this turn yield") {
@ -86,6 +85,8 @@ impl Plugin for StopSignEditor {
} }
} }
}; };
map.edit_stop_sign(sign);
} }
} }
} }
@ -106,7 +107,7 @@ impl Plugin for StopSignEditor {
if t.parent != *i { if t.parent != *i {
return Some(ctx.cs.get("irrelevant turn", Color::grey(0.3))); return Some(ctx.cs.get("irrelevant turn", Color::grey(0.3)));
} }
match ctx.control_map.stop_signs[i].get_priority(t) { match ctx.map.get_stop_sign(*i).get_priority(t) {
TurnPriority::Priority => { TurnPriority::Priority => {
Some(ctx.cs.get("priority stop sign turn", Color::GREEN)) Some(ctx.cs.get("priority stop sign turn", Color::GREEN))
} }

View File

@ -2,9 +2,8 @@
// TODO how to edit cycle time? // TODO how to edit cycle time?
use control::TurnPriority;
use ezgui::Color; use ezgui::Color;
use map_model::IntersectionID; use map_model::{IntersectionID, TurnPriority};
use objects::{Ctx, ID}; use objects::{Ctx, ID};
use piston::input::Key; use piston::input::Key;
use plugins::{Plugin, PluginCtx}; use plugins::{Plugin, PluginCtx};
@ -37,14 +36,13 @@ impl TrafficSignalEditor {
impl Plugin for TrafficSignalEditor { impl Plugin for TrafficSignalEditor {
fn event(&mut self, ctx: PluginCtx) -> bool { fn event(&mut self, ctx: PluginCtx) -> bool {
let input = ctx.input; let input = ctx.input;
let map = &ctx.primary.map; let map = &mut ctx.primary.map;
let control_map = &mut ctx.primary.control_map;
let selected = ctx.primary.current_selection; let selected = ctx.primary.current_selection;
if *self == TrafficSignalEditor::Inactive { if *self == TrafficSignalEditor::Inactive {
match selected { match selected {
Some(ID::Intersection(id)) => { Some(ID::Intersection(id)) => {
if control_map.traffic_signals.contains_key(&id) if map.maybe_get_traffic_signal(id).is_some()
&& input.key_pressed(Key::E, &format!("edit traffic signal for {}", id)) && input.key_pressed(Key::E, &format!("edit traffic signal for {}", id))
{ {
*self = TrafficSignalEditor::Active { *self = TrafficSignalEditor::Active {
@ -67,7 +65,7 @@ impl Plugin for TrafficSignalEditor {
} else { } else {
// Change cycles // Change cycles
{ {
let cycles = &control_map.traffic_signals[&i].cycles; let cycles = &map.get_traffic_signal(*i).cycles;
if let Some(n) = input.number_chosen( if let Some(n) = input.number_chosen(
cycles.len(), cycles.len(),
&format!( &format!(
@ -84,28 +82,33 @@ impl Plugin for TrafficSignalEditor {
// Change turns // Change turns
if let Some(ID::Turn(id)) = selected { if let Some(ID::Turn(id)) = selected {
if id.parent == *i { if id.parent == *i {
let cycle = let mut signal = map.get_traffic_signal(*i).clone();
&mut control_map.traffic_signals.get_mut(&i).unwrap().cycles {
[*current_cycle]; let cycle = &mut signal.cycles[*current_cycle];
if cycle.get_priority(id) == TurnPriority::Priority { if cycle.get_priority(id) == TurnPriority::Priority {
if input if input.key_pressed(
.key_pressed(Key::Backspace, "remove this turn from this cycle") Key::Backspace,
{ "remove this turn from this cycle",
cycle.remove(id); ) {
} cycle.remove(id);
} else if cycle.could_be_priority_turn(id, map) { }
if input.key_pressed( } else if cycle.could_be_priority_turn(id, map) {
Key::Space, if input.key_pressed(
"add this turn to this cycle as priority", Key::Space,
) { "add this turn to this cycle as priority",
cycle.add(id, TurnPriority::Priority); ) {
} cycle.add(id, TurnPriority::Priority);
} else if cycle.get_priority(id) == TurnPriority::Stop { }
if input.key_pressed(Key::Y, "add this turn to this cycle as yield") } else if cycle.get_priority(id) == TurnPriority::Stop {
{ if input
cycle.add(id, TurnPriority::Yield); .key_pressed(Key::Y, "add this turn to this cycle as yield")
{
cycle.add(id, TurnPriority::Yield);
}
} }
} }
map.edit_traffic_signal(signal);
} }
} }
} }
@ -128,7 +131,7 @@ impl Plugin for TrafficSignalEditor {
return Some(ctx.cs.get("irrelevant turn", Color::grey(0.3))); return Some(ctx.cs.get("irrelevant turn", Color::grey(0.3)));
} }
let cycle = &ctx.control_map.traffic_signals[&i].cycles[*current_cycle]; let cycle = &ctx.map.get_traffic_signal(*i).cycles[*current_cycle];
// TODO maybe something to indicate unused in any cycle so far // TODO maybe something to indicate unused in any cycle so far
let could_be_priority = cycle.could_be_priority_turn(t, ctx.map); let could_be_priority = cycle.could_be_priority_turn(t, ctx.map);

View File

@ -1,8 +1,9 @@
use control::{ControlTrafficSignal, TurnPriority};
use dimensioned::si; use dimensioned::si;
use ezgui::{Color, GfxCtx}; use ezgui::{Color, GfxCtx};
use geom::Circle; use geom::Circle;
use map_model::{IntersectionID, LaneID, TurnType, LANE_THICKNESS}; use map_model::{
ControlTrafficSignal, IntersectionID, LaneID, TurnPriority, TurnType, LANE_THICKNESS,
};
use objects::{Ctx, ID}; use objects::{Ctx, ID};
use piston::input::Key; use piston::input::Key;
use plugins::{Plugin, PluginCtx}; use plugins::{Plugin, PluginCtx};
@ -92,7 +93,7 @@ impl Plugin for TurnCyclerState {
//draw_map.get_l(id).draw_debug(g, cs, map.get_l(id)); //draw_map.get_l(id).draw_debug(g, cs, map.get_l(id));
} }
TurnCyclerState::Intersection(id) => { TurnCyclerState::Intersection(id) => {
if let Some(signal) = ctx.control_map.traffic_signals.get(&id) { if let Some(signal) = ctx.map.maybe_get_traffic_signal(*id) {
draw_traffic_signal(signal, g, ctx); draw_traffic_signal(signal, g, ctx);
} }
} }

View File

@ -84,9 +84,9 @@ impl Renderable for DrawIntersection {
return ctx.cs.get("border intersection", Color::rgb(50, 205, 50)); return ctx.cs.get("border intersection", Color::rgb(50, 205, 50));
} }
let changed = if let Some(s) = ctx.control_map.traffic_signals.get(&self.id) { let changed = if let Some(s) = ctx.map.maybe_get_traffic_signal(self.id) {
s.is_changed() s.is_changed()
} else if let Some(s) = ctx.control_map.stop_signs.get(&self.id) { } else if let Some(s) = ctx.map.maybe_get_stop_sign(self.id) {
s.is_changed() s.is_changed()
} else { } else {
false false

View File

@ -1,7 +1,6 @@
// 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 colors::ColorScheme; use colors::ColorScheme;
use control::ControlMap;
use dimensioned::si; use dimensioned::si;
use ezgui::{Color, GfxCtx, Text}; use ezgui::{Color, GfxCtx, Text};
use geom::{Bounds, Circle, Line, Polygon, Pt2D}; use geom::{Bounds, Circle, Line, Polygon, Pt2D};
@ -52,7 +51,7 @@ pub struct DrawLane {
} }
impl DrawLane { impl DrawLane {
pub fn new(lane: &Lane, map: &Map, control_map: &ControlMap) -> DrawLane { pub fn new(lane: &Lane, map: &Map) -> DrawLane {
let road = map.get_r(lane.parent); let road = map.get_r(lane.parent);
let polygon = lane.lane_center_pts.make_polygons_blindly(LANE_THICKNESS); let polygon = lane.lane_center_pts.make_polygons_blindly(LANE_THICKNESS);
@ -86,7 +85,7 @@ impl DrawLane {
if lane.is_driving() if lane.is_driving()
&& map.get_i(lane.dst_i).intersection_type == IntersectionType::StopSign && map.get_i(lane.dst_i).intersection_type == IntersectionType::StopSign
{ {
if let Some(m) = calculate_stop_sign_line(lane, control_map) { if let Some(m) = calculate_stop_sign_line(lane, map) {
markings.push(m); markings.push(m);
} }
} }
@ -269,8 +268,8 @@ fn calculate_driving_lines(lane: &Lane, parent: &Road) -> Option<Marking> {
}) })
} }
fn calculate_stop_sign_line(lane: &Lane, control_map: &ControlMap) -> Option<Marking> { fn calculate_stop_sign_line(lane: &Lane, map: &Map) -> Option<Marking> {
if control_map.stop_signs[&lane.dst_i].is_priority_lane(lane.id) { if map.get_stop_sign(lane.dst_i).is_priority_lane(lane.id) {
return None; return None;
} }

View File

@ -2,7 +2,6 @@
use aabb_quadtree::QuadTree; use aabb_quadtree::QuadTree;
use abstutil::Timer; use abstutil::Timer;
use control::ControlMap;
use geom::Bounds; use geom::Bounds;
use kml::ExtraShape; use kml::ExtraShape;
use map_model::{ use map_model::{
@ -40,17 +39,12 @@ pub struct DrawMap {
} }
impl DrawMap { impl DrawMap {
pub fn new( pub fn new(map: &Map, raw_extra_shapes: Vec<ExtraShape>, timer: &mut Timer) -> DrawMap {
map: &Map,
control_map: &ControlMap,
raw_extra_shapes: Vec<ExtraShape>,
timer: &mut Timer,
) -> DrawMap {
let mut lanes: Vec<DrawLane> = Vec::new(); let mut lanes: Vec<DrawLane> = Vec::new();
timer.start_iter("make DrawLanes", map.all_lanes().len()); timer.start_iter("make DrawLanes", map.all_lanes().len());
for l in map.all_lanes() { for l in map.all_lanes() {
timer.next(); timer.next();
lanes.push(DrawLane::new(l, map, control_map)); lanes.push(DrawLane::new(l, map));
} }
let mut turn_to_lane_offset: HashMap<TurnID, usize> = HashMap::new(); let mut turn_to_lane_offset: HashMap<TurnID, usize> = HashMap::new();
@ -172,9 +166,9 @@ impl DrawMap {
} }
} }
pub fn edit_lane_type(&mut self, id: LaneID, map: &Map, control_map: &ControlMap) { pub fn edit_lane_type(&mut self, id: LaneID, map: &Map) {
// No need to edit the quadtree; the bbox shouldn't depend on lane type. // No need to edit the quadtree; the bbox shouldn't depend on lane type.
self.lanes[id.0] = DrawLane::new(map.get_l(id), map, control_map); self.lanes[id.0] = DrawLane::new(map.get_l(id), map);
} }
pub fn edit_remove_turn(&mut self, id: TurnID) { pub fn edit_remove_turn(&mut self, id: TurnID) {

View File

@ -4,7 +4,6 @@
use abstutil; use abstutil;
use colors::ColorScheme; use colors::ColorScheme;
use control::ControlMap;
//use cpuprofiler; //use cpuprofiler;
use ezgui::{Canvas, Color, GfxCtx, Text, UserInput, BOTTOM_LEFT, GUI}; use ezgui::{Canvas, Color, GfxCtx, Text, UserInput, BOTTOM_LEFT, GUI};
use kml; use kml;
@ -97,7 +96,6 @@ impl GUI for UI {
Ctx { Ctx {
cs: &mut self.cs.borrow_mut(), cs: &mut self.cs.borrow_mut(),
map: &self.primary.map, map: &self.primary.map,
control_map: &self.primary.control_map,
draw_map: &self.primary.draw_map, draw_map: &self.primary.draw_map,
canvas: &self.canvas, canvas: &self.canvas,
sim: &self.primary.sim, sim: &self.primary.sim,
@ -116,7 +114,6 @@ impl GUI for UI {
Ctx { Ctx {
cs: &mut self.cs.borrow_mut(), cs: &mut self.cs.borrow_mut(),
map: &self.primary.map, map: &self.primary.map,
control_map: &self.primary.control_map,
draw_map: &self.primary.draw_map, draw_map: &self.primary.draw_map,
canvas: &self.canvas, canvas: &self.canvas,
sim: &self.primary.sim, sim: &self.primary.sim,
@ -130,7 +127,6 @@ impl GUI for UI {
Ctx { Ctx {
cs: &mut self.cs.borrow_mut(), cs: &mut self.cs.borrow_mut(),
map: &self.primary.map, map: &self.primary.map,
control_map: &self.primary.control_map,
draw_map: &self.primary.draw_map, draw_map: &self.primary.draw_map,
canvas: &self.canvas, canvas: &self.canvas,
sim: &self.primary.sim, sim: &self.primary.sim,
@ -144,7 +140,6 @@ impl GUI for UI {
Ctx { Ctx {
cs: &mut self.cs.borrow_mut(), cs: &mut self.cs.borrow_mut(),
map: &self.primary.map, map: &self.primary.map,
control_map: &self.primary.control_map,
draw_map: &self.primary.draw_map, draw_map: &self.primary.draw_map,
canvas: &self.canvas, canvas: &self.canvas,
sim: &self.primary.sim, sim: &self.primary.sim,
@ -161,7 +156,6 @@ impl GUI for UI {
pub struct PerMapUI { pub struct PerMapUI {
pub map: Map, pub map: Map,
pub draw_map: DrawMap, pub draw_map: DrawMap,
pub control_map: ControlMap,
pub sim: Sim, pub sim: Sim,
pub current_selection: Option<ID>, pub current_selection: Option<ID>,
@ -204,8 +198,7 @@ impl PerMapUI {
pub fn new(flags: SimFlags, kml: &Option<String>) -> (PerMapUI, PluginsPerMap) { pub fn new(flags: SimFlags, kml: &Option<String>) -> (PerMapUI, PluginsPerMap) {
let mut timer = abstutil::Timer::new("setup PerMapUI"); let mut timer = abstutil::Timer::new("setup PerMapUI");
let (map, control_map, sim) = let (map, sim) = sim::load(flags.clone(), Some(Tick::from_seconds(30)), &mut timer);
sim::load(flags.clone(), Some(Tick::from_seconds(30)), &mut timer);
let extra_shapes: Vec<kml::ExtraShape> = if let Some(path) = kml { let extra_shapes: Vec<kml::ExtraShape> = if let Some(path) = kml {
if path.ends_with(".kml") { if path.ends_with(".kml") {
kml::load(&path, &map.get_gps_bounds(), &mut timer) kml::load(&path, &map.get_gps_bounds(), &mut timer)
@ -221,7 +214,7 @@ impl PerMapUI {
}; };
timer.start("draw_map"); timer.start("draw_map");
let draw_map = DrawMap::new(&map, &control_map, extra_shapes, &mut timer); let draw_map = DrawMap::new(&map, extra_shapes, &mut timer);
timer.stop("draw_map"); timer.stop("draw_map");
let steepness_viz = plugins::steep::SteepnessVisualizer::new(&map); let steepness_viz = plugins::steep::SteepnessVisualizer::new(&map);
@ -233,7 +226,6 @@ impl PerMapUI {
let state = PerMapUI { let state = PerMapUI {
map, map,
draw_map, draw_map,
control_map,
sim, sim,
current_selection: None, current_selection: None,
@ -427,7 +419,6 @@ impl UI {
let ctx = Ctx { let ctx = Ctx {
cs: &mut self.cs.borrow_mut(), cs: &mut self.cs.borrow_mut(),
map: &self.primary.map, map: &self.primary.map,
control_map: &self.primary.control_map,
draw_map: &self.primary.draw_map, draw_map: &self.primary.draw_map,
canvas: &self.canvas, canvas: &self.canvas,
sim: &self.primary.sim, sim: &self.primary.sim,

View File

@ -5,7 +5,6 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
[dependencies] [dependencies]
abstutil = { path = "../abstutil" } abstutil = { path = "../abstutil" }
control = { path = "../control" }
cpuprofiler = "0.0.3" cpuprofiler = "0.0.3"
log = "0.4.5" log = "0.4.5"
map_model = { path = "../map_model" } map_model = { path = "../map_model" }

View File

@ -1,7 +1,6 @@
// 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
extern crate abstutil; extern crate abstutil;
extern crate control;
extern crate cpuprofiler; extern crate cpuprofiler;
extern crate log; extern crate log;
extern crate map_model; extern crate map_model;
@ -35,7 +34,7 @@ fn main() {
// TODO not the ideal way to distinguish what thing we loaded // TODO not the ideal way to distinguish what thing we loaded
let load = flags.sim_flags.load.clone(); let load = flags.sim_flags.load.clone();
let mut timer = Timer::new("setup headless"); let mut timer = Timer::new("setup headless");
let (map, control_map, mut sim) = sim::load( let (map, mut sim) = sim::load(
flags.sim_flags, flags.sim_flags,
Some(sim::Tick::from_seconds(30)), Some(sim::Tick::from_seconds(30)),
&mut timer, &mut timer,
@ -63,7 +62,6 @@ fn main() {
.unwrap(); .unwrap();
sim.run_until_done( sim.run_until_done(
&map, &map,
&control_map,
Box::new(move |sim| { Box::new(move |sim| {
if Some(sim.time) == save_at { if Some(sim.time) == save_at {
sim.save(); sim.save();

View File

@ -1,29 +1,44 @@
use abstutil::{deserialize_btreemap, serialize_btreemap}; use abstutil;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use {Lane, LaneType, Road, RoadID}; use {ControlStopSign, ControlTrafficSignal, IntersectionID, Lane, LaneType, Road, RoadID};
// 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?
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RoadEdits { pub struct MapEdits {
pub edits_name: String, pub edits_name: String,
pub map_name: String,
// TODO detect when we wind up editing back to the original thing // TODO detect when we wind up editing back to the original thing
#[serde(
serialize_with = "serialize_btreemap",
deserialize_with = "deserialize_btreemap"
)]
pub(crate) roads: BTreeMap<RoadID, RoadEdit>, pub(crate) roads: BTreeMap<RoadID, RoadEdit>,
pub(crate) stop_signs: BTreeMap<IntersectionID, ControlStopSign>,
pub(crate) traffic_signals: BTreeMap<IntersectionID, ControlTrafficSignal>,
} }
impl RoadEdits { impl MapEdits {
pub fn new() -> RoadEdits { pub fn new(map_name: &str) -> MapEdits {
RoadEdits { MapEdits {
// Something has to fill this out later // Something has to fill this out later
edits_name: "no_edits".to_string(), edits_name: "no_edits".to_string(),
map_name: map_name.to_string(),
roads: BTreeMap::new(), roads: BTreeMap::new(),
stop_signs: BTreeMap::new(),
traffic_signals: BTreeMap::new(),
} }
} }
pub fn describe(&self) -> String {
format!(
"map edits \"{}\" ({} roads, {} stop signs, {} traffic signals",
self.edits_name,
self.roads.len(),
self.stop_signs.len(),
self.traffic_signals.len()
)
}
pub fn save(&self) {
abstutil::save_object("edits", &self.map_name, &self.edits_name, self);
}
pub fn change_lane_type( pub fn change_lane_type(
&mut self, &mut self,
reason: EditReason, reason: EditReason,
@ -45,10 +60,6 @@ impl RoadEdits {
} }
false false
} }
pub fn len(&self) -> usize {
self.roads.len()
}
} }
#[derive(Serialize, Deserialize, Debug, Clone, Copy)] #[derive(Serialize, Deserialize, Debug, Clone, Copy)]

View File

@ -30,6 +30,8 @@ mod parcel;
mod pathfind; mod pathfind;
pub mod raw_data; pub mod raw_data;
mod road; mod road;
mod stop_signs;
mod traffic_signals;
mod traversable; mod traversable;
mod turn; mod turn;
@ -37,7 +39,7 @@ use abstutil::Cloneable;
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, BusRouteID, BusStop, BusStopID}; pub use bus_stop::{BusRoute, BusRouteID, BusStop, BusStopID};
pub use edits::{EditReason, RoadEdits}; pub use edits::{EditReason, MapEdits};
pub use find_closest::FindClosest; pub use find_closest::FindClosest;
pub use intersection::{Intersection, IntersectionID, IntersectionType}; pub use intersection::{Intersection, IntersectionID, IntersectionType};
pub use lane::{Lane, LaneID, LaneType, PARKING_SPOT_LENGTH}; pub use lane::{Lane, LaneID, LaneType, PARKING_SPOT_LENGTH};
@ -46,9 +48,12 @@ pub use map::Map;
pub use parcel::{Parcel, ParcelID}; pub use parcel::{Parcel, ParcelID};
pub use pathfind::{Path, PathRequest, PathStep, Pathfinder, Trace}; pub use pathfind::{Path, PathRequest, PathStep, Pathfinder, Trace};
pub use road::{Road, RoadID}; pub use road::{Road, RoadID};
pub use stop_signs::ControlStopSign;
pub use traffic_signals::ControlTrafficSignal;
pub use traversable::{Position, Traversable}; pub use traversable::{Position, Traversable};
pub use turn::{Turn, TurnID, TurnType}; pub use turn::{Turn, TurnID, TurnPriority, TurnType};
pub const LANE_THICKNESS: f64 = 2.5; pub const LANE_THICKNESS: f64 = 2.5;
impl Cloneable for IntersectionID {} impl Cloneable for IntersectionID {}
impl Cloneable for MapEdits {}

View File

@ -1,8 +1,5 @@
use edits::RoadEdits;
use lane::LaneType;
use raw_data;
use road::RoadID;
use std::iter; use std::iter;
use {raw_data, LaneType, MapEdits, RoadID};
// (original direction, reversed direction) // (original direction, reversed direction)
fn get_lanes(r: &raw_data::Road) -> (Vec<LaneType>, Vec<LaneType>) { fn get_lanes(r: &raw_data::Road) -> (Vec<LaneType>, Vec<LaneType>) {
@ -118,7 +115,7 @@ impl LaneSpec {
} }
} }
pub fn get_lane_specs(r: &raw_data::Road, id: RoadID, edits: &RoadEdits) -> Vec<LaneSpec> { pub fn get_lane_specs(r: &raw_data::Road, id: RoadID, edits: &MapEdits) -> 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

@ -2,7 +2,7 @@
use abstutil; use abstutil;
use abstutil::{deserialize_btreemap, serialize_btreemap, Error, Timer}; use abstutil::{deserialize_btreemap, serialize_btreemap, Error, Timer};
use edits::RoadEdits; use edits::MapEdits;
use geom::{Bounds, GPSBounds, HashablePt2D, PolyLine, Pt2D}; use geom::{Bounds, GPSBounds, HashablePt2D, PolyLine, Pt2D};
use make; use make;
use raw_data; use raw_data;
@ -10,9 +10,9 @@ use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::io; use std::io;
use std::path; use std::path;
use { use {
Area, AreaID, Building, BuildingID, BusRoute, BusRouteID, BusStop, BusStopID, Intersection, Area, AreaID, Building, BuildingID, BusRoute, BusRouteID, BusStop, BusStopID, ControlStopSign,
IntersectionID, IntersectionType, Lane, LaneID, LaneType, Parcel, ParcelID, Road, RoadID, Turn, ControlTrafficSignal, Intersection, IntersectionID, IntersectionType, Lane, LaneID, LaneType,
TurnID, LANE_THICKNESS, Parcel, ParcelID, Road, RoadID, Turn, TurnID, LANE_THICKNESS,
}; };
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
@ -35,15 +35,18 @@ pub struct Map {
bus_routes: Vec<BusRoute>, bus_routes: Vec<BusRoute>,
areas: Vec<Area>, areas: Vec<Area>,
stop_signs: BTreeMap<IntersectionID, ControlStopSign>,
traffic_signals: BTreeMap<IntersectionID, ControlTrafficSignal>,
// Note that border nodes belong in neither!
gps_bounds: GPSBounds, gps_bounds: GPSBounds,
bounds: Bounds, bounds: Bounds,
name: String, name: String,
road_edits: RoadEdits, edits: MapEdits,
} }
impl Map { impl Map {
pub fn new(path: &str, road_edits: RoadEdits, timer: &mut Timer) -> Result<Map, io::Error> { pub fn new(path: &str, edits: MapEdits, timer: &mut Timer) -> Result<Map, io::Error> {
let data: raw_data::Map = abstutil::read_binary(path, timer)?; let data: raw_data::Map = abstutil::read_binary(path, timer)?;
Ok(Map::create_from_raw( Ok(Map::create_from_raw(
path::Path::new(path) path::Path::new(path)
@ -53,7 +56,7 @@ impl Map {
.into_string() .into_string()
.unwrap(), .unwrap(),
data, data,
road_edits, edits,
timer, timer,
)) ))
} }
@ -61,7 +64,7 @@ impl Map {
pub fn create_from_raw( pub fn create_from_raw(
name: String, name: String,
mut data: raw_data::Map, mut data: raw_data::Map,
road_edits: RoadEdits, edits: MapEdits,
timer: &mut Timer, timer: &mut Timer,
) -> Map { ) -> Map {
timer.start("raw_map to Map"); timer.start("raw_map to Map");
@ -75,7 +78,7 @@ impl Map {
let mut m = Map { let mut m = Map {
name, name,
road_edits, edits,
gps_bounds: gps_bounds.clone(), gps_bounds: gps_bounds.clone(),
bounds: bounds.clone(), bounds: bounds.clone(),
roads: Vec::new(), roads: Vec::new(),
@ -87,6 +90,8 @@ impl Map {
bus_stops: BTreeMap::new(), bus_stops: BTreeMap::new(),
bus_routes: Vec::new(), bus_routes: Vec::new(),
areas: Vec::new(), areas: Vec::new(),
stop_signs: BTreeMap::new(),
traffic_signals: BTreeMap::new(),
}; };
let mut pt_to_intersection: HashMap<HashablePt2D, IntersectionID> = HashMap::new(); let mut pt_to_intersection: HashMap<HashablePt2D, IntersectionID> = HashMap::new();
@ -148,7 +153,7 @@ impl Map {
}); });
// 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, &m.road_edits) { for lane in make::get_lane_specs(r, road_id, &m.edits) {
let id = LaneID(counter); let id = LaneID(counter);
counter += 1; counter += 1;
@ -243,6 +248,29 @@ impl Map {
m.intersections[t.id.parent.0].turns.push(t.id); m.intersections[t.id.parent.0].turns.push(t.id);
} }
let mut stop_signs: BTreeMap<IntersectionID, ControlStopSign> = BTreeMap::new();
let mut traffic_signals: BTreeMap<IntersectionID, ControlTrafficSignal> = BTreeMap::new();
for i in &m.intersections {
match i.intersection_type {
IntersectionType::StopSign => {
stop_signs.insert(i.id, ControlStopSign::new(&m, i.id));
}
IntersectionType::TrafficSignal => {
traffic_signals.insert(i.id, ControlTrafficSignal::new(&m, i.id));
}
IntersectionType::Border => {}
};
}
// Override with edits
for (i, ss) in &m.edits.stop_signs {
stop_signs.insert(*i, ss.clone());
}
for (i, ts) in &m.edits.traffic_signals {
traffic_signals.insert(*i, ts.clone());
}
m.stop_signs = stop_signs;
m.traffic_signals = traffic_signals;
make::make_all_buildings( make::make_all_buildings(
&mut m.buildings, &mut m.buildings,
&data.buildings, &data.buildings,
@ -286,10 +314,11 @@ impl Map {
m m
} }
// The caller has to clone get_road_edits(), mutate, actualize the changes, then store them // The caller has to clone get_edits(), mutate, actualize the changes, then store them
// here. // here.
pub fn store_new_edits(&mut self, edits: RoadEdits) { // TODO Only road editor calls this. Stop sign / traffic signal editor have a nicer pattern.
self.road_edits = edits; pub fn store_new_edits(&mut self, edits: MapEdits) {
self.edits = edits;
} }
pub fn edit_lane_type(&mut self, lane: LaneID, new_type: LaneType) { pub fn edit_lane_type(&mut self, lane: LaneID, new_type: LaneType) {
@ -313,6 +342,16 @@ impl Map {
} }
} }
pub fn edit_stop_sign(&mut self, sign: ControlStopSign) {
self.edits.stop_signs.insert(sign.id, sign.clone());
self.stop_signs.insert(sign.id, sign);
}
pub fn edit_traffic_signal(&mut self, signal: ControlTrafficSignal) {
self.edits.traffic_signals.insert(signal.id, signal.clone());
self.traffic_signals.insert(signal.id, signal);
}
pub fn all_roads(&self) -> &Vec<Road> { pub fn all_roads(&self) -> &Vec<Road> {
&self.roads &self.roads
} }
@ -373,6 +412,14 @@ impl Map {
self.bus_stops.get(&id) self.bus_stops.get(&id)
} }
pub fn maybe_get_stop_sign(&self, id: IntersectionID) -> Option<&ControlStopSign> {
self.stop_signs.get(&id)
}
pub fn maybe_get_traffic_signal(&self, id: IntersectionID) -> Option<&ControlTrafficSignal> {
self.traffic_signals.get(&id)
}
pub fn get_r(&self, id: RoadID) -> &Road { pub fn get_r(&self, id: RoadID) -> &Road {
&self.roads[id.0] &self.roads[id.0]
} }
@ -401,6 +448,14 @@ impl Map {
&self.areas[id.0] &self.areas[id.0]
} }
pub fn get_stop_sign(&self, id: IntersectionID) -> &ControlStopSign {
&self.stop_signs[&id]
}
pub fn get_traffic_signal(&self, id: IntersectionID) -> &ControlTrafficSignal {
&self.traffic_signals[&id]
}
// All these helpers should take IDs and return objects. // All these helpers should take IDs and return objects.
pub fn get_source_intersection(&self, l: LaneID) -> &Intersection { pub fn get_source_intersection(&self, l: LaneID) -> &Intersection {
@ -483,8 +538,8 @@ impl Map {
&self.name &self.name
} }
pub fn get_road_edits(&self) -> &RoadEdits { pub fn get_edits(&self) -> &MapEdits {
&self.road_edits &self.edits
} }
pub fn all_bus_stops(&self) -> &BTreeMap<BusStopID, BusStop> { pub fn all_bus_stops(&self) -> &BTreeMap<BusStopID, BusStop> {
@ -543,10 +598,7 @@ impl Map {
} }
pub fn save(&self) { pub fn save(&self) {
let path = format!( let path = format!("../data/maps/{}_{}.abst", self.name, self.edits.edits_name);
"../data/maps/{}_{}.abst",
self.name, self.road_edits.edits_name
);
info!("Saving {}...", path); info!("Saving {}...", path);
abstutil::write_binary(&path, self).expect(&format!("Saving {} failed", path)); abstutil::write_binary(&path, self).expect(&format!("Saving {} failed", path));
info!("Saved {}", path); info!("Saved {}", path);

View File

@ -1,13 +1,10 @@
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
use abstutil::{deserialize_btreemap, serialize_btreemap, Error}; use abstutil::{deserialize_btreemap, serialize_btreemap, Error};
use map_model::{IntersectionID, LaneID, Map, TurnID, TurnType};
use std::collections::{BTreeMap, HashMap, HashSet}; use std::collections::{BTreeMap, HashMap, HashSet};
use TurnPriority; use {IntersectionID, LaneID, Map, TurnID, TurnPriority, TurnType};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ControlStopSign { pub struct ControlStopSign {
intersection: IntersectionID, pub id: IntersectionID,
#[serde( #[serde(
serialize_with = "serialize_btreemap", serialize_with = "serialize_btreemap",
deserialize_with = "deserialize_btreemap" deserialize_with = "deserialize_btreemap"
@ -18,9 +15,9 @@ pub struct ControlStopSign {
} }
impl ControlStopSign { impl ControlStopSign {
pub fn new(map: &Map, intersection: IntersectionID) -> ControlStopSign { pub fn new(map: &Map, id: IntersectionID) -> ControlStopSign {
let ss = smart_assignment(map, intersection); let ss = smart_assignment(map, id);
ss.validate(map, intersection).unwrap(); ss.validate(map).unwrap();
ss ss
} }
@ -57,9 +54,9 @@ impl ControlStopSign {
.is_some() .is_some()
} }
fn validate(&self, map: &Map, intersection: IntersectionID) -> Result<(), Error> { fn validate(&self, map: &Map) -> Result<(), Error> {
// Does the assignment cover the correct set of turns? // Does the assignment cover the correct set of turns?
let all_turns = &map.get_i(intersection).turns; let all_turns = &map.get_i(self.id).turns;
assert_eq!(self.turns.len(), all_turns.len()); assert_eq!(self.turns.len(), all_turns.len());
for t in all_turns { for t in all_turns {
assert!(self.turns.contains_key(t)); assert!(self.turns.contains_key(t));
@ -91,9 +88,9 @@ impl ControlStopSign {
} }
} }
fn smart_assignment(map: &Map, intersection: IntersectionID) -> ControlStopSign { fn smart_assignment(map: &Map, id: IntersectionID) -> ControlStopSign {
if map.get_i(intersection).roads.len() <= 2 { if map.get_i(id).roads.len() <= 2 {
return for_degenerate_and_deadend(map, intersection); return for_degenerate_and_deadend(map, id);
} }
// Higher numbers are higher rank roads // Higher numbers are higher rank roads
@ -102,10 +99,10 @@ fn smart_assignment(map: &Map, intersection: IntersectionID) -> ControlStopSign
let mut highest_rank = 0; let mut highest_rank = 0;
// TODO should just be incoming, but because of weirdness with sidewalks... // TODO should just be incoming, but because of weirdness with sidewalks...
for l in map for l in map
.get_i(intersection) .get_i(id)
.incoming_lanes .incoming_lanes
.iter() .iter()
.chain(map.get_i(intersection).outgoing_lanes.iter()) .chain(map.get_i(id).outgoing_lanes.iter())
{ {
let r = map.get_parent(*l); let r = map.get_parent(*l);
let rank = if let Some(highway) = r.osm_tags.get("highway") { let rank = if let Some(highway) = r.osm_tags.get("highway") {
@ -141,15 +138,15 @@ fn smart_assignment(map: &Map, intersection: IntersectionID) -> ControlStopSign
ranks.insert(rank); ranks.insert(rank);
} }
if ranks.len() == 1 { if ranks.len() == 1 {
return all_way_stop(map, intersection); return all_way_stop(map, id);
} }
let mut ss = ControlStopSign { let mut ss = ControlStopSign {
intersection, id,
turns: BTreeMap::new(), turns: BTreeMap::new(),
changed: false, changed: false,
}; };
for t in &map.get_i(intersection).turns { for t in &map.get_i(id).turns {
if rank_per_incoming_lane[&t.src] == highest_rank { if rank_per_incoming_lane[&t.src] == highest_rank {
// If it's the highest rank road, make the straight and right turns priority (if // If it's the highest rank road, make the straight and right turns priority (if
// possible) and other turns yield. // possible) and other turns yield.
@ -169,25 +166,25 @@ fn smart_assignment(map: &Map, intersection: IntersectionID) -> ControlStopSign
ss ss
} }
fn all_way_stop(map: &Map, intersection: IntersectionID) -> ControlStopSign { fn all_way_stop(map: &Map, id: IntersectionID) -> ControlStopSign {
let mut ss = ControlStopSign { let mut ss = ControlStopSign {
intersection, id,
turns: BTreeMap::new(), turns: BTreeMap::new(),
changed: false, changed: false,
}; };
for t in &map.get_i(intersection).turns { for t in &map.get_i(id).turns {
ss.turns.insert(*t, TurnPriority::Stop); ss.turns.insert(*t, TurnPriority::Stop);
} }
ss ss
} }
fn for_degenerate_and_deadend(map: &Map, i: IntersectionID) -> ControlStopSign { fn for_degenerate_and_deadend(map: &Map, id: IntersectionID) -> ControlStopSign {
let mut ss = ControlStopSign { let mut ss = ControlStopSign {
intersection: i, id,
turns: BTreeMap::new(), turns: BTreeMap::new(),
changed: false, changed: false,
}; };
for t in &map.get_i(i).turns { for t in &map.get_i(id).turns {
// Only the crosswalks should conflict with other turns. // Only the crosswalks should conflict with other turns.
let priority = match map.get_t(*t).turn_type { let priority = match map.get_t(*t).turn_type {
TurnType::Crosswalk => TurnPriority::Stop, TurnType::Crosswalk => TurnPriority::Stop,
@ -199,9 +196,9 @@ fn for_degenerate_and_deadend(map: &Map, i: IntersectionID) -> ControlStopSign {
// Due to a few observed issues (multiple driving lanes road (a temporary issue) and bad // Due to a few observed issues (multiple driving lanes road (a temporary issue) and bad
// intersection geometry), sometimes more turns conflict than really should. For now, just // intersection geometry), sometimes more turns conflict than really should. For now, just
// detect and fallback to an all-way stop. // detect and fallback to an all-way stop.
if let Err(err) = ss.validate(map, i) { if let Err(err) = ss.validate(map) {
warn!("Giving up on for_degenerate_and_deadend({}): {}", i, err); warn!("Giving up on for_degenerate_and_deadend({}): {}", id, err);
return all_way_stop(map, i); return all_way_stop(map, id);
} }
ss ss

View File

@ -1,8 +1,7 @@
use dimensioned::si; use dimensioned::si;
use map_model::{IntersectionID, Map, TurnID};
use std; use std;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use TurnPriority; use {IntersectionID, Map, TurnID, TurnPriority};
const CYCLE_DURATION: si::Second<f64> = si::Second { const CYCLE_DURATION: si::Second<f64> = si::Second {
value_unsafe: 15.0, value_unsafe: 15.0,

View File

@ -31,6 +31,18 @@ pub enum TurnType {
Other, Other,
} }
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy, PartialOrd)]
pub enum TurnPriority {
// For stop signs: cars have to stop before doing this turn, and are accepted with the lowest priority.
// For traffic signals: can't do this turn at all.
Stop,
// Cars can do this immediately if there are no previously accepted conflicting turns.
Yield,
// These must be non-conflicting, and cars don't have to stop before doing this turn (unless a
// conflicting Yield has been accepted).
Priority,
}
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct Turn { pub struct Turn {
pub id: TurnID, pub id: TurnID,

View File

@ -19,7 +19,7 @@ fn main() {
"precompute {} with {}", "precompute {} with {}",
flags.load, flags.edits_name flags.load, flags.edits_name
)); ));
let (map, _, _) = sim::load(flags, None, &mut timer); let (map, _) = sim::load(flags, None, &mut timer);
timer.start("save map"); timer.start("save map");
map.save(); map.save();
timer.stop("save map"); timer.stop("save map");

View File

@ -6,7 +6,6 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
[dependencies] [dependencies]
abstutil = { path = "../abstutil" } abstutil = { path = "../abstutil" }
backtrace = "0.3.9" backtrace = "0.3.9"
control = { path = "../control" }
derivative = "1.0.0" derivative = "1.0.0"
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] } dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
geom = { path = "../geom" } geom = { path = "../geom" }

View File

@ -1,5 +1,4 @@
use abstutil::WeightedUsizeChoice; use abstutil::WeightedUsizeChoice;
use control::ControlMap;
use driving::DrivingGoal; use driving::DrivingGoal;
use map_model::{BuildingID, BusRoute, BusRouteID, BusStopID, LaneID, Map, RoadID}; use map_model::{BuildingID, BusRoute, BusRouteID, BusStopID, LaneID, Map, RoadID};
use std::collections::{BTreeSet, VecDeque}; use std::collections::{BTreeSet, VecDeque};
@ -14,11 +13,11 @@ use {
impl Sim { impl Sim {
// TODO share the helpers for spawning specific parking spots and stuff? // TODO share the helpers for spawning specific parking spots and stuff?
pub fn run_until_done(&mut self, map: &Map, control_map: &ControlMap, callback: Box<Fn(&Sim)>) { pub fn run_until_done(&mut self, map: &Map, callback: Box<Fn(&Sim)>) {
let mut benchmark = self.start_benchmark(); let mut benchmark = self.start_benchmark();
loop { loop {
match panic::catch_unwind(panic::AssertUnwindSafe(|| { match panic::catch_unwind(panic::AssertUnwindSafe(|| {
self.step(&map, &control_map); self.step(&map);
})) { })) {
Ok(()) => {} Ok(()) => {}
Err(err) => { Err(err) => {
@ -43,7 +42,6 @@ impl Sim {
pub fn run_until_expectations_met( pub fn run_until_expectations_met(
&mut self, &mut self,
map: &Map, map: &Map,
control_map: &ControlMap,
all_expectations: Vec<Event>, all_expectations: Vec<Event>,
time_limit: Tick, time_limit: Tick,
) { ) {
@ -53,7 +51,7 @@ impl Sim {
if expectations.is_empty() { if expectations.is_empty() {
return; return;
} }
for ev in self.step(&map, &control_map).into_iter() { for ev in self.step(&map).into_iter() {
if ev == *expectations.front().unwrap() { if ev == *expectations.front().unwrap() {
info!("At {}, met expectation {:?}", self.time, ev); info!("At {}, met expectation {:?}", self.time, ev);
expectations.pop_front(); expectations.pop_front();

View File

@ -2,10 +2,9 @@
use abstutil; use abstutil;
use abstutil::{deserialize_btreemap, serialize_btreemap, Error}; use abstutil::{deserialize_btreemap, serialize_btreemap, Error};
use control::{ControlMap, ControlStopSign, TurnPriority};
use dimensioned::si; use dimensioned::si;
use kinematics; use kinematics;
use map_model::{IntersectionID, IntersectionType, Map, TurnID}; use map_model::{ControlStopSign, IntersectionID, IntersectionType, Map, TurnID, TurnPriority};
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use view::WorldView; use view::WorldView;
use {AgentID, CarID, Event, PedestrianID, Tick, Time}; use {AgentID, CarID, Event, PedestrianID, Tick, Time};
@ -95,21 +94,12 @@ impl IntersectionSimState {
} }
} }
pub fn step( pub fn step(&mut self, events: &mut Vec<Event>, time: Tick, map: &Map, view: &WorldView) {
&mut self,
events: &mut Vec<Event>,
time: Tick,
map: &Map,
control_map: &ControlMap,
view: &WorldView,
) {
for i in self.intersections.iter_mut() { for i in self.intersections.iter_mut() {
match i { match i {
IntersectionPolicy::StopSignPolicy(ref mut p) => { IntersectionPolicy::StopSignPolicy(ref mut p) => p.step(events, time, map, view),
p.step(events, time, map, control_map, view)
}
IntersectionPolicy::TrafficSignalPolicy(ref mut p) => { IntersectionPolicy::TrafficSignalPolicy(ref mut p) => {
p.step(events, time, map, control_map, view) p.step(events, time, map, view)
} }
IntersectionPolicy::BorderPolicy => {} IntersectionPolicy::BorderPolicy => {}
} }
@ -142,7 +132,7 @@ impl IntersectionSimState {
} }
} }
pub fn debug(&mut self, id: IntersectionID, control_map: &ControlMap) { pub fn debug(&mut self, id: IntersectionID, map: &Map) {
if let Some(old) = self.debug { if let Some(old) = self.debug {
match self.intersections.get_mut(old.0).unwrap() { match self.intersections.get_mut(old.0).unwrap() {
IntersectionPolicy::StopSignPolicy(ref mut p) => { IntersectionPolicy::StopSignPolicy(ref mut p) => {
@ -159,11 +149,11 @@ impl IntersectionSimState {
match self.intersections.get_mut(id.0).unwrap() { match self.intersections.get_mut(id.0).unwrap() {
IntersectionPolicy::StopSignPolicy(ref mut p) => { IntersectionPolicy::StopSignPolicy(ref mut p) => {
p.debug = true; p.debug = true;
println!("{}", abstutil::to_json(&control_map.stop_signs[&id])); println!("{}", abstutil::to_json(map.get_stop_sign(id)));
} }
IntersectionPolicy::TrafficSignalPolicy(ref mut p) => { IntersectionPolicy::TrafficSignalPolicy(ref mut p) => {
p.debug = true; p.debug = true;
println!("{}", abstutil::to_json(&control_map.traffic_signals[&id])); println!("{}", abstutil::to_json(map.get_traffic_signal(id)));
} }
IntersectionPolicy::BorderPolicy => { IntersectionPolicy::BorderPolicy => {
println!("{} is a border", id); println!("{} is a border", id);
@ -254,15 +244,8 @@ impl StopSign {
}).is_some() }).is_some()
} }
fn step( fn step(&mut self, events: &mut Vec<Event>, time: Tick, map: &Map, view: &WorldView) {
&mut self, let ss = map.get_stop_sign(self.id);
events: &mut Vec<Event>,
time: Tick,
map: &Map,
control_map: &ControlMap,
view: &WorldView,
) {
let ss = &control_map.stop_signs[&self.id];
// If anybody is stopped, promote them. // If anybody is stopped, promote them.
// TODO retain() would rock // TODO retain() would rock
@ -342,15 +325,8 @@ impl TrafficSignal {
} }
} }
fn step( fn step(&mut self, events: &mut Vec<Event>, time: Tick, map: &Map, view: &WorldView) {
&mut self, let signal = map.get_traffic_signal(self.id);
events: &mut Vec<Event>,
time: Tick,
map: &Map,
control_map: &ControlMap,
view: &WorldView,
) {
let signal = &control_map.traffic_signals[&self.id];
let (cycle, _remaining_cycle_time) = let (cycle, _remaining_cycle_time) =
signal.current_cycle_and_remaining_time(time.as_time()); signal.current_cycle_and_remaining_time(time.as_time());

View File

@ -2,7 +2,6 @@
extern crate abstutil; extern crate abstutil;
extern crate backtrace; extern crate backtrace;
extern crate control;
#[macro_use] #[macro_use]
extern crate derivative; extern crate derivative;
extern crate dimensioned; extern crate dimensioned;
@ -58,7 +57,7 @@ pub use events::Event;
pub use instrument::save_backtraces; pub use instrument::save_backtraces;
pub use kinematics::VehicleType; pub use kinematics::VehicleType;
pub use make::{ pub use make::{
load, ABTest, ABTestResults, BorderSpawnOverTime, MapEdits, Neighborhood, NeighborhoodBuilder, load, ABTest, ABTestResults, BorderSpawnOverTime, Neighborhood, NeighborhoodBuilder,
OriginDestination, Scenario, SeedParkedCars, SimFlags, SpawnOverTime, OriginDestination, Scenario, SeedParkedCars, SimFlags, SpawnOverTime,
}; };
use map_model::{BuildingID, LaneID}; use map_model::{BuildingID, LaneID};
@ -162,5 +161,4 @@ impl Cloneable for Neighborhood {}
impl Cloneable for NeighborhoodBuilder {} impl Cloneable for NeighborhoodBuilder {}
impl Cloneable for Scenario {} impl Cloneable for Scenario {}
impl Cloneable for Tick {} impl Cloneable for Tick {}
impl Cloneable for MapEdits {}
impl Cloneable for ABTest {} impl Cloneable for ABTest {}

View File

@ -1,41 +0,0 @@
use abstutil;
use control::{ControlStopSign, ControlTrafficSignal};
use map_model::{IntersectionID, RoadEdits};
use std::collections::BTreeMap;
// This has to live in sim, not map_model, because the control layer is between the two.
#[derive(Serialize, Deserialize, Clone)]
pub struct MapEdits {
pub edits_name: String,
pub map_name: String,
pub road_edits: RoadEdits,
pub stop_signs: BTreeMap<IntersectionID, ControlStopSign>,
pub traffic_signals: BTreeMap<IntersectionID, ControlTrafficSignal>,
}
impl MapEdits {
pub fn new() -> MapEdits {
MapEdits {
edits_name: "no_edits".to_string(),
map_name: "TODO".to_string(), // TODO er
road_edits: RoadEdits::new(),
stop_signs: BTreeMap::new(),
traffic_signals: BTreeMap::new(),
}
}
pub fn describe(&self) -> String {
format!(
"map edits \"{}\" ({} roads, {} stop signs, {} traffic signals",
self.edits_name,
self.road_edits.len(),
self.stop_signs.len(),
self.traffic_signals.len()
)
}
pub fn save(&self) {
abstutil::save_object("edits", &self.map_name, &self.edits_name, self);
}
}

View File

@ -1,7 +1,6 @@
use abstutil; use abstutil;
use control::ControlMap; use map_model::{Map, MapEdits};
use map_model::Map; use {Scenario, Sim, Tick};
use {MapEdits, Scenario, Sim, Tick};
#[derive(StructOpt, Debug, Clone)] #[derive(StructOpt, Debug, Clone)]
#[structopt(name = "sim_flags")] #[structopt(name = "sim_flags")]
@ -44,7 +43,7 @@ pub fn load(
flags: SimFlags, flags: SimFlags,
savestate_every: Option<Tick>, savestate_every: Option<Tick>,
timer: &mut abstutil::Timer, timer: &mut abstutil::Timer,
) -> (Map, ControlMap, Sim) { ) -> (Map, Sim) {
if flags.load.contains("data/save/") { if flags.load.contains("data/save/") {
assert_eq!(flags.edits_name, "no_edits"); assert_eq!(flags.edits_name, "no_edits");
@ -54,7 +53,7 @@ pub fn load(
timer.stop("read sim savestate"); timer.stop("read sim savestate");
let edits: MapEdits = if sim.edits_name == "no_edits" { let edits: MapEdits = if sim.edits_name == "no_edits" {
MapEdits::new() MapEdits::new(&sim.map_name)
} else { } else {
abstutil::read_json(&format!( abstutil::read_json(&format!(
"../data/edits/{}/{}.json", "../data/edits/{}/{}.json",
@ -68,12 +67,11 @@ pub fn load(
timer, timer,
).unwrap_or_else(|_| { ).unwrap_or_else(|_| {
let map_path = format!("../data/raw_maps/{}.abst", sim.map_name); let map_path = format!("../data/raw_maps/{}.abst", sim.map_name);
Map::new(&map_path, edits.road_edits.clone(), timer) Map::new(&map_path, edits, timer)
.expect(&format!("Couldn't load map from {}", map_path)) .expect(&format!("Couldn't load map from {}", map_path))
}); });
let control_map = ControlMap::new(&map, edits.stop_signs, edits.traffic_signals);
(map, control_map, sim) (map, sim)
} else if flags.load.contains("data/scenarios/") { } else if flags.load.contains("data/scenarios/") {
info!("Seeding the simulation from scenario {}", flags.load); info!("Seeding the simulation from scenario {}", flags.load);
let scenario: Scenario = abstutil::read_json(&flags.load).expect("loading scenario failed"); let scenario: Scenario = abstutil::read_json(&flags.load).expect("loading scenario failed");
@ -88,10 +86,9 @@ pub fn load(
timer, timer,
).unwrap_or_else(|_| { ).unwrap_or_else(|_| {
let map_path = format!("../data/raw_maps/{}.abst", scenario.map_name); let map_path = format!("../data/raw_maps/{}.abst", scenario.map_name);
Map::new(&map_path, edits.road_edits.clone(), timer) Map::new(&map_path, edits, timer)
.expect(&format!("Couldn't load map from {}", map_path)) .expect(&format!("Couldn't load map from {}", map_path))
}); });
let control_map = ControlMap::new(&map, edits.stop_signs, edits.traffic_signals);
let mut sim = Sim::new( let mut sim = Sim::new(
&map, &map,
// TODO or the scenario name if no run name // TODO or the scenario name if no run name
@ -100,7 +97,7 @@ pub fn load(
savestate_every, savestate_every,
); );
scenario.instantiate(&mut sim, &map); scenario.instantiate(&mut sim, &map);
(map, control_map, sim) (map, sim)
} else if flags.load.contains("data/raw_maps/") { } else if flags.load.contains("data/raw_maps/") {
// TODO relative dir is brittle; match more cautiously // TODO relative dir is brittle; match more cautiously
let map_name = flags let map_name = flags
@ -110,30 +107,22 @@ pub fn load(
.to_string(); .to_string();
info!("Loading map {}", flags.load); info!("Loading map {}", flags.load);
let edits = load_edits(&map_name, &flags); let edits = load_edits(&map_name, &flags);
let map = Map::new(&flags.load, edits.road_edits.clone(), timer) let map = Map::new(&flags.load, edits, timer)
.expect(&format!("Couldn't load map from {}", flags.load)); .expect(&format!("Couldn't load map from {}", flags.load));
let control_map = ControlMap::new(&map, edits.stop_signs, edits.traffic_signals);
timer.start("create sim"); timer.start("create sim");
let sim = Sim::new(&map, flags.run_name, flags.rng_seed, savestate_every); let sim = Sim::new(&map, flags.run_name, flags.rng_seed, savestate_every);
timer.stop("create sim"); timer.stop("create sim");
(map, control_map, sim) (map, sim)
} else if flags.load.contains("data/maps/") { } else if flags.load.contains("data/maps/") {
assert_eq!(flags.edits_name, "no_edits"); assert_eq!(flags.edits_name, "no_edits");
info!("Loading map {}", flags.load); info!("Loading map {}", flags.load);
let map: Map = abstutil::read_binary(&flags.load, timer) let map: Map = abstutil::read_binary(&flags.load, timer)
.expect(&format!("Couldn't load map from {}", flags.load)); .expect(&format!("Couldn't load map from {}", flags.load));
// TODO Bit sad to load edits to reconstitute ControlMap, but this is necessary right now
let edits: MapEdits = abstutil::read_json(&format!(
"../data/edits/{}/{}.json",
map.get_name(),
map.get_road_edits().edits_name
)).unwrap();
let control_map = ControlMap::new(&map, edits.stop_signs, edits.traffic_signals);
timer.start("create sim"); timer.start("create sim");
let sim = Sim::new(&map, flags.run_name, flags.rng_seed, savestate_every); let sim = Sim::new(&map, flags.run_name, flags.rng_seed, savestate_every);
timer.stop("create sim"); timer.stop("create sim");
(map, control_map, sim) (map, sim)
} else { } else {
panic!("Don't know how to load {}", flags.load); panic!("Don't know how to load {}", flags.load);
} }
@ -141,7 +130,7 @@ pub fn load(
fn load_edits(map_name: &str, flags: &SimFlags) -> MapEdits { fn load_edits(map_name: &str, flags: &SimFlags) -> MapEdits {
if flags.edits_name == "no_edits" { if flags.edits_name == "no_edits" {
return MapEdits::new(); return MapEdits::new(map_name);
} }
if flags.edits_name.contains("data/") || flags.edits_name.contains(".json") { if flags.edits_name.contains("data/") || flags.edits_name.contains(".json") {
panic!( panic!(

View File

@ -2,13 +2,11 @@
// it. // it.
mod a_b_test; mod a_b_test;
mod edits;
mod load; mod load;
mod neighborhood; mod neighborhood;
mod scenario; mod scenario;
pub use self::a_b_test::{ABTest, ABTestResults}; pub use self::a_b_test::{ABTest, ABTestResults};
pub use self::edits::MapEdits;
pub use self::load::{load, SimFlags}; pub use self::load::{load, SimFlags};
pub use self::neighborhood::{Neighborhood, NeighborhoodBuilder}; pub use self::neighborhood::{Neighborhood, NeighborhoodBuilder};
pub use self::scenario::{ pub use self::scenario::{

View File

@ -2,7 +2,6 @@
use abstutil; use abstutil;
use abstutil::Error; use abstutil::Error;
use control::ControlMap;
use driving::DrivingSimState; use driving::DrivingSimState;
use instrument::capture_backtrace; use instrument::capture_backtrace;
use intersections::IntersectionSimState; use intersections::IntersectionSimState;
@ -77,7 +76,7 @@ impl Sim {
transit_state: TransitSimState::new(), transit_state: TransitSimState::new(),
time: Tick::zero(), time: Tick::zero(),
map_name: map.get_name().to_string(), map_name: map.get_name().to_string(),
edits_name: map.get_road_edits().edits_name.to_string(), edits_name: map.get_edits().edits_name.to_string(),
run_name, run_name,
savestate_every, savestate_every,
current_agent_for_debugging: None, current_agent_for_debugging: None,
@ -144,13 +143,13 @@ impl Sim {
} }
} }
pub fn step(&mut self, map: &Map, control_map: &ControlMap) -> Vec<Event> { pub fn step(&mut self, map: &Map) -> Vec<Event> {
// If there's an error, panic, so editor or headless will catch it, call dump_before_abort, // If there's an error, panic, so editor or headless will catch it, call dump_before_abort,
// and also do any other bail-out handling. // and also do any other bail-out handling.
self.inner_step(map, control_map).unwrap() self.inner_step(map).unwrap()
} }
fn inner_step(&mut self, map: &Map, control_map: &ControlMap) -> Result<(Vec<Event>), Error> { fn inner_step(&mut self, map: &Map) -> Result<(Vec<Event>), Error> {
let mut view = WorldView::new(); let mut view = WorldView::new();
let mut events: Vec<Event> = Vec::new(); let mut events: Vec<Event> = Vec::new();
@ -237,7 +236,7 @@ impl Sim {
// Note that the intersection sees the WorldView BEFORE the updates that just happened this // Note that the intersection sees the WorldView BEFORE the updates that just happened this
// tick. // tick.
self.intersection_state self.intersection_state
.step(&mut events, self.time, map, control_map, &view); .step(&mut events, self.time, map, &view);
// Do this at the end of the step, so that tick 0 actually occurs and things can happen // Do this at the end of the step, so that tick 0 actually occurs and things can happen
// then. // then.
@ -286,8 +285,8 @@ impl Sim {
self.driving_state.toggle_debug(id); self.driving_state.toggle_debug(id);
} }
pub fn debug_intersection(&mut self, id: IntersectionID, control_map: &ControlMap) { pub fn debug_intersection(&mut self, id: IntersectionID, map: &Map) {
self.intersection_state.debug(id, control_map); self.intersection_state.debug(id, map);
} }
pub fn save(&self) -> String { pub fn save(&self) -> String {

View File

@ -35,12 +35,12 @@ pub fn run(t: &mut TestRunner) {
Box::new(|_| { Box::new(|_| {
let map1 = map_model::Map::new( let map1 = map_model::Map::new(
"../data/raw_maps/montlake.abst", "../data/raw_maps/montlake.abst",
map_model::RoadEdits::new(), map_model::MapEdits::new("montlake"),
&mut abstutil::Timer::new("raw to map"), &mut abstutil::Timer::new("raw to map"),
).unwrap(); ).unwrap();
let map2 = map_model::Map::new( let map2 = map_model::Map::new(
"../data/raw_maps/montlake.abst", "../data/raw_maps/montlake.abst",
map_model::RoadEdits::new(), map_model::MapEdits::new("montlake"),
&mut abstutil::Timer::new("raw to map"), &mut abstutil::Timer::new("raw to map"),
).unwrap(); ).unwrap();

View File

@ -8,7 +8,7 @@ pub fn run(t: &mut TestRunner) {
t.run_slow( t.run_slow(
"park_on_goal_st", "park_on_goal_st",
Box::new(|h| { Box::new(|h| {
let (map, control_map, mut sim) = sim::load( let (map, mut sim) = sim::load(
sim::SimFlags::synthetic_test("parking_test", "park_on_goal_st"), sim::SimFlags::synthetic_test("parking_test", "park_on_goal_st"),
None, None,
&mut Timer::new("setup test"), &mut Timer::new("setup test"),
@ -28,21 +28,20 @@ pub fn run(t: &mut TestRunner) {
sim.run_until_expectations_met( sim.run_until_expectations_met(
&map, &map,
&control_map,
vec![sim::Event::CarReachedParkingSpot( vec![sim::Event::CarReachedParkingSpot(
car, car,
sim::ParkingSpot::new(north_parking, 4), sim::ParkingSpot::new(north_parking, 4),
)], )],
sim::Tick::from_minutes(2), sim::Tick::from_minutes(2),
); );
sim.run_until_done(&map, &control_map, Box::new(|_sim| {})); sim.run_until_done(&map, Box::new(|_sim| {}));
}), }),
); );
t.run_slow( t.run_slow(
"wander_around_for_parking", "wander_around_for_parking",
Box::new(|h| { Box::new(|h| {
let (map, control_map, mut sim) = sim::load( let (map, mut sim) = sim::load(
sim::SimFlags::synthetic_test("parking_test", "wander_around_for_parking"), sim::SimFlags::synthetic_test("parking_test", "wander_around_for_parking"),
None, None,
&mut Timer::new("setup test"), &mut Timer::new("setup test"),
@ -62,14 +61,13 @@ pub fn run(t: &mut TestRunner) {
sim.run_until_expectations_met( sim.run_until_expectations_met(
&map, &map,
&control_map,
vec![sim::Event::CarReachedParkingSpot( vec![sim::Event::CarReachedParkingSpot(
car, car,
sim::ParkingSpot::new(south_parking, 0), sim::ParkingSpot::new(south_parking, 0),
)], )],
sim::Tick::from_minutes(2), sim::Tick::from_minutes(2),
); );
sim.run_until_done(&map, &control_map, Box::new(|_sim| {})); sim.run_until_done(&map, Box::new(|_sim| {}));
}), }),
); );
} }

View File

@ -6,14 +6,14 @@ pub fn run(t: &mut TestRunner) {
t.run_slow( t.run_slow(
"small_spawn_completes", "small_spawn_completes",
Box::new(|h| { Box::new(|h| {
let (map, control_map, mut sim) = sim::load( let (map, mut sim) = sim::load(
sim::SimFlags::for_test("aorta_model_completes"), sim::SimFlags::for_test("aorta_model_completes"),
Some(sim::Tick::from_seconds(30)), Some(sim::Tick::from_seconds(30)),
&mut Timer::new("setup test"), &mut Timer::new("setup test"),
); );
sim.small_spawn(&map); sim.small_spawn(&map);
h.setup_done(&sim); h.setup_done(&sim);
sim.run_until_done(&map, &control_map, Box::new(|_sim| {})); sim.run_until_done(&map, Box::new(|_sim| {}));
}), }),
); );
} }

View File

@ -6,7 +6,7 @@ pub fn run(t: &mut TestRunner) {
t.run_slow( t.run_slow(
"serialization", "serialization",
Box::new(|_| { Box::new(|_| {
let (map, _, mut sim) = sim::load( let (map, mut sim) = sim::load(
sim::SimFlags::for_test("serialization"), sim::SimFlags::for_test("serialization"),
None, None,
&mut Timer::new("setup test"), &mut Timer::new("setup test"),
@ -24,7 +24,7 @@ pub fn run(t: &mut TestRunner) {
"from_scratch", "from_scratch",
Box::new(|_| { Box::new(|_| {
println!("Creating two simulations"); println!("Creating two simulations");
let (map, control_map, mut sim1) = sim::load( let (map, mut sim1) = sim::load(
sim::SimFlags::for_test("from_scratch_1"), sim::SimFlags::for_test("from_scratch_1"),
None, None,
&mut Timer::new("setup test"), &mut Timer::new("setup test"),
@ -42,8 +42,8 @@ pub fn run(t: &mut TestRunner) {
sim2.save() sim2.save()
); );
} }
sim1.step(&map, &control_map); sim1.step(&map);
sim2.step(&map, &control_map); sim2.step(&map);
} }
}), }),
); );
@ -52,7 +52,7 @@ pub fn run(t: &mut TestRunner) {
"with_savestating", "with_savestating",
Box::new(|_| { Box::new(|_| {
println!("Creating two simulations"); println!("Creating two simulations");
let (map, control_map, mut sim1) = sim::load( let (map, mut sim1) = sim::load(
sim::SimFlags::for_test("with_savestating_1"), sim::SimFlags::for_test("with_savestating_1"),
None, None,
&mut Timer::new("setup test"), &mut Timer::new("setup test"),
@ -62,8 +62,8 @@ pub fn run(t: &mut TestRunner) {
sim2.small_spawn(&map); sim2.small_spawn(&map);
for _ in 1..600 { for _ in 1..600 {
sim1.step(&map, &control_map); sim1.step(&map);
sim2.step(&map, &control_map); sim2.step(&map);
} }
if sim1 != sim2 { if sim1 != sim2 {
@ -77,7 +77,7 @@ pub fn run(t: &mut TestRunner) {
let sim1_save = sim1.save(); let sim1_save = sim1.save();
for _ in 1..60 { for _ in 1..60 {
sim1.step(&map, &control_map); sim1.step(&map);
} }
if sim1 == sim2 { if sim1 == sim2 {

View File

@ -7,7 +7,7 @@ pub fn run(t: &mut TestRunner) {
t.run_slow( t.run_slow(
"bus_reaches_stops", "bus_reaches_stops",
Box::new(|h| { Box::new(|h| {
let (map, control_map, mut sim) = sim::load( let (map, mut sim) = sim::load(
SimFlags::for_test("bus_reaches_stops"), SimFlags::for_test("bus_reaches_stops"),
Some(Tick::from_seconds(30)), Some(Tick::from_seconds(30)),
&mut Timer::new("setup test"), &mut Timer::new("setup test"),
@ -24,20 +24,15 @@ pub fn run(t: &mut TestRunner) {
expectations.push(Event::BusDepartedFromStop(bus, *stop)); expectations.push(Event::BusDepartedFromStop(bus, *stop));
} }
sim.run_until_expectations_met( sim.run_until_expectations_met(&map, expectations, Tick::from_minutes(10));
&map, sim.run_until_done(&map, Box::new(|_sim| {}));
&control_map,
expectations,
Tick::from_minutes(10),
);
sim.run_until_done(&map, &control_map, Box::new(|_sim| {}));
}), }),
); );
t.run_slow( t.run_slow(
"ped_uses_bus", "ped_uses_bus",
Box::new(|h| { Box::new(|h| {
let (map, control_map, mut sim) = sim::load( let (map, mut sim) = sim::load(
SimFlags::for_test("ped_uses_bus"), SimFlags::for_test("ped_uses_bus"),
Some(Tick::from_seconds(30)), Some(Tick::from_seconds(30)),
&mut Timer::new("setup test"), &mut Timer::new("setup test"),
@ -56,7 +51,6 @@ pub fn run(t: &mut TestRunner) {
sim.run_until_expectations_met( sim.run_until_expectations_met(
&map, &map,
&control_map,
vec![ vec![
sim::Event::PedReachedBusStop(ped, ped_stop1), sim::Event::PedReachedBusStop(ped, ped_stop1),
sim::Event::BusArrivedAtStop(bus, ped_stop1), sim::Event::BusArrivedAtStop(bus, ped_stop1),