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.
53 lines
1.9 KiB
Python
53 lines
1.9 KiB
Python
import json
|
|
from nats.aio.client import Client
|
|
from src.backend.config import settings
|
|
from src.backend.nats_client.subjects import Subjects
|
|
|
|
CAPABILITIES = {
|
|
"service": settings.service_name,
|
|
"domain": settings.service_domain,
|
|
"version": "1.0.0",
|
|
"description": "Intel RealSense D4xx stereo depth camera server",
|
|
"endpoints": {
|
|
"rest": {
|
|
"health": {"method": "GET", "path": "/api/health"},
|
|
"discover": {"method": "GET", "path": "/api/discover"},
|
|
"open": {"method": "POST", "path": "/api/open"},
|
|
"close": {"method": "POST", "path": "/api/close"},
|
|
"capture": {"method": "GET", "path": "/api/capture"},
|
|
"rgb": {"method": "GET", "path": "/api/rgb"},
|
|
"depth": {"method": "GET", "path": "/api/depth"},
|
|
},
|
|
},
|
|
"nats": {
|
|
"actions": [
|
|
{
|
|
"subject": Subjects.action("snapshot"),
|
|
"pattern": "request/reply",
|
|
"description": "Capture RGB+depth frame",
|
|
"request_schema": {"include_depth": "boolean"},
|
|
"response_schema": {"rgb_jpeg_b64": "string", "depth_png_b64": "string", "timestamp": "number"},
|
|
},
|
|
{
|
|
"subject": Subjects.action("status"),
|
|
"pattern": "request/reply",
|
|
"description": "Get camera status",
|
|
"response_schema": {"camera_open": "boolean", "sdk_initialized": "boolean"},
|
|
},
|
|
],
|
|
},
|
|
}
|
|
|
|
|
|
async def publish_discovery(nc: Client):
|
|
await nc.publish(
|
|
Subjects.DISCOVERY_ANNOUNCE,
|
|
json.dumps(CAPABILITIES).encode(),
|
|
)
|
|
|
|
async def handle_discovery_request(msg):
|
|
await msg.respond(json.dumps(CAPABILITIES).encode())
|
|
|
|
await nc.subscribe(Subjects.DISCOVERY_REQUEST, cb=handle_discovery_request)
|
|
await nc.subscribe(Subjects.SERVICE_DISCOVERY, cb=handle_discovery_request)
|