diff --git a/game/src/edit/traffic_signals.rs b/game/src/edit/traffic_signals.rs index d319a8e423..13fea11f81 100644 --- a/game/src/edit/traffic_signals.rs +++ b/game/src/edit/traffic_signals.rs @@ -78,8 +78,8 @@ impl State for TrafficSignalEditor { let next_priority = match phase.get_priority(id) { TurnPriority::Banned => { if ui.primary.map.get_t(id).turn_type == TurnType::Crosswalk { - if phase.could_be_priority_turn(id, &ui.primary.map) { - Some(TurnPriority::Priority) + if phase.could_be_protected_turn(id, &ui.primary.map) { + Some(TurnPriority::Protected) } else { None } @@ -87,17 +87,14 @@ impl State for TrafficSignalEditor { Some(TurnPriority::Yield) } } - TurnPriority::Stop => { - panic!("Can't have TurnPriority::Stop in a traffic signal"); - } TurnPriority::Yield => { - if phase.could_be_priority_turn(id, &ui.primary.map) { - Some(TurnPriority::Priority) + if phase.could_be_protected_turn(id, &ui.primary.map) { + Some(TurnPriority::Protected) } else { Some(TurnPriority::Banned) } } - TurnPriority::Priority => Some(TurnPriority::Banned), + TurnPriority::Protected => Some(TurnPriority::Banned), }; if let Some(pri) = next_priority { if ctx.input.contextual_action( @@ -173,7 +170,7 @@ impl State for TrafficSignalEditor { let mut phase = Phase::new(self.diagram.i); for t in ui.primary.map.get_turns_in_intersection(self.diagram.i) { if t.between_sidewalks() { - phase.edit_turn(t, TurnPriority::Priority); + phase.edit_turn(t, TurnPriority::Protected); } } signal.phases.insert(current_phase, phase); @@ -205,14 +202,13 @@ impl State for TrafficSignalEditor { let phase = &map.get_traffic_signal(self.diagram.i).phases[self.diagram.current_phase()]; for t in &ui.primary.draw_map.get_turns(self.diagram.i, map) { let arrow_color = match phase.get_priority(t.id) { - TurnPriority::Priority => ui + TurnPriority::Protected => ui .cs .get_def("priority turn in current phase", Color::GREEN), TurnPriority::Yield => ui .cs .get_def("yield turn in current phase", Color::rgb(255, 105, 180)), TurnPriority::Banned => ui.cs.get_def("turn not in current phase", Color::BLACK), - TurnPriority::Stop => panic!("Can't have TurnPriority::Stop in a traffic signal"), }; t.draw_icon( &mut batch, diff --git a/game/src/render/traffic_signal.rs b/game/src/render/traffic_signal.rs index 7caa7a11bb..f4f405f71c 100644 --- a/game/src/render/traffic_signal.rs +++ b/game/src/render/traffic_signal.rs @@ -28,12 +28,12 @@ pub fn draw_signal_phase( ); for (id, crosswalk) in &ctx.draw_map.get_i(phase.parent).crosswalks { - if phase.get_priority(*id) == TurnPriority::Priority { + if phase.get_priority(*id) == TurnPriority::Protected { batch.append(crosswalk.clone()); } } - for t in &phase.priority_turns { + for t in &phase.protected_turns { let turn = ctx.map.get_t(*t); if !turn.between_sidewalks() { DrawTurn::full_geom(turn, batch, priority_color); @@ -83,7 +83,7 @@ pub fn draw_signal_phase( // TODO Written in a complicated way, and still doesn't look right. fn draw_signal_phase_with_icons(phase: &Phase, batch: &mut GeomBatch, ctx: &DrawCtx) { for (id, crosswalk) in &ctx.draw_map.get_i(phase.parent).crosswalks { - if phase.get_priority(*id) == TurnPriority::Priority { + if phase.get_priority(*id) == TurnPriority::Protected { batch.append(crosswalk.clone()); } } @@ -106,7 +106,7 @@ fn draw_signal_phase_with_icons(phase: &Phase, batch: &mut GeomBatch, ctx: &Draw } match phase.get_priority(turn.id) { - TurnPriority::Priority => { + TurnPriority::Protected => { green.push(turn.id); } TurnPriority::Yield => { @@ -115,7 +115,6 @@ fn draw_signal_phase_with_icons(phase: &Phase, batch: &mut GeomBatch, ctx: &Draw TurnPriority::Banned => { red.push(turn.id); } - TurnPriority::Stop => unreachable!(), } } let count = vec![&green, &yellow, &red] diff --git a/map_model/src/stop_signs.rs b/map_model/src/stop_signs.rs index e1881f8a38..39f519415a 100644 --- a/map_model/src/stop_signs.rs +++ b/map_model/src/stop_signs.rs @@ -85,9 +85,10 @@ impl ControlStopSign { self.turns[&turn] } + // TODO rm pub fn could_be_priority_turn(&self, id: TurnID, map: &Map) -> bool { for (t, pri) in &self.turns { - if *pri == TurnPriority::Priority && map.get_t(id).conflicts_with(map.get_t(*t)) { + if *pri == TurnPriority::Protected && map.get_t(id).conflicts_with(map.get_t(*t)) { return false; } } @@ -124,7 +125,7 @@ impl ControlStopSign { } // Are all of the SharedSidewalkCorner prioritized? if map.get_t(*t).turn_type == TurnType::SharedSidewalkCorner { - assert_eq!(self.turns[t], TurnPriority::Priority); + assert_eq!(self.turns[t], TurnPriority::Protected); } } @@ -133,7 +134,7 @@ impl ControlStopSign { .turns .iter() .filter_map(|(turn, pri)| { - if *pri == TurnPriority::Priority { + if *pri == TurnPriority::Protected { Some(*turn) } else { None @@ -171,9 +172,9 @@ impl ControlStopSign { let ss = self.roads.get_mut(&r).unwrap(); ss.enabled = !ss.enabled; let new_pri = if ss.enabled { - TurnPriority::Stop - } else { TurnPriority::Yield + } else { + TurnPriority::Protected }; for l in ss.travel_lanes.clone() { for (turn, _) in map.get_next_turns_and_lanes(l, self.id) { @@ -183,7 +184,7 @@ impl ControlStopSign { if new_pri == TurnPriority::Yield && self.could_be_priority_turn(turn.id, map) { match turn.turn_type { TurnType::Straight | TurnType::Right | TurnType::Crosswalk => { - self.turns.insert(turn.id, TurnPriority::Priority); + self.turns.insert(turn.id, TurnPriority::Protected); } _ => {} } @@ -198,7 +199,7 @@ impl ControlStopSign { for l in &ss.travel_lanes { for (turn, _) in map.get_next_turns_and_lanes(*l, self.id) { match self.turns[&turn.id] { - TurnPriority::Stop | TurnPriority::Banned => { + TurnPriority::Yield | TurnPriority::Banned => { ss.enabled = true; } _ => {} @@ -250,21 +251,21 @@ fn smart_assignment(map: &Map, id: IntersectionID) -> Warn { }; for t in &map.get_i(id).turns { if map.get_t(*t).turn_type == TurnType::SharedSidewalkCorner { - ss.turns.insert(*t, TurnPriority::Priority); + ss.turns.insert(*t, TurnPriority::Protected); } else if rank_per_incoming_lane[&t.src] == highest_rank { // If it's the highest rank road, prioritize main turns and make others yield. ss.turns.insert(*t, TurnPriority::Yield); if ss.could_be_priority_turn(*t, map) { match map.get_t(*t).turn_type { TurnType::Straight | TurnType::Right | TurnType::Crosswalk => { - ss.turns.insert(*t, TurnPriority::Priority); + ss.turns.insert(*t, TurnPriority::Protected); } _ => {} } } } else { // Lower rank roads have to stop. - ss.turns.insert(*t, TurnPriority::Stop); + ss.turns.insert(*t, TurnPriority::Yield); } } Warn::ok(ss) @@ -278,9 +279,9 @@ fn all_way_stop(map: &Map, id: IntersectionID) -> ControlStopSign { }; for t in &map.get_i(id).turns { if map.get_t(*t).turn_type == TurnType::SharedSidewalkCorner { - ss.turns.insert(*t, TurnPriority::Priority); + ss.turns.insert(*t, TurnPriority::Protected); } else { - ss.turns.insert(*t, TurnPriority::Stop); + ss.turns.insert(*t, TurnPriority::Yield); } } ss @@ -295,9 +296,9 @@ fn for_degenerate_and_deadend(map: &Map, id: IntersectionID) -> Warn TurnPriority::Stop, + TurnType::Crosswalk => TurnPriority::Yield, TurnType::LaneChangeLeft | TurnType::LaneChangeRight => TurnPriority::Yield, - _ => TurnPriority::Priority, + _ => TurnPriority::Protected, }; ss.turns.insert(*t, priority); } diff --git a/map_model/src/traffic_signals.rs b/map_model/src/traffic_signals.rs index ad9c65a1fa..501dae09ce 100644 --- a/map_model/src/traffic_signals.rs +++ b/map_model/src/traffic_signals.rs @@ -77,7 +77,7 @@ impl ControlTrafficSignal { let expected_turns: BTreeSet = map.get_i(self.id).turns.iter().cloned().collect(); let mut actual_turns: BTreeSet = BTreeSet::new(); for phase in &self.phases { - actual_turns.extend(phase.priority_turns.iter()); + actual_turns.extend(phase.protected_turns.iter()); actual_turns.extend(phase.yield_turns.iter()); } if expected_turns != actual_turns { @@ -86,8 +86,8 @@ impl ControlTrafficSignal { for phase in &self.phases { // Do any of the priority turns in one phase conflict? - for t1 in phase.priority_turns.iter().map(|t| map.get_t(*t)) { - for t2 in phase.priority_turns.iter().map(|t| map.get_t(*t)) { + for t1 in phase.protected_turns.iter().map(|t| map.get_t(*t)) { + for t2 in phase.protected_turns.iter().map(|t| map.get_t(*t)) { if t1.conflicts_with(t2) { return Err(Error::new(format!( "Traffic signal has conflicting priority turns in one phase:\n{:?}\n\n{:?}", @@ -104,7 +104,7 @@ impl ControlTrafficSignal { assert!(!phase.yield_turns.contains(&t.id)); } TurnType::SharedSidewalkCorner => { - assert!(phase.priority_turns.contains(&t.id)); + assert!(phase.protected_turns.contains(&t.id)); } _ => {} } @@ -131,11 +131,11 @@ impl ControlTrafficSignal { loop { let add_turn = remaining_turns .iter() - .position(|&t| current_phase.could_be_priority_turn(t, map)); + .position(|&t| current_phase.could_be_protected_turn(t, map)); match add_turn { Some(idx) => { current_phase - .priority_turns + .protected_turns .insert(remaining_turns.remove(idx)); } None => { @@ -375,11 +375,11 @@ impl ControlTrafficSignal { for turn in map.get_turns_in_intersection(i) { match turn.turn_type { TurnType::SharedSidewalkCorner => { - all_walk.priority_turns.insert(turn.id); - all_yield.priority_turns.insert(turn.id); + all_walk.protected_turns.insert(turn.id); + all_yield.protected_turns.insert(turn.id); } TurnType::Crosswalk => { - all_walk.priority_turns.insert(turn.id); + all_walk.protected_turns.insert(turn.id); } _ => { all_yield.yield_turns.insert(turn.id); @@ -409,10 +409,10 @@ impl ControlTrafficSignal { for turn in map.get_turns_in_intersection(i) { let parent = map.get_l(turn.id.src).parent; if turn.turn_type == TurnType::SharedSidewalkCorner { - phase.priority_turns.insert(turn.id); + phase.protected_turns.insert(turn.id); } else if turn.turn_type == TurnType::Crosswalk { if parent == adj1 || parent == adj2 { - phase.priority_turns.insert(turn.id); + phase.protected_turns.insert(turn.id); } } else if parent == r { phase.yield_turns.insert(turn.id); @@ -430,10 +430,10 @@ impl ControlTrafficSignal { pub fn convert_to_ped_scramble(&mut self, map: &Map) { // Remove Crosswalk turns from existing phases. for phase in self.phases.iter_mut() { - // Crosswalks are usually only priority_turns, but also clear out from yield_turns. + // Crosswalks are usually only protected_turns, but also clear out from yield_turns. for t in map.get_turns_in_intersection(self.id) { if t.turn_type == TurnType::Crosswalk { - phase.priority_turns.remove(&t.id); + phase.protected_turns.remove(&t.id); phase.yield_turns.remove(&t.id); } } @@ -441,8 +441,8 @@ impl ControlTrafficSignal { // Blindly try to promote yield turns to protected, now that crosswalks are gone. let mut promoted = Vec::new(); for t in &phase.yield_turns { - if phase.could_be_priority_turn(*t, map) { - phase.priority_turns.insert(*t); + if phase.could_be_protected_turn(*t, map) { + phase.protected_turns.insert(*t); promoted.push(*t); } } @@ -454,7 +454,7 @@ impl ControlTrafficSignal { let mut phase = Phase::new(self.id); for t in map.get_turns_in_intersection(self.id) { if t.between_sidewalks() { - phase.edit_turn(t, TurnPriority::Priority); + phase.edit_turn(t, TurnPriority::Protected); } } self.phases.push(phase); @@ -464,7 +464,7 @@ impl ControlTrafficSignal { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Phase { pub parent: IntersectionID, - pub priority_turns: BTreeSet, + pub protected_turns: BTreeSet, pub yield_turns: BTreeSet, pub duration: Duration, } @@ -473,15 +473,15 @@ impl Phase { pub fn new(parent: IntersectionID) -> Phase { Phase { parent, - priority_turns: BTreeSet::new(), + protected_turns: BTreeSet::new(), yield_turns: BTreeSet::new(), duration: Duration::seconds(30.0), } } - pub fn could_be_priority_turn(&self, t1: TurnID, map: &Map) -> bool { + pub fn could_be_protected_turn(&self, t1: TurnID, map: &Map) -> bool { let turn1 = map.get_t(t1); - for t2 in &self.priority_turns { + for t2 in &self.protected_turns { if t1 == *t2 || turn1.conflicts_with(map.get_t(*t2)) { return false; } @@ -490,8 +490,8 @@ impl Phase { } pub fn get_priority(&self, t: TurnID) -> TurnPriority { - if self.priority_turns.contains(&t) { - TurnPriority::Priority + if self.protected_turns.contains(&t) { + TurnPriority::Protected } else if self.yield_turns.contains(&t) { TurnPriority::Yield } else { @@ -505,10 +505,10 @@ impl Phase { ids.extend(t.other_crosswalk_ids.clone()); } for id in ids { - self.priority_turns.remove(&id); + self.protected_turns.remove(&id); self.yield_turns.remove(&id); - if pri == TurnPriority::Priority { - self.priority_turns.insert(id); + if pri == TurnPriority::Protected { + self.protected_turns.insert(id); } else if pri == TurnPriority::Yield { self.yield_turns.insert(id); } @@ -516,7 +516,7 @@ impl Phase { } } -// Add all legal priority turns to existing phases. +// Add all legal protected turns to existing phases. fn expand_all_phases(phases: &mut Vec, map: &Map, intersection: IntersectionID) { let all_turns: Vec = map .get_turns_in_intersection(intersection) @@ -525,8 +525,8 @@ fn expand_all_phases(phases: &mut Vec, map: &Map, intersection: Intersect .collect(); for phase in phases.iter_mut() { for t in &all_turns { - if !phase.priority_turns.contains(t) && phase.could_be_priority_turn(*t, map) { - phase.priority_turns.insert(*t); + if !phase.protected_turns.contains(t) && phase.could_be_protected_turn(*t, map) { + phase.protected_turns.insert(*t); } } } @@ -550,7 +550,7 @@ fn make_phases( for turn in map.get_turns_in_intersection(i) { // These never conflict with anything. if turn.turn_type == TurnType::SharedSidewalkCorner { - phase.priority_turns.insert(turn.id); + phase.protected_turns.insert(turn.id); continue; } @@ -561,7 +561,7 @@ fn make_phases( phase.edit_turn( turn, if protected { - TurnPriority::Priority + TurnPriority::Protected } else { TurnPriority::Yield }, diff --git a/map_model/src/turn.rs b/map_model/src/turn.rs index 6116ed7ec5..6743020b8a 100644 --- a/map_model/src/turn.rs +++ b/map_model/src/turn.rs @@ -54,14 +54,11 @@ pub enum TurnPriority { // Can't do this turn at all! Banned, // For stop signs: cars have to stop before doing this turn, and are accepted with the lowest priority. - // For traffic signals: this priority doesn't make sense; can't be used. - Stop, - // Cars can do this immediately if there are no previously accepted conflicting turns. + // For traffic signals: Cars can do this immediately if there are no previously accepted conflicting turns. Yield, - // These must be non-conflicting, and cars don't have to stop before doing this turn (unless a - // conflicting Yield has been accepted). - // TODO Rename Protected? - Priority, + // For stop signs: cars can do this without stopping. These can conflict! + // For traffic signals: Must be non-conflicting. + Protected, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] diff --git a/sim/src/mechanics/intersection.rs b/sim/src/mechanics/intersection.rs index b1800cb48e..959a50a45a 100644 --- a/sim/src/mechanics/intersection.rs +++ b/sim/src/mechanics/intersection.rs @@ -99,6 +99,7 @@ impl IntersectionSimState { // TODO Only wake up agents that would then be accepted. // Sort by waiting time, so things like stop signs actually are first-come, first-served. + // TODO Actually, this should be by priority first. let mut waiting: Vec<(Request, Duration)> = self.state[&i] .waiting .iter() @@ -132,11 +133,10 @@ impl IntersectionSimState { for req in state.waiting.keys() { match phase.get_priority(req.turn) { TurnPriority::Banned => {} - TurnPriority::Stop => unreachable!(), TurnPriority::Yield => { yields.push(req.agent); } - TurnPriority::Priority => { + TurnPriority::Protected => { // TODO Use update in case turn_finished scheduled an event for them already. scheduler.update(now, Command::update_agent(req.agent)); } @@ -254,7 +254,7 @@ impl State { assert!(our_priority != TurnPriority::Banned); let our_time = self.waiting[req]; - if our_priority == TurnPriority::Stop && now < our_time + WAIT_AT_STOP_SIGN { + if our_priority == TurnPriority::Yield && now < our_time + WAIT_AT_STOP_SIGN { // Since we have "ownership" of scheduling for req.agent, don't need to use // scheduler.update. scheduler.push(