mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 15:02:59 +03:00
the great control layer merge
This commit is contained in:
parent
609c731fa0
commit
4d7c1203a6
@ -3,7 +3,6 @@
|
||||
members = [
|
||||
"abstutil",
|
||||
"analyze_code",
|
||||
"control",
|
||||
"convert_osm",
|
||||
"editor",
|
||||
"ezgui",
|
||||
|
@ -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"
|
@ -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,
|
||||
}
|
@ -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, )* );
|
||||
}
|
||||
}
|
||||
}*/
|
@ -6,7 +6,6 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
|
||||
[dependencies]
|
||||
aabb-quadtree = "0.1.0"
|
||||
abstutil = { path = "../abstutil" }
|
||||
control = { path = "../control" }
|
||||
counter = "0.4.3"
|
||||
cpuprofiler = "0.0.3"
|
||||
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
extern crate aabb_quadtree;
|
||||
extern crate abstutil;
|
||||
extern crate control;
|
||||
extern crate counter;
|
||||
extern crate cpuprofiler;
|
||||
extern crate dimensioned;
|
||||
|
@ -1,5 +1,4 @@
|
||||
use colors::ColorScheme;
|
||||
use control::ControlMap;
|
||||
use ezgui::Canvas;
|
||||
use geom::Pt2D;
|
||||
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 {
|
||||
ID::Lane(id) => {
|
||||
map.get_l(id).dump_debug();
|
||||
}
|
||||
ID::Intersection(id) => {
|
||||
map.get_i(id).dump_debug();
|
||||
sim.debug_intersection(id, control_map);
|
||||
sim.debug_intersection(id, map);
|
||||
}
|
||||
ID::Turn(id) => {
|
||||
map.get_t(id).dump_debug(map);
|
||||
@ -102,7 +101,6 @@ impl ID {
|
||||
pub struct Ctx<'a> {
|
||||
pub cs: &'a mut ColorScheme,
|
||||
pub map: &'a Map,
|
||||
pub control_map: &'a ControlMap,
|
||||
pub draw_map: &'a DrawMap,
|
||||
pub canvas: &'a Canvas,
|
||||
pub sim: &'a Sim,
|
||||
|
@ -44,7 +44,6 @@ impl Plugin for DebugObjectsState {
|
||||
} else if ctx.input.key_pressed(Key::D, "debug") {
|
||||
id.debug(
|
||||
&ctx.primary.map,
|
||||
&ctx.primary.control_map,
|
||||
&mut ctx.primary.sim,
|
||||
&ctx.primary.draw_map,
|
||||
);
|
||||
|
@ -1,10 +1,9 @@
|
||||
use control::ControlMap;
|
||||
use ezgui::{GfxCtx, Wizard, WrappedWizard};
|
||||
use map_model::Map;
|
||||
use objects::{Ctx, SIM_SETUP};
|
||||
use piston::input::Key;
|
||||
use plugins::{choose_edits, Plugin, PluginCtx};
|
||||
use sim::{MapEdits, SimFlags};
|
||||
use sim::SimFlags;
|
||||
use ui::{PerMapUI, PluginsPerMap};
|
||||
|
||||
pub enum EditsManager {
|
||||
@ -36,7 +35,6 @@ impl Plugin for EditsManager {
|
||||
if manage_edits(
|
||||
&mut ctx.primary.current_flags,
|
||||
&ctx.primary.map,
|
||||
&ctx.primary.control_map,
|
||||
ctx.kml,
|
||||
&mut new_primary,
|
||||
wizard.wrap(ctx.input),
|
||||
@ -76,7 +74,6 @@ impl Plugin for EditsManager {
|
||||
fn manage_edits(
|
||||
current_flags: &mut SimFlags,
|
||||
map: &Map,
|
||||
control_map: &ControlMap,
|
||||
kml: &Option<String>,
|
||||
new_primary: &mut Option<(PerMapUI, PluginsPerMap)>,
|
||||
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
|
||||
// wizard is started...
|
||||
let mut edits = MapEdits {
|
||||
edits_name: current_flags.edits_name.to_string(),
|
||||
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();
|
||||
let mut edits = map.get_edits().clone();
|
||||
edits.edits_name = edits.edits_name.clone();
|
||||
|
||||
match wizard
|
||||
.choose_string(&format!("Manage {}", edits.describe()), choices)?
|
||||
|
@ -15,17 +15,16 @@ impl RoadEditor {
|
||||
|
||||
impl Plugin for RoadEditor {
|
||||
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.primary.current_selection,
|
||||
&mut ctx.primary.map,
|
||||
&mut ctx.primary.draw_map,
|
||||
&ctx.primary.control_map,
|
||||
&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;
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
// Add turns back
|
||||
|
@ -81,10 +81,10 @@ impl Plugin for SimController {
|
||||
self.last_step = Some(Instant::now());
|
||||
self.benchmark = Some(primary.sim.start_benchmark());
|
||||
} 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;
|
||||
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/
|
||||
let dt_s = elapsed_seconds(tick);
|
||||
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;
|
||||
if let Some((s, _)) = secondary {
|
||||
s.sim.step(&s.map, &s.control_map);
|
||||
s.sim.step(&s.map);
|
||||
}
|
||||
self.last_step = Some(Instant::now());
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
use control::TurnPriority;
|
||||
use ezgui::Color;
|
||||
use map_model::IntersectionID;
|
||||
use map_model::{IntersectionID, TurnPriority};
|
||||
use objects::{Ctx, ID};
|
||||
use piston::input::Key;
|
||||
use plugins::{Plugin, PluginCtx};
|
||||
@ -29,14 +28,13 @@ impl StopSignEditor {
|
||||
impl Plugin for StopSignEditor {
|
||||
fn event(&mut self, ctx: PluginCtx) -> bool {
|
||||
let input = ctx.input;
|
||||
let map = &ctx.primary.map;
|
||||
let control_map = &mut ctx.primary.control_map;
|
||||
let map = &mut ctx.primary.map;
|
||||
let selected = ctx.primary.current_selection;
|
||||
|
||||
if *self == StopSignEditor::Inactive {
|
||||
match selected {
|
||||
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))
|
||||
{
|
||||
*self = StopSignEditor::Active(id);
|
||||
@ -55,7 +53,8 @@ impl Plugin for StopSignEditor {
|
||||
new_state = Some(StopSignEditor::Inactive);
|
||||
} else if let Some(ID::Turn(id)) = selected {
|
||||
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) {
|
||||
TurnPriority::Priority => {
|
||||
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 {
|
||||
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 => {
|
||||
Some(ctx.cs.get("priority stop sign turn", Color::GREEN))
|
||||
}
|
||||
|
@ -2,9 +2,8 @@
|
||||
|
||||
// TODO how to edit cycle time?
|
||||
|
||||
use control::TurnPriority;
|
||||
use ezgui::Color;
|
||||
use map_model::IntersectionID;
|
||||
use map_model::{IntersectionID, TurnPriority};
|
||||
use objects::{Ctx, ID};
|
||||
use piston::input::Key;
|
||||
use plugins::{Plugin, PluginCtx};
|
||||
@ -37,14 +36,13 @@ impl TrafficSignalEditor {
|
||||
impl Plugin for TrafficSignalEditor {
|
||||
fn event(&mut self, ctx: PluginCtx) -> bool {
|
||||
let input = ctx.input;
|
||||
let map = &ctx.primary.map;
|
||||
let control_map = &mut ctx.primary.control_map;
|
||||
let map = &mut ctx.primary.map;
|
||||
let selected = ctx.primary.current_selection;
|
||||
|
||||
if *self == TrafficSignalEditor::Inactive {
|
||||
match selected {
|
||||
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))
|
||||
{
|
||||
*self = TrafficSignalEditor::Active {
|
||||
@ -67,7 +65,7 @@ impl Plugin for TrafficSignalEditor {
|
||||
} else {
|
||||
// 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(
|
||||
cycles.len(),
|
||||
&format!(
|
||||
@ -84,28 +82,33 @@ impl Plugin for TrafficSignalEditor {
|
||||
// Change turns
|
||||
if let Some(ID::Turn(id)) = selected {
|
||||
if id.parent == *i {
|
||||
let cycle =
|
||||
&mut control_map.traffic_signals.get_mut(&i).unwrap().cycles
|
||||
[*current_cycle];
|
||||
if cycle.get_priority(id) == TurnPriority::Priority {
|
||||
if input
|
||||
.key_pressed(Key::Backspace, "remove this turn from this cycle")
|
||||
{
|
||||
cycle.remove(id);
|
||||
}
|
||||
} else if cycle.could_be_priority_turn(id, map) {
|
||||
if input.key_pressed(
|
||||
Key::Space,
|
||||
"add this turn to this cycle as 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")
|
||||
{
|
||||
cycle.add(id, TurnPriority::Yield);
|
||||
let mut signal = map.get_traffic_signal(*i).clone();
|
||||
{
|
||||
let cycle = &mut signal.cycles[*current_cycle];
|
||||
if cycle.get_priority(id) == TurnPriority::Priority {
|
||||
if input.key_pressed(
|
||||
Key::Backspace,
|
||||
"remove this turn from this cycle",
|
||||
) {
|
||||
cycle.remove(id);
|
||||
}
|
||||
} else if cycle.could_be_priority_turn(id, map) {
|
||||
if input.key_pressed(
|
||||
Key::Space,
|
||||
"add this turn to this cycle as 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")
|
||||
{
|
||||
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)));
|
||||
}
|
||||
|
||||
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
|
||||
let could_be_priority = cycle.could_be_priority_turn(t, ctx.map);
|
||||
|
@ -1,8 +1,9 @@
|
||||
use control::{ControlTrafficSignal, TurnPriority};
|
||||
use dimensioned::si;
|
||||
use ezgui::{Color, GfxCtx};
|
||||
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 piston::input::Key;
|
||||
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));
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -84,9 +84,9 @@ impl Renderable for DrawIntersection {
|
||||
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()
|
||||
} 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()
|
||||
} else {
|
||||
false
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
use colors::ColorScheme;
|
||||
use control::ControlMap;
|
||||
use dimensioned::si;
|
||||
use ezgui::{Color, GfxCtx, Text};
|
||||
use geom::{Bounds, Circle, Line, Polygon, Pt2D};
|
||||
@ -52,7 +51,7 @@ pub struct 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 polygon = lane.lane_center_pts.make_polygons_blindly(LANE_THICKNESS);
|
||||
|
||||
@ -86,7 +85,7 @@ impl DrawLane {
|
||||
if lane.is_driving()
|
||||
&& 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);
|
||||
}
|
||||
}
|
||||
@ -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> {
|
||||
if control_map.stop_signs[&lane.dst_i].is_priority_lane(lane.id) {
|
||||
fn calculate_stop_sign_line(lane: &Lane, map: &Map) -> Option<Marking> {
|
||||
if map.get_stop_sign(lane.dst_i).is_priority_lane(lane.id) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
use aabb_quadtree::QuadTree;
|
||||
use abstutil::Timer;
|
||||
use control::ControlMap;
|
||||
use geom::Bounds;
|
||||
use kml::ExtraShape;
|
||||
use map_model::{
|
||||
@ -40,17 +39,12 @@ pub struct DrawMap {
|
||||
}
|
||||
|
||||
impl DrawMap {
|
||||
pub fn new(
|
||||
map: &Map,
|
||||
control_map: &ControlMap,
|
||||
raw_extra_shapes: Vec<ExtraShape>,
|
||||
timer: &mut Timer,
|
||||
) -> DrawMap {
|
||||
pub fn new(map: &Map, raw_extra_shapes: Vec<ExtraShape>, timer: &mut Timer) -> DrawMap {
|
||||
let mut lanes: Vec<DrawLane> = Vec::new();
|
||||
timer.start_iter("make DrawLanes", map.all_lanes().len());
|
||||
for l in map.all_lanes() {
|
||||
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();
|
||||
@ -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.
|
||||
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) {
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
use abstutil;
|
||||
use colors::ColorScheme;
|
||||
use control::ControlMap;
|
||||
//use cpuprofiler;
|
||||
use ezgui::{Canvas, Color, GfxCtx, Text, UserInput, BOTTOM_LEFT, GUI};
|
||||
use kml;
|
||||
@ -97,7 +96,6 @@ impl GUI for UI {
|
||||
Ctx {
|
||||
cs: &mut self.cs.borrow_mut(),
|
||||
map: &self.primary.map,
|
||||
control_map: &self.primary.control_map,
|
||||
draw_map: &self.primary.draw_map,
|
||||
canvas: &self.canvas,
|
||||
sim: &self.primary.sim,
|
||||
@ -116,7 +114,6 @@ impl GUI for UI {
|
||||
Ctx {
|
||||
cs: &mut self.cs.borrow_mut(),
|
||||
map: &self.primary.map,
|
||||
control_map: &self.primary.control_map,
|
||||
draw_map: &self.primary.draw_map,
|
||||
canvas: &self.canvas,
|
||||
sim: &self.primary.sim,
|
||||
@ -130,7 +127,6 @@ impl GUI for UI {
|
||||
Ctx {
|
||||
cs: &mut self.cs.borrow_mut(),
|
||||
map: &self.primary.map,
|
||||
control_map: &self.primary.control_map,
|
||||
draw_map: &self.primary.draw_map,
|
||||
canvas: &self.canvas,
|
||||
sim: &self.primary.sim,
|
||||
@ -144,7 +140,6 @@ impl GUI for UI {
|
||||
Ctx {
|
||||
cs: &mut self.cs.borrow_mut(),
|
||||
map: &self.primary.map,
|
||||
control_map: &self.primary.control_map,
|
||||
draw_map: &self.primary.draw_map,
|
||||
canvas: &self.canvas,
|
||||
sim: &self.primary.sim,
|
||||
@ -161,7 +156,6 @@ impl GUI for UI {
|
||||
pub struct PerMapUI {
|
||||
pub map: Map,
|
||||
pub draw_map: DrawMap,
|
||||
pub control_map: ControlMap,
|
||||
pub sim: Sim,
|
||||
|
||||
pub current_selection: Option<ID>,
|
||||
@ -204,8 +198,7 @@ impl PerMapUI {
|
||||
pub fn new(flags: SimFlags, kml: &Option<String>) -> (PerMapUI, PluginsPerMap) {
|
||||
let mut timer = abstutil::Timer::new("setup PerMapUI");
|
||||
|
||||
let (map, control_map, sim) =
|
||||
sim::load(flags.clone(), Some(Tick::from_seconds(30)), &mut timer);
|
||||
let (map, sim) = sim::load(flags.clone(), Some(Tick::from_seconds(30)), &mut timer);
|
||||
let extra_shapes: Vec<kml::ExtraShape> = if let Some(path) = kml {
|
||||
if path.ends_with(".kml") {
|
||||
kml::load(&path, &map.get_gps_bounds(), &mut timer)
|
||||
@ -221,7 +214,7 @@ impl PerMapUI {
|
||||
};
|
||||
|
||||
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");
|
||||
|
||||
let steepness_viz = plugins::steep::SteepnessVisualizer::new(&map);
|
||||
@ -233,7 +226,6 @@ impl PerMapUI {
|
||||
let state = PerMapUI {
|
||||
map,
|
||||
draw_map,
|
||||
control_map,
|
||||
sim,
|
||||
|
||||
current_selection: None,
|
||||
@ -427,7 +419,6 @@ impl UI {
|
||||
let ctx = Ctx {
|
||||
cs: &mut self.cs.borrow_mut(),
|
||||
map: &self.primary.map,
|
||||
control_map: &self.primary.control_map,
|
||||
draw_map: &self.primary.draw_map,
|
||||
canvas: &self.canvas,
|
||||
sim: &self.primary.sim,
|
||||
|
@ -5,7 +5,6 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
abstutil = { path = "../abstutil" }
|
||||
control = { path = "../control" }
|
||||
cpuprofiler = "0.0.3"
|
||||
log = "0.4.5"
|
||||
map_model = { path = "../map_model" }
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
extern crate abstutil;
|
||||
extern crate control;
|
||||
extern crate cpuprofiler;
|
||||
extern crate log;
|
||||
extern crate map_model;
|
||||
@ -35,7 +34,7 @@ fn main() {
|
||||
// TODO not the ideal way to distinguish what thing we loaded
|
||||
let load = flags.sim_flags.load.clone();
|
||||
let mut timer = Timer::new("setup headless");
|
||||
let (map, control_map, mut sim) = sim::load(
|
||||
let (map, mut sim) = sim::load(
|
||||
flags.sim_flags,
|
||||
Some(sim::Tick::from_seconds(30)),
|
||||
&mut timer,
|
||||
@ -63,7 +62,6 @@ fn main() {
|
||||
.unwrap();
|
||||
sim.run_until_done(
|
||||
&map,
|
||||
&control_map,
|
||||
Box::new(move |sim| {
|
||||
if Some(sim.time) == save_at {
|
||||
sim.save();
|
||||
|
@ -1,29 +1,44 @@
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap};
|
||||
use abstutil;
|
||||
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)]
|
||||
pub struct RoadEdits {
|
||||
pub struct MapEdits {
|
||||
pub edits_name: String,
|
||||
pub map_name: String,
|
||||
|
||||
// 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) stop_signs: BTreeMap<IntersectionID, ControlStopSign>,
|
||||
pub(crate) traffic_signals: BTreeMap<IntersectionID, ControlTrafficSignal>,
|
||||
}
|
||||
|
||||
impl RoadEdits {
|
||||
pub fn new() -> RoadEdits {
|
||||
RoadEdits {
|
||||
impl MapEdits {
|
||||
pub fn new(map_name: &str) -> MapEdits {
|
||||
MapEdits {
|
||||
// Something has to fill this out later
|
||||
edits_name: "no_edits".to_string(),
|
||||
map_name: map_name.to_string(),
|
||||
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(
|
||||
&mut self,
|
||||
reason: EditReason,
|
||||
@ -45,10 +60,6 @@ impl RoadEdits {
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.roads.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||
|
@ -30,6 +30,8 @@ mod parcel;
|
||||
mod pathfind;
|
||||
pub mod raw_data;
|
||||
mod road;
|
||||
mod stop_signs;
|
||||
mod traffic_signals;
|
||||
mod traversable;
|
||||
mod turn;
|
||||
|
||||
@ -37,7 +39,7 @@ use abstutil::Cloneable;
|
||||
pub use area::{Area, AreaID, AreaType};
|
||||
pub use building::{Building, BuildingID, FrontPath};
|
||||
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 intersection::{Intersection, IntersectionID, IntersectionType};
|
||||
pub use lane::{Lane, LaneID, LaneType, PARKING_SPOT_LENGTH};
|
||||
@ -46,9 +48,12 @@ pub use map::Map;
|
||||
pub use parcel::{Parcel, ParcelID};
|
||||
pub use pathfind::{Path, PathRequest, PathStep, Pathfinder, Trace};
|
||||
pub use road::{Road, RoadID};
|
||||
pub use stop_signs::ControlStopSign;
|
||||
pub use traffic_signals::ControlTrafficSignal;
|
||||
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;
|
||||
|
||||
impl Cloneable for IntersectionID {}
|
||||
impl Cloneable for MapEdits {}
|
||||
|
@ -1,8 +1,5 @@
|
||||
use edits::RoadEdits;
|
||||
use lane::LaneType;
|
||||
use raw_data;
|
||||
use road::RoadID;
|
||||
use std::iter;
|
||||
use {raw_data, LaneType, MapEdits, RoadID};
|
||||
|
||||
// (original direction, reversed direction)
|
||||
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) {
|
||||
info!("Using edits for {}", id);
|
||||
(e.forwards_lanes.clone(), e.backwards_lanes.clone())
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use abstutil;
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap, Error, Timer};
|
||||
use edits::RoadEdits;
|
||||
use edits::MapEdits;
|
||||
use geom::{Bounds, GPSBounds, HashablePt2D, PolyLine, Pt2D};
|
||||
use make;
|
||||
use raw_data;
|
||||
@ -10,9 +10,9 @@ use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
use std::io;
|
||||
use std::path;
|
||||
use {
|
||||
Area, AreaID, Building, BuildingID, BusRoute, BusRouteID, BusStop, BusStopID, Intersection,
|
||||
IntersectionID, IntersectionType, Lane, LaneID, LaneType, Parcel, ParcelID, Road, RoadID, Turn,
|
||||
TurnID, LANE_THICKNESS,
|
||||
Area, AreaID, Building, BuildingID, BusRoute, BusRouteID, BusStop, BusStopID, ControlStopSign,
|
||||
ControlTrafficSignal, Intersection, IntersectionID, IntersectionType, Lane, LaneID, LaneType,
|
||||
Parcel, ParcelID, Road, RoadID, Turn, TurnID, LANE_THICKNESS,
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
@ -35,15 +35,18 @@ pub struct Map {
|
||||
bus_routes: Vec<BusRoute>,
|
||||
areas: Vec<Area>,
|
||||
|
||||
stop_signs: BTreeMap<IntersectionID, ControlStopSign>,
|
||||
traffic_signals: BTreeMap<IntersectionID, ControlTrafficSignal>,
|
||||
// Note that border nodes belong in neither!
|
||||
gps_bounds: GPSBounds,
|
||||
bounds: Bounds,
|
||||
|
||||
name: String,
|
||||
road_edits: RoadEdits,
|
||||
edits: MapEdits,
|
||||
}
|
||||
|
||||
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)?;
|
||||
Ok(Map::create_from_raw(
|
||||
path::Path::new(path)
|
||||
@ -53,7 +56,7 @@ impl Map {
|
||||
.into_string()
|
||||
.unwrap(),
|
||||
data,
|
||||
road_edits,
|
||||
edits,
|
||||
timer,
|
||||
))
|
||||
}
|
||||
@ -61,7 +64,7 @@ impl Map {
|
||||
pub fn create_from_raw(
|
||||
name: String,
|
||||
mut data: raw_data::Map,
|
||||
road_edits: RoadEdits,
|
||||
edits: MapEdits,
|
||||
timer: &mut Timer,
|
||||
) -> Map {
|
||||
timer.start("raw_map to Map");
|
||||
@ -75,7 +78,7 @@ impl Map {
|
||||
|
||||
let mut m = Map {
|
||||
name,
|
||||
road_edits,
|
||||
edits,
|
||||
gps_bounds: gps_bounds.clone(),
|
||||
bounds: bounds.clone(),
|
||||
roads: Vec::new(),
|
||||
@ -87,6 +90,8 @@ impl Map {
|
||||
bus_stops: BTreeMap::new(),
|
||||
bus_routes: Vec::new(),
|
||||
areas: Vec::new(),
|
||||
stop_signs: BTreeMap::new(),
|
||||
traffic_signals: BTreeMap::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
|
||||
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);
|
||||
counter += 1;
|
||||
|
||||
@ -243,6 +248,29 @@ impl Map {
|
||||
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(
|
||||
&mut m.buildings,
|
||||
&data.buildings,
|
||||
@ -286,10 +314,11 @@ impl Map {
|
||||
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.
|
||||
pub fn store_new_edits(&mut self, edits: RoadEdits) {
|
||||
self.road_edits = edits;
|
||||
// TODO Only road editor calls this. Stop sign / traffic signal editor have a nicer pattern.
|
||||
pub fn store_new_edits(&mut self, edits: MapEdits) {
|
||||
self.edits = edits;
|
||||
}
|
||||
|
||||
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> {
|
||||
&self.roads
|
||||
}
|
||||
@ -373,6 +412,14 @@ impl Map {
|
||||
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 {
|
||||
&self.roads[id.0]
|
||||
}
|
||||
@ -401,6 +448,14 @@ impl Map {
|
||||
&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.
|
||||
|
||||
pub fn get_source_intersection(&self, l: LaneID) -> &Intersection {
|
||||
@ -483,8 +538,8 @@ impl Map {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn get_road_edits(&self) -> &RoadEdits {
|
||||
&self.road_edits
|
||||
pub fn get_edits(&self) -> &MapEdits {
|
||||
&self.edits
|
||||
}
|
||||
|
||||
pub fn all_bus_stops(&self) -> &BTreeMap<BusStopID, BusStop> {
|
||||
@ -543,10 +598,7 @@ impl Map {
|
||||
}
|
||||
|
||||
pub fn save(&self) {
|
||||
let path = format!(
|
||||
"../data/maps/{}_{}.abst",
|
||||
self.name, self.road_edits.edits_name
|
||||
);
|
||||
let path = format!("../data/maps/{}_{}.abst", self.name, self.edits.edits_name);
|
||||
info!("Saving {}...", path);
|
||||
abstutil::write_binary(&path, self).expect(&format!("Saving {} failed", path));
|
||||
info!("Saved {}", path);
|
||||
|
@ -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 map_model::{IntersectionID, LaneID, Map, TurnID, TurnType};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use TurnPriority;
|
||||
use {IntersectionID, LaneID, Map, TurnID, TurnPriority, TurnType};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ControlStopSign {
|
||||
intersection: IntersectionID,
|
||||
pub id: IntersectionID,
|
||||
#[serde(
|
||||
serialize_with = "serialize_btreemap",
|
||||
deserialize_with = "deserialize_btreemap"
|
||||
@ -18,9 +15,9 @@ pub struct ControlStopSign {
|
||||
}
|
||||
|
||||
impl ControlStopSign {
|
||||
pub fn new(map: &Map, intersection: IntersectionID) -> ControlStopSign {
|
||||
let ss = smart_assignment(map, intersection);
|
||||
ss.validate(map, intersection).unwrap();
|
||||
pub fn new(map: &Map, id: IntersectionID) -> ControlStopSign {
|
||||
let ss = smart_assignment(map, id);
|
||||
ss.validate(map).unwrap();
|
||||
ss
|
||||
}
|
||||
|
||||
@ -57,9 +54,9 @@ impl ControlStopSign {
|
||||
.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?
|
||||
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());
|
||||
for t in all_turns {
|
||||
assert!(self.turns.contains_key(t));
|
||||
@ -91,9 +88,9 @@ impl ControlStopSign {
|
||||
}
|
||||
}
|
||||
|
||||
fn smart_assignment(map: &Map, intersection: IntersectionID) -> ControlStopSign {
|
||||
if map.get_i(intersection).roads.len() <= 2 {
|
||||
return for_degenerate_and_deadend(map, intersection);
|
||||
fn smart_assignment(map: &Map, id: IntersectionID) -> ControlStopSign {
|
||||
if map.get_i(id).roads.len() <= 2 {
|
||||
return for_degenerate_and_deadend(map, id);
|
||||
}
|
||||
|
||||
// Higher numbers are higher rank roads
|
||||
@ -102,10 +99,10 @@ fn smart_assignment(map: &Map, intersection: IntersectionID) -> ControlStopSign
|
||||
let mut highest_rank = 0;
|
||||
// TODO should just be incoming, but because of weirdness with sidewalks...
|
||||
for l in map
|
||||
.get_i(intersection)
|
||||
.get_i(id)
|
||||
.incoming_lanes
|
||||
.iter()
|
||||
.chain(map.get_i(intersection).outgoing_lanes.iter())
|
||||
.chain(map.get_i(id).outgoing_lanes.iter())
|
||||
{
|
||||
let r = map.get_parent(*l);
|
||||
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);
|
||||
}
|
||||
if ranks.len() == 1 {
|
||||
return all_way_stop(map, intersection);
|
||||
return all_way_stop(map, id);
|
||||
}
|
||||
|
||||
let mut ss = ControlStopSign {
|
||||
intersection,
|
||||
id,
|
||||
turns: BTreeMap::new(),
|
||||
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 it's the highest rank road, make the straight and right turns priority (if
|
||||
// possible) and other turns yield.
|
||||
@ -169,25 +166,25 @@ fn smart_assignment(map: &Map, intersection: IntersectionID) -> ControlStopSign
|
||||
ss
|
||||
}
|
||||
|
||||
fn all_way_stop(map: &Map, intersection: IntersectionID) -> ControlStopSign {
|
||||
fn all_way_stop(map: &Map, id: IntersectionID) -> ControlStopSign {
|
||||
let mut ss = ControlStopSign {
|
||||
intersection,
|
||||
id,
|
||||
turns: BTreeMap::new(),
|
||||
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
|
||||
}
|
||||
|
||||
fn for_degenerate_and_deadend(map: &Map, i: IntersectionID) -> ControlStopSign {
|
||||
fn for_degenerate_and_deadend(map: &Map, id: IntersectionID) -> ControlStopSign {
|
||||
let mut ss = ControlStopSign {
|
||||
intersection: i,
|
||||
id,
|
||||
turns: BTreeMap::new(),
|
||||
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.
|
||||
let priority = match map.get_t(*t).turn_type {
|
||||
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
|
||||
// intersection geometry), sometimes more turns conflict than really should. For now, just
|
||||
// detect and fallback to an all-way stop.
|
||||
if let Err(err) = ss.validate(map, i) {
|
||||
warn!("Giving up on for_degenerate_and_deadend({}): {}", i, err);
|
||||
return all_way_stop(map, i);
|
||||
if let Err(err) = ss.validate(map) {
|
||||
warn!("Giving up on for_degenerate_and_deadend({}): {}", id, err);
|
||||
return all_way_stop(map, id);
|
||||
}
|
||||
|
||||
ss
|
@ -1,8 +1,7 @@
|
||||
use dimensioned::si;
|
||||
use map_model::{IntersectionID, Map, TurnID};
|
||||
use std;
|
||||
use std::collections::BTreeSet;
|
||||
use TurnPriority;
|
||||
use {IntersectionID, Map, TurnID, TurnPriority};
|
||||
|
||||
const CYCLE_DURATION: si::Second<f64> = si::Second {
|
||||
value_unsafe: 15.0,
|
@ -31,6 +31,18 @@ pub enum TurnType {
|
||||
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)]
|
||||
pub struct Turn {
|
||||
pub id: TurnID,
|
||||
|
@ -19,7 +19,7 @@ fn main() {
|
||||
"precompute {} with {}",
|
||||
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");
|
||||
map.save();
|
||||
timer.stop("save map");
|
||||
|
@ -6,7 +6,6 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
|
||||
[dependencies]
|
||||
abstutil = { path = "../abstutil" }
|
||||
backtrace = "0.3.9"
|
||||
control = { path = "../control" }
|
||||
derivative = "1.0.0"
|
||||
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
|
||||
geom = { path = "../geom" }
|
||||
|
@ -1,5 +1,4 @@
|
||||
use abstutil::WeightedUsizeChoice;
|
||||
use control::ControlMap;
|
||||
use driving::DrivingGoal;
|
||||
use map_model::{BuildingID, BusRoute, BusRouteID, BusStopID, LaneID, Map, RoadID};
|
||||
use std::collections::{BTreeSet, VecDeque};
|
||||
@ -14,11 +13,11 @@ use {
|
||||
impl Sim {
|
||||
// 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();
|
||||
loop {
|
||||
match panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
self.step(&map, &control_map);
|
||||
self.step(&map);
|
||||
})) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
@ -43,7 +42,6 @@ impl Sim {
|
||||
pub fn run_until_expectations_met(
|
||||
&mut self,
|
||||
map: &Map,
|
||||
control_map: &ControlMap,
|
||||
all_expectations: Vec<Event>,
|
||||
time_limit: Tick,
|
||||
) {
|
||||
@ -53,7 +51,7 @@ impl Sim {
|
||||
if expectations.is_empty() {
|
||||
return;
|
||||
}
|
||||
for ev in self.step(&map, &control_map).into_iter() {
|
||||
for ev in self.step(&map).into_iter() {
|
||||
if ev == *expectations.front().unwrap() {
|
||||
info!("At {}, met expectation {:?}", self.time, ev);
|
||||
expectations.pop_front();
|
||||
|
@ -2,10 +2,9 @@
|
||||
|
||||
use abstutil;
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap, Error};
|
||||
use control::{ControlMap, ControlStopSign, TurnPriority};
|
||||
use dimensioned::si;
|
||||
use kinematics;
|
||||
use map_model::{IntersectionID, IntersectionType, Map, TurnID};
|
||||
use map_model::{ControlStopSign, IntersectionID, IntersectionType, Map, TurnID, TurnPriority};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use view::WorldView;
|
||||
use {AgentID, CarID, Event, PedestrianID, Tick, Time};
|
||||
@ -95,21 +94,12 @@ impl IntersectionSimState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step(
|
||||
&mut self,
|
||||
events: &mut Vec<Event>,
|
||||
time: Tick,
|
||||
map: &Map,
|
||||
control_map: &ControlMap,
|
||||
view: &WorldView,
|
||||
) {
|
||||
pub fn step(&mut self, events: &mut Vec<Event>, time: Tick, map: &Map, view: &WorldView) {
|
||||
for i in self.intersections.iter_mut() {
|
||||
match i {
|
||||
IntersectionPolicy::StopSignPolicy(ref mut p) => {
|
||||
p.step(events, time, map, control_map, view)
|
||||
}
|
||||
IntersectionPolicy::StopSignPolicy(ref mut p) => p.step(events, time, map, view),
|
||||
IntersectionPolicy::TrafficSignalPolicy(ref mut p) => {
|
||||
p.step(events, time, map, control_map, view)
|
||||
p.step(events, time, map, view)
|
||||
}
|
||||
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 {
|
||||
match self.intersections.get_mut(old.0).unwrap() {
|
||||
IntersectionPolicy::StopSignPolicy(ref mut p) => {
|
||||
@ -159,11 +149,11 @@ impl IntersectionSimState {
|
||||
match self.intersections.get_mut(id.0).unwrap() {
|
||||
IntersectionPolicy::StopSignPolicy(ref mut p) => {
|
||||
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) => {
|
||||
p.debug = true;
|
||||
println!("{}", abstutil::to_json(&control_map.traffic_signals[&id]));
|
||||
println!("{}", abstutil::to_json(map.get_traffic_signal(id)));
|
||||
}
|
||||
IntersectionPolicy::BorderPolicy => {
|
||||
println!("{} is a border", id);
|
||||
@ -254,15 +244,8 @@ impl StopSign {
|
||||
}).is_some()
|
||||
}
|
||||
|
||||
fn step(
|
||||
&mut self,
|
||||
events: &mut Vec<Event>,
|
||||
time: Tick,
|
||||
map: &Map,
|
||||
control_map: &ControlMap,
|
||||
view: &WorldView,
|
||||
) {
|
||||
let ss = &control_map.stop_signs[&self.id];
|
||||
fn step(&mut self, events: &mut Vec<Event>, time: Tick, map: &Map, view: &WorldView) {
|
||||
let ss = map.get_stop_sign(self.id);
|
||||
|
||||
// If anybody is stopped, promote them.
|
||||
// TODO retain() would rock
|
||||
@ -342,15 +325,8 @@ impl TrafficSignal {
|
||||
}
|
||||
}
|
||||
|
||||
fn step(
|
||||
&mut self,
|
||||
events: &mut Vec<Event>,
|
||||
time: Tick,
|
||||
map: &Map,
|
||||
control_map: &ControlMap,
|
||||
view: &WorldView,
|
||||
) {
|
||||
let signal = &control_map.traffic_signals[&self.id];
|
||||
fn step(&mut self, events: &mut Vec<Event>, time: Tick, map: &Map, view: &WorldView) {
|
||||
let signal = map.get_traffic_signal(self.id);
|
||||
let (cycle, _remaining_cycle_time) =
|
||||
signal.current_cycle_and_remaining_time(time.as_time());
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
extern crate abstutil;
|
||||
extern crate backtrace;
|
||||
extern crate control;
|
||||
#[macro_use]
|
||||
extern crate derivative;
|
||||
extern crate dimensioned;
|
||||
@ -58,7 +57,7 @@ pub use events::Event;
|
||||
pub use instrument::save_backtraces;
|
||||
pub use kinematics::VehicleType;
|
||||
pub use make::{
|
||||
load, ABTest, ABTestResults, BorderSpawnOverTime, MapEdits, Neighborhood, NeighborhoodBuilder,
|
||||
load, ABTest, ABTestResults, BorderSpawnOverTime, Neighborhood, NeighborhoodBuilder,
|
||||
OriginDestination, Scenario, SeedParkedCars, SimFlags, SpawnOverTime,
|
||||
};
|
||||
use map_model::{BuildingID, LaneID};
|
||||
@ -162,5 +161,4 @@ impl Cloneable for Neighborhood {}
|
||||
impl Cloneable for NeighborhoodBuilder {}
|
||||
impl Cloneable for Scenario {}
|
||||
impl Cloneable for Tick {}
|
||||
impl Cloneable for MapEdits {}
|
||||
impl Cloneable for ABTest {}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
use abstutil;
|
||||
use control::ControlMap;
|
||||
use map_model::Map;
|
||||
use {MapEdits, Scenario, Sim, Tick};
|
||||
use map_model::{Map, MapEdits};
|
||||
use {Scenario, Sim, Tick};
|
||||
|
||||
#[derive(StructOpt, Debug, Clone)]
|
||||
#[structopt(name = "sim_flags")]
|
||||
@ -44,7 +43,7 @@ pub fn load(
|
||||
flags: SimFlags,
|
||||
savestate_every: Option<Tick>,
|
||||
timer: &mut abstutil::Timer,
|
||||
) -> (Map, ControlMap, Sim) {
|
||||
) -> (Map, Sim) {
|
||||
if flags.load.contains("data/save/") {
|
||||
assert_eq!(flags.edits_name, "no_edits");
|
||||
|
||||
@ -54,7 +53,7 @@ pub fn load(
|
||||
timer.stop("read sim savestate");
|
||||
|
||||
let edits: MapEdits = if sim.edits_name == "no_edits" {
|
||||
MapEdits::new()
|
||||
MapEdits::new(&sim.map_name)
|
||||
} else {
|
||||
abstutil::read_json(&format!(
|
||||
"../data/edits/{}/{}.json",
|
||||
@ -68,12 +67,11 @@ pub fn load(
|
||||
timer,
|
||||
).unwrap_or_else(|_| {
|
||||
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))
|
||||
});
|
||||
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/") {
|
||||
info!("Seeding the simulation from scenario {}", flags.load);
|
||||
let scenario: Scenario = abstutil::read_json(&flags.load).expect("loading scenario failed");
|
||||
@ -88,10 +86,9 @@ pub fn load(
|
||||
timer,
|
||||
).unwrap_or_else(|_| {
|
||||
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))
|
||||
});
|
||||
let control_map = ControlMap::new(&map, edits.stop_signs, edits.traffic_signals);
|
||||
let mut sim = Sim::new(
|
||||
&map,
|
||||
// TODO or the scenario name if no run name
|
||||
@ -100,7 +97,7 @@ pub fn load(
|
||||
savestate_every,
|
||||
);
|
||||
scenario.instantiate(&mut sim, &map);
|
||||
(map, control_map, sim)
|
||||
(map, sim)
|
||||
} else if flags.load.contains("data/raw_maps/") {
|
||||
// TODO relative dir is brittle; match more cautiously
|
||||
let map_name = flags
|
||||
@ -110,30 +107,22 @@ pub fn load(
|
||||
.to_string();
|
||||
info!("Loading map {}", flags.load);
|
||||
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));
|
||||
let control_map = ControlMap::new(&map, edits.stop_signs, edits.traffic_signals);
|
||||
timer.start("create sim");
|
||||
let sim = Sim::new(&map, flags.run_name, flags.rng_seed, savestate_every);
|
||||
timer.stop("create sim");
|
||||
(map, control_map, sim)
|
||||
(map, sim)
|
||||
} else if flags.load.contains("data/maps/") {
|
||||
assert_eq!(flags.edits_name, "no_edits");
|
||||
|
||||
info!("Loading map {}", flags.load);
|
||||
let map: Map = abstutil::read_binary(&flags.load, timer)
|
||||
.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");
|
||||
let sim = Sim::new(&map, flags.run_name, flags.rng_seed, savestate_every);
|
||||
timer.stop("create sim");
|
||||
(map, control_map, sim)
|
||||
(map, sim)
|
||||
} else {
|
||||
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 {
|
||||
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") {
|
||||
panic!(
|
||||
|
@ -2,13 +2,11 @@
|
||||
// it.
|
||||
|
||||
mod a_b_test;
|
||||
mod edits;
|
||||
mod load;
|
||||
mod neighborhood;
|
||||
mod scenario;
|
||||
|
||||
pub use self::a_b_test::{ABTest, ABTestResults};
|
||||
pub use self::edits::MapEdits;
|
||||
pub use self::load::{load, SimFlags};
|
||||
pub use self::neighborhood::{Neighborhood, NeighborhoodBuilder};
|
||||
pub use self::scenario::{
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
use abstutil;
|
||||
use abstutil::Error;
|
||||
use control::ControlMap;
|
||||
use driving::DrivingSimState;
|
||||
use instrument::capture_backtrace;
|
||||
use intersections::IntersectionSimState;
|
||||
@ -77,7 +76,7 @@ impl Sim {
|
||||
transit_state: TransitSimState::new(),
|
||||
time: Tick::zero(),
|
||||
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,
|
||||
savestate_every,
|
||||
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,
|
||||
// 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 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
|
||||
// tick.
|
||||
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
|
||||
// then.
|
||||
@ -286,8 +285,8 @@ impl Sim {
|
||||
self.driving_state.toggle_debug(id);
|
||||
}
|
||||
|
||||
pub fn debug_intersection(&mut self, id: IntersectionID, control_map: &ControlMap) {
|
||||
self.intersection_state.debug(id, control_map);
|
||||
pub fn debug_intersection(&mut self, id: IntersectionID, map: &Map) {
|
||||
self.intersection_state.debug(id, map);
|
||||
}
|
||||
|
||||
pub fn save(&self) -> String {
|
||||
|
@ -35,12 +35,12 @@ pub fn run(t: &mut TestRunner) {
|
||||
Box::new(|_| {
|
||||
let map1 = map_model::Map::new(
|
||||
"../data/raw_maps/montlake.abst",
|
||||
map_model::RoadEdits::new(),
|
||||
map_model::MapEdits::new("montlake"),
|
||||
&mut abstutil::Timer::new("raw to map"),
|
||||
).unwrap();
|
||||
let map2 = map_model::Map::new(
|
||||
"../data/raw_maps/montlake.abst",
|
||||
map_model::RoadEdits::new(),
|
||||
map_model::MapEdits::new("montlake"),
|
||||
&mut abstutil::Timer::new("raw to map"),
|
||||
).unwrap();
|
||||
|
||||
|
@ -8,7 +8,7 @@ pub fn run(t: &mut TestRunner) {
|
||||
t.run_slow(
|
||||
"park_on_goal_st",
|
||||
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"),
|
||||
None,
|
||||
&mut Timer::new("setup test"),
|
||||
@ -28,21 +28,20 @@ pub fn run(t: &mut TestRunner) {
|
||||
|
||||
sim.run_until_expectations_met(
|
||||
&map,
|
||||
&control_map,
|
||||
vec![sim::Event::CarReachedParkingSpot(
|
||||
car,
|
||||
sim::ParkingSpot::new(north_parking, 4),
|
||||
)],
|
||||
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(
|
||||
"wander_around_for_parking",
|
||||
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"),
|
||||
None,
|
||||
&mut Timer::new("setup test"),
|
||||
@ -62,14 +61,13 @@ pub fn run(t: &mut TestRunner) {
|
||||
|
||||
sim.run_until_expectations_met(
|
||||
&map,
|
||||
&control_map,
|
||||
vec![sim::Event::CarReachedParkingSpot(
|
||||
car,
|
||||
sim::ParkingSpot::new(south_parking, 0),
|
||||
)],
|
||||
sim::Tick::from_minutes(2),
|
||||
);
|
||||
sim.run_until_done(&map, &control_map, Box::new(|_sim| {}));
|
||||
sim.run_until_done(&map, Box::new(|_sim| {}));
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -6,14 +6,14 @@ pub fn run(t: &mut TestRunner) {
|
||||
t.run_slow(
|
||||
"small_spawn_completes",
|
||||
Box::new(|h| {
|
||||
let (map, control_map, mut sim) = sim::load(
|
||||
let (map, mut sim) = sim::load(
|
||||
sim::SimFlags::for_test("aorta_model_completes"),
|
||||
Some(sim::Tick::from_seconds(30)),
|
||||
&mut Timer::new("setup test"),
|
||||
);
|
||||
sim.small_spawn(&map);
|
||||
h.setup_done(&sim);
|
||||
sim.run_until_done(&map, &control_map, Box::new(|_sim| {}));
|
||||
sim.run_until_done(&map, Box::new(|_sim| {}));
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ pub fn run(t: &mut TestRunner) {
|
||||
t.run_slow(
|
||||
"serialization",
|
||||
Box::new(|_| {
|
||||
let (map, _, mut sim) = sim::load(
|
||||
let (map, mut sim) = sim::load(
|
||||
sim::SimFlags::for_test("serialization"),
|
||||
None,
|
||||
&mut Timer::new("setup test"),
|
||||
@ -24,7 +24,7 @@ pub fn run(t: &mut TestRunner) {
|
||||
"from_scratch",
|
||||
Box::new(|_| {
|
||||
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"),
|
||||
None,
|
||||
&mut Timer::new("setup test"),
|
||||
@ -42,8 +42,8 @@ pub fn run(t: &mut TestRunner) {
|
||||
sim2.save()
|
||||
);
|
||||
}
|
||||
sim1.step(&map, &control_map);
|
||||
sim2.step(&map, &control_map);
|
||||
sim1.step(&map);
|
||||
sim2.step(&map);
|
||||
}
|
||||
}),
|
||||
);
|
||||
@ -52,7 +52,7 @@ pub fn run(t: &mut TestRunner) {
|
||||
"with_savestating",
|
||||
Box::new(|_| {
|
||||
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"),
|
||||
None,
|
||||
&mut Timer::new("setup test"),
|
||||
@ -62,8 +62,8 @@ pub fn run(t: &mut TestRunner) {
|
||||
sim2.small_spawn(&map);
|
||||
|
||||
for _ in 1..600 {
|
||||
sim1.step(&map, &control_map);
|
||||
sim2.step(&map, &control_map);
|
||||
sim1.step(&map);
|
||||
sim2.step(&map);
|
||||
}
|
||||
|
||||
if sim1 != sim2 {
|
||||
@ -77,7 +77,7 @@ pub fn run(t: &mut TestRunner) {
|
||||
let sim1_save = sim1.save();
|
||||
|
||||
for _ in 1..60 {
|
||||
sim1.step(&map, &control_map);
|
||||
sim1.step(&map);
|
||||
}
|
||||
|
||||
if sim1 == sim2 {
|
||||
|
@ -7,7 +7,7 @@ pub fn run(t: &mut TestRunner) {
|
||||
t.run_slow(
|
||||
"bus_reaches_stops",
|
||||
Box::new(|h| {
|
||||
let (map, control_map, mut sim) = sim::load(
|
||||
let (map, mut sim) = sim::load(
|
||||
SimFlags::for_test("bus_reaches_stops"),
|
||||
Some(Tick::from_seconds(30)),
|
||||
&mut Timer::new("setup test"),
|
||||
@ -24,20 +24,15 @@ pub fn run(t: &mut TestRunner) {
|
||||
expectations.push(Event::BusDepartedFromStop(bus, *stop));
|
||||
}
|
||||
|
||||
sim.run_until_expectations_met(
|
||||
&map,
|
||||
&control_map,
|
||||
expectations,
|
||||
Tick::from_minutes(10),
|
||||
);
|
||||
sim.run_until_done(&map, &control_map, Box::new(|_sim| {}));
|
||||
sim.run_until_expectations_met(&map, expectations, Tick::from_minutes(10));
|
||||
sim.run_until_done(&map, Box::new(|_sim| {}));
|
||||
}),
|
||||
);
|
||||
|
||||
t.run_slow(
|
||||
"ped_uses_bus",
|
||||
Box::new(|h| {
|
||||
let (map, control_map, mut sim) = sim::load(
|
||||
let (map, mut sim) = sim::load(
|
||||
SimFlags::for_test("ped_uses_bus"),
|
||||
Some(Tick::from_seconds(30)),
|
||||
&mut Timer::new("setup test"),
|
||||
@ -56,7 +51,6 @@ pub fn run(t: &mut TestRunner) {
|
||||
|
||||
sim.run_until_expectations_met(
|
||||
&map,
|
||||
&control_map,
|
||||
vec![
|
||||
sim::Event::PedReachedBusStop(ped, ped_stop1),
|
||||
sim::Event::BusArrivedAtStop(bus, ped_stop1),
|
||||
|
Loading…
Reference in New Issue
Block a user