Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make leader agents call ahead before starting a turn, and stop cutting #900

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

dabreegster
Copy link
Collaborator

off approaching vehicles at stop signs. #517

Why did the chicken cross the road? Because it was only checking for higher priority traffic right at the edge of the intersection, not a meter away. This PR makes vehicles at the front of their queue "call ahead" and send the ETA when they'd try to start their turn. Then other agents have the opportunity to see if they might cut off an approaching vehicle.

Net results are much more reasonable ordering at stop signs. North/south traffic has priority here, but watch the utter anarchy before this change:

before.mp4

With this PR, things get better, though the northbound left turner still seems a little hesitant:

after.mp4

I'm not yet attempting similar logic at traffic signals. Both stop signs and signals have some weird logic, previously motivated by trying to resolve gridlock -- use the scheduler to let higher-priority agents go first, and don't do so many checks when trying to start a turn. Honestly all of this needs a full overhaul and more careful tests, but just making small steps forward.

The original purpose behind this work is to get more realistic pedestrian/vehicle interactions. That actually comes down to whether crosswalks are marked or unmarked. I'll follow up with some ideas to set those values more realistically.

@dabreegster
Copy link
Collaborator Author

Not ready after all... there are cases where everyone stalls at a stop sign and seem to never retry a turn that was blocked by an approaching vehicle.

@dabreegster
Copy link
Collaborator Author

Before the clock strikes 12... bug was lane-changing, of course. Agent could change their mind about what lane to target between sending their first ETA and starting the turn. Fixed. Will validate and push in the AM, then see if this combined with downgraded crossings produces better behavior.

Comment on lines 881 to 931
if other_turn.conflicts_with(turn) {
// Now we need to prioritize between the two. First use the stop sign priority
let their_priority = sign.get_priority(other_req.turn, map);
let should_yield = if our_priority < their_priority {
true
} else if our_priority > their_priority {
false
} else {
// Same priority by the stop sign, so check turn types
let turn_type_ranks = if map.get_config().driving_side == DrivingSide::Right {
vec![TurnType::Straight, TurnType::Right, TurnType::Left]
} else {
vec![TurnType::Straight, TurnType::Left, TurnType::Right]
};

// Other turn types (U-turns and pedestrian crossings) always lose. That
// should probably be configurable
let our_rank = turn_type_ranks
.iter()
.position(|x| *x == turn.turn_type)
.unwrap_or(3);
let their_rank = turn_type_ranks
.iter()
.position(|x| *x == other_turn.turn_type)
.unwrap_or(3);
// 0 is the highest rank here
// If all the priorities are equal, we should go -- we're ready to start;
// they're still approaching.
our_rank > their_rank

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very cool. You get to encode the driver's interpretations of the road rules and priority. Even let them take risks (like following a leader into an intersection, hoping traffic will keep flowing until you get out).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discrete events mean these decisions only happen at a few moments, and it's important to "wake everyone up" anytime there's a potential decision to make. And the complication this PR is exposing is the difference between people at the intersection already waiting, and those approaching it. But in principle, yes, one place to decide this ordering.

@BudgieInWA
Copy link

though the northbound left turner still seems a little hesitant
I thought they did well waiting for all the through traffic, then waiting for his exit to clear.

@dabreegster
Copy link
Collaborator Author

I found a gridlock at one intersection that's pretty rare -- leaders send an ETA, but if somebody new exits a driveway and appears in front, they become the new leader. The old one never deregistered, so people were yielding to agents who weren't the leader and couldn't proceed.

So then I made leaders be keyed by origin lane and get overwritten in this case. That problem solved, but then it exposed a problem where the nice ordering of agents based on stop sign priority and straight > right > left turns was relying on ETAs that now don't seem to get filled out as often, and so I tried adding back the logic to also look at agents that're ready to start their turn.

But then the SMP scenario breaks utterly; pedestrians keep streaming across crosswalks and cutting off vehicles unrealistically. So I don't think I'll be able to merge this PR until I detangle the entire mess there. So hard to make incremental steps. :(

@dabreegster
Copy link
Collaborator Author

Looking at how the discrete event interactions at intersections work again, I think the whole protocol is backwards. Agents ask to start turns, go to sleep when denied, get woken up in very particular orders, then ask again, and now there's all this complicated ordering during that decision. And it's definitely a load of wasted computation in gridlock scenarios, as everyone keeps asking only to get denied.

I want to invert things. Agents still send ETAs and say when they arrive at an intersection. But then intersections should be able to directly tell an agent when to start their turn. Not just wake them up and have them call maybe_start_turn again, but actually do the "are they blocked?" calculation and tell them to start.

@dabreegster
Copy link
Collaborator Author

Alright, digging out of the rabbit hole a bit -- 4b446c7 has no behavioral changes, just gets the ETA plumbing done. I urgentlyish need to fix a particular situation in one map, and it has nothing to do with approaching agents; the ordering at a stop sign between waiting agents isn't realistic:

screencast.mp4

So for the moment, will set aside this PR and the ideas for rethinking intersection protocol

@BudgieInWA
Copy link

Looking at how the discrete event interactions at intersections work again ... I want to invert things. Agents still send ETAs and say when they arrive at an intersection. But then intersections should be able to directly tell an agent when to start their turn. Not just wake them up and have them call maybe_start_turn again, but actually do the "are they blocked?" calculation and tell them to start.

This reminds me of an idea that has stuck with me for years ever since reading it in the Citybound design doc:

simulate the most strongly locally interacting traffic entities (e.g. cars on one lane) all at once within one actor (one lane = one actor)

I am interested to see how it applies to the A/B Street simulation, as I learn more about the implementation and as you iterate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants