mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 23:43:25 +03:00
removing log crate from map_model
This commit is contained in:
parent
c2791a6ead
commit
a026c02890
@ -112,9 +112,9 @@ impl<T> Warn<T> {
|
||||
}
|
||||
|
||||
impl Warn<()> {
|
||||
/*pub fn empty_warnings(warnings: Vec<String>) -> Warn<()> {
|
||||
pub fn empty_warnings(warnings: Vec<String>) -> Warn<()> {
|
||||
Warn::warnings((), warnings)
|
||||
}*/
|
||||
}
|
||||
|
||||
/*pub fn add_warning(&mut self, line: String) {
|
||||
self.warnings.push(line);
|
||||
|
@ -129,6 +129,7 @@ impl Timer {
|
||||
println!();
|
||||
|
||||
if !self.notes.is_empty() {
|
||||
println!("{} notes:", self.notes.len());
|
||||
for line in self.notes {
|
||||
println!("{}", line);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::objects::{DrawCtx, ID};
|
||||
use crate::plugins::{BlockingPlugin, PluginCtx};
|
||||
use abstutil::Timer;
|
||||
use ezgui::{Color, Key};
|
||||
use map_model::{ControlStopSign, IntersectionID, TurnPriority};
|
||||
|
||||
@ -59,7 +60,7 @@ impl BlockingPlugin for StopSignEditor {
|
||||
} else if input.modal_action("quit") {
|
||||
return false;
|
||||
} else if input.modal_action("reset to default") {
|
||||
let sign = ControlStopSign::new(map, self.i);
|
||||
let sign = ControlStopSign::new(map, self.i, &mut Timer::throwaway());
|
||||
map.edit_stop_sign(sign);
|
||||
}
|
||||
true
|
||||
|
@ -285,9 +285,10 @@ fn choose_preset(
|
||||
if let Some(ts) = ControlTrafficSignal::three_way(map, id) {
|
||||
choices.push(("three-phase".to_string(), ts));
|
||||
}
|
||||
if let Some(ts) = ControlTrafficSignal::greedy_assignment(map, id) {
|
||||
choices.push(("arbitrary assignment".to_string(), ts));
|
||||
}
|
||||
choices.push((
|
||||
"arbitrary assignment".to_string(),
|
||||
ControlTrafficSignal::greedy_assignment(map, id).unwrap(),
|
||||
));
|
||||
|
||||
wizard
|
||||
.choose_something::<ControlTrafficSignal>(
|
||||
|
@ -9,7 +9,6 @@ aabb-quadtree = "0.1.0"
|
||||
abstutil = { path = "../abstutil" }
|
||||
geom = { path = "../geom" }
|
||||
gtfs = { path = "../gtfs" }
|
||||
log = "0.4.5"
|
||||
multimap = "0.4.0"
|
||||
nbez = "0.1.0"
|
||||
ordered-float = "1.0.1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::raw_data::StableRoadID;
|
||||
use crate::{ControlStopSign, ControlTrafficSignal, IntersectionID, Lane, LaneType, Road};
|
||||
use abstutil;
|
||||
use abstutil::Error;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
@ -94,7 +94,8 @@ impl RoadEdit {
|
||||
panic!("{} is already {:?}", lane.id, new_type);
|
||||
}
|
||||
forwards[idx] = new_type;
|
||||
if !are_lanes_valid(&forwards) {
|
||||
if let Err(err) = are_lanes_valid(&forwards) {
|
||||
println!("{}", err);
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
@ -102,7 +103,8 @@ impl RoadEdit {
|
||||
panic!("{} is already {:?}", lane.id, new_type);
|
||||
}
|
||||
backwards[idx] = new_type;
|
||||
if !are_lanes_valid(&backwards) {
|
||||
if let Err(err) = are_lanes_valid(&backwards) {
|
||||
println!("{}", err);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
@ -137,22 +139,24 @@ impl RoadEdit {
|
||||
}
|
||||
}
|
||||
|
||||
fn are_lanes_valid(lanes: &Vec<LaneType>) -> bool {
|
||||
fn are_lanes_valid(lanes: &Vec<LaneType>) -> Result<(), Error> {
|
||||
// TODO this check doesn't seem to be working
|
||||
for pair in lanes.windows(2) {
|
||||
if pair[0] == LaneType::Parking && pair[1] == LaneType::Parking {
|
||||
error!("Can't have two adjacent parking lanes");
|
||||
return false;
|
||||
return Err(Error::new(
|
||||
"Can't have two adjacent parking lanes".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Can't have two sidewalks on one side of a road
|
||||
if lanes.iter().filter(|&<| lt == LaneType::Sidewalk).count() > 1 {
|
||||
error!("Can't have two sidewalks on one side of a road");
|
||||
return false;
|
||||
return Err(Error::new(
|
||||
"Can't have two sidewalks on one side of a road".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
// I'm sure other ideas will come up. :)
|
||||
|
||||
true
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
mod area;
|
||||
mod building;
|
||||
mod bus_stop;
|
||||
|
@ -1,39 +0,0 @@
|
||||
// Call the log crate, but pre-set the target.
|
||||
|
||||
/*
|
||||
macro_rules! debug {
|
||||
( $( $x:expr ),* ) => {
|
||||
{
|
||||
use log::log;
|
||||
log!(target: "map", log::Level::Debug, $( $x, )* );
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
macro_rules! info {
|
||||
( $( $x:expr ),* ) => {
|
||||
{
|
||||
use log::log;
|
||||
log!(target: "map", log::Level::Info, $( $x, )* );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! warn {
|
||||
( $( $x:expr ),* ) => {
|
||||
{
|
||||
use log::log;
|
||||
log!(target: "map", log::Level::Warn, $( $x, )* );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! error {
|
||||
( $( $x:expr ),* ) => {
|
||||
{
|
||||
use log::log;
|
||||
log!(target: "map", log::Level::Error, $( $x, )* );
|
||||
}
|
||||
}
|
||||
}
|
@ -38,7 +38,7 @@ pub fn make_all_buildings(
|
||||
.dist_along(sidewalk_pos.dist_along())
|
||||
.0;
|
||||
if sidewalk_pt.epsilon_eq(bldg_center.into()) {
|
||||
warn!("Skipping a building because front path has 0 length");
|
||||
timer.warn("Skipping a building because front path has 0 length".to_string());
|
||||
continue;
|
||||
}
|
||||
let line = trim_front_path(&points, Line::new(bldg_center.into(), sidewalk_pt));
|
||||
@ -62,10 +62,10 @@ pub fn make_all_buildings(
|
||||
|
||||
let discarded = input.len() - results.len();
|
||||
if discarded > 0 {
|
||||
info!(
|
||||
timer.note(format!(
|
||||
"Discarded {} buildings that weren't close enough to a sidewalk",
|
||||
discarded
|
||||
);
|
||||
));
|
||||
}
|
||||
timer.stop("convert buildings");
|
||||
}
|
||||
|
@ -66,10 +66,10 @@ pub fn make_bus_stops(
|
||||
);
|
||||
}
|
||||
} else {
|
||||
warn!(
|
||||
timer.warn(format!(
|
||||
"Can't find driving lane next to {}: {:?} and {:?}",
|
||||
id, road.children_forwards, road.children_backwards
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,11 +83,11 @@ pub fn make_bus_stops(
|
||||
.cloned()
|
||||
.collect();
|
||||
if stops.len() < 2 {
|
||||
warn!(
|
||||
timer.warn(format!(
|
||||
"Skipping route {} since it only has {} stop in the slice of the map",
|
||||
route_name,
|
||||
stops.len()
|
||||
);
|
||||
));
|
||||
continue;
|
||||
}
|
||||
let id = BusRouteID(routes.len());
|
||||
@ -120,10 +120,10 @@ pub fn verify_bus_routes(map: &Map, routes: Vec<BusRoute>, timer: &mut Timer) ->
|
||||
if bs1.driving_pos.lane() == bs2.driving_pos.lane() {
|
||||
// This is coming up because the dist_along's are in a bad order. But why
|
||||
// should this happen at all?
|
||||
warn!(
|
||||
timer.warn(format!(
|
||||
"Removing route {} since {:?} and {:?} are on the same lane",
|
||||
r.name, bs1, bs2
|
||||
);
|
||||
));
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
@ -139,10 +139,10 @@ pub fn verify_bus_routes(map: &Map, routes: Vec<BusRoute>, timer: &mut Timer) ->
|
||||
)
|
||||
.is_none()
|
||||
{
|
||||
warn!(
|
||||
timer.warn(format!(
|
||||
"Removing route {} since {:?} and {:?} aren't connected",
|
||||
r.name, bs1, bs2
|
||||
);
|
||||
));
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
@ -136,11 +136,11 @@ pub fn make_half_map(
|
||||
}
|
||||
|
||||
if i.incoming_lanes.is_empty() || i.outgoing_lanes.is_empty() {
|
||||
error!("{:?} is orphaned!", i);
|
||||
timer.warn(format!("{:?} is orphaned!", i));
|
||||
continue;
|
||||
}
|
||||
|
||||
for t in make::turns::make_all_turns(i, &half_map.roads, &half_map.lanes) {
|
||||
for t in make::turns::make_all_turns(i, &half_map.roads, &half_map.lanes, timer) {
|
||||
assert!(!half_map.turns.contains_key(&t.id));
|
||||
i.turns.push(t.id);
|
||||
half_map.turns.insert(t.id, t);
|
||||
@ -151,7 +151,7 @@ pub fn make_half_map(
|
||||
t.lookup_idx = half_map.turn_lookup.len();
|
||||
half_map.turn_lookup.push(t.id);
|
||||
if t.geom.length() < geom::EPSILON_DIST {
|
||||
warn!("u{} is a very short turn", t.lookup_idx);
|
||||
timer.warn(format!("u{} is a very short turn", t.lookup_idx));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use std::collections::{BTreeSet, HashSet};
|
||||
|
||||
pub fn fix_ramps(m: &mut InitialMap, timer: &mut Timer) {
|
||||
if m.roads.len() > 15_000 {
|
||||
error!("Skipping fix_ramps because map is too big! TODO: Optimize me!");
|
||||
timer.warn("Skipping fix_ramps because map is too big! TODO: Optimize me!".to_string());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -42,9 +42,12 @@ pub fn fix_ramps(m: &mut InitialMap, timer: &mut Timer) {
|
||||
|
||||
for (r, i) in fixme {
|
||||
if fix_ramp(m, r, i, timer) {
|
||||
info!("Fixed ramp {} crossing {}", r, i);
|
||||
timer.note(format!("Fixed ramp {} crossing {}", r, i));
|
||||
} else {
|
||||
info!("{} crosses {} strangely, but didn't change anything", r, i);
|
||||
timer.note(format!(
|
||||
"{} crosses {} strangely, but didn't change anything",
|
||||
r, i
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -100,7 +103,10 @@ fn fix_ramp(
|
||||
|
||||
counter += 1;
|
||||
if counter > 10 {
|
||||
warn!("Couldn't find last normal intersection from ramp {}", ramp);
|
||||
timer.warn(format!(
|
||||
"Couldn't find last normal intersection from ramp {}",
|
||||
ramp
|
||||
));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::make::initial::{Intersection, Road};
|
||||
use crate::raw_data::{StableIntersectionID, StableRoadID};
|
||||
use abstutil::{wraparound_get, Timer};
|
||||
use abstutil::{wraparound_get, Timer, Warn};
|
||||
use geom::{Distance, HashablePt2D, Line, PolyLine, Pt2D};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
@ -59,7 +59,7 @@ pub fn intersection_polygon(
|
||||
});
|
||||
|
||||
let mut endpoints = if lines.len() == 1 {
|
||||
deadend(roads, i.id, &lines)
|
||||
deadend(roads, i.id, &lines).get(timer)
|
||||
} else {
|
||||
generalized_trim_back(roads, i.id, &lines, timer)
|
||||
};
|
||||
@ -154,7 +154,7 @@ fn generalized_trim_back(
|
||||
shortest_center = trimmed;
|
||||
}
|
||||
} else {
|
||||
warn!("{} and {} hit, but the perpendicular never hit the original center line, or the trimmed thing is empty", r1, r2);
|
||||
timer.warn(format!("{} and {} hit, but the perpendicular never hit the original center line, or the trimmed thing is empty", r1, r2));
|
||||
}
|
||||
|
||||
// We could also do the update for r2, but we'll just get to it later.
|
||||
@ -229,7 +229,7 @@ fn generalized_trim_back(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!("Excluding collision between original polylines of {} and something, because stuff's too short", id);
|
||||
timer.warn(format!("Excluding collision between original polylines of {} and something, because stuff's too short", id));
|
||||
}
|
||||
|
||||
// Shift those final centers out again to find the main endpoints for the polygon.
|
||||
@ -281,7 +281,7 @@ fn generalized_trim_back(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!("Excluding collision between original polylines of {} and something, because stuff's too short", id);
|
||||
timer.warn(format!("Excluding collision between original polylines of {} and something, because stuff's too short", id));
|
||||
}
|
||||
}
|
||||
// TODO Caller will close off the polygon. Does that affect our dedupe?
|
||||
@ -292,7 +292,7 @@ fn deadend(
|
||||
roads: &mut BTreeMap<StableRoadID, Road>,
|
||||
i: StableIntersectionID,
|
||||
lines: &Vec<(StableRoadID, Line, PolyLine, PolyLine)>,
|
||||
) -> Vec<Pt2D> {
|
||||
) -> Warn<Vec<Pt2D>> {
|
||||
let (id, _, pl_a, pl_b) = &lines[0];
|
||||
let pt1 = pl_a
|
||||
.reversed()
|
||||
@ -324,12 +324,19 @@ fn deadend(
|
||||
.0;
|
||||
}
|
||||
|
||||
vec![pt1.unwrap(), pt2.unwrap(), pl_b.last_pt(), pl_a.last_pt()]
|
||||
Warn::ok(vec![
|
||||
pt1.unwrap(),
|
||||
pt2.unwrap(),
|
||||
pl_b.last_pt(),
|
||||
pl_a.last_pt(),
|
||||
])
|
||||
} else {
|
||||
error!(
|
||||
Warn::warn(
|
||||
vec![pl_a.last_pt(), pl_b.last_pt()],
|
||||
format!(
|
||||
"{} is a dead-end for {}, which is too short to make degenerate intersection geometry",
|
||||
i, id
|
||||
);
|
||||
vec![pl_a.last_pt(), pl_b.last_pt()]
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ pub fn get_lane_specs(
|
||||
edits: &MapEdits,
|
||||
) -> Vec<LaneSpec> {
|
||||
let (side1_types, side2_types) = if let Some(e) = edits.roads.get(&id) {
|
||||
info!("Using edits for {}", id);
|
||||
println!("Using edits for {}", id);
|
||||
(e.forwards_lanes.clone(), e.backwards_lanes.clone())
|
||||
} else {
|
||||
get_lane_types(r)
|
||||
|
@ -83,10 +83,10 @@ impl InitialMap {
|
||||
|
||||
for (stable_id, r) in &data.roads {
|
||||
if r.i1 == r.i2 {
|
||||
error!(
|
||||
timer.warn(format!(
|
||||
"OSM way {} is a loop on {}, skipping what would've been {}",
|
||||
r.osm_way_id, r.i1, stable_id
|
||||
);
|
||||
));
|
||||
continue;
|
||||
}
|
||||
m.intersections
|
||||
@ -162,6 +162,6 @@ impl InitialMap {
|
||||
self.focus_on = focus_on;
|
||||
self.versions_saved += 1;
|
||||
abstutil::write_binary(&path, self).expect(&format!("Saving {} failed", path));
|
||||
info!("Saved {}", path);
|
||||
println!("Saved {}", path);
|
||||
}
|
||||
}
|
||||
|
@ -39,10 +39,10 @@ pub fn make_all_parcels(
|
||||
}
|
||||
let discarded = input.len() - results.len();
|
||||
if discarded > 0 {
|
||||
info!(
|
||||
timer.note(format!(
|
||||
"Discarded {} parcels that weren't close enough to a sidewalk",
|
||||
discarded
|
||||
);
|
||||
));
|
||||
}
|
||||
timer.stop("convert parcels");
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use crate::{
|
||||
Intersection, IntersectionID, IntersectionType, Lane, LaneID, LaneType, Road, Turn, TurnID,
|
||||
TurnType, LANE_THICKNESS,
|
||||
};
|
||||
use abstutil::wraparound_get;
|
||||
use abstutil::{wraparound_get, Timer, Warn};
|
||||
use geom::{Distance, Line, PolyLine, Pt2D};
|
||||
use nbez::{Bez3o, BezCurve, Point2d};
|
||||
use std::collections::{BTreeSet, HashSet};
|
||||
@ -10,11 +10,16 @@ use std::iter;
|
||||
|
||||
// TODO Add proper warnings when the geometry is too small to handle.
|
||||
|
||||
pub fn make_all_turns(i: &Intersection, roads: &Vec<Road>, lanes: &Vec<Lane>) -> Vec<Turn> {
|
||||
pub fn make_all_turns(
|
||||
i: &Intersection,
|
||||
roads: &Vec<Road>,
|
||||
lanes: &Vec<Lane>,
|
||||
timer: &mut Timer,
|
||||
) -> Vec<Turn> {
|
||||
assert!(i.intersection_type != IntersectionType::Border);
|
||||
|
||||
let mut turns: Vec<Turn> = Vec::new();
|
||||
turns.extend(make_vehicle_turns(i, roads, lanes));
|
||||
turns.extend(make_vehicle_turns(i, roads, lanes, timer));
|
||||
turns.extend(make_walking_turns(i, roads, lanes));
|
||||
let turns = dedupe(turns);
|
||||
|
||||
@ -38,10 +43,10 @@ pub fn make_all_turns(i: &Intersection, roads: &Vec<Road>, lanes: &Vec<Lane>) ->
|
||||
}
|
||||
if !incoming_missing.is_empty() || !outgoing_missing.is_empty() {
|
||||
// TODO Annoying, but this error is noisy for border nodes.
|
||||
error!(
|
||||
timer.warn(format!(
|
||||
"Turns for {} orphan some lanes. Incoming: {:?}, outgoing: {:?}",
|
||||
i.id, incoming_missing, outgoing_missing
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
turns
|
||||
@ -61,7 +66,12 @@ fn dedupe(turns: Vec<Turn>) -> Vec<Turn> {
|
||||
keep
|
||||
}
|
||||
|
||||
fn make_vehicle_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>) -> Vec<Turn> {
|
||||
fn make_vehicle_turns(
|
||||
i: &Intersection,
|
||||
all_roads: &Vec<Road>,
|
||||
lanes: &Vec<Lane>,
|
||||
timer: &mut Timer,
|
||||
) -> Vec<Turn> {
|
||||
let roads: Vec<&Road> = i.roads.iter().map(|r| &all_roads[r.0]).collect();
|
||||
let mut lane_types: BTreeSet<LaneType> = BTreeSet::new();
|
||||
for r in &roads {
|
||||
@ -77,9 +87,8 @@ fn make_vehicle_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>
|
||||
|
||||
for lane_type in lane_types.into_iter() {
|
||||
if i.is_dead_end() {
|
||||
result.extend(make_vehicle_turns_for_dead_end(
|
||||
i, all_roads, lanes, lane_type,
|
||||
));
|
||||
result
|
||||
.extend(make_vehicle_turns_for_dead_end(i, all_roads, lanes, lane_type).get(timer));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -185,16 +194,15 @@ fn make_vehicle_turns_for_dead_end(
|
||||
roads: &Vec<Road>,
|
||||
lanes: &Vec<Lane>,
|
||||
lane_type: LaneType,
|
||||
) -> Vec<Option<Turn>> {
|
||||
) -> Warn<Vec<Option<Turn>>> {
|
||||
let road = &roads[i.roads.iter().next().unwrap().0];
|
||||
let incoming = filter_vehicle_lanes(road.incoming_lanes(i.id), lane_type);
|
||||
let outgoing = filter_vehicle_lanes(road.outgoing_lanes(i.id), lane_type);
|
||||
if incoming.is_empty() || outgoing.is_empty() {
|
||||
error!("{} needs to be a border node!", i.id);
|
||||
return Vec::new();
|
||||
return Warn::warn(Vec::new(), format!("{} needs to be a border node!", i.id));
|
||||
}
|
||||
|
||||
match_up_lanes(lanes, i.id, &incoming, &outgoing)
|
||||
Warn::ok(match_up_lanes(lanes, i.id, &incoming, &outgoing))
|
||||
}
|
||||
|
||||
fn make_walking_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>) -> Vec<Turn> {
|
||||
|
@ -107,10 +107,10 @@ impl Map {
|
||||
for i in &m.intersections {
|
||||
match i.intersection_type {
|
||||
IntersectionType::StopSign => {
|
||||
stop_signs.insert(i.id, ControlStopSign::new(&m, i.id));
|
||||
stop_signs.insert(i.id, ControlStopSign::new(&m, i.id, timer));
|
||||
}
|
||||
IntersectionType::TrafficSignal => {
|
||||
traffic_signals.insert(i.id, ControlTrafficSignal::new(&m, i.id));
|
||||
traffic_signals.insert(i.id, ControlTrafficSignal::new(&m, i.id, timer));
|
||||
}
|
||||
IntersectionType::Border => {}
|
||||
};
|
||||
@ -428,9 +428,9 @@ impl Map {
|
||||
|
||||
pub fn save(&self) {
|
||||
let path = format!("../data/maps/{}_{}.abst", self.name, self.edits.edits_name);
|
||||
info!("Saving {}...", path);
|
||||
println!("Saving {}...", path);
|
||||
abstutil::write_binary(&path, self).expect(&format!("Saving {} failed", path));
|
||||
info!("Saved {}", path);
|
||||
println!("Saved {}", path);
|
||||
}
|
||||
|
||||
pub fn find_closest_lane(&self, from: LaneID, types: Vec<LaneType>) -> Result<LaneID, Error> {
|
||||
|
@ -489,22 +489,22 @@ fn validate(map: &Map, steps: &Vec<PathStep>) {
|
||||
};
|
||||
let len = from.dist_to(to);
|
||||
if len > Distance::ZERO {
|
||||
error!("All steps in invalid path:");
|
||||
println!("All steps in invalid path:");
|
||||
for s in steps {
|
||||
match s {
|
||||
PathStep::Lane(l) => error!(
|
||||
PathStep::Lane(l) => println!(
|
||||
" {:?} from {} to {}",
|
||||
s,
|
||||
map.get_l(*l).src_i,
|
||||
map.get_l(*l).dst_i
|
||||
),
|
||||
PathStep::ContraflowLane(l) => error!(
|
||||
PathStep::ContraflowLane(l) => println!(
|
||||
" {:?} from {} to {}",
|
||||
s,
|
||||
map.get_l(*l).dst_i,
|
||||
map.get_l(*l).src_i
|
||||
),
|
||||
PathStep::Turn(_) => error!(" {:?}", s),
|
||||
PathStep::Turn(_) => println!(" {:?}", s),
|
||||
}
|
||||
}
|
||||
panic!(
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{IntersectionID, LaneID, Map, TurnID, TurnPriority, TurnType};
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap, Error};
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap, Error, Timer, Warn};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
|
||||
@ -16,9 +16,9 @@ pub struct ControlStopSign {
|
||||
}
|
||||
|
||||
impl ControlStopSign {
|
||||
pub fn new(map: &Map, id: IntersectionID) -> ControlStopSign {
|
||||
let ss = smart_assignment(map, id);
|
||||
ss.validate(map).unwrap();
|
||||
pub fn new(map: &Map, id: IntersectionID, timer: &mut Timer) -> ControlStopSign {
|
||||
let ss = smart_assignment(map, id).get(timer);
|
||||
ss.validate(map).unwrap().get(timer);
|
||||
ss
|
||||
}
|
||||
|
||||
@ -59,21 +59,24 @@ impl ControlStopSign {
|
||||
.is_none()
|
||||
}
|
||||
|
||||
fn validate(&self, map: &Map) -> Result<(), Error> {
|
||||
// Returns both errors and warnings.
|
||||
fn validate(&self, map: &Map) -> Result<Warn<()>, Error> {
|
||||
let mut warnings = Vec::new();
|
||||
|
||||
// Does the assignment cover the correct set of turns?
|
||||
let all_turns = &map.get_i(self.id).turns;
|
||||
// TODO Panic after stabilizing merged intersection issues.
|
||||
if self.turns.len() != all_turns.len() {
|
||||
error!(
|
||||
warnings.push(format!(
|
||||
"Stop sign for {} has {} turns but should have {}",
|
||||
self.id,
|
||||
self.turns.len(),
|
||||
all_turns.len()
|
||||
);
|
||||
));
|
||||
}
|
||||
for t in all_turns {
|
||||
if !self.turns.contains_key(t) {
|
||||
error!("Stop sign for {} is missing {}", self.id, t);
|
||||
warnings.push(format!("Stop sign for {} is missing {}", self.id, t));
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,11 +103,11 @@ impl ControlStopSign {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(Warn::empty_warnings(warnings))
|
||||
}
|
||||
}
|
||||
|
||||
fn smart_assignment(map: &Map, id: IntersectionID) -> ControlStopSign {
|
||||
fn smart_assignment(map: &Map, id: IntersectionID) -> Warn<ControlStopSign> {
|
||||
if map.get_i(id).roads.len() <= 2 {
|
||||
return for_degenerate_and_deadend(map, id);
|
||||
}
|
||||
@ -154,7 +157,7 @@ fn smart_assignment(map: &Map, id: IntersectionID) -> ControlStopSign {
|
||||
ranks.insert(rank);
|
||||
}
|
||||
if ranks.len() == 1 {
|
||||
return all_way_stop(map, id);
|
||||
return Warn::ok(all_way_stop(map, id));
|
||||
}
|
||||
|
||||
let mut ss = ControlStopSign {
|
||||
@ -176,7 +179,7 @@ fn smart_assignment(map: &Map, id: IntersectionID) -> ControlStopSign {
|
||||
ss.turns.insert(*t, TurnPriority::Stop);
|
||||
}
|
||||
}
|
||||
ss
|
||||
Warn::ok(ss)
|
||||
}
|
||||
|
||||
fn all_way_stop(map: &Map, id: IntersectionID) -> ControlStopSign {
|
||||
@ -191,7 +194,7 @@ fn all_way_stop(map: &Map, id: IntersectionID) -> ControlStopSign {
|
||||
ss
|
||||
}
|
||||
|
||||
fn for_degenerate_and_deadend(map: &Map, id: IntersectionID) -> ControlStopSign {
|
||||
fn for_degenerate_and_deadend(map: &Map, id: IntersectionID) -> Warn<ControlStopSign> {
|
||||
let mut ss = ControlStopSign {
|
||||
id,
|
||||
turns: BTreeMap::new(),
|
||||
@ -210,9 +213,11 @@ fn for_degenerate_and_deadend(map: &Map, id: IntersectionID) -> ControlStopSign
|
||||
// intersection geometry), sometimes more turns conflict than really should. For now, just
|
||||
// detect and fallback to an all-way stop.
|
||||
if let Err(err) = ss.validate(map) {
|
||||
warn!("Giving up on for_degenerate_and_deadend({}): {}", id, err);
|
||||
return all_way_stop(map, id);
|
||||
return Warn::warn(
|
||||
all_way_stop(map, id),
|
||||
format!("Giving up on for_degenerate_and_deadend({}): {}", id, err),
|
||||
);
|
||||
}
|
||||
|
||||
ss
|
||||
Warn::ok(ss)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{IntersectionID, Map, RoadID, TurnID, TurnPriority, TurnType};
|
||||
use abstutil::Error;
|
||||
use abstutil::{Error, Timer, Warn};
|
||||
use geom::Duration;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::BTreeSet;
|
||||
@ -14,13 +14,13 @@ pub struct ControlTrafficSignal {
|
||||
}
|
||||
|
||||
impl ControlTrafficSignal {
|
||||
pub fn new(map: &Map, id: IntersectionID) -> ControlTrafficSignal {
|
||||
pub fn new(map: &Map, id: IntersectionID, timer: &mut Timer) -> ControlTrafficSignal {
|
||||
if let Some(ts) = ControlTrafficSignal::four_way_four_phase(map, id) {
|
||||
ts
|
||||
} else if let Some(ts) = ControlTrafficSignal::three_way(map, id) {
|
||||
ts
|
||||
} else {
|
||||
ControlTrafficSignal::greedy_assignment(map, id).unwrap()
|
||||
ControlTrafficSignal::greedy_assignment(map, id).get(timer)
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,14 +83,16 @@ impl ControlTrafficSignal {
|
||||
pub fn greedy_assignment(
|
||||
map: &Map,
|
||||
intersection: IntersectionID,
|
||||
) -> Option<ControlTrafficSignal> {
|
||||
) -> Warn<ControlTrafficSignal> {
|
||||
if map.get_turns_in_intersection(intersection).is_empty() {
|
||||
error!("{} has no turns", intersection);
|
||||
return Some(ControlTrafficSignal {
|
||||
return Warn::warn(
|
||||
ControlTrafficSignal {
|
||||
id: intersection,
|
||||
cycles: vec![Cycle::new(intersection, 0)],
|
||||
changed: false,
|
||||
});
|
||||
},
|
||||
format!("{} has no turns", intersection),
|
||||
);
|
||||
}
|
||||
|
||||
let mut cycles = Vec::new();
|
||||
@ -129,11 +131,9 @@ impl ControlTrafficSignal {
|
||||
cycles,
|
||||
changed: false,
|
||||
};
|
||||
if ts.validate(map).is_ok() {
|
||||
Some(ts)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
// This must succeed
|
||||
ts.validate(map).unwrap();
|
||||
Warn::ok(ts)
|
||||
}
|
||||
|
||||
pub fn three_way(map: &Map, i: IntersectionID) -> Option<ControlTrafficSignal> {
|
||||
|
Loading…
Reference in New Issue
Block a user