mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 03:35:51 +03:00
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:
parent
5db0a7ad9d
commit
084b9d74cd
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user