from cereal import log
from openpilot . common . realtime import DT_CTRL
from openpilot . common . constants import CV
CAMERA_OFFSET = 0.04
LDW_MIN_SPEED = 31 * CV . MPH_TO_MS
LANE_DEPARTURE_THRESHOLD = 0.1
class LaneDepartureWarning :
def __init__ ( self ) :
self . left = False
self . right = False
self . last_blinker_frame = 0
def update ( self , frame , modelV2 , CS , CC ) :
if CS . leftBlinker or CS . rightBlinker :
self . last_blinker_frame = frame
recent_blinker = ( frame - self . last_blinker_frame ) * DT_CTRL < 5.0 # 5s blinker cooldown
ldw_allowed = CS . vEgo > LDW_MIN_SPEED and not recent_blinker and not CC . latActive
desire_prediction = modelV2 . meta . desirePrediction
if len ( desire_prediction ) and ldw_allowed :
right_lane_visible = modelV2 . laneLineProbs [ 2 ] > 0.5
left_lane_visible = modelV2 . laneLineProbs [ 1 ] > 0.5
l_lane_change_prob = desire_prediction [ log . Desire . laneChangeLeft ]
r_lane_change_prob = desire_prediction [ log . Desire . laneChangeRight ]
lane_lines = modelV2 . laneLines
l_lane_close = left_lane_visible and ( lane_lines [ 1 ] . y [ 0 ] > - ( 1.08 + CAMERA_OFFSET ) )
r_lane_close = right_lane_visible and ( lane_lines [ 2 ] . y [ 0 ] < ( 1.08 - CAMERA_OFFSET ) )
self . left = bool ( l_lane_change_prob > LANE_DEPARTURE_THRESHOLD and l_lane_close )
self . right = bool ( r_lane_change_prob > LANE_DEPARTURE_THRESHOLD and r_lane_close )
else :
self . left , self . right = False , False
@property
def warning ( self ) - > bool :
return bool ( self . left or self . right )