IQ.Pilot Release Commit @ d23c019

This commit is contained in:
IQ.Lvbs CI [bot]
2026-07-26 18:52:41 -05:00
parent e557c3d8ee
commit 152206f935
262 changed files with 12479 additions and 11377 deletions

View File

@@ -60,7 +60,7 @@ def host_tinygrad_flags(*, float16=False):
return f"{base} FLOAT16=1" if float16 else base
# Compile small models
for model_name in ['dmonitoring_model']:
for model_name in ['dmonitoring_model', 'dmonitoring_model_mici']:
# The optimization flags are mandatory on QCOM: without FLOAT16/NOLOCALS/JIT_BATCH_SIZE/OPENPILOT_HACKS these
# models compile to unoptimized QCOM kernels and run ~20x slower (dmonitoring_model: ~300ms -> ~14ms),
# which starves the driving model on the shared Adreno. IMAGE=2 (not upstream's IMAGE=1) because the

View File

@@ -20,19 +20,25 @@ from openpilot.selfdrive.locationd.calibration_helpers import get_calibrated_rpy
from openpilot.selfdrive.modeld.models.commonmodel_pyx import CLContext, MonitoringModelFrame
from openpilot.selfdrive.modeld.parse_model_outputs import sigmoid, safe_exp
from openpilot.selfdrive.modeld.runners.tinygrad_helpers import qcom_tensor_from_opencl_address
from openpilot.system.hardware import HARDWARE
PROCESS_NAME = "selfdrive.modeld.dmonitoringmodeld"
SEND_RAW_PRED = os.getenv('SEND_RAW_PRED')
MODEL_PKL_PATH = Path(__file__).parent / 'models/dmonitoring_model_tinygrad.pkl'
METADATA_PATH = Path(__file__).parent / 'models/dmonitoring_model_metadata.pkl'
MODELS_PATH = Path(__file__).parent / 'models'
def get_model_paths(device_type: str) -> tuple[Path, Path]:
model_name = 'dmonitoring_model_mici' if device_type == 'mici' else 'dmonitoring_model'
return MODELS_PATH / f'{model_name}_tinygrad.pkl', MODELS_PATH / f'{model_name}_metadata.pkl'
class ModelState:
inputs: dict[str, np.ndarray]
output: np.ndarray
def __init__(self, cl_ctx):
with open(METADATA_PATH, 'rb') as f:
def __init__(self, cl_ctx, device_type=None):
model_path, metadata_path = get_model_paths(device_type or HARDWARE.get_device_type())
with open(metadata_path, 'rb') as f:
model_metadata = pickle.load(f)
self.input_shapes = model_metadata['input_shapes']
self.output_slices = model_metadata['output_slices']
@@ -43,7 +49,7 @@ class ModelState:
}
self.tensor_inputs = {k: Tensor(v, device='NPY').realize() for k,v in self.numpy_inputs.items()}
with open(MODEL_PKL_PATH, "rb") as f:
with open(model_path, "rb") as f:
self.model_run = pickle.load(f)
def run(self, buf: VisionBuf, calib: np.ndarray, transform: np.ndarray) -> tuple[np.ndarray, float]:
@@ -75,8 +81,10 @@ def parse_model_output(model_output):
face_descs = model_output[f'face_descs_{ds_suffix}']
parsed[f'face_descs_{ds_suffix}'] = face_descs[:, :-6]
parsed[f'face_descs_{ds_suffix}_std'] = safe_exp(face_descs[:, -6:])
for key in ['face_prob', 'left_eye_prob', 'right_eye_prob','left_blink_prob', 'right_blink_prob', 'sunglasses_prob', 'using_phone_prob']:
parsed[f'{key}_{ds_suffix}'] = sigmoid(model_output[f'{key}_{ds_suffix}'])
for key in ['face_prob', 'left_eye_prob', 'right_eye_prob','left_blink_prob', 'right_blink_prob', 'sunglasses_prob', 'using_phone_prob', 'sleep_prob']:
output_key = f'{key}_{ds_suffix}'
if output_key in model_output:
parsed[output_key] = sigmoid(model_output[output_key])
return parsed
def fill_driver_data(msg, model_output, ds_suffix):
@@ -91,6 +99,8 @@ def fill_driver_data(msg, model_output, ds_suffix):
msg.rightBlinkProb = model_output[f'right_blink_prob_{ds_suffix}'][0, 0].item()
msg.sunglassesProb = model_output[f'sunglasses_prob_{ds_suffix}'][0, 0].item()
msg.phoneProb = model_output[f'using_phone_prob_{ds_suffix}'][0, 0].item()
sleep_prob = model_output.get(f'sleep_prob_{ds_suffix}')
msg.sleepProb = sleep_prob[0, 0].item() if sleep_prob is not None else 0.
def get_driverstate_packet(model_output, frame_id: int, location_ts: int, exec_time: float, gpu_exec_time: float):
msg = messaging.new_message('driverStateV2', valid=True)

Binary file not shown.

View File

@@ -1,8 +1,15 @@
{
"dmonitoring_model": {
"outputs": {
"dmonitoring_model_metadata.pkl": "31a86ab7a92dc0af088b15787a440dd3b210aa662e445a15145900e559a1b5c3",
"dmonitoring_model_tinygrad.pkl": "806c0ea75df6bf6dfeb81b832314c68e31df5865a52d0359e6eeb76d93ad2b52"
"dmonitoring_model_metadata.pkl": "5999c262b1c25c62e485fb4ced5806d20a8ca59e3ae94e0ff499c0fe3497fedc",
"dmonitoring_model_tinygrad.pkl": "5aca89a35b42376d56f67ccd28a1080806706d546dd8c63f6e1b4c681f8e2c01"
},
"signature": "2364ebd4bb95c4b4e539c9b1ba68324b713cbb56617396b73262accf9cdcfbfc"
},
"dmonitoring_model_mici": {
"outputs": {
"dmonitoring_model_mici_metadata.pkl": "31a86ab7a92dc0af088b15787a440dd3b210aa662e445a15145900e559a1b5c3",
"dmonitoring_model_mici_tinygrad.pkl": "806c0ea75df6bf6dfeb81b832314c68e31df5865a52d0359e6eeb76d93ad2b52"
},
"signature": "e1eeb5ce45774a816c8da2394e6ee35ebf700b71dff345e0141dbab8ff592349"
}

View File

@@ -11,7 +11,7 @@ BASEDIR = MODELD_DIR.parents[1]
TINYGRAD_DIR = BASEDIR / 'tinygrad_repo'
METADATA_SCRIPT = MODELD_DIR / 'get_model_metadata.py'
MODEL_NAMES = ['dmonitoring_model']
MODEL_NAMES = ['dmonitoring_model', 'dmonitoring_model_mici']
def _hash_file(h, path: Path) -> None:

View File

@@ -0,0 +1,37 @@
import pickle
import numpy as np
import pytest
from openpilot.selfdrive.modeld.dmonitoringmodeld import get_driverstate_packet, get_model_paths, parse_model_output, slice_outputs
@pytest.mark.parametrize("device_type, model_name", [
("mici", "dmonitoring_model_mici"),
("tici", "dmonitoring_model"),
("tizi", "dmonitoring_model"),
])
def test_model_paths(device_type, model_name):
model_path, metadata_path = get_model_paths(device_type)
assert model_path.name == f"{model_name}_tinygrad.pkl"
assert metadata_path.name == f"{model_name}_metadata.pkl"
@pytest.mark.parametrize("device_type, expected_sleep_prob", [
("mici", 0.),
("tici", 0.5),
("tizi", 0.5),
])
def test_sleep_probability_output(device_type, expected_sleep_prob):
_, metadata_path = get_model_paths(device_type)
with open(metadata_path, 'rb') as f:
metadata = pickle.load(f)
output = np.zeros(metadata['output_shapes']['outputs'][1], dtype=np.float32)
parsed = parse_model_output(slice_outputs(output, metadata['output_slices']))
parsed['raw_pred'] = b''
msg = get_driverstate_packet(parsed, 1, 0, 0., 0.)
assert msg.driverStateV2.leftDriverData.sleepProb == expected_sleep_prob
assert msg.driverStateV2.rightDriverData.sleepProb == expected_sleep_prob

View File

@@ -1,51 +1,52 @@
import hashlib
import json
import pytest
from openpilot.selfdrive.modeld import prebuilt_models
def write_outputs(models_dir, check_path):
outputs = {}
for name, contents in {
'dmonitoring_model_tinygrad.pkl': b'tinygrad',
'dmonitoring_model_metadata.pkl': b'metadata',
}.items():
(models_dir / name).write_bytes(contents)
outputs[name] = hashlib.sha256(contents).hexdigest()
check_path.write_text(json.dumps({'dmonitoring_model': {'outputs': outputs}}))
def write_outputs(models_dir, check_path, model_names):
checks = {}
for model_name in model_names:
outputs = {}
for suffix, contents in {
'tinygrad.pkl': b'tinygrad',
'metadata.pkl': b'metadata',
}.items():
name = f'{model_name}_{suffix}'
(models_dir / name).write_bytes(contents)
outputs[name] = hashlib.sha256(contents).hexdigest()
checks[model_name] = {'outputs': outputs}
check_path.write_text(json.dumps(checks))
def test_packaged_prebuilt_without_onnx(tmp_path, monkeypatch):
@pytest.fixture
def packaged_models(tmp_path, monkeypatch):
models_dir = tmp_path / 'models'
models_dir.mkdir()
check_path = models_dir / 'prebuilt_check.json'
write_outputs(models_dir, check_path)
write_outputs(models_dir, check_path, prebuilt_models.MODEL_NAMES)
monkeypatch.setattr(prebuilt_models, 'MODELS_DIR', models_dir)
monkeypatch.setattr(prebuilt_models, 'CHECK_PATH', check_path)
assert prebuilt_models.packaged_prebuilt_matches('dmonitoring_model')
assert not prebuilt_models.verify_prebuilt('dmonitoring_model', 'flags')
return models_dir
def test_packaged_prebuilt_rejects_corrupt_output(tmp_path, monkeypatch):
models_dir = tmp_path / 'models'
models_dir.mkdir()
check_path = models_dir / 'prebuilt_check.json'
write_outputs(models_dir, check_path)
(models_dir / 'dmonitoring_model_tinygrad.pkl').write_bytes(b'corrupt')
monkeypatch.setattr(prebuilt_models, 'MODELS_DIR', models_dir)
monkeypatch.setattr(prebuilt_models, 'CHECK_PATH', check_path)
assert not prebuilt_models.packaged_prebuilt_matches('dmonitoring_model')
@pytest.mark.parametrize("model_name", prebuilt_models.MODEL_NAMES)
def test_packaged_prebuilt_without_onnx(packaged_models, model_name):
assert prebuilt_models.packaged_prebuilt_matches(model_name)
assert not prebuilt_models.verify_prebuilt(model_name, 'flags')
def test_source_checkout_is_not_packaged_prebuilt(tmp_path, monkeypatch):
models_dir = tmp_path / 'models'
models_dir.mkdir()
check_path = models_dir / 'prebuilt_check.json'
write_outputs(models_dir, check_path)
(models_dir / 'dmonitoring_model.onnx').write_bytes(b'onnx')
monkeypatch.setattr(prebuilt_models, 'MODELS_DIR', models_dir)
monkeypatch.setattr(prebuilt_models, 'CHECK_PATH', check_path)
@pytest.mark.parametrize("model_name", prebuilt_models.MODEL_NAMES)
def test_packaged_prebuilt_rejects_corrupt_output(packaged_models, model_name):
(packaged_models / f'{model_name}_tinygrad.pkl').write_bytes(b'corrupt')
assert not prebuilt_models.packaged_prebuilt_matches('dmonitoring_model')
assert not prebuilt_models.packaged_prebuilt_matches(model_name)
@pytest.mark.parametrize("model_name", prebuilt_models.MODEL_NAMES)
def test_source_checkout_is_not_packaged_prebuilt(packaged_models, model_name):
(packaged_models / f'{model_name}.onnx').write_bytes(b'onnx')
assert not prebuilt_models.packaged_prebuilt_matches(model_name)