完善五轴 RTCP 仿真与验证资料

This commit is contained in:
2026-07-01 21:49:58 -04:00
parent ac4e855b2b
commit d0d58998ac
159 changed files with 6771594 additions and 339 deletions

View File

@@ -34,10 +34,11 @@
}
return win.webRtcp5AxisSimulation.getState();
}
async function waitForMachineFileStaging(win) {
async function waitForMachineFileStaging(win, profileId = null) {
for (let attempt = 0; attempt < 120; attempt += 1) {
const state = win.webRtcp5AxisSimulation.getState();
if (state.machineFileStaging?.status === "staged" && state.machineFileStaging?.save?.fileCount >= 5) {
const stagedForProfile = !profileId || state.machineFileStaging?.profileId === profileId;
if (stagedForProfile && state.machineFileStaging?.status === "staged" && state.machineFileStaging?.save?.fileCount >= 5) {
return state;
}
await wait(25);
@@ -270,10 +271,46 @@
if (xyzbcState.kinematicsRuntimeReadiness?.moduleId !== "xyzbc-trt") {
throw new Error(`XYZBC kinematics runtime did not load: ${JSON.stringify(xyzbcState.kinematicsRuntimeReadiness)}`);
}
const gmoccapyTrtProfileSelector = doc.querySelector('[data-action="select-profile"]');
gmoccapyTrtProfileSelector.value = "gmoccapy-xyzac-trt";
gmoccapyTrtProfileSelector.dispatchEvent(new Event("change", { bubbles: true }));
const gmoccapyTrtStagedState = await waitForMachineFileStaging(win, "gmoccapy-xyzac-trt");
await win.webRtcp5AxisSimulation.refreshKinematicsFrame({ operatorMessage: "browser smoke refreshed gmoccapy xyzac TRT frame" });
const gmoccapyTrtState = win.webRtcp5AxisSimulation.getState();
if (gmoccapyTrtState.machineProfile !== "gmoccapy-xyzac-trt") {
throw new Error(`profile selector did not switch to gmoccapy TRT: ${gmoccapyTrtState.machineProfile}`);
}
if (gmoccapyTrtState.profile.display.display !== "gmoccapy") {
throw new Error(`gmoccapy TRT profile did not preserve DISPLAY=gmoccapy: ${JSON.stringify(gmoccapyTrtState.profile.display)}`);
}
if (gmoccapyTrtState.profile.display.openFile !== "./examples/impeller-7bl-xyzac.ngc") {
throw new Error(`gmoccapy TRT profile did not preserve OPEN_FILE: ${gmoccapyTrtState.profile.display.openFile}`);
}
if (gmoccapyTrtState.kinematicsRuntimeReadiness?.moduleId !== "xyzac-trt") {
throw new Error(`gmoccapy TRT kinematics runtime did not load xyzac-trt: ${JSON.stringify(gmoccapyTrtState.kinematicsRuntimeReadiness)}`);
}
if (gmoccapyTrtState.kinsType !== "tcp-xyzac" || gmoccapyTrtState.rtcpState !== "on") {
throw new Error(`gmoccapy TRT default kinematics should be fixed TCP, got ${gmoccapyTrtState.kinsType}/${gmoccapyTrtState.rtcpState}`);
}
if (!gmoccapyTrtState.iniConfigReadiness?.path?.includes("configs/sim/gmoccapy/non_trivial_kinematics/table-rotary-tilting/xyzac-trt.ini")) {
throw new Error(`gmoccapy TRT INI readiness did not use gmoccapy config: ${JSON.stringify(gmoccapyTrtState.iniConfigReadiness)}`);
}
if (gmoccapyTrtStagedState.machineFileStaging?.plan?.demoDirectory !== "examples") {
throw new Error(`gmoccapy TRT staging did not use examples directory: ${JSON.stringify(gmoccapyTrtStagedState.machineFileStaging?.plan)}`);
}
if (!gmoccapyTrtStagedState.machineFileStaging?.gcodeSources?.some((source) => source.filename === "impeller-7bl-xyzac.ngc" && source.sourceRel.includes("/examples/"))) {
throw new Error(`gmoccapy TRT staging did not expose LinuxCNC examples: ${JSON.stringify(gmoccapyTrtStagedState.machineFileStaging?.gcodeSources)}`);
}
if (!gmoccapyTrtState.machineProject?.gcodeDirectory?.includes("configs/sim/gmoccapy/non_trivial_kinematics/table-rotary-tilting/examples")) {
throw new Error(`gmoccapy TRT project directory did not track examples: ${JSON.stringify(gmoccapyTrtState.machineProject)}`);
}
if (gmoccapyTrtState.rtcpFrame?.profileId !== "gmoccapy-xyzac-trt" || gmoccapyTrtState.rtcpFrame?.rtcpState !== "on") {
throw new Error(`gmoccapy TRT RTCP frame did not stay on fixed TRT: ${JSON.stringify(gmoccapyTrtState.rtcpFrame)}`);
}
const restoredProfileSelector = doc.querySelector('[data-action="select-profile"]');
restoredProfileSelector.value = "xyzac-trt";
restoredProfileSelector.dispatchEvent(new Event("change", { bubbles: true }));
await wait(500);
await waitForMachineFileStaging(win, "xyzac-trt");
await win.webRtcp5AxisSimulation.refreshKinematicsFrame({ operatorMessage: "browser smoke restored xyzac frame" });
const restoredProfileState = win.webRtcp5AxisSimulation.getState();
if (restoredProfileState.machineProfile !== "xyzac-trt") {
@@ -662,6 +699,34 @@
if (!doc.querySelector('[data-machine-file-staging="status"]')?.textContent.includes("staged")) {
throw new Error("automatic machine file staging status did not render");
}
const stagedToolTwo = win.webRtcp5AxisSimulation.queryToolDb({ toolNumber: 2 });
if (!stagedToolTwo || stagedToolTwo.idx !== 2 || stagedToolTwo.pocket !== 2 || stagedToolTwo.offset.z !== 15) {
throw new Error(`browser tool DB query did not read staged tool.tbl: ${JSON.stringify(stagedToolTwo)}`);
}
win.webRtcp5AxisSimulation.editToolDb({
toolNumber: 5,
pocket: 55,
diameter: 11.25,
toolLength: 31.5,
});
const editedBrowserTool = win.webRtcp5AxisSimulation.queryToolDb({ toolNumber: 5 });
if (
!editedBrowserTool ||
editedBrowserTool.idx !== 5 ||
editedBrowserTool.pocket !== 55 ||
editedBrowserTool.diameter !== 11.25 ||
editedBrowserTool.offset.z !== 31.5
) {
throw new Error(`browser tool DB edit did not update staged row: ${JSON.stringify(editedBrowserTool)}`);
}
const browserToolSave = await win.webRtcp5AxisSimulation.saveToolDb();
if (
browserToolSave.storageMode !== "memory-fallback" ||
browserToolSave.storageCapability?.opfsUnavailable !== true ||
!browserToolSave.text.includes("T5 P55 D+11.250000 Z+31.500000")
) {
throw new Error(`browser tool DB save did not use memory fallback LinuxCNC format: ${JSON.stringify(browserToolSave)}`);
}
win.webRtcp5AxisSimulation.dispatch({
type: "LOAD_PROGRAM",
filename: "operator-arc-demo.ngc",
@@ -889,18 +954,33 @@
for (const requiredHostNativeState of [
"hardware drive false",
"host realtime false",
"external user-M false",
"tool DB false",
"external user-M web simulation only",
"tool DB web simulation only",
"host external user-M false",
"host tool DB false",
"arbitrary user-M false",
]) {
if (!hostNativeBoundary.includes(requiredHostNativeState)) {
throw new Error(`host/native boundary diagnostic did not render ${requiredHostNativeState}: ${hostNativeBoundary}`);
}
}
const toolUserBoundary = doc.querySelector('[data-full-execution-boundary="tool-user-process"]')?.textContent || "";
for (const requiredToolUserState of [
"toolDbProcessReady=true web_simulation_only",
"externalUserMProcessReady=true web_simulation_only",
]) {
if (!toolUserBoundary.includes(requiredToolUserState)) {
throw new Error(`tool/user process diagnostic did not render ${requiredToolUserState}: ${toolUserBoundary}`);
}
}
for (const [field, expected] of Object.entries({
hardwareDrive: false,
hostRealtimeKernel: false,
externalUserMProcessReady: false,
toolDbProcessReady: false,
externalUserMProcessReady: true,
toolDbProcessReady: true,
hostExternalUserMProcessReady: false,
hostToolDbProcessReady: false,
arbitraryUserMExecution: false,
})) {
if (taskHalRunState.fullExecutionBoundary?.[field] !== expected) {
throw new Error(`full execution boundary ${field} drifted: ${JSON.stringify(taskHalRunState.fullExecutionBoundary)}`);