mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 23:15:24 +03:00
modeling border nodes in map, control, sim, editor layers
This commit is contained in:
parent
f243048c45
commit
474d92f5db
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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};
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user