feat(pose_3d): Jog mode auto-apply + safety + Precise toggle
This commit is contained in:
1 parent
5b2239e307
commit
a81fc9acf9
1 file changed
+75
@@ -424,6 +424,78 @@ function bindEditorButtons() {
|
|||||||
$('p3CancelBtn').addEventListener('click', onCancelClick);
|
$('p3CancelBtn').addEventListener('click', onCancelClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- mode toggle -----
|
||||||
|
function bindModeControls() {
|
||||||
|
for (const r of document.querySelectorAll('input[name=p3Mode]')) {
|
||||||
|
r.addEventListener('change', () => {
|
||||||
|
state.mode = r.value;
|
||||||
|
const badge = $('p3ModeBadge');
|
||||||
|
if (state.mode === 'jog') {
|
||||||
|
badge.textContent = '🔴 JOG (live)';
|
||||||
|
badge.classList.add('jog');
|
||||||
|
$('p3EditorActions').style.display = 'none';
|
||||||
|
} else {
|
||||||
|
badge.textContent = 'Editor';
|
||||||
|
badge.classList.remove('jog');
|
||||||
|
$('p3EditorActions').style.display = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindPreciseControl() {
|
||||||
|
$('p3Precise').addEventListener('change', (e) => {
|
||||||
|
state.precise = e.target.checked;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----- jog auto-apply al mouseup gizmo -----
|
||||||
|
function bindJogAutoApply() {
|
||||||
|
const { transform } = state.three;
|
||||||
|
transform.addEventListener('dragging-changed', async (e) => {
|
||||||
|
if (e.value) return; // inizio drag, niente
|
||||||
|
if (state.mode !== 'jog') return;
|
||||||
|
const side = state.active_side;
|
||||||
|
const tgt = state.target[side];
|
||||||
|
if (!tgt) return;
|
||||||
|
const cur = state.current[side];
|
||||||
|
if (!cur) return;
|
||||||
|
const dx = tgt.position[0] - cur.position[0];
|
||||||
|
const dy = tgt.position[1] - cur.position[1];
|
||||||
|
const dz = tgt.position[2] - cur.position[2];
|
||||||
|
const delta = Math.sqrt(dx*dx + dy*dy + dz*dz);
|
||||||
|
if (delta > state.live_max_step_m) {
|
||||||
|
const ok = confirm(
|
||||||
|
`Movimento richiesto ${(delta*1000).toFixed(0)} mm > soglia ${(state.live_max_step_m*1000).toFixed(0)} mm.\n` +
|
||||||
|
`Procedere comunque?`,
|
||||||
|
);
|
||||||
|
if (!ok) return;
|
||||||
|
}
|
||||||
|
clearError();
|
||||||
|
try {
|
||||||
|
const res = await jsonFetch('/api/pose_3d/apply', {
|
||||||
|
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
side, position: tgt.position, quaternion: tgt.quaternion,
|
||||||
|
dry_run: false, precise: state.precise,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const r = res.result || {};
|
||||||
|
if (r.reached_target === false || r.stalled === true) {
|
||||||
|
showError(`Move non completato: residual ${(r.position_error_mm||0).toFixed(1)} mm. ` +
|
||||||
|
`Sblocca braccia e riprova, oppure disattiva Precise.`);
|
||||||
|
} else {
|
||||||
|
$('p3Status').textContent = `✓ Jog: raggiunto (residual ${(r.position_error_mm||0).toFixed(1)} mm)`;
|
||||||
|
$('p3Status').className = 'p3-status ok';
|
||||||
|
state.target[side] = null;
|
||||||
|
syncGhostsToTargetOrReal();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
showError(e.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// ----- init triggered on first activation -----
|
// ----- init triggered on first activation -----
|
||||||
let inited = false;
|
let inited = false;
|
||||||
function ensureInit() {
|
function ensureInit() {
|
||||||
@@ -436,6 +508,9 @@ function ensureInit() {
|
|||||||
bindGizmoControls();
|
bindGizmoControls();
|
||||||
bindGizmoEvents();
|
bindGizmoEvents();
|
||||||
bindEditorButtons();
|
bindEditorButtons();
|
||||||
|
bindModeControls();
|
||||||
|
bindPreciseControl();
|
||||||
|
bindJogAutoApply();
|
||||||
pollState();
|
pollState();
|
||||||
pollTimer = setInterval(pollState, POLL_MS);
|
pollTimer = setInterval(pollState, POLL_MS);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user