Files
cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/tests/node/verify_linuxcnc_interpreter_runtime.mjs
2026-07-02 08:01:34 -04:00

122 lines
5.5 KiB
JavaScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { createLinuxCncInterpreterRuntime } from "../../app/src/runtime/linuxcnc-interpreter-runtime.js";
const runtime = await createLinuxCncInterpreterRuntime();
const readiness = runtime.readiness();
assert.equal(runtime.apiName, "web-rtcp-5axis-linuxcnc-interpreter-runtime");
assert.equal(runtime.loaded, true);
assert.equal(runtime.sourceMode, "linuxcnc-interpreter-wasm");
assert.equal(runtime.semanticBoundary, "linuxcnc_interpreter_wasm_canonical_events");
assert.equal(readiness.loaded, true);
assert.equal(readiness.runProgramReady, true);
assert.equal(readiness.remapRuntimeReady, false);
assert.equal(readiness.plannerRuntimeReady, true);
assert.equal(readiness.plannerSemanticBoundary, "linuxcnc_tp_queue_runtime_timing_from_canonical_motion");
const programText = [
"G90 G17",
"G0 X0 Y0 Z0",
"G1 X10 Y2 F100",
"G1 X12 Y4 A5 C7",
"M2",
].join("\n");
const execution = runtime.runProgram(programText);
assert.equal(execution.apiName, "web-rtcp-5axis-linuxcnc-interpreter-program-execution");
assert.equal(execution.sourceMode, "linuxcnc-interpreter-wasm");
assert.equal(execution.semanticBoundary, "linuxcnc_interpreter_wasm_canonical_events");
assert.equal(execution.summary.ready, true);
assert.equal(execution.summary.motionEventCount >= 3, true);
assert.equal(execution.summary.canonicalEventCount > execution.summary.motionEventCount, true);
assert.equal(execution.summary.motionTypes.includes("STRAIGHT_TRAVERSE"), true);
assert.equal(execution.summary.motionTypes.includes("STRAIGHT_FEED"), true);
assert.equal(execution.summary.finalAxes.x, 12);
assert.equal(execution.summary.finalAxes.y, 4);
assert.equal(execution.summary.finalAxes.a, 5);
assert.equal(execution.summary.finalAxes.c, 7);
assert.equal(execution.motion[2].feedRate, 100);
assert.equal(execution.summary.remapRuntimeReady, false);
assert.equal(execution.summary.plannerRuntimeReady, true);
assert.equal(execution.plannerTiming.semanticBoundary, "linuxcnc_tp_queue_runtime_timing_from_canonical_motion");
assert.equal(execution.plannerTiming.totalSeconds > 0, true);
assert.equal(execution.plannerTiming.motionCount, execution.motion.length);
assert.equal(execution.summary.fullLinuxCncProgramExecutionReady, false);
const g18ArcProgramText = [
"G90 G18",
"G0 X1 Z0 Y0",
"G3 X0 Z1 I-1 K0 Y2 F80",
"M2",
].join("\n");
const g18ArcExecution = runtime.runProgram(g18ArcProgramText);
const g18ArcMotion = g18ArcExecution.motion[1];
assert.equal(g18ArcExecution.summary.ready, true);
assert.equal(g18ArcExecution.summary.motionEventCount, 2);
assert.equal(g18ArcExecution.summary.motionTypes.includes("ARC_FEED"), true);
assert.equal(g18ArcExecution.summary.finalAxes.x, 0);
assert.equal(g18ArcExecution.summary.finalAxes.y, 2);
assert.equal(g18ArcExecution.summary.finalAxes.z, 1);
assert.equal(g18ArcMotion.type, "ARC_FEED");
assert.equal(g18ArcMotion.axes.arc.plane, 180);
assert.equal(g18ArcMotion.axes.arc.firstAxis, "z");
assert.equal(g18ArcMotion.axes.arc.secondAxis, "x");
assert.equal(g18ArcMotion.axes.arc.thirdAxis, "y");
assert.equal(g18ArcMotion.axes.z, 1);
assert.equal(g18ArcMotion.axes.x, 0);
assert.equal(g18ArcMotion.axes.y, 2);
assert.equal(g18ArcMotion.feedRate, 80);
assert.equal(g18ArcExecution.summary.plannerRuntimeReady, true);
const switchkinsProgramText = [
"G90 G17",
"M428",
"G0 X0 Y0 Z0 A0 C0",
"G1 X10 Y2 Z-1 A15 C30 F120",
"M429",
"G1 X0 Y0 Z0 A0 C0 F120",
"M2",
].join("\n");
const switchkinsExecution = runtime.runProgram(switchkinsProgramText);
assert.equal(switchkinsExecution.summary.ready, true);
assert.equal(switchkinsExecution.summary.motionEventCount, 3);
assert.equal(switchkinsExecution.summary.switchkinsEventCount, 2);
assert.deepEqual(switchkinsExecution.summary.switchkinsCodes, ["M428", "M429"]);
assert.equal(
switchkinsExecution.summary.switchkinsRemapBoundary,
"linuxcnc_switchkins_remap_mcode_preserved_web_runtime_applied",
);
assert.equal(switchkinsExecution.switchkinsEvents[0].switchkinsType, 1);
assert.equal(switchkinsExecution.switchkinsEvents[1].switchkinsType, 0);
assert.equal(switchkinsExecution.motion[0].kinsType, "tcp");
assert.equal(switchkinsExecution.motion[1].axes.a, 15);
assert.equal(switchkinsExecution.motion[1].axes.c, 30);
assert.equal(switchkinsExecution.motion[1].switchkinsCode, "M428");
assert.equal(switchkinsExecution.motion[2].kinsType, "identity");
assert.equal(switchkinsExecution.motion[2].switchkinsCode, "M429");
assert.equal(switchkinsExecution.summary.remapRuntimeReady, false);
assert.equal(switchkinsExecution.summary.plannerRuntimeReady, true);
assert.equal(switchkinsExecution.plannerTiming.totalSeconds > 0, true);
assert.equal(switchkinsExecution.summary.fullLinuxCncProgramExecutionReady, false);
const gmoccapyImpellerProgram = readFileSync(fileURLToPath(new URL(
"../../../linuxcnc/configs/sim/gmoccapy/non_trivial_kinematics/table-rotary-tilting/examples/impeller-7bl-xyzac.ngc",
import.meta.url,
)), "utf8");
const gmoccapyImpellerExecution = runtime.runProgram(gmoccapyImpellerProgram);
const firstG93FeedMotion = gmoccapyImpellerExecution.motion.find((event) => event.type === "STRAIGHT_FEED");
assert.equal(gmoccapyImpellerExecution.summary.ready, true);
assert.equal(gmoccapyImpellerExecution.motion[0].feedMode, "inverse-time");
assert.equal(firstG93FeedMotion.line, 9);
assert.equal(Math.abs(firstG93FeedMotion.feedRate - 635.745) < 0.001, true);
assert.notEqual(firstG93FeedMotion.feedRate, 318);
console.log("linuxcnc_interpreter_runtime_smoke=ok");