From 2267f2dce2957135a9120eb7282e369b7b7d1308 Mon Sep 17 00:00:00 2001 From: whoisdomi Date: Wed, 16 Sep 2026 06:44:08 -0500 Subject: [PATCH] lil --- selfdrive/selfdrived/events.py | 7 ++--- selfdrive/selfdrived/selfdrived.py | 17 +++++----- .../tests/test_big_model_engagement.py | 31 ++++++++++++------- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/selfdrive/selfdrived/events.py b/selfdrive/selfdrived/events.py index be4d0a8d22..09c5351d23 100644 --- a/selfdrive/selfdrived/events.py +++ b/selfdrive/selfdrived/events.py @@ -532,10 +532,9 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { "Ensure road ahead is clear"), }, - EventName.bigModelLoading: { - ET.PERMANENT: NormalPermanentAlert("Big Model Loading", - "Driving on the small model"), - }, + # bigModelLoading and bigModelPending carry no alerts on purpose: the blinking eGPU icon + # already says the big model is loading, and its absence says it is ready. + EventName.bigModelLoading: {}, # bigModelPending carries no alert on purpose: the eGPU icon clearing, and then turning # green on the next engage, is the driver's cue. A banner here announced the model before diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index a37d2c4e90..86cc43d1f9 100644 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -64,9 +64,6 @@ StarPilotEventName = custom.StarPilotOnroadEvent.EventName IGNORED_SAFETY_MODES = (SafetyModel.silent, SafetyModel.noOutput) VALID_ONLY_COMM_ISSUE_GRACE_FRAMES = max(1, round(0.5 / DT_CTRL)) -# How long the "driving on the small model" banner shows before the blinking eGPU icon -# takes over as the indication that the big model is still loading. -BIG_MODEL_LOADING_ALERT_SECONDS = 3.0 def evaluate_comm_issue(all_checks: bool, all_alive: bool, all_freq_ok: bool, @@ -259,7 +256,6 @@ class SelfdriveD: self.big_model_active = False self.big_model_failed = False self.big_model_swap_t = 0. - self.big_model_loading_t = 0. self.experimental_mode = False self.ecu_disable_failed = False self.ecu_disable_failed_checked = not ( @@ -398,12 +394,10 @@ class SelfdriveD: loading = self.params.get_bool("UsbGpuLoading") if loading: self.big_model_attempted = True - if not self.big_model_loading: - self.big_model_loading_t = time.monotonic() self.big_model_loading = loading - # Announce the small-model handover briefly; the blinking eGPU icon carries the - # "still loading" state from there so the banner does not sit on screen for minutes. - if loading and time.monotonic() < self.big_model_loading_t + BIG_MODEL_LOADING_ALERT_SECONDS: + # No alert while loading: the blinking eGPU icon already carries that state, and the + # small model is driving normally. big_model_loading still gates the frame-drop warning. + if loading: self.events.add(EventName.bigModelLoading) # The big model loads in the background while the small model drives, so it sits @@ -817,7 +811,10 @@ class SelfdriveD: # TODO: fix simulator if not SIMULATION or REPLAY: - if self.sm['modelV2'].frameDropPerc > 20: + # Loading the big model realizes its graph on the same QCOM GPU the small model is + # driving on, which costs real frames for part of the load. The small model keeps + # publishing throughout, so warn about the drops only once the load is out of the way. + if self.sm['modelV2'].frameDropPerc > 20 and not self.big_model_loading: self.events.add(EventName.modeldLagging) # Decrement personality on configured steering-wheel button presses diff --git a/selfdrive/selfdrived/tests/test_big_model_engagement.py b/selfdrive/selfdrived/tests/test_big_model_engagement.py index 57061fbbfb..bde9410e93 100644 --- a/selfdrive/selfdrived/tests/test_big_model_engagement.py +++ b/selfdrive/selfdrived/tests/test_big_model_engagement.py @@ -13,7 +13,6 @@ def test_big_model_loading_does_not_block_engagement(): # The big model loads in the background while the small model drives, so waiting for it # must never keep the driver from engaging. assert ET.NO_ENTRY not in EVENTS[EventName.bigModelLoading] - assert ET.PERMANENT in EVENTS[EventName.bigModelLoading] def test_big_model_pending_raises_no_alert(): @@ -63,22 +62,30 @@ def test_pending_is_raised_before_loading_is_cleared(): "UsbGpuPending must be raised before UsbGpuLoading is cleared" -def test_loading_banner_is_brief_and_hands_over_to_the_icon(): - # The load can run for minutes; the banner announces the handover to the small model and - # then gets out of the way, leaving the blinking eGPU icon as the "still loading" cue. +def test_big_model_loading_raises_no_alert(): + # The blinking eGPU icon already says the big model is loading, so the banner was noise + # sitting on screen for the whole load. + assert EVENTS[EventName.bigModelLoading] == {} + + +def test_frame_drop_warning_is_suppressed_while_the_big_model_loads(): + """Loading realizes the big model's graph on QCOM, the GPU the small model drives on. + + Measured on drive 00000ab7: the small model's own modelExecutionTime p95 went 37 ms -> + 126 ms for a stretch of the load, which pushed frameDropPerc past the modeldLagging + threshold. The small model keeps publishing and driving correctly throughout, so the + warning is noise until the load is done. + """ from openpilot.selfdrive.selfdrived import selfdrived - assert selfdrived.BIG_MODEL_LOADING_ALERT_SECONDS == 3.0 - source = (Path(selfdrived.__file__)).read_text(encoding="utf-8") - tree = ast.parse(source) guard = next( - node for node in ast.walk(tree) - if isinstance(node, ast.If) and "bigModelLoading" in ast.dump(node) - and "BIG_MODEL_LOADING_ALERT_SECONDS" in ast.dump(node.test) + node for node in ast.walk(ast.parse(source)) + if isinstance(node, ast.If) and "modeldLagging" in ast.dump(node) + and "frameDropPerc" in ast.dump(node.test) ) - # The alert must be gated on elapsed time, not added unconditionally every frame. - assert "big_model_loading_t" in ast.dump(guard.test) + assert "big_model_loading" in ast.dump(guard.test), \ + "modeldLagging must not fire for frames the big-model load is costing" def _big_failed(*, attempted, loading, pending, big_active, model_unavailable=False):