just use 3 turn priorities, interpret them a bit differently.

temporarily kinda breaking stop signs
This commit is contained in:
Dustin Carlino 2019-11-09 13:35:55 -08:00
parent e6fcc50696
commit 7b2a0b87b3
6 changed files with 63 additions and 70 deletions

View File

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

View File

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

View File

@ -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<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 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<ControlStop
for t in &map.get_i(id).turns {
// Only the crosswalks should conflict with other turns.
let priority = match map.get_t(*t).turn_type {
TurnType::Crosswalk => TurnPriority::Stop,
TurnType::Crosswalk => TurnPriority::Yield,
TurnType::LaneChangeLeft | TurnType::LaneChangeRight => TurnPriority::Yield,
_ => TurnPriority::Priority,
_ => TurnPriority::Protected,
};
ss.turns.insert(*t, priority);
}

View File

@ -77,7 +77,7 @@ impl ControlTrafficSignal {
let expected_turns: BTreeSet<TurnID> = map.get_i(self.id).turns.iter().cloned().collect();
let mut actual_turns: BTreeSet<TurnID> = 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<TurnID>,
pub protected_turns: BTreeSet<TurnID>,
pub yield_turns: BTreeSet<TurnID>,
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<Phase>, map: &Map, intersection: IntersectionID) {
let all_turns: Vec<TurnID> = map
.get_turns_in_intersection(intersection)
@ -525,8 +525,8 @@ fn expand_all_phases(phases: &mut Vec<Phase>, 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
},

View File

@ -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)]

View File

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