mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 12:12:00 +03:00
gracefully degrade if we cant make TurnGroups for a traffic signal. this
gets SF, Tokyo, and London to import!!!
This commit is contained in:
parent
7a0dbb28b1
commit
3b49353df2
@ -221,8 +221,12 @@ pub fn snap_bus_stops(
|
|||||||
for idx in (0..idx_in_route).rev() {
|
for idx in (0..idx_in_route).rev() {
|
||||||
let (i, pt) = route.all_pts[idx];
|
let (i, pt) = route.all_pts[idx];
|
||||||
if !raw.intersections.contains_key(&i) {
|
if !raw.intersections.contains_key(&i) {
|
||||||
found = Some(pt_to_road[&pt.to_hashable()]);
|
if let Some(r) = pt_to_road.get(&pt.to_hashable()) {
|
||||||
break;
|
found = Some(*r);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
return Err(format!("Some point on the route isn't even on a road?!"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(r) = found {
|
if let Some(r) = found {
|
||||||
|
@ -9,7 +9,7 @@ pub struct Line(Pt2D, Pt2D);
|
|||||||
|
|
||||||
impl Line {
|
impl Line {
|
||||||
pub fn new(pt1: Pt2D, pt2: Pt2D) -> Option<Line> {
|
pub fn new(pt1: Pt2D, pt2: Pt2D) -> Option<Line> {
|
||||||
if pt1.dist_to(pt2) < EPSILON_DIST {
|
if pt1.dist_to(pt2) <= EPSILON_DIST {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(Line(pt1, pt2))
|
Some(Line(pt1, pt2))
|
||||||
|
@ -120,7 +120,7 @@ impl Ring {
|
|||||||
for pt in pts.iter().cloned() {
|
for pt in pts.iter().cloned() {
|
||||||
current.push(pt);
|
current.push(pt);
|
||||||
if intersections.contains(&pt.to_hashable()) && current.len() > 1 {
|
if intersections.contains(&pt.to_hashable()) && current.len() > 1 {
|
||||||
if current[0] == pt {
|
if current[0] == pt && current.len() >= 3 {
|
||||||
rings.push(Ring::must_new(current.drain(..).collect()));
|
rings.push(Ring::must_new(current.drain(..).collect()));
|
||||||
} else {
|
} else {
|
||||||
polylines.push(PolyLine::new(current.drain(..).collect())?);
|
polylines.push(PolyLine::new(current.drain(..).collect())?);
|
||||||
|
@ -13,7 +13,7 @@ use crate::raw::{OriginalIntersection, OriginalRoad, RawMap};
|
|||||||
use crate::{
|
use crate::{
|
||||||
connectivity, osm, Area, AreaID, ControlStopSign, ControlTrafficSignal, Intersection,
|
connectivity, osm, Area, AreaID, ControlStopSign, ControlTrafficSignal, Intersection,
|
||||||
IntersectionID, IntersectionType, Lane, LaneID, Map, MapEdits, PathConstraints, Position, Road,
|
IntersectionID, IntersectionType, Lane, LaneID, Map, MapEdits, PathConstraints, Position, Road,
|
||||||
RoadID, Zone,
|
RoadID, TurnGroup, Zone,
|
||||||
};
|
};
|
||||||
use abstutil::{Parallelism, Timer};
|
use abstutil::{Parallelism, Timer};
|
||||||
use enumset::EnumSet;
|
use enumset::EnumSet;
|
||||||
@ -141,7 +141,9 @@ impl Map {
|
|||||||
}
|
}
|
||||||
// TODO Maybe easier to use the road's "yellow center line" and shift left/right from
|
// TODO Maybe easier to use the road's "yellow center line" and shift left/right from
|
||||||
// there.
|
// there.
|
||||||
let road_left_pts = map.must_left_shift(road.center_pts.clone(), r.half_width);
|
let road_left_pts = map
|
||||||
|
.left_shift(road.center_pts.clone(), r.half_width)
|
||||||
|
.unwrap_or_else(|_| road.center_pts.clone());
|
||||||
|
|
||||||
let mut fwd_width_so_far = Distance::ZERO;
|
let mut fwd_width_so_far = Distance::ZERO;
|
||||||
let mut back_width_so_far = Distance::ZERO;
|
let mut back_width_so_far = Distance::ZERO;
|
||||||
@ -306,14 +308,28 @@ impl Map {
|
|||||||
IntersectionType::StopSign => {
|
IntersectionType::StopSign => {
|
||||||
stop_signs.insert(i.id, ControlStopSign::new(&map, i.id));
|
stop_signs.insert(i.id, ControlStopSign::new(&map, i.id));
|
||||||
}
|
}
|
||||||
IntersectionType::TrafficSignal => {
|
IntersectionType::TrafficSignal => match TurnGroup::for_i(i.id, &map) {
|
||||||
traffic_signals.insert(i.id, ControlTrafficSignal::new(&map, i.id, timer));
|
Ok(_) => {
|
||||||
}
|
traffic_signals.insert(i.id, ControlTrafficSignal::new(&map, i.id, timer));
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
timer.error(format!(
|
||||||
|
"Traffic signal at {} downgraded to stop sign because of weird \
|
||||||
|
problem: {}",
|
||||||
|
i.orig_id, err
|
||||||
|
));
|
||||||
|
stop_signs.insert(i.id, ControlStopSign::new(&map, i.id));
|
||||||
|
}
|
||||||
|
},
|
||||||
IntersectionType::Border | IntersectionType::Construction => {}
|
IntersectionType::Border | IntersectionType::Construction => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
map.stop_signs = stop_signs;
|
map.stop_signs = stop_signs;
|
||||||
map.traffic_signals = traffic_signals;
|
map.traffic_signals = traffic_signals;
|
||||||
|
// Fix up the type for any problematic traffic signals
|
||||||
|
for i in map.stop_signs.keys() {
|
||||||
|
map.intersections[i.0].intersection_type = IntersectionType::StopSign;
|
||||||
|
}
|
||||||
|
|
||||||
traffic_signals::synchronize(&mut map);
|
traffic_signals::synchronize(&mut map);
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ fn new(id: IntersectionID, map: &Map) -> ControlTrafficSignal {
|
|||||||
id,
|
id,
|
||||||
phases: Vec::new(),
|
phases: Vec::new(),
|
||||||
offset: Duration::ZERO,
|
offset: Duration::ZERO,
|
||||||
turn_groups: TurnGroup::for_i(id, map),
|
turn_groups: TurnGroup::for_i(id, map).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,6 +428,7 @@ fn make_phases(
|
|||||||
|
|
||||||
pub fn brute_force(map: &Map, i: IntersectionID) {
|
pub fn brute_force(map: &Map, i: IntersectionID) {
|
||||||
let turn_groups: Vec<TurnGroup> = TurnGroup::for_i(i, map)
|
let turn_groups: Vec<TurnGroup> = TurnGroup::for_i(i, map)
|
||||||
|
.unwrap()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(id, tg)| if id.crosswalk { None } else { Some(tg) })
|
.filter_map(|(id, tg)| if id.crosswalk { None } else { Some(tg) })
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -306,7 +306,7 @@ impl ControlTrafficSignal {
|
|||||||
id,
|
id,
|
||||||
phases,
|
phases,
|
||||||
offset: Duration::seconds(raw.offset_seconds as f64),
|
offset: Duration::seconds(raw.offset_seconds as f64),
|
||||||
turn_groups: TurnGroup::for_i(id, map),
|
turn_groups: TurnGroup::for_i(id, map).unwrap(),
|
||||||
}
|
}
|
||||||
.validate()
|
.validate()
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,10 @@ pub struct TurnGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TurnGroup {
|
impl TurnGroup {
|
||||||
pub(crate) fn for_i(i: IntersectionID, map: &Map) -> BTreeMap<TurnGroupID, TurnGroup> {
|
pub(crate) fn for_i(
|
||||||
|
i: IntersectionID,
|
||||||
|
map: &Map,
|
||||||
|
) -> Result<BTreeMap<TurnGroupID, TurnGroup>, Box<dyn Error>> {
|
||||||
let mut results = BTreeMap::new();
|
let mut results = BTreeMap::new();
|
||||||
let mut groups: MultiMap<(DirectedRoadID, DirectedRoadID), TurnID> = MultiMap::new();
|
let mut groups: MultiMap<(DirectedRoadID, DirectedRoadID), TurnID> = MultiMap::new();
|
||||||
for turn in map.get_turns_in_intersection(i) {
|
for turn in map.get_turns_in_intersection(i) {
|
||||||
@ -233,11 +236,7 @@ impl TurnGroup {
|
|||||||
members.iter().map(|t| &map.get_t(*t).geom).collect(),
|
members.iter().map(|t| &map.get_t(*t).geom).collect(),
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
)
|
)?;
|
||||||
.expect(&format!(
|
|
||||||
"Weird turn group geometry near {}",
|
|
||||||
map.get_i(i).orig_id
|
|
||||||
));
|
|
||||||
let turn_types: BTreeSet<TurnType> =
|
let turn_types: BTreeSet<TurnType> =
|
||||||
members.iter().map(|t| map.get_t(*t).turn_type).collect();
|
members.iter().map(|t| map.get_t(*t).turn_type).collect();
|
||||||
if turn_types.len() > 1 {
|
if turn_types.len() > 1 {
|
||||||
@ -265,9 +264,11 @@ impl TurnGroup {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if results.is_empty() {
|
if results.is_empty() {
|
||||||
panic!("{} has no TurnGroups!", map.get_i(i).orig_id);
|
return Err(
|
||||||
|
format!("No TurnGroups! Does the intersection have at least 2 roads?").into(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
results
|
Ok(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Polyline points FROM intersection
|
// Polyline points FROM intersection
|
||||||
|
Loading…
Reference in New Issue
Block a user