Store delay for traffic signals per direction of travel, using a compressed representation of turn groups. No substantial increase in prebaked file size.

This commit is contained in:
Dustin Carlino 2020-08-20 11:42:36 -07:00
parent 5db0a7ad9d
commit 084b9d74cd
7 changed files with 50 additions and 16 deletions

View File

@ -323,7 +323,7 @@ fn delay_plot(
app.primary.sim.time()
};
if let Some(list) = data.intersection_delays.get(&i) {
for (t, dt, agent_type) in list {
for (_, t, dt, agent_type) in list {
if *t > limit {
break;
}

View File

@ -27,7 +27,9 @@ pub use crate::objects::parking_lot::{ParkingLot, ParkingLotID};
pub use crate::objects::road::{DirectedRoadID, Road, RoadID};
pub use crate::objects::stop_signs::{ControlStopSign, RoadWithStopSign};
pub use crate::objects::traffic_signals::{ControlTrafficSignal, Phase, PhaseType};
pub use crate::objects::turn::{Turn, TurnGroup, TurnGroupID, TurnID, TurnPriority, TurnType};
pub use crate::objects::turn::{
CompressedTurnGroupID, Turn, TurnGroup, TurnGroupID, TurnID, TurnPriority, TurnType,
};
pub use crate::objects::zone::{AccessRestrictions, Zone};
pub use crate::pathfind::uber_turns::{IntersectionCluster, UberTurn, UberTurnGroup};
use crate::pathfind::Pathfinder;

View File

@ -1,13 +1,14 @@
use crate::make::traffic_signals::{brute_force, get_possible_policies};
use crate::raw::OriginalRoad;
use crate::{
osm, DirectedRoadID, IntersectionID, Map, TurnGroup, TurnGroupID, TurnID, TurnPriority,
TurnType,
osm, CompressedTurnGroupID, DirectedRoadID, IntersectionID, Map, TurnGroup, TurnGroupID,
TurnID, TurnPriority, TurnType,
};
use abstutil::{deserialize_btreemap, retain_btreeset, serialize_btreemap, Timer};
use geom::Duration;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet};
use std::convert::TryFrom;
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct ControlTrafficSignal {
@ -167,7 +168,7 @@ impl ControlTrafficSignal {
{
tg.id
} else {
panic!("{} doesn't belong to any turn groups", turn)
panic!("{} doesn't belong to any turn groups in {}", turn, self.id)
}
}
@ -183,6 +184,18 @@ impl ControlTrafficSignal {
}
missing
}
pub fn compressed_id(&self, turn: TurnID) -> CompressedTurnGroupID {
for (idx, tg) in self.turn_groups.values().enumerate() {
if tg.members.contains(&turn) {
return CompressedTurnGroupID {
i: self.id,
idx: u8::try_from(idx).unwrap(),
};
}
}
panic!("{} doesn't belong to any turn groups in {}", turn, self.id)
}
}
impl Phase {

View File

@ -183,6 +183,14 @@ pub struct TurnGroupID {
pub crosswalk: bool,
}
// This is cheaper to store than a TurnGroupID. It simply indexes into the list of turn_groups.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct CompressedTurnGroupID {
pub i: IntersectionID,
// There better not be any intersection with more than 256 turn groups...
pub idx: u8,
}
// TODO Unclear how this plays with different lane types
// This is only useful for traffic signals currently.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]

View File

@ -30,7 +30,8 @@ pub struct Analytics {
pub trip_log: Vec<(Time, TripID, Option<PathRequest>, TripPhaseType)>,
// TODO Transit riders aren't represented here yet, just the vehicle they're riding.
pub intersection_delays: BTreeMap<IntersectionID, Vec<(Time, Duration, AgentType)>>,
// Only for traffic signals. The u8 is the turn group index from a CompressedTurnGroupID.
pub intersection_delays: BTreeMap<IntersectionID, Vec<(u8, Time, Duration, AgentType)>>,
// Per parking lane or lot, when does a spot become filled (true) or free (false)
pub parking_lane_changes: BTreeMap<LaneID, Vec<(Time, bool)>>,
@ -157,9 +158,9 @@ impl Analytics {
// Intersection delays
if let Event::IntersectionDelayMeasured(id, delay, agent) = ev {
self.intersection_delays
.entry(id)
.entry(id.i)
.or_insert_with(Vec::new)
.push((time, delay, agent.to_type()));
.push((id.idx, time, delay, agent.to_type()));
}
// Parking spot changes
@ -276,7 +277,7 @@ impl Analytics {
for (i, list1) in &self.intersection_delays {
if let Some(list2) = before.intersection_delays.get(i) {
let mut sum1 = Duration::ZERO;
for (t, dt, _) in list1 {
for (_, t, dt, _) in list1 {
if *t > now {
break;
}
@ -284,7 +285,7 @@ impl Analytics {
}
let mut sum2 = Duration::ZERO;
for (t, dt, _) in list2 {
for (_, t, dt, _) in list2 {
if *t > now {
break;
}

View File

@ -3,7 +3,8 @@ use crate::{
};
use geom::Duration;
use map_model::{
BuildingID, BusRouteID, BusStopID, IntersectionID, LaneID, Map, Path, PathRequest, Traversable,
BuildingID, BusRouteID, BusStopID, CompressedTurnGroupID, IntersectionID, LaneID, Map, Path,
PathRequest, Traversable,
};
use serde::{Deserialize, Serialize};
@ -41,7 +42,7 @@ pub enum Event {
// If the agent is a transit vehicle, then include a count of how many passengers are on
// board.
AgentEntersTraversable(AgentID, Traversable, Option<usize>),
IntersectionDelayMeasured(IntersectionID, Duration, AgentID),
IntersectionDelayMeasured(CompressedTurnGroupID, Duration, AgentID),
TripFinished {
trip: TripID,

View File

@ -303,8 +303,11 @@ impl IntersectionSimState {
.entry(req.clone())
.or_insert(now);
let shared_sidewalk_corner =
map.get_t(req.turn).turn_type == TurnType::SharedSidewalkCorner;
let readonly_pair = maybe_cars_and_queues.as_ref().map(|(_, c, q)| (*c, &**q));
let allowed = if map.get_t(req.turn).turn_type == TurnType::SharedSidewalkCorner {
let allowed = if shared_sidewalk_corner {
// SharedSidewalkCorner doesn't conflict with anything -- fastpath!
true
} else if !self.handle_accepted_conflicts(&req, map, readonly_pair) {
@ -413,9 +416,15 @@ impl IntersectionSimState {
// for stop signs too.
let state = self.state.get_mut(&turn.parent).unwrap();
let delay = now - state.waiting.remove(&req).unwrap();
if map.maybe_get_traffic_signal(state.id).is_some() {
self.events
.push(Event::IntersectionDelayMeasured(turn.parent, delay, agent));
// SharedSidewalkCorner are always no-conflict, immediate turns; they're not interesting.
if !shared_sidewalk_corner {
if let Some(ts) = map.maybe_get_traffic_signal(state.id) {
self.events.push(Event::IntersectionDelayMeasured(
ts.compressed_id(turn),
delay,
agent,
));
}
}
state.accepted.insert(req);
if self.break_turn_conflict_cycles {