From 7449ff7f4e1ff925193fc7df83ce3187c8e7103b Mon Sep 17 00:00:00 2001 From: wangdequan Date: Wed, 17 Jun 2026 23:00:25 +0800 Subject: [PATCH] =?UTF-8?q?=E8=99=9A=E6=8B=9FHAL=E5=AE=8C=E5=85=A8?= =?UTF-8?q?=E6=BB=A1=E8=B6=B3Web=E6=95=B0=E6=8E=A7=E4=BB=BF=E7=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 结论:motion controller matrix 已显式关联 external-offsets、QtDragon multi-joint、vismach remap sims 的 LinuxCNC configs/sim source evidence,并纳入 SDK、browser diagnostics artifact 与 release validation;虚拟 HAL 仍只作为 Web 仿真替代层,不声明 Linux kernel hard-realtime ABI、外部硬件驱动 ABI 或 native HAL module ABI。 --- text17.txt | 80 +++++++++++++++++++ wasm-port/runtime/sdk/README.md | 4 +- wasm-port/runtime/sdk/src/linuxcnc-hal.js | 30 ++++++- .../sdk/src/project-release-readiness.js | 9 ++- .../browser/real_simulation_page_smoke.html | 6 ++ .../tests/sdk/node/verify_sdk_surface.mjs | 11 +++ 6 files changed, 137 insertions(+), 3 deletions(-) diff --git a/text17.txt b/text17.txt index 7da5b06..d5b92fd 100644 --- a/text17.txt +++ b/text17.txt @@ -1033,3 +1033,83 @@ git diff --check ok 做联动,使保存的 Web CNC 仿真会话可直接输出 release-ready diagnostics evidence。 3. 将 ini-panel workflow overview 的 diagnostics URL workflow 接入固定页面表单/按钮, 让用户可在页面上输入 release artifact URL 与 browser diagnostics URL 后直接运行验证。 + +### 十一、2026-06-17 Motion Matrix Sim Config Source Evidence + +继续按本文件铁律推进:虚拟 HAL 的功能完全来源于 LinuxCNC 源程序,并且虚拟 HAL +完全满足 Web 方式数控系统仿真系统。本批完成上一节下一步第 1 项,把 motion +controller matrix 与 LinuxCNC `configs/sim` 证据建立显式关联,使 external-offsets、 +QtDragon multi-joint、vismach remap sims 的 source evidence 可在 SDK、browser +diagnostics artifact 和 release validation 中被直接验证。 + +新增实质能力: + +- `VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES` 新增 `simConfigTargets`: + - `x-single-axis-servo-dtg` 映射 `external-offsets`; + - `xyz-multi-axis-in-position` 映射 `qtdragon-on-abort`; + - `abc-rotary-feedback` 映射 `vismach-remap-sims`; +- `createVirtualHalMotionControllerMatrixReport()` 新增: + - `simConfigTargets`; + - `simConfigEvidenceRows`; + - `simConfigSourceFiles`; + - `missingSimConfigTargets`; +- motion matrix complete 判定现在同时要求: + - fixture 本身 motion/pin feedback 完整; + - fixture 映射的 LinuxCNC sim config source target 存在; + - `missingSimConfigTargets.length === 0`; +- `createVirtualHalSourceComplianceReport()` 的 `sourceFiles` 汇总 now 包含 motion + matrix 关联的 sim config source files; +- `createProjectReleaseBrowserDiagnosticsArtifactValidation()` 加严: + - 必须包含 `external-offsets`、`qtdragon-on-abort`、`vismach-remap-sims` targets; + - 必须包含 `dynamic_offsets.ini`、`qtdragon_xyyz.ini`、`puma.ini` 具体 + LinuxCNC sim config source files; +- SDK README 同步说明 motion controller matrix rows 已携带 LinuxCNC `configs/sim` + evidence。 + +新增/扩展验证: + +- `verify_sdk_surface.mjs` 覆盖: + - matrix report 包含三个 sim config targets; + - matrix report 包含 external offsets、QtDragon multi-joint、vismach puma source + files; + - `missingSimConfigTargets.length === 0`; + - fixture row 与 sim config target 的映射存在; + - browser diagnostics artifact validation 的 source files 包含三类 sim config evidence; +- `real_simulation_page_smoke.html` 覆盖: + - browser API `getVirtualHalMotionControllerMatrixReport()` 输出三类 sim config + targets; + - diagnostics/matrix 输出三类具体 LinuxCNC sim config source files; +- release diagnostics validation 现在不能只靠 target 名称通过,必须携带具体 LinuxCNC + sim config source evidence。 + +关键验证: + +```text +sdk_surface_node_smoke=ok +project_release_gate_manifest_node_smoke=ok +project_release_artifact_url_workflow_node_smoke=ok +project_batch_acceptance_workflow_node_smoke=ok +project_batch_acceptance_artifact_node_smoke=ok +browser_real_simulation_page_smoke=ok +git diff --check ok +``` + +语义边界: + +- 本批没有新增 G-code/interpreter/planner/kinematics/remap 语义; +- external-offsets、QtDragon multi-joint、vismach remap sims 只作为 LinuxCNC-owned + sim config source evidence 映射到 virtual HAL motion matrix; +- virtual HAL 仍不声称提供 Linux kernel hard-realtime ABI、外部硬件驱动 ABI 或 native + HAL module ABI; +- G-code/interpreter/planner/canonical motion 语义仍来自 LinuxCNC-backed WASM; +- Web 方式数控系统仿真所需 HAL、halcmd、motion controller 替代层继续由 + source-derived virtual HAL 满足。 + +下一步工作内容: + +1. 将 real simulation page 的 virtual HAL session snapshot 与 release diagnostics artifact + 做联动,使保存的 Web CNC 仿真会话可直接输出 release-ready diagnostics evidence。 +2. 将 ini-panel workflow overview 的 diagnostics URL workflow 接入固定页面表单/按钮, + 让用户可在页面上输入 release artifact URL 与 browser diagnostics URL 后直接运行验证。 +3. 为 motion matrix 增加 manifest-backed source check,把 matrix 关联的 sim config + source files 与 vendored LinuxCNC manifest 做显式一致性验证。 diff --git a/wasm-port/runtime/sdk/README.md b/wasm-port/runtime/sdk/README.md index cc4fc5d..ddb7e9f 100644 --- a/wasm-port/runtime/sdk/README.md +++ b/wasm-port/runtime/sdk/README.md @@ -313,7 +313,9 @@ private page state. controller runtime. It supports HAL pin/signal/param storage, `setp`, `sets`, `newsig`, `net`, `show`, `getp`, `gets`, `loadrt`/`loadusr` stubs, `addf`, thread start/stop, and servo-period motion stepping for browser - simulation and Node dashboards. + simulation and Node dashboards. The motion controller matrix rows also carry + LinuxCNC `configs/sim` evidence for external offsets, QtDragon multi-joint, + and vismach remap simulation coverage. - `createVirtualHalSourceComplianceReport()` is the machine-readable gate for the virtual HAL source rule. It maps replacement targets, runtime capabilities, and HAL pin families back to LinuxCNC source files such as diff --git a/wasm-port/runtime/sdk/src/linuxcnc-hal.js b/wasm-port/runtime/sdk/src/linuxcnc-hal.js index a3c4481..e5143a5 100644 --- a/wasm-port/runtime/sdk/src/linuxcnc-hal.js +++ b/wasm-port/runtime/sdk/src/linuxcnc-hal.js @@ -496,6 +496,7 @@ export const VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES = Object.freeze([ "axis.x.pos-cmd", "joint.0.pos-fb", ]), + simConfigTargets: Object.freeze(["external-offsets"]), expected: Object.freeze({ moving: true, inPosition: false, @@ -528,6 +529,7 @@ export const VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES = Object.freeze([ "joint.1.pos-fb", "joint.2.pos-fb", ]), + simConfigTargets: Object.freeze(["qtdragon-on-abort"]), expected: Object.freeze({ moving: false, inPosition: true, @@ -558,6 +560,7 @@ export const VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES = Object.freeze([ "joint.4.pos-fb", "joint.5.pos-fb", ]), + simConfigTargets: Object.freeze(["vismach-remap-sims"]), expected: Object.freeze({ moving: false, inPosition: true, @@ -2186,6 +2189,11 @@ function valuesClose(actual, expected, tolerance = 0.000001) { return Math.abs(Number(actual) - Number(expected)) <= tolerance; } +function virtualHalSimConfigTargetsById(targetIds = []) { + const ids = new Set(targetIds); + return VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.filter((target) => ids.has(target.id)); +} + export function createVirtualHalMotionControllerMatrixReport(options = {}) { const fixtures = options.motionFixtures ?? options.fixtures ?? VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES; const tolerance = clampNumber(options.tolerance ?? 0.000001, 0, 1); @@ -2244,11 +2252,25 @@ export function createVirtualHalMotionControllerMatrixReport(options = {}) { distanceToGoMatched && movingMatched && axisFeedbackRows.every((row) => row.matched); + const simConfigEvidenceRows = virtualHalSimConfigTargetsById(fixture.simConfigTargets ?? []) + .map((target) => ({ + id: target.id, + label: target.label, + sourceFiles: [...target.sourceFiles], + capabilities: [...target.capabilities], + evidence: target.evidence, + })); + const missingSimConfigTargets = (fixture.simConfigTargets ?? []) + .filter((targetId) => !simConfigEvidenceRows.some((target) => target.id === targetId)); return { id: fixture.id, label: fixture.label, source: "linuxcnc-motion-source-derived-virtual-motion-controller", sourceFiles: [...(fixture.sourceFiles ?? [])], + simConfigTargets: [...(fixture.simConfigTargets ?? [])], + simConfigEvidenceRows, + simConfigSourceFiles: [...new Set(simConfigEvidenceRows.flatMap((target) => target.sourceFiles))], + missingSimConfigTargets, complete, target: { ...(fixture.target ?? {}) }, initialPosition: { ...(fixture.initialPosition ?? {}) }, @@ -2269,7 +2291,8 @@ export function createVirtualHalMotionControllerMatrixReport(options = {}) { }; }); const missingFixtures = rows.filter((row) => !row.complete).map((row) => row.id); - const complete = rows.length > 0 && missingFixtures.length === 0; + const missingSimConfigTargets = rows.flatMap((row) => row.missingSimConfigTargets); + const complete = rows.length > 0 && missingFixtures.length === 0 && missingSimConfigTargets.length === 0; return { apiName: "linuxcnc-wasm-virtual-hal-motion-controller-matrix-report", matrixVersion: 1, @@ -2278,13 +2301,17 @@ export function createVirtualHalMotionControllerMatrixReport(options = {}) { complete, webSimulationSatisfied: complete, sourceFiles: [...new Set(rows.flatMap((row) => row.sourceFiles))], + simConfigSourceFiles: [...new Set(rows.flatMap((row) => row.simConfigSourceFiles))], + simConfigTargets: [...new Set(rows.flatMap((row) => row.simConfigTargets))], requiredPins: [...new Set(fixtures.flatMap((fixture) => fixture.requiredPins ?? []))], fixtureCount: rows.length, missingFixtures, + missingSimConfigTargets, rows, summaryRows: [ { id: "fixtures", label: "Motion matrix fixtures", value: `${rows.length}` }, { id: "source", label: "LinuxCNC motion source", value: complete ? "source-derived" : "incomplete" }, + { id: "sim-config-source", label: "LinuxCNC sim config source", value: missingSimConfigTargets.length === 0 ? "source-derived" : `missing ${missingSimConfigTargets.length}` }, { id: "servo-period", label: "Servo period stepping", value: complete ? "covered" : "blocked" }, { id: "axis-joint-feedback", label: "Axis/joint feedback", value: complete ? "covered" : "blocked" }, ], @@ -2526,6 +2553,7 @@ export function createVirtualHalSourceComplianceReport(options = {}) { ...simConfigSourceCoverage.sourceFiles, ...commandScriptFixtures.sourceFiles, ...motionControllerMatrix.sourceFiles, + ...motionControllerMatrix.simConfigSourceFiles, ])], missingCapabilitySources, missingFamilySources, diff --git a/wasm-port/runtime/sdk/src/project-release-readiness.js b/wasm-port/runtime/sdk/src/project-release-readiness.js index 9280f63..ea4a127 100644 --- a/wasm-port/runtime/sdk/src/project-release-readiness.js +++ b/wasm-port/runtime/sdk/src/project-release-readiness.js @@ -121,7 +121,13 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac arrayOrEmpty(motionControllerMatrix.requiredPins).includes("motion.distance-to-go") && arrayOrEmpty(motionControllerMatrix.requiredPins).includes("motion.in-position") && arrayOrEmpty(motionControllerMatrix.sourceFiles).includes("linuxcnc/src/emc/motion/motion.c") && - arrayOrEmpty(motionControllerMatrix.sourceFiles).includes("linuxcnc/src/emc/motion/axis.c"); + arrayOrEmpty(motionControllerMatrix.sourceFiles).includes("linuxcnc/src/emc/motion/axis.c") && + arrayOrEmpty(motionControllerMatrix.simConfigTargets).includes("external-offsets") && + arrayOrEmpty(motionControllerMatrix.simConfigTargets).includes("qtdragon-on-abort") && + arrayOrEmpty(motionControllerMatrix.simConfigTargets).includes("vismach-remap-sims") && + arrayOrEmpty(motionControllerMatrix.simConfigSourceFiles).includes("linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini") && + arrayOrEmpty(motionControllerMatrix.simConfigSourceFiles).includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini") && + arrayOrEmpty(motionControllerMatrix.simConfigSourceFiles).includes("linuxcnc/configs/sim/axis/vismach/puma/puma.ini"); const replacementReady = replacement.ready === true && replacement.replacesHostRuntimeForSimulation === true && objectOrEmpty(replacement.sourceCompliance).webSimulationSatisfied === true && @@ -154,6 +160,7 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac ...arrayOrEmpty(simConfigSourceCoverage.sourceFiles), ...arrayOrEmpty(commandScriptFixtures.sourceFiles), ...arrayOrEmpty(motionControllerMatrix.sourceFiles), + ...arrayOrEmpty(motionControllerMatrix.simConfigSourceFiles), ])], rows: [ { diff --git a/wasm-port/tests/browser/real_simulation_page_smoke.html b/wasm-port/tests/browser/real_simulation_page_smoke.html index c08946f..958632e 100644 --- a/wasm-port/tests/browser/real_simulation_page_smoke.html +++ b/wasm-port/tests/browser/real_simulation_page_smoke.html @@ -802,6 +802,12 @@ !motionControllerMatrix.requiredPins.includes("motion.distance-to-go") || !motionControllerMatrix.requiredPins.includes("motion.in-position") || !motionControllerMatrix.sourceFiles.includes("linuxcnc/src/emc/motion/axis.c") || + !motionControllerMatrix.simConfigTargets.includes("external-offsets") || + !motionControllerMatrix.simConfigTargets.includes("qtdragon-on-abort") || + !motionControllerMatrix.simConfigTargets.includes("vismach-remap-sims") || + !motionControllerMatrix.simConfigSourceFiles.includes("linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini") || + !motionControllerMatrix.simConfigSourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini") || + !motionControllerMatrix.simConfigSourceFiles.includes("linuxcnc/configs/sim/axis/vismach/puma/puma.ini") || !motionControllerMatrix.rows.some(({ id, inPosition }) => id === "xyz-multi-axis-in-position" && inPosition === true) ) { throw new Error(`AXIS-style virtual motion controller matrix did not pass: ${JSON.stringify(motionControllerMatrix)}`); diff --git a/wasm-port/tests/sdk/node/verify_sdk_surface.mjs b/wasm-port/tests/sdk/node/verify_sdk_surface.mjs index 5bb4007..cdebf6f 100644 --- a/wasm-port/tests/sdk/node/verify_sdk_surface.mjs +++ b/wasm-port/tests/sdk/node/verify_sdk_surface.mjs @@ -661,7 +661,15 @@ assert.equal(motionControllerMatrixReport.sourceFiles.includes("linuxcnc/src/emc assert.equal(motionControllerMatrixReport.sourceFiles.includes("linuxcnc/src/emc/motion/axis.c"), true); assert.equal(motionControllerMatrixReport.requiredPins.includes("motion.distance-to-go"), true); assert.equal(motionControllerMatrixReport.requiredPins.includes("motion.in-position"), true); +assert.equal(motionControllerMatrixReport.simConfigTargets.includes("external-offsets"), true); +assert.equal(motionControllerMatrixReport.simConfigTargets.includes("qtdragon-on-abort"), true); +assert.equal(motionControllerMatrixReport.simConfigTargets.includes("vismach-remap-sims"), true); +assert.equal(motionControllerMatrixReport.simConfigSourceFiles.includes("linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini"), true); +assert.equal(motionControllerMatrixReport.simConfigSourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini"), true); +assert.equal(motionControllerMatrixReport.simConfigSourceFiles.includes("linuxcnc/configs/sim/axis/vismach/puma/puma.ini"), true); +assert.equal(motionControllerMatrixReport.missingSimConfigTargets.length, 0); assert.equal(motionControllerMatrixReport.rows.some(({ id, inPosition }) => id === "xyz-multi-axis-in-position" && inPosition === true), true); +assert.equal(motionControllerMatrixReport.rows.some(({ id, simConfigTargets }) => id === "x-single-axis-servo-dtg" && simConfigTargets.includes("external-offsets")), true); assert.equal(motionControllerMatrixReport.rows.every(({ axisFeedbackRows }) => axisFeedbackRows.every(({ matched }) => matched)), true); assert.equal(virtualHalRuntime.getMotionControllerMatrixReport().complete, true); const steppedVirtualHal = stepVirtualHalMotion(virtualHalRuntime.getState(), { @@ -777,6 +785,9 @@ assert.equal(browserDiagnosticsArtifactValidation.commandScriptFixturesReady, tr assert.equal(browserDiagnosticsArtifactValidation.motionControllerMatrixReady, true); assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/src/hal/utils/halcmd_commands.cc"), true); assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/src/emc/motion/axis.c"), true); +assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini"), true); +assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini"), true); +assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/configs/sim/axis/vismach/puma/puma.ini"), true); const runtimeProjectReport = virtualHalRuntime.getProjectReport({ availableFunctions: VIRTUAL_HAL_WASM_BRIDGE_FUNCTIONS }); assert.equal(runtimeProjectReport.simulationRuntime.replacesHostRuntimeForSimulation, true); assert.equal(runtimeProjectReport.systemCoverage.unclassifiedSnapshotPins.length, 0);