map_model/edits/perma_traffic_signal.rs
1//! A representation of traffic signal configuration that references OpenStreetMap IDs and is
2//! hopefully robust to minor edits over time.
3
4use std::collections::BTreeSet;
5
6use serde::{Deserialize, Serialize};
7
8#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
9pub struct TrafficSignal {
10 /// The ID of the OSM node representing the intersection with the traffic signal. This node
11 /// should be tagged `highway = traffic_signals` in OSM.
12 ///
13 /// TODO Describe how consolidated intersections are handled.
14 pub intersection_osm_node_id: i64,
15 /// The traffic signal uses configuration from one plan at a time. The plans must be listed in
16 /// order of ascending `start_time_seconds`, the first plan must begin at `0` (midnight), and
17 /// the last plan must not start after 24 hours.
18 pub plans: Vec<Plan>,
19}
20
21/// A plan describes how a traffic signal is configured during some period of time. Multiple plans
22/// allow a single intersection to behave differently in the middle of the night with low traffic,
23/// compared to the middle of rush hour.
24#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
25pub struct Plan {
26 /// This plan takes effect at this local time, measured in seconds after midnight. The plan
27 /// lasts until the next plan in the listed sequence starts, or ends at midnight if it's the
28 /// last plan.
29 pub start_time_seconds: usize,
30 /// The traffic signal repeatedly cycles through these stages. During each stage, only some
31 /// turns are protected and permitted through the intersection.
32 pub stages: Vec<Stage>,
33 /// Relative to a central clock, delay the first stage by this many seconds.
34 pub offset_seconds: usize,
35}
36
37/// A traffic signal is in one stage at any time. The stage describes what movements are possible.
38#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
39pub struct Stage {
40 /// During this stage, these turns can be performed with the highest priority, protected by a
41 /// green light. No two protected turns in the same stage should cross; that would be a
42 /// conflict.
43 pub protected_turns: BTreeSet<Turn>,
44 /// During this stage, these turns can be performed after yielding. For example, an unprotected
45 /// left turn after yielding to oncoming traffic, or a right turn on red after yielding to
46 /// oncoming traffic and crosswalks.
47 pub permitted_turns: BTreeSet<Turn>,
48 /// The stage lasts this long before moving to the next one.
49 pub stage_type: StageType,
50}
51
52/// How long a stage lasts before moving to the next one.
53#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
54pub enum StageType {
55 /// A fixed number of seconds.
56 Fixed(usize),
57 /// Minimum, Delay, Additional
58 /// Minimum is the minimum cycle duration, 0 allows it to be skipped if no demand.
59 /// Delay is the duration with no demand needed to end a cycle, 0 ends as soon as there is no
60 /// demand. Additional is the maximum additional duration for an extended cycle. If minimum
61 /// is 20, and additional is 40, the maximum cycle duration is 60.
62 /// If there are crosswalks, the minimum is the minimum for the maximum crosswalks
63 Variable(usize, usize, usize),
64}
65
66/// A movement through an intersection.
67///
68/// Movements over crosswalks are a little confusing to understand. See the crosswalk_turns.png
69/// diagram in this repository for some clarification.
70#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
71pub struct Turn {
72 /// The movement begins at the end of this road segment.
73 pub from: DirectedRoad,
74 /// The movement ends at the beginning of this road segment.
75 pub to: DirectedRoad,
76 /// The ID of the OSM node representing the intersection. This is redundant for turns performed
77 /// by vehicles, but is necessary for disambiguating the 4 cases of crosswalks.
78 pub intersection_osm_node_id: i64,
79 /// True iff the movement is along a crosswalk. Note that moving over a crosswalk has a
80 /// different `Turn` for each direction.
81 pub is_crosswalk: bool,
82}
83
84/// A road segment connecting two intersections, and a direction along the segment.
85#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
86pub struct DirectedRoad {
87 /// The ID of the OSM way representing the road.
88 pub osm_way_id: i64,
89 /// The ID of the OSM node at the start of this road segment.
90 pub osm_node1: i64,
91 /// The ID of the OSM node at the end of this road segment.
92 pub osm_node2: i64,
93 /// The direction along the road segment. See
94 /// https://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right for details.
95 pub is_forwards: bool,
96}