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

-36
View File
@@ -48,40 +48,6 @@ function clearCanvas(canvas) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
// ---------------- Banner stato ----------------
async function refreshBanner() {
let state;
try {
state = await jsonFetch('/api/right_arm/state');
} catch (e) {
$('raStatusLabel').textContent = `Errore stato: ${e.message}`;
$('raStatusBanner').hidden = false;
$('raStatusBanner').className = 'ra-banner ra-banner-warn';
return;
}
const ok = state.robot_active === 'g1' && state.side === 'right';
const banner = $('raStatusBanner');
if (ok) {
banner.hidden = true;
} else {
banner.hidden = false;
banner.className = 'ra-banner ra-banner-warn';
$('raStatusLabel').textContent = `Robot attivo: ${state.robot_active} / ${state.side}. Per usare questa tab serve G1 / right.`;
}
return state;
}
async function onActivateClick() {
try {
await jsonFetch('/api/right_arm/activate', { method: 'POST' });
await refreshBanner();
await refreshPose();
} catch (e) {
alert(`Attivazione fallita: ${e.message}`);
}
}
// ---------------- Immagini ----------------
function urlWithBust(path) { return `${path}?t=${Date.now()}`; }
@@ -356,7 +322,6 @@ function markUserTouchedOnInput(prefix) {
function init() {
if (!$('tab-right-arm')) return;
$('raActivateBtn').addEventListener('click', onActivateClick);
$('raFrontDetectBtn').addEventListener('click', onDetectFront);
$('raWristDetectBtn').addEventListener('click', onDetectWrist);
$('raMoveBtn').addEventListener('click', onMove);
@@ -374,7 +339,6 @@ function init() {
populateClassDropdowns();
startFrontLoop();
startWristLoop();
refreshBanner();
refreshPose();
if (poseTimer) clearInterval(poseTimer);
poseTimer = setInterval(refreshPose, POSE_REFRESH_MS);