Skip to content

Honor speed limit priority for upcoming limits - #102

Closed
FrogAi wants to merge 2 commits into
pfeiferj:mainfrom
FrogAi:codex/honor-upcoming-speed-limit-priority
Closed

Honor speed limit priority for upcoming limits#102
FrogAi wants to merge 2 commits into
pfeiferj:mainfrom
FrogAi:codex/honor-upcoming-speed-limit-priority

Conversation

@FrogAi

@FrogAi FrogAi commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Apply PrioritySpeedLimit to the upcoming map candidate before lookahead uses it.
  • Use the selected upcoming value for direction, offset, jerk-limited activation distance, time offset, and final substitution.
  • Reset the TriggerDistance activation hysteresis when the arbitrated upcoming target changes, so a transient external value or a mid-approach priority change cannot latch a stale activation distance.
  • Keep nextSpeedLimit telemetry as the raw upcoming map value.

Motivation

The current limit already passes through configured map/external source arbitration, but the upcoming limit did not. Lookahead used raw NextLimit.Value from the map for every control calculation, so external-only, external-priority, highest, and lowest modes could switch back to the map source as soon as an upcoming limit entered range.

For example, with external-only control selecting 20 m/s and an upcoming map limit of 10 m/s, the baseline path substitutes 10 m/s. When acceptance and enable-speed gating permit it, that value can become the final controller cap.

The fix stays at the control-consumer boundary. Upcoming map discovery and the raw nextSpeedLimit output remain unchanged.

Behavior

Configuration Current map External Upcoming map Base 68813e05 Head 110a826
External-only, slowdown 30 20 10 10 20
External-only, speed-up 40 10 30 30 10
Map priority 20 25 10 10 10
External priority 40 25 10 10 25
Highest 30 20 10 10 20
Lowest 10 20 30 30 20
External priority, external unavailable 20 0 10 10 10
External-only, no upcoming limit 40 25 0 25 25

Values are m/s with zero offset. The expected targets come from a static code-path trace with fresh trigger state, the upcoming limit inside activation distance, and the direction-appropriate slowdown or speed-up option enabled.

Offset is applied after arbitration. With slowdown enabled and in range, an external-only 30 m/s target, upcoming map value 10 m/s, and 3 m/s offset changes from the baseline 13 m/s to 33 m/s.

Because the activation distance is now derived from the arbitrated value — which can change between ticks via external updates or priority/enable settings — the monotonic TriggerDistance ratchet (previously reset only when the upcoming way changed) could latch a distance computed from a transient arbitration result. On 10e8d70, one transient external frame of 100 m/s in highest mode latched a ~4000 m trigger and kept substituting the upcoming 13.9 m/s limit from 2 km out after the external value recovered; base 68813e05 is immune because its activation distance only used the per-approach-constant raw map value. 110a826 zeroes the ratchet whenever the arbitrated target changes, scoping the hysteresis to the target it was computed from. Within a constant arbitration regime (map-only, or map priority with a map value present) the ratchet behavior is identical to base.

Validation

  • An audit-only regression harness reproduced the baseline external-only failure with current map 30 m/s, selected external 20 m/s, and upcoming map 10 m/s: the observed target was 10 m/s instead of 20 m/s.
  • Static source review covered map-only, external-only, map, external, highest, lowest, missing-source fallback, both speed directions, offset ordering, and no-lookahead behavior.
  • Static source tracing of the distance path used highest priority, current map 30 m/s, external 20 m/s, upcoming map 10 m/s, offset 2 m/s, and fresh trigger state. The corrected jerk and time-offset calculations use the priority-selected 22 m/s target; the baseline uses the raw-map 12 m/s target.
  • A 14-case differential matrix (mode x external availability x next-vs-current direction, plus hold-last-seen, missing-source fallback, disabled-controls, and activation gating) passes on head; the 7 priority-bug cases fail on base 68813e05 as expected and the 7 behavior-preservation cases pass on both.
  • A multi-tick harness confirmed the trigger-distance regression on 10e8d70 (one external frame of 100 m/s in highest mode, then cleared to 0: the suggestion dropped to 13.9 m/s while still 2000 m out, with the ratchet latched at ~4033 m) and confirmed base 68813e05 immune and 110a826 corrected (the suggestion stays 27.8 m/s).
  • Fork Build #9 passed for 10e8d70; Fork Build #19 passed the make build job on exact head commit 110a826.

Compatibility

  • No schema, settings, or offline-map format changes.
  • Raw upcoming map telemetry remains raw; only the suggested control target is arbitrated.
  • Map-only, map-priority, and no-lookahead behavior is unchanged.
  • Existing priority-mode fallback to an available enabled source is preserved.
  • When no future source is selected, lookahead keeps the current suggestion instead of reviving raw map data.
  • Current-limit history and acceptance-clock ownership are not addressed here; those remain isolated in PR Track speed limit state independently of lookahead #103. Whichever of the two lands second conflicts with the other in one hunk; the resolution, validated against this PR's full regression matrix, is documented in Track speed limit state independently of lookahead #103's merge note.

Rebased onto current main (a0454e4)

main has since restructured settings into sub-structs and split the lookahead time offset by direction, so this PR was rebased rather than merged mechanically. The resolution keeps main's SpeedLimitSettings paths and its personality-based SpeedLimitIncreaseTargetSpeedTimeOffset / SpeedLimitDecreaseTargetSpeedTimeOffset branches, and applies this PR's arbitration on top: the upcoming limit is resolved through PrioritySpeedLimit first, a zero result returns the current suggestion, the trigger-distance ratchet resets when the arbitrated target changes, and both direction branches now scale offsetNextSpeedLimit instead of recomputing the raw value.

Re-verified against the rebased base: the full 14-case priority matrix (map-only, external-only, external-priority with and without a value, highest, lowest, map-priority, hold-last-seen, disabled controls, and activation gating) passes, as does the multi-tick trigger-distance regression — a transient external spike no longer latches an oversized activation distance. FrogAi Build #57 passed for the exact head.

One test-harness note worth recording for anyone re-running this: the zero value of LongitudinalPersonality selects Aggressive, not Standard, so a fixture that populates only Personalities.Standard silently exercises an all-zero personality and every lookahead toggle reads false.

@FrogAi
FrogAi force-pushed the codex/honor-upcoming-speed-limit-priority branch from 3528ae0 to 110a826 Compare August 8, 2026 23:35
@FrogAi
FrogAi force-pushed the codex/honor-upcoming-speed-limit-priority branch from 110a826 to a0454e4 Compare August 9, 2026 16:43
@FrogAi

FrogAi commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Closing this because its premise conflicts with the intended behavior: upcoming limits are map-derived, and the upcoming-limit feature deliberately ignores current-limit source priority. Applying PrioritySpeedLimit here can replace or suppress valid map lookahead under some priority settings. The branch and evidence are preserved, but this proposal should not merge.

@FrogAi FrogAi closed this Aug 10, 2026
@FrogAi
FrogAi deleted the codex/honor-upcoming-speed-limit-priority branch August 10, 2026 04:19
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.

1 participant