|  |  |  | @ -57,14 +57,21 @@ def read_logs(lr): | 
			
		
	
		
			
				
					|  |  |  |  |         if continue_outer: | 
			
		
	
		
			
				
					|  |  |  |  |           continue | 
			
		
	
		
			
				
					|  |  |  |  |       mono_to_frame[msg.logMonoTime] = frame_id | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       data['timestamp'][frame_id][service].append((msg.which()+" published", msg.logMonoTime)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       next_service = SERVICES[SERVICES.index(service)+1] | 
			
		
	
		
			
				
					|  |  |  |  |       if not data['start'][frame_id][next_service]: | 
			
		
	
		
			
				
					|  |  |  |  |         data['start'][frame_id][next_service] = msg.logMonoTime | 
			
		
	
		
			
				
					|  |  |  |  |       data['end'][frame_id][service] = msg.logMonoTime | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       if service in SERVICE_TO_DURATIONS: | 
			
		
	
		
			
				
					|  |  |  |  |         for duration in SERVICE_TO_DURATIONS[service]: | 
			
		
	
		
			
				
					|  |  |  |  |           data['duration'][frame_id][service].append((msg.which()+"."+duration, getattr(msg_obj, duration))) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       if service == SERVICES[0]: | 
			
		
	
		
			
				
					|  |  |  |  |         data['timestamp'][frame_id][service].append((msg.which()+" start of frame", msg_obj.timestampSof)) | 
			
		
	
		
			
				
					|  |  |  |  |         if not data['start'][frame_id][service]: | 
			
		
	
		
			
				
					|  |  |  |  |           data['start'][frame_id][service] = msg_obj.timestampSof | 
			
		
	
		
			
				
					|  |  |  |  |       elif msg.which() == 'controlsState': | 
			
		
	
		
			
				
					|  |  |  |  |         # Sendcan is published before controlsState, but the frameId is retrived in CS | 
			
		
	
		
			
				
					|  |  |  |  |         data['timestamp'][frame_id][service].append(("sendcan published", latest_sendcan_monotime)) | 
			
		
	
	
		
			
				
					|  |  |  | @ -78,31 +85,16 @@ def read_logs(lr): | 
			
		
	
		
			
				
					|  |  |  |  |   assert len(frame_mismatches) < 20, "Too many frame mismatches" | 
			
		
	
		
			
				
					|  |  |  |  |   return (data, frame_mismatches) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def get_min_time(frame_id, service, timestamps, use_max=False): | 
			
		
	
		
			
				
					|  |  |  |  |   return min(timestamps[frame_id][service], key=lambda x: x[1])[1] if not use_max else max(timestamps[frame_id][service], key=lambda x: x[1])[1] | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def get_interval(frame_id, service, timestamps): | 
			
		
	
		
			
				
					|  |  |  |  |   try: | 
			
		
	
		
			
				
					|  |  |  |  |     service_max = get_min_time(frame_id, service, timestamps, use_max=True)  | 
			
		
	
		
			
				
					|  |  |  |  |     if service == SERVICES[0]: | 
			
		
	
		
			
				
					|  |  |  |  |       service_min = get_min_time(frame_id, service, timestamps)  | 
			
		
	
		
			
				
					|  |  |  |  |       return (service_min, service_max) | 
			
		
	
		
			
				
					|  |  |  |  |     prev_service = SERVICES[SERVICES.index(service)-1] | 
			
		
	
		
			
				
					|  |  |  |  |     prev_service_max = get_min_time(frame_id, prev_service, timestamps, use_max=True)  | 
			
		
	
		
			
				
					|  |  |  |  |     return (prev_service_max, service_max) | 
			
		
	
		
			
				
					|  |  |  |  |   except ValueError: | 
			
		
	
		
			
				
					|  |  |  |  |     return (-1,-1) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def find_frame_id(time, service, timestamps): | 
			
		
	
		
			
				
					|  |  |  |  |   for frame_id in reversed(timestamps): | 
			
		
	
		
			
				
					|  |  |  |  |     start, end = get_interval(frame_id, service, timestamps) | 
			
		
	
		
			
				
					|  |  |  |  |     if start <= time <= end: | 
			
		
	
		
			
				
					|  |  |  |  |       return frame_id | 
			
		
	
		
			
				
					|  |  |  |  |   return -1 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def find_frame_id(time, service, start_times, end_times): | 
			
		
	
		
			
				
					|  |  |  |  |   for frame_id in reversed(start_times): | 
			
		
	
		
			
				
					|  |  |  |  |     if start_times[frame_id][service] and end_times[frame_id][service]: | 
			
		
	
		
			
				
					|  |  |  |  |       if start_times[frame_id][service] <= time <= end_times[frame_id][service]: | 
			
		
	
		
			
				
					|  |  |  |  |         yield frame_id | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ## ASSUMES THAT AT LEAST ONE CLOUDLOG IS MADE IN CONTROLSD | 
			
		
	
		
			
				
					|  |  |  |  | def insert_cloudlogs(lr, timestamps): | 
			
		
	
		
			
				
					|  |  |  |  |   t0 = get_min_time(min(timestamps.keys()), SERVICES[0], timestamps)  | 
			
		
	
		
			
				
					|  |  |  |  | def insert_cloudlogs(lr, timestamps, start_times, end_times): | 
			
		
	
		
			
				
					|  |  |  |  |   t0 = start_times[min(start_times.keys())][SERVICES[0]]  | 
			
		
	
		
			
				
					|  |  |  |  |   failed_inserts = 0 | 
			
		
	
		
			
				
					|  |  |  |  |   latest_controls_frameid = 0 | 
			
		
	
		
			
				
					|  |  |  |  |   for msg in lr: | 
			
		
	
	
		
			
				
					|  |  |  | @ -116,22 +108,28 @@ def insert_cloudlogs(lr, timestamps): | 
			
		
	
		
			
				
					|  |  |  |  |           # Filter out controlsd messages which arrive before the camera loop  | 
			
		
	
		
			
				
					|  |  |  |  |           continue | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         frame_id = latest_controls_frameid if service == "boardd" else find_frame_id(time, service, timestamps) | 
			
		
	
		
			
				
					|  |  |  |  |         if frame_id > -1: | 
			
		
	
		
			
				
					|  |  |  |  |           timestamps[frame_id][service].append((event, time)) | 
			
		
	
		
			
				
					|  |  |  |  |           if service == 'controlsd': | 
			
		
	
		
			
				
					|  |  |  |  |             latest_controls_frameid = frame_id | 
			
		
	
		
			
				
					|  |  |  |  |         if service == "boardd": | 
			
		
	
		
			
				
					|  |  |  |  |           timestamps[latest_controls_frameid][service].append((event, time)) | 
			
		
	
		
			
				
					|  |  |  |  |           end_times[latest_controls_frameid][service] = time | 
			
		
	
		
			
				
					|  |  |  |  |         else: | 
			
		
	
		
			
				
					|  |  |  |  |           failed_inserts += 1 | 
			
		
	
		
			
				
					|  |  |  |  |           frame_id_gen = find_frame_id(time, service, start_times, end_times) | 
			
		
	
		
			
				
					|  |  |  |  |           frame_id = next(frame_id_gen, False) | 
			
		
	
		
			
				
					|  |  |  |  |           if frame_id: | 
			
		
	
		
			
				
					|  |  |  |  |             if service == 'controlsd': | 
			
		
	
		
			
				
					|  |  |  |  |               latest_controls_frameid = frame_id | 
			
		
	
		
			
				
					|  |  |  |  |             timestamps[frame_id][service].append((event, time)) | 
			
		
	
		
			
				
					|  |  |  |  |           else: | 
			
		
	
		
			
				
					|  |  |  |  |             failed_inserts += 1 | 
			
		
	
		
			
				
					|  |  |  |  |   assert latest_controls_frameid > 0, "No timestamp in controlsd" | 
			
		
	
		
			
				
					|  |  |  |  |   assert failed_inserts < len(timestamps), "Too many failed cloudlog inserts" | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def print_timestamps(timestamps, durations ,relative): | 
			
		
	
		
			
				
					|  |  |  |  |   t0 = get_min_time(min(timestamps.keys()), SERVICES[0], timestamps)  | 
			
		
	
		
			
				
					|  |  |  |  | def print_timestamps(timestamps, durations, start_times, relative): | 
			
		
	
		
			
				
					|  |  |  |  |   t0 = start_times[min(start_times.keys())][SERVICES[0]] | 
			
		
	
		
			
				
					|  |  |  |  |   for frame_id in timestamps.keys(): | 
			
		
	
		
			
				
					|  |  |  |  |     print('='*80) | 
			
		
	
		
			
				
					|  |  |  |  |     print("Frame ID:", frame_id) | 
			
		
	
		
			
				
					|  |  |  |  |     if relative: | 
			
		
	
		
			
				
					|  |  |  |  |       t0 = get_min_time(frame_id, SERVICES[0], timestamps)  | 
			
		
	
		
			
				
					|  |  |  |  |       t0 = start_times[frame_id][SERVICES[0]] | 
			
		
	
		
			
				
					|  |  |  |  |     for service in SERVICES: | 
			
		
	
		
			
				
					|  |  |  |  |       print("  "+service)   | 
			
		
	
		
			
				
					|  |  |  |  |       events = timestamps[frame_id][service] | 
			
		
	
	
		
			
				
					|  |  |  | @ -140,8 +138,8 @@ def print_timestamps(timestamps, durations ,relative): | 
			
		
	
		
			
				
					|  |  |  |  |       for event, time in durations[frame_id][service]: | 
			
		
	
		
			
				
					|  |  |  |  |         print("    "+'%-53s%-53s' %(event, str(time*1000)))  | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def graph_timestamps(timestamps, relative): | 
			
		
	
		
			
				
					|  |  |  |  |   t0 = get_min_time(min(timestamps.keys()), SERVICES[0], timestamps)  | 
			
		
	
		
			
				
					|  |  |  |  | def graph_timestamps(timestamps, start_times, end_times, relative): | 
			
		
	
		
			
				
					|  |  |  |  |   t0 = start_times[min(start_times.keys())][SERVICES[0]]  | 
			
		
	
		
			
				
					|  |  |  |  |   fig, ax = plt.subplots() | 
			
		
	
		
			
				
					|  |  |  |  |   ax.set_xlim(0, 150 if relative else 750) | 
			
		
	
		
			
				
					|  |  |  |  |   ax.set_ylim(0, 15) | 
			
		
	
	
		
			
				
					|  |  |  | @ -153,19 +151,22 @@ def graph_timestamps(timestamps, relative): | 
			
		
	
		
			
				
					|  |  |  |  |   points = {"x": [], "y": [], "labels": []} | 
			
		
	
		
			
				
					|  |  |  |  |   for frame_id, services in timestamps.items(): | 
			
		
	
		
			
				
					|  |  |  |  |     if relative: | 
			
		
	
		
			
				
					|  |  |  |  |       t0 = get_min_time(frame_id, SERVICES[0], timestamps)  | 
			
		
	
		
			
				
					|  |  |  |  |       t0 = start_times[frame_id][SERVICES[0]] | 
			
		
	
		
			
				
					|  |  |  |  |     service_bars = [] | 
			
		
	
		
			
				
					|  |  |  |  |     for service, events in services.items(): | 
			
		
	
		
			
				
					|  |  |  |  |       start, end = get_interval(frame_id, service,timestamps) | 
			
		
	
		
			
				
					|  |  |  |  |       service_bars.append(((start-t0)/1e6,(end-start)/1e6)) | 
			
		
	
		
			
				
					|  |  |  |  |       for event in events: | 
			
		
	
		
			
				
					|  |  |  |  |         points['x'].append((event[1]-t0)/1e6) | 
			
		
	
		
			
				
					|  |  |  |  |         points['y'].append(frame_id) | 
			
		
	
		
			
				
					|  |  |  |  |         points['labels'].append(event[0]) | 
			
		
	
		
			
				
					|  |  |  |  |       if start_times[frame_id][service] and end_times[frame_id][service]: | 
			
		
	
		
			
				
					|  |  |  |  |         start = start_times[frame_id][service] | 
			
		
	
		
			
				
					|  |  |  |  |         end = end_times[frame_id][service] | 
			
		
	
		
			
				
					|  |  |  |  |         service_bars.append(((start-t0)/1e6,(end-start)/1e6)) | 
			
		
	
		
			
				
					|  |  |  |  |         for event in events: | 
			
		
	
		
			
				
					|  |  |  |  |           points['x'].append((event[1]-t0)/1e6) | 
			
		
	
		
			
				
					|  |  |  |  |           points['y'].append(frame_id) | 
			
		
	
		
			
				
					|  |  |  |  |           points['labels'].append(event[0]) | 
			
		
	
		
			
				
					|  |  |  |  |     ax.broken_barh(service_bars, (frame_id-0.45, 0.9), facecolors=(colors), alpha=0.5) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   scatter = ax.scatter(points['x'], points['y'], marker='d', edgecolor='black') | 
			
		
	
		
			
				
					|  |  |  |  |   tooltip = mpld3.plugins.PointLabelTooltip(scatter, labels=points['labels']) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   mpld3.plugins.connect(fig, tooltip) | 
			
		
	
		
			
				
					|  |  |  |  |   plt.legend(handles=[mpatches.Patch(color=colors[i], label=SERVICES[i]) for i in range(len(SERVICES))]) | 
			
		
	
		
			
				
					|  |  |  |  |   return fig | 
			
		
	
	
		
			
				
					|  |  |  | @ -173,7 +174,7 @@ def graph_timestamps(timestamps, relative): | 
			
		
	
		
			
				
					|  |  |  |  | def get_timestamps(lr): | 
			
		
	
		
			
				
					|  |  |  |  |   data, frame_mismatches = read_logs(lr) | 
			
		
	
		
			
				
					|  |  |  |  |   lr.reset() | 
			
		
	
		
			
				
					|  |  |  |  |   insert_cloudlogs(lr, data['timestamp']) | 
			
		
	
		
			
				
					|  |  |  |  |   insert_cloudlogs(lr, data['timestamp'], data['start'], data['end']) | 
			
		
	
		
			
				
					|  |  |  |  |   return data, frame_mismatches | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | if __name__ == "__main__": | 
			
		
	
	
		
			
				
					|  |  |  | @ -192,6 +193,6 @@ if __name__ == "__main__": | 
			
		
	
		
			
				
					|  |  |  |  |   r = DEMO_ROUTE if args.demo else args.route_or_segment_name.strip() | 
			
		
	
		
			
				
					|  |  |  |  |   lr = logreader_from_route_or_segment(r, sort_by_time=True) | 
			
		
	
		
			
				
					|  |  |  |  |   data, _ = get_timestamps(lr) | 
			
		
	
		
			
				
					|  |  |  |  |   print_timestamps(data['timestamp'], data['duration'], args.relative) | 
			
		
	
		
			
				
					|  |  |  |  |   print_timestamps(data['timestamp'], data['duration'], data['start'], args.relative) | 
			
		
	
		
			
				
					|  |  |  |  |   if args.plot: | 
			
		
	
		
			
				
					|  |  |  |  |     mpld3.show(graph_timestamps(data['timestamp'], args.relative)) | 
			
		
	
		
			
				
					|  |  |  |  |     mpld3.show(graph_timestamps(data['timestamp'], data['start'], data['end'], args.relative)) | 
			
		
	
	
		
			
				
					|  |  |  | 
 |