Lock AXIS panel contract to source behavior
This commit is contained in:
@@ -175,7 +175,7 @@ export class SimSession {
|
||||
const task = statePayload.task ?? this.task.export();
|
||||
// The loaded toolpath is immutable during execution. Avoid cloning all
|
||||
// WASM pose samples into every 10 ms step response; the frontend retains
|
||||
// the canonical path from PROGRAM_LOAD/PROGRAM_RESTART.
|
||||
// the canonical path published by the latest program transaction.
|
||||
const xyzacProgramActive = Boolean(this.xyzacProgram);
|
||||
const lightweightXyzacStep = input.kind === "SIM_STEP" && xyzacProgramActive;
|
||||
const traceOnlyStep = lightweightXyzacStep && input.payload?.trace_only === true;
|
||||
@@ -1997,7 +1997,6 @@ export class SimSession {
|
||||
case "PROGRAM_LOAD": {
|
||||
if (["RUNNING", "PAUSED"].includes(this.task.state.state)) return finish(this.error(input, "task_state", "program_load_while_active"), "failed");
|
||||
const source = input.payload?.source ?? input.payload?.text ?? input.payload?.program_source;
|
||||
this.livePathEpoch += 1;
|
||||
const savedMode = this.task.state.mode;
|
||||
const restoreMode = () => {
|
||||
if (savedMode !== "MANUAL" && this.task.state.mode !== savedMode) this.task.setMode(savedMode);
|
||||
@@ -2077,12 +2076,11 @@ export class SimSession {
|
||||
if (this.xyzacProgram) {
|
||||
const previousProgramStatus = this.xyzacProgram.snapshot().program_status;
|
||||
const result = this.xyzacProgram.start();
|
||||
if (result.status === "verified") { this.livePathEpoch += 1; this.wasmMotion.setPaused(false); this.task.setMode("AUTO"); if (this.task.state.state === "STOPPED") this.task.recover(); this.task.transition("RUNNING"); const program = this.xyzacProgram.snapshot(); this.task.setProgram("running", program.execution_source_line ?? program.current_line); }
|
||||
if (result.status === "verified") { this.wasmMotion.setPaused(false); this.task.setMode("AUTO"); if (this.task.state.state === "STOPPED") this.task.recover(); this.task.transition("RUNNING"); const program = this.xyzacProgram.snapshot(); this.task.setProgram("running", program.execution_source_line ?? program.current_line); }
|
||||
return finish(this.envelope(result.status === "verified" ? "COMMAND_RESULT" : "ERROR", input, { ...result, reopened_taskfile: ["completed", "aborted"].includes(previousProgramStatus), start_line: 0, program: this.xyzacProgram.snapshot(), task: this.task.export(), wasm_motion: this.wasmMotion.read(), motion: this.wasmMotionProjection(), motion_authority: "wasm", command: input.kind, operation_id: input.operation_id ?? null }), result.status === "verified" ? "verified" : "failed");
|
||||
}
|
||||
const result = this.program.start();
|
||||
if (result.status === "verified") {
|
||||
this.livePathEpoch += 1;
|
||||
this.task.setMode("AUTO");
|
||||
if (this.task.state.state === "STOPPED") this.task.recover();
|
||||
if (this.motionAuthority === "wasm") this.wasmMotion.setPaused(false);
|
||||
@@ -2182,12 +2180,11 @@ export class SimSession {
|
||||
this.xyzacDeferredPhysicalPoseApplied = false;
|
||||
this.xyzacAppendDeferredOnActive = false;
|
||||
const result = this.resetXyzacProgramToLoaded();
|
||||
if (result.status === "verified") { this.livePathEpoch += 1; this.wasmMotion.abort(); this.wasmMotion.setPaused(false); this.task.recover(); this.task.setMode("AUTO"); this.task.setProgram("loaded", 0); }
|
||||
if (result.status === "verified") { this.wasmMotion.abort(); this.wasmMotion.setPaused(false); this.task.recover(); this.task.setMode("AUTO"); this.task.setProgram("loaded", 0); }
|
||||
return finish(this.envelope(result.status === "verified" ? "COMMAND_RESULT" : "ERROR", input, { ...result, program: this.xyzacProgram.snapshot(), task: this.task.export(), motion_authority: "wasm", command: input.kind, operation_id: input.operation_id ?? null }), result.status === "verified" ? "verified" : "failed");
|
||||
}
|
||||
const result = this.program.restart();
|
||||
if (result.status === "verified") {
|
||||
this.livePathEpoch += 1;
|
||||
if (["ESTOP", "FAULT"].includes(this.task.state.state)) return finish(this.error(input, "task_state", "program_restart_faulted"), "failed");
|
||||
if (["RUNNING", "PAUSED"].includes(this.task.state.state)) this.task.transition("STOPPED");
|
||||
if (this.task.state.state === "STOPPED") this.task.recover();
|
||||
|
||||
@@ -30,13 +30,14 @@ const loaded = send("PROGRAM_LOAD", { source, path: "live-path.ngc" });
|
||||
assert.equal(loaded.kind, "COMMAND_RESULT");
|
||||
const loadEpoch = epoch(loaded);
|
||||
const previewCount = loaded.payload.panel_snapshot.visual.toolpath.length;
|
||||
assert.ok(loadEpoch > 0 && previewCount > 0);
|
||||
assert.equal(loadEpoch, 0);
|
||||
assert.ok(previewCount > 0);
|
||||
send("POWER", { active: true });
|
||||
send("HOME", { all: true });
|
||||
|
||||
const run = send("PROGRAM_RUN");
|
||||
const runEpoch = epoch(run);
|
||||
assert.equal(runEpoch, loadEpoch + 1);
|
||||
assert.equal(runEpoch, loadEpoch);
|
||||
send("SIM_STEP", { cycles: 5, response: "motion_delta" });
|
||||
const pause = send("PROGRAM_PAUSE");
|
||||
assert.equal(epoch(pause), runEpoch);
|
||||
@@ -55,15 +56,17 @@ assert.equal(epoch(completed), runEpoch);
|
||||
assert.equal(Object.hasOwn(completed.payload.panel_snapshot.visual, "toolpath"), false);
|
||||
|
||||
const rerun = send("PROGRAM_RUN");
|
||||
assert.equal(epoch(rerun), runEpoch + 1);
|
||||
assert.equal(epoch(rerun), runEpoch);
|
||||
const abort = send("PROGRAM_ABORT");
|
||||
assert.equal(epoch(abort), runEpoch + 1);
|
||||
assert.equal(epoch(abort), runEpoch);
|
||||
|
||||
const replacement = send("PROGRAM_LOAD", { source: "G21\nG90\nG1 X1 Y1 Z1 F300\nM2\n", path: "replacement-live-path.ngc" });
|
||||
assert.equal(epoch(replacement), runEpoch + 2);
|
||||
assert.equal(epoch(replacement), runEpoch);
|
||||
assert.equal(replacement.payload.panel_snapshot.visual.toolpath.length, 1);
|
||||
const restart = send("PROGRAM_RESTART");
|
||||
assert.equal(epoch(restart), runEpoch);
|
||||
const clear = send("VISUAL_CLEAR");
|
||||
assert.equal(epoch(clear), runEpoch + 3);
|
||||
assert.equal(epoch(clear), runEpoch + 1);
|
||||
assert.equal(clear.payload.panel_snapshot.visual.toolpath.length, 1);
|
||||
assert.equal(session.previewState.segments.length, 1);
|
||||
|
||||
@@ -71,6 +74,6 @@ console.log(JSON.stringify({
|
||||
schema: "xyzac-live-path-lifecycle.v1",
|
||||
status: "verified",
|
||||
source: "axis.py:LivePlotter/clear_live_plot/task_pause/task_resume/task_stop",
|
||||
epochs: { load: loadEpoch, run: runEpoch, pause: epoch(pause), resume: epoch(resume), completed: epoch(completed), rerun: epoch(rerun), abort: epoch(abort), replacement: epoch(replacement), clear: epoch(clear) },
|
||||
epochs: { load: loadEpoch, run: runEpoch, pause: epoch(pause), resume: epoch(resume), completed: epoch(completed), rerun: epoch(rerun), abort: epoch(abort), replacement: epoch(replacement), restart: epoch(restart), clear: epoch(clear) },
|
||||
static_preview: { initial_segments: previewCount, clear_plot_segments: clear.payload.panel_snapshot.visual.toolpath.length },
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user