Complete 3axis tutorial native and Web/WASM parity tools
This commit is contained in:
@@ -23,6 +23,7 @@ export class MotionState {
|
||||
feed_override: 1,
|
||||
spindle_override: 1,
|
||||
homed: false,
|
||||
homed_axes: [false, false, false],
|
||||
limits: { x: false, y: false, z: false },
|
||||
following_error: 0,
|
||||
jog: null,
|
||||
@@ -42,8 +43,14 @@ export class MotionState {
|
||||
if (this.state.estop) return this.fail("motion_estop_active");
|
||||
if (target !== null && !axis(target)) return this.fail("motion_axis_invalid");
|
||||
const targets = target === null ? AXES : [axis(target)];
|
||||
for (const name of targets) { this.state.axes[name] = 0; this.state.joints[AXES.indexOf(name)] = 0; this.state.limits[name] = false; }
|
||||
this.state.homed = true;
|
||||
for (const name of targets) {
|
||||
const index = AXES.indexOf(name);
|
||||
this.state.axes[name] = 0;
|
||||
this.state.joints[index] = 0;
|
||||
this.state.homed_axes[index] = true;
|
||||
this.state.limits[name] = false;
|
||||
}
|
||||
this.state.homed = this.state.homed_axes.every(Boolean);
|
||||
this.state.fault = null;
|
||||
this.state.following_error = 0;
|
||||
this.state.tick += 1;
|
||||
@@ -57,13 +64,14 @@ export class MotionState {
|
||||
return this.ok("SET_OVERRIDE");
|
||||
}
|
||||
|
||||
startJog({ axis: requestedAxis, direction = 1, speed = 1 } = {}) {
|
||||
startJog({ axis: requestedAxis, direction = 1, speed = 1, increment = null } = {}) {
|
||||
const name = axis(requestedAxis);
|
||||
if (!name) return this.fail("motion_axis_invalid");
|
||||
if (!this.state.homed) return this.fail("motion_unhomed");
|
||||
if (this.state.estop || this.state.fault) return this.fail("motion_faulted");
|
||||
if (!Number.isSafeInteger(direction) || ![-1, 1].includes(direction) || !finite(speed) || speed <= 0 || speed > MAX_SPEED) return this.fail("motion_jog_range");
|
||||
this.state.jog = { axis: name, direction, speed };
|
||||
const jogIncrement = finite(increment) && increment > 0 ? Number(increment) : null;
|
||||
this.state.jog = { axis: name, direction, speed, ...(jogIncrement === null ? {} : { increment: jogIncrement }) };
|
||||
this.state.velocity = speed * this.state.feed_override;
|
||||
return this.ok("JOG_START");
|
||||
}
|
||||
@@ -91,6 +99,16 @@ export class MotionState {
|
||||
return this.ok("FOLLOWING_ERROR");
|
||||
}
|
||||
|
||||
resetFault() {
|
||||
if (this.state.estop) return this.fail("motion_estop_active");
|
||||
if (Object.values(this.state.limits).some(Boolean)) return this.fail("motion_limit_active");
|
||||
this.state.fault = null;
|
||||
this.state.following_error = 0;
|
||||
this.state.velocity = 0;
|
||||
this.state.jog = null;
|
||||
return this.ok("RESET");
|
||||
}
|
||||
|
||||
estop(active) {
|
||||
if (typeof active !== "boolean") return this.fail("motion_estop_argument");
|
||||
this.state.estop = active;
|
||||
@@ -105,12 +123,27 @@ export class MotionState {
|
||||
if (!this.state.jog || this.state.estop || this.state.fault) { this.state.velocity = 0; return this.export(); }
|
||||
const { axis: name, direction, speed } = this.state.jog;
|
||||
if (this.state.limits[name]) { this.state.fault = "limit"; this.state.jog = null; this.state.velocity = 0; return this.export(); }
|
||||
const delta = direction * speed * this.state.feed_override * CYCLE_DISTANCE;
|
||||
const requested = speed * this.state.feed_override * CYCLE_DISTANCE;
|
||||
const increment = this.state.jog.increment == null ? null : this.state.jog.increment;
|
||||
const delta = direction * (increment === null ? requested : Math.min(requested, increment));
|
||||
const next = this.state.axes[name] + delta;
|
||||
if (!finite(next) || Math.abs(next) > MAX_POSITION) { this.state.fault = "position_range"; this.state.jog = null; this.state.velocity = 0; return this.export(); }
|
||||
this.state.axes[name] = next;
|
||||
this.state.joints[AXES.indexOf(name)] = next;
|
||||
this.state.velocity = Math.abs(speed * this.state.feed_override);
|
||||
if (increment !== null) {
|
||||
this.state.jog.increment = increment - Math.abs(delta);
|
||||
if (this.state.jog.increment <= 1e-12) { this.state.jog = null; this.state.velocity = 0; }
|
||||
}
|
||||
return this.export();
|
||||
}
|
||||
|
||||
applyWasmPosition(position, velocity = 0, tick = this.state.tick) {
|
||||
if (!position || ![position.x, position.y, position.z].every(finite)) return this.fail("motion_wasm_position_invalid");
|
||||
this.state.axes = { x: position.x, y: position.y, z: position.z };
|
||||
this.state.joints = [position.x, position.y, position.z];
|
||||
this.state.velocity = finite(velocity) ? velocity : 0;
|
||||
this.state.tick = Math.max(this.state.tick, Number.isSafeInteger(tick) ? tick : this.state.tick);
|
||||
return this.export();
|
||||
}
|
||||
|
||||
@@ -119,7 +152,11 @@ export class MotionState {
|
||||
const unsigned = { ...value }; delete unsigned.state_hash;
|
||||
if (value.state_hash !== fnv1a64(unsigned)) throw new Error("motion_restore_hash");
|
||||
if (!finite(value.tick) || !value.axes || !Array.isArray(value.joints) || value.joints.length !== 3) throw new Error("motion_restore_shape");
|
||||
this.state = clone(unsigned);
|
||||
const homedAxes = Array.isArray(value.homed_axes)
|
||||
? value.homed_axes.slice(0, AXES.length).map(Boolean)
|
||||
: AXES.map(() => value.homed === true);
|
||||
if (homedAxes.length !== AXES.length) throw new Error("motion_restore_homed_shape");
|
||||
this.state = { ...clone(unsigned), homed_axes: homedAxes, homed: homedAxes.every(Boolean) };
|
||||
return this.export();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user