mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-12 07:23:45 +08:00
Reuse exact mixed Hyundai configuration qualification on the control path
This commit is contained in:
@@ -5,6 +5,9 @@ Shared Ioniq and generic Hyundai initialization are intentionally independent.
|
||||
"""
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from functools import lru_cache
|
||||
|
||||
from capnp.lib.capnp import _DynamicStructBuilder, _DynamicStructReader
|
||||
|
||||
from opendbc.car.hyundai.values import CAR, is_blended, HyundaiFlags, HyundaiSafetyFlags
|
||||
|
||||
@@ -194,7 +197,7 @@ class BlendedLongitudinalController:
|
||||
return messages
|
||||
|
||||
|
||||
def mixed_startup_qualified(cp, *, is_release=False, allow_marked=False):
|
||||
def _mixed_startup_qualified_uncached(cp, *, is_release=False, allow_marked=False):
|
||||
"""Exact prepared mixed owner; stock topology remains immutable."""
|
||||
from opendbc.car import structs
|
||||
from opendbc.car.hyundai.hyundaicanfd import CanBus
|
||||
@@ -538,3 +541,23 @@ def startup_owner(cp, callbacks, *, requested):
|
||||
candidate = candidate_from_stock(cp, alpha_requested=requested,
|
||||
native_qualified=cp.alphaLongitudinalAvailable and mixed_startup_qualified(cp))
|
||||
return None if candidate is None else BlendedStartup(cp, candidate, callbacks)
|
||||
|
||||
|
||||
@lru_cache(maxsize=32)
|
||||
def _mixed_startup_for_bytes(key, is_release, allow_marked):
|
||||
from opendbc.car import structs
|
||||
with structs.CarParams.from_bytes(key) as cp:
|
||||
return _mixed_startup_qualified_uncached(cp, is_release=is_release, allow_marked=allow_marked)
|
||||
|
||||
|
||||
def mixed_startup_qualified(cp, *, is_release=False, allow_marked=False):
|
||||
from opendbc.car import structs
|
||||
if type(cp) in (_DynamicStructBuilder, _DynamicStructReader) and cp.schema == structs.CarParams.schema:
|
||||
try:
|
||||
snapshot = cp.copy() if type(cp) is _DynamicStructBuilder else cp.as_builder()
|
||||
key = snapshot.to_bytes()
|
||||
if len(key) <= 65536:
|
||||
return _mixed_startup_for_bytes(key, is_release, allow_marked)
|
||||
except Exception:
|
||||
pass
|
||||
return _mixed_startup_qualified_uncached(cp, is_release=is_release, allow_marked=allow_marked)
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from opendbc.car.hyundai import blended_longitudinal as mixed
|
||||
from opendbc.car.hyundai.tests.test_blended_stock_aol import params
|
||||
|
||||
|
||||
@pytest.fixture(params=(False, True))
|
||||
def cp(request):
|
||||
cache = getattr(mixed, '_mixed_startup_for_bytes', None)
|
||||
if cache is not None:
|
||||
cache.cache_clear()
|
||||
return params(request.param)
|
||||
|
||||
|
||||
def test_same_static_configuration_is_qualified_once(cp):
|
||||
before = cp.to_dict()
|
||||
with patch.object(mixed, 'alpha_eligible', wraps=mixed.alpha_eligible) as evaluate:
|
||||
for _ in range(20):
|
||||
assert mixed.mixed_startup_qualified(cp)
|
||||
assert mixed.mixed_startup_qualified(cp.as_reader())
|
||||
assert evaluate.call_count == 1
|
||||
assert cp.to_dict() == before
|
||||
|
||||
|
||||
@pytest.mark.parametrize('field', ('flags', 'brand', 'carFingerprint', 'passive', 'dashcamOnly', 'notCar',
|
||||
'steerControlType', 'alternativeExperience', 'safetyConfigs', 'safetyModel',
|
||||
'safetyParam', 'pcmCruise', 'openpilotLongitudinalControl', 'mass', 'carVin', 'carFw'))
|
||||
def test_changes_on_same_builder_are_requalified(cp, field):
|
||||
uncached = getattr(mixed, '_mixed_startup_qualified_uncached', mixed.mixed_startup_qualified)
|
||||
assert mixed.mixed_startup_qualified(cp)
|
||||
if field in ('passive', 'dashcamOnly', 'notCar', 'pcmCruise', 'openpilotLongitudinalControl'):
|
||||
setattr(cp, field, not getattr(cp, field))
|
||||
elif field in ('flags', 'alternativeExperience'):
|
||||
setattr(cp, field, int(getattr(cp, field)) ^ 1)
|
||||
elif field == 'safetyConfigs':
|
||||
cp.safetyConfigs = []
|
||||
elif field == 'safetyParam':
|
||||
cp.safetyConfigs[0].safetyParam ^= 1
|
||||
elif field == 'safetyModel':
|
||||
cp.safetyConfigs[0].safetyModel = 'noOutput'
|
||||
elif field == 'steerControlType':
|
||||
cp.steerControlType = 'angle'
|
||||
elif field == 'mass':
|
||||
cp.mass += 1
|
||||
elif field == 'carFw':
|
||||
cp.carFw = [{'ecu': 'eps', 'fwVersion': b'changed'}]
|
||||
else:
|
||||
setattr(cp, field, 'changed')
|
||||
with patch.object(mixed, 'alpha_eligible', wraps=mixed.alpha_eligible) as evaluate:
|
||||
for release in (False, True):
|
||||
for marked in (False, True):
|
||||
assert mixed.mixed_startup_qualified(cp, is_release=release, allow_marked=marked) == uncached(cp, is_release=release, allow_marked=marked)
|
||||
assert evaluate.call_count > 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize('longitudinal', (False, True))
|
||||
@pytest.mark.parametrize('marked', (False, True))
|
||||
def test_stock_long_and_aol_profiles_retain_release_restriction(cp, longitudinal, marked):
|
||||
cp.openpilotLongitudinalControl = longitudinal
|
||||
cp.pcmCruise = not longitudinal
|
||||
if longitudinal:
|
||||
cp.safetyConfigs[0].safetyParam |= 4
|
||||
cp.alternativeExperience = 32 if marked else 0
|
||||
assert mixed.mixed_startup_qualified(cp, allow_marked=marked)
|
||||
assert not mixed.mixed_startup_qualified(cp, is_release=True, allow_marked=marked)
|
||||
if marked:
|
||||
assert not mixed.mixed_startup_qualified(cp)
|
||||
|
||||
|
||||
def test_proxy_and_snapshot_failure_retain_original_validation(cp):
|
||||
class Proxy:
|
||||
def __getattr__(self, name):
|
||||
return getattr(cp, name)
|
||||
assert mixed.mixed_startup_qualified(Proxy())
|
||||
cached = getattr(mixed, '_mixed_startup_for_bytes', None)
|
||||
if cached is not None:
|
||||
with patch.object(mixed, '_mixed_startup_for_bytes', side_effect=RuntimeError('cache unavailable')):
|
||||
assert mixed.mixed_startup_qualified(cp)
|
||||
cp.passive = True
|
||||
assert not mixed.mixed_startup_qualified(cp)
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"protected_inventory_sha256": "cd934dc89ad38cfecee7994f992b3f426038c914fa9184b8c7e835b349485acd", "schema_version": 1}
|
||||
{"protected_inventory_sha256": "745786774cd0e323f79d7003c30cbacd2a576521102175b8188f790902d142ba", "schema_version": 1}
|
||||
|
||||
Reference in New Issue
Block a user