From 45513cf714ff8c5a5d15709a09530f6fb8b47aad Mon Sep 17 00:00:00 2001 From: chk <79915315+ChKendel@users.noreply.github.com> Date: Wed, 10 Jun 2026 16:54:36 +0200 Subject: [PATCH] CSV anzeigen --- public/boardViewer.html | 6 +- public/calibration.js | 135 ++++++++++++++++++++++++++++++ public/calibration_board.html | 7 ++ scripts/3b_corner_marker_poses.py | 6 +- 4 files changed, 149 insertions(+), 5 deletions(-) diff --git a/public/boardViewer.html b/public/boardViewer.html index 882841f..37b5d2e 100644 --- a/public/boardViewer.html +++ b/public/boardViewer.html @@ -105,7 +105,7 @@ table.dtbl tr:hover td { background: #1a1f2b; } .row-1cam td:first-child::before { content: ''; } .cell-hi { color: #fbbf24; } /* amber: trianguliert */ - .cell-lo { color: #fde68a; } /* hell: nur 2D */ + .cell-lo { color: #dde3ec; } /* hell: nur 2D */ .cell-unk { color: #3b82f6; } /* blau: fremd */ .cell-mut { color: var(--muted); } @@ -124,7 +124,7 @@
Erkannt Nicht erkannt - Erkannt (nur 2D) + Erkannt (nur 2D) Gemessen (3b) Fremd (3b) Kamera @@ -361,7 +361,7 @@ function buildScene(data) { if (detectedIds.has(m.id) && !Object.hasOwn(measuredById, m.id)) { nDetectedNotTriangulated++; const pos = r2vArr(m.position); - gMeasured.add(makeSphere(pos, 0.0055, 0xfde68a)); + gMeasured.add(makeSphere(pos, 0.0055, 0xdde3ec)); } } diff --git a/public/calibration.js b/public/calibration.js index a852a62..c6cbde3 100644 --- a/public/calibration.js +++ b/public/calibration.js @@ -222,6 +222,136 @@ function initCameraNpz() { }); } +// ── Board: Marker-Tabelle ───────────────────────────────────────────────────── + +async function loadBoardTable() { + const wrap = document.getElementById('board-marker-table-wrap'); + if (!wrap) return; + + const th = (a) => `style="text-align:${a};padding:3px 8px;border-bottom:1px solid #2a2d35;white-space:nowrap;background:#1e293b;color:#555b6e;font-weight:normal"`; + const td = (a, x = '') => `style="padding:2px 8px;border-bottom:1px solid #111418;text-align:${a};white-space:nowrap;${x}"`; + + try { + const r = await fetch('/api/board/latest'); + if (!r.ok) throw new Error(`HTTP ${r.status}`); + const data = await r.json(); + + if (!data.runDir) { + wrap.innerHTML = '

Noch kein Board-Run vorhanden.

'; + return; + } + const meas = data.measuredMarkers; + if (!meas?.markers?.length) { + wrap.innerHTML = `

Run: ${data.runDir} – kein 3b-Output (≥2 Kameras erforderlich).

`; + return; + } + + // Modell-Info aus robot.json + const boardMarkers = data.robot?.links?.Board?.markers ?? []; + const modelMap = {}; + for (const m of boardMarkers) modelMap[m.id] = m; + + const f1 = v => (v == null ? '–' : Number(v).toFixed(1)); + const f2 = v => (v == null ? '–' : Number(v).toFixed(2)); + const f4 = v => (v == null ? '–' : Number(v).toFixed(4)); + + const markers = [...meas.markers].sort((a, b) => { + if (a.link !== b.link) return a.link === 'Board' ? -1 : 1; + return a.marker_id - b.marker_id; + }); + + let html = `

+ Run: ${data.runDir} · ${markers.length} Marker trianguliert +

+ + + + + + + + + + + + + + + + + `; + + for (const m of markers) { + const model = modelMap[m.marker_id]; + const set = m.set ?? model?.set ?? '–'; + const [px, py, pz] = m.position_mm; + const [mnx, mny, mnz] = m.normal; + + let dist = '–', dz = '–'; + if (model && m.link === 'Board') { + const [mx, my, mz] = model.position; + const ddx = px - mx, ddy = py - my, ddz = pz - mz; + dist = Math.sqrt(ddx * ddx + ddy * ddy + ddz * ddz).toFixed(2); + dz = ddz.toFixed(2); + } + + const col = m.link === 'Board' ? '' : 'color:#3b82f6;'; + html += ` + + + + + + + + + + + + + + `; + } + html += `
IDSetLinkKam.x mmy mmz mmnxnynzdist mmΔz mmKante mm
${m.marker_id}${set}${m.link}${m.num_cameras}${f1(px)}${f1(py)}${f1(pz)}${f4(mnx)}${f4(mny)}${f4(mnz)}${dist}${dz}${f1(m.edge_length_mm)}
`; + + // Kamera-Tabelle + const cams = meas.cameras ?? []; + if (cams.length > 0) { + html += `

KAMERAS

+ + + + + + + + + + + `; + for (const c of cams) { + const [cx, cy, cz] = c.position_mm ?? [null, null, null]; + const [dx, dy, dz] = c.direction ?? [null, null, null]; + html += ` + + + + + + + + `; + } + html += `
IDx mmy mmz mmdir_xdir_ydir_z
${c.camera_id}${f1(cx)}${f1(cy)}${f1(cz)}${f4(dx)}${f4(dy)}${f4(dz)}
`; + } + + wrap.innerHTML = html; + + } catch (err) { + if (wrap) wrap.innerHTML = `

Fehler: ${err}

`; + } +} + // ── Board ───────────────────────────────────────────────────────────────────── function initBoard() { @@ -233,6 +363,9 @@ function initBoard() { logBoard.scrollTop = logBoard.scrollHeight; } + // Tabelle beim ersten Öffnen des Tabs befüllen + loadBoardTable(); + document.getElementById('btn-board-run').addEventListener('click', async () => { logB('Board-Erkennung wird gestartet …'); const btn = document.getElementById('btn-board-run'); @@ -257,6 +390,8 @@ function initBoard() { if (frame?.contentWindow) { frame.contentWindow.postMessage({ type: 'reload' }, '*'); } + // Marker-Tabelle aktualisieren + loadBoardTable(); } } else { logB(`❌ Beendet mit Exit-Code ${evt.exitCode}`); diff --git a/public/calibration_board.html b/public/calibration_board.html index 0cfe583..9b41060 100644 --- a/public/calibration_board.html +++ b/public/calibration_board.html @@ -38,4 +38,11 @@ >
+
+

Marker-Positionen (letzter Run)

+
+

(Erscheint nach einem Board-Run mit ≥2 Kameras)

+
+
+ diff --git a/scripts/3b_corner_marker_poses.py b/scripts/3b_corner_marker_poses.py index 8c3c089..eb4ab7b 100644 --- a/scripts/3b_corner_marker_poses.py +++ b/scripts/3b_corner_marker_poses.py @@ -77,6 +77,7 @@ def load_marker_info(robot_path: str) -> Dict[int, dict]: if mid >= 0: out[mid] = { "link": link_name, + "set": mk.get("set", ""), # z.B. "A0" "position_mm": mk.get("position"), # [x_mm, y_mm, z_mm] robot coords } return out @@ -158,6 +159,7 @@ def main() -> None: markers_out.append({ "marker_id": int(mid), "link": marker_info.get(mid, {}).get("link", "unknown"), + "set": marker_info.get(mid, {}).get("set", ""), "position_m": [float(v) for v in center], "position_mm": [float(v * 1000.0) for v in center], "normal": [float(v) for v in normal], @@ -195,7 +197,7 @@ def main() -> None: with open(csv_path, "w", newline="", encoding="utf-8") as fcsv: w = csv.writer(fcsv) # Marker-Tabelle - w.writerow(["marker_id", "link", "num_cameras", + w.writerow(["marker_id", "link", "set", "num_cameras", "x_mm", "y_mm", "z_mm", "nx", "ny", "nz", "model_x_mm", "model_y_mm", "model_z_mm", @@ -219,7 +221,7 @@ def main() -> None: row_model = ["", "", "", "", ""] w.writerow([ - mid, link, m["num_cameras"], + mid, link, m.get("set", ""), m["num_cameras"], round(px, 2), round(py, 2), round(pz, 2), round(mnx, 5), round(mny, 5), round(mnz, 5), *row_model,