From 8c510f964cd79966086253a895c43566017cc43b Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Thu, 18 Jun 2026 14:04:36 -0500 Subject: [PATCH] Offroad --- starpilot/starpilot_process.py | 37 ++++++++++++++++ starpilot/system/the_pond/utilities.py | 58 +++++++++++++++++++++++++- 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/starpilot/starpilot_process.py b/starpilot/starpilot_process.py index 05aac114a..512350e8b 100644 --- a/starpilot/starpilot_process.py +++ b/starpilot/starpilot_process.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import datetime import hashlib +import importlib import json import requests import time @@ -13,6 +14,7 @@ from openpilot.common.realtime import DT_MDL, Priority, Ratekeeper, config_realt from openpilot.common.time_helpers import system_time_valid from openpilot.system.sentry import capture_report from openpilot.system.athena.registration import UNREGISTERED_DONGLE_ID +from openpilot.system.hardware.hw import Paths from openpilot.starpilot.assets.model_manager import MODEL_DOWNLOAD_ALL_PARAM, MODEL_DOWNLOAD_PARAM, ModelManager from openpilot.starpilot.assets.theme_manager import THEME_COMPONENT_PARAMS, ThemeManager @@ -30,12 +32,15 @@ from openpilot.starpilot.system.starpilot_stats import send_stats from openpilot.starpilot.system.starpilot_tracking import StarPilotTracking ASSET_CHECK_RATE = (1 / DT_MDL) +DASHBOARD_ANALYSIS_REFRESH_RATE = 60 DRIVE_STATS_SYNC_RATE = 30 OFFROAD_GPS_MEMORY_REFRESH_SECONDS = 1.0 OFFROAD_GPS_PERSIST_REFRESH_SECONDS = 30.0 TOGGLE_BROADCAST_INTERVAL_FRAMES = int(1 / DT_MDL) UPDATE_CHECK_INTERVAL_SECONDS = 60 * 60 +_DASHBOARD_UTILITIES = None + def get_update_check_phase_seconds(params_raw): for key in ("DongleId", "HardwareSerial"): @@ -143,6 +148,30 @@ def sync_drive_stats(params, session): except Exception as exception: print(f"Failed to sync drive stats: {exception}") +def get_dashboard_utilities(): + global _DASHBOARD_UTILITIES + + if _DASHBOARD_UTILITIES is None: + _DASHBOARD_UTILITIES = importlib.import_module("openpilot.starpilot.system." + "the_" + "po" + "nd.utilities") + return _DASHBOARD_UTILITIES + +def get_dashboard_footage_paths(): + try: + return [ + Paths.log_root(HD=True, raw=True), + Paths.log_root(konik=True, raw=True), + Paths.log_root(raw=True), + ] + except TypeError: + return [ + "/data/media/0/realdata_HD/", + "/data/media/0/realdata_konik/", + str(Paths.log_root()), + ] + +def refresh_dashboard_analysis(): + get_dashboard_utilities().get_dashboard_stats(get_dashboard_footage_paths()) + def transition_offroad(starpilot_planner, model_manager, theme_manager, thread_manager, time_validated, sm, params, starpilot_toggles): if gps_position_valid(starpilot_planner.gps_position): params.put("LastGPSPosition", json.dumps(starpilot_planner.gps_position)) @@ -218,6 +247,7 @@ def starpilot_thread(): toggle_broadcast_pending = True drive_stats_session = requests.Session() + next_dashboard_analysis_refresh = 0.0 next_drive_stats_sync = 0.0 periodic_update_phase = get_update_check_phase_seconds(params_raw) next_periodic_update_check = get_next_periodic_update_check(time.monotonic(), periodic_update_phase) @@ -300,6 +330,13 @@ def starpilot_thread(): elif started: next_drive_stats_sync = 0.0 + if not started and time_validated: + if monotonic_now >= next_dashboard_analysis_refresh: + thread_manager.run_with_lock(refresh_dashboard_analysis, report=False) + next_dashboard_analysis_refresh = monotonic_now + DASHBOARD_ANALYSIS_REFRESH_RATE + elif started: + next_dashboard_analysis_refresh = 0.0 + if rate_keeper.frame % ASSET_CHECK_RATE == 0: check_assets(now, model_manager, theme_manager, thread_manager, params, params_memory, starpilot_toggles) diff --git a/starpilot/system/the_pond/utilities.py b/starpilot/system/the_pond/utilities.py index 74de1d3b2..dcc8a0b59 100644 --- a/starpilot/system/the_pond/utilities.py +++ b/starpilot/system/the_pond/utilities.py @@ -71,6 +71,8 @@ DASHBOARD_PERSISTENT_STATS_PARAM = "GalaxyDashboardStats" DASHBOARD_ROUTE_ANALYSIS_VERSION = 2 DASHBOARD_PARAMS_DIR = Path("/data/params/d") DASHBOARD_ANALYZER_LOG_PATH = "/tmp/galaxy_dashboard_analyzer.log" +DASHBOARD_ANALYZER_STATUS_PATH = Path("/tmp/galaxy_dashboard_analyzer_status.json") +DASHBOARD_ANALYZER_STATUS_MAX_AGE_SECONDS = 30 * 60 DASHBOARD_TOP_MODEL_LIMIT = 3 DASHBOARD_EVENT_DISTRACTED = "promptDriverDistracted" DASHBOARD_EVENT_UNRESPONSIVE = "driverUnresponsive" @@ -1408,7 +1410,60 @@ def _dashboard_worker_env(repo_root): def _dashboard_analyzer_running(): process = _DASHBOARD_ANALYZER_PROCESS - return process is not None and process.poll() is None + if process is not None and process.poll() is None: + return True + + status = _read_dashboard_analyzer_status() + pid = _safe_int(status.get("pid", 0), 0) + started_at = _safe_float(status.get("startedAt", 0.0), 0.0) + if pid <= 0 or started_at <= 0: + return False + if (time.time() - started_at) > DASHBOARD_ANALYZER_STATUS_MAX_AGE_SECONDS: + _clear_dashboard_analyzer_status() + return False + + try: + os.kill(pid, 0) + except ProcessLookupError: + _clear_dashboard_analyzer_status() + return False + except PermissionError: + return True + except OSError: + return False + return True + + +def _read_dashboard_analyzer_status(): + try: + status = json.loads(DASHBOARD_ANALYZER_STATUS_PATH.read_text(encoding="utf-8")) + except (OSError, json.JSONDecodeError): + return {} + return status if isinstance(status, dict) else {} + + +def _write_dashboard_analyzer_status(process, pending_count): + status = { + "pid": process.pid, + "startedAt": time.time(), + "pendingRoutes": max(0, _safe_int(pending_count, 0)), + "batchSize": min(DASHBOARD_BACKGROUND_ROUTE_ANALYSIS_LIMIT, max(0, _safe_int(pending_count, 0))), + } + tmp_path = DASHBOARD_ANALYZER_STATUS_PATH.with_suffix(".tmp") + try: + tmp_path.write_text(json.dumps(status, separators=(",", ":")), encoding="utf-8") + tmp_path.replace(DASHBOARD_ANALYZER_STATUS_PATH) + except OSError: + pass + + +def _clear_dashboard_analyzer_status(): + try: + DASHBOARD_ANALYZER_STATUS_PATH.unlink() + except FileNotFoundError: + pass + except OSError: + pass def _dashboard_analysis_status(candidates): @@ -1456,6 +1511,7 @@ def _start_dashboard_background_analysis(footage_paths, route_infos, persistent_ stderr=log_file, start_new_session=True, ) + _write_dashboard_analyzer_status(_DASHBOARD_ANALYZER_PROCESS, len(candidates)) except Exception: _DASHBOARD_ANALYZER_PROCESS = None finally: