feat(pose_3d): piazzamento Nuwa allineato nel frame D435i (matrice)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
2f0dc69cdd
commit
746662d534
1 file changed
+51
@@ -222,6 +222,7 @@ const state = {
|
|||||||
joint_ucses: [], // array di THREE.Group, UCS per ogni link URDF (debug)
|
joint_ucses: [], // array di THREE.Group, UCS per ogni link URDF (debug)
|
||||||
clouds_cfg: null, // {nuwa:{...}, d435:{...}} dal config
|
clouds_cfg: null, // {nuwa:{...}, d435:{...}} dal config
|
||||||
cloud_points: { nuwa: null, d435: null }, // THREE.Points obj per camera
|
cloud_points: { nuwa: null, d435: null }, // THREE.Points obj per camera
|
||||||
|
align: { enabled: false, id: 0, matrix: null /* THREE.Matrix4 */ },
|
||||||
tag_locator: { // sezione "Tag locator" nella sidebar Pose 3D
|
tag_locator: { // sezione "Tag locator" nella sidebar Pose 3D
|
||||||
marker: null, // THREE.LineSegments (crocetta XYZ) o null
|
marker: null, // THREE.LineSegments (crocetta XYZ) o null
|
||||||
position_m: null, // [x,y,z] in pelvis frame della crocetta corrente
|
position_m: null, // [x,y,z] in pelvis frame della crocetta corrente
|
||||||
@@ -1605,8 +1606,12 @@ function buildOrUpdateCloud(camKey, pointsFlat) {
|
|||||||
`Y[${ymin.toFixed(2)},${ymax.toFixed(2)}]`,
|
`Y[${ymin.toFixed(2)},${ymax.toFixed(2)}]`,
|
||||||
`Z[${zmin.toFixed(2)},${zmax.toFixed(2)}]`);
|
`Z[${zmin.toFixed(2)},${zmax.toFixed(2)}]`);
|
||||||
// (Ri-)attacca al parent corretto e applica transform optical→link
|
// (Ri-)attacca al parent corretto e applica transform optical→link
|
||||||
|
if (camKey === 'nuwa') {
|
||||||
|
applyNuwaCloudPlacement();
|
||||||
|
} else {
|
||||||
if (pts.parent !== parent) parent.add(pts);
|
if (pts.parent !== parent) parent.add(pts);
|
||||||
applyCloudTransform(camKey);
|
applyCloudTransform(camKey);
|
||||||
|
}
|
||||||
applyCloudVisibility();
|
applyCloudVisibility();
|
||||||
return pts;
|
return pts;
|
||||||
}
|
}
|
||||||
@@ -1621,6 +1626,24 @@ function applyCloudVisibility() {
|
|||||||
// Applica position+rpy+mirror sui punti del cloud `camKey`. Il mirror (sign
|
// Applica position+rpy+mirror sui punti del cloud `camKey`. Il mirror (sign
|
||||||
// flip per asse) avviene IN FRAME OTTICO grazie all'ordine T·R·S di Three.js
|
// flip per asse) avviene IN FRAME OTTICO grazie all'ordine T·R·S di Three.js
|
||||||
// (lo scale e' la prima operazione applicata al punto locale).
|
// (lo scale e' la prima operazione applicata al punto locale).
|
||||||
|
// Matrix4 locale (rispetto al parent getCloudParent('d435')) usata dal cloud
|
||||||
|
// D435i: hand-eye (M·S) oppure URDF (T·R·S). Riusata per piazzare la Nuwa
|
||||||
|
// allineata nello stesso frame del D435i.
|
||||||
|
function d435LocalMatrix() {
|
||||||
|
const sv = readCloudScaleVec('d435');
|
||||||
|
const S = new THREE.Matrix4().makeScale(sv[0], sv[1], sv[2]);
|
||||||
|
if (useD435Handeye()) {
|
||||||
|
const M = getD435HandeyeMatrix();
|
||||||
|
if (M) return M.clone().multiply(S);
|
||||||
|
}
|
||||||
|
const t = getCloudTransform('d435');
|
||||||
|
const T = new THREE.Matrix4().makeTranslation(t.offset_m[0], t.offset_m[1], t.offset_m[2]);
|
||||||
|
const e = new THREE.Euler(
|
||||||
|
t.rpy_deg[0]*Math.PI/180, t.rpy_deg[1]*Math.PI/180, t.rpy_deg[2]*Math.PI/180, 'XYZ');
|
||||||
|
const R = new THREE.Matrix4().makeRotationFromEuler(e);
|
||||||
|
return T.multiply(R).multiply(S);
|
||||||
|
}
|
||||||
|
|
||||||
function applyCloudTransform(camKey) {
|
function applyCloudTransform(camKey) {
|
||||||
const pts = state.cloud_points[camKey];
|
const pts = state.cloud_points[camKey];
|
||||||
if (!pts) return;
|
if (!pts) return;
|
||||||
@@ -1652,6 +1675,34 @@ function applyCloudTransform(camKey) {
|
|||||||
pts.scale.set(sv[0], sv[1], sv[2]);
|
pts.scale.set(sv[0], sv[1], sv[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Piazza la nuvola Nuwa: in modalità allineata la renderizza nel frame del
|
||||||
|
// D435i (parent + pipeline D435i · matrice di allineamento); altrimenti usa il
|
||||||
|
// piazzamento URDF normale.
|
||||||
|
function applyNuwaCloudPlacement() {
|
||||||
|
const pts = state.cloud_points.nuwa;
|
||||||
|
if (!pts) return;
|
||||||
|
const aligned = state.align.enabled && state.align.matrix;
|
||||||
|
if (aligned) {
|
||||||
|
const parent = getCloudParent('d435');
|
||||||
|
if (parent) {
|
||||||
|
if (pts.parent !== parent) parent.add(pts);
|
||||||
|
pts.matrixAutoUpdate = false;
|
||||||
|
pts.matrix.copy(d435LocalMatrix()).multiply(state.align.matrix);
|
||||||
|
pts.matrixWorldNeedsUpdate = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state.align.enabled && !state.align.matrix) {
|
||||||
|
const s = $('p3AlignStatus');
|
||||||
|
if (s) { s.textContent = 'nessuna calibrazione: premi Allinea'; s.style.color = 'var(--dim)'; }
|
||||||
|
}
|
||||||
|
// fallback URDF normale
|
||||||
|
const parent = getCloudParent('nuwa');
|
||||||
|
if (parent && pts.parent !== parent) parent.add(pts);
|
||||||
|
pts.matrixAutoUpdate = true;
|
||||||
|
applyCloudTransform('nuwa');
|
||||||
|
}
|
||||||
|
|
||||||
function readCloudFlip(camKey) {
|
function readCloudFlip(camKey) {
|
||||||
const tag = camKey === 'nuwa' ? 'Nuwa' : 'D435';
|
const tag = camKey === 'nuwa' ? 'Nuwa' : 'D435';
|
||||||
return [
|
return [
|
||||||
|
|||||||
Reference in new issue
Block a user