From dbfc915b6646f6a0bc0d78dfdd47b4a1c8b5cd7f Mon Sep 17 00:00:00 2001 From: chk <79915315+ChKendel@users.noreply.github.com> Date: Sun, 14 Jun 2026 21:18:29 +0200 Subject: [PATCH] Logs & Marker anzeigen --- public/boardViewer.html | 88 +++++++++++++++++++++++++++++++++-------- server/server.js | 2 + 2 files changed, 73 insertions(+), 17 deletions(-) diff --git a/public/boardViewer.html b/public/boardViewer.html index a9f83d8..2699078 100644 --- a/public/boardViewer.html +++ b/public/boardViewer.html @@ -251,7 +251,15 @@ const gCompareLines = new THREE.Group(); // Verbindungslinien Pos A↔Pos B const gPositionC = new THREE.Group(); // Pos C Marker (nur fremd, cyan) const gYAxis = new THREE.Group(); // Y-Achse Visualisierung (Kreismittelpunkte, Achse) const gSkeleton = new THREE.Group(); // Roboter-Skeleton (FK, nur im Homing-Mode) -scene.add(gPaper, gMarkers, gMeasured, gCameras, gCompare, gCompareLines, gPositionC, gYAxis, gSkeleton); +const gArmMarkers = new THREE.Group(); // Arm-Marker Modellpositionen + Fehlerlinien (FK) +scene.add(gPaper, gMarkers, gMeasured, gCameras, gCompare, gCompareLines, gPositionC, gYAxis, gSkeleton, gArmMarkers); + +const LINK_COLORS = { + Board: 0x8b6528, Base: 0x888888, + Arm1: 0x3355cc, Ellbow: 0xaaaaaa, Arm2: 0xddcc88, + Hand: 0xcc8833, Palm: 0xcc3333, + FingerA: 0x33aa33, FingerB: 0x33aa33, +}; // ── Zustand für Positionen ──────────────────────────────────────────────────── let _primaryFremdMarkers = []; // Pos A – [{marker_id, position_mm, num_cameras}] @@ -259,8 +267,9 @@ let _compareFremdMarkers = []; // Pos B – [{marker_id, position_mm, num_cam let _positionCFremdMarkers = []; // Pos C – [{marker_id, position_mm, num_cameras}] // ── Homing-Mode Zustand ─────────────────────────────────────────────────────── -let _currentRobot = null; // robot.json nach loadData() -let _homingAngles = null; // { x, y, z, a, b, c, e } nach Homing-Run +let _currentRobot = null; // robot.json nach loadData() +let _homingAngles = null; // { x, y, z, a, b, c, e } nach Homing-Run +let _measuredMarkers = null; // measuredMarkers aus letztem buildScene-Aufruf // ── Roboter-Skeleton (Forward Kinematics) ───────────────────────────────────── /** @@ -270,6 +279,7 @@ let _homingAngles = null; // { x, y, z, a, b, c, e } nach Homing-Run */ function buildSkeletonFK(robot, angles) { clearGroup(gSkeleton); + clearGroup(gArmMarkers); if (!robot?.links) return; const links = robot.links; @@ -310,23 +320,54 @@ function buildSkeletonFK(robot, angles) { // 3. Skeleton-Segment zeichnen const skel = link.skeleton; - if (!skel?.from || !skel?.to) continue; + if (skel?.from && skel?.to) { + const [fx, fy, fz] = skel.from; + const [tx, ty, tz] = skel.to; + const fromW = new THREE.Vector3(fx * S, fz * S, -fy * S).applyMatrix4(childFrame); + const toW = new THREE.Vector3(tx * S, tz * S, -ty * S).applyMatrix4(childFrame); - const [fx, fy, fz] = skel.from; - const [tx, ty, tz] = skel.to; - const fromW = new THREE.Vector3(fx * S, fz * S, -fy * S).applyMatrix4(childFrame); - const toW = new THREE.Vector3(tx * S, tz * S, -ty * S).applyMatrix4(childFrame); + const [cr, cg, cb] = skel.color ?? [0.8, 0.2, 0.2]; + const color = new THREE.Color(cr, cg, cb); + const rad = Math.max((skel.radius ?? 4) * S, 0.004); - const [cr, cg, cb] = skel.color ?? [0.8, 0.2, 0.2]; - const color = new THREE.Color(cr, cg, cb); - const rad = Math.max((skel.radius ?? 4) * S, 0.004); + gSkeleton.add(makeLine(fromW, toW, color, 0.9)); + gSkeleton.add(makeSphere(fromW, rad, color)); + gSkeleton.add(makeSphere(toW, rad, color)); + // Gelenk-Mittelpunkt (Welt-Ursprung des Link-Frames) + const jointW = new THREE.Vector3().applyMatrix4(childFrame); + gSkeleton.add(makeSphere(jointW, 0.004, 0xc8cdd8)); + } - gSkeleton.add(makeLine(fromW, toW, color, 0.9)); - gSkeleton.add(makeSphere(fromW, rad, color)); - gSkeleton.add(makeSphere(toW, rad, color)); - // Gelenk-Mittelpunkt (Welt-Ursprung des Link-Frames) - const jointW = new THREE.Vector3().applyMatrix4(childFrame); - gSkeleton.add(makeSphere(jointW, 0.004, 0xc8cdd8)); + // 4. Arm-Marker zeichnen (Modellposition via FK, als orientiertes Quadrat) + if (link.markers?.length > 0) { + const col = LINK_COLORS[linkName] ?? 0xffffff; + for (const m of link.markers) { + if (!m.position) continue; + const [lx, ly, lz] = m.position; + const posWorld = new THREE.Vector3(lx * S, lz * S, -ly * S).applyMatrix4(childFrame); + const markerSizeM = (m.size ?? 25) * S; + const [nx, ny, nz] = m.normal ?? [0, 0, 1]; + const normalWorld = new THREE.Vector3(nx, nz, -ny).transformDirection(childFrame); + gArmMarkers.add(makeMarkerSquareOriented(posWorld, normalWorld, markerSizeM, col)); + gArmMarkers.add(makeSphere(posWorld, 0.003, col)); + } + } + } + + // 5. Fehlerlinien: Modell-Marker → gemessene Position (aus 3b) + if (_measuredMarkers?.markers?.length > 0) { + for (const obs of _measuredMarkers.markers) { + if (obs.link === 'Board' || !obs.link) continue; + const ldata = links[obs.link]; + if (!ldata || !frames[obs.link]) continue; + const modelM = ldata.markers?.find(mm => mm.id === obs.marker_id); + if (!modelM?.position) continue; + const [lx, ly, lz] = modelM.position; + const modelPosW = new THREE.Vector3(lx * S, lz * S, -ly * S).applyMatrix4(frames[obs.link]); + const obsPosW = r2vArr(obs.position_mm); + gArmMarkers.add(makeLine(modelPosW, obsPosW, 0xff8800, 0.85)); + gArmMarkers.add(makeSphere(obsPosW, 0.007, LINK_COLORS[obs.link] ?? 0x3b82f6)); + } } } @@ -362,6 +403,18 @@ function makeMarkerSquare(pos, size, color) { return m; } +function makeMarkerSquareOriented(pos, normalVec, size, color) { + const geo = new THREE.PlaneGeometry(size, size); + const mat = new THREE.MeshPhongMaterial({ color, side: THREE.DoubleSide, transparent: true, opacity: 0.85 }); + const mesh = new THREE.Mesh(geo, mat); + mesh.position.copy(pos); + const n = normalVec.clone().normalize(); + if (n.lengthSq() > 1e-9) { + mesh.quaternion.setFromUnitVectors(new THREE.Vector3(0, 0, 1), n); + } + return mesh; +} + function makeEdgeBorder(pos, size, color) { const geo = new THREE.EdgesGeometry(new THREE.PlaneGeometry(size, size)); const mat = new THREE.LineBasicMaterial({ color, transparent: true, opacity: 0.75 }); @@ -404,6 +457,7 @@ function buildScene(data) { clearGroup(gPaper); clearGroup(gMarkers); clearGroup(gMeasured); clearGroup(gCameras); const { robot, detections, cameraPoses, measuredMarkers } = data; + _measuredMarkers = measuredMarkers ?? null; // Alle erkannten Marker-IDs (über alle Kameras) const detectedIds = new Set(); diff --git a/server/server.js b/server/server.js index 745a7ce..547c7b3 100755 --- a/server/server.js +++ b/server/server.js @@ -446,6 +446,8 @@ const SCRIPT_4B = path.join(__dirname, '..', 'scripts', '4b_revolute_angle.p */ function runScript(args, send) { return new Promise((resolve) => { + const cmd = [PYTHON_BIN, '-u', ...args].join(' '); + console.log(`[runScript] ${cmd}`); const proc = spawn(PYTHON_BIN, ['-u', ...args]); let outBuf = '';