Preserve stock HKG lateral ownership through delayed brake status

This commit is contained in:
firestar5683
2026-10-20 09:29:55 -05:00
parent 5c27cc667b
commit e96ba4205f
8 changed files with 430 additions and 7 deletions
@@ -0,0 +1,67 @@
import pytest
from opendbc.car.hyundai.canfd_stock_aol import STOCK_AOL_WORDS
from opendbc.safety.tests import test_hyundai_shared_canfd_stock_aol as fixture
def rx(case, name, bus, counter, values):
maximum = 16 if name == 'CRUISE_BUTTONS' else 256
frame = case.packer.make_can_msg(name, bus, dict(values, COUNTER=counter % maximum))
assert case.safety.safety_rx_hook(case.packet(frame))
def steering(case, word, counter):
name = 'LKAS_ALT' if word & 0x80 else 'LKAS' if word & 0x10 else 'LFA'
frame = case.packer.make_can_msg(name, 0, {'COUNTER': counter, 'StrTqReqVal': 1,
'ActToiSta': 1, 'LKA_OptUsmSta': 2, 'Damping_Gain': 100})
return case.packet(frame)
@pytest.mark.parametrize('word', sorted(STOCK_AOL_WORDS))
@pytest.mark.parametrize('gesture', ['cancel', 'brake'])
@pytest.mark.parametrize('veto', ['host_withdrawal', 'bad_source_checksum'])
def test_actual_stock_torque_brake_and_cancel_keep_only_existing_lateral_permission(word, gesture, veto):
case = fixture.TestHyundaiSharedCanfdStockAol(methodName='runTest')
case.setUp()
case.mode(word)
case.healthy(word)
case.safety.set_aol_test_heartbeat(True)
case.safety.aol_set_host_request(1)
assert not case.safety.get_controls_allowed()
assert case.safety.aol_get_permission_mask() == 0
assert not case.safety.safety_tx_hook(steering(case, word, 0))
case.gesture(word)
case.safety.aol_set_host_request(1)
assert case.safety.aol_get_permission_mask() == 1
pt = 1 if word & 0x10 else 0
buttons = 'CRUISE_BUTTONS_ALT' if word & 0x20 else 'CRUISE_BUTTONS'
for counter, values in ((9, {'ADAPTIVE_CRUISE_MAIN_BTN': 1}),
(10, {}), (11, {'CRUISE_BUTTONS': 2}), (12, {})):
rx(case, buttons, pt, counter, values)
scc = 2 if word & 8 else pt
rx(case, 'SCC_CONTROL', scc, 7, {'MainMode_ACC': 1, 'ACCMode': 1, 'VSetDis': 90})
assert case.safety.get_controls_allowed()
case.safety.aol_set_host_request(3)
assert case.safety.aol_get_permission_mask() == 1
case.safety.aol_set_host_request(1)
if gesture == 'cancel':
rx(case, buttons, pt, 13, {'CRUISE_BUTTONS': 4})
else:
rx(case, 'TCS', pt, 7, {'DriverBraking': 1})
assert bool(case.safety.get_controls_allowed()) == (gesture == 'cancel')
assert case.safety.aol_get_permission_mask() == 1
assert case.safety.safety_tx_hook(steering(case, word, 1))
rx(case, 'SCC_CONTROL', scc, 8, {'MainMode_ACC': 1, 'ACCMode': 0, 'VSetDis': 90})
assert not case.safety.get_controls_allowed()
assert case.safety.aol_get_permission_mask() == 1
assert case.safety.safety_tx_hook(steering(case, word, 2))
assert not case.safety.safety_tx_hook(case.packet(case.packer.make_can_msg('SCC_CONTROL', pt, {'COUNTER': 9})))
if veto == 'host_withdrawal':
case.safety.aol_set_host_request(0)
else:
address, raw, bus = case.packer.make_can_msg('TCS', pt, {'COUNTER': 8, 'DriverBraking': int(gesture == 'brake')})
corrupt = bytearray(raw)
corrupt[0] ^= 1
assert not case.safety.safety_rx_hook(case.packet((address, bytes(corrupt), bus)))
assert case.safety.aol_get_permission_mask() == 0
assert not case.safety.safety_tx_hook(steering(case, word, 3))
+4 -1
View File
@@ -1268,8 +1268,11 @@ class SelfdriveD:
user_disable = self.events.contains(ET.USER_DISABLE)
if user_disable:
from opendbc.car.hyundai.canfd_angle_aol import qualified as angle_qualified
from opendbc.car.hyundai.canfd_stock_aol import qualified as stock_canfd_qualified
if angle_qualified(self.CP, marked_only=True):
if (angle_qualified(self.CP, marked_only=True) or
self.CP.brand == 'hyundai' and CS.brakePressed and len(self.CP.safetyConfigs) == 1 and
stock_canfd_qualified(self.CP, marked_only=True)):
native = current_native(self.sm, self.CP, now_ns=now_ns, axis_session_id=self.aol_session_id)
if stock_lateral_role(self, CS, native, intent, allow_independent_cancel=True,
allow_independent_brake=True, now_ns=now_ns):
@@ -1,4 +1,5 @@
"""Classify ordinary host source loss without granting commands or engagement."""
from math import isfinite
from opendbc.car.structs import car
from openpilot.cereal import log
from openpilot.selfdrive.selfdrived.events import ET
@@ -26,12 +27,16 @@ def stock_lateral_role(self, CS, native, intent=None, *, allow_independent_cance
brake_role = False
if allow_independent_brake:
from opendbc.car.hyundai.canfd_angle_aol import command_allowed
from opendbc.car.hyundai.canfd_stock_aol import qualified as stock_canfd_qualified
settings = getattr(self, 'aol_settings', None)
previous = getattr(self, 'aol_axis_decision', None)
brake_role = bool(settings is not None and settings.enabled and CS.vEgo >= settings.pause_brake_mps and
CS.brakePressed and not CS.regenBraking and previous is not None and previous.lateral_active and
previous.native_acknowledged and not previous.longitudinal_active and command_allowed(self.CP, CS))
brake_role = bool(settings is not None and settings.enabled and CS.brakePressed and not CS.regenBraking and
previous is not None and previous.lateral_active and previous.native_acknowledged and not previous.longitudinal_active and
(CS.vEgo >= settings.pause_brake_mps and command_allowed(self.CP, CS) or
len(self.CP.safetyConfigs) == 1 and stock_canfd_qualified(self.CP, marked_only=True) and
CS.gearShifter == car.CarState.GearShifter.drive and isfinite(CS.vEgoRaw) and isfinite(CS.vEgo) and
(settings.pause_brake_mps <= 0 or CS.vEgo >= settings.pause_brake_mps or CS.standstill)))
rules = self.events.event_rules
stock_user = stock_lateral_user_event(self.CP)
users = [name for name in self.events.names if ET.USER_DISABLE in rules.get(name, {})]
@@ -0,0 +1,269 @@
from contextlib import ExitStack, contextmanager
from pathlib import Path
from types import SimpleNamespace
import pytest
from opendbc.car import gen_empty_fingerprint, structs
from opendbc.car.hyundai.canfd_stock_aol import qualified
from opendbc.car.hyundai.hyundaicanfd import CanBus
from opendbc.car.hyundai.interface import CarInterface
from opendbc.car.hyundai.values import CAR, HyundaiFlags
from openpilot.cereal import log
from openpilot.cereal.services import SERVICE_LIST
from openpilot.common.params import Params
from openpilot.common.prefix import OpenpilotPrefix
from openpilot.starpilot.aol.intent import read_settings
from openpilot.starpilot.aol.tests.stock_lateral_test_helpers import car_state, hkg_family_case
MODELS = [(CAR.GENESIS_GV70_1ST_GEN, False), (CAR.GENESIS_GV70_ELECTRIFIED_1ST_GEN, True), (CAR.KIA_EV6, True)]
@contextmanager
def configured_callers(identity, lka, guard, *, hybrid=False, lkas_action=9):
with ExitStack() as cleanup:
with OpenpilotPrefix():
saved = Params()
saved.put_bool('AlwaysOnLateral', True, block=True)
saved.put('LKASButtonControl', lkas_action, block=True)
saved.put('MainCruiseButtonControl', 9 if guard == 'mapped_main' else 0, block=True)
for key in ('CancelButtonControl', 'LongCancelButtonControl', 'VeryLongCancelButtonControl'):
saved.put(key, 3 if guard == 'configured_cancel' and key == 'CancelButtonControl' else 0, block=True)
saved.put('AolBrakePauseSpeedMps', 20.0 if guard == 'brake_pause_speed' else 0.0, block=True)
case = hkg_family_case('hkg_canfd', False)
cleanup.callback(case.doCleanups)
fingerprint = gen_empty_fingerprint()
if lka:
fingerprint[CanBus(None, fingerprint).CAM][0x50] = 16
if hybrid:
fingerprint[CanBus(None, fingerprint, lka_steering=lka).ECAN][0xFA] = 32
cp = CarInterface.get_params(identity, fingerprint, [], False, False, False)
assert bool(cp.flags & HyundaiFlags.HYBRID) == hybrid
assert qualified(cp) and not cp.openpilotLongitudinalControl and cp.pcmCruise
case.family_cp = cp.as_reader()
sd, _, step, card, receive = case.family_callers(False)
sd.aol_settings = read_settings(saved)
assert sd.aol_settings == card.aol_card_intent.settings
released = car_state()
released.buttonEvents = [structs.CarState.ButtonEvent(type='lkas', pressed=False)]
card.aol_card_intent.update(released, now_ns=10_015_000_000)
assert card.aol_card_intent.allowed_latch
engaged = car_state()
engaged.vEgoRaw = engaged.vEgo
engaged.cruiseState.enabled = True
axis, _, command = step(2, observed_state=engaged, panda_controls_allowed=True)
assert sd.enabled and axis.lateralActive and command.latActive
assert not axis.longitudinalActive and not command.longActive
assert receive(10_020_000_000, state=engaged, axis=sd.pm.messages['aolAxisState'],
event=sd.pm.messages['onroadEvents'])
yield SimpleNamespace(sd=sd, step=step, card=card, receive=receive)
@pytest.mark.parametrize('identity,lka', MODELS)
@pytest.mark.parametrize('guard', ['native_denied', 'native_long', 'native_invalid', 'native_no_request',
'panda_fault', 'relay_fault', 'critical_event', 'uncalibrated',
'invalid_can', 'reverse', 'brake_pause_speed', 'stale_source',
'future_source', 'both_pedals', 'configured_cancel', 'mapped_main',
'mapped_lkas', 'nonfinite_raw', 'regen', 'unmarked_cp', 'aol_disabled',
'invalid_pause', 'negative_pause', 'excess_pause'])
def test_late_brake_continuity_cannot_override_existing_stock_guards(identity, lka, guard):
with configured_callers(identity, lka, guard) as context:
sd, step, card = context.sd, context.step, context.card
state = car_state(brake=True)
state.vEgoRaw = state.vEgo
state.cruiseState.enabled = True
kwargs = {'panda_controls_allowed': False}
if guard == 'native_denied':
kwargs['allowed'] = False
elif guard == 'native_long':
kwargs['native_request_long'] = True
kwargs['long_allowed'] = False
elif guard == 'native_invalid':
kwargs['native_valid'] = False
elif guard == 'native_no_request':
kwargs['native_request_lat'] = False
kwargs['allowed'] = False
elif guard == 'panda_fault':
kwargs['panda_fault'] = True
elif guard == 'relay_fault':
kwargs['relay_fault'] = True
elif guard == 'critical_event':
kwargs['critical_event'] = log.OnroadEvent.EventName.controlsMismatch
elif guard == 'uncalibrated':
kwargs['calibrated'] = False
elif guard == 'brake_pause_speed':
assert sd.aol_settings.pause_brake_mps == 20.0
state.vEgoRaw = state.vEgo = 19.0
assert not state.standstill and state.vEgo < sd.aol_settings.pause_brake_mps
elif guard == 'invalid_can':
state.canValid = False
elif guard == 'reverse':
state.gearShifter = 'reverse'
elif guard == 'stale_source':
kwargs['state_stamp'] = 10_020_000_000
elif guard == 'future_source':
kwargs['state_stamp'] = 10_080_000_000
elif guard == 'both_pedals':
kwargs['gas'] = True
elif guard in ('configured_cancel', 'mapped_main', 'mapped_lkas'):
button = {'configured_cancel': 'cancel', 'mapped_main': 'mainCruise', 'mapped_lkas': 'lkas'}[guard]
state.buttonEvents = [structs.CarState.ButtonEvent(type=button, pressed=True)]
card.aol_card_intent.update(state, now_ns=10_070_000_000)
assert not card.aol_card_intent.allowed_latch
elif guard == 'nonfinite_raw':
state.vEgoRaw = float('nan')
elif guard == 'regen':
state.regenBraking = True
elif guard == 'aol_disabled':
sd.params.put_bool('AlwaysOnLateral', False, block=True)
sd.aol_settings = read_settings(sd.params)
card.aol_card_intent.settings = sd.aol_settings
card.aol_card_intent.update(state, now_ns=10_070_000_000)
assert not sd.aol_settings.enabled and not card.aol_card_intent.allowed_latch
elif guard in ('invalid_pause', 'negative_pause', 'excess_pause'):
raw = {'invalid_pause': b'not-a-number', 'negative_pause': b'-1', 'excess_pause': b'101'}[guard]
Path(sd.params.get_param_path('AolBrakePauseSpeedMps')).write_bytes(raw)
sd.aol_settings = read_settings(sd.params)
card.aol_card_intent.settings = sd.aol_settings
card.aol_card_intent.update(state, now_ns=10_070_000_000)
assert not sd.aol_settings.enabled and not card.aol_card_intent.allowed_latch
elif guard == 'unmarked_cp':
cp = sd.CP.as_builder()
cp.safetyConfigs[0].safetyParam &= ~0x0800
sd.CP = cp.as_reader()
tick = 7
if guard == 'uncalibrated':
period = round(1e9 / min(SERVICE_LIST['extrinsicsCalibration'].frequency, 100))
next_due = int(sd.sm.logMonoTime['extrinsicsCalibration']) + period
tick = max(tick, (next_due - 10_000_000_000 + 9_999_999) // 10_000_000)
axis, _, command = step(tick, observed_state=state, **kwargs)
if guard == 'uncalibrated':
assert int(sd.sm.logMonoTime['extrinsicsCalibration']) == 10_000_000_000 + tick * 10_000_000
assert sd.sm['extrinsicsCalibration'].calStatus == log.ExtrinsicsCalibration.Status.uncalibrated
assert not axis.lateralActive and not command.latActive
assert not axis.longitudinalActive and not command.longActive
@pytest.mark.parametrize('identity,lka', MODELS)
@pytest.mark.parametrize('boundary', ['unmarked', 'longitudinal', 'unknown', 'passive', 'second_panda', 'no_brake_role'])
def test_stock_brake_exception_does_not_expand_configuration_admission(identity, lka, boundary):
from openpilot.starpilot.aol.transport_pause import stock_lateral_off
fingerprint = gen_empty_fingerprint()
if lka:
fingerprint[CanBus(None, fingerprint).CAM][0x50] = 16
cp = CarInterface.get_params(identity, fingerprint, [], False, False, False)
cp.safetyConfigs[0].safetyParam |= 0x0800
assert qualified(cp, marked_only=True)
state = car_state(brake=True)
state.vEgoRaw = state.vEgo
state.cruiseState.enabled = True
state.cruiseState.available = True
native = SimpleNamespace(requestedLateral=True, lateralAllowed=True, requestedLongitudinal=False)
assert stock_lateral_off(cp, state, native, allow_independent_brake=True)
if boundary == 'unmarked':
cp.safetyConfigs[0].safetyParam &= ~0x0800
elif boundary == 'longitudinal':
cp.openpilotLongitudinalControl = True
cp.pcmCruise = False
elif boundary == 'unknown':
cp.carFingerprint = 'UNKNOWN_HYUNDAI'
elif boundary == 'passive':
cp.passive = True
elif boundary == 'second_panda':
word = cp.safetyConfigs[0].safetyParam
configs = cp.init('safetyConfigs', 2)
configs[0].safetyModel = 'noOutput'
configs[1].safetyModel = 'hyundaiCanfd'
configs[1].safetyParam = word
from opendbc.car.hyundai.canfd_owner import config_index
assert config_index(cp) == (1 if lka else None)
assert qualified(cp, marked_only=True) == lka
assert not stock_lateral_off(cp, state, native, allow_independent_brake=boundary != 'no_brake_role')
@pytest.mark.parametrize('tick', [3, 7])
@pytest.mark.parametrize('gesture', ['cancel', 'brake'])
def test_source_selected_hybrid_stock_brake_continuity(tick, gesture):
with configured_callers(CAR.HYUNDAI_TUCSON_4TH_GEN, False, 'baseline', hybrid=True) as context:
sd, step, card, receive = context.sd, context.step, context.card, context.receive
state = car_state(brake=gesture == 'brake')
state.vEgoRaw = state.vEgo
state.cruiseState.enabled = True
if gesture == 'cancel':
state.buttonEvents = [structs.CarState.ButtonEvent(type='cancel', pressed=True)]
axis, _, command = step(tick, observed_state=state, panda_controls_allowed=gesture == 'cancel')
assert axis.lateralActive and command.latActive
assert not axis.longitudinalActive and not command.longActive
assert receive(10_000_000_000 + tick * 10_000_000, state=state,
axis=sd.pm.messages['aolAxisState'], event=sd.pm.messages['onroadEvents'])
settled = car_state(brake=gesture == 'brake')
settled.vEgoRaw = settled.vEgo
axis, _, command = step(tick + 1, observed_state=settled)
assert not sd.enabled and axis.lateralActive and command.latActive
assert not axis.longitudinalActive and not command.longActive
assert receive(10_000_000_000 + (tick + 1) * 10_000_000, state=settled,
axis=sd.pm.messages['aolAxisState'], event=sd.pm.messages['onroadEvents'])
assert card.aol_card_intent.allowed_latch
@pytest.mark.parametrize('identity,lka', MODELS)
@pytest.mark.parametrize('tick', [3, 7])
@pytest.mark.parametrize('gesture', ['cancel', 'brake'])
def test_default_button_mapping_keeps_its_existing_cancel_withdrawal(identity, lka, tick, gesture):
with configured_callers(identity, lka, 'baseline', lkas_action=0) as context:
sd, step, card, receive = context.sd, context.step, context.card, context.receive
state = car_state(brake=gesture == 'brake')
state.vEgoRaw = state.vEgo
state.cruiseState.enabled = True
if gesture == 'cancel':
state.buttonEvents = [structs.CarState.ButtonEvent(type='cancel', pressed=True)]
card.aol_card_intent.update(state, now_ns=10_000_000_000 + tick * 10_000_000)
assert card.aol_card_intent.allowed_latch == (gesture == 'brake')
axis, _, command = step(tick, observed_state=state, panda_controls_allowed=gesture == 'cancel')
assert axis.lateralActive and command.latActive
assert not axis.longitudinalActive and not command.longActive
assert receive(10_000_000_000 + tick * 10_000_000, state=state,
axis=sd.pm.messages['aolAxisState'], event=sd.pm.messages['onroadEvents']) == (gesture == 'brake')
settled = car_state(brake=gesture == 'brake')
settled.vEgoRaw = settled.vEgo
axis, _, command = step(tick + 1, observed_state=settled)
assert not sd.enabled
assert bool(axis.lateralActive) == bool(command.latActive) == (gesture == 'brake')
assert not axis.longitudinalActive and not command.longActive
assert receive(10_000_000_000 + (tick + 1) * 10_000_000, state=settled,
axis=sd.pm.messages['aolAxisState'], event=sd.pm.messages['onroadEvents']) == (gesture == 'brake')
@pytest.mark.parametrize('identity,lka', MODELS)
@pytest.mark.parametrize('pause_mps', [0.0, 20.0])
def test_existing_independent_brake_policy_keeps_standstill_exception(identity, lka, pause_mps):
guard = 'brake_pause_speed' if pause_mps else 'baseline'
with configured_callers(identity, lka, guard) as context:
sd, step, card, receive = context.sd, context.step, context.card, context.receive
assert sd.aol_settings.pause_brake_mps == pause_mps
state = car_state(brake=True)
state.vEgoRaw = state.vEgo = 0.0
state.standstill = True
state.cruiseState.enabled = True
axis, _, command = step(7, observed_state=state, panda_controls_allowed=False)
assert not sd.enabled and not sd.CP.steerAtStandstill
assert axis.lateralActive and not command.latActive
assert not axis.longitudinalActive and not command.longActive
assert receive(10_070_000_000, state=state, axis=sd.pm.messages['aolAxisState'],
event=sd.pm.messages['onroadEvents'])
assert card.aol_card_intent.allowed_latch
@pytest.mark.parametrize('identity,lka', MODELS)
def test_existing_brake_pause_threshold_equality_remains_allowed(identity, lka):
with configured_callers(identity, lka, 'brake_pause_speed') as context:
sd, step = context.sd, context.step
state = car_state(brake=True)
state.vEgoRaw = state.vEgo = sd.aol_settings.pause_brake_mps
state.cruiseState.enabled = True
assert state.vEgo == 20.0 and not state.standstill
axis, _, command = step(7, observed_state=state, panda_controls_allowed=False)
assert not sd.enabled and axis.lateralActive and command.latActive
assert not axis.longitudinalActive and not command.longActive
@@ -0,0 +1,72 @@
from contextlib import ExitStack
import pytest
from opendbc.car import gen_empty_fingerprint, structs
from opendbc.car.hyundai.canfd_stock_aol import qualified
from opendbc.car.hyundai.hyundaicanfd import CanBus
from opendbc.car.hyundai.interface import CarInterface
from opendbc.car.hyundai.values import CAR
from openpilot.common.params import Params
from openpilot.common.prefix import OpenpilotPrefix
from openpilot.starpilot.aol.intent import read_settings
from openpilot.starpilot.aol.tests.stock_lateral_test_helpers import car_state, hkg_family_case
@pytest.mark.parametrize('identity,lka', [(CAR.GENESIS_GV70_1ST_GEN, False),
(CAR.GENESIS_GV70_ELECTRIFIED_1ST_GEN, True),
(CAR.KIA_EV6, True)])
@pytest.mark.parametrize('tick', [3, 7])
@pytest.mark.parametrize('gesture', ['cancel', 'brake'])
def test_configured_torque_stock_lateral_survives_stock_cruise_transition(identity, lka, tick, gesture):
with ExitStack() as cleanup:
with OpenpilotPrefix():
saved = Params()
saved.put('LKASButtonControl', 9, block=True)
saved.put('MainCruiseButtonControl', 0, block=True)
for key in ('CancelButtonControl', 'LongCancelButtonControl', 'VeryLongCancelButtonControl'):
saved.put(key, 0, block=True)
case = hkg_family_case('hkg_canfd', False)
cleanup.callback(case.doCleanups)
fingerprint = gen_empty_fingerprint()
if lka:
fingerprint[CanBus(None, fingerprint).CAM][0x50] = 16
cp = CarInterface.get_params(identity, fingerprint, [], False, False, False)
assert cp.steerControlType == structs.CarParams.SteerControlType.torque
assert qualified(cp) and not cp.openpilotLongitudinalControl and cp.pcmCruise
case.family_cp = cp.as_reader()
sd, _, step, card, receive = case.family_callers(False)
sd.aol_settings = read_settings(saved)
assert sd.aol_settings == card.aol_card_intent.settings
assert sd.aol_settings.pause_brake_mps == 0
assert card.aol_card_intent.independent_cruise_buttons
engaged = car_state()
engaged.vEgoRaw = engaged.vEgo
engaged.cruiseState.enabled = True
axis, _, command = step(2, observed_state=engaged, panda_controls_allowed=True)
assert sd.enabled and axis.lateralActive and command.latActive
assert not axis.longitudinalActive and not command.longActive
assert receive(10_020_000_000, state=engaged, axis=sd.pm.messages['aolAxisState'],
event=sd.pm.messages['onroadEvents'])
state = car_state()
state.vEgoRaw = state.vEgo
state.cruiseState.enabled = True
if gesture == 'cancel':
state.buttonEvents = [structs.CarState.ButtonEvent(type='cancel', pressed=True)]
else:
state.brakePressed = True
axis, _, command = step(tick, observed_state=state, panda_controls_allowed=gesture == 'cancel')
assert sd.enabled == (gesture == 'cancel')
assert not axis.longitudinalActive and not command.longActive
assert axis.lateralActive and command.latActive
assert receive(10_000_000_000 + tick * 10_000_000, state=state, axis=sd.pm.messages['aolAxisState'],
event=sd.pm.messages['onroadEvents'])
assert card.aol_card_intent.allowed_latch
settled = car_state(brake=gesture == 'brake')
settled.vEgoRaw = settled.vEgo
axis, _, command = step(tick + 1, observed_state=settled)
assert not sd.enabled and not axis.longitudinalActive and not command.longActive
assert axis.lateralActive and command.latActive
assert receive(10_000_000_000 + (tick + 1) * 10_000_000, state=settled,
axis=sd.pm.messages['aolAxisState'], event=sd.pm.messages['onroadEvents'])
assert card.aol_card_intent.allowed_latch
+6 -2
View File
@@ -109,12 +109,16 @@ def stock_lateral_off(cp, cs, native, *, allow_independent_cancel=False, allow_i
from openpilot.starpilot.nostalgia import physical_cancel
from opendbc.car.hyundai.canfd_angle_aol import qualified as angle_qualified
from opendbc.car.hyundai.canfd_stock_aol import qualified as stock_canfd_qualified
independent_angle = angle_qualified(cp, marked_only=True)
independent_brake = independent_angle or (allow_independent_brake and cp.brand == 'hyundai' and
len(cp.safetyConfigs) == 1 and stock_canfd_qualified(cp, marked_only=True))
return bool(cp.pcmCruise and cs.cruiseState.available and
(not cs.cruiseState.enabled or independent_angle and allow_independent_brake and cs.brakePressed) and
(not cs.cruiseState.enabled or independent_brake and allow_independent_brake and cs.brakePressed) and
cs.canValid and not cs.canTimeout and not cs.steerFaultPermanent and not cs.steerFaultTemporary and
not cs.accFaulted and not cs.doorOpen and not cs.seatbeltUnlatched and
(not cs.brakePressed or independent_angle and allow_independent_brake) and
(not cs.brakePressed or independent_brake and allow_independent_brake) and
not cs.regenBraking and (not cs.gasPressed or independent_angle) and
(not physical_cancel(cs, cp) or independent_angle and allow_independent_cancel) and
native is not None and native.requestedLateral and native.lateralAllowed and not native.requestedLongitudinal)
+1 -1
View File
@@ -1 +1 @@
{"protected_inventory_sha256": "5ac0862226ed39da17f48eedaf31f71216c3ba44557194020d15bb031bf2e284", "schema_version": 1}
{"protected_inventory_sha256": "28c9d821cce63586b434f23ee52d427e27a4357a8b42dd53cecb22288f420032", "schema_version": 1}
+3
View File
@@ -33,6 +33,9 @@ DEBUG_SAFETY_CLASS_TARGETS = {
RELEASE_TARGETS = (
"openpilot/starpilot/aol/tests/test_torque_stock_cruise_transition.py",
"openpilot/starpilot/aol/tests/test_torque_stock_brake_guards.py",
"opendbc_repo/opendbc/safety/tests/test_hyundai_torque_stock_transition.py",
"openpilot/starpilot/aol/tests/test_angle_stock_cruise_transition.py",
"opendbc_repo/opendbc/safety/tests/test_hyundai_stock_cruise_transition.py",
"opendbc_repo/opendbc/car/hyundai/tests/test_ioniq5pe_replacement_duplicates.py",