feat: 10fps daytime / 4fps night modeld + 2Hz GPS

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) <noreply@anthropic.com>
This commit is contained in:
2026-04-16 21:41:29 -05:00
parent 02f25f83c4
commit ef4e02e354
2 changed files with 15 additions and 7 deletions
+9 -5
View File
@@ -273,17 +273,21 @@ def main(demo=False):
last_vipc_frame_id = meta_main.frame_id last_vipc_frame_id = meta_main.frame_id
continue continue
# Reduced framerate: 4fps when not lat active and not standstill # Reduced framerate: daylight 10fps (skip 1/2), night 4fps (skip 4/5)
# Skip 4 out of every 5 frames (20fps -> 4fps) # 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 # Write standby timestamp so controlsd suppresses transient errors
if not full_rate: if not full_rate:
if params_memory.get("ModelFps") != b"4": is_daylight = params_memory.get_bool("IsDaylight")
params_memory.put("ModelFps", "4") 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() now = _time.monotonic()
if now - last_standby_ts_write > 1.0: if now - last_standby_ts_write > 1.0:
params_memory.put("ModelStandbyTs", str(now)) params_memory.put("ModelStandbyTs", str(now))
last_standby_ts_write = 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 last_vipc_frame_id = meta_main.frame_id
run_count += 1 run_count += 1
continue continue
+5 -1
View File
@@ -159,6 +159,7 @@ def main():
params_memory = Params("/dev/shm/params") params_memory = Params("/dev/shm/params")
last_daylight_check = 0.0 last_daylight_check = 0.0
daylight_computed = False daylight_computed = False
prev_daylight = None # CLEARPILOT: gate IsDaylight write on change
print("gpsd: entering main loop", file=sys.stderr, flush=True) print("gpsd: entering main loop", file=sys.stderr, flush=True)
while True: while True:
@@ -205,7 +206,10 @@ def main():
last_daylight_check = now_mono last_daylight_check = now_mono
utc_now = datetime.datetime.utcfromtimestamp(fix["timestamp_ms"] / 1000) utc_now = datetime.datetime.utcfromtimestamp(fix["timestamp_ms"] / 1000)
daylight = is_daylight(fix["latitude"], fix["longitude"], utc_now) daylight = is_daylight(fix["latitude"], fix["longitude"], utc_now)
# CLEARPILOT: gate on change — daylight flips twice a day, don't rewrite every 30s
if daylight != prev_daylight:
params_memory.put_bool("IsDaylight", daylight) params_memory.put_bool("IsDaylight", daylight)
prev_daylight = daylight
if not daylight_computed: if not daylight_computed:
daylight_computed = True daylight_computed = True
@@ -221,7 +225,7 @@ def main():
params_memory.put_int("ScreenDisplayMode", 0) params_memory.put_int("ScreenDisplayMode", 0)
cloudlog.warning("gpsd: auto-switch to normal (sunrise)") 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__": if __name__ == "__main__":