Files
cnc_wams/web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_xyzab_profile.mjs

175 lines
10 KiB
JavaScript

import assert from "node:assert/strict";
import { getFiveAxisProfile, fiveAxisProfiles } from "../../app/src/profiles/index.js";
import { buildRtcpFrame } from "../../app/src/runtime/rtcp-frame.js";
import { createLinuxCncBoundaryAdapter, createLinuxCncBoundaryReadiness } from "../../app/src/runtime/linuxcnc-boundary-adapter.js";
import { createProfileSourceReferenceSummary } from "../../app/src/profiles/source-reference-map.js";
import { createSimulationStore, validateRunPreconditions } from "../../app/src/state/store.js";
const profile = getFiveAxisProfile("gmoccapy-xyzab");
assert.equal(profile.id, "gmoccapy-xyzab");
assert.equal(profile.title, "gmoccapy XYZAB trivkins reference");
assert.equal(profile.iniPath, "linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.ini");
assert.deepEqual(profile.coordinates, ["X", "Y", "Z", "A", "B"]);
assert.equal(profile.traj.coordinates, "XYZAB");
assert.equal(profile.joints.length, 5);
assert.equal(profile.jointConfig.length, 5);
assert.equal(profile.kinematics, "trivkins coordinates=xyzab");
assert.equal(profile.kinematicsModuleId, "gmoccapy-xyzab-trivkins-reference");
assert.equal(profile.tcpCapable, false);
assert.equal(profile.rtcpProof, false);
assert.equal(profile.linuxCncKinematicsReady, false);
assert.equal(profile.promotionAllowed, false);
assert.equal(profile.semanticBoundary, "gmoccapy_xyzab_trivkins_reference_only_not_rtcp_proof");
assert.equal(profile.homing.noForceHoming, false);
assert.equal(profile.homing.noForceHomingIniValue, 0);
assert.equal(profile.hal.postguiRequiresHalcompReady, true);
assert.deepEqual(profile.hal.halFiles, ["core_sim_XYZAB.hal", "spindle_sim.hal", "simulated_home.hal"]);
assert.deepEqual(profile.hal.postguiHalFiles, ["gmoccapy_postgui.hal"]);
assert.equal(profile.nativeRuntime.task, "milltask");
assert.equal(profile.nativeRuntime.emcmot, "motmod");
assert.equal(profile.nativeRuntime.halui, "halui");
assert.equal(profile.nativeRuntime.displayCycleTimeMs, 100);
assert.equal(profile.nativeRuntime.servoPeriodNs, 1000000);
assert.equal(profile.axisLimits.X.max, 600);
assert.equal(profile.axisLimits.Y.max, 400);
assert.equal(profile.axisLimits.Z.min, -400);
assert.equal(profile.axisLimits.B.maxVelocity, 90);
assert.equal(profile.jointConfig[4].axis, "B");
assert.equal(profile.jointConfig[4].homeOffset, 45);
assert.equal(profile.hal.halcmd.feedbackNets.length, 5);
assert.equal(profile.hal.halcmd.offsetNets.some((net) => net.target === "gmoccapy.tooloffset-z"), true);
assert.equal(profile.hal.halcmd.simulationLoops.some((net) => net.signal === "tool-change-loop"), true);
assert.equal(profile.hal.halcmd.toolChange.strategy, "iocontrol-loopback");
assert.equal(profile.hal.halcmd.toolChange.manualGmoccapyPinsConnected, false);
assert.deepEqual(profile.hal.halcmd.toolChange.postguiUnlinks, [
"iocontrol.0.tool-change",
"iocontrol.0.tool-changed",
"iocontrol.0.tool-prep-number",
]);
assert.equal(profile.hal.halcmd.toolChange.commentedManualGuiNets.length, 3);
assert.equal(profile.hal.halcmd.toolChange.activeLoop.signal, "tool-change-loop");
assert.equal(profile.halPins.includes("gmoccapy.program.current-line"), true);
assert.equal(profile.halPins.includes("gmoccapy.spindle_at_speed_led"), true);
assert.equal(profile.halPins.includes("gmoccapy.jog.axis.jog-x-plus"), true);
assert.equal(profile.halPins.includes("gmoccapy.jog.axis.jog-y-minus"), true);
assert.equal(profile.halPins.includes("gmoccapy.jog.axis.jog-b-minus"), true);
assert.equal(profile.halPins.includes("gmoccapy.jog.jog-inc-0"), true);
assert.equal(profile.halPins.includes("gmoccapy.jog.jog-inc-5"), true);
assert.equal(profile.halPins.includes("gmoccapy.jog.jog-increment"), true);
assert.equal(profile.halPins.includes("gmoccapy.jog.turtle-jog"), true);
assert.equal(profile.halPins.includes("gmoccapy.ignore-limits"), true);
assert.equal(profile.halPins.includes("gmoccapy.optional-stop"), true);
assert.equal(profile.halPins.includes("gmoccapy.blockdelete"), true);
assert.equal(profile.halPins.includes("gmoccapy.unlock-settings"), true);
assert.equal(profile.halPins.includes("gmoccapy.feed.feed-override.count-enable"), true);
assert.equal(profile.halPins.includes("gmoccapy.feed.reset-feed-override"), true);
assert.equal(profile.halPins.includes("gmoccapy.spindle.reset-spindle-override"), true);
assert.equal(profile.halPins.includes("gmoccapy.jog.jog-velocity.direct-value"), true);
assert.equal(profile.halPins.includes("gmoccapy.delete-message"), true);
assert.equal(profile.halPins.includes("gmoccapy.warning-confirm"), true);
assert.equal(profile.halPins.includes("gmoccapy.probeheight"), true);
assert.equal(profile.halPins.includes("gmoccapy.blockheight"), true);
assert.equal(profile.halPins.includes("gmoccapy.toolmeasurement"), true);
assert.equal(profile.halPins.includes("gmoccapy.searchvel"), true);
assert.equal(profile.halPins.includes("gmoccapy.probevel"), true);
assert.equal(profile.halPins.includes("gmoccapy.toolchange-confirm"), true);
assert.equal(profile.toolsensor.configured, false);
assert.equal(profile.toolsensor.useToolMeasurementPref, false);
assert.equal(profile.toolsensor.blockHeightPref, 0);
assert.equal(profile.toolsensor.reason.includes("no [TOOLSENSOR]"), true);
assert.equal(profile.userMessages.configured, false);
assert.equal(profile.userMessages.count, 0);
assert.equal(profile.userMessages.reason.includes("no [DISPLAY] MESSAGE_*"), true);
assert.equal(profile.nativePages.filePage.configured, true);
assert.equal(profile.nativePages.filePage.programPrefix, "../../nc_files/");
assert.equal(profile.nativePages.filePage.webImplementation, "partial");
assert.equal(profile.nativePages.macroPage.configured, true);
assert.equal(profile.nativePages.macroPage.count, 5);
assert.equal(profile.nativePages.macroPage.macros.find((macro) => macro.name === "increment").args.length, 2);
assert.equal(profile.nativePages.macroPage.macros.find((macro) => macro.name === "go_to_position").command, "O<go_to_position> call [X-pos] [Y-pos] [Z-pos]");
assert.equal(profile.nativePages.toolEditor.configured, true);
assert.equal(profile.nativePages.toolEditor.writebackEnabled, false);
assert.equal(profile.nativePages.toolEditor.toolCount, 17);
assert.equal(profile.nativePages.implementationMatrixBoundary.includes("diagnostic-only"), true);
assert.equal(profile.toolTable.toolCount, 17);
assert.equal(profile.macros.includes("go_to_position X-pos Y-pos Z-pos"), true);
assert.equal(profile.panelSchema.id, "gmoccapy-xyzab-hal-component");
assert.equal(profile.panelSchema.boundary, "gmoccapy_hal_component_reference_only");
assert.equal(profile.panelSchema.groups.length, 2);
const taskModeControls = profile.panelSchema.groups.find((group) => group.id === "task-mode-actions").controls;
assert.deepEqual(taskModeControls.map((control) => [control.id, control.halpin]), [
["tbtn-estop", "gmoccapy.v-button.button-0"],
["tbtn-on", "gmoccapy.v-button.button-1"],
["rbt-manual", "gmoccapy.v-button.button-2"],
["rbt-mdi", "gmoccapy.v-button.button-3"],
["rbt-auto", "gmoccapy.v-button.button-4"],
]);
assert.deepEqual(fiveAxisProfiles.map(({ id }) => id), ["xyzac-trt", "xyzbc-trt", "gmoccapy-xyzab"]);
const sourceSummary = createProfileSourceReferenceSummary("gmoccapy-xyzab");
assert.equal(sourceSummary.profileId, "gmoccapy-xyzab");
assert.equal(sourceSummary.referenceCount >= 10, true);
assert.equal(sourceSummary.kinds.includes("ini"), true);
assert.equal(sourceSummary.kinds.includes("halfile"), true);
assert.equal(sourceSummary.kinds.includes("postgui_hal"), true);
assert.equal(sourceSummary.kinds.includes("icon_manifest"), true);
assert.equal(sourceSummary.kinds.includes("python_gui"), true);
assert.equal(sourceSummary.promotionAllowed, false);
assert.equal(sourceSummary.semanticBoundary, "profile_source_map_only_not_runtime_proof");
assert.ok(sourceSummary.references.some((reference) => reference.path.endsWith("gmoccapy_XYZAB.ini")));
assert.ok(sourceSummary.references.some((reference) => reference.path.endsWith("gmoccapy_postgui.hal")));
assert.ok(sourceSummary.references.some((reference) => reference.path.endsWith("gmoccapy-button-icons.json")));
const adapter = createLinuxCncBoundaryAdapter({ profile });
assert.equal(adapter.profileId, "gmoccapy-xyzab");
assert.equal(adapter.profileSummary.coordinates, "XYZAB");
assert.equal(adapter.profileSummary.jointCount, 5);
assert.equal(adapter.profileSummary.mdiCommandCount, 0);
assert.equal(adapter.profileSummary.remapCount, 2);
assert.equal(adapter.profileSummary.toolCount, 17);
assert.equal(adapter.profileSummary.feedbackNetCount, 5);
assert.equal(adapter.profileSummary.halFileCount, 4);
assert.equal(adapter.promotionAllowed, false);
assert.equal(adapter.linuxCncKinematicsReady, false);
const readiness = createLinuxCncBoundaryReadiness(adapter);
assert.equal(readiness.ready, false);
assert.equal(readiness.promotionAllowed, false);
assert.equal(readiness.missing.includes("kinematics runtime"), true);
const frame = buildRtcpFrame({
axisPose: { x: 10, y: 20, z: -5, a: 30, b: 45, c: 99 },
activeLine: 10,
profile,
});
assert.equal(frame.profileId, "gmoccapy-xyzab");
assert.deepEqual(frame.jointPose.map((joint) => joint.axis), ["X", "Y", "Z", "A", "B"]);
assert.equal(frame.jointPose[4].value, 45);
assert.equal(frame.readiness.linuxCncKinematicsReady, false);
assert.equal(frame.readiness.promotionAllowed, false);
const store = createSimulationStore();
store.dispatch({ type: "SET_PROFILE", profileId: "gmoccapy-xyzab" });
assert.equal(store.getState().machineProfile, "gmoccapy-xyzab");
assert.equal(store.getState().profile.tcpCapable, false);
assert.equal(store.getState().rtcpState, "off");
store.dispatch({ type: "SET_KINS_TYPE", kinsType: "tcp-xyzac" });
assert.equal(store.getState().kinsType, "identity");
assert.equal(store.getState().rtcpState, "off");
assert.equal(store.getState().operatorMessage, "kinematics tcp-xyzac blocked: gmoccapy-xyzab is not TCP capable");
store.dispatch({ type: "SET_RTCP", enabled: true });
assert.equal(store.getState().rtcpState, "off");
assert.equal(store.getState().operatorMessage, "RTCP blocked: gmoccapy-xyzab is trivkins coordinates=xyzab reference only");
const preconditions = validateRunPreconditions(store.getState(), {
requireTaskHalRuntime: false,
requireTaskHalSession: false,
});
assert.equal(preconditions.ok, false);
assert.equal(preconditions.operatorMessage, "run blocked: unsupported five-axis profile gmoccapy-xyzab");
console.log("gmoccapy_xyzab_profile_smoke=ok");