Use more realistic lane widths during importing. #597

This commit is contained in:
Dustin Carlino 2021-05-03 11:06:18 -07:00
parent 5a86a7cef1
commit 1bcbe057f0
5 changed files with 49 additions and 411 deletions

View File

@ -531,8 +531,8 @@ fn width_choices(app: &App, l: LaneID) -> Vec<Choice<Distance>> {
LaneSpec::typical_lane_widths(lane.lane_type, &app.primary.map.get_r(lane.parent).osm_tags); LaneSpec::typical_lane_widths(lane.lane_type, &app.primary.map.get_r(lane.parent).osm_tags);
if !choices.iter().any(|(x, _)| *x == lane.width) { if !choices.iter().any(|(x, _)| *x == lane.width) {
choices.push((lane.width, "custom")); choices.push((lane.width, "custom"));
choices.sort();
} }
choices.sort();
choices choices
.into_iter() .into_iter()
.map(|(x, label)| Choice::new(format!("{} - {}", x.to_string(&app.opts.units), label), x)) .map(|(x, label)| Choice::new(format!("{} - {}", x.to_string(&app.opts.units), label), x))

View File

@ -32,7 +32,7 @@ use serde::{Deserialize, Serialize};
use abstio::MapName; use abstio::MapName;
use abstutil::{deserialize_btreemap, serialize_btreemap}; use abstutil::{deserialize_btreemap, serialize_btreemap};
use geom::{Bounds, Distance, GPSBounds, Polygon}; use geom::{Bounds, GPSBounds, Polygon};
pub use crate::city::City; pub use crate::city::City;
pub use crate::edits::{ pub use crate::edits::{
@ -46,7 +46,10 @@ pub use crate::objects::building::{
}; };
pub use crate::objects::bus_stop::{BusRoute, BusRouteID, BusStop, BusStopID}; pub use crate::objects::bus_stop::{BusRoute, BusRouteID, BusStop, BusStopID};
pub use crate::objects::intersection::{Intersection, IntersectionID, IntersectionType}; pub use crate::objects::intersection::{Intersection, IntersectionID, IntersectionType};
pub use crate::objects::lane::{Lane, LaneID, LaneSpec, LaneType, PARKING_LOT_SPOT_LENGTH}; pub use crate::objects::lane::{
Lane, LaneID, LaneSpec, LaneType, NORMAL_LANE_THICKNESS, PARKING_LOT_SPOT_LENGTH,
SIDEWALK_THICKNESS,
};
pub use crate::objects::parking_lot::{ParkingLot, ParkingLotID}; pub use crate::objects::parking_lot::{ParkingLot, ParkingLotID};
pub use crate::objects::road::{DirectedRoadID, Direction, Road, RoadID}; pub use crate::objects::road::{DirectedRoadID, Direction, Road, RoadID};
pub use crate::objects::stop_signs::{ControlStopSign, RoadWithStopSign}; pub use crate::objects::stop_signs::{ControlStopSign, RoadWithStopSign};
@ -73,12 +76,6 @@ mod pathfind;
pub mod raw; pub mod raw;
mod traversable; mod traversable;
// TODO Minimize uses of these!
pub const NORMAL_LANE_THICKNESS: Distance = Distance::const_meters(2.5);
pub(crate) const SERVICE_ROAD_LANE_THICKNESS: Distance = Distance::const_meters(1.5);
pub const SIDEWALK_THICKNESS: Distance = Distance::const_meters(1.5);
pub(crate) const SHOULDER_THICKNESS: Distance = Distance::const_meters(0.5);
// The map used by the simulation and UI. This struct is declared here so that the rest of the // The map used by the simulation and UI. This struct is declared here so that the rest of the
// crate can reach into private fields. // crate can reach into private fields.
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]

View File

@ -3,36 +3,20 @@ use std::iter;
use abstutil::Tags; use abstutil::Tags;
use crate::{ use crate::{osm, Direction, DrivingSide, LaneSpec, LaneType, MapConfig};
osm, Direction, DrivingSide, LaneSpec, LaneType, MapConfig, NORMAL_LANE_THICKNESS,
SERVICE_ROAD_LANE_THICKNESS, SHOULDER_THICKNESS, SIDEWALK_THICKNESS,
};
fn fwd(lt: LaneType) -> LaneSpec {
LaneSpec {
lt,
dir: Direction::Fwd,
width: match lt {
LaneType::Sidewalk => SIDEWALK_THICKNESS,
LaneType::Shoulder => SHOULDER_THICKNESS,
_ => NORMAL_LANE_THICKNESS,
},
}
}
fn back(lt: LaneType) -> LaneSpec {
LaneSpec {
lt,
dir: Direction::Back,
width: match lt {
LaneType::Sidewalk => SIDEWALK_THICKNESS,
LaneType::Shoulder => SHOULDER_THICKNESS,
_ => NORMAL_LANE_THICKNESS,
},
}
}
pub fn get_lane_specs_ltr(tags: &Tags, cfg: &MapConfig) -> Vec<LaneSpec> { pub fn get_lane_specs_ltr(tags: &Tags, cfg: &MapConfig) -> Vec<LaneSpec> {
let fwd = |lt: LaneType| LaneSpec {
lt,
dir: Direction::Fwd,
width: LaneSpec::typical_lane_widths(lt, tags)[0].0,
};
let back = |lt: LaneType| LaneSpec {
lt,
dir: Direction::Back,
width: LaneSpec::typical_lane_widths(lt, tags)[0].0,
};
// Easy special cases first. // Easy special cases first.
if tags.is_any("railway", vec!["light_rail", "rail"]) { if tags.is_any("railway", vec!["light_rail", "rail"]) {
return vec![fwd(LaneType::LightRail)]; return vec![fwd(LaneType::LightRail)];
@ -41,7 +25,7 @@ pub fn get_lane_specs_ltr(tags: &Tags, cfg: &MapConfig) -> Vec<LaneSpec> {
return vec![fwd(LaneType::Sidewalk)]; return vec![fwd(LaneType::Sidewalk)];
} }
// Eventually, we should have some kind of special LaneType for shared walking/cycling paths of // Eventually, we should have some kind of special LaneType for shared walking/cycling paths of
// different kinds. Until then, model by making a narrow bike lane and a shoulder for walking. // different kinds. Until then, model by making bike lanes and a shoulder for walking.
if tags.is_any( if tags.is_any(
osm::HIGHWAY, osm::HIGHWAY,
vec!["cycleway", "footway", "path", "pedestrian", "track"], vec!["cycleway", "footway", "path", "pedestrian", "track"],
@ -57,15 +41,11 @@ pub fn get_lane_specs_ltr(tags: &Tags, cfg: &MapConfig) -> Vec<LaneSpec> {
} }
// Otherwise, there'll always be a bike lane. // Otherwise, there'll always be a bike lane.
let half_width = |mut spec: LaneSpec| { let mut fwd_side = vec![fwd(LaneType::Biking)];
spec.width = spec.width / 2.0;
spec
};
let mut fwd_side = vec![half_width(fwd(LaneType::Biking))];
let mut back_side = if tags.is("oneway", "yes") { let mut back_side = if tags.is("oneway", "yes") {
vec![] vec![]
} else { } else {
vec![half_width(back(LaneType::Biking))] vec![back(LaneType::Biking)]
}; };
if !tags.is("foot", "no") { if !tags.is("foot", "no") {
@ -289,14 +269,6 @@ pub fn get_lane_specs_ltr(tags: &Tags, cfg: &MapConfig) -> Vec<LaneSpec> {
} }
} }
if tags.is(osm::HIGHWAY, "service") || tags.is("narrow", "yes") {
for spec in fwd_side.iter_mut().chain(back_side.iter_mut()) {
if spec.lt == LaneType::Driving || spec.lt == LaneType::Parking {
spec.width = SERVICE_ROAD_LANE_THICKNESS;
}
}
}
let mut need_fwd_shoulder = fwd_side let mut need_fwd_shoulder = fwd_side
.last() .last()
.map(|spec| spec.lt != LaneType::Sidewalk) .map(|spec| spec.lt != LaneType::Sidewalk)

View File

@ -8,14 +8,18 @@ use geom::{Distance, Line, PolyLine, Polygon, Pt2D, Ring};
use crate::{ use crate::{
osm, BusStopID, DirectedRoadID, Direction, IntersectionID, Map, MapConfig, Road, RoadID, osm, BusStopID, DirectedRoadID, Direction, IntersectionID, Map, MapConfig, Road, RoadID,
TurnType, NORMAL_LANE_THICKNESS, SERVICE_ROAD_LANE_THICKNESS, SHOULDER_THICKNESS, TurnType,
SIDEWALK_THICKNESS,
}; };
/// From some manually audited cases in Seattle, the length of parallel street parking spots is a /// From some manually audited cases in Seattle, the length of parallel street parking spots is a
/// bit different than the length in parking lots, so set a different value here. /// bit different than the length in parking lots, so set a different value here.
pub const PARKING_LOT_SPOT_LENGTH: Distance = Distance::const_meters(6.4); pub const PARKING_LOT_SPOT_LENGTH: Distance = Distance::const_meters(6.4);
pub const NORMAL_LANE_THICKNESS: Distance = Distance::const_meters(2.5);
const SERVICE_ROAD_LANE_THICKNESS: Distance = Distance::const_meters(1.5);
pub const SIDEWALK_THICKNESS: Distance = Distance::const_meters(1.5);
const SHOULDER_THICKNESS: Distance = Distance::const_meters(0.5);
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct LaneID( pub struct LaneID(
#[serde( #[serde(
@ -405,13 +409,20 @@ impl LaneSpec {
// https://en.wikipedia.org/wiki/Lane#Lane_width // https://en.wikipedia.org/wiki/Lane#Lane_width
LaneType::Driving => { LaneType::Driving => {
let mut choices = vec![ let mut choices = vec![
(Distance::feet(8.2), "narrow"), (Distance::feet(8.0), "narrow"),
(SERVICE_ROAD_LANE_THICKNESS, "alley"), (SERVICE_ROAD_LANE_THICKNESS, "alley"),
(Distance::feet(10.0), "typical"), (Distance::feet(10.0), "typical"),
(Distance::feet(12.0), "highways"), (Distance::feet(12.0), "highway"),
]; ];
if rank == osm::RoadRank::Highway { if rank == osm::RoadRank::Highway
&& tags
.get(osm::HIGHWAY)
.map(|x| !x.ends_with("_link"))
.unwrap_or(true)
{
choices.rotate_right(1); choices.rotate_right(1);
} else if tags.is(osm::HIGHWAY, "service") || tags.is("narrow", "yes") {
choices.swap(1, 0);
} }
choices choices
} }
@ -427,11 +438,18 @@ impl LaneSpec {
(Distance::feet(10.0), "minimum"), (Distance::feet(10.0), "minimum"),
], ],
// https://nacto.org/publication/urban-street-design-guide/street-design-elements/lane-width/ // https://nacto.org/publication/urban-street-design-guide/street-design-elements/lane-width/
LaneType::Parking => vec![ LaneType::Parking => {
let mut choices = vec![
(Distance::feet(7.0), "narrow"), (Distance::feet(7.0), "narrow"),
(SERVICE_ROAD_LANE_THICKNESS, "alley"),
(Distance::feet(9.0), "wide"), (Distance::feet(9.0), "wide"),
(Distance::feet(15.0), "loading zone"), (Distance::feet(15.0), "loading zone"),
], ];
if tags.is(osm::HIGHWAY, "service") || tags.is("narrow", "yes") {
choices.swap(1, 0);
}
choices
}
// Just a guess // Just a guess
LaneType::SharedLeftTurn => vec![(NORMAL_LANE_THICKNESS, "default")], LaneType::SharedLeftTurn => vec![(NORMAL_LANE_THICKNESS, "default")],
// These're often converted from existing lanes, so just retain that width // These're often converted from existing lanes, so just retain that width

View File

@ -1,349 +0,0 @@
{
"intersection_osm_node_id": 53189942,
"plans": [
{
"start_time_seconds": 0,
"stages": [
{
"protected_turns": [
{
"from": {
"osm_way_id": 337673338,
"osm_node1": 53189942,
"osm_node2": 3447400931,
"is_forwards": false
},
"to": {
"osm_way_id": 337673338,
"osm_node1": 53189942,
"osm_node2": 3447400931,
"is_forwards": true
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": true
},
{
"from": {
"osm_way_id": 337673338,
"osm_node1": 53189942,
"osm_node2": 3447400931,
"is_forwards": true
},
"to": {
"osm_way_id": 337673338,
"osm_node1": 53189942,
"osm_node2": 3447400931,
"is_forwards": false
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": true
},
{
"from": {
"osm_way_id": 395714915,
"osm_node1": 829673827,
"osm_node2": 53189942,
"is_forwards": false
},
"to": {
"osm_way_id": 395714915,
"osm_node1": 829673827,
"osm_node2": 53189942,
"is_forwards": true
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": true
},
{
"from": {
"osm_way_id": 395714915,
"osm_node1": 829673827,
"osm_node2": 53189942,
"is_forwards": true
},
"to": {
"osm_way_id": 395714915,
"osm_node1": 829673827,
"osm_node2": 53189942,
"is_forwards": false
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": true
},
{
"from": {
"osm_way_id": 462700204,
"osm_node1": 53189942,
"osm_node2": 3447400930,
"is_forwards": false
},
"to": {
"osm_way_id": 462700204,
"osm_node1": 53189942,
"osm_node2": 3447400930,
"is_forwards": true
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": true
},
{
"from": {
"osm_way_id": 462700204,
"osm_node1": 53189942,
"osm_node2": 3447400930,
"is_forwards": true
},
"to": {
"osm_way_id": 462700204,
"osm_node1": 53189942,
"osm_node2": 3447400930,
"is_forwards": false
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": true
}
],
"permitted_turns": [
{
"from": {
"osm_way_id": 395714916,
"osm_node1": 5466048585,
"osm_node2": 53189942,
"is_forwards": true
},
"to": {
"osm_way_id": 337673338,
"osm_node1": 53189942,
"osm_node2": 3447400931,
"is_forwards": true
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": false
},
{
"from": {
"osm_way_id": 395714916,
"osm_node1": 5466048585,
"osm_node2": 53189942,
"is_forwards": true
},
"to": {
"osm_way_id": 395714915,
"osm_node1": 829673827,
"osm_node2": 53189942,
"is_forwards": false
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": false
},
{
"from": {
"osm_way_id": 395714916,
"osm_node1": 5466048585,
"osm_node2": 53189942,
"is_forwards": true
},
"to": {
"osm_way_id": 462700204,
"osm_node1": 53189942,
"osm_node2": 3447400930,
"is_forwards": true
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": false
},
{
"from": {
"osm_way_id": 462700204,
"osm_node1": 53189942,
"osm_node2": 3447400930,
"is_forwards": false
},
"to": {
"osm_way_id": 337673338,
"osm_node1": 53189942,
"osm_node2": 3447400931,
"is_forwards": true
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": false
},
{
"from": {
"osm_way_id": 462700204,
"osm_node1": 53189942,
"osm_node2": 3447400930,
"is_forwards": false
},
"to": {
"osm_way_id": 395714915,
"osm_node1": 829673827,
"osm_node2": 53189942,
"is_forwards": false
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": false
},
{
"from": {
"osm_way_id": 462700204,
"osm_node1": 53189942,
"osm_node2": 3447400930,
"is_forwards": false
},
"to": {
"osm_way_id": 395714916,
"osm_node1": 5466048585,
"osm_node2": 53189942,
"is_forwards": false
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": false
}
],
"stage_type": {
"Fixed": 30
}
},
{
"protected_turns": [
{
"from": {
"osm_way_id": 337673338,
"osm_node1": 53189942,
"osm_node2": 3447400931,
"is_forwards": false
},
"to": {
"osm_way_id": 395714915,
"osm_node1": 829673827,
"osm_node2": 53189942,
"is_forwards": false
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": false
},
{
"from": {
"osm_way_id": 395714915,
"osm_node1": 829673827,
"osm_node2": 53189942,
"is_forwards": true
},
"to": {
"osm_way_id": 337673338,
"osm_node1": 53189942,
"osm_node2": 3447400931,
"is_forwards": true
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": false
},
{
"from": {
"osm_way_id": 395714916,
"osm_node1": 5466048585,
"osm_node2": 53189942,
"is_forwards": false
},
"to": {
"osm_way_id": 395714916,
"osm_node1": 5466048585,
"osm_node2": 53189942,
"is_forwards": true
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": true
},
{
"from": {
"osm_way_id": 395714916,
"osm_node1": 5466048585,
"osm_node2": 53189942,
"is_forwards": true
},
"to": {
"osm_way_id": 395714916,
"osm_node1": 5466048585,
"osm_node2": 53189942,
"is_forwards": false
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": true
}
],
"permitted_turns": [
{
"from": {
"osm_way_id": 337673338,
"osm_node1": 53189942,
"osm_node2": 3447400931,
"is_forwards": false
},
"to": {
"osm_way_id": 395714916,
"osm_node1": 5466048585,
"osm_node2": 53189942,
"is_forwards": false
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": false
},
{
"from": {
"osm_way_id": 337673338,
"osm_node1": 53189942,
"osm_node2": 3447400931,
"is_forwards": false
},
"to": {
"osm_way_id": 462700204,
"osm_node1": 53189942,
"osm_node2": 3447400930,
"is_forwards": true
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": false
},
{
"from": {
"osm_way_id": 395714915,
"osm_node1": 829673827,
"osm_node2": 53189942,
"is_forwards": true
},
"to": {
"osm_way_id": 395714916,
"osm_node1": 5466048585,
"osm_node2": 53189942,
"is_forwards": false
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": false
},
{
"from": {
"osm_way_id": 395714915,
"osm_node1": 829673827,
"osm_node2": 53189942,
"is_forwards": true
},
"to": {
"osm_way_id": 462700204,
"osm_node1": 53189942,
"osm_node2": 3447400930,
"is_forwards": true
},
"intersection_osm_node_id": 53189942,
"is_crosswalk": false
}
],
"stage_type": {
"Fixed": 30
}
}
],
"offset_seconds": 0
}
]
}