diff --git a/scripts/recv_raw_rolling.py b/scripts/recv_raw_rolling.py index 686d065..42abf11 100644 --- a/scripts/recv_raw_rolling.py +++ b/scripts/recv_raw_rolling.py @@ -10,10 +10,19 @@ import socket import numpy as np import cv2 +import time +from collections import deque # Debug flag - set to True to see frame reception details DEBUG = False +# Line drop detection parameters +EXPECTED_FPS = 200 # Expected frame rate (from 200fps ini file) +EXPECTED_INTERVAL_MS = 1000.0 / EXPECTED_FPS # 5ms for 200fps +DROP_THRESHOLD_MS = EXPECTED_INTERVAL_MS * 2.5 # Alert if gap > 2.5x expected (12.5ms) +STATS_WINDOW_SIZE = 100 # Track stats over last N frames +STATUS_INTERVAL = 100 # Print status every N frames + # Rotation mode - set to rotate incoming data before display # Options: None, cv2.ROTATE_90_CLOCKWISE, cv2.ROTATE_90_COUNTERCLOCKWISE, cv2.ROTATE_180 ROTATION = cv2.ROTATE_90_COUNTERCLOCKWISE # Rotate rows to columns @@ -46,7 +55,15 @@ rolling_buffer = np.zeros((DISPLAY_HEIGHT, DISPLAY_WIDTH, CHANNELS), dtype=np.ui current_column = 0 frame_count = 0 +# Line drop detection state +last_frame_time = None +first_frame_time = None +frame_intervals = deque(maxlen=STATS_WINDOW_SIZE) +total_drops = 0 +drops_since_last_status = 0 + while True: + current_time = time.time() data, addr = sock.recvfrom(65536) if len(data) != FRAME_SIZE: @@ -54,10 +71,38 @@ while True: print(f"Received {len(data)} bytes (expected {FRAME_SIZE}), skipping...") continue - if DEBUG: - frame_count += 1 - if frame_count % 30 == 0: - print(f"Received {frame_count} frames, current column: {current_column}") + # Initialize timing on first frame + if first_frame_time is None: + first_frame_time = current_time + + # Line drop detection + if last_frame_time is not None: + interval_ms = (current_time - last_frame_time) * 1000 + frame_intervals.append(interval_ms) + + # Detect line drop + if interval_ms > DROP_THRESHOLD_MS: + total_drops += 1 + drops_since_last_status += 1 + + last_frame_time = current_time + frame_count += 1 + + # Print status every STATUS_INTERVAL frames + if frame_count % STATUS_INTERVAL == 0: + elapsed_time = current_time - first_frame_time + real_fps = frame_count / elapsed_time if elapsed_time > 0 else 0 + avg_interval = np.mean(frame_intervals) if len(frame_intervals) > 0 else 0 + instant_fps = 1000.0 / avg_interval if avg_interval > 0 else 0 + + status = f"Frame {frame_count}: Real FPS: {real_fps:.1f} | Instant: {instant_fps:.1f}" + if drops_since_last_status > 0: + status += f" | ⚠️ {drops_since_last_status} drops detected" + drops_since_last_status = 0 + else: + status += f" | Total drops: {total_drops}" + + print(status) # Parse the incoming data frame = np.frombuffer(data, dtype=np.uint8).reshape((COLUMN_WIDTH, COLUMN_HEIGHT, CHANNELS)) @@ -77,7 +122,7 @@ while True: # Move to the next column position, wrapping around when reaching the end current_column = (current_column + 1) % DISPLAY_WIDTH - # Display the rolling buffer + # Display the rolling buffer (clean, no overlays) cv2.imshow("Rolling Column Stream", rolling_buffer) if cv2.waitKey(1) == 27: # ESC to quit