Make editing maps with transit stops a little more resilient. #372

Transit stop IDs previously were tied to LaneIDs, but those can easily
change with edits to the number of lanes on a road. We still may need to
re-snap transit stops (if the driving position or sidewalk changes), but
this prevents one more common type of problem.

This requires regenerating everything, since it's a binary schema
change...
This commit is contained in:
Dustin Carlino 2022-02-17 20:18:24 +00:00
parent 0dc8972187
commit 6a5366292f
11 changed files with 31 additions and 34 deletions

View File

@ -1,10 +1,13 @@
#!/bin/bash
# TODO It's probably more useful to now manually run commands from this file.
set -e
rm -fv data/input/us/seattle/raw_maps/huge_seattle.bin data/system/us/seattle/maps/huge_seattle.bin data/input/us/seattle/popdat.bin
RUST_BACKTRACE=1 cargo run --release --bin cli --features importer/scenarios -- regenerate-everything
# Or more efficiently:
# ./target/release/cli regenerate-everything-externally
# If a map changes that has external JSON scenarios, enable this!
# importer/external_scenarios.sh

View File

@ -388,13 +388,13 @@ impl App {
let road = draw_map.get_r(id);
for lane in &road.lanes {
agents_on.push(Traversable::Lane(lane.id));
for ts in &map.get_l(lane.id).transit_stops {
if show_objs.show(&ID::TransitStop(*ts)) {
transit_stops.push(draw_map.get_ts(*ts));
}
}
lanes.push(lane);
}
for ts in &map.get_r(id).transit_stops {
if show_objs.show(&ID::TransitStop(*ts)) {
transit_stops.push(draw_map.get_ts(*ts));
}
}
roads.push(road);
}
ID::Intersection(id) => {

View File

@ -378,11 +378,11 @@ impl DrawMap {
ID::Road(id) => {
let road = self.get_r(id);
for lane in &road.lanes {
for ts in &map.get_l(lane.id).transit_stops {
transit_stops.push(self.get_ts(*ts));
}
lanes.push(lane);
}
for ts in &map.get_r(id).transit_stops {
transit_stops.push(self.get_ts(*ts));
}
roads.push(road);
}
ID::Intersection(id) => {

View File

@ -905,7 +905,7 @@ impl Map {
// Might need to update bus stops.
if enforce_valid {
for id in &effects.changed_roads {
let stops = self.get_r(*id).all_transit_stops();
let stops = self.get_r(*id).transit_stops.clone();
for s in stops {
let sidewalk_pos = self.get_ts(s).sidewalk_pos;
// Must exist, because we aren't allowed to orphan a bus stop.

View File

@ -1,7 +1,7 @@
//! See <https://a-b-street.github.io/docs/tech/map/importing/index.html> for an overview. This module
//! covers the RawMap->Map stage.
use std::collections::{BTreeMap, HashMap, HashSet};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use structopt::StructOpt;
@ -155,6 +155,7 @@ impl Map {
percent_incline: raw_road.percent_incline,
crosswalk_forward: raw_road.crosswalk_forward,
crosswalk_backward: raw_road.crosswalk_backward,
transit_stops: BTreeSet::new(),
};
road.speed_limit = road.speed_limit_from_osm();
road.access_restrictions = road.access_restrictions_from_osm();

View File

@ -62,11 +62,12 @@ fn create_stop(
.find_closest_lane(sidewalk_lane, |l| vehicle.can_use(l, map))
.map(|l| sidewalk_pos.equiv_pos(l, map))
{
let road = sidewalk_lane.road;
let id = TransitStopID {
sidewalk: sidewalk_lane,
idx: map.get_l(sidewalk_lane).transit_stops.len(),
road,
idx: map.get_r(road).transit_stops.len(),
};
map.mut_lane(sidewalk_lane).transit_stops.insert(id);
map.mut_road(road).transit_stops.insert(id);
map.transit_stops.insert(
id,
TransitStop {

View File

@ -282,6 +282,9 @@ impl Map {
pub(crate) fn mut_lane(&mut self, id: LaneID) -> &mut Lane {
&mut self.roads[id.road.0].lanes[id.offset]
}
pub(crate) fn mut_road(&mut self, id: RoadID) -> &mut Road {
&mut self.roads[id.0]
}
pub fn get_i(&self, id: IntersectionID) -> &Intersection {
&self.intersections[id.0]
@ -899,9 +902,7 @@ impl Map {
self.transit_stops.clear();
self.transit_routes.clear();
for r in &mut self.roads {
for l in &mut r.lanes {
l.transit_stops.clear();
}
r.transit_stops.clear();
}
}
}

View File

@ -8,7 +8,7 @@ use geom::{Distance, Line, PolyLine, Polygon, Pt2D};
use crate::{
osm, DirectedRoadID, Direction, DrivingSide, IntersectionID, Map, MapConfig, Road, RoadID,
RoadSideID, SideOfRoad, TransitStopID, TurnType,
RoadSideID, SideOfRoad, TurnType,
};
/// From some manually audited cases in Seattle, the length of parallel street parking spots is a
@ -247,9 +247,6 @@ pub struct Lane {
pub src_i: IntersectionID,
pub dst_i: IntersectionID,
/// Meaningless order
pub transit_stops: BTreeSet<TransitStopID>,
/// {Cars, bikes} trying to start or end here might not be able to reach most lanes in the
/// graph, because this is near a border.
pub driving_blackhole: bool,

View File

@ -196,6 +196,9 @@ pub struct Road {
/// Is there a tagged crosswalk near each end of the road?
pub crosswalk_forward: bool,
pub crosswalk_backward: bool,
/// Meaningless order
pub transit_stops: BTreeSet<TransitStopID>,
}
impl Road {
@ -423,14 +426,6 @@ impl Road {
.unwrap_or(0)
}
pub fn all_transit_stops(&self) -> Vec<TransitStopID> {
self.lanes
.iter()
.flat_map(|l| l.transit_stops.iter())
.cloned()
.collect()
}
pub fn is_light_rail(&self) -> bool {
self.lanes.len() == 1 && self.lanes[0].lane_type == LaneType::LightRail
}
@ -589,7 +584,6 @@ impl Road {
dst_i,
lane_type: lane.lt,
dir: lane.dir,
transit_stops: BTreeSet::new(),
driving_blackhole: false,
biking_blackhole: false,
});

View File

@ -7,19 +7,19 @@ use serde::{Deserialize, Serialize};
use abstutil::{deserialize_usize, serialize_usize};
use geom::Time;
use crate::{LaneID, Map, PathConstraints, PathRequest, Position};
use crate::{LaneID, Map, PathConstraints, PathRequest, Position, RoadID};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct TransitStopID {
pub sidewalk: LaneID,
/// As long as this is unique per lane, this value is otherwise meaningless. Not contiguous or
pub road: RoadID,
/// As long as this is unique per road, this value is otherwise meaningless. Not contiguous or
/// ordered in any way.
pub(crate) idx: usize,
}
impl fmt::Display for TransitStopID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "TransitStopID({0}, {1})", self.sidewalk, self.idx)
write!(f, "TransitStopID({0}, {1})", self.road, self.idx)
}
}

View File

@ -4,7 +4,7 @@
"scenario": "weekday",
"finished_trips": 76640,
"cancelled_trips": 0,
"total_trip_duration_seconds": 44010529.93400101
"total_trip_duration_seconds": 43735836.876801066
},
{
"map": "montlake (in seattle (us))",