Split out of #476, which anticipated it: "Optionally (separate decision, not required for fidelity): extend LaneType with the ramp family so the mesher/panels treat them as drivable."
#476 made RoadMaker faithful to these lane types — it no longer rewrites them on save. It did not make them usable, and the gap is now visible in a way it was not before.
What the gap is
LaneType models 11 of e_laneType's values (§11.8.1). The whole ramp/merge family is outside it and parses to LaneType::Other:
entry · exit · onRamp · offRamp · connectingRamp · slipLane
Consequences today, after #476:
- Read faithfully, but inert. An
onRamp lane round-trips byte-perfectly and is drawn, but every consumer that asks "is this drivable?" says no. driving_lanes_at (and therefore junction turn generation, edit::connection, and the maneuver set) treats it exactly like none.
- Cannot be authored at all.
Lane::type_str is deliberately read-only from Python, and there is no LaneType value to pass — so a script can preserve an onRamp lane but cannot create one. RoadRunner authors these routinely.
- The properties panel shows "Other", and
rebuild_choice_combo appends that as a synthetic entry. It is honest but unhelpful, and re-picking it is now guarded precisely because it used to destroy the spelling.
Why it is a real decision, not a chore
Adding the six values is mechanical. What is not mechanical:
- Which of them count as drivable for turn generation.
onRamp/offRamp/connectingRamp/entry/exit carry traffic; slipLane does too but bypasses the intersection, which is exactly the case junction generation would need to not treat as an arm.
- Whether the mesher should style them differently from
driving (it currently styles Other as unpainted).
bidirectional, also outside the enum, is deprecated by §11.8.1 in favour of @direction="both" — so it should not be added; it should keep round-tripping as Other and ideally warn with that advice.
Scope
Acceptance
- An
onRamp lane authored from Python writes type="onRamp" and reads back as the same enum value.
core/tests/fuzz/corpus/foreign_enum_spellings.xodr still round-trips byte-identically (its onRamp/slipLane lanes now parse to real values rather than Other — the bytes must not care).
- The documented drivability ruling has a test per value.
Split out of #476, which anticipated it: "Optionally (separate decision, not required for fidelity): extend
LaneTypewith the ramp family so the mesher/panels treat them as drivable."#476 made RoadMaker faithful to these lane types — it no longer rewrites them on save. It did not make them usable, and the gap is now visible in a way it was not before.
What the gap is
LaneTypemodels 11 ofe_laneType's values (§11.8.1). The whole ramp/merge family is outside it and parses toLaneType::Other:entry·exit·onRamp·offRamp·connectingRamp·slipLaneConsequences today, after #476:
onRamplane round-trips byte-perfectly and is drawn, but every consumer that asks "is this drivable?" says no.driving_lanes_at(and therefore junction turn generation,edit::connection, and the maneuver set) treats it exactly likenone.Lane::type_stris deliberately read-only from Python, and there is noLaneTypevalue to pass — so a script can preserve anonRamplane but cannot create one. RoadRunner authors these routinely.rebuild_choice_comboappends that as a synthetic entry. It is honest but unhelpful, and re-picking it is now guarded precisely because it used to destroy the spelling.Why it is a real decision, not a chore
Adding the six values is mechanical. What is not mechanical:
onRamp/offRamp/connectingRamp/entry/exitcarry traffic;slipLanedoes too but bypasses the intersection, which is exactly the case junction generation would need to not treat as an arm.driving(it currently stylesOtheras unpainted).bidirectional, also outside the enum, is deprecated by §11.8.1 in favour of@direction="both"— so it should not be added; it should keep round-tripping asOtherand ideally warn with that advice.Scope
LaneTypewith the six values, and update everyswitchthe compiler flags (-Werror=switchmakes this enumerable rather than guesswork).docs/domain/opendrive.mdis the place.kTypeChoicesin the properties panel, and the Python enum binding.Otherto a real enum value must keep writing the same bytes.Acceptance
onRamplane authored from Python writestype="onRamp"and reads back as the same enum value.core/tests/fuzz/corpus/foreign_enum_spellings.xodrstill round-trips byte-identically (itsonRamp/slipLanelanes now parse to real values rather thanOther— the bytes must not care).