From ef4e02e354640fd1a4bc9bde186dc3fe3ab17283 Mon Sep 17 00:00:00 2001 From: Brian Hanson Date: Thu, 16 Apr 2026 21:41:29 -0500 Subject: [PATCH] feat: 10fps daytime / 4fps night modeld + 2Hz GPS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduced-rate modeld path now branches on IsDaylight: - daylight: skip 1/2 frames → 10fps (better model responsiveness when lighting gives the net more signal) - night: skip 4/5 frames → 4fps (unchanged, conservative for power) IsDaylight is already in /dev/shm (memory) via gpsd.py. Gated the IsDaylight write on change — it flips twice a day, no reason to rewrite every 30s. GPS polling bumped from 1Hz → 2Hz. ModelFps publishes "10" / "4" / "20" so longitudinal_planner's dt and FCW-threshold scaling (if re-enabled) still track actual rate. Co-Authored-By: Claude Opus 4.6 (1M context) --- selfdrive/modeld/modeld.py | 14 +++++++++----- system/clearpilot/gpsd.py | 8 ++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/selfdrive/modeld/modeld.py b/selfdrive/modeld/modeld.py index fd9c790..7b95f24 100755 --- a/selfdrive/modeld/modeld.py +++ b/selfdrive/modeld/modeld.py @@ -273,17 +273,21 @@ def main(demo=False): last_vipc_frame_id = meta_main.frame_id continue - # Reduced framerate: 4fps when not lat active and not standstill - # Skip 4 out of every 5 frames (20fps -> 4fps) + # Reduced framerate: daylight 10fps (skip 1/2), night 4fps (skip 4/5) + # Daytime runs twice as fast — better model responsiveness when lighting is good + # and the neural net has more signal. Night stays conservative for power. # Write standby timestamp so controlsd suppresses transient errors if not full_rate: - if params_memory.get("ModelFps") != b"4": - params_memory.put("ModelFps", "4") + 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 % 5 != 0: + if run_count % skip_interval != 0: last_vipc_frame_id = meta_main.frame_id run_count += 1 continue diff --git a/system/clearpilot/gpsd.py b/system/clearpilot/gpsd.py index 296975e..cf4f402 100644 --- a/system/clearpilot/gpsd.py +++ b/system/clearpilot/gpsd.py @@ -159,6 +159,7 @@ def main(): params_memory = Params("/dev/shm/params") last_daylight_check = 0.0 daylight_computed = False + prev_daylight = None # CLEARPILOT: gate IsDaylight write on change print("gpsd: entering main loop", file=sys.stderr, flush=True) while True: @@ -205,7 +206,10 @@ def main(): last_daylight_check = now_mono utc_now = datetime.datetime.utcfromtimestamp(fix["timestamp_ms"] / 1000) daylight = is_daylight(fix["latitude"], fix["longitude"], utc_now) - params_memory.put_bool("IsDaylight", daylight) + # CLEARPILOT: gate on change — daylight flips twice a day, don't rewrite every 30s + if daylight != prev_daylight: + params_memory.put_bool("IsDaylight", daylight) + prev_daylight = daylight if not daylight_computed: daylight_computed = True @@ -221,7 +225,7 @@ def main(): params_memory.put_int("ScreenDisplayMode", 0) cloudlog.warning("gpsd: auto-switch to normal (sunrise)") - time.sleep(1.0) # 1 Hz polling + time.sleep(0.5) # 2 Hz polling if __name__ == "__main__":