fix(right_arm): bbox dict, image_size da /api/status, tab non seleziona robot

Tre problemi della tab Braccio DX dopo il primo rodaggio:

1. /detect/front e /detect/wrist ritornavano bbox raw dal YOLO server,
   che lo manda come lista [x1,y1,x2,y2]; la GUI legge bbox.x1 e mostra
   NaN. Ora il router normalizza il payload via perception/detector
   ._normalize, allineandosi al resto del codice. Aggiunta regressione
   con payload reale del server.

2. La tab gateava su robot.active==g1 && wrist_side==right con banner
   "Attiva G1 right" e POST /activate. Confonde: la selezione del
   robot e' globale e non si flippa per-feature. Rimossi banner,
   bottone, endpoint /activate e _guard_g1_right(); gli endpoint
   operano sul polso destro del robot attivo qualunque esso sia.

3. image_size: [0,0] perche' Nuwa /api/intrinsics non include
   width/height; vivono in /api/status > data.resolution. Aggiunto
   NuwaClient.image_size() e usato in detect_front. Aggiornato
   docstring di intrinsics() per coerenza con il payload reale.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal PastroandClaude Opus 4.7 committed 2026-05-21 11:43:05 +02:00
1 parent 3284cd0424
commit 2f6444c0a5
5 files changed
+57 -93

No files matched your search

+14 -1
View File
@@ -39,7 +39,9 @@ class NuwaClient:
return self._get("/api/rgb").content
def intrinsics(self) -> dict[str, Any]:
"""Returns {fx, fy, cx, cy, width, height, dist_coeffs?}."""
"""Nuwa /api/intrinsics shape: {ir:{...}, rgb:{...}, extrinsics_ir_to_rgb:{...}}.
Width/height are NOT included here — use `image_size()` (or read them
from the decoded frame) when you need pixel dimensions."""
data = self._get("/api/intrinsics").json()
if isinstance(data, dict) and "data" in data:
payload = data.get("data") or {}
@@ -48,6 +50,17 @@ class NuwaClient:
return payload
return data
def image_size(self) -> tuple[int, int]:
"""Returns (width, height) of the RGB stream from /api/status."""
data = self._get("/api/status").json()
if isinstance(data, dict) and "data" in data:
data = data.get("data") or {}
res = (data or {}).get("resolution") or {}
w, h = res.get("width"), res.get("height")
if not (isinstance(w, int) and isinstance(h, int)):
raise NuwaError(f"status missing resolution.width/height: {res!r}")
return w, h
def depth_png(self) -> bytes:
"""16-bit depth PNG (values in mm)."""
return self._get("/api/depth").content