diff --git a/opendbc_repo/opendbc/safety/modes/subaru.h b/opendbc_repo/opendbc/safety/modes/subaru.h index 65c2bde1d0..11dffb2595 100644 --- a/opendbc_repo/opendbc/safety/modes/subaru.h +++ b/opendbc_repo/opendbc/safety/modes/subaru.h @@ -403,7 +403,7 @@ static safety_config subaru_init(uint16_t raw_param) { subaru_aol_enabled = ((unsigned int)alternative_experience == 32U) && ((param == 209U) || (param == 465U) || (param == 16U) || (param == 0U) || (param == 1U) || (param == 17U) || (param == 145U) || avh || (param == 177U) || (param == 401U) || (param == 8U) || (param == 520U) || (param == 512U) || (param == 2225U)); - subaru_aol_main_arm = subaru_aol_enabled && ((param == 17U) || impreza_main); + subaru_aol_main_arm = subaru_aol_enabled && ((param == 17U) || impreza_main || subaru_d_platform); if (subaru_aol_enabled) { static const AolSafetyPolicy policy = { .reset = subaru_aol_reset, diff --git a/opendbc_repo/opendbc/safety/tests/test_subaru_main_aol.py b/opendbc_repo/opendbc/safety/tests/test_subaru_main_aol.py index c572fe8ba3..8d9086bcb6 100644 --- a/opendbc_repo/opendbc/safety/tests/test_subaru_main_aol.py +++ b/opendbc_repo/opendbc/safety/tests/test_subaru_main_aol.py @@ -5,7 +5,7 @@ from opendbc.safety.tests.libsafety import libsafety_py from opendbc.safety.tests import test_subaru_stock_aol as stock_module -@pytest.fixture(params=(17, 4096, 4104, 4608, 4616)) +@pytest.fixture(params=(17, 209, 465, 4096, 4104, 4608, 4616)) def owner(request): item = stock_module.TestSubaruStockAol(methodName='runTest') item.setUp() @@ -71,7 +71,7 @@ def test_new_physical_acc_source_is_required_before_main_edge(owner): def test_acc_wire_checksum_and_counter_cannot_be_faked_by_host(owner): neutral(owner) assert owner.feed() == 1 - bus = 1 if owner.param == 17 else 2 + bus = 1 if owner.param in (17, 209, 465) else 2 bad = owner.frame('ES_Distance', {}, bus) raw = bytearray(bytes(bad.data)) raw[0] ^= 1 @@ -97,9 +97,9 @@ def test_acc_fault_cannot_be_bypassed_by_stock_enable_packets(owner): assert owner.feed() == 1 assert owner.feed(acc_fault=True) == 0 for enabled in (0, 1): - name = 'ES_Status' if owner.param == 17 else 'CruiseControl' + name = 'ES_Status' if owner.param in (17, 209, 465) else 'CruiseControl' values = {'Cruise_Activated': enabled, 'Cruise_On': 1} if name == 'CruiseControl' else {'Cruise_Activated': enabled} - assert owner.safety.safety_rx_hook(owner.frame(name, values, 1 if owner.param == 17 else 0)) + assert owner.safety.safety_rx_hook(owner.frame(name, values, 1 if owner.param in (17, 209, 465) else 0)) owner.safety.aol_set_host_request(1) assert owner.safety.aol_get_permission_mask() == 0 diff --git a/opendbc_repo/opendbc/safety/tests/test_subaru_stock_aol.py b/opendbc_repo/opendbc/safety/tests/test_subaru_stock_aol.py index 7171a19994..54daca375b 100644 --- a/opendbc_repo/opendbc/safety/tests/test_subaru_stock_aol.py +++ b/opendbc_repo/opendbc/safety/tests/test_subaru_stock_aol.py @@ -47,8 +47,8 @@ class TestSubaruStockAol(unittest.TestCase): ('ES_Status', {'Cruise_Activated': int(cruise)}, 2 if self.param == 16 else 1), ('ES_DashStatus', {'Cruise_On': int(main)}, 2), ] - if not omit_distance and self.param in (17, 4096, 4104, 4608, 4616): - frames.append(('ES_Distance', {'Cruise_Fault': int(acc_fault)}, 1 if self.param == 17 else 2)) + if not omit_distance and self.param in (17, 209, 465, 4096, 4104, 4608, 4616): + frames.append(('ES_Distance', {'Cruise_Fault': int(acc_fault)}, 1 if self.param in (17, 209, 465) else 2)) if not omit_gear: frames.append(('Transmission', {'Gear': gear}, gear_bus)) for name, fields, bus in frames: @@ -79,7 +79,7 @@ class TestSubaruStockAol(unittest.TestCase): self.assertEqual(self.feed(temporary=True), 0) self.assertEqual(self.feed(), 1) self.assertEqual(self.feed(main=False), 0) - self.assertEqual(self.feed(main=True), int(param in (17, 4096, 4104, 4608, 4616))) + self.assertEqual(self.feed(main=True), int(param in (17, 209, 465, 4096, 4104, 4608, 4616))) self.assertEqual(self.feed(cruise=True), 1) def test_permanent_fault_and_rx_fault_require_fresh_ordinary_engagement(self): diff --git a/openpilot/starpilot/car/subaru/aol.py b/openpilot/starpilot/car/subaru/aol.py index 63164e5d86..89ad8a6349 100644 --- a/openpilot/starpilot/car/subaru/aol.py +++ b/openpilot/starpilot/car/subaru/aol.py @@ -89,7 +89,7 @@ def ordinary_axis_request_allowed(cp, state): def create_intent(cp, settings): main_arm = (cp.carFingerprint == CAR.SUBARU_CROSSTREK_2025 or - (cp.carFingerprint == CAR.SUBARU_IMPREZA_2020 and qualified(cp))) + (cp.carFingerprint in (CAR.SUBARU_IMPREZA_2020, CAR.SUBARU_OUTBACK_2023) and qualified(cp))) return SubaruStockCardIntent(settings, main_arm=main_arm) diff --git a/openpilot/starpilot/car/subaru/tests/test_main_aol.py b/openpilot/starpilot/car/subaru/tests/test_main_aol.py index b0f66ede09..301246220a 100644 --- a/openpilot/starpilot/car/subaru/tests/test_main_aol.py +++ b/openpilot/starpilot/car/subaru/tests/test_main_aol.py @@ -97,3 +97,26 @@ def test_impreza_main_setting_is_exact_and_preserves_stock_assist_selection(): cp.alternativeExperience = 32 cp.safetyConfigs[0].safetyParam |= IMPREZA_MAIN_AOL assert not qualified(cp) and not sng.eligible(cp) + + +def test_outback_main_intent_uses_only_existing_exact_native_profiles(): + from opendbc.car.subaru.interface import CarInterface + from opendbc.car.subaru.values import CAR, SubaruFlags + from opendbc.car.subaru.stock_aol import qualified + from openpilot.starpilot.car.subaru.aol import create_intent + + for stopped_start in (False, True): + cp = CarInterface.get_non_essential_params(CAR.SUBARU_OUTBACK_2023) + if stopped_start: + cp.flags = int(cp.flags) | int(SubaruFlags.STOP_START_OFF) + cp.safetyConfigs[0].safetyParam |= 256 + assert qualified(cp) + assert create_intent(cp, owner().settings).main_arm + cp.alternativeExperience = 32 + assert qualified(cp, marked_only=True) + cp.safetyConfigs[0].safetyParam |= 2 + assert not qualified(cp) and not create_intent(cp, owner().settings).main_arm + for candidate in (CAR.SUBARU_OUTBACK, CAR.SUBARU_LEGACY_2025): + cp = CarInterface.get_non_essential_params(candidate) + cp.alternativeExperience = 32 + assert qualified(cp) and not create_intent(cp, owner().settings).main_arm diff --git a/openpilot/starpilot/car/subaru/tests/test_stock_aol_callers.py b/openpilot/starpilot/car/subaru/tests/test_stock_aol_callers.py index cc1a5c50ec..230667d424 100644 --- a/openpilot/starpilot/car/subaru/tests/test_stock_aol_callers.py +++ b/openpilot/starpilot/car/subaru/tests/test_stock_aol_callers.py @@ -23,8 +23,8 @@ from openpilot.starpilot.car.subaru.tests.native_fixture import subaru_native_pa @pytest.mark.parametrize('candidate', [CAR.SUBARU_ASCENT_2023, CAR.SUBARU_LEGACY_2025, CAR.SUBARU_CROSSTREK_2025, CAR.SUBARU_FORESTER, CAR.SUBARU_OUTBACK]) def test_actual_full_engage_brake_reverse_temporary_recovery_mainoff(candidate, subaru_native_pair, tmp_path, aol=True, manual=False, stop_resume=False, - hard_stop_native_first=False, main_only=False, preferences=None): - fw = firmware_records(candidate, FW_VERSIONS, 'subaru') + hard_stop_native_first=False, main_only=False, preferences=None, firmware=None): + fw = firmware_records(candidate, FW_VERSIONS, 'subaru') if firmware is None else firmware rows = [] with actual_factory(candidate, gen_empty_fingerprint(), fw, '0' * 17, manual=manual, aol=aol, preferences=preferences) as (card, params, matches): cp = card.CP @@ -232,7 +232,7 @@ def test_actual_full_engage_brake_reverse_temporary_recovery_mainoff(candidate, bool(intent and intent.lateralArmed) == aol and row['cardLatch'] == aol and row['permission'] == 0), row if 240 <= tick < 255: assert not command.latActive and bool(intent and intent.lateralArmed) == aol and row['cardLatch'] == aol and row['permission'] == 0, row - main_rearm = aol and candidate in (CAR.SUBARU_CROSSTREK_2025, CAR.SUBARU_IMPREZA_2020) + main_rearm = aol and candidate in (CAR.SUBARU_CROSSTREK_2025, CAR.SUBARU_IMPREZA_2020, CAR.SUBARU_OUTBACK_2023) if 330 <= tick < (350 if main_rearm else 400): assert not command.latActive and not bool(intent and intent.allowedLatch), row if main_rearm and 375 <= tick < 400: @@ -323,7 +323,7 @@ def test_actual_native_first_hard_stop_retains_intent_and_resumes(candidate, sub assert settled and all(not command['request'] and command['nativeAccepted'] for command in settled) -@pytest.mark.parametrize('candidate', [CAR.SUBARU_CROSSTREK_2025, CAR.SUBARU_IMPREZA_2020]) +@pytest.mark.parametrize('candidate', [CAR.SUBARU_CROSSTREK_2025, CAR.SUBARU_IMPREZA_2020, CAR.SUBARU_OUTBACK_2023]) def test_actual_main_without_set_retains_native_first_stop_intent(subaru_native_pair, tmp_path, candidate): test_actual_full_engage_brake_reverse_temporary_recovery_mainoff( candidate, subaru_native_pair, tmp_path, diff --git a/prebuilt.json b/prebuilt.json index 362036b5de..3ef4c89bee 100644 --- a/prebuilt.json +++ b/prebuilt.json @@ -1 +1 @@ -{"protected_inventory_sha256": "342afaf60ffcf7ce4a22e944e4aa384bfb13c5c08688db613d9a6795bab44822", "schema_version": 1} +{"protected_inventory_sha256": "d5495bdc0d7d08ad60b75642bb28e5b88d60766332d0d8af6a0d1af0cfa8c4b4", "schema_version": 1}