From 4c8ef93b2b47be05a4ef99a8ccc14efb4a7a5d1b Mon Sep 17 00:00:00 2001 From: Brian Hanson Date: Sat, 18 Apr 2026 11:20:48 -0500 Subject: [PATCH] modeld two-state; UI: immediate blank on ignition off; READY splash on wake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - modeld: simplified to 0fps (standstill or parked) or 20fps. Removed 4/10fps reduced-rate path, republish caching, FPCC/liveCalibration reads, and ModelFps per-cycle param writes. - ui.cc updateWakefulness: ignition on→off now resets interactive_timeout to 0 for immediate screen blank. Tap still wakes via existing handler. - home.cc offroadTransition(false): reset ready->has_driven to false so the READY text appears on fresh ignition, not the textless post-drive splash. Co-Authored-By: Claude Opus 4.7 (1M context) --- selfdrive/modeld/modeld.py | 65 +++++++------------------------------- selfdrive/ui/qt/home.cc | 4 ++- selfdrive/ui/ui.cc | 5 ++- 3 files changed, 18 insertions(+), 56 deletions(-) diff --git a/selfdrive/modeld/modeld.py b/selfdrive/modeld/modeld.py index b00e8c8..fd6c17a 100755 --- a/selfdrive/modeld/modeld.py +++ b/selfdrive/modeld/modeld.py @@ -169,7 +169,7 @@ def main(demo=False): # messaging pm = PubMaster(["modelV2", "cameraOdometry"]) - sm = SubMaster(["deviceState", "carState", "roadCameraState", "liveCalibration", "driverMonitoringState", "navModel", "navInstruction", "carControl", "frogpilotCarControl", "liveTracks", "frogpilotPlan"]) + sm = SubMaster(["deviceState", "carState", "roadCameraState", "liveCalibration", "driverMonitoringState", "navModel", "navInstruction", "carControl", "liveTracks", "frogpilotPlan"]) publish_state = PublishState() params = Params() @@ -186,11 +186,6 @@ def main(demo=False): model_standby = False last_standby_ts_write = 0 params_memory = Params("/dev/shm/params") - # CLEARPILOT: cache last model output for republishing on skip cycles. Keeps downstream - # cameraOdometry/modelV2 rate constant at 20Hz so services.py freq checks never fail - # during reduced-rate mode. Content is stale but we only reduce rate when not engaged, - # so no one is actually using it for control. - last_model_output = None nav_features = np.zeros(ModelConstants.NAV_FEATURE_LEN, dtype=np.float32) nav_instructions = np.zeros(ModelConstants.NAV_INSTRUCTION_LEN, dtype=np.float32) buf_main, buf_extra = None, None @@ -246,25 +241,18 @@ def main(demo=False): sm.update(0) - # CLEARPILOT: variable framerate — 4/10fps when not engaged, 20fps when engaged - # (or lane changing / calibrating). Downstream services get a constant publish rate - # via the republish-caching below — only the GPU inference is skipped, so no - # freq_ok cascade in consumers. - fpcc = sm['frogpilotCarControl'] - lat_active = fpcc.latRequested - lane_changing = fpcc.noLatLaneChange + # CLEARPILOT: two-state modeld — 0fps at standstill or parked, 20fps otherwise. standstill = sm['carState'].standstill - calibrating = sm['liveCalibration'].calStatus != log.LiveCalibrationData.Status.calibrated - full_rate = lat_active or lane_changing or calibrating - - # Standby transitions (standstill only, when not at full rate) - should_standby = standstill and not full_rate + parked = sm['carState'].gearShifter == car.CarState.GearShifter.park + should_standby = standstill or parked if should_standby and not model_standby: params_memory.put_bool("ModelStandby", True) + params_memory.put("ModelFps", "0") model_standby = True - cloudlog.warning("modeld: standby ON (standstill)") + cloudlog.warning("modeld: standby ON") elif not should_standby and model_standby: params_memory.put_bool("ModelStandby", False) + params_memory.put("ModelFps", "20") model_standby = False run_count = 0 frame_dropped_filter.x = 0. @@ -277,28 +265,6 @@ def main(demo=False): last_vipc_frame_id = meta_main.frame_id continue - # CLEARPILOT: reduced framerate: skip GPU inference on most frames but still - # republish cached output at full 20Hz so downstream services never see a rate - # drop (avoids freq_ok → valid cascade that causes "Communication Issue" false - # positives on engage). Daylight: skip 1/2 (compute at 10fps), night: skip 4/5 - # (compute at 4fps). ModelStandbyTs still written for model_suppress window. - republish_only = False - if not full_rate: - is_daylight = params_memory.get_bool("IsDaylight") - skip_interval = 2 if is_daylight else 5 - target_fps = b"10" if is_daylight else b"4" - if params_memory.get("ModelFps") != target_fps: - params_memory.put("ModelFps", target_fps.decode()) - now = _time.monotonic() - if now - last_standby_ts_write > 1.0: - params_memory.put("ModelStandbyTs", str(now)) - last_standby_ts_write = now - if run_count % skip_interval != 0: - republish_only = True - else: - if params_memory.get("ModelFps") != b"20": - params_memory.put("ModelFps", "20") - desire = DH.desire is_rhd = sm["driverMonitoringState"].isRHD frame_id = sm["roadCameraState"].frameId @@ -370,21 +336,12 @@ def main(demo=False): **({'radar_tracks': radar_tracks,} if DISABLE_RADAR else {}), } - # CLEARPILOT: on republish cycles, skip the GPU inference and reuse the last - # model output. Publish rate stays at 20Hz, compute rate is reduced. - if republish_only and last_model_output is not None: - model_output = last_model_output - model_execution_time = 0.0 - else: - mt1 = time.perf_counter() - model_output = model.run(buf_main, buf_extra, model_transform_main, model_transform_extra, inputs, prepare_only) - mt2 = time.perf_counter() - model_execution_time = mt2 - mt1 + mt1 = time.perf_counter() + model_output = model.run(buf_main, buf_extra, model_transform_main, model_transform_extra, inputs, prepare_only) + mt2 = time.perf_counter() + model_execution_time = mt2 - mt1 if model_output is not None: - # cache for next republish cycle - last_model_output = model_output - modelv2_send = messaging.new_message('modelV2') posenet_send = messaging.new_message('cameraOdometry') fill_model_msg(modelv2_send, model_output, publish_state, meta_main.frame_id, meta_extra.frame_id, frame_id, frame_drop_ratio, diff --git a/selfdrive/ui/qt/home.cc b/selfdrive/ui/qt/home.cc index ee973c7..f758097 100755 --- a/selfdrive/ui/qt/home.cc +++ b/selfdrive/ui/qt/home.cc @@ -122,9 +122,11 @@ void HomeWindow::offroadTransition(bool offroad) { slayout->setCurrentWidget(ready); } else { // CLEARPILOT: start onroad in splash — updateState will switch to - // camera view once the car shifts out of park + // camera view once the car shifts out of park. Reset has_driven so + // fresh ignition shows the READY text (not the post-drive textless splash). LOGW("CLP UI: onroad transition -> showing splash (parked)"); was_parked_onroad = true; + ready->has_driven = false; slayout->setCurrentWidget(ready); } } diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index b438c22..da4be4c 100755 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -558,7 +558,10 @@ void Device::updateWakefulness(const UIState &s) { } if (ignition_state_changed) { - if (ignition_on && s.scene.screen_brightness_onroad == 0 && !s.scene.standby_mode) { + if (!ignition_on) { + // CLEARPILOT: ignition on→off blanks the screen immediately (tap still wakes). + resetInteractiveTimeout(0, 0); + } else if (s.scene.screen_brightness_onroad == 0 && !s.scene.standby_mode) { resetInteractiveTimeout(0, 0); } else { resetInteractiveTimeout(s.scene.screen_timeout, s.scene.screen_timeout_onroad);