modeling border nodes in map, control, sim, editor layers

This commit is contained in:
Dustin Carlino 2018-11-11 14:33:01 -08:00
parent f243048c45
commit 474d92f5db
11 changed files with 106 additions and 45 deletions

View File

@ -14,7 +14,7 @@ mod macros;
mod stop_signs;
mod traffic_signals;
use map_model::{IntersectionID, Map};
use map_model::{IntersectionID, IntersectionType, Map};
use std::collections::{BTreeMap, HashMap};
pub use stop_signs::{ControlStopSign, TurnPriority};
pub use traffic_signals::ControlTrafficSignal;
@ -23,6 +23,7 @@ pub use traffic_signals::ControlTrafficSignal;
pub struct ControlMap {
pub traffic_signals: HashMap<IntersectionID, ControlTrafficSignal>,
pub stop_signs: HashMap<IntersectionID, ControlStopSign>,
// Note that border nodes belong in neither!
}
impl ControlMap {
@ -37,13 +38,17 @@ impl ControlMap {
};
for i in map.all_intersections() {
if i.has_traffic_signal {
ctrl.traffic_signals
.insert(i.id, ControlTrafficSignal::new(map, i.id));
} else {
ctrl.stop_signs
.insert(i.id, ControlStopSign::new(map, i.id));
}
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() {

View File

@ -31,7 +31,6 @@ pub struct ControlStopSign {
impl ControlStopSign {
pub fn new(map: &Map, intersection: IntersectionID) -> ControlStopSign {
assert!(!map.get_i(intersection).has_traffic_signal);
let ss = ControlStopSign::smart_assignment(map, intersection);
ss.validate(map, intersection).unwrap();
ss

View File

@ -17,7 +17,6 @@ pub struct ControlTrafficSignal {
impl ControlTrafficSignal {
pub fn new(map: &Map, intersection: IntersectionID) -> ControlTrafficSignal {
assert!(map.get_i(intersection).has_traffic_signal);
ControlTrafficSignal {
intersection,
cycles: greedy_assignment(map, intersection),

View File

@ -283,4 +283,12 @@ can begin or end.
- draw the FSM for cars/peds
- trips starting/ending at border nodes short-circuit some steps
What about border nodes where the sidewalk can cross over, but the driving lane leads nowhere?
What about border nodes where the sidewalk can cross over, but the driving lane
leads nowhere? Maybe instead of having a special intersection policy, we have
turns to nowhere? Sort of depends how the border node is defined -- do we have
long skinny things jutting out, or not?
- don't add any turns, even if we could
OK, now adapt the control and sim layers to handle border nodes...
Adapt trips / pathfinding. It has to be an explicit origin/goal.

View File

@ -3,7 +3,7 @@
use dimensioned::si;
use ezgui::{Color, GfxCtx};
use geom::{Angle, Bounds, Circle, Line, Polygon, Pt2D};
use map_model::{Intersection, IntersectionID, Map, TurnType, LANE_THICKNESS};
use map_model::{Intersection, IntersectionID, IntersectionType, Map, TurnType, LANE_THICKNESS};
use objects::{Ctx, ID};
use render::{RenderOptions, Renderable};
use sim::Sim;
@ -18,8 +18,7 @@ pub struct DrawIntersection {
crosswalks: Vec<Vec<Line>>,
sidewalk_corners: Vec<Polygon>,
center: Pt2D,
has_traffic_signal: bool,
is_border: bool,
intersection_type: IntersectionType,
should_draw_stop_sign: bool,
}
@ -36,9 +35,9 @@ impl DrawIntersection {
polygon: Polygon::new(&inter.polygon),
crosswalks: calculate_crosswalks(inter.id, map),
sidewalk_corners: calculate_corners(inter.id, map),
has_traffic_signal: inter.has_traffic_signal,
is_border: inter.is_border(map),
should_draw_stop_sign: !inter.has_traffic_signal && !inter.is_degenerate(),
intersection_type: inter.intersection_type,
should_draw_stop_sign: inter.intersection_type == IntersectionType::StopSign
&& !inter.is_degenerate(),
}
}
@ -87,7 +86,7 @@ impl Renderable for DrawIntersection {
fn draw(&self, g: &mut GfxCtx, opts: RenderOptions, ctx: Ctx) {
let color = opts.color.unwrap_or_else(|| {
if self.is_border {
if self.intersection_type == IntersectionType::Border {
return ctx.cs.get("border intersection", Color::rgb(50, 205, 50));
}
@ -121,7 +120,7 @@ impl Renderable for DrawIntersection {
g.draw_polygon(ctx.cs.get("sidewalk corner", Color::grey(0.7)), corner);
}
if self.has_traffic_signal {
if self.intersection_type == IntersectionType::TrafficSignal {
self.draw_traffic_signal(g, ctx);
} else if self.should_draw_stop_sign {
self.draw_stop_sign(g, ctx);

View File

@ -5,7 +5,9 @@ use control::ControlMap;
use dimensioned::si;
use ezgui::{Color, GfxCtx, Text};
use geom::{Bounds, Circle, Line, Polygon, Pt2D};
use map_model::{Lane, LaneID, LaneType, Map, Road, LANE_THICKNESS, PARKING_SPOT_LENGTH};
use map_model::{
IntersectionType, Lane, LaneID, LaneType, Map, Road, LANE_THICKNESS, PARKING_SPOT_LENGTH,
};
use objects::{Ctx, ID};
use render::{RenderOptions, Renderable, BIG_ARROW_THICKNESS, PARCEL_BOUNDARY_THICKNESS};
use sim::Sim;
@ -63,7 +65,9 @@ impl DrawLane {
}
LaneType::Biking => {}
};
if lane.is_driving() && !map.get_i(lane.dst_i).has_traffic_signal {
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) {
markings.push(m);
}

View File

@ -5,7 +5,7 @@ use dimensioned::si;
use geom::Pt2D;
use std::collections::BTreeSet;
use std::fmt;
use {LaneID, Map, RoadID, TurnID};
use {LaneID, RoadID, TurnID};
// TODO reconsider pub usize. maybe outside world shouldnt know.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
@ -17,6 +17,13 @@ impl fmt::Display for IntersectionID {
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum IntersectionType {
StopSign,
TrafficSignal,
Border,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Intersection {
pub id: IntersectionID,
@ -26,7 +33,8 @@ pub struct Intersection {
pub polygon: Vec<Pt2D>,
pub turns: Vec<TurnID>,
pub elevation: si::Meter<f64>,
pub has_traffic_signal: bool,
pub intersection_type: IntersectionType,
// Note that a lane may belong to both incoming_lanes and outgoing_lanes.
// TODO narrow down when and why. is it just sidewalks in weird cases?
@ -51,16 +59,6 @@ impl Intersection {
self.roads.len() == 2
}
pub fn is_border(&self, map: &Map) -> bool {
// Bias for driving
if !self.is_dead_end() {
return false;
}
let has_driving_in = self.incoming_lanes.iter().find(|l| map.get_l(**l).is_driving()).is_some();
let has_driving_out = self.outgoing_lanes.iter().find(|l| map.get_l(**l).is_driving()).is_some();
has_driving_in != has_driving_out
}
pub fn dump_debug(&self) {
println!("{}", abstutil::to_json(self));
}

View File

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

View File

@ -3,10 +3,15 @@ use geom::{Angle, Line};
use std::collections::{BTreeSet, HashSet};
use std::iter;
use {
Intersection, IntersectionID, Lane, LaneID, LaneType, Map, Road, RoadID, Turn, TurnID, TurnType,
Intersection, IntersectionID, IntersectionType, Lane, LaneID, LaneType, Map, Road, RoadID,
Turn, TurnID, TurnType,
};
pub fn make_all_turns(i: &Intersection, map: &Map) -> Vec<Turn> {
if i.intersection_type == IntersectionType::Border {
return Vec::new();
}
let mut turns: Vec<Turn> = Vec::new();
turns.extend(make_vehicle_turns(i, map));
turns.extend(make_walking_turns(i, map));

View File

@ -11,7 +11,8 @@ use std::io;
use std::path;
use {
Area, AreaID, Building, BuildingID, BusRoute, BusStop, BusStopID, Intersection, IntersectionID,
Lane, LaneID, LaneType, Parcel, ParcelID, Road, RoadID, Turn, TurnID, LANE_THICKNESS,
IntersectionType, Lane, LaneID, LaneType, Parcel, ParcelID, Road, RoadID, Turn, TurnID,
LANE_THICKNESS,
};
#[derive(Serialize, Deserialize, Debug)]
@ -92,7 +93,12 @@ impl Map {
polygon: Vec::new(),
turns: Vec::new(),
elevation: i.elevation,
has_traffic_signal: i.has_traffic_signal,
// Might change later
intersection_type: if i.has_traffic_signal {
IntersectionType::TrafficSignal
} else {
IntersectionType::StopSign
},
incoming_lanes: Vec::new(),
outgoing_lanes: Vec::new(),
roads: BTreeSet::new(),
@ -196,6 +202,13 @@ impl Map {
make::trim_lines(&mut m.lanes, i);
}
for i in 0..m.intersections.len() {
// Is the intersection a border?
if is_border(&m.intersections[i], &m) {
m.intersections[i].intersection_type = IntersectionType::Border;
}
}
let (stops, routes) = make::make_bus_stops(
&mut m.lanes,
&m.roads,
@ -516,3 +529,21 @@ impl Map {
info!("Saved {}", path);
}
}
fn is_border(intersection: &Intersection, map: &Map) -> bool {
// Bias for driving
if !intersection.is_dead_end() {
return false;
}
let has_driving_in = intersection
.incoming_lanes
.iter()
.find(|l| map.get_l(**l).is_driving())
.is_some();
let has_driving_out = intersection
.outgoing_lanes
.iter()
.find(|l| map.get_l(**l).is_driving())
.is_some();
has_driving_in != has_driving_out
}

View File

@ -5,7 +5,7 @@ use abstutil::{deserialize_btreemap, serialize_btreemap, Error};
use control::{ControlMap, ControlStopSign, TurnPriority};
use dimensioned::si;
use kinematics;
use map_model::{IntersectionID, Map, TurnID};
use map_model::{IntersectionID, IntersectionType, Map, TurnID};
use std::collections::{BTreeMap, BTreeSet};
use view::WorldView;
use {AgentID, CarID, Event, PedestrianID, Tick, Time};
@ -50,13 +50,15 @@ impl IntersectionSimState {
pub fn new(map: &Map) -> IntersectionSimState {
let mut intersections: Vec<IntersectionPolicy> = Vec::new();
for i in map.all_intersections() {
if i.has_traffic_signal {
intersections.push(IntersectionPolicy::TrafficSignalPolicy(TrafficSignal::new(
i.id,
)));
} else {
intersections.push(IntersectionPolicy::StopSignPolicy(StopSign::new(i.id)));
}
intersections.push(match i.intersection_type {
IntersectionType::StopSign => {
IntersectionPolicy::StopSignPolicy(StopSign::new(i.id))
}
IntersectionType::TrafficSignal => {
IntersectionPolicy::TrafficSignalPolicy(TrafficSignal::new(i.id))
}
IntersectionType::Border => IntersectionPolicy::BorderPolicy,
});
}
IntersectionSimState {
intersections,
@ -89,6 +91,7 @@ impl IntersectionSimState {
IntersectionPolicy::TrafficSignalPolicy(ref mut p) => {
p.requests.insert(req);
}
IntersectionPolicy::BorderPolicy => {}
}
}
@ -108,6 +111,7 @@ impl IntersectionSimState {
IntersectionPolicy::TrafficSignalPolicy(ref mut p) => {
p.step(events, time, control_map, view)
}
IntersectionPolicy::BorderPolicy => {}
}
}
}
@ -147,6 +151,7 @@ impl IntersectionSimState {
IntersectionPolicy::TrafficSignalPolicy(ref mut p) => {
p.debug = false;
}
IntersectionPolicy::BorderPolicy => {}
};
}
@ -160,6 +165,9 @@ impl IntersectionSimState {
p.debug = true;
println!("{}", abstutil::to_json(&control_map.traffic_signals[&id]));
}
IntersectionPolicy::BorderPolicy => {
println!("{} is a border", id);
}
};
}
}
@ -169,6 +177,7 @@ impl IntersectionSimState {
enum IntersectionPolicy {
StopSignPolicy(StopSign),
TrafficSignalPolicy(TrafficSignal),
BorderPolicy,
}
impl IntersectionPolicy {
@ -176,6 +185,7 @@ impl IntersectionPolicy {
match self {
IntersectionPolicy::StopSignPolicy(ref p) => p.accepted.contains(req),
IntersectionPolicy::TrafficSignalPolicy(ref p) => p.accepted.contains(req),
IntersectionPolicy::BorderPolicy => true,
}
}
@ -183,6 +193,9 @@ impl IntersectionPolicy {
match self {
IntersectionPolicy::StopSignPolicy(ref mut p) => p.accepted.remove(&req),
IntersectionPolicy::TrafficSignalPolicy(ref mut p) => p.accepted.remove(&req),
IntersectionPolicy::BorderPolicy => {
panic!("{:?} called on_exit for a border node; how?!", req);
}
};
}
}