Align AXIS Web control lifecycle with LinuxCNC
This commit is contained in:
@@ -78,6 +78,7 @@ export class WasmProgramRuntime {
|
||||
this.executionLines = [];
|
||||
this.executionLineMetadata = [];
|
||||
this.rapidVelocity = 35;
|
||||
this.synchronizedPosition = Object.fromEntries(AXES.map((axis) => [axis, 0]));
|
||||
if (!this.available || typeof core?._malloc !== "function") return;
|
||||
this.pointer = core._malloc(call(core, "sim_program_size", "number", [], []));
|
||||
this.motionPointer = core._malloc(SEGMENT_BYTES);
|
||||
@@ -137,6 +138,8 @@ export class WasmProgramRuntime {
|
||||
try {
|
||||
const loaded = temporary.load(this.source, this.path);
|
||||
if (loaded.status !== "verified") return loaded;
|
||||
const synchronized = temporary.synchronizePosition(this.synchronizedPosition);
|
||||
if (synchronized.status !== "verified") return synchronized;
|
||||
temporary.setRapidVelocity(this.rapidVelocity);
|
||||
for (const subroutine of this.subroutines) {
|
||||
const added = temporary.addSubroutine(subroutine.name, subroutine.source, subroutine.path);
|
||||
@@ -158,6 +161,15 @@ export class WasmProgramRuntime {
|
||||
}
|
||||
|
||||
start() { return this.invoke("sim_program_start", [], "program_start"); }
|
||||
synchronizePosition(value) {
|
||||
const position = Object.fromEntries(AXES.map((axis) => [axis, Number(value?.[axis] ?? 0)]));
|
||||
if (Object.values(position).some((coordinate) => !Number.isFinite(coordinate))) return { status: "error", code: "program_position_nonfinite" };
|
||||
this.core.HEAPF64.set(AXES.map((axis) => position[axis]), this.samplePosePointer / 8);
|
||||
const result = call(this.core, "sim_program_set_position", "number", ["number", "number"], [this.pointer, this.samplePosePointer]);
|
||||
if (result !== 0) return programError("program_set_position", result);
|
||||
this.synchronizedPosition = position;
|
||||
return { status: "verified", command: "sim_program_set_position", position: { ...position } };
|
||||
}
|
||||
setRapidVelocity(velocity) {
|
||||
if (!Number.isFinite(Number(velocity)) || Number(velocity) <= 0) return { status: "error", code: "program_rapid_velocity_invalid" };
|
||||
this.rapidVelocity = Number(velocity);
|
||||
@@ -200,6 +212,8 @@ export class WasmProgramRuntime {
|
||||
const subroutines = [...this.subroutines];
|
||||
const loaded = this.load(this.source, this.path);
|
||||
if (loaded.status !== "verified") throw new Error(loaded.code);
|
||||
const synchronized = this.synchronizePosition(Object.fromEntries(AXES.map((axis) => [axis, Number(value[axis] ?? 0)])));
|
||||
if (synchronized.status !== "verified") throw new Error(synchronized.code);
|
||||
for (const subroutine of subroutines) {
|
||||
const added = this.addSubroutine(subroutine.name, subroutine.source);
|
||||
if (added.status !== "verified") throw new Error(added.code);
|
||||
@@ -243,6 +257,15 @@ export class WasmProgramRuntime {
|
||||
const result = call(this.core, "sim_program_read_motion", "number", ["number", "number"], [this.pointer, this.motionPointer]);
|
||||
if (result !== 0) return null;
|
||||
const value = segment(this.core, this.motionPointer);
|
||||
// LinuxCNC does not enqueue a trajectory segment when a linear/rapid
|
||||
// block resolves to the current synchronized pose. This occurs naturally
|
||||
// when AUTO_RUN reopens a completed/aborted file and its first positioning
|
||||
// block names the position where the previous run stopped.
|
||||
const linearNoop = value.motion_type === 1 && AXES.every((axis) => Math.abs(Number(value.start?.[axis] ?? 0) - Number(value.end?.[axis] ?? 0)) <= 1e-12);
|
||||
if (linearNoop) {
|
||||
call(this.core, "sim_program_clear_motion", "number", ["number"], [this.pointer]);
|
||||
return null;
|
||||
}
|
||||
// LinuxCNC rapid blocks do not carry an F word. The trajectory queue
|
||||
// requires a positive velocity, so use the simulation's configured rapid
|
||||
// rate for that WASM-produced linear segment.
|
||||
|
||||
Reference in New Issue
Block a user