Files
cnc_wams/wasm-port/docs/axis-style-simulation-implementation.md
wangdequan 208992c42e 虚拟HAL完全满足Web数控仿真
结论:real simulation page 已将保存的 virtual HAL session snapshot 联动到 release diagnostics artifact,保存或恢复后的 Web CNC 仿真会话可直接输出 release-ready virtual HAL source、sim-config、halcmd fixture 与 motion matrix evidence;该能力仍限于 Web 仿真替代层,不声明 Linux kernel hard-realtime ABI、外部硬件驱动 ABI 或 native HAL module ABI。
2026-06-17 23:07:11 +08:00

22 KiB

AXIS-Style Browser Simulation Implementation Plan

This document defines the implementation plan for evolving runtime/ui/simulation/index.html toward a browser simulation surface inspired by LinuxCNC AXIS. It is a product/UI implementation guide, not permission to reimplement LinuxCNC CNC semantics in JavaScript.

Reference Target

The reference UI is LinuxCNC AXIS with:

  • a top menu and compact icon toolbar;
  • Manual Control and MDI tabs;
  • machine controls for axis selection, jog mode, homing, spindle, coolant, feed/rapid/spindle overrides, jog speed, and max velocity;
  • active G-code modal display;
  • a combined preview/DRO area;
  • a 3D toolpath preview with machine extents and tool marker;
  • DRO rows for relative/absolute position, distance-to-go, work offsets, G92 offsets, tool length offsets, and velocity;
  • a scrollable G-code source pane with active line;
  • a bottom status bar for E-stop, tool, and coordinate mode.

The browser implementation should match the operational shape of AXIS while staying suitable for a web runtime and the current WASM/OPFS architecture.

Non-Negotiable Boundary

LinuxCNC remains the only CNC semantic source.

Browser JavaScript may:

  • render UI layout and interaction state;
  • call the existing LinuxCNC-backed WASM SDK;
  • stage G-code, INI, parameter, and tool-table text into OPFS or the Emscripten filesystem;
  • display LinuxCNC-produced canonical output, motion events, modal state, run status, and validated runtime summaries;
  • animate playback over LinuxCNC-produced motion events.

Browser JavaScript must not implement:

  • G-code interpretation;
  • modal semantics;
  • cutter/tool compensation semantics;
  • parameter semantics;
  • kinematics;
  • remap behavior;
  • planner behavior;
  • canonical motion semantics beyond display mapping of LinuxCNC-produced canonical fields.

Current Baseline

The current simulation page already has:

  • LinuxCNC interpreter WASM execution through createLinuxCncInterpSdk();
  • selectable test programs under runtime/ui/simulation/programs/;
  • custom G-code text and browser File execution through LinuxCNC WASM;
  • editable G-code pane plus run-editor-text workflow;
  • canonical output rendering;
  • program-line rendering;
  • motion table;
  • final and playback axis readout;
  • SVG toolpath preview;
  • reset/step/play/finish playback over LinuxCNC canonical motion events;
  • browser smoke coverage in tests/browser/verify_real_simulation_browser.sh;
  • Node contract coverage in tests/ui/node/verify_real_simulation_programs.sh.

Target Layout

The first AXIS-style browser layout should be a single operator workspace:

menu/toolbar/status badges
┌───────────────────────┬─────────────────────────────────────┐
│ Manual / MDI tabs     │ Preview / DRO tabs                   │
│ Jog controls          │ 3D or 2.5D toolpath viewport          │
│ spindle/coolant       │ DRO overlay / panel                  │
│ overrides/speeds      │ active tool marker                   │
│ active modal codes    │ machine/work extents                 │
├───────────────────────┴─────────────────────────────────────┤
│ G-code source with active execution line                      │
├───────────────────────────────────────────────────────────────┤
│ E-stop | tool | position mode | run state | program state      │
└───────────────────────────────────────────────────────────────┘

The Phase 1 implementation has replaced the former three-column MVP with this AXIS-style shell while preserving the existing LinuxCNC-backed execution and playback APIs.

Implementation Phases

Phase 1: AXIS-Style Shell

Status: implemented.

Build the visual shell around the existing simulation state:

  • menu bar: File, Machine, View, Help;
  • toolbar: open, reload, run, pause, step, stop, reset, zoom controls;
  • left panel tabs: Manual Control and MDI;
  • right panel tabs: Preview and DRO;
  • lower G-code pane;
  • bottom status bar.

Controls may initially be display-only or disabled when no real runtime action exists, but they must show explicit readiness/blocked state.

Validation:

  • browser smoke proves all AXIS-style regions render;
  • current program selection and playback still work;
  • no existing simulation API is removed.

Current implemented regions:

  • data-axis-shell="titlebar";
  • data-axis-shell="menubar";
  • data-axis-shell="toolbar";
  • data-axis-shell="manual-mdi";
  • data-axis-shell="preview-dro";
  • data-axis-shell="gcode-pane";
  • data-axis-shell="machine-state";
  • data-axis-shell="statusbar".

Phase 2: Program Execution Workflow

Status: active; custom text/file/editor execution and OPFS program persistence are implemented. MDI scratch text can now be loaded into the AXIS G-code pane or executed through the same LinuxCNC-backed WASM path.

Upgrade the G-code pane and execution controls:

  • load a selected built-in test program;
  • run through LinuxCNC WASM;
  • reset/step/play/pause/finish playback from toolbar and keyboard-accessible buttons;
  • reload the current built-in, editor, MDI, file, or OPFS-backed program through the same LinuxCNC-backed execution path;
  • highlight active G-code line and current motion row;
  • show run status, source program, motion count, and current frame.
  • load operator-provided G-code text through runProgramText();
  • stage operator-provided G-code text without executing through loadProgramText();
  • load browser File objects through loadProgramFile();
  • edit visible G-code in the AXIS shell and run it through runEditorProgramText();
  • load or run the MDI panel scratch program through LinuxCNC-backed text execution;
  • record successful LinuxCNC-backed MDI executions in an AXIS-style MDI history list, with click-to-restore and clear controls;
  • record successful LinuxCNC-backed built-in, text, editor, file, OPFS, MDI, and session-backed executions in an AXIS-style recent program list, with click-to-stage and clear controls;
  • save the current editor G-code through OPFS with saveProgramToOpfs();
  • load an OPFS G-code program through loadProgramFromOpfs() and execute it through LinuxCNC WASM;

Built-in test programs must live in:

runtime/ui/simulation/programs/

Each program should have its own module and be exported through runtime/ui/simulation/programs/index.js. The simulation renderer should keep importing the inventory through the program index rather than embedding G-code fixtures in simulation-app.js.

Validation:

  • browser smoke runs at least one linear program, one arc program, and one canned-cycle program through toolbar actions;
  • active-line, toolhead, executed path, and status bar update together.
  • browser smoke saves an edited G-code program to OPFS, changes the editor text, reloads the OPFS program, and verifies the reloaded text executes through LinuxCNC WASM.
  • browser smoke verifies loadProgramText() stages text without executing and that MDI text execution produces LinuxCNC canonical output.
  • browser smoke verifies successful MDI execution records history, restores history text into the MDI pane, and clears history without changing LinuxCNC-produced motion state.
  • browser smoke verifies successful LinuxCNC-backed executions populate recent programs, recent entries stage text back into the editor without implicit execution, and the recent list can be cleared.

Phase 3: DRO and Modal Display

Status: partially implemented; actual axis readout and LinuxCNC UPDATE_TAG modal display are implemented.

Add a DRO panel modeled after AXIS:

  • relative actual X/Y/Z/A/B/C;
  • distance-to-go when available from LinuxCNC-produced or validated runtime events;
  • G54 and G92 rows when available from canonical output or runtime summaries;
  • tool length offset rows when available;
  • velocity from playback delta or LinuxCNC-produced runtime field when available;
  • active G-code modal display from LinuxCNC output only.

Fallback values must be marked as unavailable rather than invented.

Current implemented behavior:

  • relative actual X/Y/Z/A/B/C values are rendered from LinuxCNC canonical motion frames;
  • distance-to-go, G54, G92, tool-length offset, and velocity fields render as explicit n/a until LinuxCNC-produced or validated runtime fields are available;
  • modal rows are derived from LinuxCNC canon_event=UPDATE_TAG output;
  • spindle, coolant, tool, and override rows are derived from LinuxCNC canonical events when present and otherwise remain explicit n/a;
  • browser API exposes getDroState(), getModalState(), and getMachineStatusState().

Validation:

  • Node and browser tests verify no unavailable field is silently fabricated;
  • modal/DRO display is derived from LinuxCNC output or explicit unavailable state.

Phase 4: Preview Upgrade

Status: implemented for the current browser simulation scope; AXIS-like Three.js viewport controls are available with SVG fallback state for compatibility tests.

Improve the preview from a simple SVG polyline into an AXIS-like viewport:

  • dark viewport theme;
  • work envelope and extents grid;
  • full path versus executed path;
  • active tool marker;
  • zoom fit / pan / reset view;
  • orthographic 3D using Three.js ^0.183.2, kept stable in browser smoke.

Current implemented behavior:

  • dark viewport theme;
  • full path versus executed path;
  • active tool marker;
  • motion-derived extents rectangle, origin axes/marker, and preview legend;
  • Three.js canvas renders the primary toolpath preview from LinuxCNC canonical motion, while SVG remains a hidden fallback/state surface for compatibility;
  • runtime imports the local runtime/ui/simulation/vendor/three/three.module.js build, with runtime/ui/simulation/package.json documenting the requested three dependency range;
  • Three.js preview includes dynamic grid lines and X/Y/Z axis labels;
  • Three.js preview renders coordinate axes, motion-type segment metadata, active toolhead coordinates, renderer revision, and canvas size into the preview state API for smoke validation;
  • Three.js preview samples ARC_FEED display curves from LinuxCNC-produced canonical center, rotation, active-plane, and endpoint fields, while keeping SVG fallback state endpoint-compatible for existing browser tests;
  • Three.js preview now renders AXIS-style tool geometry with a visible tool body, optional LinuxCNC-produced tool-length-offset indicator, current tool label when available, and a viewport scale bar surfaced through getPreviewState();
  • Three.js preview renders a compact X/Y/Z orientation triad in the viewport and surfaces its structured display state through getPreviewState();
  • AXIS-style preview HUD overlays the Three.js stage with view/zoom/pan, toolhead XYZ, machine envelope, grid step, and renderer/path counts derived from LinuxCNC canonical motion and Three.js render state;
  • AXIS-style bottom status bar is structured into E-stop, tool, program source, active line, position/run mode, and preview state fields, with getAxisStatusbarState() exposing the same browser state for smoke tests;
  • fit, zoom in, zoom out, pan, Top/Front/Side/Iso view modes, and reset view controls;
  • AXIS-style preview layer toggles can show/hide rapid traverse, feed, arc, tool, envelope, and scale-bar display layers without changing the LinuxCNC-produced motion state;
  • Three.js canvas exposes an AXIS-style cursor crosshair and live X/Y preview coordinate readout derived from the current rendered viewBox; this is display state only and does not change machine or G-code state;
  • Three.js canvas supports wheel zoom, pointer-drag pan, and double-click fit;
  • browser resize refreshes the Three.js viewport while preserving playback, zoom, pan, and view-mode state;
  • dedicated desktop/mobile screenshot smoke validates the Three.js viewport, preview legend, diagnostics, compact tool table, status history, and G-code/Machine State layout in real browser viewports;
  • screenshot smoke captures Preview, DRO, and MDI entry states through stable URL view parameters;
  • screenshot smoke can persist desktop/mobile PNGs and screenshot metadata JSON when AXIS_SCREENSHOT_ARTIFACT_DIR is provided; full exportDiagnosticsArtifact() JSON is available behind AXIS_SCREENSHOT_FULL_DIAGNOSTICS=1 for CI jobs that opt into CDP capture;
  • release-readiness artifact generation summarizes persisted AXIS screenshot diagnostics when AXIS_SCREENSHOT_ARTIFACT_DIR points at the screenshot artifact directory, without changing the fixed release gate count;
  • browser API exposes fitPreview(), zoomPreview(factor), panPreview(dx, dy), setPreviewViewMode(mode), getPreviewState(), and resetPreview();
  • browser API exposes getPreviewLayerState() and setPreviewLayer(name, enabled) for AXIS-style display layer controls.
  • browser API exposes getPreviewCursorState() for the current preview cursor/crosshair readout.

Validation:

  • browser smoke verifies nonblank preview, executed path growth, toolhead movement, Three.js canvas pixels, sampled canonical arc rendering, structured tool geometry, scale bar state, AXIS preview layer toggles, and stable viewport controls;
  • browser smoke verifies pointer-driven preview cursor/crosshair coordinate readout and pointer-leave clearing;
  • mobile and desktop screenshot smoke verifies nonblank Three.js rendering, visible compact panels, and non-overlapping AXIS shell sections.

Phase 5: Machine/Session Integration

Status: partially implemented; OPFS machine/session readiness, session staging, and loaded-session program execution are visible in the AXIS shell.

Connect the AXIS-style shell to the existing OPFS/session workflow:

  • load machine session from OPFS;
  • show machine file readiness;
  • show loaded INI/parameter/tool-table/program paths;
  • stage files into WASM before execution;
  • block run controls with explicit reasons when session readiness is missing.

Current implemented behavior:

  • Manual Control panel includes machine id, session id, and G-code filename inputs;
  • Manual Control also renders explicit blocked state for real jog/spindle and coolant controls that are not backed by the browser runtime;
  • Check Session calls existing readMachineSessionReadiness();
  • readiness phase, missing checks, INI path, and G-code path render in the AXIS shell;
  • browser API exposes getMachineReadiness() and checkMachineSessionReadiness(options);
  • AXIS panels show LinuxCNC canonical machine status for spindle, coolant, tool, and override fields when available;
  • Load Session calls existing LinuxCNC-backed loadMachineSessionFromOpfs() after readiness passes;
  • staged INI, parameter, and tool-table WASM paths render in the AXIS shell;
  • browser API exposes getMachineSessionLoadState() and loadReadyMachineSession(options);
  • staged LinuxCNC tool-table load results are summarized in Machine State with OPFS/WASM paths, tool count, and the first loaded tool row;
  • staged LinuxCNC tool-table rows also render in a compact AXIS-style table with T/P/Z/D/comment columns;
  • editor/custom/built-in program execution uses runProgramWithIni() with the loaded session INI path when a session has been staged;
  • toolbar and status bar expose the current run mode as standalone or session-backed with the active INI path;
  • Manual Control exposes a Use Session toggle so a staged machine session can be enabled or bypassed for subsequent runs;
  • Machine State includes a compact run summary for execution mode, session INI, OPFS program path, readiness phase, and session load phase;
  • browser API exposes getRunMode(), setUseLoadedSession(value), and getRunSummary();
  • toolbar and Machine State expose run-control ready/fallback state so operators can see whether a requested session-backed run will actually use a loaded INI or fall back to standalone LinuxCNC WASM;
  • AXIS-style keyboard bindings route F3/F5/F6/F7, run, playback stepping, finish/reset, and preview fit through the same browser API as toolbar controls;
  • Machine State includes a compact diagnostics panel for the last LinuxCNC canonical event, last surfaced error, readiness/load phase, and most recent shortcut action;
  • Machine State includes a compact status-history ring for recent run, readiness, session, OPFS, shortcut, and error events;
  • Machine State includes a compact limits/home panel that explicitly reports n/a until LinuxCNC-produced runtime fields are available;
  • diagnostics can be exported as a structured browser artifact containing run summary, preview state, status history, tool-table summary, and limits/home state;
  • browser API exposes getDiagnosticsState(), getStatusHistory(), getToolTableSummary(), getLimitsHomeState(), exportDiagnosticsArtifact(), exportVirtualHalSessionDiagnosticsArtifact(), and handleAxisShortcut(event);
  • saved virtual HAL session snapshots are linked back into the browser diagnostics artifact as release-ready virtual HAL source, sim-config, halcmd-fixture, and motion-matrix evidence;
  • browser smoke covers run and play/pause keyboard shortcuts after waiting for their async UI/API side effects;
  • browser smoke verifies blocked readiness before OPFS files exist, then writes machine files, G-code, and a session snapshot through existing OPFS helpers and verifies readiness becomes ready;
  • browser smoke verifies a ready machine session stages INI, parameter, and tool-table files into the WASM filesystem through LinuxCNC-backed SDKs.
  • browser smoke verifies editor G-code execution uses the loaded session INI path and still renders LinuxCNC canonical output/playback state.
  • browser smoke verifies OPFS-loaded G-code also uses the loaded session INI path and that run-mode UI/API state switches to session-backed.
  • browser smoke verifies disabling Use Session returns editor execution to standalone mode while leaving the staged session available.
  • browser smoke verifies run summary API/DOM values for standalone, session-backed, and OPFS program execution.
  • browser smoke verifies AXIS URL view parameters can open Manual/MDI and Preview/DRO panels without bypassing the normal tab controls.

Validation:

  • OPFS/session browser smoke covers load -> run -> playback;
  • release gate includes the AXIS-style simulation workflow.

Required APIs

The page should expose a stable browser API under:

window.linuxCncRealSimulationApi

Required methods:

  • getState();
  • getPrograms();
  • runProgramById(programId);
  • reloadCurrentProgram();
  • getPlaybackFrame();
  • isPlaybackRunning();
  • resetPlayback();
  • stepPlayback(delta);
  • play();
  • pause();
  • finishPlayback();
  • runProgramText(programText, metadata);
  • loadProgramText(text, metadata);
  • loadProgramFile(file);
  • getProgramText();
  • setProgramText(text, metadata);
  • runEditorProgramText();
  • runMdiProgramText(text);
  • getMdiHistory();
  • clearMdiHistory();
  • getRecentPrograms();
  • clearRecentPrograms();
  • getOpfsProgramState();
  • saveProgramToOpfs(filename);
  • loadProgramFromOpfs(filename);
  • getDroState();
  • getModalState();
  • getMachineStatusState();
  • fitPreview();
  • zoomPreview(factor);
  • panPreview(dx, dy);
  • setPreviewViewMode(mode);
  • getPreviewState();
  • getPreviewLayerState();
  • setPreviewLayer(name, enabled);
  • getPreviewCursorState();
  • resetPreview();
  • getMachineReadiness();
  • checkMachineSessionReadiness(options);
  • getMachineSessionLoadState();
  • loadReadyMachineSession(options);
  • getRunMode();
  • getRunControlState();
  • getAxisStatusbarState();
  • setUseLoadedSession(value);
  • getRunSummary();
  • getDiagnosticsState();
  • getStatusHistory();
  • getToolTableSummary();
  • getLimitsHomeState();
  • exportDiagnosticsArtifact();
  • exportVirtualHalSessionDiagnosticsArtifact();
  • handleAxisShortcut(event);
  • applyAxisViewFromUrl(search);

API additions must be covered by Node or browser smoke before being relied on by UI controls.

Visual Design Rules

Use the reference as an operational model, not a pixel-perfect clone.

  • Keep controls dense and tool-like.
  • Prefer plain borders, compact buttons, tabs, and status strips.
  • Avoid landing-page composition, marketing cards, oversized hero text, and decorative backgrounds.
  • Keep preview large and central.
  • Keep G-code visible during playback.
  • Keep status and blocked reasons visible without modal interruptions.
  • Use icons where available, but text labels are acceptable until a stable icon dependency exists.

Acceptance Gates

Every implementation batch must keep these passing:

wasm-port/tests/ui/node/verify_real_simulation_programs.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_axis_screenshot_browser.sh
wasm-port/tests/docs/node/verify_real_browser_simulation_priority_docs.sh
wasm-port/tests/host/verify_project_release_gate.sh

When AXIS-style shell work starts, add or extend browser assertions for:

  • menu bar;
  • toolbar;
  • Manual Control tab;
  • MDI tab;
  • Preview tab;
  • DRO tab;
  • active G-code pane;
  • status bar;
  • playback controls driving the same LinuxCNC-backed state as the API.

Immediate Next Batch

Continue AXIS by deepening operator workflow coverage without adding browser-side CNC semantics:

  1. Add limits/home real data mapping only when LinuxCNC-produced runtime fields are available.
  2. Keep unavailable DRO and machine fields explicit n/a until LinuxCNC-produced runtime data exists.
  3. Promote AXIS screenshot artifact summaries into CI retention once the release job has a stable artifact directory.
  4. Harden the optional CDP diagnostics capture path before making full exportDiagnosticsArtifact() retention mandatory in CI.