Major rewrite of image streaming to fix webcam freeze on headset
reconnect. Instead of sending images from spawned coroutines (which
hold stale sessions), send from on_cam_move event handler which
always receives the current live session.
Changes:
- Add _setup_tracking() helper for session initialization
- Add _send_image_frame() with rate limiting for all display modes
- Move image sending to on_cam_move event handler
- Simplify all spawned coroutines to setup + keep-alive
- Track _current_session on all event handlers
- JPEG quality at 50 for bandwidth (480p Quest 3 streaming)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents coroutine death when WebSocket session drops (headset
removed/sleep). Coroutine stays alive and resumes sending when
a new session connects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add last_data_time_shared timestamp updated in all three Vuer event
handlers (CAMERA_MOVE, HAND_MOVE, CONTROLLER_MOVE). Exposes
last_data_time property for the main teleop loop to detect VP
connection freshness (connected if data received within 1 second).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
visionOS Safari doesn't support immersive-ar WebXR sessions. Pass-through
on Vision Pro requires immersive-vr with a transparent scene background.
When display_mode is pass-through, pass background=none query param to Vuer
client, which (with corresponding JS patch) skips the opaque scene background.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>