You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					110 lines
				
				2.8 KiB
			
		
		
			
		
	
	
					110 lines
				
				2.8 KiB
			| 
											6 years ago
										 | #!/usr/bin/env python3
 | ||
| 
											5 years ago
										 | # pylint: skip-file
 | ||
|  | 
 | ||
| 
											6 years ago
										 | import argparse
 | ||
|  | import bisect
 | ||
|  | import select
 | ||
|  | import sys
 | ||
|  | import termios
 | ||
|  | import time
 | ||
|  | import tty
 | ||
|  | from collections import defaultdict
 | ||
|  | 
 | ||
|  | import cereal.messaging as messaging
 | ||
|  | from tools.lib.framereader import FrameReader
 | ||
|  | from tools.lib.logreader import LogReader
 | ||
| 
											4 years ago
										 | from selfdrive.test.openpilotci import get_url
 | ||
| 
											6 years ago
										 | 
 | ||
|  | IGNORE = ['initData', 'sentinel']
 | ||
|  | 
 | ||
|  | 
 | ||
|  | def input_ready():
 | ||
|  |   return select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], [])
 | ||
|  | 
 | ||
|  | 
 | ||
| 
											4 years ago
										 | def replay(route, segment, loop):
 | ||
| 
											6 years ago
										 |   route = route.replace('|', '/')
 | ||
|  | 
 | ||
| 
											4 years ago
										 |   lr = LogReader(get_url(route, segment))
 | ||
|  |   fr = FrameReader(get_url(route, segment, "fcamera"), readahead=True)
 | ||
| 
											6 years ago
										 | 
 | ||
| 
											5 years ago
										 |   # Build mapping from frameId to segmentId from roadEncodeIdx, type == fullHEVC
 | ||
| 
											6 years ago
										 |   msgs = [m for m in lr if m.which() not in IGNORE]
 | ||
|  |   msgs = sorted(msgs, key=lambda m: m.logMonoTime)
 | ||
|  |   times = [m.logMonoTime for m in msgs]
 | ||
| 
											5 years ago
										 |   frame_idx = {m.roadEncodeIdx.frameId: m.roadEncodeIdx.segmentId for m in msgs if m.which() == 'roadEncodeIdx' and m.roadEncodeIdx.type == 'fullHEVC'}
 | ||
| 
											6 years ago
										 | 
 | ||
|  |   socks = {}
 | ||
|  |   lag = 0
 | ||
|  |   i = 0
 | ||
|  |   max_i = len(msgs) - 2
 | ||
|  | 
 | ||
|  |   while True:
 | ||
|  |     msg = msgs[i].as_builder()
 | ||
|  |     next_msg = msgs[i + 1]
 | ||
|  | 
 | ||
|  |     start_time = time.time()
 | ||
|  |     w = msg.which()
 | ||
|  | 
 | ||
| 
											5 years ago
										 |     if w == 'roadCameraState':
 | ||
| 
											6 years ago
										 |       try:
 | ||
| 
											5 years ago
										 |         img = fr.get(frame_idx[msg.roadCameraState.frameId], pix_fmt="rgb24")
 | ||
| 
											6 years ago
										 |         img = img[0][:, :, ::-1]  # Convert RGB to BGR, which is what the camera outputs
 | ||
| 
											5 years ago
										 |         msg.roadCameraState.image = img.flatten().tobytes()
 | ||
| 
											6 years ago
										 |       except (KeyError, ValueError):
 | ||
| 
											6 years ago
										 |         pass
 | ||
|  | 
 | ||
|  |     if w not in socks:
 | ||
|  |       socks[w] = messaging.pub_sock(w)
 | ||
| 
											6 years ago
										 | 
 | ||
|  |     try:
 | ||
|  |       if socks[w]:
 | ||
|  |         socks[w].send(msg.to_bytes())
 | ||
|  |     except messaging.messaging_pyx.MultiplePublishersError:
 | ||
|  |       socks[w] = None
 | ||
| 
											6 years ago
										 | 
 | ||
|  |     lag += (next_msg.logMonoTime - msg.logMonoTime) / 1e9
 | ||
|  |     lag -= time.time() - start_time
 | ||
|  | 
 | ||
|  |     dt = max(lag, 0)
 | ||
|  |     lag -= dt
 | ||
|  |     time.sleep(dt)
 | ||
|  | 
 | ||
| 
											6 years ago
										 |     if lag < -1.0 and i % 1000 == 0:
 | ||
|  |       print(f"{-lag:.2f} s behind")
 | ||
| 
											6 years ago
										 | 
 | ||
|  |     if input_ready():
 | ||
|  |       key = sys.stdin.read(1)
 | ||
|  | 
 | ||
|  |       # Handle pause
 | ||
|  |       if key == " ":
 | ||
|  |         while True:
 | ||
|  |           if input_ready() and sys.stdin.read(1) == " ":
 | ||
|  |             break
 | ||
|  |           time.sleep(0.01)
 | ||
|  | 
 | ||
|  |       # Handle seek
 | ||
|  |       dt = defaultdict(int, s=10, S=-10)[key]
 | ||
|  |       new_time = msgs[i].logMonoTime + dt * 1e9
 | ||
|  |       i = bisect.bisect_left(times, new_time)
 | ||
|  | 
 | ||
| 
											6 years ago
										 |     i = (i + 1) % max_i if loop else min(i + 1, max_i)
 | ||
| 
											6 years ago
										 | 
 | ||
|  | 
 | ||
|  | if __name__ == "__main__":
 | ||
|  |   parser = argparse.ArgumentParser()
 | ||
| 
											6 years ago
										 |   parser.add_argument("--loop", action='store_true')
 | ||
| 
											4 years ago
										 |   parser.add_argument("route")
 | ||
| 
											6 years ago
										 |   parser.add_argument("segment")
 | ||
| 
											6 years ago
										 |   args = parser.parse_args()
 | ||
|  | 
 | ||
|  |   orig_settings = termios.tcgetattr(sys.stdin)
 | ||
|  |   tty.setcbreak(sys.stdin)
 | ||
|  | 
 | ||
|  |   try:
 | ||
| 
											4 years ago
										 |     replay(args.route, args.segment, args.loop)
 | ||
| 
											6 years ago
										 |     termios.tcsetattr(sys.stdin, termios.TCSADRAIN, orig_settings)
 | ||
| 
											5 years ago
										 |   except Exception:
 | ||
| 
											6 years ago
										 |     termios.tcsetattr(sys.stdin, termios.TCSADRAIN, orig_settings)
 | ||
|  |     raise
 |