mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-29 09:33:48 +08:00
Support stock Prius retrofit AOL
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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('<f', struct.pack('<f', .14))[0]
|
||||
assert cp.lateralTuning.torque.steeringAngleDeadzoneDeg == struct.unpack('<f', struct.pack('<f', .3))[0]
|
||||
assert stock_prius_retrofit_qualified(cp) and qualified(cp)
|
||||
assert policy_for(cp).runtime_supported
|
||||
assert cp.to_dict() == before, 'Admission must not change any existing tune or configuration'
|
||||
assert not stock_prius_retrofit_qualified(cp, marked_only=True)
|
||||
cp.alternativeExperience = 32
|
||||
assert stock_prius_retrofit_qualified(cp, marked_only=True) and qualified(cp, marked_only=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('field,value', (
|
||||
('notCar', True), ('passive', True), ('dashcamOnly', True), ('secOcRequired', True),
|
||||
('pcmCruise', False), ('openpilotLongitudinalControl', True), ('flags', 0),
|
||||
('flags', int(ToyotaFlags.HYBRID | ToyotaFlags.LONG_FILTER)),
|
||||
('flags', int(ToyotaFlags.HYBRID | ToyotaFlags.GAS_INTERCEPTOR)),
|
||||
('flags', int(ToyotaFlags.HYBRID | ToyotaFlags.AUTO_BRAKE_HOLD)),
|
||||
('steerControlType', structs.CarParams.SteerControlType.angle),
|
||||
('carFingerprint', CAR.TOYOTA_PRIUS), ('carFingerprint', CAR.TOYOTA_MATRIX_RETROFIT),
|
||||
('brand', 'gm'), ('alternativeExperience', 128), ('alternativeExperience', 160),
|
||||
))
|
||||
def test_stock_prius_retrofit_admission_refuses_foreign_configuration(field, value):
|
||||
cp = factory()
|
||||
setattr(cp, field, value)
|
||||
assert not stock_prius_retrofit_qualified(cp)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('word', (73, 584, 586, 4169, 4681, 0x8042, 0x8242, 0xC042, 0xC242))
|
||||
def test_stock_prius_retrofit_rejects_other_native_owners(word):
|
||||
cp = factory()
|
||||
cp.safetyConfigs[0].safetyParam = word
|
||||
assert not stock_prius_retrofit_qualified(cp)
|
||||
|
||||
|
||||
def test_stock_prius_retrofit_refuses_invalid_native_inventory():
|
||||
cp = factory()
|
||||
cp.safetyConfigs = []
|
||||
assert not stock_prius_retrofit_qualified(cp)
|
||||
cp = factory()
|
||||
cp.safetyConfigs = [cp.safetyConfigs[0], cp.safetyConfigs[0]]
|
||||
assert not stock_prius_retrofit_qualified(cp)
|
||||
cp = factory()
|
||||
cp.safetyConfigs[0].safetyModel = structs.CarParams.SafetyModel.gm
|
||||
assert not stock_prius_retrofit_qualified(cp)
|
||||
assert not stock_prius_retrofit_qualified(None)
|
||||
@@ -0,0 +1,74 @@
|
||||
"""Manual EPS73 Prius through the current factory, callers, C++ peer and native.
|
||||
|
||||
Manual selection, acquired firmware, CAN/perception and USB are input fixtures.
|
||||
These tests do not establish physical vehicle or scheduling acceptance.
|
||||
"""
|
||||
import struct
|
||||
|
||||
import pytest
|
||||
from opendbc.car import structs
|
||||
from opendbc.car.toyota.values import CAR, ToyotaFlags
|
||||
from openpilot.starpilot.car.toyota.tests import test_rav4h_caller_native as helpers
|
||||
from openpilot.starpilot.car.toyota.tests.test_toyota_cpp_transport import host_heartbeat_bridge as host_heartbeat_bridge
|
||||
|
||||
source_matched_native = helpers.source_matched_native
|
||||
daemon_gc_scope = helpers.daemon_gc_scope
|
||||
|
||||
|
||||
@pytest.mark.parametrize('scenario', ('startup-main', 'physical', 'saved-long-off', 'ordinary-cruise'))
|
||||
def test_actual_prius_retrofit_stock_lifecycle(scenario, host_heartbeat_bridge):
|
||||
def physical(packer, **fields):
|
||||
fields['sdsu'] = None
|
||||
if scenario == 'startup-main':
|
||||
fields['cruise'] = False
|
||||
frames = helpers.physical(packer, **fields)
|
||||
frames.append(packer.make_can_msg('ACC_CONTROL', 0, {}))
|
||||
assert len(next(data for address, data, bus in frames if address == 0x262 and bus == 0)) == 8
|
||||
assert len(next(data for address, data, bus in frames if address == 0x1D3 and bus == 0)) == 8
|
||||
return frames
|
||||
|
||||
def on_state(tick, host, cs):
|
||||
cp = host.CP
|
||||
assert cp.carFingerprint == CAR.TOYOTA_PRIUS_RETROFIT
|
||||
assert cp.safetyConfigs[0].safetyParam == 585 and cp.flags == int(ToyotaFlags.HYBRID)
|
||||
assert cp.pcmCruise and not cp.openpilotLongitudinalControl
|
||||
assert cp.steerActuatorDelay == struct.unpack('<f', struct.pack('<f', .14))[0]
|
||||
assert cp.lateralTuning.torque.steeringAngleDeadzoneDeg == struct.unpack('<f', struct.pack('<f', .3))[0]
|
||||
|
||||
def observe(tick, host, cs, cc, safety, native):
|
||||
assert not cc.longActive and not safety.aol_get_permission_mask() & 2
|
||||
if scenario == 'physical':
|
||||
if tick == 265:
|
||||
assert cs.gasPressed and not cs.brakePressed
|
||||
assert cc.latActive and safety.aol_get_permission_mask() == 1
|
||||
if tick == 355:
|
||||
assert cs.brakePressed and cs.standstill
|
||||
assert cc.latActive and safety.aol_get_permission_mask() == 1
|
||||
if tick == 415:
|
||||
assert cs.gearShifter == structs.CarState.GearShifter.neutral
|
||||
assert not cc.latActive and not cc.longActive and safety.aol_get_permission_mask() == 0
|
||||
if tick == 425:
|
||||
assert cs.gearShifter == structs.CarState.GearShifter.reverse
|
||||
assert not cc.latActive and not cc.longActive and safety.aol_get_permission_mask() == 0
|
||||
if tick == 505:
|
||||
assert cs.gearShifter == structs.CarState.GearShifter.drive
|
||||
assert cc.latActive and safety.aol_get_permission_mask() == 1
|
||||
if scenario == 'startup-main' and tick >= 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)
|
||||
@@ -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}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"protected_inventory_sha256": "4e7069cd3da0a1f7965dac62ce06f6bfc8711c9ca7ae71c48488a1b1ad2be14d", "schema_version": 1}
|
||||
{"protected_inventory_sha256": "b62ac613ee4e66f5782643aff34ead6342241e888d716d437c4e70f75c09d6b3", "schema_version": 1}
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user