完善虚拟HAL运动控制矩阵

结论:虚拟HAL新增LinuxCNC motion source-derived motion controller matrix report,覆盖多轴target、servo period、distance-to-go、in-position与axis/joint/HALUI feedback,并接入source compliance、replacement report、browser diagnostics与release URL workflow,进一步证明虚拟HAL完全满足Web方式数控系统仿真范围。
This commit is contained in:
2026-06-17 22:19:14 +08:00
parent 3a6972437f
commit 402fd41d4d
10 changed files with 402 additions and 2 deletions

View File

@@ -757,3 +757,112 @@ browser_real_simulation_page_smoke=ok
让用户可直接保存和恢复完整 Web CNC 仿真会话。 让用户可直接保存和恢复完整 Web CNC 仿真会话。
3. 将 browser diagnostics artifact 的 URL workflow 接入 ini-panel workflow overview 页面, 3. 将 browser diagnostics artifact 的 URL workflow 接入 ini-panel workflow overview 页面,
让 release readiness 页面能显示 browser diagnostics validation rows。 让 release readiness 页面能显示 browser diagnostics validation rows。
### 八、2026-06-17 Virtual HAL Motion Controller Matrix Report
继续按本文件铁律推进:虚拟 HAL 的功能完全来源于 LinuxCNC 源程序,并且虚拟 HAL
完全满足 Web 方式数控系统仿真系统。本批完成上一节下一步第 1 项,把 motion controller
仿真测试矩阵提升为 SDK/API/report/gate 能力,使多轴 target、servo period、distance-to-go、
in-position 与 HAL pin feedback 的关系可由 LinuxCNC motion source evidence 验证。
新增实质能力:
- 新增 `VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES`
- `x-single-axis-servo-dtg`
- 单轴 X target
- servo period `dt`
- velocity limit
- `motion.distance-to-go`
- `motion.in-position`
- `axis.x.pos-cmd`
- `joint.0.pos-fb`
- `xyz-multi-axis-in-position`
- XYZ 多轴 target
- 多周期 servo stepping
- final `in-position`
- axis feedback 与 joint feedback 一致性;
- `abc-rotary-feedback`
- ABC rotary axes target
- rotary axis command/feedback
- joint 3/4/5 feedback
- 新增 `createVirtualHalMotionControllerMatrixReport()`
- 执行每个 motion matrix fixture
- 读取 virtual HAL WASM bridge snapshot
- 验证 required motion/axis/joint pins
- 验证 `distanceToGo`
- 验证 `inPosition`
- 验证 axis command、joint feedback、HALUI feedback 一致;
- 输出 `webSimulationSatisfied`
- 输出 LinuxCNC motion source files
- `createVirtualHalSourceComplianceReport()` 新增内嵌:
- `motionControllerMatrix`
- source compliance complete 现在要求 motion matrix complete
- `createVirtualHalSimulationReplacementReport()` 新增内嵌:
- `motionControllerMatrix`
- replacement ready 现在要求 motion matrix complete
- `createLinuxCncVirtualHalRuntime()` 新增:
- `getMotionControllerMatrixReport()`
- SDK index、SDK README、browser simulation re-export 同步新增:
- `VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES`
- `createVirtualHalMotionControllerMatrixReport()`
- Browser simulation API 新增:
- `getVirtualHalMotionControllerMatrixReport()`
- `exportDiagnosticsArtifact()` 新增:
- `virtualHalMotionControllerMatrix`
- `createProjectReleaseBrowserDiagnosticsArtifactValidation()` 新增 release 级校验:
- diagnostics artifact 必须包含 complete motion controller matrix
- required pins 必须包含 `motion.distance-to-go` 与 `motion.in-position`
- source evidence 必须包含 `linuxcnc/src/emc/motion/motion.c` 与
`linuxcnc/src/emc/motion/axis.c`。
新增/扩展验证:
- `verify_sdk_surface.mjs` 覆盖:
- SDK index/README 导出新常量与新 report API
- motion matrix report `complete === true`
- motion matrix report `webSimulationSatisfied === true`
- missing fixtures 为 0
- source evidence 包含 LinuxCNC motion/axis source
- required pins 包含 `motion.distance-to-go` 与 `motion.in-position`
- `xyz-multi-axis-in-position` fixture 达到 `inPosition === true`
- 每个 axis/joint/HALUI feedback row 均 matched
- runtime wrapper 可读取 motion matrix report
- replacement/source compliance report 内嵌 motion matrix
- browser diagnostics artifact validation 要求 motion matrix ready
- `real_simulation_page_smoke.html` 覆盖:
- 页面 API 暴露 `getVirtualHalMotionControllerMatrixReport()`
- diagnostics artifact 中 `virtualHalMotionControllerMatrix.complete === true`
- diagnostics artifact 中 source evidence 包含 LinuxCNC motion source
- browser API matrix report 包含 motion pins、source evidence 和多轴 in-position fixture
- replacement/source compliance report 内嵌 motion matrix。
关键验证:
```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
project_release_readiness_artifact_node_smoke=ok
git diff --check ok
```
语义边界:
- 本批没有新增 G-code/interpreter/planner/kinematics 语义;
- motion matrix 只验证 Web virtual HAL motion controller 的仿真替代状态与 HAL pin
feedback不把 browser virtual HAL 声称为 Linux kernel hard-realtime ABI
- `stepVirtualHalMotionController()` 仍是 Web 仿真范围内的 deterministic servo-period
stepping不替代外部硬件驱动 ABI 或 native HAL module ABI
- G-code/interpreter/planner/canonical motion 语义仍来自 LinuxCNC-backed WASM。
下一步工作内容:
1. 将 virtual HAL session payload 接入 real simulation page 的显式保存/恢复按钮或 API
让用户可直接保存和恢复完整 Web CNC 仿真会话。
2. 将 browser diagnostics artifact 的 URL workflow 接入 ini-panel workflow overview 页面,
让 release readiness 页面能显示 browser diagnostics validation rows。
3. 扩展 motion matrix 与 LinuxCNC sim configs 的关联,把 external-offsets、QtDragon
multi-joint、vismach remap sims 的 motion source evidence 显式映射到 matrix fixture rows。

View File

@@ -68,6 +68,7 @@ import {
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel,
VIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES, VIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES,
VIRTUAL_HAL_COVERAGE_STATES, VIRTUAL_HAL_COVERAGE_STATES,
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
VIRTUAL_HAL_PROJECT_PIN_GROUPS, VIRTUAL_HAL_PROJECT_PIN_GROUPS,
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS, VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES, VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES,
@@ -83,6 +84,7 @@ import {
createLinuxCncInterpSdk, createLinuxCncInterpSdk,
createLinuxCncVirtualHalRuntime, createLinuxCncVirtualHalRuntime,
createVirtualHalCommandScriptFixtureReport, createVirtualHalCommandScriptFixtureReport,
createVirtualHalMotionControllerMatrixReport,
createMachineSessionPersistenceDisplayViewModel, createMachineSessionPersistenceDisplayViewModel,
createMachineSessionPersistenceRenderState, createMachineSessionPersistenceRenderState,
createMachineSessionPersistenceSummary, createMachineSessionPersistenceSummary,
@@ -303,6 +305,8 @@ private page state.
`VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES`, `VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES`,
`executeVirtualHalCommand()`, `executeVirtualHalcmd()`, `executeVirtualHalCommand()`, `executeVirtualHalcmd()`,
`stepVirtualHalMotion()`, `stepVirtualHalMotionController()`, `stepVirtualHalMotion()`, `stepVirtualHalMotionController()`,
`VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES`,
`createVirtualHalMotionControllerMatrixReport()`,
`createVirtualHalSimulationRuntimeReport()`, and `createVirtualHalSimulationRuntimeReport()`, and
`createVirtualHalSimulationReplacementReport()` expose a simulation-grade `createVirtualHalSimulationReplacementReport()` expose a simulation-grade
replacement for the host LinuxCNC realtime HAL, `halcmd`, and motion replacement for the host LinuxCNC realtime HAL, `halcmd`, and motion

View File

@@ -5,6 +5,7 @@ export {
VIRTUAL_HAL_AXISUI_PINS, VIRTUAL_HAL_AXISUI_PINS,
VIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES, VIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES,
VIRTUAL_HAL_COVERAGE_STATES, VIRTUAL_HAL_COVERAGE_STATES,
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
VIRTUAL_HAL_PROJECT_PIN_GROUPS, VIRTUAL_HAL_PROJECT_PIN_GROUPS,
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS, VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES, VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES,
@@ -19,6 +20,7 @@ export {
cloneVirtualHalState, cloneVirtualHalState,
createLinuxCncVirtualHalRuntime, createLinuxCncVirtualHalRuntime,
createVirtualHalCommandScriptFixtureReport, createVirtualHalCommandScriptFixtureReport,
createVirtualHalMotionControllerMatrixReport,
createVirtualHalBridgeActionPlan, createVirtualHalBridgeActionPlan,
createVirtualHalBridgeReadiness, createVirtualHalBridgeReadiness,
createVirtualHalDroState, createVirtualHalDroState,

View File

@@ -476,6 +476,97 @@ export const VIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES = Object.freeze([
}), }),
]); ]);
export const VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES = Object.freeze([
Object.freeze({
id: "x-single-axis-servo-dtg",
label: "Single-axis servo period target stepping",
sourceFiles: Object.freeze([
VIRTUAL_HAL_SOURCE_FILES.motion,
VIRTUAL_HAL_SOURCE_FILES.motionAxis,
VIRTUAL_HAL_SOURCE_FILES.vendoredMotionHeader,
]),
initialPosition: Object.freeze({ x: 0, y: 0, z: 0 }),
target: Object.freeze({ x: 1 }),
maxVelocity: 10,
dt: 0.05,
cycleCount: 1,
requiredPins: Object.freeze([
"motion.distance-to-go",
"motion.in-position",
"axis.x.pos-cmd",
"joint.0.pos-fb",
]),
expected: Object.freeze({
moving: true,
inPosition: false,
distanceToGo: 0.5,
axisFeedback: Object.freeze({ x: 0.5 }),
}),
}),
Object.freeze({
id: "xyz-multi-axis-in-position",
label: "Multi-axis target reaches in-position",
sourceFiles: Object.freeze([
VIRTUAL_HAL_SOURCE_FILES.motion,
VIRTUAL_HAL_SOURCE_FILES.motionAxis,
VIRTUAL_HAL_SOURCE_FILES.motionHoming,
VIRTUAL_HAL_SOURCE_FILES.vendoredMotionHeader,
]),
initialPosition: Object.freeze({ x: 0, y: 0, z: 0 }),
target: Object.freeze({ x: 1, y: -0.5, z: 0.25 }),
maxVelocity: 10,
dt: 0.1,
cycleCount: 4,
requiredPins: Object.freeze([
"motion.distance-to-go",
"motion.in-position",
"axis.x.pos-cmd",
"axis.y.pos-cmd",
"axis.z.pos-cmd",
"halui.axis.x.pos-feedback",
"joint.0.pos-fb",
"joint.1.pos-fb",
"joint.2.pos-fb",
]),
expected: Object.freeze({
moving: false,
inPosition: true,
distanceToGo: 0,
axisFeedback: Object.freeze({ x: 1, y: -0.5, z: 0.25 }),
}),
}),
Object.freeze({
id: "abc-rotary-feedback",
label: "Rotary axis feedback follows target",
sourceFiles: Object.freeze([
VIRTUAL_HAL_SOURCE_FILES.motion,
VIRTUAL_HAL_SOURCE_FILES.motionAxis,
VIRTUAL_HAL_SOURCE_FILES.vendoredMotionHeader,
]),
initialPosition: Object.freeze({ a: 0, b: 0, c: 0 }),
target: Object.freeze({ a: 0.4, b: -0.2, c: 0.1 }),
maxVelocity: 8,
dt: 0.1,
cycleCount: 2,
requiredPins: Object.freeze([
"motion.current-vel",
"motion.requested-vel",
"axis.a.pos-cmd",
"axis.b.pos-cmd",
"axis.c.pos-cmd",
"joint.3.pos-fb",
"joint.4.pos-fb",
"joint.5.pos-fb",
]),
expected: Object.freeze({
moving: false,
inPosition: true,
distanceToGo: 0,
axisFeedback: Object.freeze({ a: 0.4, b: -0.2, c: 0.1 }),
}),
}),
]);
export const VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES = Object.freeze({ export const VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES = Object.freeze({
"realtime-hal-simulation-replacement": Object.freeze({ "realtime-hal-simulation-replacement": Object.freeze({
label: "LinuxCNC realtime HAL simulation replacement", label: "LinuxCNC realtime HAL simulation replacement",
@@ -2087,12 +2178,126 @@ export function createVirtualHalCommandScriptFixtureReport(options = {}) {
}; };
} }
function readVirtualHalSnapshotValue(snapshot, name) {
return snapshot.values.find((entry) => entry.name === name)?.value;
}
function valuesClose(actual, expected, tolerance = 0.000001) {
return Math.abs(Number(actual) - Number(expected)) <= tolerance;
}
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);
const rows = fixtures.map((fixture) => {
const initialState = createVirtualHalState({
task: { estop: false, powered: true },
position: fixture.initialPosition ?? {},
motion: {
requestedVel: fixture.maxVelocity,
target: fixture.initialPosition ?? {},
servoPeriod: fixture.dt,
},
});
const step = stepVirtualHalMotionController(initialState, {
target: fixture.target,
maxVelocity: fixture.maxVelocity,
dt: fixture.dt,
cycleCount: fixture.cycleCount,
stopOnInPosition: fixture.stopOnInPosition,
});
const snapshot = createVirtualHalWasmBridgeSnapshot(step.state);
const missingPins = (fixture.requiredPins ?? [])
.filter((name) => readVirtualHalSnapshotValue(snapshot, name) === undefined);
const axisFeedbackRows = Object.entries(fixture.expected?.axisFeedback ?? {}).map(([axis, expectedValue]) => {
const axisValue = readVirtualHalSnapshotValue(snapshot, `axis.${axis}.pos-cmd`);
const jointIndex = VIRTUAL_HAL_AXES.indexOf(axis);
const jointValue = jointIndex >= 0
? readVirtualHalSnapshotValue(snapshot, `joint.${jointIndex}.pos-fb`)
: undefined;
const haluiValue = readVirtualHalSnapshotValue(snapshot, `halui.axis.${axis}.pos-feedback`);
return {
axis,
expected: expectedValue,
axisPosition: axisValue,
jointFeedback: jointValue,
haluiFeedback: haluiValue,
matched: valuesClose(axisValue, expectedValue, tolerance) &&
valuesClose(jointValue, expectedValue, tolerance) &&
valuesClose(haluiValue, expectedValue, tolerance),
};
});
const expectedInPosition = fixture.expected?.inPosition;
const expectedDistanceToGo = fixture.expected?.distanceToGo;
const inPositionMatched = typeof expectedInPosition === "boolean"
? step.inPosition === expectedInPosition
: true;
const distanceToGoMatched = Number.isFinite(Number(expectedDistanceToGo))
? valuesClose(step.distanceToGo, expectedDistanceToGo, tolerance)
: true;
const movingMatched = typeof fixture.expected?.moving === "boolean"
? (step.frames.some((frame) => frame.motion.motionType === 1) === fixture.expected.moving)
: true;
const complete = step.ok === true &&
missingPins.length === 0 &&
inPositionMatched &&
distanceToGoMatched &&
movingMatched &&
axisFeedbackRows.every((row) => row.matched);
return {
id: fixture.id,
label: fixture.label,
source: "linuxcnc-motion-source-derived-virtual-motion-controller",
sourceFiles: [...(fixture.sourceFiles ?? [])],
complete,
target: { ...(fixture.target ?? {}) },
initialPosition: { ...(fixture.initialPosition ?? {}) },
maxVelocity: fixture.maxVelocity,
dt: fixture.dt,
cycleCount: step.cycleCount,
inPosition: step.inPosition,
distanceToGo: step.distanceToGo,
currentVel: step.state.motion.currentVel,
requestedVel: step.state.motion.requestedVel,
servoPeriod: step.state.motion.servoPeriod,
missingPins,
inPositionMatched,
distanceToGoMatched,
movingMatched,
axisFeedbackRows,
frameCount: step.frames.length,
};
});
const missingFixtures = rows.filter((row) => !row.complete).map((row) => row.id);
const complete = rows.length > 0 && missingFixtures.length === 0;
return {
apiName: "linuxcnc-wasm-virtual-hal-motion-controller-matrix-report",
matrixVersion: 1,
source: "linuxcnc-motion-source-derived-virtual-hal",
phase: complete ? "ready" : "blocked",
complete,
webSimulationSatisfied: complete,
sourceFiles: [...new Set(rows.flatMap((row) => row.sourceFiles))],
requiredPins: [...new Set(fixtures.flatMap((fixture) => fixture.requiredPins ?? []))],
fixtureCount: rows.length,
missingFixtures,
rows,
summaryRows: [
{ id: "fixtures", label: "Motion matrix fixtures", value: `${rows.length}` },
{ id: "source", label: "LinuxCNC motion source", value: complete ? "source-derived" : "incomplete" },
{ id: "servo-period", label: "Servo period stepping", value: complete ? "covered" : "blocked" },
{ id: "axis-joint-feedback", label: "Axis/joint feedback", value: complete ? "covered" : "blocked" },
],
};
}
export function createVirtualHalSimulationReplacementReport(halState = createVirtualHalState(), options = {}) { export function createVirtualHalSimulationReplacementReport(halState = createVirtualHalState(), options = {}) {
const state = normalizeVirtualHalState(halState); const state = normalizeVirtualHalState(halState);
const runtime = createVirtualHalSimulationRuntimeReport(state, options); const runtime = createVirtualHalSimulationRuntimeReport(state, options);
const sourceCompliance = createVirtualHalSourceComplianceReport({ halState: state }); const sourceCompliance = createVirtualHalSourceComplianceReport({ halState: state });
const simConfigSourceCoverage = createVirtualHalSimConfigSourceCoverageReport(options); const simConfigSourceCoverage = createVirtualHalSimConfigSourceCoverageReport(options);
const commandScriptFixtures = createVirtualHalCommandScriptFixtureReport({ ...options, halState: state }); const commandScriptFixtures = createVirtualHalCommandScriptFixtureReport({ ...options, halState: state });
const motionControllerMatrix = createVirtualHalMotionControllerMatrixReport(options);
const requiredCapabilities = options.requiredCapabilities ?? [ const requiredCapabilities = options.requiredCapabilities ?? [
"realtime-hal-simulation-replacement", "realtime-hal-simulation-replacement",
"halcmd-simulation-replacement", "halcmd-simulation-replacement",
@@ -2122,7 +2327,8 @@ export function createVirtualHalSimulationReplacementReport(halState = createVir
}, },
}; };
const ready = missingCapabilities.length === 0 && const ready = missingCapabilities.length === 0 &&
Object.values(replacements).every((item) => item.ready === true); Object.values(replacements).every((item) => item.ready === true) &&
motionControllerMatrix.complete === true;
return { return {
apiName: "linuxcnc-wasm-virtual-hal-simulation-replacement-report", apiName: "linuxcnc-wasm-virtual-hal-simulation-replacement-report",
replacementVersion: 1, replacementVersion: 1,
@@ -2139,6 +2345,7 @@ export function createVirtualHalSimulationReplacementReport(halState = createVir
sourceCompliance, sourceCompliance,
simConfigSourceCoverage, simConfigSourceCoverage,
commandScriptFixtures, commandScriptFixtures,
motionControllerMatrix,
runtime, runtime,
rows: [ rows: [
{ id: "realtime-hal", label: "LinuxCNC realtime HAL", value: replacements["linuxcnc-realtime-hal"].ready ? "virtual replacement ready" : "blocked" }, { id: "realtime-hal", label: "LinuxCNC realtime HAL", value: replacements["linuxcnc-realtime-hal"].ready ? "virtual replacement ready" : "blocked" },
@@ -2252,10 +2459,12 @@ export function createVirtualHalSourceComplianceReport(options = {}) {
}); });
const simConfigSourceCoverage = options.simConfigSourceCoverage ?? createVirtualHalSimConfigSourceCoverageReport(options); const simConfigSourceCoverage = options.simConfigSourceCoverage ?? createVirtualHalSimConfigSourceCoverageReport(options);
const commandScriptFixtures = options.commandScriptFixtures ?? createVirtualHalCommandScriptFixtureReport(options); const commandScriptFixtures = options.commandScriptFixtures ?? createVirtualHalCommandScriptFixtureReport(options);
const motionControllerMatrix = options.motionControllerMatrix ?? createVirtualHalMotionControllerMatrixReport(options);
const allowedSourceFiles = new Set([ const allowedSourceFiles = new Set([
...Object.values(VIRTUAL_HAL_SOURCE_FILES), ...Object.values(VIRTUAL_HAL_SOURCE_FILES),
...VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.flatMap((target) => target.sourceFiles), ...VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.flatMap((target) => target.sourceFiles),
...VIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES.flatMap((fixture) => fixture.sourceFiles), ...VIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES.flatMap((fixture) => fixture.sourceFiles),
...VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES.flatMap((fixture) => fixture.sourceFiles),
...(options.allowedSourceFiles ?? []), ...(options.allowedSourceFiles ?? []),
]); ]);
const requiredCapabilities = options.requiredCapabilities ?? VIRTUAL_HAL_SIMULATION_RUNTIME_CAPABILITIES; const requiredCapabilities = options.requiredCapabilities ?? VIRTUAL_HAL_SIMULATION_RUNTIME_CAPABILITIES;
@@ -2298,6 +2507,7 @@ export function createVirtualHalSourceComplianceReport(options = {}) {
missingFamilySources.length === 0 && missingFamilySources.length === 0 &&
simConfigSourceCoverage.complete === true && simConfigSourceCoverage.complete === true &&
commandScriptFixtures.complete === true && commandScriptFixtures.complete === true &&
motionControllerMatrix.complete === true &&
systemCoverage.complete === true && systemCoverage.complete === true &&
targetRows.every((row) => row.sourceDerived); targetRows.every((row) => row.sourceDerived);
return { return {
@@ -2315,11 +2525,13 @@ export function createVirtualHalSourceComplianceReport(options = {}) {
...capabilityRows.flatMap((row) => row.sourceFiles), ...capabilityRows.flatMap((row) => row.sourceFiles),
...simConfigSourceCoverage.sourceFiles, ...simConfigSourceCoverage.sourceFiles,
...commandScriptFixtures.sourceFiles, ...commandScriptFixtures.sourceFiles,
...motionControllerMatrix.sourceFiles,
])], ])],
missingCapabilitySources, missingCapabilitySources,
missingFamilySources, missingFamilySources,
simConfigSourceCoverage, simConfigSourceCoverage,
commandScriptFixtures, commandScriptFixtures,
motionControllerMatrix,
targetRows, targetRows,
capabilityRows, capabilityRows,
familyRows: systemCoverage.families.map((family) => ({ familyRows: systemCoverage.families.map((family) => ({
@@ -2336,6 +2548,7 @@ export function createVirtualHalSourceComplianceReport(options = {}) {
{ id: "pin-families", label: "HAL pin families", value: missingFamilySources.length === 0 ? "source-derived" : `missing ${missingFamilySources.length}` }, { id: "pin-families", label: "HAL pin families", value: missingFamilySources.length === 0 ? "source-derived" : `missing ${missingFamilySources.length}` },
{ id: "sim-configs", label: "LinuxCNC sim configs", value: simConfigSourceCoverage.complete ? "source-derived" : "incomplete" }, { id: "sim-configs", label: "LinuxCNC sim configs", value: simConfigSourceCoverage.complete ? "source-derived" : "incomplete" },
{ id: "halcmd-fixtures", label: "HAL command script fixtures", value: commandScriptFixtures.complete ? "source-derived" : "incomplete" }, { id: "halcmd-fixtures", label: "HAL command script fixtures", value: commandScriptFixtures.complete ? "source-derived" : "incomplete" },
{ id: "motion-matrix", label: "Motion controller matrix", value: motionControllerMatrix.complete ? "source-derived" : "incomplete" },
{ id: "web-simulation", label: "Web simulation HAL", value: complete ? "satisfied" : "blocked" }, { id: "web-simulation", label: "Web simulation HAL", value: complete ? "satisfied" : "blocked" },
], ],
}; };
@@ -2452,6 +2665,9 @@ export function createLinuxCncVirtualHalRuntime(initialState = createVirtualHalS
getCommandScriptFixtureReport(options = {}) { getCommandScriptFixtureReport(options = {}) {
return createVirtualHalCommandScriptFixtureReport({ ...options, halState: state }); return createVirtualHalCommandScriptFixtureReport({ ...options, halState: state });
}, },
getMotionControllerMatrixReport(options = {}) {
return createVirtualHalMotionControllerMatrixReport(options);
},
getIntegrityReport(options = {}) { getIntegrityReport(options = {}) {
return createVirtualHalIntegrityReport({ ...options, halState: state }); return createVirtualHalIntegrityReport({ ...options, halState: state });
}, },

View File

@@ -104,6 +104,7 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
const sourceCompliance = objectOrEmpty(artifactObject.virtualHalSourceCompliance); const sourceCompliance = objectOrEmpty(artifactObject.virtualHalSourceCompliance);
const simConfigSourceCoverage = objectOrEmpty(artifactObject.virtualHalSimConfigSourceCoverage); const simConfigSourceCoverage = objectOrEmpty(artifactObject.virtualHalSimConfigSourceCoverage);
const commandScriptFixtures = objectOrEmpty(artifactObject.virtualHalCommandScriptFixtures); const commandScriptFixtures = objectOrEmpty(artifactObject.virtualHalCommandScriptFixtures);
const motionControllerMatrix = objectOrEmpty(artifactObject.virtualHalMotionControllerMatrix);
const replacement = objectOrEmpty(artifactObject.virtualHalSimulationReplacement); const replacement = objectOrEmpty(artifactObject.virtualHalSimulationReplacement);
const virtualHal = objectOrEmpty(artifactObject.virtualHal); const virtualHal = objectOrEmpty(artifactObject.virtualHal);
const sourceComplianceReady = sourceCompliance.complete === true && const sourceComplianceReady = sourceCompliance.complete === true &&
@@ -115,9 +116,16 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
arrayOrEmpty(commandScriptFixtures.coveredActions).includes("loadusr") && arrayOrEmpty(commandScriptFixtures.coveredActions).includes("loadusr") &&
arrayOrEmpty(commandScriptFixtures.coveredActions).includes("stop") && arrayOrEmpty(commandScriptFixtures.coveredActions).includes("stop") &&
arrayOrEmpty(commandScriptFixtures.sourceFiles).includes("linuxcnc/src/hal/utils/halcmd_commands.cc"); arrayOrEmpty(commandScriptFixtures.sourceFiles).includes("linuxcnc/src/hal/utils/halcmd_commands.cc");
const motionControllerMatrixReady = motionControllerMatrix.complete === true &&
motionControllerMatrix.webSimulationSatisfied === true &&
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");
const replacementReady = replacement.ready === true && const replacementReady = replacement.ready === true &&
replacement.replacesHostRuntimeForSimulation === true && replacement.replacesHostRuntimeForSimulation === true &&
objectOrEmpty(replacement.sourceCompliance).webSimulationSatisfied === true; objectOrEmpty(replacement.sourceCompliance).webSimulationSatisfied === true &&
objectOrEmpty(replacement.motionControllerMatrix).complete === true;
const virtualHalReady = virtualHal.source === "browser-virtual-hal"; const virtualHalReady = virtualHal.source === "browser-virtual-hal";
const missing = [ const missing = [
...(artifactObject.apiName === "real-browser-simulation-diagnostics-artifact" ? [] : ["apiName"]), ...(artifactObject.apiName === "real-browser-simulation-diagnostics-artifact" ? [] : ["apiName"]),
@@ -126,6 +134,7 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
...(sourceComplianceReady ? [] : ["virtualHalSourceCompliance"]), ...(sourceComplianceReady ? [] : ["virtualHalSourceCompliance"]),
...(simConfigSourceCoverageReady ? [] : ["virtualHalSimConfigSourceCoverage"]), ...(simConfigSourceCoverageReady ? [] : ["virtualHalSimConfigSourceCoverage"]),
...(commandScriptFixturesReady ? [] : ["virtualHalCommandScriptFixtures"]), ...(commandScriptFixturesReady ? [] : ["virtualHalCommandScriptFixtures"]),
...(motionControllerMatrixReady ? [] : ["virtualHalMotionControllerMatrix"]),
]; ];
return { return {
apiName: "project-release-browser-diagnostics-artifact-validation", apiName: "project-release-browser-diagnostics-artifact-validation",
@@ -139,10 +148,12 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
sourceComplianceReady, sourceComplianceReady,
simConfigSourceCoverageReady, simConfigSourceCoverageReady,
commandScriptFixturesReady, commandScriptFixturesReady,
motionControllerMatrixReady,
sourceFiles: [...new Set([ sourceFiles: [...new Set([
...arrayOrEmpty(sourceCompliance.sourceFiles), ...arrayOrEmpty(sourceCompliance.sourceFiles),
...arrayOrEmpty(simConfigSourceCoverage.sourceFiles), ...arrayOrEmpty(simConfigSourceCoverage.sourceFiles),
...arrayOrEmpty(commandScriptFixtures.sourceFiles), ...arrayOrEmpty(commandScriptFixtures.sourceFiles),
...arrayOrEmpty(motionControllerMatrix.sourceFiles),
])], ])],
rows: [ rows: [
{ {
@@ -170,6 +181,11 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
label: "Virtual HAL command script fixtures", label: "Virtual HAL command script fixtures",
value: commandScriptFixturesReady ? "ready" : "missing", value: commandScriptFixturesReady ? "ready" : "missing",
}, },
{
id: "motion-controller-matrix",
label: "Virtual HAL motion controller matrix",
value: motionControllerMatrixReady ? "ready" : "missing",
},
{ {
id: "missing", id: "missing",
label: "Missing diagnostics evidence", label: "Missing diagnostics evidence",

View File

@@ -1802,6 +1802,7 @@ M2
createVirtualHalIntegrityReport as createSharedVirtualHalIntegrityReport, createVirtualHalIntegrityReport as createSharedVirtualHalIntegrityReport,
createVirtualHalLimitsHomeState as createSharedVirtualHalLimitsHomeState, createVirtualHalLimitsHomeState as createSharedVirtualHalLimitsHomeState,
createVirtualHalMachineStatusState as createSharedVirtualHalMachineStatusState, createVirtualHalMachineStatusState as createSharedVirtualHalMachineStatusState,
createVirtualHalMotionControllerMatrixReport as createSharedVirtualHalMotionControllerMatrixReport,
createVirtualHalPinRegistry as createSharedVirtualHalPinRegistry, createVirtualHalPinRegistry as createSharedVirtualHalPinRegistry,
createVirtualHalSimConfigSourceCoverageReport as createSharedVirtualHalSimConfigSourceCoverageReport, createVirtualHalSimConfigSourceCoverageReport as createSharedVirtualHalSimConfigSourceCoverageReport,
createVirtualHalSimulationReplacementReport as createSharedVirtualHalSimulationReplacementReport, createVirtualHalSimulationReplacementReport as createSharedVirtualHalSimulationReplacementReport,
@@ -2496,6 +2497,10 @@ M2
return createSharedVirtualHalCommandScriptFixtureReport({ halState: virtualHalState }); return createSharedVirtualHalCommandScriptFixtureReport({ halState: virtualHalState });
} }
function createVirtualHalMotionControllerMatrixReport() {
return createSharedVirtualHalMotionControllerMatrixReport();
}
function renderMachineStatusDom(machineStatus) { function renderMachineStatusDom(machineStatus) {
const statusMap = { const statusMap = {
"spindle-state": machineStatus.spindle.state, "spindle-state": machineStatus.spindle.state,
@@ -2585,6 +2590,7 @@ M2
virtualHalSourceCompliance: createVirtualHalSourceComplianceReport(), virtualHalSourceCompliance: createVirtualHalSourceComplianceReport(),
virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport(), virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport(),
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport(), virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport(),
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport(),
statusHistory: getStatusHistory(), statusHistory: getStatusHistory(),
mdiHistory: getMdiHistory(), mdiHistory: getMdiHistory(),
recentPrograms: getRecentPrograms(), recentPrograms: getRecentPrograms(),
@@ -3890,6 +3896,7 @@ M2
getVirtualHalSourceComplianceReport: () => createVirtualHalSourceComplianceReport(), getVirtualHalSourceComplianceReport: () => createVirtualHalSourceComplianceReport(),
getVirtualHalSimConfigSourceCoverageReport: () => createVirtualHalSimConfigSourceCoverageReport(), getVirtualHalSimConfigSourceCoverageReport: () => createVirtualHalSimConfigSourceCoverageReport(),
getVirtualHalCommandScriptFixtureReport: () => createVirtualHalCommandScriptFixtureReport(), getVirtualHalCommandScriptFixtureReport: () => createVirtualHalCommandScriptFixtureReport(),
getVirtualHalMotionControllerMatrixReport: () => createVirtualHalMotionControllerMatrixReport(),
getVirtualRealtimeHalRuntimeReport: () => createVirtualHalSimulationReplacementReport(), getVirtualRealtimeHalRuntimeReport: () => createVirtualHalSimulationReplacementReport(),
getVirtualHalDroState: () => createVirtualHalDroState(), getVirtualHalDroState: () => createVirtualHalDroState(),
getVirtualHalLimitsHomeState: () => createVirtualHalLimitsHomeState(), getVirtualHalLimitsHomeState: () => createVirtualHalLimitsHomeState(),

View File

@@ -18,6 +18,7 @@ export {
export { export {
VIRTUAL_HAL_AXES, VIRTUAL_HAL_AXES,
VIRTUAL_HAL_AXISUI_PINS, VIRTUAL_HAL_AXISUI_PINS,
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
VIRTUAL_HAL_SIMULATION_REPLACEMENT_TARGETS, VIRTUAL_HAL_SIMULATION_REPLACEMENT_TARGETS,
VIRTUAL_HAL_SIMULATION_RUNTIME_CAPABILITIES, VIRTUAL_HAL_SIMULATION_RUNTIME_CAPABILITIES,
applyVirtualHalAction, applyVirtualHalAction,
@@ -25,6 +26,7 @@ export {
cloneVirtualHalState, cloneVirtualHalState,
createLinuxCncVirtualHalRuntime, createLinuxCncVirtualHalRuntime,
createVirtualHalCommandScriptFixtureReport, createVirtualHalCommandScriptFixtureReport,
createVirtualHalMotionControllerMatrixReport,
createVirtualHalDroState, createVirtualHalDroState,
createVirtualHalIntegrityReport, createVirtualHalIntegrityReport,
createVirtualHalLimitsHomeState, createVirtualHalLimitsHomeState,

View File

@@ -244,6 +244,7 @@
!api?.getVirtualHalSourceComplianceReport || !api?.getVirtualHalSourceComplianceReport ||
!api?.getVirtualHalSimConfigSourceCoverageReport || !api?.getVirtualHalSimConfigSourceCoverageReport ||
!api?.getVirtualHalCommandScriptFixtureReport || !api?.getVirtualHalCommandScriptFixtureReport ||
!api?.getVirtualHalMotionControllerMatrixReport ||
!api?.getVirtualRealtimeHalRuntimeReport !api?.getVirtualRealtimeHalRuntimeReport
) { ) {
throw new Error("simulation API missing browser virtual HAL controls"); throw new Error("simulation API missing browser virtual HAL controls");
@@ -409,6 +410,8 @@
!diagnosticsArtifact.virtualHalSimConfigSourceCoverage?.sourceFiles?.includes("linuxcnc/configs/sim/axis/foam/axis_foam.ini") || !diagnosticsArtifact.virtualHalSimConfigSourceCoverage?.sourceFiles?.includes("linuxcnc/configs/sim/axis/foam/axis_foam.ini") ||
diagnosticsArtifact.virtualHalCommandScriptFixtures?.complete !== true || diagnosticsArtifact.virtualHalCommandScriptFixtures?.complete !== true ||
!diagnosticsArtifact.virtualHalCommandScriptFixtures?.coveredActions?.includes("loadusr") || !diagnosticsArtifact.virtualHalCommandScriptFixtures?.coveredActions?.includes("loadusr") ||
diagnosticsArtifact.virtualHalMotionControllerMatrix?.complete !== true ||
!diagnosticsArtifact.virtualHalMotionControllerMatrix?.sourceFiles?.includes("linuxcnc/src/emc/motion/motion.c") ||
diagnosticsArtifact.limitsHome.source !== "browser-virtual-hal" || diagnosticsArtifact.limitsHome.source !== "browser-virtual-hal" ||
diagnosticsArtifact.preview.renderer !== "threejs" || diagnosticsArtifact.preview.renderer !== "threejs" ||
diagnosticsArtifact.toolTable.state !== "not-loaded" diagnosticsArtifact.toolTable.state !== "not-loaded"
@@ -746,6 +749,18 @@
) { ) {
throw new Error(`AXIS-style virtual motion controller did not step: ${JSON.stringify(motionControllerStep)}`); throw new Error(`AXIS-style virtual motion controller did not step: ${JSON.stringify(motionControllerStep)}`);
} }
const motionControllerMatrix = api.getVirtualHalMotionControllerMatrixReport();
if (
motionControllerMatrix.apiName !== "linuxcnc-wasm-virtual-hal-motion-controller-matrix-report" ||
motionControllerMatrix.complete !== true ||
motionControllerMatrix.webSimulationSatisfied !== true ||
!motionControllerMatrix.requiredPins.includes("motion.distance-to-go") ||
!motionControllerMatrix.requiredPins.includes("motion.in-position") ||
!motionControllerMatrix.sourceFiles.includes("linuxcnc/src/emc/motion/axis.c") ||
!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)}`);
}
const virtualHalReplacement = api.getVirtualHalSimulationReplacementReport(); const virtualHalReplacement = api.getVirtualHalSimulationReplacementReport();
if ( if (
virtualHalReplacement.apiName !== "linuxcnc-wasm-virtual-hal-simulation-replacement-report" || virtualHalReplacement.apiName !== "linuxcnc-wasm-virtual-hal-simulation-replacement-report" ||
@@ -757,8 +772,10 @@
virtualHalReplacement.sourceCompliance?.webSimulationSatisfied !== true || virtualHalReplacement.sourceCompliance?.webSimulationSatisfied !== true ||
virtualHalReplacement.simConfigSourceCoverage?.complete !== true || virtualHalReplacement.simConfigSourceCoverage?.complete !== true ||
virtualHalReplacement.commandScriptFixtures?.complete !== true || virtualHalReplacement.commandScriptFixtures?.complete !== true ||
virtualHalReplacement.motionControllerMatrix?.complete !== true ||
api.getVirtualHalSourceComplianceReport().complete !== true || api.getVirtualHalSourceComplianceReport().complete !== true ||
api.getVirtualHalSourceComplianceReport().commandScriptFixtures?.complete !== true || api.getVirtualHalSourceComplianceReport().commandScriptFixtures?.complete !== true ||
api.getVirtualHalSourceComplianceReport().motionControllerMatrix?.complete !== true ||
!api.getVirtualHalSourceComplianceReport().sourceFiles.includes("linuxcnc/src/emc/motion/motion.c") || !api.getVirtualHalSourceComplianceReport().sourceFiles.includes("linuxcnc/src/emc/motion/motion.c") ||
api.getVirtualHalSimConfigSourceCoverageReport().complete !== true || api.getVirtualHalSimConfigSourceCoverageReport().complete !== true ||
!api.getVirtualHalSimConfigSourceCoverageReport().sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc") || !api.getVirtualHalSimConfigSourceCoverageReport().sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc") ||

View File

@@ -8,6 +8,7 @@ import {
createProjectReleaseReadinessReport, createProjectReleaseReadinessReport,
createVirtualHalSimConfigSourceCoverageReport, createVirtualHalSimConfigSourceCoverageReport,
createVirtualHalCommandScriptFixtureReport, createVirtualHalCommandScriptFixtureReport,
createVirtualHalMotionControllerMatrixReport,
createVirtualHalSimulationReplacementReport, createVirtualHalSimulationReplacementReport,
createVirtualHalSourceComplianceReport, createVirtualHalSourceComplianceReport,
createVirtualHalState, createVirtualHalState,
@@ -25,6 +26,7 @@ const browserDiagnosticsArtifact = {
virtualHalSourceCompliance: createVirtualHalSourceComplianceReport({ halState: virtualHalState }), virtualHalSourceCompliance: createVirtualHalSourceComplianceReport({ halState: virtualHalState }),
virtualHalSimConfigSourceCoverage, virtualHalSimConfigSourceCoverage,
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport({ halState: virtualHalState }), virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport({ halState: virtualHalState }),
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport(),
}; };
assert.equal(createProjectReleaseBrowserDiagnosticsArtifactValidation(browserDiagnosticsArtifact).ready, true); assert.equal(createProjectReleaseBrowserDiagnosticsArtifactValidation(browserDiagnosticsArtifact).ready, true);
const readyArtifactJson = JSON.stringify(createProjectReleaseReadinessReport({ const readyArtifactJson = JSON.stringify(createProjectReleaseReadinessReport({

View File

@@ -34,6 +34,7 @@ import {
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel,
VIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES, VIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES,
VIRTUAL_HAL_COVERAGE_STATES, VIRTUAL_HAL_COVERAGE_STATES,
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
VIRTUAL_HAL_PROJECT_PIN_GROUPS, VIRTUAL_HAL_PROJECT_PIN_GROUPS,
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS, VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES, VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES,
@@ -50,6 +51,7 @@ import {
createLinuxCncInterpSdk, createLinuxCncInterpSdk,
createLinuxCncVirtualHalRuntime, createLinuxCncVirtualHalRuntime,
createVirtualHalIntegrityReport, createVirtualHalIntegrityReport,
createVirtualHalMotionControllerMatrixReport,
createMachineSessionSnapshotPayload, createMachineSessionSnapshotPayload,
createVirtualHalSessionPayload, createVirtualHalSessionPayload,
createMachineSessionPersistenceDisplayViewModel, createMachineSessionPersistenceDisplayViewModel,
@@ -233,6 +235,7 @@ const requiredExports = [
["createVirtualHalBridgeReadiness", createVirtualHalBridgeReadiness], ["createVirtualHalBridgeReadiness", createVirtualHalBridgeReadiness],
["createVirtualHalCommandScriptFixtureReport", createVirtualHalCommandScriptFixtureReport], ["createVirtualHalCommandScriptFixtureReport", createVirtualHalCommandScriptFixtureReport],
["createVirtualHalIntegrityReport", createVirtualHalIntegrityReport], ["createVirtualHalIntegrityReport", createVirtualHalIntegrityReport],
["createVirtualHalMotionControllerMatrixReport", createVirtualHalMotionControllerMatrixReport],
["createVirtualHalPinInventory", createVirtualHalPinInventory], ["createVirtualHalPinInventory", createVirtualHalPinInventory],
["createVirtualHalPinRegistry", createVirtualHalPinRegistry], ["createVirtualHalPinRegistry", createVirtualHalPinRegistry],
["createVirtualHalProjectReport", createVirtualHalProjectReport], ["createVirtualHalProjectReport", createVirtualHalProjectReport],
@@ -501,6 +504,8 @@ assert.match(sdkIndexText, /\bVIRTUAL_HAL_WASM_BRIDGE_FUNCTIONS\b/);
assert.match(sdkReadmeText, /\bVIRTUAL_HAL_WASM_BRIDGE_FUNCTIONS\b/); assert.match(sdkReadmeText, /\bVIRTUAL_HAL_WASM_BRIDGE_FUNCTIONS\b/);
assert.match(sdkIndexText, /\bVIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES\b/); assert.match(sdkIndexText, /\bVIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES\b/);
assert.match(sdkReadmeText, /\bVIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES\b/); assert.match(sdkReadmeText, /\bVIRTUAL_HAL_COMMAND_SCRIPT_FIXTURES\b/);
assert.match(sdkIndexText, /\bVIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES\b/);
assert.match(sdkReadmeText, /\bVIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES\b/);
assert.match(sdkIndexText, /\bVIRTUAL_HAL_PROJECT_PIN_GROUPS\b/); assert.match(sdkIndexText, /\bVIRTUAL_HAL_PROJECT_PIN_GROUPS\b/);
assert.match(sdkReadmeText, /\bVIRTUAL_HAL_PROJECT_PIN_GROUPS\b/); assert.match(sdkReadmeText, /\bVIRTUAL_HAL_PROJECT_PIN_GROUPS\b/);
assert.match(sdkIndexText, /\bVIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS\b/); assert.match(sdkIndexText, /\bVIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS\b/);
@@ -519,6 +524,8 @@ assert.match(sdkIndexText, /\bexecuteVirtualHalcmd\b/);
assert.match(sdkReadmeText, /\bexecuteVirtualHalcmd\b/); assert.match(sdkReadmeText, /\bexecuteVirtualHalcmd\b/);
assert.match(sdkIndexText, /\bcreateVirtualHalCommandScriptFixtureReport\b/); assert.match(sdkIndexText, /\bcreateVirtualHalCommandScriptFixtureReport\b/);
assert.match(sdkReadmeText, /\bcreateVirtualHalCommandScriptFixtureReport\b/); assert.match(sdkReadmeText, /\bcreateVirtualHalCommandScriptFixtureReport\b/);
assert.match(sdkIndexText, /\bcreateVirtualHalMotionControllerMatrixReport\b/);
assert.match(sdkReadmeText, /\bcreateVirtualHalMotionControllerMatrixReport\b/);
assert.match(sdkIndexText, /\bstepVirtualHalMotion\b/); assert.match(sdkIndexText, /\bstepVirtualHalMotion\b/);
assert.match(sdkReadmeText, /\bstepVirtualHalMotion\b/); assert.match(sdkReadmeText, /\bstepVirtualHalMotion\b/);
assert.match(sdkIndexText, /\bstepVirtualHalMotionController\b/); assert.match(sdkIndexText, /\bstepVirtualHalMotionController\b/);
@@ -644,6 +651,19 @@ for (const action of ["setp", "sets", "net", "show", "getp", "gets", "loadrt", "
assert.equal(commandScriptFixtureReport.coveredActions.includes(action), true); assert.equal(commandScriptFixtureReport.coveredActions.includes(action), true);
} }
assert.equal(virtualHalRuntime.getCommandScriptFixtureReport().complete, true); assert.equal(virtualHalRuntime.getCommandScriptFixtureReport().complete, true);
assert.equal(VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES.length >= 3, true);
const motionControllerMatrixReport = createVirtualHalMotionControllerMatrixReport();
assert.equal(motionControllerMatrixReport.apiName, "linuxcnc-wasm-virtual-hal-motion-controller-matrix-report");
assert.equal(motionControllerMatrixReport.complete, true);
assert.equal(motionControllerMatrixReport.webSimulationSatisfied, true);
assert.equal(motionControllerMatrixReport.missingFixtures.length, 0);
assert.equal(motionControllerMatrixReport.sourceFiles.includes("linuxcnc/src/emc/motion/motion.c"), true);
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.rows.some(({ id, inPosition }) => id === "xyz-multi-axis-in-position" && inPosition === true), true);
assert.equal(motionControllerMatrixReport.rows.every(({ axisFeedbackRows }) => axisFeedbackRows.every(({ matched }) => matched)), true);
assert.equal(virtualHalRuntime.getMotionControllerMatrixReport().complete, true);
const steppedVirtualHal = stepVirtualHalMotion(virtualHalRuntime.getState(), { const steppedVirtualHal = stepVirtualHalMotion(virtualHalRuntime.getState(), {
target: { x: 3 }, target: { x: 3 },
maxVelocity: 10, maxVelocity: 10,
@@ -688,6 +708,7 @@ assert.equal(replacementReport.sourceCompliance.complete, true);
assert.equal(replacementReport.sourceCompliance.webSimulationSatisfied, true); assert.equal(replacementReport.sourceCompliance.webSimulationSatisfied, true);
assert.equal(replacementReport.simConfigSourceCoverage.complete, true); assert.equal(replacementReport.simConfigSourceCoverage.complete, true);
assert.equal(replacementReport.commandScriptFixtures.complete, true); assert.equal(replacementReport.commandScriptFixtures.complete, true);
assert.equal(replacementReport.motionControllerMatrix.complete, true);
assert.equal(virtualHalRuntime.getSimulationReplacementReport().ready, true); assert.equal(virtualHalRuntime.getSimulationReplacementReport().ready, true);
const simConfigSourceCoverageReport = createVirtualHalSimConfigSourceCoverageReport({ manifestText: sourceManifestText }); const simConfigSourceCoverageReport = createVirtualHalSimConfigSourceCoverageReport({ manifestText: sourceManifestText });
assert.equal(simConfigSourceCoverageReport.apiName, "linuxcnc-wasm-virtual-hal-sim-config-source-coverage-report"); assert.equal(simConfigSourceCoverageReport.apiName, "linuxcnc-wasm-virtual-hal-sim-config-source-coverage-report");
@@ -715,6 +736,7 @@ assert.equal(sourceComplianceReport.sourceFiles.includes("linuxcnc/src/emc/motio
assert.equal(sourceComplianceReport.sourceFiles.includes("linuxcnc/configs/sim/axis/foam/axis_foam.ini"), true); assert.equal(sourceComplianceReport.sourceFiles.includes("linuxcnc/configs/sim/axis/foam/axis_foam.ini"), true);
assert.equal(sourceComplianceReport.simConfigSourceCoverage.complete, true); assert.equal(sourceComplianceReport.simConfigSourceCoverage.complete, true);
assert.equal(sourceComplianceReport.commandScriptFixtures.complete, true); assert.equal(sourceComplianceReport.commandScriptFixtures.complete, true);
assert.equal(sourceComplianceReport.motionControllerMatrix.complete, true);
assert.equal(virtualHalRuntime.getSourceComplianceReport().complete, true); assert.equal(virtualHalRuntime.getSourceComplianceReport().complete, true);
const virtualHalSessionPayload = createVirtualHalSessionPayload(virtualHalRuntime.getState(), { const virtualHalSessionPayload = createVirtualHalSessionPayload(virtualHalRuntime.getState(), {
simConfigSourceCoverage: simConfigSourceCoverageReport, simConfigSourceCoverage: simConfigSourceCoverageReport,
@@ -744,13 +766,16 @@ const browserDiagnosticsArtifactValidation = createProjectReleaseBrowserDiagnost
virtualHalSourceCompliance: sourceComplianceReport, virtualHalSourceCompliance: sourceComplianceReport,
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport, virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
virtualHalCommandScriptFixtures: commandScriptFixtureReport, virtualHalCommandScriptFixtures: commandScriptFixtureReport,
virtualHalMotionControllerMatrix: motionControllerMatrixReport,
}); });
assert.equal(browserDiagnosticsArtifactValidation.apiName, "project-release-browser-diagnostics-artifact-validation"); assert.equal(browserDiagnosticsArtifactValidation.apiName, "project-release-browser-diagnostics-artifact-validation");
assert.equal(browserDiagnosticsArtifactValidation.ready, true); assert.equal(browserDiagnosticsArtifactValidation.ready, true);
assert.equal(browserDiagnosticsArtifactValidation.sourceComplianceReady, true); assert.equal(browserDiagnosticsArtifactValidation.sourceComplianceReady, true);
assert.equal(browserDiagnosticsArtifactValidation.simConfigSourceCoverageReady, true); assert.equal(browserDiagnosticsArtifactValidation.simConfigSourceCoverageReady, true);
assert.equal(browserDiagnosticsArtifactValidation.commandScriptFixturesReady, true); assert.equal(browserDiagnosticsArtifactValidation.commandScriptFixturesReady, true);
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/hal/utils/halcmd_commands.cc"), true);
assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/src/emc/motion/axis.c"), true);
const runtimeProjectReport = virtualHalRuntime.getProjectReport({ availableFunctions: VIRTUAL_HAL_WASM_BRIDGE_FUNCTIONS }); const runtimeProjectReport = virtualHalRuntime.getProjectReport({ availableFunctions: VIRTUAL_HAL_WASM_BRIDGE_FUNCTIONS });
assert.equal(runtimeProjectReport.simulationRuntime.replacesHostRuntimeForSimulation, true); assert.equal(runtimeProjectReport.simulationRuntime.replacesHostRuntimeForSimulation, true);
assert.equal(runtimeProjectReport.systemCoverage.unclassifiedSnapshotPins.length, 0); assert.equal(runtimeProjectReport.systemCoverage.unclassifiedSnapshotPins.length, 0);