Cache the list of nearby intersections to wake up for uber-turns. #497 (#513)

This shouldn't have any behavioral change.
This commit is contained in:
Dustin Carlino 2021-02-12 22:12:46 -08:00 committed by GitHub
parent d6ba8e92af
commit 3685f7b18a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 11 deletions

View File

@ -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:

View File

@ -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();

View File

@ -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<Request>,
// 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<IntersectionID>,
signal: Option<SignalState>,
}
@ -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);
}
}
}