Files
cnc_wams/wasm-port/docs/axis-style-simulation-implementation.md

518 lines
22 KiB
Markdown

# 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:
```text
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:
```text
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()`, and `handleAxisShortcut(event)`;
- 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:
```js
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()`;
- `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:
```bash
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.