rerun.io proof of concept (#32416)
	
		
	
				
					
				
			* Adding demo version for acceleration only * Adding, plot any event * Adding dynamic blueprint creation and menu to choose what to plot * Adding, pool of processes for faster data visualization * Adding, install rerun if not present * Adding. thumbnail support * Refactoring, minor cleanup * -Use rerun pre-release -Remove json as a middle format -Replace recursion with stack-based approach * Refactoring, using services from cereal instead of hardcoding them * Use of lr.run_across_segments instead of pool, Use of python dict instead of capnp objs - better performance Use LogReader syntax * Enable logging of liveTracks, pandaStates * Use of plotjuggler user experience * Fixing bug in log_msg function * cleanup --------- Co-authored-by: savojovic <jovo.savic00@gmail.com> Co-authored-by: savojovic <74861870+savojovic@users.noreply.github.com>lets-get-piffy
							parent
							
								
									9287a69624
								
							
						
					
					
						commit
						1c481c5ad3
					
				
				 1 changed files with 104 additions and 0 deletions
			
			
		| @ -0,0 +1,104 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | import subprocess | ||||||
|  | import sys | ||||||
|  | import argparse | ||||||
|  | import multiprocessing | ||||||
|  | from functools import partial | ||||||
|  | 
 | ||||||
|  | from openpilot.tools.lib.logreader import LogReader | ||||||
|  | from cereal.services import SERVICE_LIST | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | NUM_CPUS = multiprocessing.cpu_count() | ||||||
|  | DEMO_ROUTE = "a2a0ccea32023010|2023-07-27--13-01-19" | ||||||
|  | WHEEL_URL = "https://build.rerun.io/commit/660463d/wheels" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def install(): | ||||||
|  |   # currently requires a preview release build | ||||||
|  |   subprocess.run([sys.executable, "-m", "pip", "install", "--pre", "-f", WHEEL_URL, "--upgrade", "rerun-sdk"], check=True) | ||||||
|  |   print("Rerun installed") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def log_msg(msg, parent_key=''): | ||||||
|  |   stack = [(msg, parent_key)] | ||||||
|  |   while stack: | ||||||
|  |     current_msg, current_parent_key = stack.pop() | ||||||
|  |     if isinstance(current_msg, list): | ||||||
|  |       for index, item in enumerate(current_msg): | ||||||
|  |         new_key = f"{current_parent_key}/{index}" | ||||||
|  |         if isinstance(item, (int, float)): | ||||||
|  |           rr.log(str(new_key), rr.Scalar(item)) | ||||||
|  |         elif isinstance(item, dict): | ||||||
|  |           stack.append((item, new_key)) | ||||||
|  |     elif isinstance(current_msg, dict): | ||||||
|  |       for key, value in current_msg.items(): | ||||||
|  |         new_key = f"{current_parent_key}/{key}" | ||||||
|  |         if isinstance(value, (int, float)): | ||||||
|  |           rr.log(str(new_key), rr.Scalar(value)) | ||||||
|  |         elif isinstance(value, dict): | ||||||
|  |           stack.append((value, new_key)) | ||||||
|  |         elif isinstance(value, list): | ||||||
|  |           for index, item in enumerate(value): | ||||||
|  |             if isinstance(item, (int, float)): | ||||||
|  |               rr.log(f"{new_key}/{index}", rr.Scalar(item)) | ||||||
|  |     else: | ||||||
|  |       pass  # Not a plottable value | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def createBlueprint(): | ||||||
|  |   timeSeriesViews = [] | ||||||
|  |   for topic in sorted(SERVICE_LIST.keys()): | ||||||
|  |     timeSeriesViews.append(rrb.TimeSeriesView(name=topic, origin=f"/{topic}/", visible=False)) | ||||||
|  |     rr.log(topic, rr.SeriesLine(name=topic), timeless=True) | ||||||
|  |     blueprint = rrb.Blueprint(rrb.Grid(rrb.Vertical(*timeSeriesViews,rrb.SelectionPanel(expanded=False),rrb.TimePanel(expanded=False)), | ||||||
|  |                                         rrb.Spatial2DView(name="thumbnail", origin="/thumbnail"))) | ||||||
|  |   return blueprint | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def log_thumbnail(thumbnailMsg): | ||||||
|  |   bytesImgData = thumbnailMsg.get('thumbnail') | ||||||
|  |   rr.log("/thumbnail", rr.ImageEncoded(contents=bytesImgData)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def process(blueprint, lr): | ||||||
|  |   ret = [] | ||||||
|  |   rr.init("rerun_test", spawn=True, default_blueprint=blueprint) | ||||||
|  |   for msg in lr: | ||||||
|  |     ret.append(msg) | ||||||
|  |     rr.set_time_nanos("TIMELINE", msg.logMonoTime) | ||||||
|  |     if msg.which() != "thumbnail": | ||||||
|  |       log_msg(msg.to_dict()[msg.which()], msg.which()) | ||||||
|  |     else: | ||||||
|  |       log_thumbnail(msg.to_dict()[msg.which()]) | ||||||
|  |   return ret | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == '__main__': | ||||||
|  |   parser = argparse.ArgumentParser(description="A helper to run rerun on openpilot routes", | ||||||
|  |                                   formatter_class=argparse.ArgumentDefaultsHelpFormatter) | ||||||
|  |   parser.add_argument("--demo", action="store_true", help="Use the demo route instead of providing one") | ||||||
|  |   parser.add_argument("--install", action="store_true", help="Install or update rerun") | ||||||
|  |   parser.add_argument("route_or_segment_name", nargs='?', help="The route or segment name to plot") | ||||||
|  | 
 | ||||||
|  |   if len(sys.argv) == 1: | ||||||
|  |     parser.print_help() | ||||||
|  |     sys.exit() | ||||||
|  | 
 | ||||||
|  |   args = parser.parse_args() | ||||||
|  |   if args.install: | ||||||
|  |     install() | ||||||
|  |     sys.exit() | ||||||
|  | 
 | ||||||
|  |   try: | ||||||
|  |     import rerun as rr | ||||||
|  |     import rerun.blueprint as rrb | ||||||
|  |   except ImportError: | ||||||
|  |     print("Rerun is not installed, run with --install first") | ||||||
|  |     sys.exit() | ||||||
|  | 
 | ||||||
|  |   route_or_segment_name = DEMO_ROUTE if args.demo else args.route_or_segment_name.strip() | ||||||
|  |   blueprint = createBlueprint() | ||||||
|  |   print("Getting route log paths") | ||||||
|  |   lr = LogReader(route_or_segment_name) | ||||||
|  |   lr.run_across_segments(NUM_CPUS, partial(process, blueprint)) | ||||||
					Loading…
					
					
				
		Reference in new issue