mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-26 16:02:23 +03:00
adding error messages for map model queries that can fail
This commit is contained in:
parent
e681032866
commit
843742b708
@ -6,6 +6,7 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
abstutil = { path = "../abstutil" }
|
abstutil = { path = "../abstutil" }
|
||||||
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
|
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
|
||||||
|
failure = "0.1.2"
|
||||||
flame = "0.2.2"
|
flame = "0.2.2"
|
||||||
geo = "0.9.1"
|
geo = "0.9.1"
|
||||||
geom = { path = "../geom" }
|
geom = { path = "../geom" }
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
extern crate abstutil;
|
extern crate abstutil;
|
||||||
extern crate dimensioned;
|
extern crate dimensioned;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate failure;
|
||||||
extern crate flame;
|
extern crate flame;
|
||||||
extern crate geo;
|
extern crate geo;
|
||||||
extern crate geom;
|
extern crate geom;
|
||||||
@ -46,3 +48,15 @@ pub use traversable::Traversable;
|
|||||||
pub use turn::{Turn, TurnID};
|
pub use turn::{Turn, TurnID};
|
||||||
|
|
||||||
pub const LANE_THICKNESS: f64 = 2.5;
|
pub const LANE_THICKNESS: f64 = 2.5;
|
||||||
|
|
||||||
|
#[derive(Debug, Fail)]
|
||||||
|
#[fail(display = "{}", reason)]
|
||||||
|
pub struct MapError {
|
||||||
|
reason: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MapError {
|
||||||
|
pub fn new(reason: String) -> MapError {
|
||||||
|
MapError { reason }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -35,7 +35,7 @@ pub fn make_bus_stops(
|
|||||||
|
|
||||||
for (id, dists) in stops_per_sidewalk.iter_all_mut() {
|
for (id, dists) in stops_per_sidewalk.iter_all_mut() {
|
||||||
let road = &roads[lanes[id.0].parent.0];
|
let road = &roads[lanes[id.0].parent.0];
|
||||||
if let Some(driving_lane) = road.find_driving_lane_from_sidewalk(*id) {
|
if let Ok(driving_lane) = road.find_driving_lane_from_sidewalk(*id) {
|
||||||
dists.sort_by_key(|(dist, _)| NotNaN::new(dist.value_unsafe).unwrap());
|
dists.sort_by_key(|(dist, _)| NotNaN::new(dist.value_unsafe).unwrap());
|
||||||
for (idx, (dist_along, orig_pt)) in dists.iter().enumerate() {
|
for (idx, (dist_along, orig_pt)) in dists.iter().enumerate() {
|
||||||
let stop_id = BusStopID { sidewalk: *id, idx };
|
let stop_id = BusStopID { sidewalk: *id, idx };
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
use abstutil;
|
use abstutil;
|
||||||
use edits::RoadEdits;
|
use edits::RoadEdits;
|
||||||
|
use failure::{Error, ResultExt};
|
||||||
use flame;
|
use flame;
|
||||||
use geom::{Bounds, HashablePt2D, PolyLine, Pt2D};
|
use geom::{Bounds, HashablePt2D, PolyLine, Pt2D};
|
||||||
use make;
|
use make;
|
||||||
use raw_data;
|
use raw_data;
|
||||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||||
use std::io::Error;
|
|
||||||
use std::path;
|
use std::path;
|
||||||
use {
|
use {
|
||||||
Area, AreaID, Building, BuildingID, BusRoute, BusStop, BusStopID, Intersection, IntersectionID,
|
Area, AreaID, Building, BuildingID, BusRoute, BusStop, BusStopID, Intersection, IntersectionID,
|
||||||
@ -379,24 +379,26 @@ impl Map {
|
|||||||
self.bounds.clone()
|
self.bounds.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_driving_lane_from_bldg(&self, bldg: BuildingID) -> Option<LaneID> {
|
pub fn get_driving_lane_from_bldg(&self, bldg: BuildingID) -> Result<LaneID, Error> {
|
||||||
let sidewalk = self.get_b(bldg).front_path.sidewalk;
|
let sidewalk = self.get_b(bldg).front_path.sidewalk;
|
||||||
let road = self.get_parent(sidewalk);
|
let road = self.get_parent(sidewalk);
|
||||||
let parking = road.find_parking_lane(sidewalk)?;
|
road.find_parking_lane(sidewalk)
|
||||||
road.find_driving_lane(parking)
|
.and_then(|parking| road.find_driving_lane(parking))
|
||||||
|
.context(format!("get_driving_lane_from_bldg({})", bldg))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sidewalk_from_driving_lane(&self, driving: LaneID) -> Option<LaneID> {
|
pub fn get_sidewalk_from_driving_lane(&self, driving: LaneID) -> Result<LaneID, Error> {
|
||||||
let road = self.get_parent(driving);
|
let road = self.get_parent(driving);
|
||||||
// No parking lane?
|
// No parking lane?
|
||||||
if let Some(l) = road.find_sidewalk(driving) {
|
if let Ok(l) = road.find_sidewalk(driving) {
|
||||||
return Some(l);
|
return Ok(l);
|
||||||
}
|
}
|
||||||
let parking = road.find_parking_lane(driving)?;
|
road.find_parking_lane(driving)
|
||||||
road.find_sidewalk(parking)
|
.and_then(|parking| road.find_sidewalk(parking))
|
||||||
|
.context(format!("get_sidewalk_from_driving_lane({})", driving))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_driving_lane_from_parking(&self, parking: LaneID) -> Option<LaneID> {
|
pub fn get_driving_lane_from_parking(&self, parking: LaneID) -> Result<LaneID, Error> {
|
||||||
self.get_parent(parking).find_driving_lane(parking)
|
self.get_parent(parking).find_driving_lane(parking)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use dimensioned::si;
|
use dimensioned::si;
|
||||||
|
use failure::Error;
|
||||||
use geom::PolyLine;
|
use geom::PolyLine;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use {LaneID, LaneType};
|
use {LaneID, LaneType, MapError};
|
||||||
|
|
||||||
// TODO reconsider pub usize. maybe outside world shouldnt know.
|
// TODO reconsider pub usize. maybe outside world shouldnt know.
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
@ -82,25 +83,37 @@ impl Road {
|
|||||||
lane == self.children_backwards[0].0
|
lane == self.children_backwards[0].0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_sidewalk(&self, parking_or_driving: LaneID) -> Option<LaneID> {
|
pub fn find_sidewalk(&self, parking_or_driving: LaneID) -> Result<LaneID, Error> {
|
||||||
self.get_siblings(parking_or_driving)
|
self.get_siblings(parking_or_driving)
|
||||||
.iter()
|
.iter()
|
||||||
.find(|pair| pair.1 == LaneType::Sidewalk)
|
.find(|pair| pair.1 == LaneType::Sidewalk)
|
||||||
.map(|pair| pair.0)
|
.map(|pair| pair.0)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
Error::from(MapError::new(format!(
|
||||||
|
"{} doesn't have sidewalk sibling",
|
||||||
|
parking_or_driving
|
||||||
|
)))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_driving_lane(&self, parking: LaneID) -> Option<LaneID> {
|
pub fn find_driving_lane(&self, parking: LaneID) -> Result<LaneID, Error> {
|
||||||
//assert_eq!(l.lane_type, LaneType::Parking);
|
//assert_eq!(l.lane_type, LaneType::Parking);
|
||||||
self.get_siblings(parking)
|
self.get_siblings(parking)
|
||||||
.iter()
|
.iter()
|
||||||
.find(|pair| pair.1 == LaneType::Driving)
|
.find(|pair| pair.1 == LaneType::Driving)
|
||||||
.map(|pair| pair.0)
|
.map(|pair| pair.0)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
Error::from(MapError::new(format!(
|
||||||
|
"{} doesn't have driving lane sibling",
|
||||||
|
parking
|
||||||
|
)))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles intermediate parking and bus lanes and such
|
// Handles intermediate parking and bus lanes and such
|
||||||
// Additionally handles one-ways with a sidewalk on only one side.
|
// Additionally handles one-ways with a sidewalk on only one side.
|
||||||
// TODO but in reality, there probably isn't a sidewalk on the other side of the one-way. :\
|
// TODO but in reality, there probably isn't a sidewalk on the other side of the one-way. :\
|
||||||
pub fn find_driving_lane_from_sidewalk(&self, sidewalk: LaneID) -> Option<LaneID> {
|
pub fn find_driving_lane_from_sidewalk(&self, sidewalk: LaneID) -> Result<LaneID, Error> {
|
||||||
let (this_side, opposite, idx) = if let Some(idx) = self
|
let (this_side, opposite, idx) = if let Some(idx) = self
|
||||||
.children_forwards
|
.children_forwards
|
||||||
.iter()
|
.iter()
|
||||||
@ -125,25 +138,34 @@ impl Road {
|
|||||||
.find(|(_, lt)| *lt == LaneType::Driving)
|
.find(|(_, lt)| *lt == LaneType::Driving)
|
||||||
.map(|(l, _)| *l)
|
.map(|(l, _)| *l)
|
||||||
{
|
{
|
||||||
return Some(l);
|
return Ok(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is the sidewalk on a one-way with the other side having a driving lane?
|
// Is the sidewalk on a one-way with the other side having a driving lane?
|
||||||
if this_side.len() == 1 && opposite[0].1 == LaneType::Driving {
|
if this_side.len() == 1 && opposite[0].1 == LaneType::Driving {
|
||||||
return Some(opposite[0].0);
|
return Ok(opposite[0].0);
|
||||||
}
|
}
|
||||||
None
|
bail!(MapError::new(format!(
|
||||||
|
"Sidewalk {} doesn't have driving lane",
|
||||||
|
sidewalk
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_parking_lane(&self, driving: LaneID) -> Option<LaneID> {
|
pub fn find_parking_lane(&self, driving: LaneID) -> Result<LaneID, Error> {
|
||||||
//assert_eq!(l.lane_type, LaneType::Driving);
|
//assert_eq!(l.lane_type, LaneType::Driving);
|
||||||
self.get_siblings(driving)
|
self.get_siblings(driving)
|
||||||
.iter()
|
.iter()
|
||||||
.find(|pair| pair.1 == LaneType::Parking)
|
.find(|pair| pair.1 == LaneType::Parking)
|
||||||
.map(|pair| pair.0)
|
.map(|pair| pair.0)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
Error::from(MapError::new(format!(
|
||||||
|
"{} doesn't have parking lane sibling",
|
||||||
|
driving
|
||||||
|
)))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_opposite_lane(&self, lane: LaneID, lane_type: LaneType) -> Option<LaneID> {
|
pub fn get_opposite_lane(&self, lane: LaneID, lane_type: LaneType) -> Result<LaneID, Error> {
|
||||||
let forwards: Vec<LaneID> = self
|
let forwards: Vec<LaneID> = self
|
||||||
.children_forwards
|
.children_forwards
|
||||||
.iter()
|
.iter()
|
||||||
@ -158,10 +180,20 @@ impl Road {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if let Some(idx) = forwards.iter().position(|id| *id == lane) {
|
if let Some(idx) = forwards.iter().position(|id| *id == lane) {
|
||||||
return backwards.get(idx).map(|id| *id);
|
return backwards.get(idx).map(|id| *id).ok_or_else(|| {
|
||||||
|
Error::from(MapError::new(format!(
|
||||||
|
"{} doesn't have opposite lane of type {:?}",
|
||||||
|
lane, lane_type
|
||||||
|
)))
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if let Some(idx) = backwards.iter().position(|id| *id == lane) {
|
if let Some(idx) = backwards.iter().position(|id| *id == lane) {
|
||||||
return forwards.get(idx).map(|id| *id);
|
return forwards.get(idx).map(|id| *id).ok_or_else(|| {
|
||||||
|
Error::from(MapError::new(format!(
|
||||||
|
"{} doesn't have opposite lane of type {:?}",
|
||||||
|
lane, lane_type
|
||||||
|
)))
|
||||||
|
});
|
||||||
}
|
}
|
||||||
panic!("{} doesn't contain {}", self.id, lane);
|
panic!("{} doesn't contain {}", self.id, lane);
|
||||||
}
|
}
|
||||||
|
@ -202,12 +202,13 @@ impl Sim {
|
|||||||
let has_bldgs = map
|
let has_bldgs = map
|
||||||
.get_parent(lane)
|
.get_parent(lane)
|
||||||
.find_sidewalk(lane)
|
.find_sidewalk(lane)
|
||||||
.and_then(|sidewalk| Some(!map.get_l(sidewalk).building_paths.is_empty()))
|
.and_then(|sidewalk| Ok(!map.get_l(sidewalk).building_paths.is_empty()))
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
if has_bldgs {
|
if has_bldgs {
|
||||||
map.get_parent(lane)
|
map.get_parent(lane)
|
||||||
.find_driving_lane(lane)
|
.find_driving_lane(lane)
|
||||||
.and_then(|_driving_lane| Some(parked_car.car))
|
.and_then(|_driving_lane| Ok(parked_car.car))
|
||||||
|
.ok()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -325,7 +326,7 @@ fn pick_car_goal<R: Rng + ?Sized>(rng: &mut R, map: &Map, start: LaneID) -> Lane
|
|||||||
.iter()
|
.iter()
|
||||||
.filter_map(|l| {
|
.filter_map(|l| {
|
||||||
if l.id != start && l.is_driving() {
|
if l.id != start && l.is_driving() {
|
||||||
if let Some(sidewalk) = map.get_sidewalk_from_driving_lane(l.id) {
|
if let Ok(sidewalk) = map.get_sidewalk_from_driving_lane(l.id) {
|
||||||
if !map.get_l(sidewalk).building_paths.is_empty() {
|
if !map.get_l(sidewalk).building_paths.is_empty() {
|
||||||
return Some(l.id);
|
return Some(l.id);
|
||||||
}
|
}
|
||||||
|
@ -213,6 +213,7 @@ fn find_parking_spot(
|
|||||||
) -> Option<ParkingSpot> {
|
) -> Option<ParkingSpot> {
|
||||||
map.get_parent(driving_lane)
|
map.get_parent(driving_lane)
|
||||||
.find_parking_lane(driving_lane)
|
.find_parking_lane(driving_lane)
|
||||||
|
.ok()
|
||||||
.and_then(|l| parking_sim.get_first_free_spot(l, dist_along))
|
.and_then(|l| parking_sim.get_first_free_spot(l, dist_along))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user