From a952a8f8a82c754ff893711d66421d72638878c1 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Thu, 29 Oct 2026 14:27:37 -0500 Subject: [PATCH] Keep Mach-E native LONG withdrawal separate from manual steering --- openpilot/selfdrive/selfdrived/selfdrived.py | 5 +++-- .../test_ford_ordinary_long_withdrawal.py | 18 +++++++++++------- prebuilt.json | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/openpilot/selfdrive/selfdrived/selfdrived.py b/openpilot/selfdrive/selfdrived/selfdrived.py index 433c61bbcf..47d8d28cad 100644 --- a/openpilot/selfdrive/selfdrived/selfdrived.py +++ b/openpilot/selfdrive/selfdrived/selfdrived.py @@ -1777,9 +1777,10 @@ class SelfdriveD: proof[5] != companion.integrity_epoch or not ((intent.allowedLatch and intent.lateralArmed) or ordinary_ford) or not native.requestedLateral or not native.lateralAllowed or not native.requestedLongitudinal or native.longitudinalAllowed or not native.pandaInventory or - CS.brakePressed or CS.regenBraking or CS.gasPressed or CS.steeringPressed or + CS.brakePressed or CS.regenBraking or CS.gasPressed or CS.steeringPressed and not ordinary_ford or any(self.events.contains(kind) for kind in (ET.IMMEDIATE_DISABLE, ET.SOFT_DISABLE, ET.USER_DISABLE, - ET.OVERRIDE_LATERAL, ET.OVERRIDE_LONGITUDINAL))): + ET.OVERRIDE_LONGITUDINAL)) or + not ordinary_ford and self.events.contains(ET.OVERRIDE_LATERAL)): return False def identity(state): return (state.axisSessionId, state.pandaSerial, state.safetyModel, state.safetyParam, diff --git a/openpilot/starpilot/aol/tests/test_ford_ordinary_long_withdrawal.py b/openpilot/starpilot/aol/tests/test_ford_ordinary_long_withdrawal.py index ca9966b8c5..865dbef72c 100644 --- a/openpilot/starpilot/aol/tests/test_ford_ordinary_long_withdrawal.py +++ b/openpilot/starpilot/aol/tests/test_ford_ordinary_long_withdrawal.py @@ -33,9 +33,11 @@ def caller(): @pytest.mark.parametrize('pedal', ['gas', 'brake']) -def test_ordinary_pedal_edge_withdraws_long_without_inventing_aol_latch(caller, pedal): +@pytest.mark.parametrize('steering', [False, True]) +def test_ordinary_pedal_edge_withdraws_long_without_inventing_aol_latch(caller, pedal, steering): sd, cs, drive = caller - kwargs = {'native_request_lat': True, 'allowed': True, 'native_request_long': True, 'long_allowed': False, 'panda_controls_allowed': pedal == 'gas'} + kwargs = {'native_request_lat': True, 'allowed': True, 'native_request_long': True, 'long_allowed': False, + 'steering': steering, 'panda_controls_allowed': pedal == 'gas'} a, s, c = drive(10, **kwargs) assert not a.longitudinalActive and not c.longActive assert a.lateralActive and c.latActive and s.enabled @@ -51,16 +53,17 @@ def test_ordinary_pedal_edge_withdraws_long_without_inventing_aol_latch(caller, assert not s.enabled and not s.active and not a.lateralActive and not c.latActive # Releasing brake alone must not rearm ordinary ACC or independent LAT. cs.brakePressed = False - a, s, c = drive(12) + a, s, c = drive(12, steering=steering) assert not s.enabled and not a.lateralActive and not a.longitudinalActive and not c.latActive and not c.longActive else: assert s.enabled and a.lateralActive and c.latActive @pytest.mark.parametrize('fault', ['lat_denied', 'native_invalid', 'rx_fault', 'relay_fault', 'prior_expired', 'prior_absent', 'proof_absent']) -def test_faults_and_missing_original_proof_remain_immediate(caller, fault): +@pytest.mark.parametrize('steering', [False, True]) +def test_faults_and_missing_original_proof_remain_immediate(caller, fault, steering): sd, cs, drive = caller - kw = {'native_request_lat': True, 'allowed': True, 'native_request_long': True, 'long_allowed': False, 'panda_controls_allowed': False} + kw = {'native_request_lat': True, 'allowed': True, 'native_request_long': True, 'long_allowed': False, 'steering': steering, 'panda_controls_allowed': False} if fault == 'lat_denied': kw['allowed'] = False elif fault == 'native_invalid': @@ -83,10 +86,11 @@ def test_faults_and_missing_original_proof_remain_immediate(caller, fault): assert log.OnroadEvent.EventName.controlsMismatch in sd.events.names -def test_persistent_native_long_denial_keeps_original_mismatch_owner(caller): +@pytest.mark.parametrize('steering', [False, True]) +def test_persistent_native_long_denial_keeps_original_mismatch_owner(caller, steering): sd, cs, drive = caller for tick in range(10, 230): - a, s, c = drive(tick, native_request_lat=True, allowed=True, native_request_long=True, long_allowed=False, panda_controls_allowed=False) + a, s, c = drive(tick, native_request_lat=True, allowed=True, native_request_long=True, long_allowed=False, panda_controls_allowed=False, steering=steering) assert not a.longitudinalActive and not c.longActive if log.OnroadEvent.EventName.controlsMismatch in sd.events.names: break diff --git a/prebuilt.json b/prebuilt.json index 9e858a7aa0..6969d948d2 100644 --- a/prebuilt.json +++ b/prebuilt.json @@ -1 +1 @@ -{"protected_inventory_sha256": "2c7ad6865477b3c48cd53996b2a5e48fd9cd574ab56986fa1085a9247e158524", "schema_version": 1} +{"protected_inventory_sha256": "c2cb35e4cc4b850825f002c3d16def1f3c20dfdf818e154e448fb85558c08a2b", "schema_version": 1}