mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-10-19 03:13:42 +08:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d811c8ddde | |||
| e693544fd7 | |||
| f9c876ca2d | |||
| 046a3ead4e |
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
CHESTNUT_FW_VERSION = "ed4e39b7"
|
||||
CHESTNUT_FW_VERSION = "8516b768"
|
||||
CHESTNUT_USB_IDS = ((0xADD1, 0x0001), (0x3801, 0x0001))
|
||||
CHESTNUT_ROM_USB_IDS = ((0x174C, 0x2464), (0x174C, 0x2463))
|
||||
CHESTNUT_USB_PRODUCT = f"custom {CHESTNUT_FW_VERSION}-CLEAN"
|
||||
@@ -36,6 +36,10 @@ def read_int(path: Path, base: int = 10) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
def cable_connected() -> bool:
|
||||
return read_int(TYPEC_CC_ORIENTATION_PATH) != 0
|
||||
|
||||
|
||||
def usb_devices() -> list[Path]:
|
||||
try:
|
||||
devices = (d for d in USB_DEVICES_PATH.glob("*") if (d / "idVendor").exists())
|
||||
|
||||
@@ -3,6 +3,7 @@ import os
|
||||
import pickle
|
||||
import struct
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from openpilot.common.file_chunker import get_chunk_name, get_manifest_path, open_file_chunked
|
||||
@@ -41,6 +42,14 @@ def chestnut_present() -> bool:
|
||||
pass
|
||||
return False
|
||||
|
||||
def wait_for_chestnut(timeout: float = 10.) -> None:
|
||||
# the cable is detected before chestnut enumerates
|
||||
st = time.monotonic()
|
||||
while not chestnut_present():
|
||||
if time.monotonic() - st > timeout:
|
||||
raise TimeoutError("chestnut did not enumerate")
|
||||
time.sleep(0.1)
|
||||
|
||||
def chestnut_compiled() -> bool:
|
||||
path = modeld_pkl_path(chestnut=True)
|
||||
return (path.is_file() or Path(get_manifest_path(path)).is_file()) and all(
|
||||
|
||||
@@ -10,6 +10,7 @@ import builtins
|
||||
import contextlib
|
||||
import dataclasses
|
||||
import functools
|
||||
import gc
|
||||
import hashlib
|
||||
import io
|
||||
import itertools
|
||||
@@ -111,17 +112,21 @@ def read_parts(path: str) -> tuple[dict, dict]:
|
||||
return parts, _MetadataUnpickler(io.BytesIO(bytes(blob[slice(*header["extras"])]))).load()
|
||||
|
||||
|
||||
def _extended(path: str, extend) -> tuple[dict, dict, str]:
|
||||
def _extended(path: str, extend) -> tuple[dict, dict, str, dict]:
|
||||
parts, extras = read_parts(path)
|
||||
added = extend(parts, extras) if extend else {}
|
||||
return parts | added, extras, _parts_digest(added) if added else ""
|
||||
return parts | added, extras, _parts_digest(added) if added else "", {key: parts[key] for key in added if key in parts}
|
||||
|
||||
|
||||
def load_model(path: str, device_map: dict | None = None, verify: bool = True, cache: bool = True, extend=None) -> dict:
|
||||
parts, extras, extra = _extended(path, extend)
|
||||
parts, extras, extra, replaced = _extended(path, extend)
|
||||
if cache and (cached := _read_cache(path, parts, device_map, extra)) is not None:
|
||||
return extras | cached
|
||||
shared: dict = {}
|
||||
if verify and replaced:
|
||||
for header, blob in replaced.values():
|
||||
PlainJit(header, blob, device_map, verify, shared)
|
||||
gc.collect()
|
||||
jits = {key: PlainJit(header, blob, device_map, verify, shared) for key, (header, blob) in parts.items()}
|
||||
if cache:
|
||||
_write_cache(path, jits, device_map, extra)
|
||||
|
||||
@@ -7,8 +7,10 @@ See the LICENSE.md file in the root directory for more details.
|
||||
"""
|
||||
|
||||
from collections.abc import Callable
|
||||
import gc
|
||||
import os
|
||||
os.environ['GMMU'] = '0'
|
||||
from tinygrad.device import Device
|
||||
import numpy as np
|
||||
import threading
|
||||
import time
|
||||
@@ -16,7 +18,7 @@ from setproctitle import setproctitle
|
||||
|
||||
import openpilot.cereal.messaging as messaging
|
||||
from openpilot.common.hardware import COMMA_HARDWARE
|
||||
from openpilot.selfdrive.modeld.helpers import chestnut_present
|
||||
from openpilot.selfdrive.modeld.helpers import chestnut_present, wait_for_chestnut
|
||||
from openpilot.cereal import log
|
||||
from opendbc.car.structs import car
|
||||
from openpilot.cereal.services import SERVICE_LIST
|
||||
@@ -26,6 +28,7 @@ from msgq.visionipc import VisionIpcClient, VisionBuf
|
||||
from opendbc.car.car_helpers import get_demo_car_params
|
||||
from openpilot.common.swaglog import cloudlog
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.common.hardware.usb import cable_connected
|
||||
from openpilot.common.filter_simple import FirstOrderFilter
|
||||
from openpilot.common.realtime import config_realtime_process, DT_MDL
|
||||
from openpilot.common.transformations.camera import DEVICE_CAMERAS
|
||||
@@ -179,6 +182,8 @@ class ModelState(ModelStateBase):
|
||||
self.numpy_inputs['big_tfm'][:, :] = transforms[self._wide_key].reshape(3, 3)
|
||||
|
||||
raw_outputs = self.adapter.run()
|
||||
if self.chestnut and (err := Device[self.DEV].error_state.host.view(fmt='q')[0]):
|
||||
raise RuntimeError(f"chestnut failed with {err}")
|
||||
|
||||
if after_enqueue is not None:
|
||||
after_enqueue()
|
||||
@@ -253,9 +258,8 @@ def main(demo=False):
|
||||
|
||||
cloudlog.bind(daemon=PROCESS_NAME)
|
||||
setproctitle(PROCESS_NAME)
|
||||
config_realtime_process(7, 54)
|
||||
|
||||
CHESTNUT = chestnut_present()
|
||||
CHESTNUT = _find_driving_pkl(get_active_bundle(chestnut=True)) is not None and (chestnut_present() or cable_connected())
|
||||
if CHESTNUT:
|
||||
from tinygrad.runtime.ops_amd import AMDDevice
|
||||
AMDDevice.wait_timeout_ms = 3000
|
||||
@@ -264,6 +268,8 @@ def main(demo=False):
|
||||
params.put_bool("ChestnutLoading", CHESTNUT)
|
||||
params.remove("ChestnutActive")
|
||||
|
||||
gc.disable()
|
||||
|
||||
# visionipc clients
|
||||
while True:
|
||||
available_streams = VisionIpcClient.available_streams("camerad", block=False)
|
||||
@@ -296,6 +302,7 @@ def main(demo=False):
|
||||
def load_big():
|
||||
nonlocal big_model
|
||||
try:
|
||||
wait_for_chestnut()
|
||||
m = ModelState(cam_w=vipc_client_main.width, cam_h=vipc_client_main.height, chestnut=True)
|
||||
m.warmup()
|
||||
big_model = m
|
||||
@@ -305,7 +312,13 @@ def main(demo=False):
|
||||
loader.start()
|
||||
loader.join(BIG_MODEL_TIMEOUT)
|
||||
model = big_model
|
||||
params.put_bool("ChestnutActive", model is not None)
|
||||
if model is None and not params.get_bool("ChestnutRetry"):
|
||||
# a crank can cut the chestnut power during the load, retry once with an onroad cycle
|
||||
cloudlog.error("big model load failed, cycling onroad to retry")
|
||||
params.put_bool("ChestnutRetry", True)
|
||||
params.put_bool("OnroadCycleRequested", True)
|
||||
else:
|
||||
params.put_bool("ChestnutActive", model is not None)
|
||||
|
||||
small_model = ModelState(cam_w=vipc_client_main.width, cam_h=vipc_client_main.height, chestnut=False) if model is None or CHESTNUT else None
|
||||
if model is None:
|
||||
@@ -314,10 +327,13 @@ def main(demo=False):
|
||||
assert model is not None
|
||||
cloudlog.warning(f"models loaded in {time.monotonic() - st:.1f}s, modeld starting")
|
||||
|
||||
config_realtime_process(7, 54)
|
||||
|
||||
# messaging
|
||||
pub_socks = ["modelV2", "drivingModelData", "cameraOdometry", "modelDataV2SP"] + (["chestnutGpuState"] if CHESTNUT else [])
|
||||
pm = PubMaster(pub_socks)
|
||||
sm = SubMaster(["deviceState", "carState", "narrowRoadCameraState", "extrinsicsCalibration", "driverMonitoringState", "carControl", "lateralDelay"])
|
||||
sm = SubMaster(["deviceState", "carState", "narrowRoadCameraState", "extrinsicsCalibration", "driverMonitoringState",
|
||||
"carControl", "controlsState", "lateralDelay"])
|
||||
|
||||
publish_state = PublishState()
|
||||
chestnut_state = ChestnutGpuState(pm, model.chestnut) if CHESTNUT else None
|
||||
@@ -445,7 +461,7 @@ def main(demo=False):
|
||||
run_count % round(model.constants.MODEL_FREQ / SERVICE_LIST['chestnutGpuState'].frequency) == 0)
|
||||
model_output = model.run(bufs, transforms, inputs, chestnut_state.send if send_chestnut else None)
|
||||
except Exception:
|
||||
if not params.get_bool("ChestnutActive"):
|
||||
if not model.chestnut:
|
||||
raise
|
||||
cloudlog.exception("big model failed, fall back to small")
|
||||
params.put_bool("ChestnutActive", False)
|
||||
@@ -464,6 +480,8 @@ def main(demo=False):
|
||||
posenet_send = messaging.new_message('cameraOdometry')
|
||||
mdv2sp_send = messaging.new_message('modelDataV2SP')
|
||||
|
||||
if not sm['carControl'].latActive:
|
||||
prev_action.desiredCurvature = sm['controlsState'].curvature
|
||||
action = model.get_action_from_model(model_output, prev_action, lat_action_t, long_action_t, v_ego)
|
||||
prev_action = action
|
||||
fill_model_msg(drivingdata_send, modelv2_send, model_output, action,
|
||||
|
||||
Reference in New Issue
Block a user