Cut down unnecessary DM uncertain alerts (#2157)

* cut down high std alerts

* clean comments

* uncertain curve tune

* update test gt

* update refs

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
old-commit-hash: a2adfdb155
commatwo_master
ZwX1616 5 years ago committed by GitHub
parent 7accebd4a7
commit 6f3c2fba6e
  1. 2
      selfdrive/controls/lib/events.py
  2. 15
      selfdrive/monitoring/driver_monitor.py
  3. 13
      selfdrive/monitoring/test_monitoring.py
  4. 2
      selfdrive/test/process_replay/ref_commit

@ -413,7 +413,7 @@ EVENTS = {
"CHECK DRIVER FACE VISIBILITY", "CHECK DRIVER FACE VISIBILITY",
"Driver Monitor Model Output Uncertain", "Driver Monitor Model Output Uncertain",
AlertStatus.normal, AlertSize.mid, AlertStatus.normal, AlertSize.mid,
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .4, 0., 1.), Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .4, 0., 1.5),
}, },
EventName.manualRestart: { EventName.manualRestart: {

@ -15,8 +15,8 @@ EventName = car.CarEvent.EventName
# ****************************************************************************************** # ******************************************************************************************
_AWARENESS_TIME = 70. # one minute limit without user touching steering wheels make the car enter a terminal status _AWARENESS_TIME = 70. # one minute limit without user touching steering wheels make the car enter a terminal status
_AWARENESS_PRE_TIME_TILL_TERMINAL = 15. # a first alert is issued 25s before expiration _AWARENESS_PRE_TIME_TILL_TERMINAL = 15. # a first alert is issued 15s before expiration
_AWARENESS_PROMPT_TIME_TILL_TERMINAL = 6. # a second alert is issued 15s before start decelerating the car _AWARENESS_PROMPT_TIME_TILL_TERMINAL = 6. # a second alert is issued 6s before start decelerating the car
_DISTRACTED_TIME = 11. _DISTRACTED_TIME = 11.
_DISTRACTED_PRE_TIME_TILL_TERMINAL = 8. _DISTRACTED_PRE_TIME_TILL_TERMINAL = 8.
_DISTRACTED_PROMPT_TIME_TILL_TERMINAL = 6. _DISTRACTED_PROMPT_TIME_TILL_TERMINAL = 6.
@ -24,10 +24,10 @@ _DISTRACTED_PROMPT_TIME_TILL_TERMINAL = 6.
_FACE_THRESHOLD = 0.6 _FACE_THRESHOLD = 0.6
_EYE_THRESHOLD = 0.6 _EYE_THRESHOLD = 0.6
_SG_THRESHOLD = 0.5 _SG_THRESHOLD = 0.5
_BLINK_THRESHOLD = 0.5 # 0.225 _BLINK_THRESHOLD = 0.5
_BLINK_THRESHOLD_SLACK = 0.65 _BLINK_THRESHOLD_SLACK = 0.65
_BLINK_THRESHOLD_STRICT = 0.5 _BLINK_THRESHOLD_STRICT = 0.5
_PITCH_WEIGHT = 1.35 # 1.5 # pitch matters a lot more _PITCH_WEIGHT = 1.35 # pitch matters a lot more
_POSESTD_THRESHOLD = 0.14 _POSESTD_THRESHOLD = 0.14
_METRIC_THRESHOLD = 0.4 _METRIC_THRESHOLD = 0.4
_METRIC_THRESHOLD_SLACK = 0.55 _METRIC_THRESHOLD_SLACK = 0.55
@ -116,6 +116,7 @@ class DriverStatus():
self.step_change = 0. self.step_change = 0.
self.active_monitoring_mode = True self.active_monitoring_mode = True
self.hi_stds = 0 self.hi_stds = 0
self.hi_std_alert_enabled = True
self.threshold_prompt = _DISTRACTED_PROMPT_TIME_TILL_TERMINAL / _DISTRACTED_TIME self.threshold_prompt = _DISTRACTED_PROMPT_TIME_TILL_TERMINAL / _DISTRACTED_TIME
self.is_rhd_region = False self.is_rhd_region = False
@ -212,7 +213,7 @@ class DriverStatus():
self._set_timers(self.face_detected and not is_model_uncertain) self._set_timers(self.face_detected and not is_model_uncertain)
if self.face_detected and not self.pose.low_std: if self.face_detected and not self.pose.low_std:
if not is_model_uncertain: if not is_model_uncertain:
self.step_change *= max(0, (model_std_max-0.5)*(model_std_max-2)) self.step_change *= min(1.0, max(0.6, 1.6*(model_std_max-0.5)*(model_std_max-2)))
self.hi_stds += 1 self.hi_stds += 1
elif self.face_detected and self.pose.low_std: elif self.face_detected and self.pose.low_std:
self.hi_stds = 0 self.hi_stds = 0
@ -228,8 +229,9 @@ class DriverStatus():
driver_attentive = self.driver_distraction_filter.x < 0.37 driver_attentive = self.driver_distraction_filter.x < 0.37
awareness_prev = self.awareness awareness_prev = self.awareness
if self.face_detected and self.hi_stds * DT_DMON > _HI_STD_TIMEOUT: if self.face_detected and self.hi_stds * DT_DMON > _HI_STD_TIMEOUT and self.hi_std_alert_enabled:
events.add(EventName.driverMonitorLowAcc) events.add(EventName.driverMonitorLowAcc)
self.hi_std_alert_enabled = False # only showed once until orange prompt resets it
if (driver_attentive and self.face_detected and self.pose.low_std and self.awareness > 0): if (driver_attentive and self.face_detected and self.pose.low_std and self.awareness > 0):
# only restore awareness when paying attention and alert is not red # only restore awareness when paying attention and alert is not red
@ -255,6 +257,7 @@ class DriverStatus():
elif self.awareness <= self.threshold_prompt: elif self.awareness <= self.threshold_prompt:
# prompt orange alert # prompt orange alert
alert = EventName.promptDriverDistracted if self.active_monitoring_mode else EventName.promptDriverUnresponsive alert = EventName.promptDriverDistracted if self.active_monitoring_mode else EventName.promptDriverUnresponsive
self.hi_std_alert_enabled = True
elif self.awareness <= self.threshold_pre: elif self.awareness <= self.threshold_pre:
# pre green alert # pre green alert
alert = EventName.preDriverDistracted if self.active_monitoring_mode else EventName.preDriverUnresponsive alert = EventName.preDriverDistracted if self.active_monitoring_mode else EventName.preDriverUnresponsive

@ -196,8 +196,7 @@ class TestMonitoring(unittest.TestCase):
self.assertEqual(events_output[int((_redlight_time+0.5)/DT_DMON)].names[0], EventName.promptDriverDistracted) self.assertEqual(events_output[int((_redlight_time+0.5)/DT_DMON)].names[0], EventName.promptDriverDistracted)
# 9. op engaged, model is extremely uncertain. driver first attentive, then distracted # 9. op engaged, model is extremely uncertain. driver first attentive, then distracted
# - should only pop the green alert about model uncertainty # - should pop a uncertain message first, then slowly into active green/orange, finally back to wheel touch but timer locked by orange
# - (note: this's just for sanity check, std output should never be this high)
def test_one_indecisive_model(self): def test_one_indecisive_model(self):
ds_vector = [msg_ATTENTIVE_UNCERTAIN] * int(_UNCERTAIN_SECONDS_TO_GREEN/DT_DMON) + \ ds_vector = [msg_ATTENTIVE_UNCERTAIN] * int(_UNCERTAIN_SECONDS_TO_GREEN/DT_DMON) + \
[msg_ATTENTIVE] * int(_DISTRACTED_SECONDS_TO_ORANGE/DT_DMON) + \ [msg_ATTENTIVE] * int(_DISTRACTED_SECONDS_TO_ORANGE/DT_DMON) + \
@ -205,9 +204,9 @@ class TestMonitoring(unittest.TestCase):
interaction_vector = always_false[:] interaction_vector = always_false[:]
events_output = run_DState_seq(ds_vector, interaction_vector, always_true, always_false)[0] events_output = run_DState_seq(ds_vector, interaction_vector, always_true, always_false)[0]
self.assertTrue(len(events_output[int(_UNCERTAIN_SECONDS_TO_GREEN*0.5/DT_DMON)]) == 0) self.assertTrue(len(events_output[int(_UNCERTAIN_SECONDS_TO_GREEN*0.5/DT_DMON)]) == 0)
self.assertEqual(events_output[int((_UNCERTAIN_SECONDS_TO_GREEN-0.1)/DT_DMON)].names[0], EventName.driverMonitorLowAcc) self.assertEqual(events_output[int((_HI_STD_TIMEOUT)/DT_DMON)].names[0], EventName.driverMonitorLowAcc)
self.assertTrue(len(events_output[int((_UNCERTAIN_SECONDS_TO_GREEN+_DISTRACTED_SECONDS_TO_ORANGE-0.5)/DT_DMON)]) == 0) self.assertTrue(len(events_output[int((_UNCERTAIN_SECONDS_TO_GREEN+_DISTRACTED_SECONDS_TO_ORANGE-0.5)/DT_DMON)]) == 0)
self.assertEqual(events_output[int((_TEST_TIMESPAN-5.)/DT_DMON)].names[0], EventName.driverMonitorLowAcc) self.assertTrue(EventName.promptDriverDistracted in events_output[int((_TEST_TIMESPAN-5.)/DT_DMON)].names)
# 10. op engaged, model is somehow uncertain and driver is distracted # 10. op engaged, model is somehow uncertain and driver is distracted
# - should slow down the alert countdown but it still gets there # - should slow down the alert countdown but it still gets there
@ -216,9 +215,9 @@ class TestMonitoring(unittest.TestCase):
interaction_vector = always_false[:] interaction_vector = always_false[:]
events_output = run_DState_seq(ds_vector, interaction_vector, always_true, always_false)[0] events_output = run_DState_seq(ds_vector, interaction_vector, always_true, always_false)[0]
self.assertTrue(len(events_output[int(_UNCERTAIN_SECONDS_TO_GREEN*0.5/DT_DMON)]) == 0) self.assertTrue(len(events_output[int(_UNCERTAIN_SECONDS_TO_GREEN*0.5/DT_DMON)]) == 0)
self.assertEqual(events_output[int((_UNCERTAIN_SECONDS_TO_GREEN)/DT_DMON)].names[0], EventName.driverMonitorLowAcc) self.assertEqual(events_output[int((_HI_STD_TIMEOUT)/DT_DMON)].names[0], EventName.driverMonitorLowAcc)
self.assertEqual(events_output[int((2.5*(_DISTRACTED_TIME-_DISTRACTED_PRE_TIME_TILL_TERMINAL))/DT_DMON)].names[1], EventName.preDriverDistracted) self.assertTrue(EventName.preDriverDistracted in events_output[int((2*(_DISTRACTED_TIME-_DISTRACTED_PRE_TIME_TILL_TERMINAL))/DT_DMON)].names)
self.assertEqual(events_output[int((2.5*(_DISTRACTED_TIME-_DISTRACTED_PROMPT_TIME_TILL_TERMINAL))/DT_DMON)].names[1], EventName.promptDriverDistracted) self.assertTrue(EventName.promptDriverDistracted in events_output[int((2*(_DISTRACTED_TIME-_DISTRACTED_PROMPT_TIME_TILL_TERMINAL))/DT_DMON)].names)
self.assertEqual(events_output[int((_DISTRACTED_TIME+1)/DT_DMON)].names[1], EventName.promptDriverDistracted) self.assertEqual(events_output[int((_DISTRACTED_TIME+1)/DT_DMON)].names[1], EventName.promptDriverDistracted)
self.assertEqual(events_output[int((_DISTRACTED_TIME*2.5)/DT_DMON)].names[1], EventName.promptDriverDistracted) # set_timer blocked self.assertEqual(events_output[int((_DISTRACTED_TIME*2.5)/DT_DMON)].names[1], EventName.promptDriverDistracted) # set_timer blocked

@ -1 +1 @@
5c2c99c4572d68f17ffa3a33acf8e4e205ca94c2 45b676ebf79e402b5482b5fbadcc8147fdb8a1f8
Loading…
Cancel
Save