Complete 3axis tutorial native and Web/WASM parity tools
This commit is contained in:
@@ -41,6 +41,39 @@ function readInterpreterState(core, pointer) {
|
||||
};
|
||||
}
|
||||
|
||||
function readInterpreterMotion(core, interpreter, sourceLine = null) {
|
||||
if (typeof core._sim_interpreter_read_motion !== "function" || typeof core._sim_interpreter_motion_size !== "function") return null;
|
||||
const size = core._sim_interpreter_motion_size();
|
||||
if (!Number.isSafeInteger(size) || size < 216 || size > 4096) throw new Error("wasm_motion_size_invalid");
|
||||
const pointer = core._malloc(size);
|
||||
if (!pointer) throw new Error("wasm_motion_allocation_failed");
|
||||
try {
|
||||
const result = call(core, "sim_interpreter_read_motion", "number", ["number", "number"], [interpreter, pointer]);
|
||||
if (result !== 0) return null;
|
||||
const doubles = core.HEAPF64.subarray(pointer / 8, pointer / 8 + 26);
|
||||
const ints = core.HEAP32.subarray(pointer / 4 + 52, pointer / 4 + 54);
|
||||
const pose = (offset) => ({
|
||||
x: doubles[offset], y: doubles[offset + 1], z: doubles[offset + 2],
|
||||
a: doubles[offset + 3], b: doubles[offset + 4], c: doubles[offset + 5],
|
||||
u: doubles[offset + 6], v: doubles[offset + 7], w: doubles[offset + 8],
|
||||
});
|
||||
return {
|
||||
source_line: sourceLine,
|
||||
start: pose(0),
|
||||
end: pose(9),
|
||||
center: { x: doubles[18], y: doubles[19], z: doubles[20] },
|
||||
normal: { x: doubles[21], y: doubles[22], z: doubles[23] },
|
||||
velocity: doubles[24],
|
||||
acceleration: doubles[25],
|
||||
motion_type: ints[0],
|
||||
turn: ints[1],
|
||||
source: "wasm_interpreter_canonical_motion",
|
||||
};
|
||||
} finally {
|
||||
core._free(pointer);
|
||||
}
|
||||
}
|
||||
|
||||
function readCanonical(core, interpreter) {
|
||||
if (typeof core._sim_interpreter_canonical !== "function") return null;
|
||||
const required = call(core, "sim_interpreter_canonical", "number", ["number", "number", "number"], [interpreter, 0, 0]);
|
||||
@@ -328,6 +361,32 @@ export class ProgramRunner {
|
||||
return this.snapshot();
|
||||
}
|
||||
|
||||
preview() {
|
||||
if (!this.loaded) return { status: "error", code: "program_not_loaded" };
|
||||
const source = this.source;
|
||||
const path = this.path;
|
||||
const segments = [];
|
||||
let result = { status: "verified" };
|
||||
try {
|
||||
for (let steps = 0; steps < MAX_EXPANDED_LINES && this.programCounter < this.lines.length; steps += 1) {
|
||||
result = this.executeNext(true);
|
||||
if (result.status !== "verified") break;
|
||||
if (result.motion) {
|
||||
const motion = result.motion;
|
||||
const linearNoop = motion.motion_type === 1
|
||||
&& ["x", "y", "z", "a", "b", "c", "u", "v", "w"].every((axis) => motion.start[axis] === motion.end[axis]);
|
||||
if (!linearNoop) segments.push(motion);
|
||||
}
|
||||
}
|
||||
if (result.status !== "verified") return { ...result, preview: { status: "error", segments } };
|
||||
return { status: "verified", preview: { status: "verified", segments } };
|
||||
} catch (error) {
|
||||
return { status: "error", code: error.message, preview: { status: "error", segments } };
|
||||
} finally {
|
||||
this.load(source, path);
|
||||
}
|
||||
}
|
||||
|
||||
pause() {
|
||||
if (this.status !== "running") return { status: "error", code: "program_not_running" };
|
||||
this.status = "paused";
|
||||
@@ -398,7 +457,7 @@ export class ProgramRunner {
|
||||
if (stateResult !== 0) return { status: "error", code: "mdi_state_read", result: stateResult };
|
||||
this.state = readInterpreterState(this.core, this.stateBuffer);
|
||||
const interpreterState = cloneState(this.state);
|
||||
return { status: "verified", block, state: interpreterState, interpreter_state: interpreterState, runner: this.snapshot() };
|
||||
return { status: "verified", block, state: interpreterState, interpreter_state: interpreterState, motion: readInterpreterMotion(this.core, this.interpreter, this.state.line), runner: this.snapshot() };
|
||||
} catch (error) {
|
||||
return { status: "error", code: error.message };
|
||||
}
|
||||
@@ -588,7 +647,7 @@ export class ProgramRunner {
|
||||
}
|
||||
if (this.state.program_end) this.status = "completed";
|
||||
else if (this.programCounter >= this.lines.length && !seeking) this.status = "completed";
|
||||
return { status: "verified", line: index + 1, text: sourceLine, state: cloneState(this.state), program_status: this.status };
|
||||
return { status: "verified", line: index + 1, text: sourceLine, state: cloneState(this.state), program_status: this.status, motion: readInterpreterMotion(this.core, this.interpreter, index + 1) };
|
||||
}
|
||||
this.status = "completed";
|
||||
return { status: "verified", line: this.currentLine, text: null, state: cloneState(this.state), program_status: this.status };
|
||||
@@ -618,6 +677,11 @@ export class ProgramRunner {
|
||||
this.lastError = this.lastError ?? { code: error.message };
|
||||
}
|
||||
}
|
||||
const unitsCode = this.state.units === 20 ? "G20" : "G21";
|
||||
const distanceCode = this.state.distance_mode === 91 ? "G91" : "G90";
|
||||
const planeCode = this.state.plane === 18 ? "G18" : this.state.plane === 19 ? "G19" : "G17";
|
||||
const motionCode = `G${this.state.motion_mode}`;
|
||||
const spindleCode = this.state.spindle_mode === 5 ? "M5" : `M${this.state.spindle_mode}`;
|
||||
return {
|
||||
status: "verified",
|
||||
program_status: this.status,
|
||||
@@ -632,6 +696,7 @@ export class ProgramRunner {
|
||||
modal_hash,
|
||||
motion_control: { ...this.motionControl },
|
||||
motion_control_hash: fnv1a64(this.motionControl),
|
||||
active_gcodes: `${unitsCode} ${distanceCode} ${planeCode} ${motionCode} ${spindleCode}`,
|
||||
error_column,
|
||||
error_code,
|
||||
error: this.lastError,
|
||||
|
||||
Reference in New Issue
Block a user