From 076cda2d6c4e10170ff02fc7cb4b9dfd4865e564 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Fri, 23 Oct 2026 15:54:01 -0500 Subject: [PATCH] Support stock Prius retrofit AOL --- openpilot/starpilot/car/toyota/aol.py | 13 ++++ .../toyota/tests/test_prius_retrofit_stock.py | 69 +++++++++++++++++ .../test_prius_retrofit_stock_callers.py | 74 +++++++++++++++++++ .../toyota/tests/test_rav4h_caller_native.py | 9 ++- prebuilt.json | 2 +- tools/ci/run_vehicle_tests.py | 4 + 6 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 openpilot/starpilot/car/toyota/tests/test_prius_retrofit_stock.py create mode 100644 openpilot/starpilot/car/toyota/tests/test_prius_retrofit_stock_callers.py diff --git a/openpilot/starpilot/car/toyota/aol.py b/openpilot/starpilot/car/toyota/aol.py index 7696be40c5..0478d968ab 100644 --- a/openpilot/starpilot/car/toyota/aol.py +++ b/openpilot/starpilot/car/toyota/aol.py @@ -85,7 +85,20 @@ def matrix_stock_qualified(cp, *, marked_only=False): return config.safetyModel == structs.CarParams.SafetyModel.toyota and config.safetyParam == 856 +def stock_prius_retrofit_qualified(cp, *, marked_only=False): + if (cp is None or cp.brand != 'toyota' or cp.carFingerprint != CAR.TOYOTA_PRIUS_RETROFIT or + cp.notCar or cp.passive or cp.dashcamOnly or cp.secOcRequired or not cp.pcmCruise or + cp.openpilotLongitudinalControl or cp.steerControlType != structs.CarParams.SteerControlType.torque or + len(cp.safetyConfigs) != 1 or cp.flags & ~int(ToyotaFlags.ZSS) != int(ToyotaFlags.HYBRID) or + cp.alternativeExperience not in ((32,) if marked_only else (0, 32))): + return False + config = cp.safetyConfigs[0] + return config.safetyModel == structs.CarParams.SafetyModel.toyota and config.safetyParam == 585 + + def qualified(cp, *, marked_only=False): + if stock_prius_retrofit_qualified(cp, marked_only=marked_only): + return True if matrix_stock_qualified(cp, marked_only=marked_only): return True if angle_qualified(cp, marked_only=marked_only): diff --git a/openpilot/starpilot/car/toyota/tests/test_prius_retrofit_stock.py b/openpilot/starpilot/car/toyota/tests/test_prius_retrofit_stock.py new file mode 100644 index 0000000000..ae4fd898ef --- /dev/null +++ b/openpilot/starpilot/car/toyota/tests/test_prius_retrofit_stock.py @@ -0,0 +1,69 @@ +import pytest +import struct +from opendbc.car import gen_empty_fingerprint, structs +from opendbc.car.toyota.interface import CarInterface +from opendbc.car.toyota.values import CAR, ToyotaFlags +from openpilot.starpilot.car.toyota.aol import policy_for, qualified, stock_prius_retrofit_qualified + + +def factory(*, alpha=False, zss=False): + fp = gen_empty_fingerprint() + if zss: + fp[0][0x23] = 8 + fw = [structs.CarParams.CarFw(ecu=structs.CarParams.Ecu.eps, address=0x7A1, + fwVersion=b'8965B47070' + bytes(6), brand='toyota', bus=0)] + return CarInterface.get_params(CAR.TOYOTA_PRIUS_RETROFIT, fp, fw, alpha, False, False) + + +@pytest.mark.parametrize('alpha', (False, True)) +@pytest.mark.parametrize('zss', (False, True)) +def test_manual_stock_prius_retrofit_factory_and_policy(alpha, zss): + cp = factory(alpha=alpha, zss=zss) + before = cp.to_dict() + assert not cp.openpilotLongitudinalControl and cp.pcmCruise and not cp.dashcamOnly + assert cp.safetyConfigs[0].safetyParam == 585 + assert cp.flags == int(ToyotaFlags.HYBRID) | (int(ToyotaFlags.ZSS) if zss else 0) + assert cp.steerActuatorDelay == struct.unpack('= 220: + assert cs.cruiseState.available and not cs.cruiseState.enabled + assert host.aol_card_intent.allowed_latch and cc.latActive + assert safety.aol_get_permission_mask() == 1 + if scenario == 'ordinary-cruise' and tick >= 220: + assert not host.aol_card_intent.settings.enabled + assert not host.aol_card_intent.allowed_latch + assert cs.cruiseState.enabled and cc.enabled and cc.latActive + if scenario == 'saved-long-off' and tick >= 310: + assert not host.CP.openpilotLongitudinalControl and not cc.longActive + assert host.CP.safetyConfigs[0].safetyParam == 585 + + fw = [structs.CarParams.CarFw(ecu=structs.CarParams.Ecu.eps, address=0x7A1, + fwVersion=b'8965B47070' + bytes(6), brand='toyota', bus=0)] + actual_scenario = 'physical' if scenario == 'physical' else 'off' if scenario == 'saved-long-off' else 'nominal' + helpers.run_case(True, actual_scenario, candidate=CAR.TOYOTA_PRIUS_RETROFIT, + bridge=host_heartbeat_bridge, input_clock=True, aol=scenario != 'ordinary-cruise', + sdsu_words=(585, 585), firmware_override=fw, fingerprint_frames=[], manual_selection=True, + physical_frames=physical, on_state=on_state, on_sample=observe) diff --git a/openpilot/starpilot/car/toyota/tests/test_rav4h_caller_native.py b/openpilot/starpilot/car/toyota/tests/test_rav4h_caller_native.py index 416f09ddde..81a68c2818 100644 --- a/openpilot/starpilot/car/toyota/tests/test_rav4h_caller_native.py +++ b/openpilot/starpilot/car/toyota/tests/test_rav4h_caller_native.py @@ -248,8 +248,13 @@ def run_case(stock, scenario='nominal', *, aol=True, candidate=CAR.TOYOTA_RAV4H, params.put('AolBrakePauseSpeedMps', float(brake_pause_mps), block=True) fw = firmware(candidate) if firmware_override is None else firmware_override if manual_selection: - assert candidate == CAR.TOYOTA_MATRIX_RETROFIT and stock and not fw - assert firmware_override == [] and fingerprint_frames == [] + assert stock and fingerprint_frames == [] + if candidate == CAR.TOYOTA_MATRIX_RETROFIT: + assert not fw and firmware_override == [] + else: + assert candidate == CAR.TOYOTA_PRIUS_RETROFIT and len(fw) == 1 + assert fw[0].ecu == structs.CarParams.Ecu.eps and fw[0].address == 0x7A1 and fw[0].bus == 0 + assert bytes(fw[0].fwVersion) == b'8965B47070' + bytes(6) else: exact, found = match_fw_to_car(fw, '', log=False) assert exact and found == {candidate} diff --git a/prebuilt.json b/prebuilt.json index 63132ec339..377fa5a466 100644 --- a/prebuilt.json +++ b/prebuilt.json @@ -1 +1 @@ -{"protected_inventory_sha256": "4e7069cd3da0a1f7965dac62ce06f6bfc8711c9ca7ae71c48488a1b1ad2be14d", "schema_version": 1} +{"protected_inventory_sha256": "b62ac613ee4e66f5782643aff34ead6342241e888d716d437c4e70f75c09d6b3", "schema_version": 1} diff --git a/tools/ci/run_vehicle_tests.py b/tools/ci/run_vehicle_tests.py index 83e6da04ba..f301c2ac29 100644 --- a/tools/ci/run_vehicle_tests.py +++ b/tools/ci/run_vehicle_tests.py @@ -24,6 +24,8 @@ from tools.ci import lifecycle_shards, vehicle_pytest # Representative production callers plus their source/native refusal cases. # The emitted selected_test_ids record exact parametrized configurations. AOL_LIFECYCLE_TARGETS = ( + 'openpilot/starpilot/car/toyota/tests/test_prius_retrofit_stock.py', + 'openpilot/starpilot/car/toyota/tests/test_prius_retrofit_stock_callers.py', 'openpilot/starpilot/aol/tests/test_crossmake_native_admission.py', 'openpilot/starpilot/aol/tests/test_hkg_source_policy_cache.py', 'openpilot/starpilot/aol/tests/test_hkg_native_admission.py', @@ -206,6 +208,8 @@ DEBUG_SAFETY_CLASS_TARGETS = { RELEASE_TARGETS = ( + 'openpilot/starpilot/car/toyota/tests/test_prius_retrofit_stock.py', + 'openpilot/starpilot/car/toyota/tests/test_prius_retrofit_stock_callers.py', 'opendbc_repo/opendbc/car/hyundai/tests/test_long_cp_copy.py', 'opendbc_repo/opendbc/car/ford/tests/test_mache_display_handoff.py', 'opendbc_repo/opendbc/safety/tests/test_ford_mache_display.py',