Advance simulation parity and 3-axis tutorial coverage

This commit is contained in:
2026-08-23 18:00:56 +08:00
parent 4a11d9692b
commit 938654b19d
107 changed files with 13537 additions and 3565 deletions

View File

@@ -20,6 +20,7 @@ import { PythonCallbacks } from "./python-callbacks.mjs";
import { createTrace, validateTrace } from "./trace-export.mjs";
import { ConfigurationBatchRuntime } from "../workspace/configuration-batch.mjs";
import { AuthoritativeRuntime } from "./authoritative-runtime.mjs";
import { axisState } from "./axis-state.mjs";
const PROTOCOL_SCHEMA = 1;
const CONTEXT_ID = "linuxcnc-2.10.0-pre0-wasm-m1-py-c1";
@@ -98,6 +99,9 @@ export class SimSession {
}
envelope(kind, input, payload, tick = this.tick) {
const statePayload = payload && typeof payload === "object" ? payload : {};
const program = statePayload.program ?? (this.program.loaded ? this.program.snapshot() : {});
const task = statePayload.task ?? this.task.export();
return {
schema_version: PROTOCOL_SCHEMA,
kind,
@@ -106,7 +110,7 @@ export class SimSession {
seq: input.seq,
...(text(input.operation_id) ? { operation_id: input.operation_id } : {}),
simulation_tick: tick,
payload,
payload: { ...statePayload, axis_state: axisState({ task, program, action: input.kind, payload: input.payload ?? {} }) },
};
}
@@ -268,7 +272,6 @@ export class SimSession {
if (event.kind === "ESTOP") replayDeviceIo.estop(event.payload?.active === true);
if (event.kind === "IO_RECOVER") replayDeviceIo.interlockReset();
if (event.kind === "SIM_STEP") replayMotion.step(event.tick);
if (event.kind === "SIM_STEP") replayAuthoritative.step(event.tick);
if (event.kind === "PROGRAM_LOAD") replayProgram.load(event.payload?.source ?? event.payload?.text ?? event.payload?.program_source, event.payload?.path ?? null);
if (event.kind === "PROGRAM_RUN") replayProgram.start();
if (event.kind === "PROGRAM_PAUSE") replayProgram.pause();
@@ -277,8 +280,16 @@ export class SimSession {
if (event.kind === "PROGRAM_RESTART") replayProgram.restart();
if (event.kind === "SIM_STEP" && replayProgram.loaded) {
if (replayProgram.status === "paused" && state.task?.program_status === "running") replayProgram.resume();
replayProgram.tick(Number.isSafeInteger(event.payload?.cycles) ? event.payload.cycles : 1);
replayAuthoritative.syncProgram(replayProgram.snapshot());
for (let replayTick = replayAuthoritative.state.tick + 1; replayTick <= event.tick; replayTick += 1) {
replayProgram.tick(1);
const synced = replayAuthoritative.syncProgram(replayProgram.snapshot());
if (synced.status === "blocked") throw new Error(synced.code);
const stepped = replayAuthoritative.step(replayTick);
if (stepped.status === "error") throw new Error(stepped.code);
}
} else if (event.kind === "SIM_STEP") {
const stepped = replayAuthoritative.step(event.tick);
if (stepped.status === "error") throw new Error(stepped.code);
}
if (event.kind === "PLC_CONFIG") replayPlc.configure(event.payload);
if (event.kind === "PLC_SET") replayPlc.setRegister(event.payload?.register, event.payload?.value);