import  math 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  numpy  as  np 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  common . numpy_fast  import  interp 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  common . realtime  import  sec_since_boot 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  selfdrive . modeld . constants  import  T_IDXS 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  selfdrive . controls . lib . radar_helpers  import  _LEAD_ACCEL_TAU 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  selfdrive . controls . lib . lead_mpc_lib  import  libmpc_py 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  selfdrive . controls . lib . drive_helpers  import  MPC_COST_LONG ,  CONTROL_N 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  selfdrive . swaglog  import  cloudlog 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								MPC_T  =  list ( np . arange ( 0 , 1. , .2 ) )  +  list ( np . arange ( 1. , 10.6 , .6 ) ) 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  LeadMpc ( ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  __init__ ( self ,  mpc_id ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . lead_id  =  mpc_id 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . reset_mpc ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . prev_lead_status  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . prev_lead_x  =  0.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . new_lead  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . last_cloudlog_t  =  0.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . n_its  =  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . duration  =  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . status  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . v_solution  =  np . zeros ( CONTROL_N ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . a_solution  =  np . zeros ( CONTROL_N ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . j_solution  =  np . zeros ( CONTROL_N ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  reset_mpc ( self ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ffi ,  self . libmpc  =  libmpc_py . get_libmpc ( self . lead_id ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . libmpc . init ( MPC_COST_LONG . TTC ,  MPC_COST_LONG . DISTANCE , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     MPC_COST_LONG . ACCELERATION ,  MPC_COST_LONG . JERK ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . mpc_solution  =  ffi . new ( " log_t * " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . cur_state  =  ffi . new ( " state_t * " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . cur_state [ 0 ] . v_ego  =  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . cur_state [ 0 ] . a_ego  =  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . a_lead_tau  =  _LEAD_ACCEL_TAU 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  set_cur_state ( self ,  v ,  a ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    v_safe  =  max ( v ,  1e-3 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    a_safe  =  a 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . cur_state [ 0 ] . v_ego  =  v_safe 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . cur_state [ 0 ] . a_ego  =  a_safe 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  update ( self ,  CS ,  radarstate ,  v_cruise ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    v_ego  =  CS . vEgo 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . lead_id  ==  0 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      lead  =  radarstate . leadOne 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      lead  =  radarstate . leadTwo 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . status  =  lead . status 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Setup current mpc state 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . cur_state [ 0 ] . x_ego  =  0.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  lead  is  not  None  and  lead . status : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      x_lead  =  lead . dRel 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      v_lead  =  max ( 0.0 ,  lead . vLead ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      a_lead  =  lead . aLeadK 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( v_lead  <  0.1  or  - a_lead  /  2.0  >  v_lead ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        v_lead  =  0.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        a_lead  =  0.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . a_lead_tau  =  lead . aLeadTau 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . new_lead  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  not  self . prev_lead_status  or  abs ( x_lead  -  self . prev_lead_x )  >  2.5 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . libmpc . init_with_simulation ( v_ego ,  x_lead ,  v_lead ,  a_lead ,  self . a_lead_tau ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . new_lead  =  True 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . prev_lead_status  =  True 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . prev_lead_x  =  x_lead 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . cur_state [ 0 ] . x_l  =  x_lead 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . cur_state [ 0 ] . v_l  =  v_lead 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . prev_lead_status  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # Fake a fast lead car, so mpc keeps running 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . cur_state [ 0 ] . x_l  =  50.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . cur_state [ 0 ] . v_l  =  v_ego  +  10.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      a_lead  =  0.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . a_lead_tau  =  _LEAD_ACCEL_TAU 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Calculate mpc 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    t  =  sec_since_boot ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . n_its  =  self . libmpc . run_mpc ( self . cur_state ,  self . mpc_solution ,  self . a_lead_tau ,  a_lead ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . v_solution  =  interp ( T_IDXS [ : CONTROL_N ] ,  MPC_T ,  self . mpc_solution . v_ego ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . a_solution  =  interp ( T_IDXS [ : CONTROL_N ] ,  MPC_T ,  self . mpc_solution . a_ego ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . j_solution  =  interp ( T_IDXS [ : CONTROL_N ] ,  MPC_T [ : - 1 ] ,  self . mpc_solution . j_ego ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . duration  =  int ( ( sec_since_boot ( )  -  t )  *  1e9 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Reset if NaN or goes through lead car 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    crashing  =  any ( lead  -  ego  <  - 50  for  ( lead ,  ego )  in  zip ( self . mpc_solution [ 0 ] . x_l ,  self . mpc_solution [ 0 ] . x_ego ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    nans  =  any ( math . isnan ( x )  for  x  in  self . mpc_solution [ 0 ] . v_ego ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    backwards  =  min ( self . mpc_solution [ 0 ] . v_ego )  <  - 0.15 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( backwards  or  crashing )  and  self . prev_lead_status )  or  nans : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  t  >  self . last_cloudlog_t  +  5.0 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . last_cloudlog_t  =  t 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        cloudlog . warning ( " Longitudinal mpc  %d  reset - backwards:  %s  crashing:  %s  nan:  %s "  %  ( 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                          self . lead_id ,  backwards ,  crashing ,  nans ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . libmpc . init ( MPC_COST_LONG . TTC ,  MPC_COST_LONG . DISTANCE , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       MPC_COST_LONG . ACCELERATION ,  MPC_COST_LONG . JERK ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . cur_state [ 0 ] . v_ego  =  v_ego 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . cur_state [ 0 ] . a_ego  =  0.0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . a_mpc  =  CS . aEgo 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . prev_lead_status  =  False