mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 13:33:42 +08:00
Keep ordinary Mach-E pedal withdrawal with its existing mismatch owner
Withdraw native-denied LONG immediately while retaining only an already proven LAT grant. Preserve fault checks, original proof deadlines and ordinary mismatch counter.
This commit is contained in:
Executable → Regular
+9
-2
@@ -1733,6 +1733,13 @@ class SelfdriveD:
|
||||
mismatch counter retain their original fault ownership.
|
||||
"""
|
||||
from openpilot.starpilot.aol.transport_pause import independent_lateral_health
|
||||
from opendbc.car.ford.values import CAR as FORD_CAR
|
||||
from openpilot.starpilot.car.ford.aol import native_accepts_cp as ford_native_accepts_cp
|
||||
# Established ordinary Mach-E cruise does not require an independent AOL latch.
|
||||
# Its native LONG pedal withdrawal may precede Card; the original combined
|
||||
# publication, live LAT grant and every health/deadline check below still apply.
|
||||
ordinary_ford = bool(self.CP.carFingerprint == FORD_CAR.FORD_MUSTANG_MACH_E_MK1 and
|
||||
ford_native_accepts_cp(self.CP, int(car.CarParams.SafetyModel.ford), 19))
|
||||
proof = getattr(self, 'aol_published_input_proof', None)
|
||||
prior = getattr(self, 'aol_published_input_native', None)
|
||||
anchor = getattr(self, 'aol_ordinary_source_anchor', None)
|
||||
@@ -1746,7 +1753,7 @@ class SelfdriveD:
|
||||
anchor[3] != cp_identity(self.CP) or proof[0] != self.aol_session_id or
|
||||
not proof[8] or not proof[9] or not 0 < proof[2] <= now_ns <= proof[3] or
|
||||
intent is None or companion is None or proof[4] != intent.producerSessionId or
|
||||
proof[5] != companion.integrity_epoch or not intent.allowedLatch or not intent.lateralArmed or
|
||||
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
|
||||
@@ -1780,7 +1787,7 @@ class SelfdriveD:
|
||||
# Retain only its already granted LAT; all proof, health and LONG withdrawal gates remain.
|
||||
# The exact vehicle policies and all proof/health checks above remain required.
|
||||
from openpilot.starpilot.car.ford.aol import early_native_long_withdrawal_supported as ford_early_long
|
||||
return bool(gm_native_accepts_cp(self.CP, native.safetyModel, native.safetyParam) or
|
||||
return bool(ordinary_ford or gm_native_accepts_cp(self.CP, native.safetyModel, native.safetyParam) or
|
||||
early_native_long_withdrawal_supported(self.CP) or ford_early_long(self.CP) or
|
||||
toyota_aol_qualified(self.CP, marked_only=True) or
|
||||
not native.pandaInventory[owners[0]].controlsAllowed and
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
from contextlib import ExitStack
|
||||
import pytest
|
||||
from openpilot.common.prefix import OpenpilotPrefix
|
||||
from openpilot.cereal import log
|
||||
from openpilot.starpilot.aol.tests import test_ioniq_availability as fixture
|
||||
from opendbc.car import gen_empty_fingerprint
|
||||
from opendbc.car.ford.interface import CarInterface
|
||||
from opendbc.car.ford.values import CAR
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def caller():
|
||||
case = fixture.IoniqAvailabilityTests(methodName='runTest')
|
||||
with ExitStack() as stack:
|
||||
stack.callback(case.doCleanups)
|
||||
stack.enter_context(OpenpilotPrefix())
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
fingerprint[0] = {0x5A: 8, 0x3A6: 8, 0x3A7: 8}
|
||||
cp = CarInterface.get_params(CAR.FORD_MUSTANG_MACH_E_MK1, fingerprint, [], True, False, False)
|
||||
cp.alternativeExperience = 32
|
||||
assert cp.safetyConfigs[-1].safetyParam == 19 and cp.flags == 3
|
||||
sd, controls, step = case._authority_callers(True, cp=cp, genuine_events=True)
|
||||
cs = fixture.car_state()
|
||||
cs.cruiseState.enabled = True
|
||||
|
||||
def drive(tick, **kw):
|
||||
return step(tick, latched=False, observed_state=cs, **kw)
|
||||
|
||||
for tick in range(1, 10):
|
||||
a, s, c = drive(tick)
|
||||
assert s.enabled and a.lateralActive and a.longitudinalActive and c.latActive and c.longActive
|
||||
yield sd, cs, drive
|
||||
|
||||
|
||||
@pytest.mark.parametrize('pedal', ['gas', 'brake'])
|
||||
def test_ordinary_pedal_edge_withdraws_long_without_inventing_aol_latch(caller, pedal):
|
||||
sd, cs, drive = caller
|
||||
kwargs = {'native_request_lat': True, 'allowed': True, 'native_request_long': True, 'long_allowed': False, '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
|
||||
assert not sd.aol_last_intent.allowedLatch and not sd.aol_last_intent.lateralArmed
|
||||
assert log.OnroadEvent.EventName.controlsMismatch not in sd.events.names
|
||||
if pedal == 'brake':
|
||||
cs.brakePressed = True
|
||||
a, s, c = drive(11, gas=pedal == 'gas', **kwargs)
|
||||
assert not a.longitudinalActive and not c.longActive
|
||||
assert not sd.aol_last_intent.allowedLatch and not sd.aol_last_intent.lateralArmed
|
||||
assert log.OnroadEvent.EventName.controlsMismatch not in sd.events.names
|
||||
if pedal == 'brake':
|
||||
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)
|
||||
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):
|
||||
sd, cs, drive = caller
|
||||
kw = {'native_request_lat': True, 'allowed': True, 'native_request_long': True, 'long_allowed': False, 'panda_controls_allowed': False}
|
||||
if fault == 'lat_denied':
|
||||
kw['allowed'] = False
|
||||
elif fault == 'native_invalid':
|
||||
kw['native_valid'] = False
|
||||
elif fault == 'rx_fault':
|
||||
kw['panda_fault'] = True
|
||||
elif fault == 'relay_fault':
|
||||
kw['relay_fault'] = True
|
||||
elif fault == 'prior_expired':
|
||||
p = list(sd.aol_published_input_proof)
|
||||
p[3] = 10_099_999_999
|
||||
sd.aol_published_input_proof = tuple(p)
|
||||
elif fault == 'prior_absent':
|
||||
sd.aol_published_input_native = None
|
||||
elif fault == 'proof_absent':
|
||||
sd.aol_published_input_proof = None
|
||||
a, s, c = drive(10, **kw)
|
||||
assert not a.longitudinalActive and not c.longActive
|
||||
assert not s.enabled and not a.lateralActive and not c.latActive
|
||||
assert log.OnroadEvent.EventName.controlsMismatch in sd.events.names
|
||||
|
||||
|
||||
def test_persistent_native_long_denial_keeps_original_mismatch_owner(caller):
|
||||
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)
|
||||
assert not a.longitudinalActive and not c.longActive
|
||||
if log.OnroadEvent.EventName.controlsMismatch in sd.events.names:
|
||||
break
|
||||
assert sd.mismatch_counter >= 200
|
||||
assert not s.enabled and not a.lateralActive and not c.latActive
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"protected_inventory_sha256": "f8a8a5e56e3891c86ed3d164c987d3b4fda326cdd91e7303eb1b57da536ea662", "schema_version": 1}
|
||||
{"protected_inventory_sha256": "d90e3f031dbf26c980c4fdb5fdbf891f984bc5425caf5382d95114211f154e08", "schema_version": 1}
|
||||
|
||||
Reference in New Issue
Block a user