#!/usr/bin/env python3 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  unittest 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  numpy  as  np 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  cereal  import  log 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  cereal . messaging  as  messaging 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  selfdrive . config  import  Conversions  as  CV 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								from  selfdrive . controls . lib . lead_mpc  import  LeadMpc 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  RW ( v_ego ,  v_l ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  TR  =  1.8 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  G  =  9.81 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  ( v_ego  *  TR  -  ( v_l  -  v_ego )  *  TR  +  v_ego  *  v_ego  /  ( 2  *  G )  -  v_l  *  v_l  /  ( 2  *  G ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								class  FakePubMaster ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  def  send ( self ,  s ,  data ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    assert  data 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  run_following_distance_simulation ( v_lead ,  t_end = 200.0 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  dt  =  0.2 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  t  =  0. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  x_lead  =  200.0 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  x_ego  =  0.0 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  v_ego  =  v_lead 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  a_ego  =  0.0 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  mpc  =  LeadMpc ( 0 ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  first  =  True 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  while  t  <  t_end : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Setup CarState 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    CS  =  messaging . new_message ( ' carState ' ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CS . carState . vEgo  =  v_ego 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CS . carState . aEgo  =  a_ego 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # Setup model packet 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    radarstate  =  messaging . new_message ( ' radarState ' ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    lead  =  log . RadarState . LeadData . new_message ( ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    lead . modelProb  =  .75 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    lead . dRel  =  x_lead  -  x_ego 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    lead . vLead  =  v_lead 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    lead . aLeadK  =  0.0 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    lead . status  =  True 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    radarstate . radarState . leadOne  =  lead 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Run MPC 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    mpc . set_cur_state ( v_ego ,  a_ego ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  first :   # Make sure MPC is converged on first timestep 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      for  _  in  range ( 20 ) : 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        mpc . update ( CS . carState ,  radarstate . radarState ,  0 ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    mpc . update ( CS . carState ,  radarstate . radarState ,  0 ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Choose slowest of two solutions 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    v_ego ,  a_ego  =  mpc . mpc_solution . v_ego [ 5 ] ,  mpc . mpc_solution . a_ego [ 5 ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Update state 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    x_lead  + =  v_lead  *  dt 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    x_ego  + =  v_ego  *  dt 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    t  + =  dt 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    first  =  False 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  x_lead  -  x_ego 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								class  TestFollowingDistance ( unittest . TestCase ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  def  test_following_distanc ( self ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  speed_mph  in  np . linspace ( 10 ,  100 ,  num = 10 ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      v_lead  =  float ( speed_mph  *  CV . MPH_TO_MS ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      simulation_steady_state  =  run_following_distance_simulation ( v_lead ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      correct_steady_state  =  RW ( v_lead ,  v_lead )  +  4.0 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      self . assertAlmostEqual ( simulation_steady_state ,  correct_steady_state ,  delta = .1 ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								if  __name__  ==  " __main__ " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  unittest . main ( )