Skip to content

Derive lane-specific halt points from OpenDRIVE signals - #498

Open
aprabou wants to merge 17 commits into
Scenic-Foundation:mainfrom
aprabou:derive-stop-line-standalone
Open

aprabou wants to merge 17 commits into
Scenic-Foundation:mainfrom
aprabou:derive-stop-line-standalone

Conversation

@aprabou

@aprabou aprabou commented Aug 19, 2026

Copy link
Copy Markdown

Summary

  • preserve OpenDRIVE signal placement, validity, semantics, and element references
  • derive a longitudinal stopping station separately from the physical signal position
  • expose lane-specific and next-ahead halt points while excluding outgoing junction lanes

Test plan

  • pytest -q tests/formats/opendrive/test_signal_halt_encodings.py
  • pytest -q tests/formats/opendrive/test_opendrive.py
  • Black formatting check for changed files

Preserve signal placement and reference metadata so driving behaviors can distinguish physical devices from applicable stopping locations.
@aprabou
aprabou marked this pull request as draft August 19, 2026 20:50
Limit halt decisions to road-relative signal metadata until physical pole coordinate conversion is implemented reliably.
Preserve effective stop semantics and propagate ordered signal positions through the road hierarchy so driving logic can query applicable signals in travel order.
Preserve exact modern semantics while warning developers away from legacy country and subtype metadata.
@aprabou

aprabou commented Sep 8, 2026

Copy link
Copy Markdown
Author

#491 has maneuver ⇔ signal work which is not present in this PR, so will keep that open.

@aprabou

aprabou commented Sep 20, 2026

Copy link
Copy Markdown
Author

Update: the earlier note that #491 was not in this PR is outdated. Maneuver↔signal linking from #491 was migrated here in 5e6bf18, and #491 is closed.

…object per device.

Document stop/four-way/yield/traffic-light/turn-on-red as tags, put unknown literals in otherTags, and keep CARLA type codes (206/205/1000001) as classifiers. Four-way still halts. Point maneuver.signal at the approach copy used for halt, not the discarded connector clone.
@aprabou
aprabou marked this pull request as ready for review September 20, 2026 07:02

@Eric-Vin Eric-Vin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the work on this Ashwin! I'm seeing some strange behavior when I try to use these changes locally. Can you check the following:

  • I'm not seeing any signal tags for the Carla maps (specifically Town05). Can you investigate this and also add a test?
  • I'm seeing some duplicate signals (i.e. signals at the same s value), but it's difficult to tell if this is correct or not since I'm not sure what the signals are due to the above issue.
  • Let's add some visualization to the 2D driving domain visualizer. I'm thinking we should render all stoplines, and then we can render a small symbol near it indicating what kind of stopline it is (e.g. stop-sign, signal, etc...). This will help us sanity check that the map looks correct.

def predecessor(self):
return _rejectIfNonexistent(self._predecessor, "predecessor")

@property

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need to make these @property? Since we aren't going to reject if they don't exist (they'll just be empty), I don't know if that's necessary.

FOUR_WAY = "fourWay" #: All-way stop: every approach must halt.
YIELD = "yield" #: Give way to conflicting traffic; stop only if needed.
TRAFFIC_LIGHT = "trafficLight"
#: Signalized control; whether to proceed depends on the current indication.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We may want to specify whether one of TURN_ON_RED_ALLOWED and TURN_ON_RED_ALLOWED must be present, or if we can have a light with neither.

# Signal entries are ordered by element-local s, which always increases from
# the start of this element's centerline to its end. For backward lanes this
# is travel order, the reverse of OpenDRIVE road-s order.
SignalEntry = Tuple[

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should we make this SignalEntries, or is there a better name? Also, we probably want to minimize the amount of XODR specific things in this class.

_signalEntries: Tuple[SignalEntry, ...] = ()
_signalSValues: Tuple[float, ...] = ()

def signalLookup(self) -> Tuple[List[SignalEntry], List[float]]:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it makes more sense to zip this and return a tuple of tuples.

@Eric-Vin

Copy link
Copy Markdown
Collaborator

Pushed some commits to fix the pickle test failures, since those are pretty tricky.

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.

2 participants