Idle animations. Closes #14

This commit is contained in:
PROFERIS - Mi³osz Stocki
2026-07-09 14:01:00 +02:00
parent 79e0be007e
commit dd8f6b2277
6 changed files with 244 additions and 14 deletions
+34 -14
View File
@@ -52,21 +52,39 @@ function getSteps() {
let motionQueue = [];
let isMoving = false;
let currentIsIdleMove = false;
let currentResolve = null;
let queueCheckInterval = null;
let currentMotionMode = 'direct';
let hasHesitated = false;
function stopCurrentMove() {
motionQueue = [];
isMoving = false;
if (queueCheckInterval) {
clearInterval(queueCheckInterval);
queueCheckInterval = null;
}
if (currentResolve) {
currentResolve(false); // resolve false because aborted
currentResolve = null;
}
}
async function executeQueue() {
if (motionQueue.length === 0) {
isMoving = false;
if (queueCheckInterval) clearInterval(queueCheckInterval);
if (queueCheckInterval) {
clearInterval(queueCheckInterval);
queueCheckInterval = null;
}
// Restore speed if it was altered
await MotionEffects.onSequenceEnd(currentMotionMode);
if (currentResolve) currentResolve(true);
currentResolve = null;
document.dispatchEvent(new CustomEvent('wiji:motion-end', { detail: { isIdleMove: currentIsIdleMove } }));
return;
}
@@ -83,11 +101,8 @@ async function executeQueue() {
await BLE.write(cmd);
} catch (e) {
UI.log(`BLE error: ${e.message}`, 'error');
motionQueue = []; // clear queue on error
isMoving = false;
if (queueCheckInterval) clearInterval(queueCheckInterval);
if (currentResolve) currentResolve(false);
currentResolve = null;
stopCurrentMove();
document.dispatchEvent(new CustomEvent('wiji:motion-end', { detail: { isIdleMove: currentIsIdleMove } }));
return;
}
@@ -102,12 +117,9 @@ async function executeQueue() {
// Check for timeout stall
if (Date.now() - waypointStartTime > CONFIG.WAYPOINT_TIMEOUT_MS) {
clearInterval(queueCheckInterval);
motionQueue = [];
isMoving = false;
stopCurrentMove();
forceUnhome('Motion timeout! Arms may be stuck. Rehoming required.');
if (currentResolve) currentResolve(false);
currentResolve = null;
document.dispatchEvent(new CustomEvent('wiji:motion-end', { detail: { isIdleMove: currentIsIdleMove } }));
return;
}
@@ -222,12 +234,18 @@ function buildSegments(startX, startY, endX, endY, mode) {
* Dynamically slices the path into segments to prevent out-of-bounds arcs.
* @returns {Promise<boolean>} Resolves to true if successful, false if aborted/error.
*/
async function goto(targetX, targetY, mode = 'direct') {
async function goto(targetX, targetY, mode = 'direct', isIdleMove = false) {
if (isMoving) {
UI.log('Arm is currently moving! Wait for it to finish.', 'warn');
return false;
// If the currently executing move is an idle move, and this is a user move, we can interrupt it.
if (currentIsIdleMove && !isIdleMove) {
stopCurrentMove(); // Abort the idle move
} else {
UI.log('Arm is currently moving! Wait for it to finish.', 'warn');
return false;
}
}
currentIsIdleMove = isIdleMove;
mode = MotionEffects.resolveMode(mode);
currentMotionMode = mode;
@@ -283,6 +301,8 @@ async function goto(targetX, targetY, mode = 'direct') {
await MotionEffects.onSequenceStart(mode);
document.dispatchEvent(new CustomEvent('wiji:motion-start', { detail: { isIdleMove: currentIsIdleMove } }));
return new Promise((resolve) => {
currentResolve = resolve;
executeQueue();