180 lines
10 KiB
JavaScript
180 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-xyzac-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");
|