Display live WASM machining parameters

This commit is contained in:
2026-09-02 12:38:27 +08:00
parent cd0286a3d6
commit ee2c992328
15 changed files with 152 additions and 10 deletions

View File

@@ -196,6 +196,13 @@ export class SimSession {
source_hash: program.source_hash,
state_hash: program.state_hash,
active_gcodes: program.active_gcodes,
feed: program.feed,
speed: program.speed,
units: program.units,
distance_mode: program.distance_mode,
motion_control: program.motion_control,
motion_control_mode: program.motion_control_mode,
path_tolerance: program.path_tolerance,
} : null;
const trace = Array.isArray(statePayload.motion_trace) ? statePayload.motion_trace : [];
const motionSample = motionDelta ? (trace.at(-1) ?? {
@@ -239,12 +246,14 @@ export class SimSession {
};
}
wasmMotionProjection() {
wasmMotionProjection(program = null) {
const wasmMotion = this.wasmMotion.read();
const position = wasmMotion.status === "verified" ? wasmMotion.state.position : { x: 0, y: 0, z: 0, a: 0, b: 0, c: 0, u: 0, v: 0, w: 0 };
const home = this.wasmHomeLimit.read();
const io = this.xyzacIo?.canonical?.();
const ioState = io && typeof io === "object" && io.status !== "blocked" ? io : null;
const sourceProgram = program ?? this.xyzacProgram?.snapshot();
const spindle = ioState?.spindles?.[0] ?? null;
const kinematics = this.xyzacKinematics?.snapshot?.();
const plannerJoints = wasmMotion.status === "verified" && Array.isArray(wasmMotion.state.joint_commanded) && wasmMotion.state.joint_commanded.length === 5 ? [...wasmMotion.state.joint_commanded] : null;
const kinematicsJoints = plannerJoints ?? (kinematics?.joints?.length === 5 ? [...kinematics.joints] : null);
@@ -255,8 +264,14 @@ export class SimSession {
axes: { x: position.x, y: position.y, z: position.z },
joints: kinematicsJoints ?? (home.status === "verified" && Array.isArray(home.state.joints) ? [...home.state.joints] : [position.x, position.y, position.z, position.a ?? 0, position.c ?? 0]),
velocity: wasmMotion.status === "verified" ? wasmMotion.state.velocity : 0,
velocity_mm_min: Number(wasmMotion.state?.velocity_mm_min ?? 0),
feed_command_mm_min: Number(sourceProgram?.feed ?? 0),
feed_override: Number(wasmMotion.state?.feed_override ?? 1),
spindle_override: Number(ioState?.spindles?.[0]?.override ?? 1),
spindle_speed_rpm: Number(spindle?.speed_rpm ?? 0),
spindle_command_rpm: Number(spindle?.command_rpm ?? 0),
spindle_enabled: Boolean(spindle?.enabled),
spindle_at_speed: Boolean(spindle?.at_speed),
velocity_scale: Number(wasmMotion.state?.velocity_scale ?? 1),
jog_scale: Number(wasmMotion.state?.jog_scale ?? 1),
jog_velocity_linear: Number(wasmMotion.state?.jog_velocity_linear ?? 0),
@@ -290,6 +305,17 @@ export class SimSession {
return { ...unsigned, state_hash: fnv1a64(unsigned) };
}
syncXyzacProgramSpindle(program) {
if (!this.xyzacIo || !program || typeof program !== "object") return { status: "skipped" };
const mode = Number(program.spindle_mode ?? 5);
const rpm = Number(program.speed ?? 0);
const enabled = (mode === 3 || mode === 4) && Number.isFinite(rpm) && rpm > 0;
const signedRpm = mode === 4 ? -rpm : rpm;
const current = this.xyzacIo.canonical()?.spindles?.[0];
if (current && Boolean(current.enabled) === enabled && Math.abs(Number(current.command_rpm ?? 0) - (enabled ? signedRpm * Number(current.override ?? 1) : 0)) < 1e-9) return { status: "skipped" };
return this.xyzacIo.command("SPINDLE_COMMAND", { spindle: 0, rpm: signedRpm, enabled });
}
loadXyzacSubroutines(programPath) {
if (!this.xyzacProgram) return { status: "verified", count: 0 };
const requirement = this.xyzacProgram.requiresSubroutines();
@@ -323,7 +349,7 @@ export class SimSession {
}
panelSnapshot({ task = this.task.export(), program = this.xyzacProgram ? this.xyzacProgram.snapshot() : this.program.loaded ? this.program.snapshot() : null, input = {}, tick = this.tick, motionTrace = null, includeToolpath = input.kind !== "SIM_STEP" || !this.xyzacProgram, includeConfiguration = input.kind !== "SIM_STEP" || !this.xyzacProgram, includeStableRuntime = input.kind !== "SIM_STEP" || !this.xyzacProgram } = {}) {
const motion = this.xyzacProgram ? this.wasmMotionProjection() : this.motion.export();
const motion = this.xyzacProgram ? this.wasmMotionProjection(program) : this.motion.export();
const wasmMotion = this.wasmMotion.read();
const homeLimit = this.wasmHomeLimit.read();
const ioState = this.xyzacIo?.canonical?.() ?? {};
@@ -1681,6 +1707,8 @@ export class SimSession {
}
const step = this.xyzacProgram.step();
if (step.status !== "verified") throw new Error(step.code);
const spindleSync = this.syncXyzacProgramSpindle(step.program);
if (spindleSync.status === "error") throw new Error(spindleSync.code ?? "wasm_program_spindle_sync_failed");
// Path control is produced by the WASM interpreter and
// applied to the WASM trajectory queue before enqueue.
const motionControlMode = Number(step.program?.motion_control_mode ?? 0);