mirror of
https://github.com/infiniteCable2/openpilot.git
synced 2026-09-11 02:33:41 +08:00
c47aadee19
* Tinygrad bump from sync-20250627
* bump tinygrad_repo
* Reformat metadata generator to match driving_models.json
* bump tinygrad
* Revert "bump tinygrad"
This reverts commit f479dfd5021266e22b34deca06cc3c4d531fb7e8.
* revert me after SP model compiled
* Model recompiled successfully, initiate "revert me after SP model compiled"
This reverts commit 95706eb688c9f5522903bee21892b8871ff8f957.
* The "FillMe" placeholder caused an extra 10 seconds of work
* bump to 22Jul2025
* Update build-all-tinygrad-models.yaml
* Update build-all-tinygrad-models.yaml
* Update build-all-tinygrad-models.yaml
* Update build-all-tinygrad-models.yaml
* Update build-all-tinygrad-models.yaml
* Update build-all-tinygrad-models.yaml
* Update build-all-tinygrad-models.yaml
* Allow more dynamic short names
This should hopefully be future-proof for now.. It's robust enough to return the correct word-digit format (see example on how it generates from given display name below):
'Last Horizon V2 (November 22, 2024)' -> LHV2
'Alabama (November 25, 2024)' -> ALABAMA
'PlayStation (December 03, 2024)' -> PLAYSTAT
'Postal Service (December 09, 2024)' -> PS
'Null Pointer (December 13, 2024)' -> NP
'North America (December 16, 2024)' -> NA
'National Public Radio (December 18, 2024)' -> NPR
'Filet o Fish (March 7, 2025)' -> FOF
'Tomb Raider 2 (April 18, 2025)' -> TR2
'Tomb Raider 3 (April 22, 2025)' -> TR3
'Tomb Raider 4 (April 25, 2025)' -> TR4
'Tomb Raider 5 (April 25, 2025)' -> TR5
'Tomb Raider 6 (April 30, 2025)' -> TR6
'Tomb Raider 7 (May 07, 2025)' -> TR7
'Down to Ride (Revision: May 10, 2025)' -> DTR
'SP Vikander Model (May 16, 2025)' -> SPVM
'VFF Driving (May 15, 2025)' -> VFFD
'Secret Good Openpilot (May 16, 2025)' -> SGO
'Vegetarian Filet o Fish (May 29, 2025)' -> VFOF
'Down To Ride (Revision: May 30, 2025)' -> DTR
'Vegetarian Filet o Fish v2 (June 05, 2025)' -> VFOFV2
'Kerrygold Driving (June 08, 2025)' -> KD
'Tomb Raider 10 (June 16, 2025)' -> TR10
'Organic Kerrygold (June 17, 2025)' -> OK
'Liquid Crystal Driving (June 21, 2025)' -> LCD
'Vegetarian Filet o Fish v3 (June 21, 2025)' -> VFOFV3
'Vibe Model [Custom Model]' -> VMCM
'Tomb Raider 13 (June 27, 2025)' -> TR13
'Aggressive TR (June 28, 2025)' -> ATR
'Tomb Raider 14 (June 30, 2025)' -> TR14
'Cookiemonster Tomb Raider (July 02, 2025)' -> CTR
'Down to Ride (Revision: July 07, 2025)' -> DTR
'Simple Plan Driving (July 07, 2025)' -> SPD
'Down to Ride (Revision: July 08, 2025)' -> DTR
'Tomb Raider 15 (July 09, 2025)' -> TR15
'Tomb Raider 15 rev-2 (July 11, 2025)' -> TR15R2
'Le Tomb Raider 14 (July 14, 2025)' -> LTR14
'Le Tomb Raider 14h (July 17, 2025)' -> LTR14H
'Tomb Raider 16 (July 18, 2025)' -> TR16
'Tomb Raider 16v2 (July 21, 2025)' -> TR16V2
* Update build-all-tinygrad-models.yaml
* Update build-all-tinygrad-models.yaml
* No need to sleep 3 seconds, just send it
* try dynamic
* cleanup
* Update build-single-tinygrad-model.yaml
* bc devtekve said. also, this is repetitive af
* Revert "bc devtekve said. also, this is repetitive af"
This reverts commit 3a0c1562de6eae1d2d213d2f53cfb2edb4eef40c.
* maybe we could use a script instead that both build all
That both build all and sunnypilot-build-model reference
* refactor: consolidate model building steps into a single workflow
* tweak
* tweakx2
* tweakx3
* tweakx4
* dunno dunno...
* output dir
* lots of changes
* Revert "lots of changes"
This reverts commit 4aadb0ee2929fdf9d902335161b22072bef4e068.
* fail if all fail
* no inputs needed
* make it easier for us
* note failure and exit 0
* Update build-all-tinygrad-models.yaml
* not needed unless we really want it
* Update build-single-tinygrad-model.yaml
* Merge branch 'sync-20250627-tinygrad' of github.com:sunnypilot/sunnypilot into sync-20250627-tinygrad
* retry for failed ?
* always run this step because sometimes one build fails
which causes the matrix to fail, but most builds still have uploaded artifacts.
* strip
* no escape
* Update build-all-tinygrad-models.yaml
* Test case from terminal run
(openpilot) james@Mac sunnypilot % jq -c '[.bundles[] | select(.runner=="tinygrad") | {ref, display_name: (.display_name | gsub(" \\([^)]*\\)"; "")), is_20hz}]' \
/Users/james/Documents/GitHub/sunnypilot-docs/docs/driving_models_v6.json > matrix.json
mkdir -p output
touch "output/model-Tomb Raider 16v2 (July 21, 2025)-544"
touch "output/model-Space Lab Model (July 24, 2025)-547"
touch "output/model-Space Lab Model v1 (July 24, 2025)-548"
built=(); while IFS= read -r line; do built+=("$line"); done < <(
ls output | sed -E 's/^model-//' | sed -E 's/-[0-9]+$//' | sed -E 's/ \([^)]*\)//' | awk '{gsub(/^ +| +$/, ""); print}'
)
jq -c --argjson built "$(printf '%s\n' "${built[@]}" | jq -R . | jq -s .)" \
'map(select(.display_name as $n | ($built | index($n | gsub("^ +| +$"; "")) | not)))' \
matrix.json > retry_matrix.json
cat retry_matrix.json
[]
(openpilot) james@Mac sunnypilot %
* always
* great success
* add suffix to retry artifact so it doesn't conflict
* retry to get_model too
* and there haha
* unnecessary hyphen
* compare built to missing. include retries
* adjust copy of artifacts.
* Update build-all-tinygrad-models.yaml
* Update model selector versioning and add documentation
* Update retry condition for failed models in build-all-tinygrad-models.yaml
* Update retry condition for failed models in build-all-tinygrad-models.yaml
* Update build-single-tinygrad-model.yaml
* false
* default none because why not
* red diff? i think?
* meh ... not needed i guess
* error error error
* Nayan is watching... always watching mike wazowski
* string all the way
* lots of retries just in case because im scared
* more robust
* ONLY ONE!!!!!!
* delete.... a lot
* fix artifacts
* fix artifacts
* make sure each is unique :)
* skip files like artifact duhhhh
* artifact name dir
* concurrency
* copy here
* Update build-single-tinygrad-model.yaml
* Update build-single-tinygrad-model.yaml
* bump
* bump tinygrad
* max parallel? if not, i have the other remedy ready in build-all
* revert me!
* I resynced tinygrad woo hoo
* setup shouldnt fail
* pull
* big ole diff
* condition
* Update build-all-tinygrad-models.yaml
* not always() never always() never!!!
* not failure instead of great success
* Update build-all-tinygrad-models.yaml
* yay that worked. lets invoke build-single one last time
* these arent used and are just taking up 250MB space
* really frog?
* bump back to 3
* self-hosted, tici
* rename to trigger tests
* split sync
---------
Co-authored-by: DevTekVE <devtekve@gmail.com>
188 lines
6.6 KiB
Python
188 lines
6.6 KiB
Python
"""
|
|
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 hashlib
|
|
import os
|
|
import pickle
|
|
import numpy as np
|
|
import json
|
|
|
|
from openpilot.common.params import Params
|
|
from cereal import custom
|
|
from openpilot.sunnypilot.modeld.constants import Meta, MetaTombRaider, MetaSimPose
|
|
from openpilot.sunnypilot.modeld.runners import ModelRunner
|
|
from openpilot.system.hardware import PC
|
|
from openpilot.system.hardware.hw import Paths
|
|
from pathlib import Path
|
|
|
|
# see the README.md for more details on the model selector versioning
|
|
CURRENT_SELECTOR_VERSION = 8
|
|
REQUIRED_MIN_SELECTOR_VERSION = 6
|
|
|
|
USE_ONNX = os.getenv('USE_ONNX', PC)
|
|
|
|
CUSTOM_MODEL_PATH = Paths.model_root()
|
|
METADATA_PATH = Path(__file__).parent / '../models/supercombo_metadata.pkl'
|
|
|
|
ModelManager = custom.ModelManagerSP
|
|
|
|
|
|
async def verify_file(file_path: str, expected_hash: str) -> bool:
|
|
"""Verifies file hash against expected hash"""
|
|
if not os.path.exists(file_path):
|
|
return False
|
|
|
|
sha256_hash = hashlib.sha256()
|
|
with open(file_path, "rb") as file:
|
|
for chunk in iter(lambda: file.read(4096), b""):
|
|
sha256_hash.update(chunk)
|
|
|
|
return sha256_hash.hexdigest().lower() == expected_hash.lower()
|
|
|
|
|
|
def is_bundle_version_compatible(bundle: dict) -> bool:
|
|
"""
|
|
Checks whether the model bundle is compatible with the current selector version constraints.
|
|
|
|
The bundle specifies a `minimum_selector_version`, which defines the minimum selector version
|
|
required to load the model. This function ensures that:
|
|
|
|
1. The model is not too old: the bundle must require at least `REQUIRED_MIN_SELECTOR_VERSION`.
|
|
2. The model is not too new: it must support the current selector version (`CURRENT_SELECTOR_VERSION`).
|
|
|
|
This allows the selector to enforce both a minimum and maximum range of supported models,
|
|
even if a model would otherwise be compatible.
|
|
|
|
:param bundle: Dictionary containing `minimum_selector_version`, as defined by the model bundle.
|
|
:type bundle: Dict
|
|
:return: True if the selector version is within the accepted range for the bundle; otherwise False.
|
|
:rtype: Bool
|
|
"""
|
|
return bool(REQUIRED_MIN_SELECTOR_VERSION <= bundle.get("minimumSelectorVersion", 0) <= CURRENT_SELECTOR_VERSION)
|
|
|
|
def get_active_bundle(params: Params = None) -> custom.ModelManagerSP.ModelBundle:
|
|
"""Gets the active model bundle from cache"""
|
|
if params is None:
|
|
params = Params()
|
|
|
|
try:
|
|
if (active_bundle := json.loads(params.get("ModelManager_ActiveBundle") or "{}")) and is_bundle_version_compatible(active_bundle):
|
|
return custom.ModelManagerSP.ModelBundle(**active_bundle)
|
|
except Exception:
|
|
pass
|
|
|
|
return None
|
|
|
|
|
|
def get_active_model_runner(params: Params = None, force_check=False) -> custom.ModelManagerSP.Runner:
|
|
"""
|
|
Determines and returns the active model runner type, based on provided parameters.
|
|
The function utilizes caching to prevent redundant calculations and checks.
|
|
|
|
If the cached "ModelRunnerTypeCache" exists in the provided parameters and `force_check`
|
|
is set to False, the cached value is directly returned. Otherwise, the function determines
|
|
the runner type based on the active model bundle. If a model bundle containing a drive
|
|
model exists, the runner type is derived based on the filename of the drive model.
|
|
Finally, it updates the cache with the determined runner type, if needed.
|
|
|
|
:param params: The parameter set used to retrieve caching and runner details. If `None`,
|
|
a default `Params` instance is created internally.
|
|
:type params: Params
|
|
:param force_check: A flag indicating whether to bypass cached results and always
|
|
re-determine the runner type. Defaults to `False`.
|
|
:type force_check: bool
|
|
:return: The determined or cached model runner type.
|
|
:rtype: custom.ModelManagerSP.Runner
|
|
"""
|
|
if params is None:
|
|
params = Params()
|
|
|
|
if (cached_runner_type := params.get("ModelRunnerTypeCache")) and not force_check:
|
|
if isinstance(cached_runner_type, str) and cached_runner_type.isdigit():
|
|
return int(cached_runner_type)
|
|
|
|
runner_type = custom.ModelManagerSP.Runner.stock
|
|
|
|
if active_bundle := get_active_bundle(params):
|
|
runner_type = active_bundle.runner.raw
|
|
|
|
if cached_runner_type != runner_type:
|
|
params.put("ModelRunnerTypeCache", str(int(runner_type)))
|
|
|
|
return runner_type
|
|
|
|
def _get_model():
|
|
if bundle := get_active_bundle():
|
|
drive_model = next(model for model in bundle.models if model.type == ModelManager.Model.Type.supercombo)
|
|
return drive_model
|
|
|
|
return None
|
|
|
|
def get_model_path():
|
|
if USE_ONNX:
|
|
return {ModelRunner.ONNX: Path(__file__).parent / '../models/supercombo.onnx'}
|
|
|
|
if model := _get_model():
|
|
return {ModelRunner.THNEED: f"{CUSTOM_MODEL_PATH}/{model.artifact.fileName}"}
|
|
|
|
return {ModelRunner.THNEED: Path(__file__).parent / '../models/supercombo.thneed'}
|
|
|
|
|
|
def load_metadata():
|
|
metadata_path = METADATA_PATH
|
|
|
|
if model := _get_model():
|
|
metadata_path = f"{CUSTOM_MODEL_PATH}/{model.metadata.fileName}"
|
|
|
|
with open(metadata_path, 'rb') as f:
|
|
return pickle.load(f)
|
|
|
|
|
|
def prepare_inputs(model_metadata) -> dict[str, np.ndarray]:
|
|
# img buffers are managed in openCL transform code so we don't pass them as inputs
|
|
inputs = {
|
|
k: np.zeros(v, dtype=np.float32).flatten()
|
|
for k, v in model_metadata['input_shapes'].items()
|
|
if 'img' not in k
|
|
}
|
|
|
|
return inputs
|
|
|
|
|
|
def load_meta_constants(model_metadata):
|
|
"""
|
|
Determines and loads the appropriate meta model class based on the metadata provided. The function checks
|
|
specific keys and conditions within the provided metadata dictionary to identify the corresponding meta
|
|
model class to return.
|
|
|
|
:param model_metadata: Dictionary containing metadata about the model. It includes
|
|
details such as input shapes, output slices, and other configurations for identifying
|
|
metadata-dependent meta model classes.
|
|
:type model_metadata: dict
|
|
:return: The appropriate meta model class (Meta, MetaSimPose, or MetaTombRaider)
|
|
based on the conditions and metadata provided.
|
|
:rtype: type
|
|
"""
|
|
meta = Meta # Default Meta
|
|
|
|
if 'sim_pose' in model_metadata['input_shapes'].keys():
|
|
# Meta for models with sim_pose input
|
|
meta = MetaSimPose
|
|
else:
|
|
# Meta for Tomb Raider, it does not include sim_pose input but has the same meta slice as previous models
|
|
meta_slice = model_metadata['output_slices']['meta']
|
|
meta_tf_slice = slice(5868, 5921, None)
|
|
|
|
if (
|
|
meta_slice.start == meta_tf_slice.start and
|
|
meta_slice.stop == meta_tf_slice.stop and
|
|
meta_slice.step == meta_tf_slice.step
|
|
):
|
|
meta = MetaTombRaider
|
|
|
|
return meta
|