Ford: fire the stall-rescue pulse only on a fractional delivery deficit#148
Open
jrneulight wants to merge 1 commit into
Open
Ford: fire the stall-rescue pulse only on a fractional delivery deficit#148jrneulight wants to merge 1 commit into
jrneulight wants to merge 1 commit into
Conversation
jrneulight
force-pushed
the
bp-7.0-stall-frac
branch
from
July 20, 2026 04:01
e4dce5e to
d2f59ed
Compare
ghbarker
added a commit
to ghbarker/openpilot
that referenced
this pull request
Jul 20, 2026
…luePilotDev#144 (truthful shadow) Folds the two open upstream PRs that bear on the Mach-E angle-mode lateral failures into this branch, adapted to compose with the drift branch and low-speed boost already here: - PR BluePilotDev#148: the classic stall branch now arms on a fractional delivery deficit (measured < 0.65x desired) instead of desired-leads-measured plus the absolute gap alone. Upstream's on-road evidence: the absolute condition misfired twice mid-curve on honest deep-curve entry transients (0.7-0.85x delivered), releasing steering exactly when the car was behind; true stalls measure 0.28-0.59x. The drift branch keeps its own near-straight guard and is unaffected. - PR BluePilotDev#144: bp_kappa_cmd (the shadow curvature ford.h's angle-mode deviation check judges against angle_meas) is now published from measured curvature whenever the planner kappa cannot honestly describe the car's steering: inactive frames, human-turn override, stall-blip pulses, and while the driver presses. Kills the stale-zero re-engage race at the source -- which matters more on this branch, since the drift branch fires mode-0 pulses in situations the old code never did -- and fixes the driver-press shadow excursions behind the only two real lateral safety blocks in upstream's 4.5h replay. All measurement reads route through the new LateralCurvExt.get_current_curvature(). Tests: merged both PRs' unit suites into one file (shared harness), plus two new drift-branch cases (hands-off drift fires; curve exit with a genuine command never fires). 9/9 pass locally. Replay of the three incident segments (4/6/8) is unchanged except one classic fire shifting 0.2s later under the stricter gate -- every fire on this route is a true stall (0.2-0.3x delivered) or a guarded drift event. Not folded: PR BluePilotDev#145 (pinion yaw sensor) -- changes panda safety firmware (ford.h) and is opt-in; deferred until after this branch's road test. PR BluePilotDev#146 (Expedition FW), BluePilotDev#147 (audio), BluePilotDev#132 (comma-four UI refactor) are unrelated to this issue. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 20, 2026
The reactive stall detector's curve condition was only |desired| > |measured|, so an honest deep-curve ENTRY -- the car tracking at 0.7-0.85x of a large, fast-rising demand -- armed the pulse on absolute gap alone, dropping steering for 300 ms mid-curve exactly when the car was already behind. Observed on-road twice in one windy section (|des| 0.016-0.021, delivery 0.71-0.83), each pulse followed by the driver grabbing the wheel within 0.2 s; settled delivery on the same drive was ~1.0 everywhere, confirming these were transients, not stalls. Arm the pulse only when the car delivers under 0.65x of the demand. Detector replay across five routes (~47 engaged minutes, measurement-faithful): every true rescue kept (all fire at 0.28-0.59x delivered), both misfires eliminated, zero new fires; the closest blocked transient sits at 0.71x. All other guards (hold, cooldown, episode cap, press/lane-change resets) unchanged. Unit tests pin both directions.
jrneulight
force-pushed
the
bp-7.0-stall-frac
branch
from
July 20, 2026 15:14
d2f59ed to
70d8002
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The angle-mode reactive stall detector (the 300 ms mode-0 "rescue pulse" that resets
post-override PSCM attenuation) arms on
|desired| > |measured|plus an absolute gapthreshold. That condition cannot tell a stalled PSCM from an honestly-lagging one: on a
deep curve entry the car tracks at 0.7–0.85× of a large, fast-rising demand, clears
the gap threshold on magnitude alone, and the pulse releases steering mid-curve exactly
when the car is already behind.
The evidence that motivated this
0000001e--be********, 25–31 mph,|desired curvature| 0.016–0.021), the detector fired twice mid-curve while the car was
delivering 0.71–0.83× — each pulse followed by the driver grabbing the wheel within
0.2 s.
were entry transients, not stalls.
(~47 engaged minutes).
Why the fix is shaped this way
A stall is a fractional failure, not an absolute gap. The pulse now arms only when
the car is delivering under 0.65× of the demand (
_STALL_DELIVERY_FRACTION) — oneconstant and one condition. The measured separation is wide: every true stall in the
archive sits at ≤ 0.59×, every honest transient at ≥ 0.71×. All other guards (0.5 s
hold, 2 s cooldown, 3-pulse episode cap, press/lane-change resets) are untouched, so a
genuinely stuck PSCM is rescued exactly as before.
The evidence afterwards
Detector replay, ported verbatim and measurement-faithful (live steer ratio,
instantaneous angle offset, roll compensation, the recorded devLim flag), across five
routes:
is calibrated, not curve-fit.
delivered), both misfires eliminated, zero new fires anywhere.
On-road since opening (update, two drives on a branch carrying this gate): a windy
hands-on route (
00000027--97********, 26 min) crossed 38 qualifying curve entries withzero entry-transient fires — a per-blip audit shows the gate honored on every pulse
that did fire — while a true stall still rescued cleanly; a follow-up drive
(
0000002a--ce********) fired 4 pulses, each in a legitimate post-press window, zeromisfires. The gate's exact claim, confirmed on the road in its target scenario.
What each change is
_STALL_DELIVERY_FRACTION = 0.65constant with the measured justification in thecomment.
abs(desired) > abs(measured)becomesabs(measured) < 0.65 * abs(desired).transient (0.72× of a deep demand, gap over threshold) must never fire; a true stall
(0.20×) must.
Test it yourself
Risks / limits
just above 0.65× delivered will no longer pulse — by measurement, everything in that
band was an honest transient the pulse made worse.
now merged) and applies in yaw mode too. Ford: extend the angle-mode stall rescue below 9 m/s with the pinion measurement #153 extends the stall rescue down to 5 m/s
with the pinion measurement, which widens exposure to the old absolute-gap trigger
this PR replaces — merged in the other order, Ford: extend the angle-mode stall rescue below 9 m/s with the pinion measurement #153 carries a known-imperfect trigger
into a new speed range. A further flag-on follow-up (1.5× gap floor for the pinion
path, validated jointly with this gate) comes after both.
this branch had added a self-contained scaffold back when bp-dev had no
car/ford/tests/, and Ford: opt-in pinion curvature measurement (Use Pinion Yaw Sensor) #145 has since added a fuller one. Resolved by keeping Ford: opt-in pinion curvature measurement (Use Pinion Yaw Sensor) #145'sscaffold and porting
TestStallFractionalGateonto its_pinion_harness(flag=False)— the detector change itself applied unchanged.