sunnypilot v2026.002.000
version: sunnypilot v2026.002.000 (staging) date: 2026-07-21T07:44:02 master commit: 2c334ede443d7391d27575af8c854a095ba702a8
This commit is contained in:
commit
de77c89cf6
3995 files changed
+1260688
No files matched your search
@@ -0,0 +1,204 @@
|
||||
"""
|
||||
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
||||
|
||||
This file is part of sunnypilot and is licensed under the MIT License.
|
||||
See the LICENSE.md file in the root directory for more details.
|
||||
"""
|
||||
|
||||
import pickle
|
||||
import pytest
|
||||
|
||||
import openpilot.sunnypilot.models.helpers as helpers
|
||||
import openpilot.sunnypilot.modeld_v2.modeld as modeld_module
|
||||
from openpilot.sunnypilot.modeld_v2.constants import ModelConstants
|
||||
from openpilot.sunnypilot.models.split_model_constants import SplitModelConstants
|
||||
|
||||
|
||||
class DummyOverride:
|
||||
def __init__(self, key, value):
|
||||
self.key = key
|
||||
self.value = value
|
||||
|
||||
|
||||
class DummyArtifact:
|
||||
def __init__(self, file_name):
|
||||
self.fileName = file_name
|
||||
|
||||
|
||||
class DummyModelType:
|
||||
def __init__(self, raw):
|
||||
self.raw = raw
|
||||
|
||||
|
||||
class DummyModel:
|
||||
def __init__(self, type_str, artifact_file):
|
||||
self.type = DummyModelType(type_str)
|
||||
self.artifact = DummyArtifact(artifact_file)
|
||||
|
||||
|
||||
class DummyBundle:
|
||||
def __init__(self, is_20hz=False, models=None, generation=10):
|
||||
self.overrides = [DummyOverride('lat', '.1'), DummyOverride('long', '.3')]
|
||||
self.generation = generation
|
||||
self.is20hz = is_20hz
|
||||
self.models = models or []
|
||||
|
||||
|
||||
class Archetype:
|
||||
def __init__(self, name, metadata_structure, model_stubs, is_20hz,
|
||||
expected_model_type, expected_constants_class, expected_parser_module,
|
||||
expected_desire_key):
|
||||
self.name = name
|
||||
self.metadata_structure = metadata_structure
|
||||
self.model_stubs = model_stubs
|
||||
self.is_20hz = is_20hz
|
||||
self.expected_model_type = expected_model_type
|
||||
self.expected_constants_class = expected_constants_class
|
||||
self.expected_parser_module = expected_parser_module
|
||||
self.expected_desire_key = expected_desire_key
|
||||
|
||||
|
||||
def _noop_jit(**kwargs):
|
||||
pass
|
||||
|
||||
|
||||
def _make_vision_policy_metadata(vision_input_shapes, policy_input_shapes,
|
||||
vision_output_slices, policy_output_slices):
|
||||
return {
|
||||
'vision': {'input_shapes': vision_input_shapes, 'output_slices': vision_output_slices},
|
||||
'policy': {'input_shapes': policy_input_shapes, 'output_slices': policy_output_slices},
|
||||
}
|
||||
|
||||
|
||||
def _make_multi_policy_metadata(vision_input_shapes, policy_input_shapes,
|
||||
vision_output_slices, policy_output_slices):
|
||||
return {
|
||||
'vision': {'input_shapes': vision_input_shapes, 'output_slices': vision_output_slices},
|
||||
'offPolicy': {'input_shapes': policy_input_shapes, 'output_slices': policy_output_slices},
|
||||
}
|
||||
|
||||
|
||||
def _make_tri_policy_metadata(vision_input_shapes, policy_input_shapes,
|
||||
vision_output_slices, policy_output_slices):
|
||||
return {
|
||||
'vision': {'input_shapes': vision_input_shapes, 'output_slices': vision_output_slices},
|
||||
'onPolicy': {'input_shapes': policy_input_shapes, 'output_slices': policy_output_slices},
|
||||
'offPolicy': {'input_shapes': policy_input_shapes, 'output_slices': policy_output_slices},
|
||||
}
|
||||
|
||||
|
||||
def _make_supercombo_metadata(input_shapes, output_slices):
|
||||
return {'model': {'input_shapes': input_shapes, 'output_slices': output_slices}}
|
||||
|
||||
|
||||
SPLIT_VISION_INPUT_SHAPES = {'img': (1, 12, 128, 256), 'big_img': (1, 12, 128, 256)}
|
||||
SPLIT_POLICY_INPUT_SHAPES = {'features_buffer': (1, 25, 512), 'desire_pulse': (1, 25, 8), 'traffic_convention': (1, 2)}
|
||||
SPLIT_VISION_SLICES = {'hidden_state': slice(0, 512), 'pose': slice(512, 524)}
|
||||
SPLIT_POLICY_SLICES = {'plan': slice(0, 495), 'meta': slice(495, 550)}
|
||||
|
||||
SUPERCOMBO_INPUT_SHAPES = {
|
||||
'img': (1, 12, 128, 256), 'big_img': (1, 12, 128, 256),
|
||||
'desire': (1, 100, 8), 'features_buffer': (1, 99, 512),
|
||||
'lateral_control_params': (1, 2), 'prev_desired_curv': (1, 100, 1),
|
||||
'traffic_convention': (1, 2),
|
||||
}
|
||||
SUPERCOMBO_SLICES = {'plan': slice(0, 495), 'hidden_state': slice(495, 1007), 'meta': slice(1007, 1062)}
|
||||
|
||||
CAM_W, CAM_H = 1928, 1208
|
||||
|
||||
ARCHETYPES = {
|
||||
'vision_policy_split': Archetype(
|
||||
name='vision_policy_split',
|
||||
metadata_structure=_make_vision_policy_metadata(
|
||||
SPLIT_VISION_INPUT_SHAPES, SPLIT_POLICY_INPUT_SHAPES,
|
||||
SPLIT_VISION_SLICES, SPLIT_POLICY_SLICES),
|
||||
model_stubs=[DummyModel('vision', 'driving_test_tinygrad.pkl'),
|
||||
DummyModel('policy', 'driving_test_tinygrad.pkl')],
|
||||
is_20hz=True,
|
||||
expected_model_type='split',
|
||||
expected_constants_class=SplitModelConstants,
|
||||
expected_parser_module='parse_model_outputs_split',
|
||||
expected_desire_key='desire',
|
||||
),
|
||||
'vision_multi_policy': Archetype(
|
||||
name='vision_multi_policy',
|
||||
metadata_structure=_make_multi_policy_metadata(
|
||||
SPLIT_VISION_INPUT_SHAPES, SPLIT_POLICY_INPUT_SHAPES,
|
||||
SPLIT_VISION_SLICES, SPLIT_POLICY_SLICES),
|
||||
model_stubs=[DummyModel('vision', 'driving_test_tinygrad.pkl'),
|
||||
DummyModel('offPolicy', 'driving_test_tinygrad.pkl')],
|
||||
is_20hz=True,
|
||||
expected_model_type='multi_policy',
|
||||
expected_constants_class=SplitModelConstants,
|
||||
expected_parser_module='parse_model_outputs_split',
|
||||
expected_desire_key='desire',
|
||||
),
|
||||
'tri_policy': Archetype(
|
||||
name='tri_policy',
|
||||
metadata_structure=_make_tri_policy_metadata(
|
||||
SPLIT_VISION_INPUT_SHAPES, SPLIT_POLICY_INPUT_SHAPES,
|
||||
SPLIT_VISION_SLICES, SPLIT_POLICY_SLICES),
|
||||
model_stubs=[DummyModel('vision', 'driving_test_tinygrad.pkl'),
|
||||
DummyModel('onPolicy', 'driving_test_tinygrad.pkl'),
|
||||
DummyModel('offPolicy', 'driving_test_tinygrad.pkl')],
|
||||
is_20hz=True,
|
||||
expected_model_type='multi_policy',
|
||||
expected_constants_class=SplitModelConstants,
|
||||
expected_parser_module='parse_model_outputs_split',
|
||||
expected_desire_key='desire',
|
||||
),
|
||||
'supercombo_non20hz': Archetype(
|
||||
name='supercombo_non20hz',
|
||||
metadata_structure=_make_supercombo_metadata(SUPERCOMBO_INPUT_SHAPES, SUPERCOMBO_SLICES),
|
||||
model_stubs=[DummyModel('supercombo', 'driving_test_tinygrad.pkl')],
|
||||
is_20hz=False,
|
||||
expected_model_type='supercombo',
|
||||
expected_constants_class=ModelConstants,
|
||||
expected_parser_module='parse_model_outputs',
|
||||
expected_desire_key='desire',
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def make_pkl_data(archetype):
|
||||
return {
|
||||
'metadata': archetype.metadata_structure,
|
||||
(CAM_W, CAM_H): {'run_policy': _noop_jit, 'warp_enqueue': _noop_jit},
|
||||
}
|
||||
|
||||
|
||||
def write_pkl(tmp_path, archetype):
|
||||
pkl_path = tmp_path / 'driving_test_tinygrad.pkl'
|
||||
with open(pkl_path, 'wb') as f:
|
||||
pickle.dump(make_pkl_data(archetype), f)
|
||||
return pkl_path
|
||||
|
||||
|
||||
def make_bundle(archetype):
|
||||
return DummyBundle(
|
||||
models=archetype.model_stubs,
|
||||
is_20hz=archetype.is_20hz,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def patch_modeld(monkeypatch):
|
||||
def _patch(bundle):
|
||||
monkeypatch.setattr(helpers, 'get_active_bundle', lambda params=None: bundle, raising=False)
|
||||
monkeypatch.setattr(modeld_module, 'get_active_bundle', lambda params=None: bundle, raising=False)
|
||||
|
||||
return _patch
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def model_state_factory(tmp_path, monkeypatch, patch_modeld):
|
||||
from openpilot.common.hardware import hw
|
||||
|
||||
def _create(archetype):
|
||||
write_pkl(tmp_path, archetype)
|
||||
bundle = make_bundle(archetype)
|
||||
patch_modeld(bundle)
|
||||
monkeypatch.setattr(hw.Paths, 'model_root', staticmethod(lambda: str(tmp_path)))
|
||||
return modeld_module.ModelState(cam_w=CAM_W, cam_h=CAM_H)
|
||||
|
||||
return _create
|
||||
Reference in new issue
Block a user