mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-29 12:43:38 +03:00
change speed limits in the map_model layer
This commit is contained in:
parent
3d16c7c626
commit
07c48f612d
@ -182,19 +182,19 @@ data/input/seattle/parcels_urbansim.txt,db63d7d606e8702d12f9399e87e6a00f,https:/
|
||||
data/input/seattle/popdat.bin,793dd4075de7a4cf5ea8005cd68a06c8,https://www.dropbox.com/s/wrpji7e14rdwszs/popdat.bin.zip?dl=0
|
||||
data/input/seattle/sidewalks.bin,129b460f56f5eb41cab3bfd70fb5fde9,https://www.dropbox.com/s/ma9bmisijc7v7xa/sidewalks.bin.zip?dl=0
|
||||
data/input/seattle/trips_2014.csv,d4a8e733045b28c0385fb81359d6df03,https://www.dropbox.com/s/5ppravwmk6bf20d/trips_2014.csv.zip?dl=0
|
||||
data/system/maps/23rd.bin,9233bb46ba3496b4ab53197f5c029934,https://www.dropbox.com/s/wjl45codk6rqfg4/23rd.bin.zip?dl=0
|
||||
data/system/maps/ballard.bin,49ff23b42753cd8d3041d088ae115639,https://www.dropbox.com/s/u4rvz50she3yrk0/ballard.bin.zip?dl=0
|
||||
data/system/maps/barranquilla.bin,f486f373eb04e0408847527b84ab66fd,https://www.dropbox.com/s/iuvggdfr16u6luw/barranquilla.bin.zip?dl=0
|
||||
data/system/maps/caphill.bin,417bfe016e8085af60d2d2b9f17bceab,https://www.dropbox.com/s/bh20pn3wxygetw8/caphill.bin.zip?dl=0
|
||||
data/system/maps/downtown.bin,cf0998f708acb6e86d63f36ab131b19a,https://www.dropbox.com/s/4do5cg4vc17lafo/downtown.bin.zip?dl=0
|
||||
data/system/maps/downtown_atx.bin,f0c2d19284b3afdd9194d8cece002a4b,https://www.dropbox.com/s/5avnbkd4oxby2hs/downtown_atx.bin.zip?dl=0
|
||||
data/system/maps/downtown_la.bin,ad73e60a7e078881bd12e4558619b368,https://www.dropbox.com/s/gkcl982cj6kxvrz/downtown_la.bin.zip?dl=0
|
||||
data/system/maps/huge_austin.bin,cca4408c14146b47715b017449937a3c,https://www.dropbox.com/s/khy0m6v9yt0gjnt/huge_austin.bin.zip?dl=0
|
||||
data/system/maps/huge_seattle.bin,e383ab41e6626e08d58e09c01de4c0b9,https://www.dropbox.com/s/btvr3qajshnivhb/huge_seattle.bin.zip?dl=0
|
||||
data/system/maps/intl_district.bin,825f6480fcb54983de9eb6dc055898a9,https://www.dropbox.com/s/fohppni52ekc5l3/intl_district.bin.zip?dl=0
|
||||
data/system/maps/lakeslice.bin,11d05f5ae2bea0751ca5dc2388fbde1c,https://www.dropbox.com/s/99zi0gcbyvqrkud/lakeslice.bin.zip?dl=0
|
||||
data/system/maps/montlake.bin,b71aa517fc4774b7fdd7c7643f360547,https://www.dropbox.com/s/zvhm2j5lavixxcr/montlake.bin.zip?dl=0
|
||||
data/system/maps/west_seattle.bin,ee10fd358d16b005e50a473fd00946ed,https://www.dropbox.com/s/5pp1ik9l40yj3wh/west_seattle.bin.zip?dl=0
|
||||
data/system/maps/23rd.bin,1b01be89048b08440e9da8a121eaf6c1,https://www.dropbox.com/s/wjl45codk6rqfg4/23rd.bin.zip?dl=0
|
||||
data/system/maps/ballard.bin,07e65eacf9d158520a86e5ef5345b9e9,https://www.dropbox.com/s/u4rvz50she3yrk0/ballard.bin.zip?dl=0
|
||||
data/system/maps/barranquilla.bin,51fb8787696fd41f2785233b8899992c,https://www.dropbox.com/s/iuvggdfr16u6luw/barranquilla.bin.zip?dl=0
|
||||
data/system/maps/caphill.bin,75d42602513554c40190e6dd308d0651,https://www.dropbox.com/s/bh20pn3wxygetw8/caphill.bin.zip?dl=0
|
||||
data/system/maps/downtown.bin,09ba0aa6ec9307f1f56e75124fee0060,https://www.dropbox.com/s/4do5cg4vc17lafo/downtown.bin.zip?dl=0
|
||||
data/system/maps/downtown_atx.bin,adaaeb4616d8aba97c67e8e168b69d23,https://www.dropbox.com/s/5avnbkd4oxby2hs/downtown_atx.bin.zip?dl=0
|
||||
data/system/maps/downtown_la.bin,126479cf28da991b47e75a3300ea1680,https://www.dropbox.com/s/gkcl982cj6kxvrz/downtown_la.bin.zip?dl=0
|
||||
data/system/maps/huge_austin.bin,8d0dedf397eccd8cfc57bf9a0bc9af65,https://www.dropbox.com/s/khy0m6v9yt0gjnt/huge_austin.bin.zip?dl=0
|
||||
data/system/maps/huge_seattle.bin,63847b7fbcd3bcb428c2661262671fdd,https://www.dropbox.com/s/btvr3qajshnivhb/huge_seattle.bin.zip?dl=0
|
||||
data/system/maps/intl_district.bin,5fb9c68f355d5aa571584c153d95ea5d,https://www.dropbox.com/s/fohppni52ekc5l3/intl_district.bin.zip?dl=0
|
||||
data/system/maps/lakeslice.bin,ede83326617e1c13a0b73f68a8bb94d1,https://www.dropbox.com/s/99zi0gcbyvqrkud/lakeslice.bin.zip?dl=0
|
||||
data/system/maps/montlake.bin,6f32bf30a3de12bbca8d7ceadd3fd86b,https://www.dropbox.com/s/zvhm2j5lavixxcr/montlake.bin.zip?dl=0
|
||||
data/system/maps/west_seattle.bin,9ca3dba9a94bfe3857bdf92d2a4574de,https://www.dropbox.com/s/5pp1ik9l40yj3wh/west_seattle.bin.zip?dl=0
|
||||
data/system/prebaked_results/lakeslice/weekday.bin,54c504f93db1aa7401e38ef7350adfb0,https://www.dropbox.com/s/1c1sohvy50263wg/weekday.bin.zip?dl=0
|
||||
data/system/prebaked_results/montlake/car vs bike contention.bin,1031311cb5f27dcda4a92083cc0c214f,https://www.dropbox.com/s/jefg0ikjy9dsrdd/car%20vs%20bike%20contention.bin.zip?dl=0
|
||||
data/system/prebaked_results/montlake/weekday.bin,30033ba544b2bd9810aa7278ee380ec2,https://www.dropbox.com/s/1aq7n9ow8tfqb5d/weekday.bin.zip?dl=0
|
||||
|
@ -147,6 +147,7 @@ impl State for EditMode {
|
||||
let id = match edits.commands.pop().unwrap() {
|
||||
EditCmd::ChangeLaneType { id, .. } => ID::Lane(id),
|
||||
EditCmd::ReverseLane { l, .. } => ID::Lane(l),
|
||||
EditCmd::ChangeSpeedLimit { id, .. } => ID::Road(id),
|
||||
EditCmd::ChangeIntersection { i, .. } => ID::Intersection(i),
|
||||
};
|
||||
apply_map_edits(ctx, app, edits);
|
||||
|
@ -26,7 +26,7 @@ pub fn info(ctx: &EventCtx, app: &App, details: &mut Details, id: LaneID) -> Vec
|
||||
),
|
||||
));
|
||||
} else {
|
||||
kv.push(("Speed limit", r.get_speed_limit().to_string()));
|
||||
kv.push(("Speed limit", r.speed_limit.to_string()));
|
||||
}
|
||||
|
||||
kv.push(("Length", l.length().describe_rounded()));
|
||||
|
@ -143,6 +143,7 @@ pub fn edits(ctx: &mut EventCtx, app: &App) -> Layers {
|
||||
vec![
|
||||
format!("{} lane types changed", edits.original_lts.len()),
|
||||
format!("{} lanes reversed", edits.reversed_lanes.len()),
|
||||
format!("{} speed limits changed", edits.changed_speed_limits.len()),
|
||||
format!(
|
||||
"{} intersections changed",
|
||||
edits.original_intersections.len()
|
||||
|
@ -170,7 +170,9 @@ impl GameplayMode {
|
||||
pub fn allows(&self, edits: &MapEdits) -> bool {
|
||||
for cmd in &edits.commands {
|
||||
match cmd {
|
||||
EditCmd::ChangeLaneType { .. } | EditCmd::ReverseLane { .. } => {
|
||||
EditCmd::ChangeLaneType { .. }
|
||||
| EditCmd::ReverseLane { .. }
|
||||
| EditCmd::ChangeSpeedLimit { .. } => {
|
||||
if !self.can_edit_lanes() {
|
||||
return false;
|
||||
}
|
||||
|
@ -2,7 +2,8 @@ use crate::raw::{OriginalIntersection, OriginalRoad};
|
||||
use crate::{
|
||||
ControlStopSign, ControlTrafficSignal, IntersectionID, LaneID, LaneType, Map, RoadID, TurnID,
|
||||
};
|
||||
use abstutil::{deserialize_btreemap, retain_btreemap, serialize_btreemap, Timer};
|
||||
use abstutil::{deserialize_btreemap, retain_btreemap, retain_btreeset, serialize_btreemap, Timer};
|
||||
use geom::Speed;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
@ -15,6 +16,7 @@ pub struct MapEdits {
|
||||
pub original_lts: BTreeMap<LaneID, LaneType>,
|
||||
pub reversed_lanes: BTreeSet<LaneID>,
|
||||
pub original_intersections: BTreeMap<IntersectionID, EditIntersection>,
|
||||
pub changed_speed_limits: BTreeSet<RoadID>,
|
||||
|
||||
// Edits without these are player generated.
|
||||
pub proposal_description: Vec<String>,
|
||||
@ -39,6 +41,11 @@ pub enum EditCmd {
|
||||
// New intended dst_i
|
||||
dst_i: IntersectionID,
|
||||
},
|
||||
ChangeSpeedLimit {
|
||||
id: RoadID,
|
||||
new: Speed,
|
||||
old: Speed,
|
||||
},
|
||||
ChangeIntersection {
|
||||
i: IntersectionID,
|
||||
new: EditIntersection,
|
||||
@ -64,6 +71,7 @@ impl MapEdits {
|
||||
original_lts: BTreeMap::new(),
|
||||
reversed_lanes: BTreeSet::new(),
|
||||
original_intersections: BTreeMap::new(),
|
||||
changed_speed_limits: BTreeSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,11 +95,11 @@ impl MapEdits {
|
||||
);
|
||||
}
|
||||
|
||||
// Original lane types, reversed lanes, and all changed intersections
|
||||
pub(crate) fn update_derived(&mut self, map: &Map) {
|
||||
let mut orig_lts = BTreeMap::new();
|
||||
let mut reversed_lanes = BTreeSet::new();
|
||||
let mut orig_intersections: BTreeMap<IntersectionID, EditIntersection> = BTreeMap::new();
|
||||
let mut changed_speed_limits = BTreeSet::new();
|
||||
|
||||
for cmd in &self.commands {
|
||||
match cmd {
|
||||
@ -107,6 +115,9 @@ impl MapEdits {
|
||||
reversed_lanes.insert(*l);
|
||||
}
|
||||
}
|
||||
EditCmd::ChangeSpeedLimit { id, .. } => {
|
||||
changed_speed_limits.insert(*id);
|
||||
}
|
||||
EditCmd::ChangeIntersection { i, ref old, .. } => {
|
||||
if !orig_intersections.contains_key(i) {
|
||||
orig_intersections.insert(*i, old.clone());
|
||||
@ -119,10 +130,14 @@ impl MapEdits {
|
||||
retain_btreemap(&mut orig_intersections, |i, orig| {
|
||||
map.get_i_edit(*i) != orig.clone()
|
||||
});
|
||||
retain_btreeset(&mut changed_speed_limits, |r| {
|
||||
map.get_r(*r).speed_limit != map.get_r(*r).speed_limit_from_osm()
|
||||
});
|
||||
|
||||
self.original_lts = orig_lts;
|
||||
self.reversed_lanes = reversed_lanes;
|
||||
self.original_intersections = orig_intersections;
|
||||
self.changed_speed_limits = changed_speed_limits;
|
||||
}
|
||||
|
||||
// Assumes update_derived has been called.
|
||||
@ -147,6 +162,13 @@ impl MapEdits {
|
||||
new: map.get_i_edit(*i),
|
||||
});
|
||||
}
|
||||
for r in &self.changed_speed_limits {
|
||||
self.commands.push(EditCmd::ChangeSpeedLimit {
|
||||
id: *r,
|
||||
new: map.get_r(*r).speed_limit,
|
||||
old: map.get_r(*r).speed_limit_from_osm(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,6 +236,11 @@ enum PermanentEditCmd {
|
||||
// New intended dst_i
|
||||
dst_i: OriginalIntersection,
|
||||
},
|
||||
ChangeSpeedLimit {
|
||||
id: OriginalRoad,
|
||||
new: Speed,
|
||||
old: Speed,
|
||||
},
|
||||
ChangeIntersection {
|
||||
i: OriginalIntersection,
|
||||
new: PermanentEditIntersection,
|
||||
@ -241,6 +268,13 @@ impl PermanentMapEdits {
|
||||
l: OriginalLane::to_permanent(*l, map),
|
||||
dst_i: map.get_i(*dst_i).orig_id,
|
||||
},
|
||||
EditCmd::ChangeSpeedLimit { id, new, old } => {
|
||||
PermanentEditCmd::ChangeSpeedLimit {
|
||||
id: map.get_r(*id).orig_id,
|
||||
new: *new,
|
||||
old: *old,
|
||||
}
|
||||
}
|
||||
EditCmd::ChangeIntersection { i, new, old } => {
|
||||
PermanentEditCmd::ChangeIntersection {
|
||||
i: map.get_i(*i).orig_id,
|
||||
@ -273,6 +307,13 @@ impl PermanentMapEdits {
|
||||
let dst_i = map.find_i_by_osm_id(dst_i.osm_node_id)?;
|
||||
Ok(EditCmd::ReverseLane { l, dst_i })
|
||||
}
|
||||
PermanentEditCmd::ChangeSpeedLimit { id, new, old } => {
|
||||
let id = map.find_r_by_osm_id(
|
||||
id.osm_way_id,
|
||||
(id.i1.osm_node_id, id.i2.osm_node_id),
|
||||
)?;
|
||||
Ok(EditCmd::ChangeSpeedLimit { id, new, old })
|
||||
}
|
||||
PermanentEditCmd::ChangeIntersection { i, new, old } => {
|
||||
let id = map.find_i_by_osm_id(i.osm_node_id)?;
|
||||
Ok(EditCmd::ChangeIntersection {
|
||||
@ -291,6 +332,7 @@ impl PermanentMapEdits {
|
||||
original_lts: BTreeMap::new(),
|
||||
reversed_lanes: BTreeSet::new(),
|
||||
original_intersections: BTreeMap::new(),
|
||||
changed_speed_limits: BTreeSet::new(),
|
||||
};
|
||||
edits.update_derived(map);
|
||||
Ok(edits)
|
||||
@ -322,7 +364,8 @@ impl PermanentEditIntersection {
|
||||
let mut translated_must_stop = BTreeMap::new();
|
||||
for (r, stop) in must_stop {
|
||||
translated_must_stop.insert(
|
||||
map.find_r_by_osm_id(r.osm_way_id, (r.i1.osm_node_id, r.i2.osm_node_id))?,
|
||||
map.find_r_by_osm_id(r.osm_way_id, (r.i1.osm_node_id, r.i2.osm_node_id))
|
||||
.ok()?,
|
||||
stop,
|
||||
);
|
||||
}
|
||||
@ -360,13 +403,10 @@ impl OriginalLane {
|
||||
}
|
||||
|
||||
fn from_permanent(self, map: &Map) -> Result<LaneID, String> {
|
||||
let r = map.get_r(
|
||||
map.find_r_by_osm_id(
|
||||
self.parent.osm_way_id,
|
||||
(self.parent.i1.osm_node_id, self.parent.i2.osm_node_id),
|
||||
)
|
||||
.ok_or_else(|| format!("can't find {:?}", self))?,
|
||||
);
|
||||
let r = map.get_r(map.find_r_by_osm_id(
|
||||
self.parent.osm_way_id,
|
||||
(self.parent.i1.osm_node_id, self.parent.i2.osm_node_id),
|
||||
)?);
|
||||
if r.children_forwards.len() != self.num_fwd || r.children_backwards.len() != self.num_back
|
||||
{
|
||||
return Err(format!("number of lanes has changed in {:?}", self));
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
NORMAL_LANE_THICKNESS, SIDEWALK_THICKNESS,
|
||||
};
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap, Error, Timer, Warn};
|
||||
use geom::{Angle, Bounds, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D};
|
||||
use geom::{Angle, Bounds, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D, Speed};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashSet, VecDeque};
|
||||
|
||||
@ -643,16 +643,23 @@ impl Map {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn find_r_by_osm_id(&self, osm_way_id: i64, osm_node_ids: (i64, i64)) -> Option<RoadID> {
|
||||
pub fn find_r_by_osm_id(
|
||||
&self,
|
||||
osm_way_id: i64,
|
||||
osm_node_ids: (i64, i64),
|
||||
) -> Result<RoadID, String> {
|
||||
for r in self.all_roads() {
|
||||
if r.orig_id.osm_way_id == osm_way_id
|
||||
&& r.orig_id.i1.osm_node_id == osm_node_ids.0
|
||||
&& r.orig_id.i2.osm_node_id == osm_node_ids.1
|
||||
{
|
||||
return Some(r.id);
|
||||
return Ok(r.id);
|
||||
}
|
||||
}
|
||||
None
|
||||
Err(format!(
|
||||
"Can't find osm_way_id {} between nodes {} and {}",
|
||||
osm_way_id, osm_node_ids.0, osm_node_ids.1
|
||||
))
|
||||
}
|
||||
|
||||
pub fn find_i_by_osm_id(&self, osm_node_id: i64) -> Result<IntersectionID, String> {
|
||||
@ -933,7 +940,9 @@ fn make_half_map(
|
||||
center_pts: r.trimmed_center_pts.clone(),
|
||||
src_i: i1,
|
||||
dst_i: i2,
|
||||
speed_limit: Speed::ZERO,
|
||||
};
|
||||
road.speed_limit = road.speed_limit_from_osm();
|
||||
|
||||
for lane in &r.lane_specs {
|
||||
let id = LaneID(map.lanes.len());
|
||||
@ -1150,6 +1159,15 @@ impl EditCmd {
|
||||
recalculate_turns(dst_i, map, effects, timer);
|
||||
true
|
||||
}
|
||||
EditCmd::ChangeSpeedLimit { id, new, .. } => {
|
||||
if map.roads[id.0].speed_limit != *new {
|
||||
map.roads[id.0].speed_limit = *new;
|
||||
effects.changed_roads.insert(*id);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
EditCmd::ChangeIntersection {
|
||||
i,
|
||||
ref new,
|
||||
@ -1206,6 +1224,15 @@ impl EditCmd {
|
||||
}
|
||||
.apply(effects, map, timer)
|
||||
}
|
||||
EditCmd::ChangeSpeedLimit { id, old, .. } => {
|
||||
if map.roads[id.0].speed_limit != *old {
|
||||
map.roads[id.0].speed_limit = *old;
|
||||
effects.changed_roads.insert(*id);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
EditCmd::ChangeIntersection {
|
||||
i,
|
||||
ref old,
|
||||
|
@ -128,8 +128,8 @@ pub fn cost(lane: &Lane, turn: &Turn, constraints: PathConstraints, map: &Map) -
|
||||
match constraints {
|
||||
PathConstraints::Car => {
|
||||
// Prefer slightly longer route on faster roads
|
||||
let t1 = lane.length() / map.get_r(lane.parent).get_speed_limit();
|
||||
let t2 = turn.geom.length() / map.get_parent(turn.id.dst).get_speed_limit();
|
||||
let t1 = lane.length() / map.get_r(lane.parent).speed_limit;
|
||||
let t2 = turn.geom.length() / map.get_parent(turn.id.dst).speed_limit;
|
||||
(t1 + t2).inner_seconds().round() as usize
|
||||
}
|
||||
PathConstraints::Bike => {
|
||||
@ -155,8 +155,8 @@ pub fn cost(lane: &Lane, turn: &Turn, constraints: PathConstraints, map: &Map) -
|
||||
}
|
||||
PathConstraints::Bus => {
|
||||
// Like Car, but prefer bus lanes.
|
||||
let t1 = lane.length() / map.get_r(lane.parent).get_speed_limit();
|
||||
let t2 = turn.geom.length() / map.get_parent(turn.id.dst).get_speed_limit();
|
||||
let t1 = lane.length() / map.get_r(lane.parent).speed_limit;
|
||||
let t2 = turn.geom.length() / map.get_parent(turn.id.dst).speed_limit;
|
||||
let lt_penalty = if lane.is_bus() {
|
||||
1.0
|
||||
} else {
|
||||
|
@ -97,6 +97,7 @@ pub struct Road {
|
||||
// self is 'from'. (via, to). Only BanTurns.
|
||||
pub complicated_turn_restrictions: Vec<(RoadID, RoadID)>,
|
||||
pub orig_id: OriginalRoad,
|
||||
pub speed_limit: Speed,
|
||||
|
||||
// Invariant: A road must contain at least one child
|
||||
// These are ordered from closest to center lane (left-most when driving on the right) to
|
||||
@ -205,8 +206,7 @@ impl Road {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_speed_limit(&self) -> Speed {
|
||||
// TODO Should probably cache this
|
||||
pub(crate) fn speed_limit_from_osm(&self) -> Speed {
|
||||
if let Some(limit) = self.osm_tags.get(osm::MAXSPEED) {
|
||||
// TODO handle other units
|
||||
if limit.ends_with(" mph") {
|
||||
|
@ -734,7 +734,9 @@ fn import_turn_group(id: seattle_traffic_signals::Turn, map: &Map) -> Option<Tur
|
||||
|
||||
fn find_r(id: seattle_traffic_signals::DirectedRoad, map: &Map) -> Option<DirectedRoadID> {
|
||||
Some(DirectedRoadID {
|
||||
id: map.find_r_by_osm_id(id.osm_way_id, (id.osm_node1, id.osm_node2))?,
|
||||
id: map
|
||||
.find_r_by_osm_id(id.osm_way_id, (id.osm_node1, id.osm_node2))
|
||||
.ok()?,
|
||||
forwards: id.is_forwards,
|
||||
})
|
||||
}
|
||||
|
@ -167,8 +167,8 @@ impl Traversable {
|
||||
|
||||
pub fn speed_limit(&self, map: &Map) -> Speed {
|
||||
match *self {
|
||||
Traversable::Lane(id) => map.get_parent(id).get_speed_limit(),
|
||||
Traversable::Turn(id) => map.get_parent(id.dst).get_speed_limit(),
|
||||
Traversable::Lane(id) => map.get_parent(id).speed_limit,
|
||||
Traversable::Turn(id) => map.get_parent(id.dst).speed_limit,
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user