From 3685f7b18ab52698a8805c86eb192a6e65f9280f Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Fri, 12 Feb 2021 22:12:46 -0800 Subject: [PATCH] Cache the list of nearby intersections to wake up for uber-turns. #497 (#513) This shouldn't have any behavioral change. --- README.md | 1 + importer/src/bin/generate_houses.rs | 8 +++++-- sim/src/mechanics/intersection.rs | 35 +++++++++++++++++++++-------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 1e17ac0c4a..3aa07a03bb 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ Others: - Lots of help with rendering SVG and fonts from [RazrFalcon](https://github.com/RazrFalcon) and [nical](https://github.com/nical) +- Lots of traffic signal and uber-turn work from [Bruce](https://github.com/BruceBrown) Data: diff --git a/importer/src/bin/generate_houses.rs b/importer/src/bin/generate_houses.rs index d3ed45a6ce..32b064367d 100644 --- a/importer/src/bin/generate_houses.rs +++ b/importer/src/bin/generate_houses.rs @@ -6,7 +6,7 @@ use std::collections::HashSet; use aabb_quadtree::QuadTree; use geojson::{Feature, FeatureCollection, GeoJson}; -use rand::{SeedableRng, Rng}; +use rand::{Rng, SeedableRng}; use rand_xorshift::XorShiftRng; use abstutil::{CmdArgs, Timer}; @@ -24,7 +24,11 @@ fn main() { let houses = generate_buildings_on_empty_residential_roads(&map, &mut rng, &mut timer); if houses.len() <= num_required { - panic!("Only generated {} houses, but wanted at least {}", houses.len(), num_required); + panic!( + "Only generated {} houses, but wanted at least {}", + houses.len(), + num_required + ); } let mut features = Vec::new(); diff --git a/sim/src/mechanics/intersection.rs b/sim/src/mechanics/intersection.rs index 7cbace547d..cdcba26c2f 100644 --- a/sim/src/mechanics/intersection.rs +++ b/sim/src/mechanics/intersection.rs @@ -64,6 +64,9 @@ struct State { // complete the entire sequence. This is especially necessary since groups of traffic signals // are not yet configured as one. reserved: BTreeSet, + // In some cases, a turn completing at one intersection may affect agents waiting to start an + // uber-turn at nearby intersections. + uber_turn_neighbors: Vec, signal: Option, } @@ -111,11 +114,16 @@ impl IntersectionSimState { accepted: BTreeSet::new(), waiting: BTreeMap::new(), reserved: BTreeSet::new(), + uber_turn_neighbors: Vec::new(), signal: None, }; if i.is_traffic_signal() { state.signal = Some(SignalState::new(i.id, Time::START_OF_DAY, map, scheduler)); } + if let Some(mut set) = map_model::IntersectionCluster::autodetect(i.id, map) { + set.remove(&i.id); + state.uber_turn_neighbors.extend(set); + } sim.state.insert(i.id, state); } sim @@ -130,13 +138,6 @@ impl IntersectionSimState { map: &Map, handling_live_edits: bool, ) { - // wake up intersections in the cluster in order to start uber-turns. - if let Some(set) = map_model::IntersectionCluster::autodetect(turn.parent, map) { - for id in &set { - self.wakeup_waiting(now, *id, scheduler, map); - } - } - let state = self.state.get_mut(&turn.parent).unwrap(); assert!(state.accepted.remove(&Request { agent, turn })); state.reserved.remove(&Request { agent, turn }); @@ -145,11 +146,19 @@ impl IntersectionSimState { } if self.break_turn_conflict_cycles { if let AgentID::Car(car) = agent { - // todo: when drain_filter() is no longer experimental, use it instead of - // retian_btreeset() + // TODO when drain_filter() is no longer experimental, use it instead of + // retain_btreeset() retain_btreeset(&mut self.blocked_by, |(_, c)| *c != car); } } + + // If this intersection has uber-turns going through it, then we may need to wake up agents + // with a reserved uber-turn that're waiting at nearby intersections. They may have + // reserved their sequence of turns but then gotten stuck by somebody filling up a queue a + // few steps away. + for id in &self.state[&turn.parent].uber_turn_neighbors { + self.wakeup_waiting(now, *id, scheduler, map); + } } /// For deleting cars @@ -561,6 +570,14 @@ impl IntersectionSimState { } (None, None) => {} } + + // It's unlikely, but the player might create/destroy traffic signals close together and + // change the uber-turns that exist. To be safe, recalculate everywhere. + state.uber_turn_neighbors.clear(); + if let Some(mut set) = map_model::IntersectionCluster::autodetect(state.id, map) { + set.remove(&state.id); + state.uber_turn_neighbors.extend(set); + } } }