diff --git a/public/boardViewer.html b/public/boardViewer.html
index d52071c..844d1a5 100644
--- a/public/boardViewer.html
+++ b/public/boardViewer.html
@@ -333,7 +333,8 @@ async function loadData() {
return;
}
buildScene(data);
- statusEl.textContent = `Run: ${data.runDir} • ${new Date().toLocaleTimeString('de-CH')}`;
+ const robotLabel = data.robotFile ? ` • Robot: ${data.robotFile}` : '';
+ statusEl.textContent = `Run: ${data.runDir}${robotLabel} • ${new Date().toLocaleTimeString('de-CH')}`;
} catch (err) {
statusEl.textContent = `Fehler: ${err.message ?? err}`;
}
diff --git a/server/server.js b/server/server.js
index 3a40535..ec797f1 100755
--- a/server/server.js
+++ b/server/server.js
@@ -218,6 +218,28 @@ async function findLatestCalibSession() {
}
}
+/**
+ * Sucht die neueste Kalibrierungs-Session, die eine NPZ für die angegebene Kamera enthält.
+ * Gibt { session, npzPath } zurück oder null wenn keine gefunden.
+ */
+async function findLatestNpzForCamera(camId) {
+ try {
+ await fsPromises.access(calibDataDir);
+ const entries = await fsPromises.readdir(calibDataDir, { withFileTypes: true });
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name).sort().reverse();
+ for (const dir of dirs) {
+ const npzPath = path.join(calibDataDir, dir, `${camId}_calibration.npz`);
+ try {
+ await fsPromises.access(npzPath);
+ return { session: dir, npzPath };
+ } catch {}
+ }
+ return null;
+ } catch {
+ return null;
+ }
+}
+
/** Liest meta.json einer Session */
async function readCalibMeta(sessionName) {
try {
@@ -474,7 +496,13 @@ app.post('/api/board/run', async (req, res) => {
await fsPromises.mkdir(runDir, { recursive: true });
send({ type: 'log', text: `▶ Board-Run: ${ts}` });
send({ type: 'log', text: `▶ Ordner: ${runDir}` });
+
+ // Robot-JSON laden und Marker-Anzahl loggen
+ let robotData = null;
+ try { robotData = JSON.parse(await fsPromises.readFile(ROBOT_JSON, 'utf8')); } catch {}
+ const boardMarkerCount = robotData?.links?.Board?.markers?.length ?? '?';
send({ type: 'log', text: `▶ Robot-JSON: ${ROBOT_JSON}` });
+ send({ type: 'log', text: `▶ Board-Marker (A0): ${boardMarkerCount} Marker aus links.Board.markers` });
send({ type: 'log', text: '' });
// 2. Kameras ermitteln
@@ -482,14 +510,9 @@ app.post('/api/board/run', async (req, res) => {
const camData = await new WebcamClient(WEBCAM_URL).getCameras();
const cameraIds = (camData.cameras ?? []).map(c => c.id);
send({ type: 'log', text: `▶ Kameras: ${cameraIds.join(', ')}` });
-
- // 3. Aktuelle Kalibrierungs-Session für NPZ-Dateien
- const calibSession = await findLatestCalibSession();
- if (!calibSession) throw new Error('Keine Kalibrierungs-Session. Bitte zuerst Camera NPZ kalibrieren.');
- send({ type: 'log', text: `▶ NPZ-Session: ${calibSession}` });
send({ type: 'log', text: '' });
- // 4. Pro Kamera: Foto → Script 1 → Script 2
+ // 3. Pro Kamera: Foto → Script 1 → Script 2
for (const camId of cameraIds) {
send({ type: 'log', text: `─── ${camId} ${'─'.repeat(40 - camId.length)}` });
@@ -509,13 +532,14 @@ app.post('/api/board/run', async (req, res) => {
await fsPromises.writeFile(imgPath, Buffer.from(await snapResp.arrayBuffer()));
send({ type: 'log', text: `✅ Foto: ${camId}.jpg` });
- // NPZ prüfen
- const npzPath = path.join(calibDataDir, calibSession, `${camId}_calibration.npz`);
- try { await fsPromises.access(npzPath); }
- catch {
- send({ type: 'log', text: `⚠ Keine NPZ (${camId}_calibration.npz) – übersprungen` });
+ // NPZ suchen – neueste Session, die eine NPZ für diese Kamera enthält
+ const npzInfo = await findLatestNpzForCamera(camId);
+ if (!npzInfo) {
+ send({ type: 'log', text: `⚠ Keine NPZ für ${camId} gefunden (in keiner Kalibrierungs-Session) – übersprungen` });
continue;
}
+ const npzPath = npzInfo.npzPath;
+ send({ type: 'log', text: `▶ NPZ: data/calibration/${npzInfo.session}/${camId}_calibration.npz` });
// Script 1 – ArUco-Erkennung
send({ type: 'log', text: '\n▷ 1_detect_aruco_observations' });
@@ -659,7 +683,7 @@ app.get('/api/board/latest', async (req, res) => {
measuredMarkers = JSON.parse(raw);
} catch {}
- return res.json({ runDir: runName, robot, detections, cameraPoses, measuredMarkers });
+ return res.json({ runDir: runName, robotFile: path.basename(ROBOT_JSON), robot, detections, cameraPoses, measuredMarkers });
} catch (err) {
return res.status(500).json({ error: String(err) });
}