MB-001 · Vision Pro head-tracked stereo camera rig
A remote pan-tilt stereo camera rig that follows the wearer's head. Nothing is mounted on the headset. Research of 3 Nov 2026 (HKT). All latency figures on this page are estimates until the glass-to-glass test replaces them.
Concept and status
| Item | Detail |
|---|---|
| Topology | Remote only. Nothing is mounted on the Vision Pro, and there is no headset-mounted variant. |
| Wired side | Cameras are USB-wired and servos are wired, both to the same rig machine (Raspberry Pi 5 class). |
| Only wireless hop | Rig machine ↔ Vision Pro over Wi-Fi 6: stereo video out, head pose in over UDP. |
| Camera in hand | One Quanrui USB48MP01-QFZ (serial OFZ20240723-XFH9GD3M). A second matched unit is needed for stereo. |
| Working path | Path B: two USB UVC webcams on a Pi 5. Path A (Insta360 Go Ultra) is ruled out. |
The wearer turns their head. The Vision Pro sends yaw and pitch to a far-away rig, two servos pan and tilt a camera bar, and two cameras about 63 mm apart stream a side-by-side stereo picture back, so the wearer sees through the rig in near real time.
System and wiring diagram
Orange dashed is the only wireless link. Blue is wired data, red is power, black dashed is common ground.
The Pi 5 has no hardware H.264 encoder, so video is software-encoded (Raspberry Pi white paper). Its onboard radio is Wi-Fi 5, and the headset is Wi-Fi 6 only, not Wi-Fi 7 (Apple specs). Put the Pi on Ethernet to the router, or add a USB Wi-Fi 6 adapter if it must be the access point.
Design paths
| Path | Status | What it is | Why |
|---|---|---|---|
| A: 2 × Insta360 Go Ultra | Ruled out | Two action cameras as the stereo eyes, streaming over their own Wi-Fi. | Insta360 says the Go Ultra cannot livestream and cannot be a webcam (https://onlinemanual.insta360.com/goultra/en-us/faq/functionality/livestreaming). Only an unofficial, reverse-engineered Wi-Fi pull exists (https://github.com/Daiki-Iijima/insta360-go-ultra-sdk), and each camera is its own hotspot, so a synced stereo pair is not realistic. |
| B: 2 × USB UVC webcams on a Pi 5 | Working path | Two UVC cameras on the rig machine, MJPEG capture, side-by-side compose, software H.264, WebRTC to the headset. | Direct frames, controllable encoding, wired to the same machine as the servos. Needs measuring: MJPEG decode and x264 cost on the Pi 5, and two-camera USB bandwidth. |
Software base: VisionProTeleop vs OpenTeleVision
| VisionProTeleop (chosen base) | OpenTeleVision | |
|---|---|---|
| Headset side | Native visionOS app from the App Store (Tracking Streamer) | Safari WebXR page served by Vuer, needs local HTTPS |
| Video | WebRTC, software x264 or VP8 in aiortc. Library takes one already side-by-side frame. | JPEG per eye over websocket by default; reports of high delay (a third-party issue cites more than 500 ms, anecdotal) |
| Head pose back | Full 4×4 matrix, about 120 Hz at source, gRPC or WebRTC data channel | Vuer events over websocket |
| Cameras | Any UVC camera | ZED Mini via the ZED SDK, hard-wired |
| Servo / gimbal | None in the repo | 2-DoF Dynamixel neck, but no limits, filtering or rate limiting |
| Published latency | Wireless stereo 2560×720: mean 59.9 ms, p95 117 ms (synthetic frames, not glass-to-glass) | None published |
| Upkeep | Active (last commit 28 Dec 2025), MIT | Last commit 26 Sep 2024, pinned old dependencies, Apache-2.0 |
Decision: base on VisionProTeleop and borrow only the head to yaw/pitch to active-neck idea from OpenTeleVision, adding the limits and filtering it lacks.
Recommended stack
| Layer | Pick | Why and caveats |
|---|---|---|
| Software base | VisionProTeleop avp_stream on the Pi, plus the stock Tracking Streamer app on the headset | WebRTC video and head pose already solved, published latency, no Swift fork. You build the dual-UVC stitch and the servo layer. |
| Rig machine | Raspberry Pi 5 | No hardware H.264 encoder. Onboard Wi-Fi is 802.11ac, so use Ethernet or a USB Wi-Fi 6 adapter. Stock aiortc caps video at 30 fps and about 3 Mbps; patch the bitrate cap and the x264 preset. |
| Servo control, heavy build (recommended) | Waveshare Bus Servo Adapter (A) over USB, 2 × Feetech STS3215 (7.4 V) | Closed loop with position, load and voltage feedback, torque hold, no PWM jitter, 19.5 kgf·cm. Adapter US$4.99, servo US$16.99 as shown on the Waveshare page (two variant prices were shown, check at order). |
| Servo control, light build | PCA9685 over I²C (US$14.95), 2 × Savox SH-0257MG+ (€21.95 each) | PCA9685 runs its own PWM, independent of Linux scheduling. The Savox gives 2.2 kgf·cm at 6 V against about 2.5 needed for tilt, so it is marginal unless the real module weighs about 30–40 g. |
| Speed-first alternative | PCA9685 with 2 × DS3218 (6.8 V) | Faster than the STS3215 (about 429 deg/s no-load) and 21.5 kgf·cm, but no feedback and about 4.4 A combined stall. |
| Servo power | Separate supply, never the Pi's 5 V pins | PWM servos: 5–6 V UBEC or PSU at 5 A or more. STS3215: 7.4 V (2S). Common ground with the Pi. |
| Pi power | Official 27 W USB-C PD supply (5.1 V / 5 A), US$14.04 | Raises the downstream USB limit to 1.6 A total. |
| Cameras | See Camera comparison | Owned Quanrui module first, then an ELP stereo module or global-shutter pair. |
| Failsafe | Hold 250 ms, park after 2 s, ramp on resume | Covers Wi-Fi drops, the headset app being killed, and packet bursts. These are design choices, not measured values. |
What to change in VisionProTeleop
- Feed it one stitched frame. Use configure_video(device=None, size="2560x720", fps=30, stereo=True) and push frames with update_frame(). stereo=True is metadata only; the library never composites two sources. Capture both cameras in your own threads with OpenCV V4L2 in MJPG and np.hstack the left and right frames.
- Raise the encoder caps. aiortc clamps H.264 at 3 Mbps. Set its MAX_BITRATE and DEFAULT_BITRATE to roughly 8–12 Mbps and set the x264 preset to ultrafast with zerolatency. This is a monkeypatch, untested on the Pi.
- Turn the head matrix into yaw and pitch. The library returns a 4×4 matrix, not a quaternion. Use the forward column. Which column and sign is still to be confirmed by printing the matrix while looking straight ahead.
- Filter and limit. One Euro filter, slew-rate limit matched to the servo, deadband about 0.3–0.5°, clamp inside the mechanical stops, command the servos at 100 Hz.
- Add the failsafe. Drop stale sequence numbers. Hold for 250 ms with no valid packet, glide to park after 2 s, and ramp from the current angle on resume.
Round-trip latency budget
Per-stage budget
| Stage | Where | Best (ms) | Typical (ms) | Worst (ms) | Basis |
|---|---|---|---|---|---|
| S1 Head pose out | Headset | 1 | 6 | 12 | Estimate |
| S2 Wi-Fi 6 up (24-byte UDP) | Wireless | 2 | 4 | 25 | Estimate |
| S3 Pose in, clamp, servo command | Wired | 1 | 3 | 20 | Estimate; a bus-servo packet is about 0.1 ms, a 50 Hz PWM frame can wait up to 20 ms |
| S4 Servo response | Wired control | 15 | 40 | 90 | Estimate |
| S5 Cameras capture over USB | Wired | 50 | 90 | 110 | Derived from a third-party measurement on other cameras |
| S6 Compose, MJPEG decode, H.264 encode | Rig machine | 14 | 34 | 60 | Estimate (14 + 20 typical) |
| S8 Wi-Fi 6 down | Wireless | 3 | 6 | 40 | Estimate |
| S9 Jitter buffer + decode | Headset | 4 | 12 | 30 | Typical decode part sourced from Transitive (7 ms), rest estimate |
| S11 Render to the eyes | Headset | 8 | 15 | 30 | Estimate |
| Total | 98 | 210 | 417 | Sums of the columns above |
Anchors: WebRTC latency breakdown and VisionProTeleop's own benchmark, wireless stereo 3840×1080 min 16, mean 57, p95 113 ms (repo). That benchmark uses synthetic frames and a Mac encoder, so it covers only the encode-to-display half. It is not glass-to-glass.
Per-scenario totals
| Scenario | Best (ms) | Typical (ms) | Worst (ms) | Notes |
|---|---|---|---|---|
| (a) Machine on Ethernet, router, headset on Wi-Fi 6 | 98 | 210 | 417 | Baseline. Contention from other Wi-Fi clients drives the tail. |
| (b) Machine is the Wi-Fi access point | 96.5 | 207 | 384 | Saves about 3 ms typical, more in the tail. The Pi 5 radio is Wi-Fi 5, so add a Wi-Fi 6 adapter. Own channel and SSID matter more than the Wi-Fi generation (https://jitter.is/blog/ethernet-vs-wifi-jitter/). |
| (c) Rig remote over the internet or VPN, WAN round trip R = 20 / 60 / 150 ms | ≈ 237 / 277 / 367 | Adds R plus about 7 ms. R values are examples, not measurements. Pose packets need UDP or an unordered data channel. |
What the lag looks like: at about 210 ms, a head turn of 30 / 90 / 250 / 380 deg/s leaves the picture about 6 / 19 / 53 / 80 degrees behind the head. The fix is to draw the stereo quad world-locked at the rig's pan and tilt angle at capture time, send those angles in the frame metadata, and let the Vision Pro compositor move it. Prediction of 30–60 ms on the pose helps, but it cannot hide camera, encode and network delay, because those delay the picture, not the command.
| Lever | Saves (typical, estimate) | Cost |
|---|---|---|
| 60 fps camera mode, short exposure | About 30–40 ms in S5 | Needs light; check the real modes with v4l2-ctl |
| MJPEG passthrough, no decode or encode | About 34 ms (S6 + S7) | 10–40 Mbps per eye, lost frames, no pairing guarantee |
| Hardware-encode board instead of the Pi 5 | About 10–15 ms in S7 | Different board |
| Digital or bus servo, 200+ Hz command | S3 up to about 15 ms, S4 about 10–20 ms | Cost and power supply |
| Pi as dedicated access point, clean 5 GHz channel, Wi-Fi 6 adapter | About 3 ms typical, much less tail | Extra adapter |
Realistic tuned target is about 150–170 ms typical (estimate), which is why reprojection matters more than any single component.
Servo speed and torque
Head speed to follow: slow 30–90 deg/s, quick 250–380 deg/s. A reflex flick near 780 deg/s cannot be tracked with hobby servos, and need not be. Recommended target: at least about 400 deg/s no-load and about 280 deg/s after load, so a 250 deg/s turn is followed without saturating. Above about 380 deg/s, let the servo saturate and rely on reprojection.
| Servo | No-load (deg/s) | Derated ×0.7 (deg/s) | Extra lag at 250 deg/s | Extra lag at 380 deg/s | Stall torque (kgf·cm) | Weight |
|---|---|---|---|---|---|---|
| MG90S @ 6 V | 750 | 525 | keeps up | keeps up | 1.8–2.2 | 13 g |
| DS3218 @ 6.8 V | 429 | 300 | keeps up | +42 ms | 21.5 | 60 g |
| MG996R @ 6 V | 400 | 280 | keeps up | +56 ms | 11 | 55 g |
| STS3215 @ 7.4 V | 312 | 219 | +34 ms | +116 ms | 19.5 | 55 g |
| STS3215 @ 6 V | 251 | 176 | +100 ms | +182 ms | 19.5 at 7.4 V | 55 g |
Speeds are vendor no-load figures converted to deg/s; the 0.7 load derating and the lag arithmetic are derived or estimated, not measured. Vendor pages disagree in places (MG996R speed, STS3215 torque), so check your own units.
| Case | Payload (assumed) | Tilt axis needs (×3 margin) | Pan axis needs (×3 margin) |
|---|---|---|---|
| Light: 2 × 38 mm module | 0.24 kg, centre of mass 30 mm from the tilt axis | At least 2.5 kgf·cm | At least 0.6 kgf·cm |
| Heavy: 2 × Logitech Brio | 0.40 kg envelope, centre of mass 50 mm from the tilt axis | At least 7.5 kgf·cm | At least 2.3 kgf·cm |
- Tilt sets the torque requirement. Pan mostly needs a bearing, because the whole payload sits on its shaft. Balance the camera platform around the tilt axis and the static term nearly vanishes.
- Recommended: STS3215 at 7.4 V for the heavy build, for feedback, torque hold and a hardware acceleration ramp that the failsafe uses. Keep its speed limit just under 300 deg/s.
- If speed matters more than feedback: DS3218 at 6.8 V on a PCA9685, with a separate supply sized for about 2.2 A stall each.
- Avoid a 50 Hz-only PWM path where you can; it adds up to 20 ms of command wait. Command at 100–200 Hz.
- Sagging a 6.8 V servo to 5 V costs about 13% speed and 16% torque (derived from the DS3218 datasheet), so the supply must hold its voltage under load.
- Smoothing adds lag of about 1/(2π·fc): 20 Hz is 8 ms, 10 Hz is 16 ms, 5 Hz is 32 ms. Use a One Euro filter and keep the cutoff at 10 Hz or more while moving.
- Savox SH-0257MG+ and MG90S are fine for slow turns but marginal on torque for anything heavier than the light case.
Power plan
| Rail | Load | Running | Stall or worst case | Source |
|---|---|---|---|---|
| Pi 5 supply, 5.1 V / 5 A | Pi 5 and peripherals | Not sourced | PSU 5 A; USB total at most 1.6 A | Raspberry Pi 27 W brief |
| USB from the Pi | 2 × USB48MP01 module | 1.10–1.22 A | Same | ELP listing (550–610 mA each) |
| USB via powered hub | 2 × Brio | 1.0–1.8 A (500 mA declared, about 896 mA reported each) | Same | Brio descriptor, one user report |
| Servo rail 5–6 V | 2 × Savox SH-0257MG+ | 0.36 A rated | 2.8 A | Savox |
| Servo rail 5–6 V | 2 × MG90S | About 0.2 A each (assumed) | About 1.7–1.8 A (secondary datasheets) | Third-party |
| Servo rail 6 V | 2 × MG996R | 1.0–1.8 A | 5.0 A | TowerPro / Digikey datasheet |
| Servo rail 6.8 V | 2 × DS3218 | Not given | 4.4 A (3.6 A at 5 V) | DS3218 datasheet |
| Servo rail 7.4 V | 2 × STS3215 | 0.30 A no-load (loaded: not sourced) | 5.0 A | Waveshare |
- Servo rail headline: about 0.4–1.0 A running and about 5 A at stall for the heavy builds, about 2–2.8 A at stall for the light build. Size the supply for the stall figure, or fuse it (about 5–7 A) and use the STS3215's software torque and current limits.
- Servos always run from a separate supply with a common ground to the Pi. Never power them from the Pi's 5 V pins or USB.
- Bulk capacitors of 470–1000 µF per one or two servos at the servo input, more at the supply for the heavy build. This is a rule of thumb with no sourced value; adjust after a brown-out test.
- Two Brio cameras may exceed the Pi's 1.6 A USB budget, so use a powered USB 3.0 hub.
- To check: the Waveshare adapter page lists a 9–12.6 V supply for ST-series servos, yet the 7.4 V STS3215 variant needs 7.4 V. Confirm in the adapter wiki (https://docs.waveshare.com/Bus_Servo_Adapter_A) before wiring; otherwise use the 12 V servo variant (30 kgf·cm).
3D mock-up and CAD
Drag to rotate, scroll or pinch to zoom. Concept CAD: several dimensions are assumptions (see the model notes below), so check them against vendor drawings before printing.
Switch the render style (shaded, solid, clay, wireframe, x-ray, blueprint) or press Explode to pull the parts apart. If the 3D viewer does not appear, WebGL may be unavailable or blocked; the renders and STL/GLB downloads below still work.
Renders (heavy build)
Click a render to open it as an interactive 3D model (orbit, zoom, pan). The model loads only when opened.
3D
3D
3D
3D
3D
3D
3DModel notes
| Item | Value |
|---|---|
| Camera spacing | 63 mm, inside the Vision Pro IPD range of 51–75 mm |
| Camera module | 38 × 38 mm, depth 15 mm (depth is an assumption) |
| Servo (heavy) | STS3215, 45.2 × 24.7 × 35 mm; shaft offset about 10 mm is approximate |
| Base deck | 100 × 158 × 6 mm, with a 6.6 mm hole for a 1/4-20 tripod screw |
| Walls and plates | Cradle wall 2.4 mm, yoke plate 4 mm, arms 4 mm, camera bar 121 × 52 × 4 mm |
| Tilt axis | 77 mm above the deck |
| Ghost parts | Pi 5 (56 × 85 × 17 mm), PCA9685 (62 × 14 × 8 mm), power block (14 × 30 × 10 mm) |
| Brio | 102 mm wide, so the CAD mounts it in portrait |
| Axes | Cameras look along +Y, the pan axis is Z, and the tilt axis is X |
Downloads
Camera comparison
Google Sheet (owner access) — 20 cameras, shortlist and notes (tabs: Cameras, Shortlist, Notes). The sheet is private to the owner; the same table is embedded below and available as CSV.
Cameras page → Photos, sort, filters and where-to-buy links for all 20 cameras.
Prices are as shown on each page on 3 Nov 2026. Where a vendor publishes no figure, the table says unknown.
Shortlist
| Rank | Camera | Price | Why | Watch out for |
|---|---|---|---|---|
| 1 | Quanrui USB48MP01-QFZ (owned, CAM-01) | Owned; a second ELP unit is US$116.99 | Zero-cost prototype. MJPEG 4K30 and 1080p30 on USB 2.0, 38 × 38 mm. | Rolling shutter and autofocus. Weight only published as 100 g on the ELP page (unverified), so weigh it. |
| 2 | ELP-USB3D1080P02-V83 (CAM-05) | US$78.23 | Two sensors on one board, one synced 3840 × 1080 side-by-side MJPEG stream at 60 fps, about 45 g, one USB device. | Baseline not published; modest sensors. |
| 3 | Arducam B0385 OV9782 (CAM-10) | US$59.99 | Colour global shutter, MJPG 100 fps at 1280 × 800, hardware trigger input to sync two units. Suits head motion. | 1280 × 800 only; patchy stock; an IR-filter conflict between the datasheet and one listing. |
| 4 | ELP-USBFHD06H-L100 (CAM-06) | US$54.60 | H.264 or MJPEG at 1080p30 on the camera, about 30 g. Offloads the Pi, which has no H.264 encoder. | 30 fps, no sync between two units; pair frames in software. |
Benchmarks, not picks: ZED Mini (US$399, 63 mm baseline, about 60 g, but the encode runs on the host) and Logitech Brio 4K (US$169.99, about 65 g per the Logitech datasheet with an 85 g conflict on the support page, plus a 69 g clip). Mono OV9281 modules are not suitable for colour viewing.
All cameras (from the sheet CSV)
Click a column header to sort. Scroll sideways for all 22 columns.
| ID | Name / model | Maker | Sensor | Max resolution | FPS @1080p | FPS @4K | Output formats (MJPEG/YUY2/H.264) | Sensor size | Min lux | Low-light notes | Latency notes | USB / UVC / Pi compatibility | Size (mm) | Weight (g) | FOV / lens | Shutter | Price | Where to buy (link) | Stereo suitability | Source URL | Notes |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| CAM-01 | Quanrui Vision 全瑞视讯 USB48MP01-QFZ (owned; same family as RERVISION RER-USB48MP01 / ELP-USB48MP01) | Quanrui Vision / RERVISION (锐尔威视) / ELP (same Shenzhen supplier family) | Samsung S5KGM1ST04-FG9 (GM1) 48MP | 8000x6000 (3 fps MJPEG per rervision.cn; 5 fps per ELP page; 4000x3000 12-15 fps depending on page) | 30 (MJPEG) | 30 (3840x2160 MJPEG) | MJPEG / YUY2 (YUYV) | 1/2 inch (4:3) | 0.3 | S/N 36 dB; dynamic range 82 dB (rervision.cn); sensitivity 1.4 V/lux-sec; autofocus (~200 ms) may hunt in dim light (untested) | unknown (vendor publishes no latency figure; needs glass-to-glass test) | USB 2.0 High Speed, UVC; ELP page states Linux (kernel >2.6.26) and Raspberry Pi support; 550-610 mA per unit | 38 x 38 (double-deck board; height not published) | 100 (ELP AF70 page only; rervision.cn publishes none - looks high for a bare 38x38 board, weigh your unit) | Autofocus M8.15 lens, ~82 deg D / ~70 deg H (this QFZ lens variant unconfirmed; ELP also lists AF100 / KAF70 / KAF100 variants whose FOV was not verified) | Electronic rolling | Owned unit - n/a. Same-family ELP-USB48MP01-AF70: USD 116.99 (webcamerausb.com, as shown 2026-11-03) | https://www.webcamerausb.com/elp-48mp-usb-camera-fastfocus-automatically-high-definition-8000x6000-industrial-webcam-camera-module-uvc-free-driver-camera-usb20-for-raspberry-pi-linux-windows-android-p-421.html | OK for a first prototype: need a 2nd unit; no hardware sync; two independent autofocus lenses can hunt differently; 1080p capped at 30 fps; each unit ~550-610 mA | http://www.rervision.cn/4800%E4%B8%87usb%E6%91%84%E5%83%8F%E5%A4%B4-c-109_188/4800%E4%B8%87%E8%87%AA%E5%8A%A8%E5%AF%B9%E7%84%A6usb%E6%91%84%E5%83%8F%E5%A4%B4%E6%A8%A1%E7%BB%84%E5%B7%A5%E4%B8%9A%E7%9B%B8%E6%9C%BA%E5%9B%BE%E5%83%8F%E5%88%86%E6%9E%90%E5%8C%BB%E7%96%97%E5%BD%B1%E5%83%8F%E7%94%B5%E8%84%91%E7%9B%B4%E6%92%AD-p-187.html ; https://www.webcamerausb.com/elp-48mp-usb-camera-fastfocus-automatically-high-definition-8000x6000-industrial-webcam-camera-module-uvc-free-driver-camera-usb20-for-raspberry-pi-linux-windows-android-p-421.html | '-QFZ' suffix not found in any public listing; specs are the family's. Spec inconsistencies between pages (fps at 8000x6000/4000x3000, S/N, weight); 1080p30 and 4K30 MJPEG are consistent on all pages. Serial OFZ20240723-XFH9GD3M. |
| CAM-02 | ELP-USBFHD08S-L60 (OV4689 high-speed) | ELP (Ailipu) | OmniVision OV4689 | 1920x1080 | 60 (MJPEG) | n/a | MJPEG / YUY2 (YUYV) | 1/3 inch (2.0 um pixels) | 0.1 | S/N 38.3 dB; dynamic range 64.6 dB; sensitivity 1.9 V/lux-sec (vendor page) | unknown (vendor publishes no latency figure; needs glass-to-glass test); derived frame interval at 60 fps = 16.7 ms, 120 fps @720p = 8.3 ms | USB 2.0 HS, UVC; page lists Linux and Raspberry Pi; 150-185 mA | 38 x 38 | ~30 (vendor page) | S-mount fixed focus; page lists 3.6 mm standard, options 2.1/2.8/6/8/12 mm; model L60 = 6 mm lens, FOV not stated; 'FOV(D)170' appears only in the optional-lens line | Electronic rolling | USD 65.10 (webcamerausb.com, as shown 2026-11-03) | https://www.webcamerausb.com/elp-260fps120fps60fps-usb20-web-camera-driver-free-ov4689-cmos-sensor-1080p-hd-mini-high-frame-rate-module-camera-260fps-p-271.html | Good matched pair (2 identical units) if no hardware sync is acceptable; best 1080p60 MJPEG option here | https://www.webcamerausb.com/elp-260fps120fps60fps-usb20-web-camera-driver-free-ov4689-cmos-sensor-1080p-hd-mini-high-frame-rate-module-camera-260fps-p-271.html | Two 1080p60 MJPEG streams on USB 2.0: check bandwidth per controller. |
| CAM-03 | ELP-USBGS800P03-V100 (OV9281 mono global shutter) | ELP (Ailipu) | OmniVision OV9281 (monochrome) | 1280x800 | n/a (max 1280x800 / 1280x720 @120 MJPEG) | n/a | MJPEG | 1/4 inch (3 um pixels) | 0.3 | S/N 37 dB; dynamic range 70 dB; mono (no colour filter) | unknown (vendor publishes no latency figure; needs glass-to-glass test); derived frame interval at 120 fps = 8.3 ms | USB 2.0 HS, UVC, Linux listed; 100-130 mA | 38 x 38 | unknown | M12 'no distortion' V100 lens; FOV degrees not stated | Global | USD 48.29 (webcamerausb.com, as shown 2026-11-03) | https://www.webcamerausb.com/elp-global-shutter-usb-camera-module-800p-120fps-480p-210fps-240p-420fps-120p-640fps-high-speed-usb-camera-board-with-no-distortion-lens-monochrome-usb-webcam-plug-paly-for-industrial-machines-p-450.html | Low: monochrome only (no colour video for the headset); no sync pin documented | https://www.webcamerausb.com/elp-global-shutter-usb-camera-module-800p-120fps-480p-210fps-240p-420fps-120p-640fps-high-speed-usb-camera-board-with-no-distortion-lens-monochrome-usb-webcam-plug-paly-for-industrial-machines-p-450.html | Useful as a low-latency/no-rolling-shutter test camera, not for final colour passthrough. |
| CAM-04 | ELP-USB3DGS800P (dual OV9281 synchronized stereo; variants H120 / V83 / L180) | ELP (Ailipu) | 2x OmniVision OV9281 (monochrome) | 2560x800 (side-by-side stitched) | n/a (2560x800 @120 fps) | n/a | MJPEG (single stitched UVC stream) | 1/4 inch | unknown | Mono sensors; vendor claims 'higher sensitivity, lower noise'; no lux figure on page | unknown (vendor publishes no latency figure; needs glass-to-glass test); derived frame interval at 120 fps = 8.3 ms | USB 2.0 UVC; page lists Raspberry Pi / Jetson Nano / OpenCV | 80 x 16.5 | unknown | L180 variant: 180 deg fisheye, 149 deg HFOV; H120 variant: ~98 deg HFOV (per vendor search listing, page itself bot-blocked); baseline not published | Global | USD 88.80 for L180 variant (webcamerausb.com, as shown 2026-11-03); other variants unknown | https://www.webcamerausb.com/elp-duallens-synchronized-global-shutter-monochrome-usb-camera-1200p-60fps-480p-120fps-fisheye-wide-angle-for-robot-vision-highspeed-motion-analysis-p-576.html | Hardware-synchronized global-shutter pair in one UVC stream, but monochrome only | https://www.webcamerausb.com/elp-duallens-synchronized-global-shutter-monochrome-usb-camera-1200p-60fps-480p-120fps-fisheye-wide-angle-for-robot-vision-highspeed-motion-analysis-p-576.html ; https://www.hdusbcameras.com/elp-ov9281-800p-global-shutter-usb-camera-module-high-speed-120fps-at-2560x800-210fps-at-640x240-monochrome-hardware-synchronized-stereo-3d-vision-webcam-for-robotics.html | Page headline says '1200P 60fps' but body says 120 fps @ 2560x800; treat 120 fps as 'advertised'. |
| CAM-05 | ELP-USB3D1080P02-V83 (dual JX-F35 1080p synchronized stereo) | ELP (Ailipu) | 2x JX-F35 (1/2.7 inch, 3.0 um pixels) | 3840x1080 (side-by-side stitched; each eye 1920x1080) | 60 (3840x1080 MJPEG @60 = 2x 1080p60) | n/a | MJPEG / YUY2 (YUYV) | 1/2.7 inch | 0.3 | Sensitivity 4.5 V/lux-sec; no S/N or dynamic-range figures on page | unknown (vendor publishes no latency figure; needs glass-to-glass test); single stitched stream = both eyes captured in the same frame | USB 2.0 HS (Type-C), UVC, 210-240 mA; page lists Raspberry Pi, OpenCV, V4L2 | 80 x 16.5 (board) | ~45 (webcamerausb.com page) | M12 no-distortion lens, ~80-85 deg HFOV / 56 deg VFOV; other lenses optional (65-187 deg HFOV); baseline not published | Electronic rolling | USD 78.23 (webcamerausb.com, as shown 2026-11-03) | https://www.webcamerausb.com/elp-1080p-synchronous-dual-lens-usb-camera-4mp-3840x1080p-60fps-3d-stereo-camera-module-for-deep-inspectionface-recognition-distance-measurement-p-442.html | Best ready-made stereo: two eyes in one synchronized MJPEG stream, 1080p60 per eye, light and tiny. Baseline is fixed (unpublished) and may be well under the 51-75 mm human IPD range | https://www.webcamerausb.com/elp-1080p-synchronous-dual-lens-usb-camera-4mp-3840x1080p-60fps-3d-stereo-camera-module-for-deep-inspectionface-recognition-distance-measurement-p-442.html ; https://www.elpcctv.com/elp-4mp-3840x1080p-60fps-synchronous-dual-lens-usb-camera-module-with-no-distortion-85-degree-lens-p-406.html | Bare board, no enclosure. Measure baseline yourself (80 mm board suggests lens spacing < 80 mm, not confirmed). |
| CAM-06 | ELP-USBFHD06H-L100 (IMX323/IMX322, on-camera H.264) | ELP (Ailipu) | Sony IMX322 per svpro.cc spec table (other ELP/Amazon listings use IMX323 in the title; same board) | 1920x1080 | 30 (H.264, MJPEG) | n/a | H.264 / MJPEG / YUY2 (YUV only up to 800x600@15) | 1/2.9 inch | 0.01 | S/N 42 dB; dynamic range 86 dB; sensitivity 5.0 V/lux-sec - best low-light spec among the cheap ELP boards | unknown (vendor publishes no latency figure; needs glass-to-glass test); on-camera H.264 adds encoder latency (size unknown) | USB 2.0 HS, UVC, OTG; Linux 2.6+ listed on spec table; 140-190 mA | 38 x 38 (compatible 32 x 32) | ~30 (vendor spec table; same page's 'Weight 0.25 kg' is shipping/packaging) | M12 'no distortion' L100 lens; FOV degrees not stated (other lenses: 2.1/2.8/3.7/6 mm, 170/180 deg fisheye) | Electronic rolling | USD 54.60 (svpro.cc, as shown 2026-11-03); USD 57.20 (webcamerausb.com, as shown by search index) | https://www.svpro.cc/product/elp-no-distortion-low-light-usb-camera-module-h-264-mini-1080p-security-usb-webcam-for-industry/ | Pair of two for H.264 offload on Pi 5 (no HW encoder): Pi just forwards H.264; no sync | https://www.svpro.cc/product/elp-no-distortion-low-light-usb-camera-module-h-264-mini-1080p-security-usb-webcam-for-industry/ | Verify H264 appears in v4l2-ctl --list-formats-ext; H.264 GOP/bitrate controls unknown. |
| CAM-07 | ELP-SUSB1080P01-L80 (IMX291 USB 3.0) | ELP (Ailipu) | Sony IMX291 | 1920x1080 | 50 (MJPEG and uncompressed YUY2 on USB 3.0) | n/a | MJPEG / YUY2 (YUYV) | 1/2.8 inch (2.9 um pixels) | 0.01 | S/N 40 dB; dynamic range 65 dB; sensitivity 1.9 V/lux-sec (vendor page) | unknown (vendor publishes no latency figure; needs glass-to-glass test); YUY2 on USB 3.0 avoids camera-side JPEG; derived frame interval at 50 fps = 20 ms | USB 3.0, UVC; Linux listed; 170-210 mA; Pi 5 has 2x USB 3.0 ports (raspberrypi.com) | 38 x 38 | ~50 (vendor page) | 8 mm M12 lens (L80); FOV degrees not stated; other lenses optional | Electronic rolling | USD 58.80 (webcamerausb.com, as shown 2026-11-03) | https://www.webcamerausb.com/elp-usb30-camera-50fps-1080p-720p-2mp-sony-sensor-usb-30-webcam-for-linux-android-windows-p-262.html | Good matched pair: 1080p50, uncompressed option; Pi 5 has two USB 3.0 ports (supports simultaneous 5 Gbps per raspberrypi.com) so one per port | https://www.webcamerausb.com/elp-usb30-camera-50fps-1080p-720p-2mp-sony-sensor-usb-30-webcam-for-linux-android-windows-p-262.html ; https://www.raspberrypi.com/products/raspberry-pi-5/ | Pick lens: L80 is a narrow 8 mm; L36 (3.6 mm) variant is listed at same price. Uncompressed 1080p50 YUY2 x2 would need software encode on Pi. |
| CAM-08 | Arducam B0201 1080P low-light USB (IMX291, H.264) | Arducam (UCTRONICS) | Sony IMX291 | 1947x1109 effective | 30 (H.264 and MJPG) | n/a | MJPG / YUY2 (640x480@30 only) / H.264 | 1/2.8 inch (2.9 um pixels) | unknown (datasheet gives none; a 0.001 lux marketing claim seen only in a search snippet, unverified) | Dynamic range 80 dB; fixed focus F2.0 lens with integral IR filter | unknown (vendor publishes no latency figure; needs glass-to-glass test); on-camera H.264 adds encoder latency (size unknown) | USB 2.0 UVC; datasheet lists Windows, Linux, Mac; max 300 mA; Pi not specifically stated | unknown (not in datasheet text) | unknown | 120 deg D, M12, fixed focus | Electronic rolling (not stated; IMX291 is rolling) | USD 71.55 special order (RobotShop, data as of 2026-10-14 UTC); EUR 63.90 Welectron (search snippet only) | https://www.robotshop.com/products/arducam-1080p-low-light-wide-angle-usb-camera-module-w-microphone | Matched pair possible; on-camera H.264 offloads Pi; no sync | https://www.uctronics.com/download/Amazon/B0201_IMX291_120_UVC_Camera_Datasheet.pdf ; https://www.robotshop.com/products/arducam-1080p-low-light-wide-angle-usb-camera-module-w-microphone | Arducam's own site listed it out of stock per search index; arducam.com pages block the fetcher. |
| CAM-09 | Arducam B0332 OV9281 mono global shutter USB | Arducam | OmniVision OV9281 (monochrome) | 1280x800 | n/a (1280x800 max) | n/a | MJPG / YUY2 (10 fps only) | 1/4 inch (3 um pixels) | unknown | Dynamic range 68 dB; no IR-cut filter (IR sensitive) | unknown (vendor publishes no latency figure; needs glass-to-glass test); derived frame interval at 100-120 fps = 8-10 ms | USB 2.0 UVC; Windows/Linux/Mac per Arducam search-index copy; max 200 mA | 38 x 38 | 49.5 (arducam.com product table 'Weight 0.0495 kg' - may be shipping weight) | 70 deg H, M12 low-distortion lens | Global | USD 49.99 (arducam.com via search-index copy, page blocked to fetcher); USD 63.12 (RobotShop, re-stocking soon, data as of 2026-11-02 UTC) | https://www.robotshop.com/products/arducam-120fps-global-shutter-usb-camera-board-1mp-ov9281-uvc-m12-lens | Mono only; external trigger pins (F/G) available like B0385 | https://www.arducam.com/arducam-100fps-global-shutter-usb-camera-board-1mp-720p-ov9281-uvc-webcam-module-with-low-distortion-m12-lens-without-microphones-for-computer-laptop-android-device-and-raspberry-pi.html ; https://www.robotshop.com/products/arducam-120fps-global-shutter-usb-camera-board-1mp-ov9281-uvc-m12-lens ; https://cdn.robotshop.com/media/A/Adu/RB-Adu-256/pdf/arducam-1mp-ov9281-usb-camera-120fps-global-shutter-uvc-low-distortion-m12-lens-manual.pdf | Frame rate disagrees by page: 100 fps (arducam.com) vs 120 fps (RobotShop and manual). |
| CAM-10 | Arducam B0385 OV9782 colour global shutter USB (external trigger) | Arducam | OmniVision OV9782 (colour) | 1280x800 | n/a (1280x800 max) | n/a | MJPG (100 fps) / YUY2 (10 fps) | 1/4 inch | unknown | Dynamic range 68 dB; datasheet says IR filter fitted (visible light only) but one listing copy says 'without IR filter' - check; no lux figure | unknown (vendor publishes no latency figure; needs glass-to-glass test); derived frame interval at 100 fps = 10 ms | USB 2.0 UVC; Raspberry Pi named on vendor page; max 200 mA | 38 x 38 (datasheet; hole pitch 34x34 / 28x28) | unknown | 70 deg H, EFL 2.8 mm, distortion <1 %, M12x0.5 | Global | USD 59.99 (arducam.com via search-index copy, page blocked to fetcher); Amazon US 'currently unavailable' (checked 2026-11-03); iot-store.com.au out of stock | https://www.arducam.com/100fps-global-shutter-color-usb-camera-board-1mp-ov9782-uvc-webcam-module-with-low-distortion-m12-lens-without-microphones-for-computer-laptop-android-device-and-raspberry-pi-arducam.html | Best DIY synchronised colour pair: solder F (trigger) and G (GND); rising edge, pulse >= 2 us; see Arducam external-trigger doc for mode switching. Only 1280x800, and Linux trigger-mode behaviour is untested by us | https://docs.arducam.com/UVC-Camera/Appilcation-Note/External-Trigger-Mode/OV9782-Global-Shutter/ ; https://iot-store.com.au/products/arducam-global-shutter-camera-b0385 ; Arducam B0385 datasheet PDF (V1.0, 16.12.2021; read from a saved copy, URL not retained) | Stock is patchy. |
| CAM-11 | Arducam B0495 AR0234 colour global shutter USB 3.0 | Arducam | onsemi AR0234 (colour) | 1920x1200 | n/a at 1080p; 1920x1200 @50 (YUY2 on USB 3.0) | n/a | YUY2 only (no MJPEG per datasheet) | 1/2.6 inch (3.0 um pixels) | unknown | F3.0 lens; integral IR-cut; no lux figure | unknown (vendor publishes no latency figure; needs glass-to-glass test); uncompressed so no camera-side encode | USB 3.2 Gen1 Type-C, UVC, Windows/Linux; 1.45 W max; on USB 2.0 only 960x600 @10 fps | 34 x 34 | unknown | 95 deg D (82 H x 66 V), M12 manual focus, 3 % distortion | Global | CAD 221.41 backorder (ca.robotshop.com, data as of 2026-10-31 UTC) | https://ca.robotshop.com/products/arducam-23mp-ar0234-color-global-shutter-usb-30-camera-module-w-encolsure | Nice image (colour global shutter) but 2 uncompressed YUY2 streams = host software encode on Pi 5; expensive; no sync pin documented | https://blog.arducam.com/downloads/datasheet/B0495_AR0234_Global_Shutter_USB3.0_Camera_Module_Datasheet.pdf ; https://ca.robotshop.com/products/arducam-23mp-ar0234-color-global-shutter-usb-30-camera-module-w-encolsure | RobotShop copy says 80 fps; datasheet says 80 fps only at 960x600. |
| CAM-12 | Arducam ezBOX-Swift B0559 (1080p100 MJPG, autofocus) | Arducam | Sony 1080P colour sensor (exact model not published) | 1920x1080 | 100 (MJPG) | n/a | MJPG only | 1/2.8 inch (2.24 um pixels) | unknown | F1.8 lens, integral 650 nm IR filter; 720p180, VGA 360 fps (software may report only 240) | unknown (vendor publishes no latency figure; needs glass-to-glass test); derived frame interval at 100 fps = 10 ms | USB 2.0 UVC; datasheet lists Windows, Linux; 1.75 W; JST B4B-ZR connector | 32 x 32 x 1.6 (board) | unknown | 78 deg D x 65 H x 52 V, EFL 3.95 mm, autofocus 10 cm-infinity | Rolling | EUR 74.99 (antratek.com, in stock, as shown 2026-11-03) | https://www.antratek.com/arducam-ezbox-swift | Fast 1080p100 pair possible; autofocus on both could hunt independently; no sync | https://cdn.arducam.com/downloads/datasheet/B0559_1080P_High%20framrate_USB_Camera_Datasheet.pdf ; https://www.antratek.com/arducam-ezbox-swift | Only 32x32 board; weight and enclosure size unpublished. |
| CAM-13 | GXIVISION LSM36156 dual-lens 4MP stereo USB (baseline adjustable) | GXIVISION (Shenzhen Guoxun Intelligent Technology) | unknown (not on listing) | 3840x1080 (stitched) | 30 (3840x1080 MJPG @30) | n/a | MJPEG 3840x1080@30; YUY2 3840x1080@3 | unknown | unknown | unknown | unknown (vendor publishes no latency figure; needs glass-to-glass test) | USB 2.0, UVC driver-free; buyer review: works on laptop and Android; some apps show only one eye unless 3840x1080 selected | unknown | unknown | Fixed focus; FOV unknown; 'baseline adjustable' per listing | Rolling | USD 62.97 + USD 4.50 shipping (eBay HK listing, as shown 2026-11-03); sibling LSM36156/2: USD 62.05 | https://www.ebay.com.hk/itm/355093813100 | Adjustable baseline is attractive for matching IPD (51-75 mm), synchronized one-stream; only 30 fps and unspecified sensors | https://www.ebay.com.hk/itm/355093813100 ; https://www.ebay.com.hk/itm/355549742612 | An AliExpress listing for the same seller family exists (aliexpress.us/item/3256809657959986) but could not be opened (bot block), so no AliExpress specs are used. Seller store also lists a 720p adjustable-baseline stereo module (HK$421.89, not opened). |
| CAM-14 | GXIVISION S2M03 SC200AI 1080p60 USB module | GXIVISION | SmartSens SC200AI | 1920x1080 | 60 advertised (a verified buyer review says it 'actually supports 1080p at 30fps' - verify) | n/a | MJPEG / YUY2 | unknown | unknown | unknown | unknown (vendor publishes no latency figure; needs glass-to-glass test) | USB 2.0 UVC plug-and-play; buyer review: works on Linux | unknown | unknown | unknown on listing | Rolling | USD 33.55 + USD 3.20 shipping (eBay HK, HK$263.19, as shown 2026-11-03) | https://www.ebay.com.hk/itm/355024084095 | Cheap matched pair candidate but frame rate unverified; no sync | https://www.ebay.com.hk/itm/355024084095 | Treat 60 fps as unverified until v4l2-ctl --list-formats-ext confirms. |
| CAM-15 | GXIVISION S2M06 2MP colour global shutter USB (1600x1200 @60) | GXIVISION | unknown (not on listing) | 1600x1200 | n/a (1600x1200 @60 advertised) | n/a | MJPEG / YUY2 | unknown | unknown | unknown | unknown (vendor publishes no latency figure; needs glass-to-glass test) | USB 2.0 UVC driver-free | unknown | unknown | unknown | Global | USD 119.00 + USD 3.20 shipping (eBay HK, as shown 2026-11-03) | https://www.ebay.com.hk/itm/355024320435 | Colour global shutter at 60 fps is attractive, but sensor and trigger options unknown and only 1-month warranty | https://www.ebay.com.hk/itm/355024320435 | Specs are seller-listing only. |
| CAM-16 | Hampo 003-0409 dual OV2710 USB module | Hampo (Dongguan Hampo Electronic Technology) | 2x OmniVision OV2710 | 1920x1080 each | 30 (MJPG, each camera) | n/a | MJPG / YUY2 (YUY2 1080p only 5 fps) | 1/2.7 inch (3.0 um pixels) | 0.5 | Weaker low-light than IMX323/IMX291 boards | unknown (vendor publishes no latency figure; needs glass-to-glass test) | USB 2.0 UVC; page says it enumerates as 2 cameras (not one stitched frame); 200 mA | 80 x 16 x 20 (PCB) | unknown | 95 deg D, M12, fixed focus 1 m-infinity | Electronic rolling (not stated) | unknown (quote request; no price on page) | https://www.hampotech.com/no-distortion-uvc-ov2710-usb-dual-lens-camera-module-product/ | Synchronised frames claimed; two UVC devices on one USB 2.0 link - bandwidth for 2x 1080p30 MJPEG untested | https://www.hampotech.com/no-distortion-uvc-ov2710-usb-dual-lens-camera-module-product/ | Factory supplier, MOQ/price by enquiry. |
| CAM-17 | Logitech Brio 4K (V-U0040 / 960-001746) | Logitech | onsemi AR1335 13MP RGB (+ OmniVision OV7251 IR) | 4096x2160 (4K DCI) | 60 (MJPEG) | 30 (MJPEG) | MJPEG, YUY2, NV12 | unknown | unknown | RightLight 3 auto light correction (marketing); no lux figure | unknown (vendor publishes no latency figure; needs glass-to-glass test) | UVC: yes. USB 3.0 needed for 4K (older spec: USB 2.0 limited to 1080p30). Logitech lists Windows/macOS/ChromeOS only; Linux/Pi not stated - test | 102 x 27 x 26.5 (webcam only; clip adds 36.3 x 23.8 x 62.7) | 65 (Logitech datasheet and product page, excl. cable); 85 (Logitech support spec page, unclear basis); mounting clip 69.2 g separate. User's ~63 g not found in any source | 90 / 78 / 65 deg diagonal presets (Logi Tune, Windows/macOS only); 5x digital zoom; autofocus | unknown (not stated) | USD 169.99 (logitech.com US, as shown 2026-11-03) | https://www.logitech.com/en-us/shop/p/brio-4k-hdr-webcam.960-001105 | Two Brios = ~130 g + 2 USB 3 ports + autofocus mismatch; no sync; wide 4K possible but heaviest sensible option for pan-tilt | https://support.logi.com/hc/en-us/articles/31952740030999-Specification-BRIO-4K ; https://www.logitech.com/content/dam/logitech/en/video-collaboration/pdf/brio-datasheet.pdf ; https://www.logitech.com/en-gb/products/webcams/brio-4k-hdr-webcam.html | Mic-array and Windows Hello IR camera add bulk you do not need. |
| CAM-18 | Logitech C920 HD Pro | Logitech | unknown (not published) | 1080p (3 MP true optical resolution per Logitech) | 30 | n/a | MJPEG, YUY2; H.264 only on older hardware revisions (Logitech removed in-camera encoding from newer C920/C922/Brio per Reddit PSA citing Logitech) | unknown | unknown | RightLight 2 (marketing) | unknown (vendor publishes no latency figure; needs glass-to-glass test) | USB 2.0, UVC yes; long-standing Pi use (Stack Overflow H.264 passthrough tutorial on Pi 3) | 94 x 24 x 29 (W x D x H) | 162 (Logitech support spec) | 78 deg D / 70.42 H / 43.3 V, f 3.67 mm, autofocus | unknown (not stated) | CHF 69.90 (logitech.com en-ch, 'sold out temporarily', as shown 2026-11-03) | https://www.logitech.com/en-ch/shop/p/c920-pro-hd-webcam | Poor: 162 g each, bulky housing, no sync | https://support.logi.com/hc/en-us/articles/360023307294-C920-Technical-Specifications ; https://www.reddit.com/r/linux/comments/f2icry/psa_logitech_has_removed_hardware_h264_encoder/ ; https://stackoverflow.com/questions/49846400/raspberry-pi-use-vlc-to-stream-webcam-logitech-c920-h264-video-without-tran | Include as baseline only. |
| CAM-19 | Logitech C922 Pro Stream | Logitech | unknown | 1080p | 30 | n/a | unknown on fetched page (H.264 reportedly removed per Reddit PSA) | unknown | unknown | Autofocus and light correction (marketing) | unknown (vendor publishes no latency figure; needs glass-to-glass test) | UVC (not stated on fetched page) | unknown | unknown | 78 deg diagonal, autofocus; 720p @60 | unknown | USD 119.99 (logitech.com US, as shown 2026-11-03) | https://www.logitech.com/en-us/shop/p/c922-pro-stream-webcam | Poor: bulky, no sync; 720p60 only for high rate | https://www.logitech.com/en-us/shop/p/c922-pro-stream-webcam | Weight not on the page fetched; look up before considering. |
| CAM-20 | Stereolabs ZED Mini (ZED-121210) | Stereolabs | 2x 4MP 1/3-inch sensors (models not published) | 2x 2208x1242 (2K @15 fps) | 30 (2x 1920x1080 side-by-side) | n/a | Side-by-side stream over UVC; Stereolabs lists H.264/H.265/lossless encoding as 'on host' (no on-camera encoder); exact UVC pixel format not on page | 1/3 inch | unknown | no lux figure on store page | unknown (vendor publishes no latency figure; needs glass-to-glass test); fully synchronised sensors | USB 3.0 Type-C (store header says USB 3.1); Stereolabs support article covers using the ZED without CUDA (SDK depth needs NVIDIA GPU); Pi 5 untested by us | 124.5 x 30.5 x 26.5 | 60 (Stereolabs store page) | 102 deg H x 57 deg V; baseline 63 mm | Electronic synchronised rolling | USD 399 (stereolabs.com store, as shown 2026-11-03) | https://www.stereolabs.com/store/products/zed-mini | Purpose-built, 63 mm baseline is inside human IPD range (51-75 mm), calibrated; but 60 g, 124.5 mm long, USB 3, and no on-camera encoder means Pi 5 must software-encode ~3840x1080 | https://www.stereolabs.com/store/products/zed-mini ; https://support.stereolabs.com/articles/7166665108-can-i-use-the-zed-without-cuda | Most expensive; listed as ready-made benchmark. 720p60 side-by-side is available as a lighter encode load. |
Open questions
- Which video codec does the Vision Pro actually negotiate (VP8 or H.264), and does it send REMB? Without it the bitrate may stay at 1–3 Mbps and the stereo picture will look blocky.
- Can a Pi 5 run two MJPEG decodes, the hstack and x264 at 2560 × 720 and 30 fps? Not measured.
- How much head-pose jitter and delay is there over Wi-Fi 6, and is the head pose predicted? The library's message has no timestamp.
- Pose path: VisionProTeleop returns a 4×4 matrix over gRPC or a WebRTC data channel, while the wiring diagram assumes a 24-byte UDP packet from a small visionOS app. Which one do we build?
- Which column of the head matrix is forward, and with which sign, after the library's frame rotation?
- Two free-running USB cameras can be up to one frame (33 ms at 30 fps) out of step, and two cameras on USB 2.0 need MJPEG and possibly separate controllers.
- What does the Quanrui module really weigh with its cable? That decides light or heavy servos.
- Does the Waveshare adapter accept 7.4 V, or does it need 9–12.6 V and the 12 V servo variant?
- Remote mode of VisionProTeleop depends on third-party Cloudflare signalling and TURN servers that may be limited later.
- The published latency is a synthetic round trip, not glass-to-glass, and no head-to-servo figure exists anywhere.
- The Vision Pro shows video on a flat, head-anchored plane by default. World-locked reprojection needs app work.
Next steps
- Read the camera formats with v4l2-ctl. Run v4l2-ctl -d /dev/video0 --list-formats-ext and v4l2-ctl --all on each camera. Record the real MJPEG and H.264 modes, 60 fps availability, manual exposure and focus controls, and USB current.
- Glass-to-glass latency test. Film a stopwatch or LED in front of the camera, with the display in the same slow-motion phone frame. Do it per camera and mode, then through the full Pi, Wi-Fi and headset path. This replaces the estimates in the budget.
- Head-matrix print to pin the yaw and pitch axes. Print the 3 × 3 part of the head matrix while looking straight ahead, which should be close to a permutation matrix, then nod and turn to confirm which column is forward and the signs.
- PCA9685 and STS3215 bench test with a watchdog. Drive both servo options from UDP packets with the hold, park and ramp-on-resume failsafe. Log stall current and brown-outs, and weigh the Quanrui module.
Handoff for builders / agents
Download MB-001-handoff.zip (about 1 MB)
| File | What it holds |
|---|---|
| HANDOFF.md | The spec: goal, architecture, head-pose and video interfaces, parts list, mechanics, control loop, latency budget, TouchDesigner guide, simulator requirements, acceptance tests, open questions, sources |
| README.md | Short summary and quick start |
| params.json | All parameters in machine-readable form: variants, limits, servos, protocol, latency, expected forward-kinematics table |
| validation.json | Model and URDF checks run on the box |
| mb001_module38_sts3215.urdf | URDF, default variant (also sh0257, brio_mg996r). Meshes are in the zip; the URDF refers to them by relative path |
| In the zip | GLB, FBX, OBJ and one STL per part for each of the 3 variants (millimetres, joint pivots on the axes: base, yoke, cam_bar, cameras), the OpenSCAD source with re-export notes, the camera sheet and the wiring and latency diagrams |
Flagged in the spec as unverified: the TouchDesigner sign conventions and camera facing, the UDP port (proposed), the head-matrix forward axis, the servo connector pinout, the adapter input voltage, camera depth, weight and field of view, and the tilt limit (about ±30° is an estimate).
Research files and links
| File | What it holds |
|---|---|
| MB-001-latency-budget.md | Round-trip latency budget and servo speed/torque requirements |
| MB-001-servos-power.md | Servo control options, servo picks, wiring and power |
| MB-001-visionproteleop-deep-dive.md | Source-verified read of VisionProTeleop and OpenTeleVision |
| MB-001-cameras.md | Camera shortlist and notes |
| MB-001-avp-live-video.md | How to get live stereo video onto a Vision Pro |
| MB-001-touchdesigner-avp-stream.md | TouchDesigner to Vision Pro streaming options |
| MB-001-cameras.csv | The 20-row camera data table (CAM-01 to CAM-20) |
| MB-001-camera-sheet.csv | CSV copy of the Google Sheet |
External sources
- https://github.com/Improbable-AI/VisionProTeleop
- https://github.com/OpenTeleVision/TeleVision
- https://www.apple.com/apple-vision-pro/specs/
- https://transitiverobotics.com/blog/webrtc-latency-breakdown/
- https://jitter.is/blog/ethernet-vs-wifi-jitter/
- https://onlinemanual.insta360.com/goultra/en-us/faq/functionality/livestreaming
- https://www.waveshare.com/product/bus-servo-adapter-a.htm
- https://www.adafruit.com/product/815