- Ziel: Extrinsische Position des Marker-Boards im Kamera-Koordinatensystem bestimmen
- (Rotations- und Translationsvektor via
solvePnP).
- Geplante Aktionen: Kamerabild mit erkannten Markern anzeigen · Pose berechnen ·
- Kalibrierungsdatei speichern.
-
Aktionen werden ergänzt sobald das Konzept feststeht.
+
Board – ArUco & Kamera-Pose
+
+ Ablauf
+
+ Foto aufnehmen → ArUco erkennen → Kamera-Pose schätzen
+
+ Schritte
+
+ 1_detect_aruco_observations → 2_estimate_camera_from_observations
+
+ Letzter Run
+ –
-
-
-
-
-
+
+
+
@@ -543,6 +546,78 @@
btn.disabled = false;
}
});
+
+ // ── Board ──────────────────────────────────────────────────────────────────
+
+ const logBoard = document.getElementById('log-board');
+
+ function logB(msg) {
+ const ts = new Date().toLocaleTimeString('de-CH');
+ logBoard.value += `[${ts}] ${msg}\n`;
+ logBoard.scrollTop = logBoard.scrollHeight;
+ }
+
+ // SSE-Stream lesen (gleiche Logik wie compute)
+ async function readSseStream(response, logFn, onDone) {
+ const reader = response.body.getReader();
+ const decoder = new TextDecoder();
+ let buffer = '';
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ buffer += decoder.decode(value, { stream: true });
+ const parts = buffer.split('\n\n');
+ buffer = parts.pop();
+ for (const part of parts) {
+ for (const line of part.split('\n')) {
+ if (!line.startsWith('data: ')) continue;
+ try {
+ const evt = JSON.parse(line.slice(6));
+ if (evt.type === 'log') {
+ if (evt.text !== '') logFn(evt.text);
+ } else if (evt.type === 'done') {
+ onDone(evt);
+ }
+ } catch { /* ignore */ }
+ }
+ }
+ }
+ }
+
+ document.getElementById('btn-board-run').addEventListener('click', async () => {
+ logB('Board-Erkennung wird gestartet …');
+ const btn = document.getElementById('btn-board-run');
+ btn.disabled = true;
+
+ try {
+ const response = await fetch('/api/board/run', { method: 'POST' });
+
+ if (!response.ok) {
+ const raw = await response.text().catch(() => '');
+ let msg;
+ try { msg = JSON.parse(raw).error || raw; }
+ catch { msg = raw.slice(0, 300) || `HTTP ${response.status}`; }
+ logB(`❌ HTTP ${response.status}: ${msg}`);
+ return;
+ }
+
+ await readSseStream(response, logB, (evt) => {
+ if (evt.exitCode === 0) {
+ logB('✅ Board-Run abgeschlossen.');
+ if (evt.runDir) {
+ document.getElementById('board-last-run').textContent = evt.runDir;
+ }
+ } else {
+ logB(`❌ Beendet mit Exit-Code ${evt.exitCode}`);
+ }
+ });
+
+ } catch (err) {
+ logB(`❌ Fehler: ${err}`);
+ } finally {
+ btn.disabled = false;
+ }
+ });