#!/usr/bin/env python3 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  os 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  time 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  threading 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  cereal . messaging  as  messaging 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  cereal  import  car ,  log 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  openpilot . common . params  import  Params 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  openpilot . common . realtime  import  config_realtime_process ,  Priority ,  Ratekeeper 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  openpilot . common . swaglog  import  cloudlog ,  ForwardingHandler 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  opendbc . car  import  DT_CTRL ,  structs 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  opendbc . car . can_definitions  import  CanData ,  CanRecvCallable ,  CanSendCallable 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  opendbc . car . carlog  import  carlog 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  opendbc . car . fw_versions  import  ObdCallback 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  opendbc . car . car_helpers  import  get_car ,  interfaces 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  opendbc . car . interfaces  import  CarInterfaceBase ,  RadarInterfaceBase 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  openpilot . selfdrive . pandad  import  can_capnp_to_list ,  can_list_to_can_capnp 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  openpilot . selfdrive . car . cruise  import  VCruiseHelper 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  openpilot . selfdrive . car . car_specific  import  MockCarState 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								REPLAY  =  " REPLAY "  in  os . environ 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								EventName  =  log . OnroadEvent . EventName 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								# forward 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								carlog . addHandler ( ForwardingHandler ( cloudlog ) ) 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  obd_callback ( params :  Params )  - >  ObdCallback : 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  set_obd_multiplexing ( obd_multiplexing :  bool ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  params . get_bool ( " ObdMultiplexingEnabled " )  !=  obd_multiplexing : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . warning ( f " Setting OBD multiplexing to  { obd_multiplexing } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      params . remove ( " ObdMultiplexingChanged " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      params . put_bool ( " ObdMultiplexingEnabled " ,  obd_multiplexing ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      params . get_bool ( " ObdMultiplexingChanged " ,  block = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . warning ( " OBD multiplexing set successfully " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  set_obd_multiplexing 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  can_comm_callbacks ( logcan :  messaging . SubSocket ,  sendcan :  messaging . PubSocket )  - >  tuple [ CanRecvCallable ,  CanSendCallable ] : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  can_recv ( wait_for_one :  bool  =  False )  - >  list [ list [ CanData ] ] : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    wait_for_one :  wait  the  normal  logcan  socket  timeout  for  a  CAN  packet ,  may  return  empty  list  if  nothing  comes 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Returns :  CAN  packets  comprised  of  CanData  objects  for  easy  access 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret  =  [ ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  can  in  messaging . drain_sock ( logcan ,  wait_for_one = wait_for_one ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ret . append ( [ CanData ( msg . address ,  msg . dat ,  msg . src )  for  msg  in  can . can ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  ret 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  can_send ( msgs :  list [ CanData ] )  - >  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    sendcan . send ( can_list_to_can_capnp ( msgs ,  msgtype = ' sendcan ' ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  can_recv ,  can_send 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								class  Car : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  CI :  CarInterfaceBase 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  RI :  RadarInterfaceBase 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  CP :  car . CarParams 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  __init__ ( self ,  CI = None ,  RI = None )  - >  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . can_sock  =  messaging . sub_sock ( ' can ' ,  timeout = 20 ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . sm  =  messaging . SubMaster ( [ ' pandaStates ' ,  ' carControl ' ,  ' onroadEvents ' ] ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . pm  =  messaging . PubMaster ( [ ' sendcan ' ,  ' carState ' ,  ' carParams ' ,  ' carOutput ' ,  ' liveTracks ' ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . can_rcv_cum_timeout_counter  =  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . CC_prev  =  car . CarControl . new_message ( ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . CS_prev  =  car . CarState . new_message ( ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . initialized_prev  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												selfdrive/car: ban cereal and capnp (#33208)
* ban cereal and msgq
* common too
* do toyota/values.py
* do all fingerprints
* example without builder
* this still works, but no type checking anymore
* stash
* wtf, how does this work
* okay actually not bad
* safe
* epic!
* stash data_structures.py
* some clean up
* hell yeah
* clean up old file
* add to delete
* delete
This reverts commit 90239b7797ace31ee647a2fdbd67e0c3faa98dcf.
* switch more CarParams stuff over
remove unused
* fix car tests by removing cereal! mypy forgets about dataclass if we wrap it :(
* fix this too
* fix this too
* remove more cereal and add some good hyundai tests
* bunch more typing
* override default with 20hz radar
* temp capnp converter helper
* more lateralTuning
* small union replicator is better than what i was trying, and fixes mypy dynamic typing issues
* can keep all this the same now!
* type ret: CarParams, add more missing structs, revert lateralTuning changes (smaller diff!)
* revert more
* get first enum automatically, but ofc mypy doesn't pick up the new metaclass so can't use :(
would have been `CarParams.NetworkLocation()`
* Revert "get first enum automatically, but ofc mypy doesn't pick up the new metaclass so can't use :("
This reverts commit bb28b228becba932052d2fc5a4389784027435b1.
* remove cereal from car_helpers (TODO: caching)
* remove a bunch of temp lines
* use dataclass_transform!
* remove some car.CarParams from the interfaces
* remove rest of car.CarParams from the interfaces
* same which() API
* sort
* from cereal/cache from fingerprinting!
* more typing
* dataclass to capnp helper for CarParams, cached it since it's kinda slow
* (partial) fix process replay fingerprintig for new API
* latcontrollers take capnp
* forgot this
* fix test_models
* fix unit tests
* not here
* VehicleModel and controller still takes capnp CP since they get it from Params()
* fix modeld test
* more fix
* need to namespace to structs, since CarState is both class and struct
* this was never in the base class?!
* clean that up again
* fix import error
fix import error
* cmts and more structs
* remove some more cereal from toyota + convert CarState to capnp
* bruh this was wrong
* replace more cereal
* EventName is one of the last things...
* replace a bunch more cereal.car
* missing imports
* more
* can fix this typing now
* proper toyota+others CS typing!
* mypy can detect return type of CS.update() now
* fix redeclaration of cruise_buttons type
* mypy is only complaining about events now
* temp fix
* add carControl struct
* replace CarControl
i hope there's no circular imports in hyundai's CC
* fine now
* lol this was wrong too
* fix crash
* include my failed attempts at recursively converting to dataclass (doesn't implicitly convert types/recursively :( )
but attrs does, maybe will switch in the future
* clean up
* try out attr.s for its converter (doesn't work recursively yet, but interesting!)
* Revert "try out attr.s for its converter (doesn't work recursively yet, but interesting!)"
This reverts commit ff2434f7bbd45a4d4bfb21f7d6712d1f1c3bcde9.
* test processes doesn't fail anymore (on toyota)!
* fix honda crash
* stash
* Revert "stash"
This reverts commit c1762af4e776790e4ad1322ad4ce0610157346e0.
* remove a bunch more cereal!
* LET'S GOOO
* fix these tests
* and these
* and that
* stash, something is wrong with hyundai enable
* Revert "stash, something is wrong with hyundai enable"
This reverts commit 39cf327def258e2959fe23cd7a550a858f6d8f03.
* forgot these
* remove cereal from fw_versions
* Revert "remove cereal from fw_versions"
This reverts commit 232b37cd409b55d04b1afc90d4a80c49e710eb56.
* remove rest of the cereal exceptions!
* fix that
* add typing to radard since I didn't realize RI.update() switched from cereal to structs
* and here too!
* add TODO for slots
* needed CS to be capnp, fix comparisons, and type hint car_specific so it's easier to catch type issues (capnp isn't detected by mypy :( )
* remove the struct converter
* save ~4-5% CPU at 100hz, we don't modify after so no need to deepcopy
btw pickle.loads(pickle.dumps()) is faster by ~1% CPU
* deepcopy -> copy: we can technically make a reference, but copy is almost free and less error-prone
saves ~1% CPU
* add non-copying asdict function
* should save ~3% CPU (still 4% above baseline)
* fix that, no dict support
* ~27% decrease in time for 20k iterations on 3X (3.37857 -> 2.4821s)
* give a better name
* fix
* dont support none, capitalize
* sheesh, this called type() on every field
* remove CS.events, clean up
* bump card %
* this was a bug on master!
* add a which enum
* default to pid
* revert
* update refs
* not needed, but consistent
* just Ecu
* don't need to do this in this pr
* clean up
* no cast
* consistent typing
* rm
* fix
* can do this if we're desperate for the last few %
* Revert "can do this if we're desperate for the last few %"
This reverts commit 18e11ac7883a0a56583750b1cc5a2b13011e7299.
* type this
* don't need to convert carControl
* i guess don't support set either
* fix CP type hint
* simplify that
old-commit-hash: 6a15c42143a4764e79df851d797f950a6212f464
											 
										 
										
											1 year ago 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . last_actuators_output  =  structs . CarControl . Actuators ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . params  =  Params ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . can_callbacks  =  can_comm_callbacks ( self . can_sock ,  self . pm . sock [ ' sendcan ' ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    is_release  =  self . params . get_bool ( " IsReleaseBranch " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  CI  is  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # wait for one pandaState and one CAN packet 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      print ( " Waiting for CAN messages... " ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      while  True : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        can  =  messaging . recv_one_retry ( self . can_sock ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( can . can )  >  0 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          break 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      alpha_long_allowed  =  self . params . get_bool ( " AlphaLongitudinalEnabled " ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      num_pandas  =  len ( messaging . recv_one_retry ( self . sm . sock [ ' pandaStates ' ] ) . pandaStates ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cached_params  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cached_params_raw  =  self . params . get ( " CarParamsCache " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  cached_params_raw  is  not  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        with  car . CarParams . from_bytes ( cached_params_raw )  as  _cached_params : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								          cached_params  =  _cached_params 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . CI  =  get_car ( * self . can_callbacks ,  obd_callback ( self . params ) ,  alpha_long_allowed ,  is_release ,  num_pandas ,  cached_params ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . RI  =  interfaces [ self . CI . CP . carFingerprint ] . RadarInterface ( self . CI . CP ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . CP  =  self . CI . CP 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # continue onto next fingerprinting step in pandad 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . params . put_bool ( " FirmwareQueryDone " ,  True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . CI ,  self . CP  =  CI ,  CI . CP 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . RI  =  RI 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . CP . alternativeExperience  =  0 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    openpilot_enabled_toggle  =  self . params . get_bool ( " OpenpilotEnabledToggle " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    controller_available  =  self . CI . CC  is  not  None  and  openpilot_enabled_toggle  and  not  self . CP . dashcamOnly 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . CP . passive  =  not  controller_available  or  self . CP . dashcamOnly 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . CP . passive : 
  
						 
					
						
							
								
									
										
											 
										
											
												selfdrive/car: ban cereal and capnp (#33208)
* ban cereal and msgq
* common too
* do toyota/values.py
* do all fingerprints
* example without builder
* this still works, but no type checking anymore
* stash
* wtf, how does this work
* okay actually not bad
* safe
* epic!
* stash data_structures.py
* some clean up
* hell yeah
* clean up old file
* add to delete
* delete
This reverts commit 90239b7797ace31ee647a2fdbd67e0c3faa98dcf.
* switch more CarParams stuff over
remove unused
* fix car tests by removing cereal! mypy forgets about dataclass if we wrap it :(
* fix this too
* fix this too
* remove more cereal and add some good hyundai tests
* bunch more typing
* override default with 20hz radar
* temp capnp converter helper
* more lateralTuning
* small union replicator is better than what i was trying, and fixes mypy dynamic typing issues
* can keep all this the same now!
* type ret: CarParams, add more missing structs, revert lateralTuning changes (smaller diff!)
* revert more
* get first enum automatically, but ofc mypy doesn't pick up the new metaclass so can't use :(
would have been `CarParams.NetworkLocation()`
* Revert "get first enum automatically, but ofc mypy doesn't pick up the new metaclass so can't use :("
This reverts commit bb28b228becba932052d2fc5a4389784027435b1.
* remove cereal from car_helpers (TODO: caching)
* remove a bunch of temp lines
* use dataclass_transform!
* remove some car.CarParams from the interfaces
* remove rest of car.CarParams from the interfaces
* same which() API
* sort
* from cereal/cache from fingerprinting!
* more typing
* dataclass to capnp helper for CarParams, cached it since it's kinda slow
* (partial) fix process replay fingerprintig for new API
* latcontrollers take capnp
* forgot this
* fix test_models
* fix unit tests
* not here
* VehicleModel and controller still takes capnp CP since they get it from Params()
* fix modeld test
* more fix
* need to namespace to structs, since CarState is both class and struct
* this was never in the base class?!
* clean that up again
* fix import error
fix import error
* cmts and more structs
* remove some more cereal from toyota + convert CarState to capnp
* bruh this was wrong
* replace more cereal
* EventName is one of the last things...
* replace a bunch more cereal.car
* missing imports
* more
* can fix this typing now
* proper toyota+others CS typing!
* mypy can detect return type of CS.update() now
* fix redeclaration of cruise_buttons type
* mypy is only complaining about events now
* temp fix
* add carControl struct
* replace CarControl
i hope there's no circular imports in hyundai's CC
* fine now
* lol this was wrong too
* fix crash
* include my failed attempts at recursively converting to dataclass (doesn't implicitly convert types/recursively :( )
but attrs does, maybe will switch in the future
* clean up
* try out attr.s for its converter (doesn't work recursively yet, but interesting!)
* Revert "try out attr.s for its converter (doesn't work recursively yet, but interesting!)"
This reverts commit ff2434f7bbd45a4d4bfb21f7d6712d1f1c3bcde9.
* test processes doesn't fail anymore (on toyota)!
* fix honda crash
* stash
* Revert "stash"
This reverts commit c1762af4e776790e4ad1322ad4ce0610157346e0.
* remove a bunch more cereal!
* LET'S GOOO
* fix these tests
* and these
* and that
* stash, something is wrong with hyundai enable
* Revert "stash, something is wrong with hyundai enable"
This reverts commit 39cf327def258e2959fe23cd7a550a858f6d8f03.
* forgot these
* remove cereal from fw_versions
* Revert "remove cereal from fw_versions"
This reverts commit 232b37cd409b55d04b1afc90d4a80c49e710eb56.
* remove rest of the cereal exceptions!
* fix that
* add typing to radard since I didn't realize RI.update() switched from cereal to structs
* and here too!
* add TODO for slots
* needed CS to be capnp, fix comparisons, and type hint car_specific so it's easier to catch type issues (capnp isn't detected by mypy :( )
* remove the struct converter
* save ~4-5% CPU at 100hz, we don't modify after so no need to deepcopy
btw pickle.loads(pickle.dumps()) is faster by ~1% CPU
* deepcopy -> copy: we can technically make a reference, but copy is almost free and less error-prone
saves ~1% CPU
* add non-copying asdict function
* should save ~3% CPU (still 4% above baseline)
* fix that, no dict support
* ~27% decrease in time for 20k iterations on 3X (3.37857 -> 2.4821s)
* give a better name
* fix
* dont support none, capitalize
* sheesh, this called type() on every field
* remove CS.events, clean up
* bump card %
* this was a bug on master!
* add a which enum
* default to pid
* revert
* update refs
* not needed, but consistent
* just Ecu
* don't need to do this in this pr
* clean up
* no cast
* consistent typing
* rm
* fix
* can do this if we're desperate for the last few %
* Revert "can do this if we're desperate for the last few %"
This reverts commit 18e11ac7883a0a56583750b1cc5a2b13011e7299.
* type this
* don't need to convert carControl
* i guess don't support set either
* fix CP type hint
* simplify that
old-commit-hash: 6a15c42143a4764e79df851d797f950a6212f464
											 
										 
										
											1 year ago 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      safety_config  =  structs . CarParams . SafetyConfig ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      safety_config . safetyModel  =  structs . CarParams . SafetyModel . noOutput 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . CP . safetyConfigs  =  [ safety_config ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  self . CP . secOcRequired  and  not  is_release : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      # Copy user key if available 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      try : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        with  open ( " /cache/params/SecOCKey " )  as  f : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          user_key  =  f . readline ( ) . strip ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  len ( user_key )  ==  32 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . params . put ( " SecOCKey " ,  user_key ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      except  Exception : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        pass 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      secoc_key  =  self . params . get ( " SecOCKey " ,  encoding = ' utf8 ' ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  secoc_key  is  not  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        saved_secoc_key  =  bytes . fromhex ( secoc_key . strip ( ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( saved_secoc_key )  ==  16 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          self . CP . secOcKeyAvailable  =  True 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          self . CI . CS . secoc_key  =  saved_secoc_key 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  controller_available : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . CI . CC . secoc_key  =  saved_secoc_key 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          cloudlog . warning ( " Saved SecOC key is invalid " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Write previous route's CarParams 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    prev_cp  =  self . params . get ( " CarParamsPersistent " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  prev_cp  is  not  None : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . params . put ( " CarParamsPrevRoute " ,  prev_cp ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # Write CarParams for controls and radard 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    cp_bytes  =  self . CP . to_bytes ( ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . params . put ( " CarParams " ,  cp_bytes ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . params . put_nonblocking ( " CarParamsCache " ,  cp_bytes ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . params . put_nonblocking ( " CarParamsPersistent " ,  cp_bytes ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . mock_carstate  =  MockCarState ( ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . v_cruise_helper  =  VCruiseHelper ( self . CP ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . is_metric  =  self . params . get_bool ( " IsMetric " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . experimental_mode  =  self . params . get_bool ( " ExperimentalMode " ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # card is driven by can recv, expected at 100Hz 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . rk  =  Ratekeeper ( 100 ,  print_delay_threshold = None ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  state_update ( self )  - >  tuple [ car . CarState ,  structs . RadarDataT  |  None ] : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ carState update loop, driven by can """ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    can_strs  =  messaging . drain_sock_raw ( self . can_sock ,  wait_for_one = True ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    can_list  =  can_capnp_to_list ( can_strs ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # Update carState from CAN 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    CS  =  self . CI . update ( can_list ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  self . CP . brand  ==  ' mock ' : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      CS  =  self . mock_carstate . update ( CS ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # Update radar tracks from CAN 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    RD :  structs . RadarDataT  |  None  =  self . RI . update ( can_list ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . sm . update ( 0 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    can_rcv_valid  =  len ( can_strs )  >  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Check for CAN timeout 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  can_rcv_valid : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . can_rcv_cum_timeout_counter  + =  1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  can_rcv_valid  and  REPLAY : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . can_log_mono_time  =  messaging . log_from_bytes ( can_strs [ 0 ] ) . logMonoTime 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . v_cruise_helper . update_v_cruise ( CS ,  self . sm [ ' carControl ' ] . enabled ,  self . is_metric ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  self . sm [ ' carControl ' ] . enabled  and  not  self . CC_prev . enabled : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      # Use CarState w/ buttons from the step selfdrived enables on 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . v_cruise_helper . initialize_v_cruise ( self . CS_prev ,  self . experimental_mode ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # TODO: mirror the carState.cruiseState struct? 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    CS . vCruise  =  float ( self . v_cruise_helper . v_cruise_kph ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    CS . vCruiseCluster  =  float ( self . v_cruise_helper . v_cruise_cluster_kph ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  CS ,  RD 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  state_publish ( self ,  CS :  car . CarState ,  RD :  structs . RadarDataT  |  None ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ carState and carParams publish loop """ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # carParams - logged every 50 seconds (> 1 per segment) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  self . sm . frame  %  int ( 50.  /  DT_CTRL )  ==  0 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cp_send  =  messaging . new_message ( ' carParams ' ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cp_send . valid  =  True 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      cp_send . carParams  =  self . CP 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . pm . send ( ' carParams ' ,  cp_send ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # publish new carOutput 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    co_send  =  messaging . new_message ( ' carOutput ' ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    co_send . valid  =  self . sm . all_checks ( [ ' carControl ' ] ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    co_send . carOutput . actuatorsOutput  =  self . last_actuators_output 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . pm . send ( ' carOutput ' ,  co_send ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # kick off controlsd step while we actuate the latest carControl packet 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cs_send  =  messaging . new_message ( ' carState ' ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cs_send . valid  =  CS . canValid 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cs_send . carState  =  CS 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cs_send . carState . canErrorCounter  =  self . can_rcv_cum_timeout_counter 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cs_send . carState . cumLagMs  =  - self . rk . remaining  *  1000. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . pm . send ( ' carState ' ,  cs_send ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  RD  is  not  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      tracks_msg  =  messaging . new_message ( ' liveTracks ' ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      tracks_msg . valid  =  not  any ( RD . errors . to_dict ( ) . values ( ) ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      tracks_msg . liveTracks  =  RD 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . pm . send ( ' liveTracks ' ,  tracks_msg ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  controls_update ( self ,  CS :  car . CarState ,  CC :  car . CarControl ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ control update loop, driven by carControl """ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  not  self . initialized_prev : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # Initialize CarInterface, once controls are ready 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      # TODO: this can make us miss at least a few cycles when doing an ECU knockout 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . CI . init ( self . CP ,  * self . can_callbacks ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      # signal pandad to switch to car safety mode 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . params . put_bool_nonblocking ( " ControlsReady " ,  True ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  self . sm . all_alive ( [ ' carControl ' ] ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # send car controls over can 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      now_nanos  =  self . can_log_mono_time  if  REPLAY  else  int ( time . monotonic ( )  *  1e9 ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . last_actuators_output ,  can_sends  =  self . CI . apply ( CC ,  now_nanos ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      self . pm . send ( ' sendcan ' ,  can_list_to_can_capnp ( can_sends ,  msgtype = ' sendcan ' ,  valid = CS . canValid ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . CC_prev  =  CC 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  step ( self ) : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    CS ,  RD  =  self . state_update ( ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . state_publish ( CS ,  RD ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    initialized  =  ( not  any ( e . name  ==  EventName . selfdriveInitializing  for  e  in  self . sm [ ' onroadEvents ' ] )  and 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								                   self . sm . seen [ ' onroadEvents ' ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  self . CP . passive  and  initialized : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . controls_update ( CS ,  self . sm [ ' carControl ' ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . initialized_prev  =  initialized 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    self . CS_prev  =  CS 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  params_thread ( self ,  evt ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  not  evt . is_set ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . is_metric  =  self . params . get_bool ( " IsMetric " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      self . experimental_mode  =  self . params . get_bool ( " ExperimentalMode " )  and  self . CP . openpilotLongitudinalControl 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      time . sleep ( 0.1 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  card_thread ( self ) : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    e  =  threading . Event ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    t  =  threading . Thread ( target = self . params_thread ,  args = ( e ,  ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    try : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      t . start ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      while  True : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . step ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . rk . monitor_time ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    finally : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      e . set ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      t . join ( ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  main ( ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  config_realtime_process ( 4 ,  Priority . CTRL_HIGH ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  car  =  Car ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  car . card_thread ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								if  __name__  ==  " __main__ " : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  main ( )