From 426382960a457dd258a3a52360af833ab624be5b Mon Sep 17 00:00:00 2001 From: Brian Hanson Date: Sat, 18 Apr 2026 13:21:07 -0500 Subject: [PATCH] dmonitoringd: narrow update_states gate to fix stuck face_detected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original gate was sm.all_checks() which required modelV2 fresh and liveCalibration.valid. Both fail spuriously in our setup: - modelV2 stops at standstill/parked (two-state modeld) - calibrationd propagates its own freq_ok glitches into liveCalibration.valid Either condition froze DM pose updates — face_detected stuck False → maybe_distracted True → awareness decayed to 0 within ~6s of engagement ("TAKE OVER" driver-distraction alert the moment controlsd engaged). Narrow the gate to only the subs update_states actually consumes (driverStateV2, carState, controlsState, liveCalibration), check only alive+valid (skip freq_ok), and skip liveCalibration.valid — rpyCalib presence is sufficient proof that calibration has produced output. Co-Authored-By: Claude Opus 4.7 (1M context) --- selfdrive/monitoring/dmonitoringd.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/selfdrive/monitoring/dmonitoringd.py b/selfdrive/monitoring/dmonitoringd.py index 12addef..020a201 100755 --- a/selfdrive/monitoring/dmonitoringd.py +++ b/selfdrive/monitoring/dmonitoringd.py @@ -44,7 +44,18 @@ def dmonitoringd_thread(): # Get data from dmonitoringmodeld events = Events() - if sm.all_checks() and len(sm['liveCalibration'].rpyCalib): + # CLEARPILOT: narrow update_states gate. The original sm.all_checks() also + # required modelV2 fresh (stops at standstill in two-state modeld) and + # liveCalibration.valid (calibrationd cascades its own freq_ok to valid, which + # flaps). Both made DM freeze pose → face_detected stuck False → awareness + # decayed to 0 within 6s of engagement. Narrow the gate to the subs + # update_states actually reads, and only to alive+valid (skip freq_ok and + # skip liveCalibration.valid). rpyCalib presence is sufficient to know + # calibration has produced output. + if (sm.alive['driverStateV2'] and sm.valid['driverStateV2'] and + sm.alive['carState'] and sm.valid['carState'] and + sm.alive['controlsState'] and sm.valid['controlsState'] and + sm.alive['liveCalibration'] and len(sm['liveCalibration'].rpyCalib) > 0): driver_status.update_states(sm['driverStateV2'], sm['liveCalibration'].rpyCalib, sm['carState'].vEgo, sm['controlsState'].enabled) # Block engaging after max number of distrations