# functions common among cars 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  capnp 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  cereal  import  car 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  common . numpy_fast  import  clip 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  typing  import  Dict ,  List 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# kg of standard extra cargo to count for drive, gas, etc... 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								STD_CARGO_KG  =  136. 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								ButtonType  =  car . CarState . ButtonEvent . Type 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								EventName  =  car . CarEvent . EventName 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  create_button_event ( cur_but :  int ,  prev_but :  int ,  buttons_dict :  Dict [ int ,  capnp . lib . capnp . _EnumModule ] , 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        unpressed :  int  =  0 )  - >  capnp . lib . capnp . _DynamicStructBuilder : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  cur_but  !=  unpressed : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    be  =  car . CarState . ButtonEvent ( pressed = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    but  =  cur_but 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    be  =  car . CarState . ButtonEvent ( pressed = False ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    but  =  prev_but 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  be . type  =  buttons_dict . get ( but ,  ButtonType . unknown ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  be 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  create_button_enable_events ( buttonEvents :  capnp . lib . capnp . _DynamicListBuilder ,  pcm_cruise :  bool  =  False )  - >  List [ int ] : 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  events  =  [ ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  b  in  buttonEvents : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # do enable on both accel and decel buttons 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  not  pcm_cruise : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  b . type  in  ( ButtonType . accelCruise ,  ButtonType . decelCruise )  and  not  b . pressed : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        events . append ( EventName . buttonEnable ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # do disable on button down 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  b . type  ==  ButtonType . cancel  and  b . pressed : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      events . append ( EventName . buttonCancel ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  events 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  gen_empty_fingerprint ( ) : 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  return  { i :  { }  for  i  in  range ( 0 ,  8 ) } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# FIXME: hardcoding honda civic 2016 touring params so they can be used to 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# scale unknown params for other cars 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  CivicParams : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  MASS  =  1326.  +  STD_CARGO_KG 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  WHEELBASE  =  2.70 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  CENTER_TO_FRONT  =  WHEELBASE  *  0.4 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  CENTER_TO_REAR  =  WHEELBASE  -  CENTER_TO_FRONT 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ROTATIONAL_INERTIA  =  2500 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  TIRE_STIFFNESS_FRONT  =  192150 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  TIRE_STIFFNESS_REAR  =  202500 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# TODO: get actual value, for now starting with reasonable value for 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# civic and scaling by mass and wheelbase 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  scale_rot_inertia ( mass ,  wheelbase ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  CivicParams . ROTATIONAL_INERTIA  *  mass  *  wheelbase  * *  2  /  ( CivicParams . MASS  *  CivicParams . WHEELBASE  * *  2 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# TODO: start from empirically derived lateral slip stiffness for the civic and scale by 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# mass and CG position, so all cars will have approximately similar dyn behaviors 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  scale_tire_stiffness ( mass ,  wheelbase ,  center_to_front ,  tire_stiffness_factor = 1.0 ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  center_to_rear  =  wheelbase  -  center_to_front 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  tire_stiffness_front  =  ( CivicParams . TIRE_STIFFNESS_FRONT  *  tire_stiffness_factor )  *  mass  /  CivicParams . MASS  *  \
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         ( center_to_rear  /  wheelbase )  /  ( CivicParams . CENTER_TO_REAR  /  CivicParams . WHEELBASE ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  tire_stiffness_rear  =  ( CivicParams . TIRE_STIFFNESS_REAR  *  tire_stiffness_factor )  *  mass  /  CivicParams . MASS  *  \
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        ( center_to_front  /  wheelbase )  /  ( CivicParams . CENTER_TO_FRONT  /  CivicParams . WHEELBASE ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  tire_stiffness_front ,  tire_stiffness_rear 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  dbc_dict ( pt_dbc ,  radar_dbc ,  chassis_dbc = None ,  body_dbc = None )  - >  Dict [ str ,  str ] : 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  return  { ' pt ' :  pt_dbc ,  ' radar ' :  radar_dbc ,  ' chassis ' :  chassis_dbc ,  ' body ' :  body_dbc } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  apply_std_steer_torque_limits ( apply_torque ,  apply_torque_last ,  driver_torque ,  LIMITS ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # limits due to driver torque 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  driver_max_torque  =  LIMITS . STEER_MAX  +  ( LIMITS . STEER_DRIVER_ALLOWANCE  +  driver_torque  *  LIMITS . STEER_DRIVER_FACTOR )  *  LIMITS . STEER_DRIVER_MULTIPLIER 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  driver_min_torque  =  - LIMITS . STEER_MAX  +  ( - LIMITS . STEER_DRIVER_ALLOWANCE  +  driver_torque  *  LIMITS . STEER_DRIVER_FACTOR )  *  LIMITS . STEER_DRIVER_MULTIPLIER 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  max_steer_allowed  =  max ( min ( LIMITS . STEER_MAX ,  driver_max_torque ) ,  0 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  min_steer_allowed  =  min ( max ( - LIMITS . STEER_MAX ,  driver_min_torque ) ,  0 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  apply_torque  =  clip ( apply_torque ,  min_steer_allowed ,  max_steer_allowed ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # slow rate if steer torque increases in magnitude 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  apply_torque_last  >  0 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    apply_torque  =  clip ( apply_torque ,  max ( apply_torque_last  -  LIMITS . STEER_DELTA_DOWN ,  - LIMITS . STEER_DELTA_UP ) , 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        apply_torque_last  +  LIMITS . STEER_DELTA_UP ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    apply_torque  =  clip ( apply_torque ,  apply_torque_last  -  LIMITS . STEER_DELTA_UP , 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        min ( apply_torque_last  +  LIMITS . STEER_DELTA_DOWN ,  LIMITS . STEER_DELTA_UP ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  int ( round ( float ( apply_torque ) ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  apply_toyota_steer_torque_limits ( apply_torque ,  apply_torque_last ,  motor_torque ,  LIMITS ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # limits due to comparison of commanded torque VS motor reported torque 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  max_lim  =  min ( max ( motor_torque  +  LIMITS . STEER_ERROR_MAX ,  LIMITS . STEER_ERROR_MAX ) ,  LIMITS . STEER_MAX ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  min_lim  =  max ( min ( motor_torque  -  LIMITS . STEER_ERROR_MAX ,  - LIMITS . STEER_ERROR_MAX ) ,  - LIMITS . STEER_MAX ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  apply_torque  =  clip ( apply_torque ,  min_lim ,  max_lim ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # slow rate if steer torque increases in magnitude 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  apply_torque_last  >  0 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    apply_torque  =  clip ( apply_torque , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        max ( apply_torque_last  -  LIMITS . STEER_DELTA_DOWN ,  - LIMITS . STEER_DELTA_UP ) , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        apply_torque_last  +  LIMITS . STEER_DELTA_UP ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    apply_torque  =  clip ( apply_torque , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        apply_torque_last  -  LIMITS . STEER_DELTA_UP , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        min ( apply_torque_last  +  LIMITS . STEER_DELTA_DOWN ,  LIMITS . STEER_DELTA_UP ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  int ( round ( float ( apply_torque ) ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  crc8_pedal ( data ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  crc  =  0xFF     # standard init value 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  poly  =  0xD5    # standard crc8: x8+x7+x6+x4+x2+1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size  =  len ( data ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  for  i  in  range ( size  -  1 ,  - 1 ,  - 1 ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    crc  ^ =  data [ i ] 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    for  _  in  range ( 8 ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ( crc  &  0x80 )  !=  0 ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        crc  =  ( ( crc  <<  1 )  ^  poly )  &  0xFF 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        crc  << =  1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  crc 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  create_gas_interceptor_command ( packer ,  gas_amount ,  idx ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # Common gas pedal msg generator 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  enable  =  gas_amount  >  0.001 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  values  =  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    " ENABLE " :  enable , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    " COUNTER_PEDAL " :  idx  &  0xF , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  enable : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    values [ " GAS_COMMAND " ]  =  gas_amount  *  255. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    values [ " GAS_COMMAND2 " ]  =  gas_amount  *  255. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  dat  =  packer . make_can_msg ( " GAS_COMMAND " ,  0 ,  values ) [ 2 ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  checksum  =  crc8_pedal ( dat [ : - 1 ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  values [ " CHECKSUM_PEDAL " ]  =  checksum 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  packer . make_can_msg ( " GAS_COMMAND " ,  0 ,  values ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  make_can_msg ( addr ,  dat ,  bus ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  [ addr ,  0 ,  dat ,  bus ] 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  get_safety_config ( safety_model ,  safety_param  =  None ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ret  =  car . CarParams . SafetyConfig . new_message ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ret . safetyModel  =  safety_model 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  safety_param  is  not  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . safetyParam  =  safety_param 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  ret