完善 LinuxCNC 对标矩阵与 gmoccapy TRT 仿真
This commit is contained in:
@@ -71,9 +71,12 @@
|
||||
throw new Error(`executed G-code row should be light gray, got ${previousBackground}`);
|
||||
}
|
||||
}
|
||||
const listText = list.textContent;
|
||||
if (/\bpending\b|\bstopped\s+\|\s+F\b|\brunning\s+\|\s+F\b/.test(listText)) {
|
||||
throw new Error("G-code list should not render execution status text");
|
||||
const executionText = activeRow.querySelector("[data-line-execution]")?.textContent || "";
|
||||
if (
|
||||
executionText &&
|
||||
!/\b(running|done|paused|stopped|mdi|ready)\b\s+\|\s+F\s+[-.\d]+\s+\|\s+cycle\s+\d+\/\d+/.test(executionText)
|
||||
) {
|
||||
throw new Error(`G-code line execution text has unexpected format: ${executionText}`);
|
||||
}
|
||||
const rowBounds = activeRow.getBoundingClientRect();
|
||||
const listBounds = list.getBoundingClientRect();
|
||||
@@ -82,6 +85,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
function assertSidebarModeVisualState(doc, { manualActive, autoActive }) {
|
||||
const expected = [
|
||||
[doc.querySelector('[data-action="mode-manual"]'), "MANUAL", manualActive],
|
||||
[doc.querySelector('[data-action="mode-auto"]'), "AUTO", autoActive],
|
||||
];
|
||||
for (const [button, label, active] of expected) {
|
||||
if (!button) {
|
||||
throw new Error(`missing ${label} mode button`);
|
||||
}
|
||||
if (button.dataset.active !== String(active)) {
|
||||
throw new Error(`${label} mode button active flag should be ${active}, got ${button.dataset.active}`);
|
||||
}
|
||||
const style = getComputedStyle(button);
|
||||
const backgroundImage = style.backgroundImage;
|
||||
const color = style.color.replace(/\s/g, "");
|
||||
if (active) {
|
||||
if (!backgroundImage.includes("rgb(174, 233, 174)") || color !== "rgb(7,95,22)") {
|
||||
throw new Error(`${label} active mode button should render green, got ${backgroundImage} / ${color}`);
|
||||
}
|
||||
} else if (!backgroundImage.includes("rgb(221, 217, 209)") || color !== "rgb(48,48,48)") {
|
||||
throw new Error(`${label} inactive mode button should render gray, got ${backgroundImage} / ${color}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function runSmoke() {
|
||||
await new Promise((resolve, reject) => {
|
||||
frame.addEventListener("load", resolve, { once: true });
|
||||
@@ -216,6 +244,21 @@
|
||||
if (!profileSelector || profileSelector.options.length < 2) {
|
||||
throw new Error("missing five-axis profile selector");
|
||||
}
|
||||
const titlebar = doc.querySelector('[data-region="titlebar"]');
|
||||
const currentLineIndicator = titlebar?.querySelector("[data-titlebar-current-line]");
|
||||
if (!titlebar || !currentLineIndicator) {
|
||||
throw new Error("missing stable titlebar nodes");
|
||||
}
|
||||
win.webRtcp5AxisSimulation.dispatch({ type: "SET_VIEW", view: "x" });
|
||||
await wait(50);
|
||||
if (profileSelector !== doc.querySelector('[data-action="select-profile"]')) {
|
||||
throw new Error("titlebar profile selector should not be remounted on state updates");
|
||||
}
|
||||
if (currentLineIndicator !== doc.querySelector("[data-titlebar-current-line]")) {
|
||||
throw new Error("titlebar current-line indicator should not be remounted on state updates");
|
||||
}
|
||||
win.webRtcp5AxisSimulation.dispatch({ type: "RESET_VIEW" });
|
||||
await wait(50);
|
||||
profileSelector.value = "xyzbc-trt";
|
||||
profileSelector.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
await wait(500);
|
||||
@@ -273,7 +316,7 @@
|
||||
['[data-action="STOP"]', "stop"],
|
||||
['[data-action="PAUSE"]', "pause"],
|
||||
['[data-action="HOME"]', "ref_all"],
|
||||
['[data-action="toggle-flood"]', "coolant_flood_active"],
|
||||
['[data-action="toggle-flood"]', "coolant_flood_inactive"],
|
||||
['[data-action="toggle-mist"]', "coolant_mist_inactive"],
|
||||
['[data-action="view-x"]', "tool_axis_x"],
|
||||
]) {
|
||||
@@ -523,6 +566,18 @@
|
||||
}
|
||||
doc.querySelector('[data-action="mode-auto"]').click();
|
||||
await wait(50);
|
||||
const autoModeState = win.webRtcp5AxisSimulation.getState();
|
||||
if (autoModeState.machine.mode !== "auto") {
|
||||
throw new Error(`AUTO mode button did not switch task mode: ${autoModeState.machine.mode}`);
|
||||
}
|
||||
if (autoModeState.machine.powerOn !== true || autoModeState.machine.taskState !== "on") {
|
||||
throw new Error(`AUTO mode button should preserve machine power: ${JSON.stringify(autoModeState.machine)}`);
|
||||
}
|
||||
const postAutoManualButton = doc.querySelector('[data-action="mode-manual"]');
|
||||
if (postAutoManualButton?.disabled || postAutoManualButton.dataset.commandReady !== "true") {
|
||||
throw new Error("MANUAL mode button should remain enabled after switching to AUTO");
|
||||
}
|
||||
assertSidebarModeVisualState(doc, { manualActive: false, autoActive: true });
|
||||
if (!doc.querySelector('[data-linuxcnc-task-policy="gates"]')?.textContent.includes("auto")) {
|
||||
throw new Error("LinuxCNC task policy did not expose auto run gate");
|
||||
}
|
||||
@@ -779,6 +834,10 @@
|
||||
throw new Error("RUN did not highlight a LinuxCNC task/HAL motion line");
|
||||
}
|
||||
assertActiveGcodeRowVisible(doc);
|
||||
const runExecutionText = doc.querySelector(".gcode-row.active [data-line-execution]")?.textContent || "";
|
||||
if (!runExecutionText.includes("F ") || !runExecutionText.includes("cycle") || !runExecutionText.includes("linuxcnc-task-motion-hal-wasm")) {
|
||||
throw new Error(`RUN did not render current G-code line execution details: ${runExecutionText}`);
|
||||
}
|
||||
const stopLineBefore = win.webRtcp5AxisSimulation.getState().activeLine;
|
||||
doc.querySelector('[data-action="STOP"]').click();
|
||||
await wait(150);
|
||||
@@ -928,6 +987,7 @@
|
||||
}
|
||||
doc.querySelector('[data-action="mode-manual"]').click();
|
||||
await wait(50);
|
||||
assertSidebarModeVisualState(doc, { manualActive: true, autoActive: false });
|
||||
doc.querySelector('[data-action="mode-jog"]').click();
|
||||
await wait(50);
|
||||
const xBeforeJog = win.webRtcp5AxisSimulation.getState().axisPose.x;
|
||||
@@ -1248,7 +1308,7 @@
|
||||
doc.querySelector('[data-action="toggle-mist"]').click();
|
||||
await wait(50);
|
||||
const coolantState = win.webRtcp5AxisSimulation.getState().coolant;
|
||||
if (coolantState.flood !== false || coolantState.mist !== true) {
|
||||
if (coolantState.flood !== true || coolantState.mist !== true) {
|
||||
throw new Error("coolant buttons did not update state");
|
||||
}
|
||||
doc.querySelector('[data-action="view-x"]').click();
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
|
||||
import { createMemorySessionStorage } from "../../app/src/runtime/five-axis-session.js";
|
||||
import { createLinuxCncInterpreterRuntime } from "../../app/src/runtime/linuxcnc-interpreter-runtime.js";
|
||||
import { parseLinuxCncIni } from "../../app/src/runtime/linuxcnc-ini-runtime.js";
|
||||
import { getFiveAxisProfile } from "../../app/src/profiles/index.js";
|
||||
import { createSimulationStore } from "../../app/src/state/store.js";
|
||||
|
||||
function sidebarEntry(state, id) {
|
||||
const entry = state.rightSidebarEntrances.find((candidate) => candidate.id === id);
|
||||
assert.ok(entry, `missing right sidebar entry ${id}`);
|
||||
return entry;
|
||||
}
|
||||
|
||||
async function waitForValidatedProgram(store) {
|
||||
for (let attempt = 0; attempt < 30; attempt += 1) {
|
||||
const state = store.getState();
|
||||
if (!state.interpreterExecutionPending && state.programValidation?.ready) {
|
||||
return state;
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
}
|
||||
return store.getState();
|
||||
}
|
||||
|
||||
async function loadIniConfigFromVendoredSource(profile) {
|
||||
const text = await readFile(
|
||||
new URL(`../../../wasm-port/vendor/linuxcnc/${profile.iniPath}`, import.meta.url),
|
||||
"utf8",
|
||||
);
|
||||
return parseLinuxCncIni(text, {
|
||||
path: profile.iniPath,
|
||||
profileId: profile.id,
|
||||
});
|
||||
}
|
||||
|
||||
const store = createSimulationStore();
|
||||
let state = store.getState();
|
||||
assert.equal(state.rightSidebarEntrances.length, 9);
|
||||
assert.deepEqual(
|
||||
state.rightSidebarEntrances.map((entry) => entry.label),
|
||||
["E-STOP", "POWER", "RESET", "AUTO", "MANUAL", "JOG", "MDI", "IDENTITY", "TCP"],
|
||||
);
|
||||
assert.equal(sidebarEntry(state, "power").allowed, true);
|
||||
assert.equal(sidebarEntry(state, "auto").allowed, false);
|
||||
assert.equal(sidebarEntry(state, "manual").allowed, false);
|
||||
assert.equal(sidebarEntry(state, "jog").allowed, false);
|
||||
assert.equal(sidebarEntry(state, "mdi").allowed, false);
|
||||
assert.equal(sidebarEntry(state, "identity").active, true);
|
||||
assert.equal(sidebarEntry(state, "identity").status, "active-blocked");
|
||||
assert.equal(sidebarEntry(state, "tcp").allowed, false);
|
||||
|
||||
store.dispatch({ type: "ESTOP" });
|
||||
state = store.getState();
|
||||
assert.equal(sidebarEntry(state, "estop").status, "emergency");
|
||||
assert.equal(sidebarEntry(state, "power").allowed, false);
|
||||
assert.equal(sidebarEntry(state, "power").operatorMessage, "power on blocked: reset estop first");
|
||||
|
||||
store.dispatch({ type: "RESET" });
|
||||
store.dispatch({ type: "TOGGLE_POWER" });
|
||||
state = store.getState();
|
||||
assert.equal(state.machine.taskState, "on");
|
||||
assert.equal(sidebarEntry(state, "power").active, true);
|
||||
assert.equal(sidebarEntry(state, "manual").active, true);
|
||||
assert.equal(sidebarEntry(state, "jog").active, false);
|
||||
assert.equal(sidebarEntry(state, "auto").allowed, false);
|
||||
assert.equal(sidebarEntry(state, "auto").operatorMessage, "mode blocked: home machine before AUTO");
|
||||
|
||||
store.dispatch({ type: "SET_MODE", mode: "jog" });
|
||||
state = store.getState();
|
||||
assert.equal(state.machine.mode, "manual");
|
||||
assert.equal(state.machine.manualPanel, "jog");
|
||||
assert.equal(sidebarEntry(state, "manual").active, false);
|
||||
assert.equal(sidebarEntry(state, "jog").active, true);
|
||||
|
||||
store.dispatch({ type: "HOME" });
|
||||
store.dispatch({ type: "SET_MODE", mode: "auto" });
|
||||
state = store.getState();
|
||||
assert.equal(sidebarEntry(state, "auto").active, true);
|
||||
assert.equal(sidebarEntry(state, "mdi").allowed, true);
|
||||
assert.equal(sidebarEntry(state, "tcp").allowed, true);
|
||||
|
||||
store.dispatch({ type: "SET_KINS_TYPE", kinsType: "tcp-xyzac" });
|
||||
state = store.getState();
|
||||
assert.equal(state.kinsType, "tcp-xyzac");
|
||||
assert.equal(state.rtcpState, "on");
|
||||
assert.equal(sidebarEntry(state, "tcp").active, true);
|
||||
store.dispatch({ type: "SET_KINS_TYPE", kinsType: "identity" });
|
||||
assert.equal(store.getState().kinsType, "identity");
|
||||
|
||||
store.dispatch({
|
||||
type: "LOAD_PROGRAM",
|
||||
filename: "sidebar-running-gate.ngc",
|
||||
content: [
|
||||
"G0 X0 Y0 Z0",
|
||||
"G1 X1 F100",
|
||||
"G1 X2",
|
||||
"G1 X3",
|
||||
"G1 X4",
|
||||
"G1 X5",
|
||||
"G1 X6",
|
||||
"G1 X7",
|
||||
"G1 X8",
|
||||
"G1 X9",
|
||||
"M2",
|
||||
].join("\n"),
|
||||
});
|
||||
store.dispatch({ type: "RUN" });
|
||||
state = store.getState();
|
||||
assert.equal(state.runState, "running");
|
||||
assert.equal(sidebarEntry(state, "manual").allowed, false);
|
||||
assert.equal(sidebarEntry(state, "tcp").allowed, false);
|
||||
assert.equal(sidebarEntry(state, "tcp").operatorMessage, "kinematics blocked: interpreter must be idle");
|
||||
|
||||
store.dispatch({ type: "STOP" });
|
||||
store.dispatch({ type: "SET_MODE", mode: "manual" });
|
||||
|
||||
const profile = getFiveAxisProfile("xyzac-trt");
|
||||
const iniConfig = await loadIniConfigFromVendoredSource(profile);
|
||||
store.dispatch({ type: "ATTACH_INI_CONFIG", profileId: profile.id, iniConfig });
|
||||
store.dispatch({
|
||||
type: "ATTACH_INTERPRETER_RUNTIME",
|
||||
runtime: await createLinuxCncInterpreterRuntime(),
|
||||
});
|
||||
await store.stageMachineFiles({ storage: createMemorySessionStorage() });
|
||||
state = store.getState();
|
||||
assert.equal(state.machineProject.profileId, "xyzac-trt");
|
||||
assert.equal(state.machineProject.projectRoot, "web-rtcp-5axis-sim-plan/machines/xyzac-trt");
|
||||
assert.equal(state.machineProject.ini.filename, "xyzac-trt.ini");
|
||||
assert.equal(state.machineProject.ini.sourceMatchesProfile, true);
|
||||
assert.equal(state.machineProject.ini.textMatchesLoadedIni, true);
|
||||
assert.equal(state.machineProject.configFileCount > 0, true);
|
||||
assert.equal(state.machineProject.gcodeFileCount, 16);
|
||||
assert.equal(state.machineProject.gcodeFiles.some((file) => file.filename === "impeller-7bl-xyzac.ngc"), true);
|
||||
|
||||
store.dispatch({
|
||||
type: "LOAD_LINUXCNC_GCODE_SOURCE",
|
||||
sourceRel: "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
|
||||
});
|
||||
state = await waitForValidatedProgram(store);
|
||||
assert.equal(state.programValidation.ready, true);
|
||||
assert.equal(state.programValidation.sourceGuard, "linuxcnc_vendored_5axis_gcode_source_file");
|
||||
assert.equal(state.programValidation.previewSource, "linuxcnc_interpreter_canonical_motion");
|
||||
assert.equal(state.programValidation.motionEventCount > 0, true);
|
||||
assert.equal(state.programValidation.plannerSampleCount > 0, true);
|
||||
assert.equal(state.programValidation.realtimeAxisValues.x, state.axisPose.x);
|
||||
assert.equal(state.machineProject.selectedProgram.filename, "impeller-7bl-xyzac.ngc");
|
||||
|
||||
const xyzbcStore = createSimulationStore();
|
||||
xyzbcStore.dispatch({ type: "SET_PROFILE", profileId: "xyzbc-trt" });
|
||||
const xyzbcProfile = getFiveAxisProfile("xyzbc-trt");
|
||||
xyzbcStore.dispatch({
|
||||
type: "ATTACH_INI_CONFIG",
|
||||
profileId: xyzbcProfile.id,
|
||||
iniConfig: await loadIniConfigFromVendoredSource(xyzbcProfile),
|
||||
});
|
||||
await xyzbcStore.stageMachineFiles({ storage: createMemorySessionStorage() });
|
||||
const xyzbcState = xyzbcStore.getState();
|
||||
assert.equal(xyzbcState.machineProject.profileId, "xyzbc-trt");
|
||||
assert.equal(xyzbcState.machineProject.ini.filename, "xyzbc-trt.ini");
|
||||
assert.equal(xyzbcState.machineProject.gcodeFiles.some((file) => file.filename === "boat-xyzbc.ngc"), true);
|
||||
|
||||
console.log("gmoccapy_trt_project_sidebar_smoke=ok");
|
||||
@@ -0,0 +1,131 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
|
||||
import {
|
||||
LINUXCNC_PARITY_ITEMS,
|
||||
RIGHT_SIDEBAR_PARITY_ENTRIES,
|
||||
SWITCHKINS_PARITY_CODES,
|
||||
} from "../../app/src/runtime/linuxcnc-parity-matrix.js";
|
||||
import { createMemorySessionStorage } from "../../app/src/runtime/five-axis-session.js";
|
||||
import { createLinuxCncInterpreterRuntime } from "../../app/src/runtime/linuxcnc-interpreter-runtime.js";
|
||||
import { parseLinuxCncIni } from "../../app/src/runtime/linuxcnc-ini-runtime.js";
|
||||
import { getFiveAxisProfile } from "../../app/src/profiles/index.js";
|
||||
import { createSimulationStore } from "../../app/src/state/store.js";
|
||||
|
||||
function item(matrix, id) {
|
||||
const found = matrix.items.find((entry) => entry.id === id);
|
||||
assert.ok(found, `missing parity matrix item ${id}`);
|
||||
return found;
|
||||
}
|
||||
|
||||
async function waitForValidatedProgram(store) {
|
||||
for (let attempt = 0; attempt < 30; attempt += 1) {
|
||||
const state = store.getState();
|
||||
if (!state.interpreterExecutionPending && state.programValidation?.ready) {
|
||||
return state;
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
}
|
||||
return store.getState();
|
||||
}
|
||||
|
||||
async function loadIniConfigFromVendoredSource(profile) {
|
||||
const text = await readFile(
|
||||
new URL(`../../../wasm-port/vendor/linuxcnc/${profile.iniPath}`, import.meta.url),
|
||||
"utf8",
|
||||
);
|
||||
return parseLinuxCncIni(text, {
|
||||
path: profile.iniPath,
|
||||
profileId: profile.id,
|
||||
});
|
||||
}
|
||||
|
||||
assert.equal(LINUXCNC_PARITY_ITEMS.length >= 11, true);
|
||||
assert.deepEqual(RIGHT_SIDEBAR_PARITY_ENTRIES, [
|
||||
"E-STOP",
|
||||
"POWER",
|
||||
"RESET",
|
||||
"AUTO",
|
||||
"MANUAL",
|
||||
"JOG",
|
||||
"MDI",
|
||||
"IDENTITY",
|
||||
"TCP",
|
||||
]);
|
||||
assert.deepEqual(SWITCHKINS_PARITY_CODES, ["M428", "M429", "M430"]);
|
||||
|
||||
const store = createSimulationStore();
|
||||
let state = store.getState();
|
||||
let matrix = state.linuxCncParityMatrix;
|
||||
|
||||
assert.equal(matrix.apiName, "web-rtcp-5axis-linuxcnc-parity-matrix");
|
||||
assert.equal(matrix.profileId, "xyzac-trt");
|
||||
assert.equal(matrix.status, "implemented");
|
||||
assert.equal(matrix.implementedCount, matrix.itemCount);
|
||||
assert.equal(matrix.rightSidebarComplete, true);
|
||||
assert.equal(matrix.switchkinsComplete, true);
|
||||
assert.deepEqual(matrix.actualRightSidebarEntries, RIGHT_SIDEBAR_PARITY_ENTRIES);
|
||||
assert.equal(matrix.requiredSwitchkinsCodes.every((code) => matrix.activeSwitchkinsCodes.includes(code)), true);
|
||||
assert.equal(matrix.linuxCncPrograms.some((path) => path.endsWith("impeller-7bl-xyzac.ngc")), true);
|
||||
assert.equal(matrix.linuxCncPrograms.some((path) => path.endsWith("boat-xyzbc.ngc")), true);
|
||||
assert.equal(matrix.linuxCncFunctions.includes("E-STOP/POWER/RESET task-state entry"), true);
|
||||
assert.equal(matrix.linuxCncFunctions.includes("M428 TCP"), true);
|
||||
assert.equal(matrix.linuxCncFunctions.includes("M429 identity"), true);
|
||||
assert.equal(matrix.linuxCncFunctions.includes("M430 userk"), true);
|
||||
|
||||
assert.equal(item(matrix, "xyzac-trt-axis-vismach-config").active, true);
|
||||
assert.equal(item(matrix, "xyzac-trt-axis-vismach-config").sourceMapped, true);
|
||||
assert.equal(item(matrix, "xyzac-trt-axis-vismach-config").linuxCncPaths.some((path) => path.endsWith("xyzac-trt.ini")), true);
|
||||
assert.equal(item(matrix, "xyzbc-trt-axis-vismach-config").implemented, true);
|
||||
assert.equal(item(matrix, "xyzbc-trt-axis-vismach-config").active, false);
|
||||
assert.equal(item(matrix, "gmoccapy-trt-config").linuxCncPaths.some((path) => path.includes("gmoccapy/non_trivial_kinematics/table-rotary-tilting/xyzac-trt.ini")), true);
|
||||
assert.equal(item(matrix, "gmoccapy-trt-config").functions.includes("DISPLAY gmoccapy"), true);
|
||||
assert.equal(item(matrix, "gmoccapy-native-operator-ui").active, true);
|
||||
assert.equal(item(matrix, "right-sidebar-task-interlocks").active, true);
|
||||
assert.equal(item(matrix, "vismach-machine-preview").active, true);
|
||||
assert.equal(item(matrix, "source-derived-kinematics-switchkins").active, true);
|
||||
assert.equal(item(matrix, "linuxcnc-interpreter-program-validation").active, false);
|
||||
assert.equal(item(matrix, "machine-project-directory").active, false);
|
||||
assert.equal(item(matrix, "task-hal-status-loop").implemented, true);
|
||||
assert.equal(item(matrix, "gmoccapy-postgui-tool-spindle").active, true);
|
||||
|
||||
store.dispatch({ type: "SET_PROFILE", profileId: "xyzbc-trt" });
|
||||
state = store.getState();
|
||||
matrix = state.linuxCncParityMatrix;
|
||||
assert.equal(matrix.profileId, "xyzbc-trt");
|
||||
assert.equal(item(matrix, "xyzac-trt-axis-vismach-config").active, false);
|
||||
assert.equal(item(matrix, "xyzbc-trt-axis-vismach-config").active, true);
|
||||
assert.equal(item(matrix, "source-derived-kinematics-switchkins").evidence.activeSwitchkinsCodes.includes("M428"), true);
|
||||
|
||||
store.dispatch({ type: "SET_PROFILE", profileId: "xyzac-trt" });
|
||||
const profile = getFiveAxisProfile("xyzac-trt");
|
||||
store.dispatch({
|
||||
type: "ATTACH_INI_CONFIG",
|
||||
profileId: profile.id,
|
||||
iniConfig: await loadIniConfigFromVendoredSource(profile),
|
||||
});
|
||||
store.dispatch({
|
||||
type: "ATTACH_INTERPRETER_RUNTIME",
|
||||
runtime: await createLinuxCncInterpreterRuntime(),
|
||||
});
|
||||
await store.stageMachineFiles({ storage: createMemorySessionStorage() });
|
||||
state = store.getState();
|
||||
matrix = state.linuxCncParityMatrix;
|
||||
assert.equal(item(matrix, "machine-project-directory").active, true);
|
||||
assert.equal(item(matrix, "machine-project-directory").evidence.iniSourceMatchesProfile, true);
|
||||
assert.equal(item(matrix, "machine-project-directory").evidence.gcodeFileCount >= 8, true);
|
||||
|
||||
store.dispatch({
|
||||
type: "LOAD_LINUXCNC_GCODE_SOURCE",
|
||||
sourceRel: "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
|
||||
});
|
||||
state = await waitForValidatedProgram(store);
|
||||
matrix = state.linuxCncParityMatrix;
|
||||
assert.equal(state.programValidation.ready, true);
|
||||
assert.equal(item(matrix, "linuxcnc-interpreter-program-validation").active, true);
|
||||
assert.equal(item(matrix, "linuxcnc-interpreter-program-validation").evidence.sourceGuard, "linuxcnc_vendored_5axis_gcode_source_file");
|
||||
assert.equal(item(matrix, "linuxcnc-interpreter-program-validation").evidence.motionEventCount > 0, true);
|
||||
assert.equal(item(matrix, "linuxcnc-interpreter-program-validation").evidence.plannerSampleCount > 0, true);
|
||||
assert.equal(matrix.activeCount >= 9, true);
|
||||
|
||||
console.log("linuxcnc_parity_matrix_smoke=ok");
|
||||
@@ -127,6 +127,13 @@ assert.equal(kinematicsState.rtcpFrame.sourceMode, "source-derived-kinematics-wa
|
||||
assert.equal(kinematicsState.rtcpFrame.semanticBoundary, "linuxcnc_kinematics_wasm_c_abi");
|
||||
assert.equal(kinematicsState.rtcpFrame.readiness.linuxCncKinematicsReady, true);
|
||||
|
||||
kinematicsStore.dispatch({ type: "SET_RTCP", enabled: true });
|
||||
kinematicsState = kinematicsStore.getState();
|
||||
assert.equal(kinematicsState.rtcpState, "off");
|
||||
assert.equal(kinematicsState.operatorMessage, "kinematics blocked: machine must be on");
|
||||
|
||||
kinematicsStore.dispatch({ type: "TOGGLE_POWER" });
|
||||
kinematicsStore.dispatch({ type: "HOME" });
|
||||
kinematicsStore.dispatch({ type: "SET_RTCP", enabled: true });
|
||||
kinematicsState = kinematicsStore.getState();
|
||||
assert.equal(kinematicsState.rtcpState, "on");
|
||||
@@ -134,8 +141,6 @@ assert.equal(kinematicsState.rtcpFrame.sourceMode, "source-derived-kinematics-wa
|
||||
assert.equal(kinematicsState.lastKinematicsResult.moduleId, "xyzac-trt");
|
||||
assert.equal(kinematicsState.dro.tcpX, kinematicsState.rtcpFrame.tcpPose.x);
|
||||
|
||||
kinematicsStore.dispatch({ type: "TOGGLE_POWER" });
|
||||
kinematicsStore.dispatch({ type: "HOME" });
|
||||
kinematicsStore.dispatch({ type: "SET_MODE", mode: "auto" });
|
||||
kinematicsStore.dispatch({ type: "STEP" });
|
||||
kinematicsState = kinematicsStore.getState();
|
||||
@@ -270,6 +275,8 @@ assert.equal(store.getState().machineProfile, "xyzbc-trt");
|
||||
assert.equal(store.getState().profile.traj.coordinates, "XYZBC");
|
||||
const xyzbcRuntime = await createLinuxCncKinematicsRuntime({ moduleId: "xyzbc-trt" });
|
||||
store.dispatch({ type: "ATTACH_KINEMATICS_RUNTIME", runtime: xyzbcRuntime });
|
||||
store.dispatch({ type: "TOGGLE_POWER" });
|
||||
store.dispatch({ type: "HOME" });
|
||||
store.dispatch({ type: "SET_RTCP", enabled: true });
|
||||
state = store.getState();
|
||||
assert.equal(state.kinsType, "tcp-xyzbc");
|
||||
@@ -277,6 +284,7 @@ assert.equal(state.rtcpFrame.kinematicsModuleId, "xyzbc-trt");
|
||||
assert.equal(state.rtcpFrame.jointPose[3].axis, "B");
|
||||
|
||||
store.dispatch({ type: "SET_PROFILE", profileId: "xyzac-trt" });
|
||||
store.dispatch({ type: "RESET" });
|
||||
store.dispatch({ type: "RUN" });
|
||||
assert.equal(store.getState().activeLine, 501);
|
||||
assert.equal(store.getState().operatorMessage, "run blocked: machine must be on");
|
||||
|
||||
Reference in New Issue
Block a user