1- from math import atan2
1+ from math import atan2 , radians
22import numpy as np
33
44from cereal import car , log
@@ -43,6 +43,9 @@ def __init__(self, device_type):
4343 self ._POSE_YAW_THRESHOLD = 0.4020
4444 self ._POSE_YAW_THRESHOLD_SLACK = 0.5042
4545 self ._POSE_YAW_THRESHOLD_STRICT = self ._POSE_YAW_THRESHOLD
46+ self ._POSE_YAW_MIN_STEER_DEG = 30
47+ self ._POSE_YAW_STEER_FACTOR = 0.15
48+ self ._POSE_YAW_STEER_MAX_OFFSET = 0.3927
4649 self ._PITCH_NATURAL_OFFSET = 0.011 # initial value before offset is learned
4750 self ._PITCH_NATURAL_THRESHOLD = 0.449
4851 self ._YAW_NATURAL_OFFSET = 0.075 # initial value before offset is learned
@@ -59,7 +62,6 @@ def __init__(self, device_type):
5962 self ._POSESTD_THRESHOLD = 0.3
6063 self ._HI_STD_FALLBACK_TIME = int (10 / self ._DT_DMON ) # fall back to wheel touch if model is uncertain for 10s
6164 self ._DISTRACTED_FILTER_TS = 0.25 # 0.6Hz
62- self ._ALWAYS_ON_ALERT_MIN_SPEED = 11
6365
6466 self ._POSE_CALIB_MIN_SPEED = 13 # 30 mph
6567 self ._POSE_OFFSET_MIN_COUNT = int (60 / self ._DT_DMON ) # valid data counts before calibration completes, 1min cumulative
@@ -101,6 +103,7 @@ def __init__(self, settings):
101103 self .low_std = True
102104 self .cfactor_pitch = 1.
103105 self .cfactor_yaw = 1.
106+ self .steer_yaw_offset = 0.
104107
105108class DriverProb :
106109 def __init__ (self , raw_priors , max_trackable ):
@@ -238,7 +241,11 @@ def _get_distracted_types(self):
238241 yaw_error = self .pose .yaw - min (max (self .pose .yaw_offseter .filtered_stat .mean (),
239242 self .settings ._YAW_MIN_OFFSET ), self .settings ._YAW_MAX_OFFSET )
240243 pitch_error = 0 if pitch_error > 0 else abs (pitch_error ) # no positive pitch limit
241- yaw_error = abs (yaw_error )
244+
245+ if yaw_error * self .pose .steer_yaw_offset > 0 : # unidirectional
246+ yaw_error = max (abs (yaw_error ) - min (abs (self .pose .steer_yaw_offset ), self .settings ._POSE_YAW_STEER_MAX_OFFSET ), 0. )
247+ else :
248+ yaw_error = abs (yaw_error )
242249
243250 pitch_threshold = self .settings ._POSE_PITCH_THRESHOLD * self .pose .cfactor_pitch if self .pose .calibrated else self .settings ._PITCH_NATURAL_THRESHOLD
244251 yaw_threshold = self .settings ._POSE_YAW_THRESHOLD * self .pose .cfactor_yaw
@@ -254,7 +261,7 @@ def _get_distracted_types(self):
254261
255262 return distracted_types
256263
257- def _update_states (self , driver_state , cal_rpy , car_speed , op_engaged , standstill , demo_mode = False ):
264+ def _update_states (self , driver_state , cal_rpy , car_speed , op_engaged , standstill , demo_mode = False , steering_angle_deg = 0. ):
258265 rhd_pred = driver_state .wheelOnRightProb
259266 # calibrates only when there's movement and either face detected
260267 if car_speed > self .settings ._WHEELPOS_CALIB_MIN_SPEED and (driver_state .leftDriverData .faceProb > self .settings ._FACE_THRESHOLD or
@@ -277,8 +284,11 @@ def _update_states(self, driver_state, cal_rpy, car_speed, op_engaged, standstil
277284
278285 self .face_detected = driver_data .faceProb > self .settings ._FACE_THRESHOLD
279286 self .pose .roll , self .pose .pitch , self .pose .yaw = face_orientation_from_net (driver_data .faceOrientation , driver_data .facePosition , cal_rpy )
287+ steer_d = max (abs (steering_angle_deg ) - self .settings ._POSE_YAW_MIN_STEER_DEG , 0. )
288+ self .pose .steer_yaw_offset = radians (steer_d ) * - np .sign (steering_angle_deg ) * self .settings ._POSE_YAW_STEER_FACTOR
280289 if self .wheel_on_right :
281290 self .pose .yaw *= - 1
291+ self .pose .steer_yaw_offset *= - 1
282292 self .wheel_on_right_last = self .wheel_on_right
283293 self .pose .pitch_std = driver_data .faceOrientationStd [0 ]
284294 self .pose .yaw_std = driver_data .faceOrientationStd [1 ]
@@ -360,19 +370,19 @@ def _update_events(self, driver_engaged, op_engaged, standstill, wrong_gear, car
360370 if self .awareness > self .threshold_prompt :
361371 return
362372
373+ _reaching_pre = self .awareness - self .step_change <= self .threshold_pre
363374 _reaching_audible = self .awareness - self .step_change <= self .threshold_prompt
364375 _reaching_terminal = self .awareness - self .step_change <= 0
365- standstill_orange_exemption = standstill and _reaching_audible
376+ standstill_exemption = standstill and _reaching_pre
366377 always_on_red_exemption = always_on_valid and not op_engaged and _reaching_terminal
367- always_on_lowspeed_exemption = always_on_valid and not op_engaged and car_speed < self .settings ._ALWAYS_ON_ALERT_MIN_SPEED
368378
369379 certainly_distracted = self .driver_distraction_filter .x > 0.63 and self .driver_distracted and self .face_detected
370380 maybe_distracted = self .hi_stds > self .settings ._HI_STD_FALLBACK_TIME or not self .face_detected
371381
372382 if certainly_distracted or maybe_distracted :
373- # should always be counting if distracted unless at standstill (lowspeed for always-on) and reaching orange
383+ # should always be counting if distracted unless at standstill and reaching green
374384 # also will not be reaching 0 if DM is active when not engaged
375- if not (standstill_orange_exemption or always_on_red_exemption or ( always_on_lowspeed_exemption and _reaching_audible ) ):
385+ if not (standstill_exemption or always_on_red_exemption ):
376386 self .awareness = max (self .awareness - self .step_change , - 0.1 )
377387
378388 alert = None
@@ -385,7 +395,7 @@ def _update_events(self, driver_engaged, op_engaged, standstill, wrong_gear, car
385395 elif self .awareness <= self .threshold_prompt :
386396 # prompt orange alert
387397 alert = EventName .promptDriverDistracted if self .active_monitoring_mode else EventName .promptDriverUnresponsive
388- elif self .awareness <= self .threshold_pre and not always_on_lowspeed_exemption :
398+ elif self .awareness <= self .threshold_pre :
389399 # pre green alert
390400 alert = EventName .preDriverDistracted if self .active_monitoring_mode else EventName .preDriverUnresponsive
391401
@@ -451,6 +461,7 @@ def run_step(self, sm, demo=False):
451461 op_engaged = enabled ,
452462 standstill = standstill ,
453463 demo_mode = demo ,
464+ steering_angle_deg = sm ['carState' ].steeringAngleDeg ,
454465 )
455466
456467 # Update distraction events
0 commit comments