|  |  | @ -3,7 +3,7 @@ import argparse | 
			
		
	
		
		
			
				
					
					|  |  |  | import base64 |  |  |  | import base64 | 
			
		
	
		
		
			
				
					
					|  |  |  | import io |  |  |  | import io | 
			
		
	
		
		
			
				
					
					|  |  |  | import os |  |  |  | import os | 
			
		
	
		
		
			
				
					
					|  |  |  | import time |  |  |  | import json | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | from pathlib import Path |  |  |  | from pathlib import Path | 
			
		
	
		
		
			
				
					
					|  |  |  | import matplotlib.pyplot as plt |  |  |  | import matplotlib.pyplot as plt | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -11,15 +11,21 @@ from openpilot.tools.lib.logreader import LogReader | 
			
		
	
		
		
			
				
					
					|  |  |  | from openpilot.system.hardware.hw import Paths |  |  |  | from openpilot.system.hardware.hw import Paths | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | def report(platform, maneuvers): |  |  |  | def format_car_params(CP): | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   return json.dumps({k: v for k, v in CP.to_dict().items() if not k.endswith('DEPRECATED')}, indent=2) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | def report(platform, route, CP, maneuvers): | 
			
		
	
		
		
			
				
					
					|  |  |  |   output_path = Path(__file__).resolve().parent / "longitudinal_reports" |  |  |  |   output_path = Path(__file__).resolve().parent / "longitudinal_reports" | 
			
		
	
		
		
			
				
					
					|  |  |  |   output_fn = output_path / f"{platform}_{time.strftime('%Y%m%d-%H_%M_%S')}.html" |  |  |  |   output_fn = output_path / f"{platform}_{route}.html" | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   output_path.mkdir(exist_ok=True) |  |  |  |   output_path.mkdir(exist_ok=True) | 
			
		
	
		
		
			
				
					
					|  |  |  |   with open(output_fn, "w") as f: |  |  |  |   with open(output_fn, "w") as f: | 
			
		
	
		
		
			
				
					
					|  |  |  |     f.write("<h1>Longitudinal maneuver report</h1>\n") |  |  |  |     f.write("<h1>Longitudinal maneuver report</h1>\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |     f.write(f"<h3>{platform}</h3>\n") |  |  |  |     f.write(f"<h3>{platform}</h3>\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     f.write(f"<h3>{route}</h3>\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     f.write(f"<details><summary><h3 style='display: inline-block;'>CarParams</h3></summary><pre>{format_car_params(CP)}</pre></details>\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |     for description, runs in maneuvers: |  |  |  |     for description, runs in maneuvers: | 
			
		
	
		
		
			
				
					
					|  |  |  |       print('plotting maneuver:', description, 'runs:', len(runs)) |  |  |  |       print(f'plotting maneuver: {description}, runs: {len(runs)}') | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       f.write("<div style='border-top: 1px solid #000; margin: 20px 0;'></div>\n") |  |  |  |       f.write("<div style='border-top: 1px solid #000; margin: 20px 0;'></div>\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |       f.write(f"<h2>{description}</h2>\n") |  |  |  |       f.write(f"<h2>{description}</h2>\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |       for run, msgs in enumerate(runs): |  |  |  |       for run, msgs in enumerate(runs): | 
			
		
	
	
		
		
			
				
					|  |  | @ -28,6 +34,11 @@ def report(platform, maneuvers): | 
			
		
	
		
		
			
				
					
					|  |  |  |         t_carState, carState = zip(*[(m.logMonoTime, m.carState) for m in msgs if m.which() == 'carState'], strict=True) |  |  |  |         t_carState, carState = zip(*[(m.logMonoTime, m.carState) for m in msgs if m.which() == 'carState'], strict=True) | 
			
		
	
		
		
			
				
					
					|  |  |  |         t_longitudinalPlan, longitudinalPlan = zip(*[(m.logMonoTime, m.longitudinalPlan) for m in msgs if m.which() == 'longitudinalPlan'], strict=True) |  |  |  |         t_longitudinalPlan, longitudinalPlan = zip(*[(m.logMonoTime, m.longitudinalPlan) for m in msgs if m.which() == 'longitudinalPlan'], strict=True) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         t_carControl = [(t - t_carControl[0]) / 1e9 for t in t_carControl] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         t_carOutput = [(t - t_carOutput[0]) / 1e9 for t in t_carOutput] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         t_carState = [(t - t_carState[0]) / 1e9 for t in t_carState] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         t_longitudinalPlan = [(t - t_longitudinalPlan[0]) / 1e9 for t in t_longitudinalPlan] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         longActive = [m.longActive for m in carControl] |  |  |  |         longActive = [m.longActive for m in carControl] | 
			
		
	
		
		
			
				
					
					|  |  |  |         gasPressed = [m.gasPressed for m in carState] |  |  |  |         gasPressed = [m.gasPressed for m in carState] | 
			
		
	
		
		
			
				
					
					|  |  |  |         brakePressed = [m.brakePressed for m in carState] |  |  |  |         brakePressed = [m.brakePressed for m in carState] | 
			
		
	
	
		
		
			
				
					|  |  | @ -41,7 +52,7 @@ def report(platform, maneuvers): | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         plt.rcParams['font.size'] = 40 |  |  |  |         plt.rcParams['font.size'] = 40 | 
			
		
	
		
		
			
				
					
					|  |  |  |         fig = plt.figure(figsize=(30, 25)) |  |  |  |         fig = plt.figure(figsize=(30, 25)) | 
			
		
	
		
		
			
				
					
					|  |  |  |         ax = fig.subplots(4, 1, sharex=True, gridspec_kw={'hspace': 0, 'height_ratios': [5, 3, 1, 1]}) |  |  |  |         ax = fig.subplots(4, 1, sharex=True, gridspec_kw={'height_ratios': [5, 3, 1, 1]}) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         ax[0].grid(linewidth=4) |  |  |  |         ax[0].grid(linewidth=4) | 
			
		
	
		
		
			
				
					
					|  |  |  |         ax[0].plot(t_carControl, [m.actuators.accel for m in carControl], label='carControl.actuators.accel', linewidth=6) |  |  |  |         ax[0].plot(t_carControl, [m.actuators.accel for m in carControl], label='carControl.actuators.accel', linewidth=6) | 
			
		
	
	
		
		
			
				
					|  |  | @ -112,4 +123,4 @@ if __name__ == '__main__': | 
			
		
	
		
		
			
				
					
					|  |  |  |     if active_prev: |  |  |  |     if active_prev: | 
			
		
	
		
		
			
				
					
					|  |  |  |       maneuvers[-1][1][-1].append(msg) |  |  |  |       maneuvers[-1][1][-1].append(msg) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   report(platform, maneuvers) |  |  |  |   report(platform, args.route, CP, maneuvers) | 
			
				
				
			
		
	
		
		
	
	
		
		
			
				
					|  |  | 
 |