mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-09-02 01:53:45 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 51987a62d0 | |||
| 98ed8111f6 |
@@ -121,7 +121,7 @@ jobs:
|
|||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
build_model:
|
build_model:
|
||||||
runs-on: [self-hosted, chestnut]
|
runs-on: [self-hosted, "${{ inputs.target_hardware == 'chestnut' && 'chestnut' || 'tici' }}"]
|
||||||
needs: get_model
|
needs: get_model
|
||||||
env:
|
env:
|
||||||
MODEL_NAME: ${{ inputs.custom_name || inputs.upstream_branch }} (${{ needs.get_model.outputs.model_date }})
|
MODEL_NAME: ${{ inputs.custom_name || inputs.upstream_branch }} (${{ needs.get_model.outputs.model_date }})
|
||||||
|
|||||||
@@ -132,7 +132,6 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
{"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||||
{"ChestnutActive", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION | CLEAR_ON_IGNITION_ON, BOOL}},
|
{"ChestnutActive", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION | CLEAR_ON_IGNITION_ON, BOOL}},
|
||||||
{"ChestnutLoading", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION | CLEAR_ON_IGNITION_ON, BOOL}},
|
{"ChestnutLoading", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION | CLEAR_ON_IGNITION_ON, BOOL}},
|
||||||
{"AuxPowerSave", {PERSISTENT | BACKUP, BOOL}},
|
|
||||||
{"Version", {PERSISTENT, STRING}},
|
{"Version", {PERSISTENT, STRING}},
|
||||||
|
|
||||||
// --- sunnypilot params --- //
|
// --- sunnypilot params --- //
|
||||||
|
|||||||
@@ -220,7 +220,6 @@ class UIState(UIStateSP):
|
|||||||
ChestnutState.UNCOMPILED if detected else ChestnutState.DISCONNECTED)
|
ChestnutState.UNCOMPILED if detected else ChestnutState.DISCONNECTED)
|
||||||
return
|
return
|
||||||
|
|
||||||
self.chestnut_present = self.chestnut_present or detected
|
|
||||||
model_seen = self.sm.recv_frame["modelV2"] > self.started_frame
|
model_seen = self.sm.recv_frame["modelV2"] > self.started_frame
|
||||||
if not self.chestnut_present:
|
if not self.chestnut_present:
|
||||||
self.chestnut_state = ChestnutState.DISCONNECTED
|
self.chestnut_state = ChestnutState.DISCONNECTED
|
||||||
|
|||||||
@@ -8,22 +8,22 @@ See the LICENSE.md file in the root directory for more details.
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
os.environ['GMMU'] = '0'
|
os.environ['GMMU'] = '0'
|
||||||
|
import numpy as np
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
from setproctitle import setproctitle
|
||||||
|
from tinygrad.tensor import Tensor
|
||||||
|
|
||||||
|
import openpilot.cereal.messaging as messaging
|
||||||
from openpilot.common.hardware import COMMA_HARDWARE
|
from openpilot.common.hardware import COMMA_HARDWARE
|
||||||
from openpilot.selfdrive.modeld.helpers import chestnut_present, load_oob
|
from openpilot.selfdrive.modeld.helpers import chestnut_present, load_oob
|
||||||
import time
|
|
||||||
import numpy as np
|
|
||||||
import openpilot.cereal.messaging as messaging
|
|
||||||
from openpilot.cereal import log
|
from openpilot.cereal import log
|
||||||
from opendbc.car.structs import car
|
from opendbc.car.structs import car
|
||||||
from openpilot.cereal.services import SERVICE_LIST
|
from openpilot.cereal.services import SERVICE_LIST
|
||||||
from setproctitle import setproctitle
|
|
||||||
from openpilot.cereal.messaging import PubMaster, SubMaster
|
from openpilot.cereal.messaging import PubMaster, SubMaster
|
||||||
from openpilot.cereal.visionipc import VisionStreamType
|
from openpilot.cereal.visionipc import VisionStreamType
|
||||||
from msgq.visionipc import VisionIpcClient, VisionBuf
|
from msgq.visionipc import VisionIpcClient, VisionBuf
|
||||||
from opendbc.car.car_helpers import get_demo_car_params
|
from opendbc.car.car_helpers import get_demo_car_params
|
||||||
|
|
||||||
from tinygrad.tensor import Tensor
|
|
||||||
|
|
||||||
from openpilot.common.file_chunker import open_file_chunked
|
from openpilot.common.file_chunker import open_file_chunked
|
||||||
from openpilot.common.swaglog import cloudlog
|
from openpilot.common.swaglog import cloudlog
|
||||||
from openpilot.common.params import Params
|
from openpilot.common.params import Params
|
||||||
@@ -42,13 +42,13 @@ from openpilot.sunnypilot.modeld_v2.constants import Plan
|
|||||||
from openpilot.sunnypilot.modeld_v2.meta_helper import load_meta_constants
|
from openpilot.sunnypilot.modeld_v2.meta_helper import load_meta_constants
|
||||||
from openpilot.sunnypilot.modeld_v2.camera_offset_helper import CameraOffsetHelper
|
from openpilot.sunnypilot.modeld_v2.camera_offset_helper import CameraOffsetHelper
|
||||||
from openpilot.sunnypilot.modeld_v2.compile_modeld import derive_frame_skip, make_split_input_queues, make_supercombo_input_queues, WARP_INPUTS, POLICY_INPUTS
|
from openpilot.sunnypilot.modeld_v2.compile_modeld import derive_frame_skip, make_split_input_queues, make_supercombo_input_queues, WARP_INPUTS, POLICY_INPUTS
|
||||||
|
|
||||||
from openpilot.sunnypilot.livedelay.helpers import get_lat_delay
|
from openpilot.sunnypilot.livedelay.helpers import get_lat_delay
|
||||||
from openpilot.sunnypilot.modeld_v2.modeld_base import ModelStateBase
|
from openpilot.sunnypilot.modeld_v2.modeld_base import ModelStateBase
|
||||||
from openpilot.sunnypilot.models.helpers import get_active_bundle
|
from openpilot.sunnypilot.models.helpers import get_active_bundle
|
||||||
from openpilot.sunnypilot.selfdrive.controls.lib.relc import RoadEdgeLaneChangeController
|
from openpilot.sunnypilot.selfdrive.controls.lib.relc import RoadEdgeLaneChangeController
|
||||||
|
|
||||||
PROCESS_NAME = "openpilot.selfdrive.modeld.modeld_tinygrad"
|
PROCESS_NAME = "openpilot.selfdrive.modeld.modeld_tinygrad"
|
||||||
|
BIG_MODEL_TIMEOUT = 60
|
||||||
|
|
||||||
|
|
||||||
def _pkl_exists(path):
|
def _pkl_exists(path):
|
||||||
@@ -68,6 +68,7 @@ def _find_driving_pkl(bundle):
|
|||||||
pkl_path = os.path.join(model_root, pkl_name)
|
pkl_path = os.path.join(model_root, pkl_name)
|
||||||
if _pkl_exists(pkl_path):
|
if _pkl_exists(pkl_path):
|
||||||
return pkl_path
|
return pkl_path
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class FrameMeta:
|
class FrameMeta:
|
||||||
@@ -102,7 +103,7 @@ class ModelState(ModelStateBase):
|
|||||||
self.chestnut = chestnut
|
self.chestnut = chestnut
|
||||||
|
|
||||||
pkl_path = _find_driving_pkl(model_bundle)
|
pkl_path = _find_driving_pkl(model_bundle)
|
||||||
assert pkl_path is not None, "No driving pkl found — all models must be compiled with compile_modeld.py"
|
assert pkl_path is not None, f"No driving pkl found for {'chestnut' if chestnut else 'small model'} — all models must be compiled with compile_modeld.py"
|
||||||
self._init_combined(pkl_path, cam_w, cam_h, model_bundle)
|
self._init_combined(pkl_path, cam_w, cam_h, model_bundle)
|
||||||
|
|
||||||
def _init_combined(self, pkl_path, cam_w, cam_h, bundle):
|
def _init_combined(self, pkl_path, cam_w, cam_h, bundle):
|
||||||
@@ -185,9 +186,6 @@ class ModelState(ModelStateBase):
|
|||||||
else:
|
else:
|
||||||
self.warp(**{k: self.input_queues[k] for k in WARP_INPUTS}, frame=frame_tensor, big_frame=big_frame_tensor)
|
self.warp(**{k: self.input_queues[k] for k in WARP_INPUTS}, frame=frame_tensor, big_frame=big_frame_tensor)
|
||||||
|
|
||||||
if self.chestnut:
|
|
||||||
self.warmup()
|
|
||||||
|
|
||||||
def warmup(self) -> None:
|
def warmup(self) -> None:
|
||||||
dummy_frames = {k: np.zeros(self.frame_buf_params[k][3], dtype=np.uint8) for k in self._vision_input_names}
|
dummy_frames = {k: np.zeros(self.frame_buf_params[k][3], dtype=np.uint8) for k in self._vision_input_names}
|
||||||
transforms = {k: np.eye(3, dtype=np.float32) for k in [self._road_key, self._wide_key] if k}
|
transforms = {k: np.eye(3, dtype=np.float32) for k in [self._road_key, self._wide_key] if k}
|
||||||
@@ -288,8 +286,7 @@ class ModelState(ModelStateBase):
|
|||||||
buf[0, -1, :] = outputs['desired_curvature'][0, :] if not self.mlsim else 0
|
buf[0, -1, :] = outputs['desired_curvature'][0, :] if not self.mlsim else 0
|
||||||
|
|
||||||
if self.chestnut and not np.all(np.isfinite(outputs.get('plan', np.array([0.])))):
|
if self.chestnut and not np.all(np.isfinite(outputs.get('plan', np.array([0.])))):
|
||||||
cloudlog.error("model output not finite, dropping frame")
|
raise RuntimeError("model output not finite")
|
||||||
return None
|
|
||||||
|
|
||||||
return outputs
|
return outputs
|
||||||
|
|
||||||
@@ -363,21 +360,26 @@ def main(demo=False):
|
|||||||
|
|
||||||
model = None
|
model = None
|
||||||
if CHESTNUT:
|
if CHESTNUT:
|
||||||
import threading
|
big_model = None
|
||||||
def load():
|
def load_big():
|
||||||
nonlocal model
|
nonlocal big_model
|
||||||
model = ModelState(cam_w=vipc_client_main.width, cam_h=vipc_client_main.height, chestnut=True)
|
try:
|
||||||
t = threading.Thread(target=load, daemon=True)
|
m = ModelState(cam_w=vipc_client_main.width, cam_h=vipc_client_main.height, chestnut=True)
|
||||||
t.start()
|
m.warmup()
|
||||||
t.join(60)
|
big_model = m
|
||||||
if model is None:
|
except Exception:
|
||||||
params.put_bool("ChestnutActive", False)
|
cloudlog.exception("chestnut load failed")
|
||||||
raise RuntimeError("chestnut model load failed or timed out (60s)")
|
loader = threading.Thread(target=load_big, daemon=True)
|
||||||
params.put_bool("ChestnutActive", True)
|
loader.start()
|
||||||
else:
|
loader.join(BIG_MODEL_TIMEOUT)
|
||||||
model = ModelState(cam_w=vipc_client_main.width, cam_h=vipc_client_main.height, chestnut=False)
|
model = big_model
|
||||||
|
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:
|
||||||
|
model = small_model
|
||||||
params.put_bool("ChestnutLoading", False)
|
params.put_bool("ChestnutLoading", False)
|
||||||
|
assert model is not None
|
||||||
cloudlog.warning(f"models loaded in {time.monotonic() - st:.1f}s, modeld starting")
|
cloudlog.warning(f"models loaded in {time.monotonic() - st:.1f}s, modeld starting")
|
||||||
|
|
||||||
# messaging
|
# messaging
|
||||||
@@ -386,7 +388,7 @@ def main(demo=False):
|
|||||||
sm = SubMaster(["deviceState", "carState", "narrowRoadCameraState", "extrinsicsCalibration", "driverMonitoringState", "carControl", "lateralDelay"])
|
sm = SubMaster(["deviceState", "carState", "narrowRoadCameraState", "extrinsicsCalibration", "driverMonitoringState", "carControl", "lateralDelay"])
|
||||||
|
|
||||||
publish_state = PublishState()
|
publish_state = PublishState()
|
||||||
chestnut_state = ChestnutState(pm, CHESTNUT) if CHESTNUT else None
|
chestnut_state = ChestnutState(pm, model.chestnut) if CHESTNUT else None
|
||||||
|
|
||||||
# setup filter to track dropped frames
|
# setup filter to track dropped frames
|
||||||
frame_dropped_filter = FirstOrderFilter(0., 10., 1. / model.constants.MODEL_FREQ)
|
frame_dropped_filter = FirstOrderFilter(0., 10., 1. / model.constants.MODEL_FREQ)
|
||||||
@@ -509,7 +511,19 @@ def main(demo=False):
|
|||||||
inputs['action_t'] = np.array([lat_action_t, long_action_t], dtype=np.float32)
|
inputs['action_t'] = np.array([lat_action_t, long_action_t], dtype=np.float32)
|
||||||
|
|
||||||
mt1 = time.perf_counter()
|
mt1 = time.perf_counter()
|
||||||
model_output = model.run(bufs, transforms, inputs, prepare_only)
|
try:
|
||||||
|
model_output = model.run(bufs, transforms, inputs, prepare_only)
|
||||||
|
except Exception:
|
||||||
|
if not params.get_bool("ChestnutActive"):
|
||||||
|
raise
|
||||||
|
cloudlog.exception("chestnut failed, falling back to small")
|
||||||
|
params.put_bool("ChestnutActive", False)
|
||||||
|
assert small_model is not None
|
||||||
|
model = small_model
|
||||||
|
if chestnut_state is not None:
|
||||||
|
chestnut_state.big = False
|
||||||
|
run_count = 0
|
||||||
|
model_output = None
|
||||||
mt2 = time.perf_counter()
|
mt2 = time.perf_counter()
|
||||||
model_execution_time = mt2 - mt1
|
model_execution_time = mt2 - mt1
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
"""
|
||||||
|
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 io
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from openpilot.common.file_chunker import get_chunk_name
|
||||||
|
from openpilot.common.hardware import hw
|
||||||
|
from openpilot.common.test import OpenpilotTestCase
|
||||||
|
from openpilot.selfdrive.modeld.helpers import dump_oob
|
||||||
|
import openpilot.sunnypilot.modeld_v2.modeld as modeld_module
|
||||||
|
from openpilot.sunnypilot.modeld_v2.tests import helpers as tests_helpers
|
||||||
|
from openpilot.sunnypilot.modeld_v2.tests.helpers import DummyModel, DummyBundle, CAM_W, CAM_H
|
||||||
|
from openpilot.sunnypilot.models.fetcher import ModelParser, ModelFetcher
|
||||||
|
|
||||||
|
tmp_path = tests_helpers.tmp_path
|
||||||
|
|
||||||
|
|
||||||
|
class TestFallback(OpenpilotTestCase):
|
||||||
|
def test_find_dual_model_in_bundle(self, tmp_path, monkeypatch):
|
||||||
|
lebowski_file = 'driving_lebowski.pkl'
|
||||||
|
tsfdo_file = 'driving_tsfdo.pkl'
|
||||||
|
(tmp_path / lebowski_file).write_bytes(b'fkasdjfkljf')
|
||||||
|
(tmp_path / tsfdo_file).write_bytes(b'dskfajklsdjlsfka')
|
||||||
|
|
||||||
|
monkeypatch.setattr(hw.Paths, 'model_root', staticmethod(lambda: str(tmp_path)))
|
||||||
|
big_bundle = DummyBundle(models=[DummyModel('supercombo', lebowski_file)])
|
||||||
|
small_bundle = DummyBundle(models=[DummyModel('supercombo', tsfdo_file)])
|
||||||
|
big_pkl = modeld_module._find_driving_pkl(big_bundle)
|
||||||
|
small_pkl = modeld_module._find_driving_pkl(small_bundle)
|
||||||
|
|
||||||
|
assert big_pkl is not None and lebowski_file in big_pkl
|
||||||
|
assert small_pkl is not None and tsfdo_file in small_pkl
|
||||||
|
|
||||||
|
def test_download_models_and_init_modelstate_fallback(self, tmp_path, monkeypatch):
|
||||||
|
monkeypatch.setattr(hw.Paths, 'model_root', staticmethod(lambda: str(tmp_path)))
|
||||||
|
big_json = requests.get(ModelFetcher.MODEL_URL_CHESTNUT).json()
|
||||||
|
big_bundle = ModelParser.parse_models(big_json)[-1]
|
||||||
|
small_json = requests.get(ModelFetcher.MODEL_URL).json()
|
||||||
|
small_bundle = ModelParser.parse_models(small_json)[-1]
|
||||||
|
|
||||||
|
buf = io.BytesIO()
|
||||||
|
dump_oob(tests_helpers.make_pkl_data(tests_helpers.ARCHETYPES['supercombo_non20hz']), buf)
|
||||||
|
oob_bytes = buf.getvalue()
|
||||||
|
|
||||||
|
for bundle in (big_bundle, small_bundle):
|
||||||
|
artifact = bundle.models[0].artifact
|
||||||
|
for i in range(len(artifact.chunks)):
|
||||||
|
(tmp_path / get_chunk_name(artifact.fileName, i, len(artifact.chunks))).write_bytes(oob_bytes if i == 0 else b"")
|
||||||
|
|
||||||
|
monkeypatch.setattr(modeld_module, 'get_active_bundle', lambda params=None, *, chestnut=None: small_bundle)
|
||||||
|
assert modeld_module.ModelState(CAM_W, CAM_H, chestnut=False).chestnut is False
|
||||||
|
|
||||||
|
monkeypatch.setattr(modeld_module, 'get_active_bundle', lambda params=None, *, chestnut=None: big_bundle)
|
||||||
|
try:
|
||||||
|
assert modeld_module.ModelState(CAM_W, CAM_H, chestnut=True).chestnut is True
|
||||||
|
except Exception as e:
|
||||||
|
assert "AMD" in str(e) or "device" in str(e).lower()
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import requests
|
||||||
|
import re
|
||||||
|
|
||||||
from openpilot.common.basedir import BASEDIR
|
from openpilot.common.basedir import BASEDIR
|
||||||
from openpilot.selfdrive.ui.ui_state import ui_state
|
from openpilot.selfdrive.ui.ui_state import ui_state
|
||||||
from openpilot.sunnypilot import get_file_hash
|
from openpilot.sunnypilot import get_file_hash
|
||||||
from openpilot.sunnypilot.models.model_name import DEFAULT_MODEL, DEFAULT_BIG_MODEL
|
from openpilot.sunnypilot.models.model_name import DEFAULT_MODEL, DEFAULT_BIG_MODEL
|
||||||
|
from openpilot.sunnypilot.models.fetcher import ModelFetcher
|
||||||
|
|
||||||
|
|
||||||
def get_default_model() -> str:
|
def get_default_model() -> str:
|
||||||
@@ -30,14 +33,29 @@ def update_model_hash():
|
|||||||
print(f"Generated and updated new combined model hash to {MODEL_HASH_PATH}")
|
print(f"Generated and updated new combined model hash to {MODEL_HASH_PATH}")
|
||||||
|
|
||||||
|
|
||||||
|
def get_ref_for_name(url: str, name: str) -> str:
|
||||||
|
response = requests.get(url, timeout=10)
|
||||||
|
if response.status_code == 200:
|
||||||
|
bundles = response.json()["bundles"]
|
||||||
|
matching = [b for b in bundles if re.search(name, f"{b['short_name']} {b['display_name']}", re.IGNORECASE)]
|
||||||
|
if matching:
|
||||||
|
return max(matching, key=lambda b: int(b["index"]))["ref"]
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def update_default_model_names(default_model_name: str, default_big_model_name: str):
|
def update_default_model_names(default_model_name: str, default_big_model_name: str):
|
||||||
print("[CHANGE DEFAULT MODEL NAMES]")
|
print("[CHANGE DEFAULT MODEL NAMES]")
|
||||||
|
small_ref = get_ref_for_name(ModelFetcher.MODEL_URL, default_model_name)
|
||||||
|
big_ref = get_ref_for_name(ModelFetcher.MODEL_URL_CHESTNUT, default_big_model_name)
|
||||||
|
|
||||||
with open(DEFAULT_MODEL_NAME_PATH, "w") as f:
|
with open(DEFAULT_MODEL_NAME_PATH, "w") as f:
|
||||||
f.write(f'DEFAULT_MODEL = "{default_model_name}"\n')
|
f.write(f'DEFAULT_MODEL = "{default_model_name}"\n')
|
||||||
|
f.write(f'DEFAULT_MODEL_REF = "{small_ref}"\n')
|
||||||
f.write(f'DEFAULT_BIG_MODEL = "{default_big_model_name}"\n')
|
f.write(f'DEFAULT_BIG_MODEL = "{default_big_model_name}"\n')
|
||||||
|
f.write(f'DEFAULT_BIG_MODEL_REF = "{big_ref}"\n')
|
||||||
|
|
||||||
print(f'New default small model name: "{default_model_name}"')
|
print(f'New default small model name: "{default_model_name}" (ref: {small_ref})')
|
||||||
print(f'New default big model name: "{default_big_model_name}"')
|
print(f'New default big model name: "{default_big_model_name}" (ref: {big_ref})')
|
||||||
print("[DONE]")
|
print("[DONE]")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -328,6 +328,12 @@ class ModelManagerSP:
|
|||||||
validate_active_bundles(self.params, self.source_models)
|
validate_active_bundles(self.params, self.source_models)
|
||||||
self.active_bundle = get_active_bundle(self.params, chestnut=self.chestnut_present)
|
self.active_bundle = get_active_bundle(self.params, chestnut=self.chestnut_present)
|
||||||
|
|
||||||
|
if get_selected_bundle(self.params, "chestnut") is not None and get_selected_bundle(self.params, "qcom") is None:
|
||||||
|
if self.params.get("ModelManager_DownloadRef") is None:
|
||||||
|
from openpilot.sunnypilot.models.model_name import DEFAULT_MODEL_REF
|
||||||
|
if DEFAULT_MODEL_REF:
|
||||||
|
self.params.put("ModelManager_DownloadRef", DEFAULT_MODEL_REF)
|
||||||
|
|
||||||
self._process_download_requests()
|
self._process_download_requests()
|
||||||
|
|
||||||
if self.params.get("ModelManager_ClearCache"):
|
if self.params.get("ModelManager_ClearCache"):
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
DEFAULT_MODEL = "CD210"
|
DEFAULT_MODEL = "CD210"
|
||||||
|
DEFAULT_MODEL_REF = "5b6436a90cf6902b8aaa71c2b6f3d7164d8ae391"
|
||||||
DEFAULT_BIG_MODEL = "Lebowski"
|
DEFAULT_BIG_MODEL = "Lebowski"
|
||||||
|
DEFAULT_BIG_MODEL_REF = "fa0c6876d3cf070e91e25e5353ceadc68a5b3285"
|
||||||
|
|||||||
@@ -1675,12 +1675,6 @@
|
|||||||
"widget": "toggle",
|
"widget": "toggle",
|
||||||
"title": "Onroad Uploads"
|
"title": "Onroad Uploads"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"key": "AuxPowerSave",
|
|
||||||
"widget": "toggle",
|
|
||||||
"title": "Disable Aux Port When Offroad",
|
|
||||||
"description": "Power off the aux USB-C port while offroad to save power. It powers back on automatically when you go onroad."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"key": "MaxTimeOffroad",
|
"key": "MaxTimeOffroad",
|
||||||
"widget": "option",
|
"widget": "option",
|
||||||
|
|||||||
@@ -30,10 +30,6 @@ sections:
|
|||||||
- key: OnroadUploads
|
- key: OnroadUploads
|
||||||
widget: toggle
|
widget: toggle
|
||||||
title: Onroad Uploads
|
title: Onroad Uploads
|
||||||
- key: AuxPowerSave
|
|
||||||
widget: toggle
|
|
||||||
title: Disable Aux Port When Offroad
|
|
||||||
description: Power off the aux USB-C port while offroad to save power. It powers back on automatically when you go onroad.
|
|
||||||
- key: MaxTimeOffroad
|
- key: MaxTimeOffroad
|
||||||
widget: option
|
widget: option
|
||||||
title: Max Time Offroad
|
title: Max Time Offroad
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert
|
|||||||
from openpilot.common.hardware import HARDWARE, COMMA_HARDWARE
|
from openpilot.common.hardware import HARDWARE, COMMA_HARDWARE
|
||||||
from openpilot.common.basedir import BASEDIR
|
from openpilot.common.basedir import BASEDIR
|
||||||
from openpilot.common.hardware.usb import CHESTNUT_FW_VERSION, CHESTNUT_ROM_USB_IDS, CHESTNUT_USB_IDS, get_usb_state, get_usb_topology, set_usb_state
|
from openpilot.common.hardware.usb import CHESTNUT_FW_VERSION, CHESTNUT_ROM_USB_IDS, CHESTNUT_USB_IDS, get_usb_state, get_usb_topology, set_usb_state
|
||||||
from openpilot.system.hardware.chestnut.flash import VBUS_PATH
|
|
||||||
from openpilot.common.linux import LinuxSystemStats
|
from openpilot.common.linux import LinuxSystemStats
|
||||||
from openpilot.system.loggerd.config import get_available_percent
|
from openpilot.system.loggerd.config import get_available_percent
|
||||||
from openpilot.common.swaglog import cloudlog
|
from openpilot.common.swaglog import cloudlog
|
||||||
@@ -50,10 +49,6 @@ class Chestnut:
|
|||||||
self.attempts = 0
|
self.attempts = 0
|
||||||
self.last_attempt = 0.
|
self.last_attempt = 0.
|
||||||
self.flashed = False
|
self.flashed = False
|
||||||
self.vbus_on = None
|
|
||||||
self.params = Params()
|
|
||||||
self.powersave = False
|
|
||||||
self.last_offroad = None
|
|
||||||
|
|
||||||
def flash(self) -> None:
|
def flash(self) -> None:
|
||||||
ret = subprocess.run(["sudo", sys.executable, os.path.join(BASEDIR, "openpilot/system/hardware/chestnut/flash.py"), CHESTNUT_FW_VERSION],
|
ret = subprocess.run(["sudo", sys.executable, os.path.join(BASEDIR, "openpilot/system/hardware/chestnut/flash.py"), CHESTNUT_FW_VERSION],
|
||||||
@@ -61,19 +56,9 @@ class Chestnut:
|
|||||||
cloudlog.event("chestnut flash done", returncode=ret.returncode, output=ret.stdout[-1000:], error=ret.returncode != 0)
|
cloudlog.event("chestnut flash done", returncode=ret.returncode, output=ret.stdout[-1000:], error=ret.returncode != 0)
|
||||||
self.flashed = ret.returncode == 0
|
self.flashed = ret.returncode == 0
|
||||||
|
|
||||||
def set_vbus(self, on: bool) -> None:
|
|
||||||
if on == self.vbus_on:
|
|
||||||
return
|
|
||||||
subprocess.run(["sudo", "tee", VBUS_PATH], input=b"1" if on else b"0", stdout=subprocess.DEVNULL, check=False)
|
|
||||||
self.vbus_on = on
|
|
||||||
|
|
||||||
def update(self, offroad: bool, usb_state: list[dict]) -> None:
|
def update(self, offroad: bool, usb_state: list[dict]) -> None:
|
||||||
mismatch = any((d["vendorId"], d["productId"]) in CHESTNUT_USB_IDS + CHESTNUT_ROM_USB_IDS and
|
mismatch = any((d["vendorId"], d["productId"]) in CHESTNUT_USB_IDS + CHESTNUT_ROM_USB_IDS and
|
||||||
d["product"] != f"custom {CHESTNUT_FW_VERSION}-CLEAN" for d in usb_state)
|
d["product"] != f"custom {CHESTNUT_FW_VERSION}-CLEAN" for d in usb_state)
|
||||||
if offroad != self.last_offroad:
|
|
||||||
self.powersave = self.params.get_bool("AuxPowerSave")
|
|
||||||
self.last_offroad = offroad
|
|
||||||
self.set_vbus((not offroad or mismatch) or not self.powersave)
|
|
||||||
if not mismatch:
|
if not mismatch:
|
||||||
self.flashed = False
|
self.flashed = False
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user