#!/usr/bin/env python3 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								import  os 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  sys 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								import  multiprocessing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  subprocess 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								import  argparse 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								from  tempfile  import  NamedTemporaryFile 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  common . basedir  import  BASEDIR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  selfdrive . test . process_replay . compare_logs  import  save_log 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								from  tools . lib . api  import  CommaApi 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  tools . lib . auth_config  import  get_token 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								from  tools . lib . logreader  import  LogReader 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								from  tools . lib . route  import  Route 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  urllib . parse  import  urlparse ,  parse_qs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								juggle_dir  =  os . path . dirname ( os . path . realpath ( __file__ ) ) 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  load_segment ( segment_name ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  print ( f " Loading  { segment_name } " ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  if  segment_name  is  None : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  [ ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  try : 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  list ( LogReader ( segment_name ) ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  except  ValueError  as  e : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    print ( f " Error parsing  { segment_name } :  { e } " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  [ ] 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								def  start_juggler ( fn = None ,  dbc = None ,  layout = None ) : 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  env  =  os . environ . copy ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  env [ " BASEDIR " ]  =  BASEDIR 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  pj  =  os . getenv ( " PLOTJUGGLER_PATH " ,  os . path . join ( juggle_dir ,  " bin/plotjuggler " ) ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  dbc : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    env [ " DBC_NAME " ]  =  dbc 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  extra_args  =  [ ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  fn  is  not  None : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    extra_args . append ( f ' -d  { fn } ' ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  if  layout  is  not  None : 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    extra_args . append ( f ' -l  { layout } ' ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  extra_args  =  "   " . join ( extra_args ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  subprocess . call ( f ' { pj }  --plugin_folders  { os . path . join ( juggle_dir ,  " bin " ) }   { extra_args } ' ,  shell = True ,  env = env ,  cwd = juggle_dir ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								def  juggle_route ( route_name ,  segment_number ,  segment_count ,  qlog ,  can ,  layout ) : 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  if  ' cabana '  in  route_name : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    query  =  parse_qs ( urlparse ( route_name ) . query ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    api  =  CommaApi ( get_token ( ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    logs  =  api . get ( f ' v1/route/ { query [ " route " ] [ 0 ] } /log_urls?sig= { query [ " sig " ] [ 0 ] } &exp= { query [ " exp " ] [ 0 ] } ' ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  elif  route_name . startswith ( " http:// " )  or  route_name . startswith ( " https:// " )  or  os . path . isfile ( route_name ) : 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    logs  =  [ route_name ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  else : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    r  =  Route ( route_name ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    logs  =  r . qlog_paths ( )  if  qlog  else  r . log_paths ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  if  segment_number  is  not  None : 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    logs  =  logs [ segment_number : segment_number + segment_count ] 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  None  in  logs : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    fallback_answer  =  input ( " At least one of the rlogs in this segment does not exist, would you like to use the qlogs? (y/n) :  " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  fallback_answer  ==  ' y ' : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      logs  =  r . qlog_paths ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  segment_number  is  not  None : 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        logs  =  logs [ segment_number : segment_number + segment_count ] 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    else : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      print ( f " Please try a different  { ' segment '  if  segment_number  is  not  None  else  ' route ' } " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      return 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  all_data  =  [ ] 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  with  multiprocessing . Pool ( 24 )  as  pool : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  d  in  pool . map ( load_segment ,  logs ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      all_data  + =  d 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  if  not  can : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    all_data  =  [ d  for  d  in  all_data  if  d . which ( )  not  in  [ ' can ' ,  ' sendcan ' ] ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  # Infer DBC name from logs 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  dbc  =  None 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  for  cp  in  [ m  for  m  in  all_data  if  m . which ( )  ==  ' carParams ' ] : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    try : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      DBC  =  __import__ ( f " selfdrive.car. { cp . carParams . carName } .values " ,  fromlist = [ ' DBC ' ] ) . DBC 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      dbc  =  DBC [ cp . carParams . carFingerprint ] [ ' pt ' ] 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    except  ( ImportError ,  KeyError ,  AttributeError ) : 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      pass 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    break 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  tempfile  =  NamedTemporaryFile ( suffix = ' .rlog ' ,  dir = juggle_dir ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  save_log ( tempfile . name ,  all_data ,  compress = False ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  del  all_data 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  start_juggler ( tempfile . name ,  dbc ,  layout ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								def  get_arg_parser ( ) : 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  parser  =  argparse . ArgumentParser ( description = " PlotJuggler plugin for reading openpilot logs " , 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                   formatter_class = argparse . ArgumentDefaultsHelpFormatter ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  parser . add_argument ( " --qlog " ,  action = " store_true " ,  help = " Use qlogs " ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  parser . add_argument ( " --can " ,  action = " store_true " ,  help = " Parse CAN data " ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  parser . add_argument ( " --stream " ,  action = " store_true " ,  help = " Start PlotJuggler without a route to stream data using Cereal " ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  parser . add_argument ( " --layout " ,  nargs = ' ? ' ,  help = " Run PlotJuggler with a pre-defined layout " ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  parser . add_argument ( " route_name " ,  nargs = ' ? ' ,  help = " The route name to plot (cabana share URL accepted) " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  parser . add_argument ( " segment_number " ,  type = int ,  nargs = ' ? ' ,  help = " The index of the segment to plot " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  parser . add_argument ( " segment_count " ,  type = int ,  nargs = ' ? ' ,  help = " The number of segments to plot " ,  default = 1 ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  return  parser 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								if  __name__  ==  " __main__ " : 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  arg_parser  =  get_arg_parser ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  len ( sys . argv )  ==  1 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    arg_parser . print_help ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    sys . exit ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  args  =  arg_parser . parse_args ( sys . argv [ 1 : ] ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  args . stream : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    start_juggler ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  else : 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    juggle_route ( args . route_name ,  args . segment_number ,  args . segment_count ,  args . qlog ,  args . can ,  args . layout )