mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-04 11:33:47 +08:00
Reject Bolt CAN interrupt faults in AOL admission
This commit is contained in:
@@ -30,24 +30,20 @@ def _diagnostic_mask(cp):
|
||||
len(cp.safetyConfigs) == 1 and int(cp.safetyConfigs[0].safetyParam) == 0xC02 and cp.alternativeExperience == 32 and
|
||||
qualified(cp, marked_only=True)) else 0
|
||||
from opendbc.car.gm.aol import qualified_gm
|
||||
from opendbc.car.gm.values import CAR, is_volt_sdgm_profile, is_bolt_present_no_acc_pedal_profile
|
||||
from opendbc.car.gm.values import CAR, is_volt_sdgm_profile
|
||||
if cp.brand != 'gm' or len(cp.safetyConfigs) != 1:
|
||||
return 0
|
||||
word = int(cp.safetyConfigs[0].safetyParam)
|
||||
# Only these two exact identities can use this diagnostic classification.
|
||||
# Only this exact GM identity can use this diagnostic classification.
|
||||
# Reject every other profile before the full GM admission walk. Current
|
||||
# faults and all existing qualification checks remain authoritative.
|
||||
if not ((cp.carFingerprint == CAR.CHEVROLET_VOLT_2019 and word == 0x1005) or
|
||||
(cp.carFingerprint == CAR.CHEVROLET_BOLT_CC_2018_2021 and word == 0x9D)):
|
||||
if not (cp.carFingerprint == CAR.CHEVROLET_VOLT_2019 and word == 0x1005):
|
||||
return 0
|
||||
if not qualified_gm(cp) or not aol_enabled(cp):
|
||||
return 0
|
||||
if (cp.carFingerprint == CAR.CHEVROLET_VOLT_2019 and word == 0x1005 and
|
||||
is_volt_sdgm_profile(cp, longitudinal=False) and cp.pcmCruise and not cp.openpilotLongitudinalControl):
|
||||
return 1 << 18
|
||||
if (cp.carFingerprint == CAR.CHEVROLET_BOLT_CC_2018_2021 and word == 0x9D and
|
||||
is_bolt_present_no_acc_pedal_profile(cp) and cp.openpilotLongitudinalControl and not cp.pcmCruise):
|
||||
return (1 << 2) | (1 << 3)
|
||||
except (AttributeError, TypeError, ValueError, OverflowError, IndexError):
|
||||
pass
|
||||
return 0
|
||||
|
||||
@@ -33,7 +33,7 @@ def owner(label):
|
||||
def test_diagnostic_receipt_does_not_invent_native_authority(label, mask):
|
||||
cp, state = owner(label)
|
||||
state = replace(state, pandaInventory=(replace(state.pandaInventory[0], faults=mask),))
|
||||
admitted = mask == 0 or (label == 'volt' and mask == 1 << 18) or (label == 'bolt' and mask in (1 << 2, 1 << 3, 12))
|
||||
admitted = mask == 0 or (label == 'volt' and mask == 1 << 18)
|
||||
assert native_inventory_matches_cp(state, cp) == admitted
|
||||
accepted = current_native(sm_for(cp, state), cp, now_ns=NOW, axis_session_id='session')
|
||||
if not admitted:
|
||||
@@ -51,7 +51,7 @@ def test_diagnostic_receipt_does_not_invent_native_authority(label, mask):
|
||||
@pytest.mark.parametrize('bit', (0, 1, 4, 5, 7, 8, 15, 20, 21, 22, 23, 25, 26, 27, 31))
|
||||
def test_authority_faults_and_unknown_bits_still_block(label, bit):
|
||||
cp, state = owner(label)
|
||||
baseline = replace(state, pandaInventory=(replace(state.pandaInventory[0], faults=(1 << 18 if label == 'volt' else 12)),))
|
||||
baseline = replace(state, pandaInventory=(replace(state.pandaInventory[0], faults=(1 << 18 if label == 'volt' else 0)),))
|
||||
assert current_native(sm_for(cp, baseline), cp, now_ns=NOW, axis_session_id='session') == baseline
|
||||
state = replace(baseline, pandaInventory=(replace(baseline.pandaInventory[0], faults=baseline.pandaInventory[0].faults | (1 << bit)),))
|
||||
assert current_native(sm_for(cp, state), cp, now_ns=NOW, axis_session_id='session') is None
|
||||
@@ -61,7 +61,7 @@ def test_authority_faults_and_unknown_bits_still_block(label, bit):
|
||||
@pytest.mark.parametrize('bad', ('rx', 'heartbeat', 'word', 'ae', 'serial', 'session', 'expired'))
|
||||
def test_diagnostic_bits_cannot_bypass_other_vetoes(label, bad):
|
||||
cp, state = owner(label)
|
||||
slot = replace(state.pandaInventory[0], faults=(1 << 18 if label == 'volt' else 12))
|
||||
slot = replace(state.pandaInventory[0], faults=(1 << 18 if label == 'volt' else 0))
|
||||
baseline = replace(state, pandaInventory=(slot,))
|
||||
assert current_native(sm_for(cp, baseline), cp, now_ns=NOW, axis_session_id='session') == baseline
|
||||
mutations = {'rx': {'safetyRxChecksInvalid': True}, 'heartbeat': {'heartbeatLost': True},
|
||||
@@ -88,9 +88,9 @@ def test_other_volt_configs_do_not_borrow_stock_register_policy(word):
|
||||
assert blocking_fault_mask(1 << 18, cp)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('identity', (CAR.CHEVROLET_BOLT_CC_2017, CAR.CHEVROLET_BOLT_CC_2022_2023,
|
||||
@pytest.mark.parametrize('identity', (CAR.CHEVROLET_BOLT_CC_2017, CAR.CHEVROLET_BOLT_CC_2018_2021, CAR.CHEVROLET_BOLT_CC_2022_2023,
|
||||
CAR.CHEVROLET_BOLT_ACC_2022_2023_PEDAL))
|
||||
def test_other_bolt_generations_do_not_borrow_irq_policy(identity):
|
||||
def test_all_bolt_generations_reject_irq_faults(identity):
|
||||
from openpilot.starpilot.aol.panda_faults import blocking_fault_mask
|
||||
cp = params(identity, pedal=True, camera=True)
|
||||
cp.alternativeExperience = 32
|
||||
@@ -102,20 +102,20 @@ def test_latest_raw_faults_use_same_exact_policy_and_retain_native_veto(label):
|
||||
from openpilot.cereal import messaging
|
||||
from openpilot.starpilot.aol.transport_pause import healthy_transport
|
||||
cp, state = owner(label)
|
||||
allowed = 'registerDivergent' if label == 'volt' else 'interruptRateCan2'
|
||||
mask = 1 << 18 if label == 'volt' else 1 << 3
|
||||
allowed = ['registerDivergent'] if label == 'volt' else []
|
||||
mask = 1 << 18 if label == 'volt' else 0
|
||||
state = replace(state, pandaInventory=(replace(state.pandaInventory[0], faults=mask),))
|
||||
sm = sm_for(cp, state)
|
||||
assert current_native(sm, cp, now_ns=NOW, axis_session_id='session') == state
|
||||
event = messaging.new_message('pandaStates', 1, valid=True, logMonoTime=NOW)
|
||||
event.pandaStates[0] = sm['pandaStates'][0]
|
||||
event.pandaStates[0].faults = [allowed]
|
||||
event.pandaStates[0].faults = allowed
|
||||
sm.update_msgs(NOW / 1e9, [event.as_reader()])
|
||||
assert healthy_transport(sm, cp, car_state(), 'session', NOW)
|
||||
event.pandaStates[0].faults = [allowed, 'relayMalfunction']
|
||||
event.pandaStates[0].faults = [*allowed, 'relayMalfunction']
|
||||
sm.update_msgs(NOW / 1e9, [event.as_reader()])
|
||||
assert not healthy_transport(sm, cp, car_state(), 'session', NOW)
|
||||
event.pandaStates[0].faults = [allowed]
|
||||
event.pandaStates[0].faults = allowed
|
||||
event.pandaStates[0].heartbeatLost = True
|
||||
sm.update_msgs(NOW / 1e9, [event.as_reader()])
|
||||
assert not healthy_transport(sm, cp, car_state(), 'session', NOW)
|
||||
@@ -126,8 +126,7 @@ def test_raw_enum_policy_does_not_borrow_other_config_diagnostics(label):
|
||||
from openpilot.cereal import log
|
||||
from openpilot.starpilot.aol.panda_faults import blocking_fault_list
|
||||
cp, _ = owner(label)
|
||||
allowed = [log.PandaState.FaultType.registerDivergent] if label == 'volt' else [
|
||||
log.PandaState.FaultType.interruptRateCan1, log.PandaState.FaultType.interruptRateCan2]
|
||||
allowed = [log.PandaState.FaultType.registerDivergent] if label == 'volt' else []
|
||||
assert not blocking_fault_list(allowed, cp)
|
||||
denied = (log.PandaState.FaultType.interruptRateCan1 if label == 'volt' else log.PandaState.FaultType.registerDivergent)
|
||||
assert blocking_fault_list([*allowed, denied], cp)
|
||||
@@ -190,7 +189,7 @@ def test_real_native_permission_and_brake_withdrawal_remain_authoritative(label)
|
||||
assert parsed.brakePressed
|
||||
assert not mask & 2
|
||||
slot = replace(state.pandaInventory[0], controlsAllowed=bool(safety.get_controls_allowed()),
|
||||
faults=1 << 18 if label == 'volt' else 12)
|
||||
faults=1 << 18 if label == 'volt' else 0)
|
||||
receipt = replace(state, observedMonoTime=now, validUntilMonoTime=now + 200_000_000,
|
||||
lateralAllowed=bool(mask & 1), longitudinalAllowed=bool(mask & 2),
|
||||
requestedLateral=bool(request & 1), requestedLongitudinal=bool(request & 2),
|
||||
@@ -203,3 +202,28 @@ def test_real_native_permission_and_brake_withdrawal_remain_authoritative(label)
|
||||
no_entry=False, immediate_disable=False, dm_lockout=False, pause_brake_mps=0.)
|
||||
assert not decision.longitudinal_active
|
||||
safety.set_alternative_experience(0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('faults', (['interruptRateCan1'], ['interruptRateCan2'],
|
||||
['interruptRateCan1', 'interruptRateCan2']))
|
||||
def test_bolt_irq_faults_reject_raw_and_inventory_authority(faults):
|
||||
from openpilot.cereal import messaging
|
||||
from openpilot.starpilot.aol.panda_faults import blocking_fault_list
|
||||
from openpilot.starpilot.aol.transport_pause import healthy_transport
|
||||
cp, state = owner('bolt')
|
||||
mask = sum({'interruptRateCan1': 1 << 2, 'interruptRateCan2': 1 << 3}[fault] for fault in faults)
|
||||
slot = replace(state.pandaInventory[0], controlsAllowed=True, faults=mask)
|
||||
receipt = replace(state, lateralAllowed=True, longitudinalAllowed=True, pandaInventory=(slot,))
|
||||
sm = sm_for(cp, receipt)
|
||||
assert not native_inventory_matches_cp(receipt, cp)
|
||||
assert current_native(sm, cp, now_ns=NOW, axis_session_id='session') is None
|
||||
# A newer raw health sample must veto even a clean admitted inventory.
|
||||
sm = sm_for(cp, state)
|
||||
assert current_native(sm, cp, now_ns=NOW, axis_session_id='session') == state
|
||||
assert healthy_transport(sm, cp, car_state(), 'session', NOW)
|
||||
event = messaging.new_message('pandaStates', 1, valid=True, logMonoTime=NOW)
|
||||
event.pandaStates[0] = sm['pandaStates'][0]
|
||||
event.pandaStates[0].faults = faults
|
||||
sm.update_msgs(NOW / 1e9, [event.as_reader()])
|
||||
assert blocking_fault_list(sm['pandaStates'][0].faults, cp)
|
||||
assert not healthy_transport(sm, cp, car_state(), 'session', NOW)
|
||||
|
||||
Reference in New Issue
Block a user