boardViewer

This commit is contained in:
chk
2026-06-19 06:43:06 +02:00
parent d36ef6189d
commit aa78116837
8 changed files with 593 additions and 73 deletions

View File

@@ -367,20 +367,24 @@ function buildSkeletonFK(robot, angles) {
const markerSizeM = (m.size ?? 25) * S;
const [nx, ny, nz] = m.normal ?? [0, 0, 1];
// Marker-Orientierung ZUERST im lokalen Link-Frame bauen, DANN die volle
// childFrame-Rotation anwenden. So wird der Roll (Drehung des Markers um
// seine eigene Normale) korrekt mitgeführt — auch wenn die Link-Drehachse
// parallel zur Marker-Normale liegt (z.B. Marker 197: normal [-1,0,0] ∥
// Arm1-Achse [-1,0,0]). Eine reine Welt-Normalen-Rekonstruktion würde
// genau diesen Anteil verlieren.
const nLocal = new THREE.Vector3(nx, nz, -ny).normalize(); // robot→three.js
// Marker-Orientierung ZUERST im lokalen ROBOT-Frame bauen (rohe Normale:
// Minimal-Rotation [0,0,1]→Normale + Spin um die Normale), DANN über qView
// in three.js-Achsen und mit qFrame in die Welt drehen. Würde man die
// Normale wie früher schon VOR der Minimal-Rotation nach three.js drehen
// (nx,nz,-ny), verdreht eine schräg liegende Normale (z.B. [-1,0,1]) das
// Quadrat zusätzlich um ihren Azimut (~45°) um die eigene Achse; der Spin
// kann das nicht kompensieren. Der Link-Roll um die Normale bleibt
// erhalten, weil qFrame zuletzt wirkt (z.B. Marker 197: normal [-1,0,0] ∥
// Arm1-Achse). Gegen triangulierte Ecken geprüft (Capture 20260616_133151,
// Marker 146): diese Reihenfolge 0.8°, die alte 45.5°.
const nRobot = new THREE.Vector3(nx, ny, nz).normalize(); // rohe robot-Normale
const spinRad = ((m.spin ?? 0) * Math.PI) / 180;
const qNormalLoc = new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 0, 1), nLocal);
const qSpinLoc = new THREE.Quaternion().setFromAxisAngle(nLocal, spinRad);
const qMarkerLoc = qSpinLoc.multiply(qNormalLoc); // Q_spin ∘ Q_normal (lokal)
const qNormalLoc = new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 0, 1), nRobot);
const qSpinLoc = new THREE.Quaternion().setFromAxisAngle(nRobot, spinRad);
const qView = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), -Math.PI / 2); // robot→three.js
const qFrame = new THREE.Quaternion().setFromRotationMatrix(childFrame);
const qMarkerW = qFrame.clone().multiply(qMarkerLoc); // in Welt drehen
const normalW = nLocal.clone().applyQuaternion(qFrame).normalize();
const qMarkerW = qFrame.clone().multiply(qView).multiply(qSpinLoc.multiply(qNormalLoc)); // lokal → three.js → Welt
const normalW = new THREE.Vector3(nx, nz, -ny).applyQuaternion(qFrame).normalize();
// P1: orientiertes Quadrat (Normale + Roll + Spin in einem Quaternion).
// PlaneGeometry hat nativ die +Z-Normale, qMarkerW dreht +Z auf die