Files
StarPilot/openpilot/starpilot/galaxy/camera_snapshot.py
T
Prabhaav Pillai c532223fa0 Restore V-Adj Spot Monitoring warnings and polish Galaxy settings, cameras, and updates
Bundle the verified VASM model, enable it at startup, and split VASM and vision speed-sign inference across little cores when both are active.
Restore VASM warnings in PiP activation, red outlines, and onroad blind-spot borders, including expanded Android Auto views.
Improve cabin snapshots with longer warm-up, adjusted capture timeouts, a fresh preview frame, and clearer capture buttons and save prompts.
Polish Galaxy settings with dimmed gated controls and icons, clearer vehicle fingerprinting and steering availability descriptions, rounded speed-offset ranges, and immediate refresh after saving.
Improve updater startup messages and preserve update/reconnect screens across service interruptions and restarts.
Add regression tests for the updated behavior.
2026-10-19 23:07:19 -04:00

72 lines
2.4 KiB
Python

"""One bounded parked snapshot from an already-running camera owner."""
import subprocess
import sys
import threading
import time
CAMERAS = frozenset(("cabin", "wide", "narrow"))
MAX_JPEG_BYTES = 1_000_000
_CAPTURE_LOCK = threading.Lock()
class SnapshotUnavailable(Exception):
pass
class SnapshotDenied(SnapshotUnavailable):
pass
class CameraSnapshot:
def __init__(self, *, spawn=subprocess.Popen, clock=time.monotonic):
self.spawn, self.clock = spawn, clock
self.last_request = {}
def capture(self, camera: str, *, permitted) -> bytes:
if camera not in CAMERAS:
raise ValueError("Unknown camera")
if not permitted():
raise SnapshotDenied
if not _CAPTURE_LOCK.acquire(blocking=False):
raise SnapshotUnavailable("Another snapshot is in progress")
process = None
try:
if self.clock() - self.last_request.get(camera, float('-inf')) < 1:
raise SnapshotUnavailable("Wait before another snapshot")
self.last_request[camera] = self.clock()
from openpilot.starpilot.galaxy.camera_request import request, boot_ns
request()
frame_after = boot_ns()
deadline = self.clock() + (24 if camera == "cabin" else 12)
process = self.spawn([sys.executable, '-m', 'openpilot.starpilot.galaxy.camera_snapshot_worker', camera],
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, close_fds=True)
while self.clock() < deadline:
if not permitted():
raise SnapshotDenied
try:
body, _ = process.communicate(timeout=min(.1, max(.001, deadline - self.clock())))
except subprocess.TimeoutExpired:
continue
if not permitted():
raise SnapshotDenied
if (process.returncode != 0 or not 4 <= len(body) <= MAX_JPEG_BYTES or
not body.startswith(b'\xff\xd8') or not body.endswith(b'\xff\xd9')):
raise SnapshotUnavailable("No fresh camera frame")
if camera == "cabin":
from openpilot.starpilot.galaxy.camera_request import mark_frame
mark_frame(clock=lambda: frame_after)
return body
raise SnapshotUnavailable("Camera timed out")
except OSError as error:
raise SnapshotUnavailable("Camera unavailable") from error
finally:
if process is not None:
if process.poll() is None:
process.kill()
process.wait()
if process.stdout is not None:
process.stdout.close()
_CAPTURE_LOCK.release()