import  numpy  as  np 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  collections  import  defaultdict 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  common . numpy_fast  import  interp 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								_FCW_A_ACT_V  =  [ - 3. ,  - 2. ] 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								_FCW_A_ACT_BP  =  [ 0. ,  30. ] 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								class  FCWChecker ( ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  __init__ ( self ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . reset_lead ( 0.0 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  reset_lead ( self ,  cur_time ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . last_fcw_a  =  0.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . v_lead_max  =  0.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . lead_seen_t  =  cur_time 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . last_fcw_time  =  0.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . last_min_a  =  0.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . counters  =  defaultdict ( lambda :  0 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  @staticmethod 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  calc_ttc ( v_ego ,  a_ego ,  x_lead ,  v_lead ,  a_lead ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    max_ttc  =  5.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    v_rel  =  v_ego  -  v_lead 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    a_rel  =  a_ego  -  a_lead 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # assuming that closing gap ARel comes from lead vehicle decel, 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # then limit ARel so that v_lead will get to zero in no sooner than t_decel. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # This helps underweighting ARel when v_lead is close to zero. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    t_decel  =  2. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    a_rel  =  np . minimum ( a_rel ,  v_lead  /  t_decel ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # delta of the quadratic equation to solve for ttc 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    delta  =  v_rel * * 2  +  2  *  x_lead  *  a_rel 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # assign an arbitrary high ttc value if there is no solution to ttc 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  delta  <  0.1  or  ( np . sqrt ( delta )  +  v_rel  <  0.1 ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ttc  =  max_ttc 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ttc  =  np . minimum ( 2  *  x_lead  /  ( np . sqrt ( delta )  +  v_rel ) ,  max_ttc ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  ttc 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  update ( self ,  mpc_solution ,  cur_time ,  active ,  v_ego ,  a_ego ,  x_lead ,  v_lead ,  a_lead ,  y_lead ,  vlat_lead ,  fcw_lead ,  blinkers ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    mpc_solution_a  =  list ( mpc_solution [ 0 ] . a_ego ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . last_min_a  =  min ( mpc_solution_a ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . v_lead_max  =  max ( self . v_lead_max ,  v_lead ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( fcw_lead  >  0.99 ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ttc  =  self . calc_ttc ( v_ego ,  a_ego ,  x_lead ,  v_lead ,  a_lead ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . counters [ ' v_ego ' ]  =  self . counters [ ' v_ego ' ]  +  1  if  v_ego  >  5.0  else  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . counters [ ' ttc ' ]  =  self . counters [ ' ttc ' ]  +  1  if  ttc  <  2.5  else  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . counters [ ' v_lead_max ' ]  =  self . counters [ ' v_lead_max ' ]  +  1  if  self . v_lead_max  >  2.5  else  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . counters [ ' v_ego_lead ' ]  =  self . counters [ ' v_ego_lead ' ]  +  1  if  v_ego  >  v_lead  else  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . counters [ ' lead_seen ' ]  =  self . counters [ ' lead_seen ' ]  +  0.33 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . counters [ ' y_lead ' ]  =  self . counters [ ' y_lead ' ]  +  1  if  abs ( y_lead )  <  1.0  else  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . counters [ ' vlat_lead ' ]  =  self . counters [ ' vlat_lead ' ]  +  1  if  abs ( vlat_lead )  <  0.4  else  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . counters [ ' blinkers ' ]  =  self . counters [ ' blinkers ' ]  +  10.0  /  ( 20  *  3.0 )  if  not  blinkers  else  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      a_thr  =  interp ( v_lead ,  _FCW_A_ACT_BP ,  _FCW_A_ACT_V ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      a_delta  =  min ( mpc_solution_a [ : 15 ] )  -  min ( 0.0 ,  a_ego ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      future_fcw_allowed  =  all ( c  > =  10  for  c  in  self . counters . values ( ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      future_fcw  =  ( self . last_min_a  <  - 3.0  or  a_delta  <  a_thr )  and  future_fcw_allowed 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      if  future_fcw  and  ( self . last_fcw_time  +  5.0  <  cur_time ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . last_fcw_time  =  cur_time 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . last_fcw_a  =  self . last_min_a 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  True 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  False