Commit Graph
3 Commits
Author SHA1 Message Date
OliviaCandClaude Opus 5.5 1ad422062c feat: frame work off the event loop, each frame encoded once
- Endpoints that wait for the camera or encode/compute (capture, rgb, depth,
  depth/color, pointcloud, pointcloud/roi, measure, snapshot, and the SDK
  calls discover/open/close) are plain `def`: FastAPI runs them in its
  thread pool, so one slow request no longer holds the others. Plain `def`
  rather than asyncio.to_thread in each route: it is FastAPI's own mechanism
  and keeps the route bodies unchanged.
- /ws and the NATS snapshot stay async and use asyncio.to_thread for the
  frame wait, the encoding and the recording write.
- EncodedFrame: the JPEG q85, 16-bit PNG, colormap JPEG q90, their base64
  and the depth stats of a frame are computed once, on first use, and
  shared: parallel requests, /ws and NATS on the same frame get the same
  bytes. The last 4 frames' encodings are kept.
- camera.cached_frame(): the whole cached frame (get_rgb/get_depth unchanged).

Contract unchanged: same endpoints, same JSON fields. frame_id still counts
responses (now under a lock); two parallel /api/capture served by one frame
have different frame_id and the same timestamp and images.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 13:03:28 +02:00
OliviaCandClaude Opus 5.5 9aa63e4e02 feat: per-phase timings of the frame path in the log
One log line per phase every PHASE_LOG_EVERY samples (default 100, 0 = off):
mean and max of wait_frames, align, convert, each JPEG/PNG encoding,
colormap, depth_stats, base64, json and ws_send. Meant for the measurement
on PC2 via `docker logs` (optimize-streams R01): where a capture spends its
~130 ms of CPU is not known yet.

capture() moves its numpy conversion into _frame_from() unchanged, only so
the block can be timed; _depth_colormap() likewise wraps _jet_colormap().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 12:57:25 +02:00
robot 07d95792e3 Initial commit: RealSense D435 API server
Drop-in replacement for the Nuwa-HP60C camera container, exposing RGB +
aligned depth + intrinsics via REST/WebSocket so the existing
pestello-pose-detector pipeline can consume frames without changes.

Key adaptations for D4xx on USB 2.0 (this robot has no USB 3 port exposed
externally — see STATUS.md):
- pyrealsense2 built from source; the librealsense v2.55.1 install rule
  doesn't ship the main .so, so we copy it from the build dir and add an
  __init__.py that re-exports the submodule.
- Color stream uses YUYV format on USB 2.x (BGR8/RGB8 time out on this
  bus); converted to BGR via cv2.cvtColor in capture().
- rs.align is skipped on USB 2 (incompatible with YUYV); color is
  cv2-resized to depth shape for approximate per-pixel alignment.
- Driver auto-detects usb_type_descriptor and falls back to the
  full-resolution BGR8 + rs.align pipeline when on USB 3.

Tested: /api/{health,status,discover,rgb,depth,depth/color,capture,
intrinsics} all return 200 with valid payloads at 640x480.
2026-05-19 00:58:23 +02:00