Expand WASM sim-config staging coverage
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,4 +2,5 @@
|
|||||||
/.codex/
|
/.codex/
|
||||||
/git.txt
|
/git.txt
|
||||||
/text.txt
|
/text.txt
|
||||||
|
/test-results/
|
||||||
/linuxcnc/
|
/linuxcnc/
|
||||||
|
|||||||
@@ -72,6 +72,41 @@ The current aggregate host/WASM/browser smoke command is:
|
|||||||
wasm-port/tests/host/verify_host_smokes.sh
|
wasm-port/tests/host/verify_host_smokes.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Validation Layers
|
||||||
|
|
||||||
|
Use these layers when deciding where a LinuxCNC asset belongs. Do not widen a
|
||||||
|
later layer until the narrower layer has either passed or recorded an explicit
|
||||||
|
expected boundary.
|
||||||
|
|
||||||
|
| Layer | Scope | Entry command | Current result | Expected boundary |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| 1 | `linuxcnc/nc_files` basic G-code smoke | `wasm-port/tests/native/verify_nc_files.sh` | `total: 107`, `pass: 101`, `expected_fail: 6`, `unexpected_fail: 0` | LinuxCNC-native entry-point/context edges only: W-axis machine context, lathe tool/cutter-comp context, upstream O-word syntax edge, and probe runtime context. |
|
||||||
|
| 2 | `linuxcnc/configs/sim` native strict harness | `wasm-port/tests/native/verify_sim_configs.sh` | `total: 159`, `pass: 151`, `expected_fail: 8`, `unexpected_fail: 0` | Native `bin/rs274` cannot provide task/user-M process execution or some INI axis-mask/runtime context. The upstream `incremental_repetition_g533.ngc` demo remains an expected upstream demo edge and must not be made pass by changing G-code semantics. |
|
||||||
|
| 3 | Standalone native runtime probes | `wasm-port/tests/native/verify_native_probes.sh` | Passes with `native probes complete` after source sync, no-standalone-semantics, fixture baseline, sim-config, and `nc_files` checks | Runtime adapters may cover filesystem, HAL/user-M, remap, parameter, tool, kinematics, TP, and WASM/browser boundary behavior, but CNC semantics must still come from vendored LinuxCNC source. |
|
||||||
|
| 4 | WASM Node/browser representative smoke | `wasm-port/tests/host/verify_host_smokes.sh` plus targeted Node/browser commands below | Current targeted checks pass with `sim_configs_wasm_node_smoke=ok`, `nc_files_wasm_node_smoke=ok`, `browser_interp_smoke=ok`, `browser_ini_opfs_smoke=ok`, and aggregate `host_wasm_opfs_browser_smokes=ok` | JS/browser code may stage files, apply executable bits, persist OPFS text, and forward paths to C ABI calls. It must not implement G-code, remap, tool-table, parameter, planner, kinematics, or user-M semantics. |
|
||||||
|
|
||||||
|
Layer 4 is made of focused smoke commands so failures can be isolated before
|
||||||
|
running the aggregate host check:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wasm-port/tests/wasm/node/verify_ini_wasm.sh
|
||||||
|
wasm-port/tests/wasm/node/verify_interp_wasm.sh
|
||||||
|
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
|
||||||
|
wasm-port/tests/wasm/node/verify_nc_files_wasm.sh
|
||||||
|
wasm-port/tests/wasm/node/verify_tp_wasm.sh
|
||||||
|
wasm-port/tests/opfs/node/verify_file_service.sh
|
||||||
|
wasm-port/tests/browser/verify_ini_panel_browser.sh
|
||||||
|
wasm-port/tests/browser/verify_interp_browser.sh
|
||||||
|
wasm-port/tests/host/verify_host_smokes.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Layer 4 sim-config staging uses `planSimConfigStaging()` to collect
|
||||||
|
INI-declared `[DISPLAY]OPEN_FILE`, `[EMCIO]TOOL_TABLE`,
|
||||||
|
`[RS274NGC]PARAMETER_FILE`, `[RS274NGC]SUBROUTINE_PATH`,
|
||||||
|
`[RS274NGC]USER_M_PATH`, and remap-NGC files from the vendored source
|
||||||
|
manifest. That planner is a host filesystem helper only; execution still goes
|
||||||
|
through vendored LinuxCNC interpreter/remap/tool/parameter code.
|
||||||
|
|
||||||
## Validation Chain
|
## Validation Chain
|
||||||
|
|
||||||
The native validation script runs these checks in order:
|
The native validation script runs these checks in order:
|
||||||
@@ -424,13 +459,13 @@ The validation fails if:
|
|||||||
| Harness | Purpose |
|
| Harness | Purpose |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `tests/wasm/node/verify_ini_wasm.sh` | Validates the browser-facing INI WASM module can be built from vendored LinuxCNC `inifile.cc`, loaded through the JS SDK in Node, and queried through the exported C ABI, including LinuxCNC-backed boolean conversion and machine-session file-name string lookup. |
|
| `tests/wasm/node/verify_ini_wasm.sh` | Validates the browser-facing INI WASM module can be built from vendored LinuxCNC `inifile.cc`, loaded through the JS SDK in Node, and queried through the exported C ABI, including LinuxCNC-backed boolean conversion and machine-session file-name string lookup. |
|
||||||
| `tests/wasm/node/verify_interp_wasm.sh` | Validates the interpreter-core WASM module can be built from vendored LinuxCNC interpreter/remap source, loaded through the interpreter JS SDK, run the first fixture group through `Interp::execute()` and selected file fixtures plus vendored upstream `tests/interp` regression files through `Interp::open()`/`read()`/`execute()`, match the native canonical event plus required state readback fixtures, run vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo files through the WASM C ABI/SDK path, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. |
|
| `tests/wasm/node/verify_interp_wasm.sh` | Validates the interpreter-core WASM module can be built from vendored LinuxCNC interpreter/remap source, loaded through the interpreter JS SDK, run the first fixture group through `Interp::execute()` and selected file fixtures plus vendored upstream `tests/interp` regression files through `Interp::open()`/`read()`/`execute()`, match the native canonical event plus required state readback fixtures, emit `run_step` execution-status records with LinuxCNC line number, encoded source statement, return code, and interpreter axis positions for file execution, run vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo files through the WASM C ABI/SDK path, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. |
|
||||||
| `tests/wasm/node/verify_sim_configs_wasm.sh` | Validates representative vendored LinuxCNC `configs/sim` programs in Node WASM through `runSimConfigProgram()`, copying `axis/foam`, `axis/geometry`, and `axis/external_offsets` INI/G-code/user-M assets into the Emscripten filesystem before forwarding to `runFileWithIni()`, plus bridge-mill `5axis.ini`, tool table, `remap_subs/*.ngc`, and `5axisgui.ngc` before forwarding to `runFiveAxisRemapFile()`. This covers INI-driven `U/V/W` axis mask handling, real `USER_M_PATH` registration for executable `M110`/`M111`, and vendored LinuxCNC bridge-mill NGC remap execution without spawning host processes. |
|
| `tests/wasm/node/verify_sim_configs_wasm.sh` | Validates representative vendored LinuxCNC `configs/sim` programs in Node WASM through `planSimConfigStaging()` plus `runSimConfigProgram()`. The staging planner uses INI text and `tools/source-manifest.txt` to collect the program, INI, tool table, parameter file when vendored, `SUBROUTINE_PATH` files, `USER_M_PATH` files, and remap-NGC files before forwarding to `runFileWithIni()` or `runFiveAxisRemapFile()`. This covers INI-driven `U/V/W` axis mask handling, real `USER_M_PATH` registration for executable `M110`/`M111`, all four current external-offset M111 expected-failure programs, `SUBROUTINE_PATH` staging for `opa_demo.ngc -> circles.ngc`, bridge-mill remap-subroutine staging, and vendored LinuxCNC bridge-mill NGC remap execution without spawning host processes. The same smoke includes a synthetic staging-plan assertion for `TOOL_TABLE`, `PARAMETER_FILE`, `SUBROUTINE_PATH`, and `USER_M_PATH` collection. |
|
||||||
| `tests/wasm/node/verify_nc_files_wasm.sh` | Validates representative vendored LinuxCNC `nc_files` examples in Node WASM by copying `arcspiral.ngc`, `hole-circle.ngc`, `factorial.ngc`, and `m6demo.ngc` into the Emscripten filesystem and forwarding to the LinuxCNC-backed `Interp::open()`/`read()`/`execute()` path. JavaScript only stages files and checks LinuxCNC output; it does not implement G-code, O-word, tool-change, or M-code behavior. |
|
| `tests/wasm/node/verify_nc_files_wasm.sh` | Validates representative vendored LinuxCNC `nc_files` examples in Node WASM by copying `3D_Chips.ngc`, `arcspiral.ngc`, `hole-circle.ngc`, `factorial.ngc`, and `m6demo.ngc` into the Emscripten filesystem and forwarding to the LinuxCNC-backed `Interp::open()`/`read()`/`execute()` path. `3D_Chips.ngc` is staged with a minimal INI-declared `tool.tbl` because the upstream program contains `T1 M6`; JavaScript only stages files and checks LinuxCNC output, including `run_step` status records, and does not implement G-code, O-word, tool-change, or M-code behavior. |
|
||||||
| `tests/wasm/node/verify_tp_wasm.sh` | Validates a standalone trajectory-planner WASM module can be built from vendored LinuxCNC TP/TC/Ruckig support source, loaded in Node, and run the same linear, arc, and queued-line planner probe paths covered by the native TP harness. |
|
| `tests/wasm/node/verify_tp_wasm.sh` | Validates a standalone trajectory-planner WASM module can be built from vendored LinuxCNC TP/TC/Ruckig support source, loaded in Node, and run the same linear, arc, and queued-line planner probe paths covered by the native TP harness. |
|
||||||
| `tests/opfs/node/verify_file_service.sh` | Validates the host-owned OPFS text-file adapter, path model, session snapshot store including custom filenames and envelope/path rejection paths, machine file store, G-code text store including filename rejection paths, OPFS-to-WASM parameter/tool-table bridges, and grouped machine-session loading without moving file persistence, parameter semantics, or tool-table semantics into the WASM core. |
|
| `tests/opfs/node/verify_file_service.sh` | Validates the host-owned OPFS text-file adapter, path model, session snapshot store including custom filenames and envelope/path rejection paths, machine file store, G-code text store including filename rejection paths, OPFS-to-WASM parameter/tool-table bridges, and grouped machine-session loading without moving file persistence, parameter semantics, or tool-table semantics into the WASM core. |
|
||||||
| `tests/browser/verify_ini_panel_browser.sh` | Validates the INI SDK, INI/interpreter WASM module loading, LinuxCNC-backed INI machine-session file-name string lookup, OPFS text-file round trip, generic session snapshot round trip plus custom filename and envelope/path rejection paths, machine file text round trip, G-code text round trip plus filename rejection paths, and the INI panel UI's machine-session load with default OPFS parameter/tool-table file mapping, G-code run, canonical-event display paths, and 5-axis remap demo action in a real browser runtime. |
|
| `tests/browser/verify_ini_panel_browser.sh` | Validates the INI SDK, INI/interpreter WASM module loading, LinuxCNC-backed INI machine-session file-name string lookup, OPFS text-file round trip, generic session snapshot round trip plus custom filename and envelope/path rejection paths, machine file text round trip, G-code text round trip plus filename rejection paths, and the INI panel UI's machine-session load with default OPFS parameter/tool-table file mapping, G-code run, `run_step`-backed progress/line/statement/axis display, canonical-event display paths, and 5-axis remap demo action in a real browser runtime. |
|
||||||
| `tests/browser/verify_interp_browser.sh` | Validates the interpreter-core WASM module loads through the interpreter JS SDK in a real browser runtime and runs selected positive and negative canonical fixtures plus vendored upstream `tests/interp` regression files through vendored LinuxCNC `Interp::execute()` and `Interp::open()`/`read()`/`execute()` via the exported C ABI, including direct browser SDK and OPFS-backed parameter-file restore/save, non-random/random tool-table load/save through vendored LinuxCNC source, vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo execution, representative vendored `configs/sim` `foam`, `geometry`, `external_offsets`, and bridge-mill programs through `runSimConfigProgram()`, and representative vendored `nc_files` examples through `runFile()`. |
|
| `tests/browser/verify_interp_browser.sh` | Validates the interpreter-core WASM module loads through the interpreter JS SDK in a real browser runtime and runs selected positive and negative canonical fixtures plus vendored upstream `tests/interp` regression files through vendored LinuxCNC `Interp::execute()` and `Interp::open()`/`read()`/`execute()` via the exported C ABI, including direct browser SDK and OPFS-backed parameter-file restore/save, non-random/random tool-table load/save through vendored LinuxCNC source, vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo execution, representative vendored `configs/sim` `foam`, `geometry`, `external_offsets`, and bridge-mill programs through `runSimConfigProgram()`, and representative vendored `nc_files` examples through `runFile()` or `runFileWithIni()` when the upstream file requires INI/tool-table context. |
|
||||||
| `tests/host/verify_host_smokes.sh` | Runs the current host-side Node, WASM interpreter-core, WASM trajectory-planner, OPFS, and browser smoke validation with shared WASM builds. |
|
| `tests/host/verify_host_smokes.sh` | Runs the current host-side Node, WASM interpreter-core, WASM trajectory-planner, OPFS, and browser smoke validation with shared WASM builds. |
|
||||||
|
|
||||||
## Fixture Coverage
|
## Fixture Coverage
|
||||||
@@ -752,17 +787,21 @@ canned-cycle, state-tag motion, tool-table setup, and O-word subroutine
|
|||||||
fixtures, plus threading/rigid tap, NURBS dispatch boundaries, and the
|
fixtures, plus threading/rigid tap, NURBS dispatch boundaries, and the
|
||||||
comparable canonical runtime edge and program-end cleanup calls. The
|
comparable canonical runtime edge and program-end cleanup calls. The
|
||||||
standalone vendored-source harness, Node WASM smoke, and browser smoke also
|
standalone vendored-source harness, Node WASM smoke, and browser smoke also
|
||||||
pin `coordinate_offsets` MDI/file-path, `feed_control_modes`, the
|
pin `coordinate_offsets` MDI/file-path, `feed_control_modes`, `run_step`
|
||||||
|
file-execution status output for line number, URI-encoded source statement,
|
||||||
|
return code, and current interpreter axis positions, the
|
||||||
`position_params` MDI/file-path, `tool_semantics`, and `canon_runtime_edges`
|
`position_params` MDI/file-path, `tool_semantics`, and `canon_runtime_edges`
|
||||||
post-program modal, override, spindle, mist, and flood `_setup` state. Native
|
post-program modal, override, spindle, mist, and flood `_setup` state. Native
|
||||||
and WASM standalone checks also cover the user M-code registration boundary for
|
and WASM standalone checks also cover the user M-code registration boundary for
|
||||||
INI-declared `M110`/`M111` handlers while keeping process execution outside the
|
INI-declared `M110`/`M111` handlers while keeping process execution outside the
|
||||||
browser/WASM runtime. Node and browser WASM sim-config coverage now run the real
|
browser/WASM runtime. Node and browser WASM sim-config coverage now run the real
|
||||||
vendored `axis/geometry/xyzc.ngc` and
|
vendored `axis/geometry/xyzc.ngc` and the
|
||||||
`axis/external_offsets/dyn_demo.ngc` programs with their executable
|
`axis/external_offsets/dyn_demo.ngc`, `eoffsets.ngc`, `jwp_z.ngc`, and
|
||||||
`M110`/`M111` files, `axis/foam/foam.ngc` with its `U/V` machine
|
`opa_demo.ngc` programs with their executable `M110`/`M111` files,
|
||||||
configuration, and bridge-mill `5axisgui.ngc` with its `W` machine
|
`opa_demo.ngc`'s `SUBROUTINE_PATH` dependency on `circles.ngc`,
|
||||||
coordinates. The same upstream baseline also
|
`axis/foam/foam.ngc` with its `U/V` machine configuration and shared
|
||||||
|
`axis/sim.tbl` tool table staged beside the INI, and
|
||||||
|
bridge-mill `5axisgui.ngc` with its `W` machine coordinates. The same upstream baseline also
|
||||||
validates the current negative fixture error text and absent canonical-event
|
validates the current negative fixture error text and absent canonical-event
|
||||||
constraints. Fixtures that depend on standalone-only runtime
|
constraints. Fixtures that depend on standalone-only runtime
|
||||||
adapters, HAL state, upstream `rs274` output gaps such as
|
adapters, HAL state, upstream `rs274` output gaps such as
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ semantic rewrites:
|
|||||||
| Go math C/C++ linkage | `genserkins` runtime probing compiles vendored `gomath.c` through a narrow C++ wrapper so LinuxCNC `genserfuncs.c` can link to the upstream Go math symbols without editing vendored source. |
|
| Go math C/C++ linkage | `genserkins` runtime probing compiles vendored `gomath.c` through a narrow C++ wrapper so LinuxCNC `genserfuncs.c` can link to the upstream Go math symbols without editing vendored source. |
|
||||||
| Switchkins iterative forward | `genhexkins` runtime probing follows LinuxCNC switchkins iterative-forward behavior, including the first-call warmup path before asserting roundtrip convergence. |
|
| Switchkins iterative forward | `genhexkins` runtime probing follows LinuxCNC switchkins iterative-forward behavior, including the first-call warmup path before asserting roundtrip convergence. |
|
||||||
| Browser storage | OPFS remains outside the native core; `runtime/opfs/file-service.js` owns browser text-file persistence, `runtime/opfs/path-model.js` owns host-side storage paths for INI, tool table, parameter, G-code, preview-cache, and session-snapshot content, `runtime/opfs/snapshot-store.js` owns generic JSON session snapshot persistence, `runtime/opfs/machine-file-store.js` owns pure-text machine-file and G-code persistence, `runtime/opfs/linuxcnc-parameter-bridge.js` only copies parameter files between OPFS text storage and the LinuxCNC-backed WASM parameter-file ABI, `runtime/opfs/linuxcnc-tool-table-bridge.js` only copies tool tables between OPFS text storage and the LinuxCNC-backed WASM tool-table ABI, and `runtime/opfs/linuxcnc-machine-session-bridge.js` groups INI, parameter, and tool-table loading while using the LinuxCNC-backed INI SDK for `[EMCIO]RANDOM_TOOLCHANGER`, `[RS274NGC]PARAMETER_FILE`, and `[EMCIO]TOOL_TABLE` when available; explicit host session file-name options take precedence over INI-derived file names, missing INI file-name values fall back to host default parameter/tool-table paths, and path validation remains owned by the OPFS path model, including rejection of traversal or nested path segments from INI-derived file names. |
|
| Browser storage | OPFS remains outside the native core; `runtime/opfs/file-service.js` owns browser text-file persistence, `runtime/opfs/path-model.js` owns host-side storage paths for INI, tool table, parameter, G-code, preview-cache, and session-snapshot content, `runtime/opfs/snapshot-store.js` owns generic JSON session snapshot persistence, `runtime/opfs/machine-file-store.js` owns pure-text machine-file and G-code persistence, `runtime/opfs/linuxcnc-parameter-bridge.js` only copies parameter files between OPFS text storage and the LinuxCNC-backed WASM parameter-file ABI, `runtime/opfs/linuxcnc-tool-table-bridge.js` only copies tool tables between OPFS text storage and the LinuxCNC-backed WASM tool-table ABI, and `runtime/opfs/linuxcnc-machine-session-bridge.js` groups INI, parameter, and tool-table loading while using the LinuxCNC-backed INI SDK for `[EMCIO]RANDOM_TOOLCHANGER`, `[RS274NGC]PARAMETER_FILE`, and `[EMCIO]TOOL_TABLE` when available; explicit host session file-name options take precedence over INI-derived file names, missing INI file-name values fall back to host default parameter/tool-table paths, and path validation remains owned by the OPFS path model, including rejection of traversal or nested path segments from INI-derived file names. |
|
||||||
| Sim-config SDK staging | `runtime/sdk/src/linuxcnc-interp.js` exposes `runSimConfigProgram()` as a host-boundary convenience only. It writes caller-provided text files into the Emscripten filesystem, applies executable bits for user M-code files, and forwards to existing LinuxCNC-backed C ABI entry points such as `runFileWithIni()` or `runFiveAxisRemapFile()`; it does not implement interpreter, axis, remap, or user M-code semantics. |
|
| Sim-config SDK staging | `runtime/sdk/src/sim-config-staging.js` exposes `planSimConfigStaging()` as a host-boundary file planner for representative vendored `configs/sim` programs. It reads INI text plus `tools/source-manifest.txt` to collect `[DISPLAY]OPEN_FILE`, `[EMCIO]TOOL_TABLE`, `[RS274NGC]PARAMETER_FILE`, `[RS274NGC]SUBROUTINE_PATH`, `[RS274NGC]USER_M_PATH`, and remap-NGC files for staging. `runtime/sdk/src/linuxcnc-interp.js` exposes `runSimConfigProgram()` as the execution convenience only: it writes planned text files into the Emscripten filesystem, applies executable bits for user M-code files, and forwards to existing LinuxCNC-backed C ABI entry points such as `runFileWithIni()` or `runFiveAxisRemapFile()`; neither helper implements interpreter, axis, remap, tool, parameter, or user M-code semantics. |
|
||||||
|
|
||||||
## Enforced Non-Drift Rules
|
## Enforced Non-Drift Rules
|
||||||
|
|
||||||
|
|||||||
@@ -48,19 +48,20 @@ wasm-port/tests/host/verify_host_smokes.sh
|
|||||||
| Reject standalone CNC semantics | Done | `tools/verify_no_standalone_cnc_semantics.sh` guards project-owned `Interp::...` definitions outside documented runtime-edge stubs. |
|
| Reject standalone CNC semantics | Done | `tools/verify_no_standalone_cnc_semantics.sh` guards project-owned `Interp::...` definitions outside documented runtime-edge stubs. |
|
||||||
| Maintain source reuse map | Done | Current sim-config, remap, interpreter, kinematics, TP, user-M, tool, named-parameter, and OPFS runtime boundaries are recorded in `docs/source-reuse-map.md`; keep updating it whenever LinuxCNC source, test assets, or runtime boundaries are added. |
|
| Maintain source reuse map | Done | Current sim-config, remap, interpreter, kinematics, TP, user-M, tool, named-parameter, and OPFS runtime boundaries are recorded in `docs/source-reuse-map.md`; keep updating it whenever LinuxCNC source, test assets, or runtime boundaries are added. |
|
||||||
| Maintain compatibility validation notes | Done | Current native, Node WASM, browser, OPFS, and host aggregate checks are recorded in `docs/compatibility-validation.md`; keep updating it whenever a validation command or fixture class is added. |
|
| Maintain compatibility validation notes | Done | Current native, Node WASM, browser, OPFS, and host aggregate checks are recorded in `docs/compatibility-validation.md`; keep updating it whenever a validation command or fixture class is added. |
|
||||||
|
| Document validation layers | Done | `docs/compatibility-validation.md` now records Layer 1 `nc_files` basic smoke, Layer 2 `configs/sim` native strict harness, Layer 3 standalone native runtime probes, and Layer 4 WASM Node/browser representative smokes with entry commands, current results, expected boundaries, and the no-LinuxCNC-semantics rule. |
|
||||||
| Build LinuxCNC test inventory | In progress | `linuxcnc/tests/remap` has been inventoried by dependency class; the first broader `linuxcnc/tests` pass now records full-process, HAL/realtime, linuxcncrsh, Python-binding, and external-component families in the blocked table. |
|
| Build LinuxCNC test inventory | In progress | `linuxcnc/tests/remap` has been inventoried by dependency class; the first broader `linuxcnc/tests` pass now records full-process, HAL/realtime, linuxcncrsh, Python-binding, and external-component families in the blocked table. |
|
||||||
| Prefer pure interpreter tests first | In progress | Continue with tests that can run through `Interp::open()`, `read()`, and `execute()` without realtime hardware or GUI. |
|
| Prefer pure interpreter tests first | In progress | Continue with tests that can run through `Interp::open()`, `read()`, and `execute()` without realtime hardware or GUI. |
|
||||||
| Add upstream-output comparison | In progress | Use upstream `../linuxcnc/bin/rs274` or original `test.sh` output where practical, then compare against native/WASM/browser output. |
|
| Add upstream-output comparison | In progress | Use upstream `../linuxcnc/bin/rs274` or original `test.sh` output where practical, then compare against native/WASM/browser output. |
|
||||||
| Promote tests through three layers | In progress | Add each selected test first to native harnesses, then WASM Node, then browser smoke where meaningful. |
|
| Promote tests through three layers | In progress | Add each selected test first to native harnesses, then WASM Node, then browser smoke where meaningful. |
|
||||||
| Record blocked tests | In progress | First broader family-level blocked batch is recorded below; continue expanding it as each `linuxcnc/tests` family is inspected. |
|
| Record blocked tests | In progress | First broader family-level blocked batch is recorded below; continue expanding it as each `linuxcnc/tests` family is inspected. |
|
||||||
| Add aggregate smoke coverage | Done | `tests/host/verify_host_smokes.sh` now runs stable Node WASM, sim-config WASM, `nc_files` WASM, OPFS, and browser smoke checks with shared builds. Current run passed with `host_wasm_opfs_browser_smokes=ok`. |
|
| Add aggregate smoke coverage | Done | `tests/host/verify_host_smokes.sh` now runs stable Node WASM, sim-config WASM, `nc_files` WASM, OPFS, and browser smoke checks with shared builds. Current run passed with `host_wasm_opfs_browser_smokes=ok`. |
|
||||||
| Add `linuxcnc/nc_files` basic examples | Done | `tests/native/verify_nc_files.sh` now runs the basic/example subset of upstream `linuxcnc/nc_files` through LinuxCNC `bin/rs274`; current native baseline is 107 total, 101 pass, 6 expected context/entry-point edges, 0 unexpected failures. Exploratory `--all` inventory is 247 total, 219 pass, 28 expected context/entry-point edges, 0 unexpected failures. A representative vendored subset now passes Node WASM and browser execution through LinuxCNC-backed `Interp::open()`/`read()`/`execute()`. |
|
| Add `linuxcnc/nc_files` basic examples | Done | `tests/native/verify_nc_files.sh` now runs the basic/example subset of upstream `linuxcnc/nc_files` through LinuxCNC `bin/rs274`; current native baseline is 107 total, 101 pass, 6 expected context/entry-point edges, 0 unexpected failures. Exploratory `--all` inventory is 247 total, 219 pass, 28 expected context/entry-point edges, 0 unexpected failures. A representative vendored subset now passes Node WASM and browser execution through LinuxCNC-backed `Interp::open()`/`read()`/`execute()`, with `3D_Chips.ngc` using an INI-declared tool-table context for its upstream `T1 M6` line. |
|
||||||
|
|
||||||
## LinuxCNC Test Asset Queue
|
## LinuxCNC Test Asset Queue
|
||||||
|
|
||||||
| LinuxCNC test path | Status | Current target | Notes |
|
| LinuxCNC test path | Status | Current target | Notes |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `nc_files` basic/example programs | Done | Native, WASM Node, browser | Native coverage is tracked by `wasm-port/tests/native/verify_nc_files.sh`; complete programs execute strictly, macro/library files are wrapped with temporary `M2` for load/parse validation, and six known LinuxCNC-native context edges are classified explicitly. `--all` also inventories probe/plasmac/NURBS files and currently classifies all 28 non-passing files as expected runtime-context or entry-point edges. The representative vendored WASM/browser subset covers `arcspiral.ngc`, `hole-circle.ngc`, `factorial.ngc`, and `m6demo.ngc` through LinuxCNC-backed file execution only. |
|
| `nc_files` basic/example programs | Done | Native, WASM Node, browser | Native coverage is tracked by `wasm-port/tests/native/verify_nc_files.sh`; complete programs execute strictly, macro/library files are wrapped with temporary `M2` for load/parse validation, and six known LinuxCNC-native context edges are classified explicitly. `--all` also inventories probe/plasmac/NURBS files and currently classifies all 28 non-passing files as expected runtime-context or entry-point edges. The representative vendored WASM/browser subset covers `3D_Chips.ngc`, `arcspiral.ngc`, `hole-circle.ngc`, `factorial.ngc`, and `m6demo.ngc` through LinuxCNC-backed file execution, with `3D_Chips.ngc` staged through `runFileWithIni()` and an INI-declared `tool.tbl` instead of being judged without its required tool context. |
|
||||||
| `tests/remap/duplicate-o-word` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word`; validates duplicate O-word behavior through vendored LinuxCNC remap/O-word/file execution paths. |
|
| `tests/remap/duplicate-o-word` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word`; validates duplicate O-word behavior through vendored LinuxCNC remap/O-word/file execution paths. |
|
||||||
| `tests/remap/fail/args.0` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/fail/args.0`; validates required `P`/`Q` remap arguments when both are present through vendored LinuxCNC remap argument handling. |
|
| `tests/remap/fail/args.0` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/fail/args.0`; validates required `P`/`Q` remap arguments when both are present through vendored LinuxCNC remap argument handling. |
|
||||||
| `tests/remap/fail/args.1` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/fail/args.1`; validates LinuxCNC missing-`Q` remap error text and upstream-style continue-after-error flow. |
|
| `tests/remap/fail/args.1` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/fail/args.1`; validates LinuxCNC missing-`Q` remap error text and upstream-style continue-after-error flow. |
|
||||||
@@ -92,7 +93,7 @@ wasm-port/tests/host/verify_host_smokes.sh
|
|||||||
| `tests/interp/abort-hot-comment` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment`; validates LinuxCNC `(ABORT,...)` hot-comment parameter expansion for numbered, named, and INI named parameters through vendored file execution paths and `INI_FILE_NAME`. |
|
| `tests/interp/abort-hot-comment` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment`; validates LinuxCNC `(ABORT,...)` hot-comment parameter expansion for numbered, named, and INI named parameters through vendored file execution paths and `INI_FILE_NAME`. |
|
||||||
| `configs/sim/axis/foam/foam.ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/configs/sim/axis/foam`; validates LinuxCNC INI-driven `U/V` axis mask handling through `axis_foam.ini` and vendored file execution paths. |
|
| `configs/sim/axis/foam/foam.ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/configs/sim/axis/foam`; validates LinuxCNC INI-driven `U/V` axis mask handling through `axis_foam.ini` and vendored file execution paths. |
|
||||||
| `configs/sim/axis/geometry/xyzc.ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/configs/sim/axis/geometry`; validates LinuxCNC `USER_M_PATH` registration with the real executable `M110` while process execution remains a deterministic standalone `USER_M_COMMAND` boundary. |
|
| `configs/sim/axis/geometry/xyzc.ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/configs/sim/axis/geometry`; validates LinuxCNC `USER_M_PATH` registration with the real executable `M110` while process execution remains a deterministic standalone `USER_M_COMMAND` boundary. |
|
||||||
| `configs/sim/axis/external_offsets/dyn_demo.ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets`; validates LinuxCNC `USER_M_PATH` registration with the real executable `M111` against an upstream sim program while process execution remains a deterministic standalone boundary. |
|
| `configs/sim/axis/external_offsets/*.ngc` M111 demos | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets`; validates `dyn_demo.ngc`, `eoffsets.ngc`, `jwp_z.ngc`, and `opa_demo.ngc` with their corresponding INI files, real executable `M111`, shared `eoffset.tbl`, and `opa_demo.ngc`'s `circles.ngc` subroutine while process execution remains a deterministic standalone boundary. |
|
||||||
| More `tests/remap/*` interpreter-only cases | Planned | Native first | Select cases that do not require Python behavior beyond documented runtime-edge stubs unless the required LinuxCNC source path is ported. |
|
| More `tests/remap/*` interpreter-only cases | Planned | Native first | Select cases that do not require Python behavior beyond documented runtime-edge stubs unless the required LinuxCNC source path is ported. |
|
||||||
| More `tests/interp/*` interpreter-only cases | Planned | Native first | Select upstream interpreter cases that can run through vendored file execution without Python, HAL, realtime motion, or GUI. |
|
| More `tests/interp/*` interpreter-only cases | Planned | Native first | Select upstream interpreter cases that can run through vendored file execution without Python, HAL, realtime motion, or GUI. |
|
||||||
| `tests/rs274ngc/*` candidates | Planned | Native first | Use upstream `rs274` as the baseline where output is comparable. |
|
| `tests/rs274ngc/*` candidates | Planned | Native first | Use upstream `rs274` as the baseline where output is comparable. |
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ remap_subroutine: PASS 65, FAIL 0
|
|||||||
Remaining failures are explicit LinuxCNC-native baseline edges:
|
Remaining failures are explicit LinuxCNC-native baseline edges:
|
||||||
|
|
||||||
- `axis/external_offsets/*`: 4 failures from sim-only user M-codes `M111`.
|
- `axis/external_offsets/*`: 4 failures from sim-only user M-codes `M111`.
|
||||||
|
The native harness now resolves the corresponding INI by
|
||||||
|
`[DISPLAY]OPEN_FILE`, so `eoffsets.ngc`, `jwp_z.ngc`, and `opa_demo.ngc`
|
||||||
|
are no longer judged through `dynamic_offsets.ini`.
|
||||||
- `axis/geometry/xyzc.ngc`: 1 failure from sim-only user M-code `M110`.
|
- `axis/geometry/xyzc.ngc`: 1 failure from sim-only user M-code `M110`.
|
||||||
- `axis/foam/foam.ngc`: 1 failure from missing `U/V` axis support in the
|
- `axis/foam/foam.ngc`: 1 failure from missing `U/V` axis support in the
|
||||||
LinuxCNC `bin/rs274` entry point.
|
LinuxCNC `bin/rs274` entry point.
|
||||||
@@ -392,9 +395,11 @@ ABI paths. They cover:
|
|||||||
WASM.
|
WASM.
|
||||||
- `axis/geometry/xyzc.ngc` with `xyzc.ini` and real executable `M110`, verifying
|
- `axis/geometry/xyzc.ngc` with `xyzc.ini` and real executable `M110`, verifying
|
||||||
`USER_M_PATH` registration in WASM.
|
`USER_M_PATH` registration in WASM.
|
||||||
- `axis/external_offsets/dyn_demo.ngc` with `dynamic_offsets.ini` and real
|
- `axis/external_offsets/dyn_demo.ngc`, `eoffsets.ngc`, `jwp_z.ngc`, and
|
||||||
executable `M111`, verifying the same user-M boundary against an upstream sim
|
`opa_demo.ngc` with their corresponding INI files, real executable `M111`,
|
||||||
program.
|
shared `eoffset.tbl`, and `opa_demo.ngc`'s `circles.ngc` subroutine,
|
||||||
|
verifying the same user-M and `SUBROUTINE_PATH` boundaries against upstream
|
||||||
|
sim programs.
|
||||||
|
|
||||||
Completion checks:
|
Completion checks:
|
||||||
|
|
||||||
@@ -457,7 +462,8 @@ programs.
|
|||||||
3. Update `tools/source-manifest.txt` and `tools/verify_vendor_sync.sh` if new
|
3. Update `tools/source-manifest.txt` and `tools/verify_vendor_sync.sh` if new
|
||||||
LinuxCNC files are copied into `wasm-port/vendor/linuxcnc`. Done for the
|
LinuxCNC files are copied into `wasm-port/vendor/linuxcnc`. Done for the
|
||||||
representative `axis/foam`, `axis/geometry`, and `axis/external_offsets`
|
representative `axis/foam`, `axis/geometry`, and `axis/external_offsets`
|
||||||
sim-config files; no `verify_vendor_sync.sh` logic change was needed.
|
sim-config files, including the remaining external-offset M111 programs and
|
||||||
|
`circles.ngc`; no `verify_vendor_sync.sh` logic change was needed.
|
||||||
|
|
||||||
4. Preserve the latest result summary as a machine-readable artifact, but do
|
4. Preserve the latest result summary as a machine-readable artifact, but do
|
||||||
not commit generated logs unless they are intentionally used as fixtures.
|
not commit generated logs unless they are intentionally used as fixtures.
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ Current validation is intentionally mechanical:
|
|||||||
| Switchable 5-axis bridge kinematics | `src/emc/kinematics/5axiskins.c`, `switchkins.c`, `switchkins.h`, `userkfuncs.c`, plus `src/rtapi/rtapi_ctype.h` | Copy unchanged | HAL pin allocation, HAL component lifecycle, and RTAPI module metadata are standalone runtime edges; switchable 5-axis forward/inverse behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_5axis_kinematics_probe` |
|
| Switchable 5-axis bridge kinematics | `src/emc/kinematics/5axiskins.c`, `switchkins.c`, `switchkins.h`, `userkfuncs.c`, plus `src/rtapi/rtapi_ctype.h` | Copy unchanged | HAL pin allocation, HAL component lifecycle, and RTAPI module metadata are standalone runtime edges; switchable 5-axis forward/inverse behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_5axis_kinematics_probe` |
|
||||||
| TRT table-rotary kinematics | `src/emc/kinematics/trtfuncs.c`, `xyzac-trt-kins.c`, `xyzbc-trt-kins.c` | Copy unchanged | HAL pin allocation and switchkins lifecycle stay runtime boundaries; XYZAC/XYZBC TRT forward/inverse behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_xyzac_trt_kinematics_probe`, `linuxcnc_xyzbc_trt_kinematics_probe` |
|
| TRT table-rotary kinematics | `src/emc/kinematics/trtfuncs.c`, `xyzac-trt-kins.c`, `xyzbc-trt-kins.c` | Copy unchanged | HAL pin allocation and switchkins lifecycle stay runtime boundaries; XYZAC/XYZBC TRT forward/inverse behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_xyzac_trt_kinematics_probe`, `linuxcnc_xyzbc_trt_kinematics_probe` |
|
||||||
| Five-axis switchkins machine configs and M428/M429/M430 remaps | `configs/sim/axis/vismach/5axis/bridgemill/*`, `table-dual-rotary/*`, and `table-rotary-tilting/*` selected INI, HAL, tool-table, XML, demo, and `remap_subs/*.ngc` files plus `src/emc/rs274ngc/interp_remap.cc` | Copy unchanged | `M428`, `M429`, and `M430` remain LinuxCNC `REMAP` entries that call LinuxCNC NGC subroutines using `M68`, `M66`, `_hal[motion.switchkins-type]`, and the INI/HAL `motion.analog-out-03 => motion.switchkins-type` link; standalone remap descriptor parsing routes through vendored `Interp::parse_remap()` and `find_ngc_file()`, and NGC remap/file execution routes through vendored LinuxCNC O-word and `open()`/`read()`/`execute()` paths while HAL synchronization stays a runtime adapter boundary | Vendor byte sync, `linuxcnc_5axis_remap_asset_probe`, `linuxcnc_remap_parse_harness`, `linuxcnc_remap_hal_sync_harness`, `linuxcnc_5axis_remap_execute_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/wasm/node/verify_sim_configs_wasm.sh`, `tests/browser/verify_interp_browser.sh`, `tests/browser/verify_ini_panel_browser.sh` |
|
| Five-axis switchkins machine configs and M428/M429/M430 remaps | `configs/sim/axis/vismach/5axis/bridgemill/*`, `table-dual-rotary/*`, and `table-rotary-tilting/*` selected INI, HAL, tool-table, XML, demo, and `remap_subs/*.ngc` files plus `src/emc/rs274ngc/interp_remap.cc` | Copy unchanged | `M428`, `M429`, and `M430` remain LinuxCNC `REMAP` entries that call LinuxCNC NGC subroutines using `M68`, `M66`, `_hal[motion.switchkins-type]`, and the INI/HAL `motion.analog-out-03 => motion.switchkins-type` link; standalone remap descriptor parsing routes through vendored `Interp::parse_remap()` and `find_ngc_file()`, and NGC remap/file execution routes through vendored LinuxCNC O-word and `open()`/`read()`/`execute()` paths while HAL synchronization stays a runtime adapter boundary | Vendor byte sync, `linuxcnc_5axis_remap_asset_probe`, `linuxcnc_remap_parse_harness`, `linuxcnc_remap_hal_sync_harness`, `linuxcnc_5axis_remap_execute_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/wasm/node/verify_sim_configs_wasm.sh`, `tests/browser/verify_interp_browser.sh`, `tests/browser/verify_ini_panel_browser.sh` |
|
||||||
| Representative sim-config machine programs | `configs/sim/axis/foam/*`, `configs/sim/axis/geometry/M110`, `xyzc.ini`, `xyzc.ngc`, `configs/sim/axis/external_offsets/M111`, `dyn_demo.ngc`, `dynamic_offsets.ini`, `eoffset.tbl`, and `configs/sim/axis/sim.tbl` | Copy unchanged | The `foam`, `xyzc`, and dynamic external-offset sample programs remain LinuxCNC sim-config assets. The standalone boundary only copies INI, tool table, G-code, and executable user-M files into the native or WASM filesystem, then calls vendored LinuxCNC INI parsing and `Interp::open()`/`read()`/`execute()` through the existing machine-config adapter. The JS SDK `runSimConfigProgram()` is only the host file-staging helper for this boundary: it writes caller-provided text files to the Emscripten filesystem, applies executable bits, and forwards to LinuxCNC-backed C ABI entry points. `M110`/`M111` process execution stays a runtime boundary represented by deterministic `USER_M_COMMAND` canonical events | Vendor byte sync, `tests/native/verify_sim_configs.sh`, `tests/wasm/node/verify_sim_configs_wasm.sh`, `tests/browser/verify_interp_browser.sh` |
|
| Representative sim-config machine programs | `configs/sim/axis/foam/*`, `configs/sim/axis/geometry/M110`, `xyzc.ini`, `xyzc.ngc`, `configs/sim/axis/external_offsets/M111`, `dyn_demo.ngc`, `dynamic_offsets.ini`, `eoffsets.ngc`, `eoffsets.ini`, `jwp_z.ngc`, `jwp_z.ini`, `opa_demo.ngc`, `opa.ini`, `circles.ngc`, `eoffset.tbl`, and `configs/sim/axis/sim.tbl` | Copy unchanged | The `foam`, `xyzc`, and external-offset sample programs remain LinuxCNC sim-config assets. The standalone boundary only copies INI, tool table, G-code, executable user-M files, and `SUBROUTINE_PATH` files into the native or WASM filesystem, then calls vendored LinuxCNC INI parsing and `Interp::open()`/`read()`/`execute()` through the existing machine-config adapter. The native sim-config harness now prefers `[DISPLAY]OPEN_FILE` when several INI files live beside a program, so each program is judged with its corresponding machine context. The JS SDK `runSimConfigProgram()` is only the host file-staging helper for this boundary: it writes caller-provided text files to the Emscripten filesystem, applies executable bits, and forwards to LinuxCNC-backed C ABI entry points. `M110`/`M111` process execution stays a runtime boundary represented by deterministic `USER_M_COMMAND` canonical events | Vendor byte sync, `tests/native/verify_sim_configs.sh`, `tests/wasm/node/verify_sim_configs_wasm.sh`, `tests/browser/verify_interp_browser.sh` |
|
||||||
| Representative `nc_files` examples | `nc_files/arcspiral.ngc`, `nc_files/factorial.ngc`, `nc_files/hole-circle.ngc`, `nc_files/m6demo.ngc` | Copy unchanged | These upstream `linuxcnc/nc_files` examples are copied byte-for-byte into the WASM vendor tree after the native `nc_files` harness classifies the broader directory. Node and browser tests only stage the original `.ngc` text in the Emscripten filesystem and call the LinuxCNC-backed `Interp::open()`, `read()`, and `execute()` path through the existing SDK; no G-code, O-word, tool-change, or M-code behavior is implemented in JavaScript | Vendor byte sync, `tests/native/verify_nc_files.sh`, `tests/wasm/node/verify_nc_files_wasm.sh`, `tests/browser/verify_interp_browser.sh`, `tests/host/verify_host_smokes.sh` |
|
| Representative `nc_files` examples | `nc_files/3D_Chips.ngc`, `nc_files/arcspiral.ngc`, `nc_files/factorial.ngc`, `nc_files/hole-circle.ngc`, `nc_files/m6demo.ngc` | Copy unchanged | These upstream `linuxcnc/nc_files` examples are copied byte-for-byte into the WASM vendor tree after the native `nc_files` harness classifies the broader directory. Node and browser tests only stage the original `.ngc` text and, for `3D_Chips.ngc`, the minimal INI-declared tool table context required by its upstream `T1 M6` line in the Emscripten filesystem, then call the LinuxCNC-backed `Interp::open()`, `read()`, and `execute()` path through the existing SDK; no G-code, O-word, tool-change, or M-code behavior is implemented in JavaScript | Vendor byte sync, `tests/native/verify_nc_files.sh`, `tests/wasm/node/verify_nc_files_wasm.sh`, `tests/browser/verify_interp_browser.sh`, `tests/host/verify_host_smokes.sh` |
|
||||||
| LinuxCNC remap regression fixtures | `tests/remap/duplicate-o-word/*`, `tests/remap/fail/args.0/*`, `tests/remap/fail/args.1/*`, `tests/remap/fail/args.2/*`, `tests/remap/fail/body-ngc/*`, `tests/remap/m30-interaction/*`, `tests/remap/nested-remaps-oword/*`, `tests/remap/posargs.0/*`, `tests/remap/sequencing/*`, selected NGC-only `tests/remap/remap-io/test-ngc.ini` plus `io_*.ngc`, and `src/emc/rs274ngc/interp_remap.cc` plus `interp_o_word.cc` | Copy unchanged | The upstream duplicate O-word, NGC-only remap failure, M30/remap-level interaction, nested O-word remap, positional-argument remap, G/M remap sequencing, and remap-IO NGC subroutine regressions remain LinuxCNC REMAP/O-word/file or MDI execution tests. The standalone boundary only copies the upstream test files into native or WASM filesystems, reads LinuxCNC INI `SUBROUTINE_PATH`, `REMAP`, and `OWORD_NARGS` entries, and calls vendored `Interp::parse_remap()`, `open()`, `read()`, and `execute()` or feeds the upstream remap-IO MDI sequence into vendored `Interp::execute()`; the continue-on-error runner path only mirrors LinuxCNC `rs274 -n 0` test execution and does not implement duplicate-label, O-word, nested remap, M30, positional-argument, failure, sequencing, M62-M68, M66 input, or remap semantics | Vendor byte sync, `linuxcnc_duplicate_oword_remap_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/browser/verify_interp_browser.sh` |
|
| LinuxCNC remap regression fixtures | `tests/remap/duplicate-o-word/*`, `tests/remap/fail/args.0/*`, `tests/remap/fail/args.1/*`, `tests/remap/fail/args.2/*`, `tests/remap/fail/body-ngc/*`, `tests/remap/m30-interaction/*`, `tests/remap/nested-remaps-oword/*`, `tests/remap/posargs.0/*`, `tests/remap/sequencing/*`, selected NGC-only `tests/remap/remap-io/test-ngc.ini` plus `io_*.ngc`, and `src/emc/rs274ngc/interp_remap.cc` plus `interp_o_word.cc` | Copy unchanged | The upstream duplicate O-word, NGC-only remap failure, M30/remap-level interaction, nested O-word remap, positional-argument remap, G/M remap sequencing, and remap-IO NGC subroutine regressions remain LinuxCNC REMAP/O-word/file or MDI execution tests. The standalone boundary only copies the upstream test files into native or WASM filesystems, reads LinuxCNC INI `SUBROUTINE_PATH`, `REMAP`, and `OWORD_NARGS` entries, and calls vendored `Interp::parse_remap()`, `open()`, `read()`, and `execute()` or feeds the upstream remap-IO MDI sequence into vendored `Interp::execute()`; the continue-on-error runner path only mirrors LinuxCNC `rs274 -n 0` test execution and does not implement duplicate-label, O-word, nested remap, M30, positional-argument, failure, sequencing, M62-M68, M66 input, or remap semantics | Vendor byte sync, `linuxcnc_duplicate_oword_remap_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/browser/verify_interp_browser.sh` |
|
||||||
| LinuxCNC interpreter regression fixtures | `tests/interp/do-while-break/*`, `tests/interp/oword-bug315/*`, `tests/interp/oword-bug315-p2/*`, `tests/interp/exists/*`, `tests/interp/return-value/*`, `tests/interp/subs-follow-main/*`, `tests/interp/fractional-linenumbers/*`, `tests/interp/namedparam-bug424/*`, selected `tests/interp/rotation/*` pure interpreter cases, `tests/interp/iniparam/*`, `tests/interp/iniparam-failassign/*`, `tests/interp/m19/*`, `tests/interp/magic_comments/param_format_printing/*`, selected `tests/interp/m98m99/*` pure interpreter cases, `tests/interp/sub-call-from-sub/*`, `tests/interp/sequence-number/*`, `tests/interp/nested-sub-error/*`, `tests/interp/nested-sub-in-file-error/*`, `tests/interp/abort-hot-comment/*`, plus vendored interpreter/O-word sources including `interp_o_word.cc`, `interp_read.cc`, `interp_execute.cc`, `interp_find.cc`, `interp_namedparams.cc`, and `rs274ngc_pre.cc` | Copy unchanged | The upstream do/while/break, O-word bug315, `EXISTS[]`, subroutine return-value, subs-after-main, fractional line-number, named-parameter, selected rotation/G53/G28 absolute-position and endpoint, INI named-parameter lookup/read-only protection, M19 spindle-orient offset/timeout handling, magic-comment parameter formatting, selected Fanuc `M98/M99` and O-expression call regressions, external-subroutine-call, external-subroutine line-number, nested-subroutine-definition rejection, blocked forward-seek-to-later-numbered-sub, and `(ABORT,...)` hot-comment parameter-expansion regressions remain LinuxCNC interpreter file-execution tests. The standalone boundary only vendors the original upstream assets, copies `*.ngc`, `test.ini`, `test.tbl`, `subs/*.ngc`, and referenced external subroutine `.ngc` files into native or WASM filesystems where applicable, sets the LinuxCNC `INI_FILE_NAME` runtime edge for `_ini[...]`, applies LinuxCNC INI machine settings such as `[RS274NGC]ORIENT_OFFSET`, reads LinuxCNC INI `SUBROUTINE_PATH`, captures LinuxCNC `(PRINT,...)` output through the existing stdout/Emscripten `print` boundary, and calls vendored `Interp::open()`, `read()`, and `execute()`; it does not implement O-word loop, break, subroutine, dynamic call, `M98/M99`, `EXISTS[]`, named-parameter, absolute-position named-parameter, G28/G53 endpoint, INI-variable, read-only parameter, line-number, spindle-speed, spindle-orient, magic-comment formatting, subroutine lookup, ABORT hot-comment, error, or branch semantics | Vendor byte sync, `linuxcnc_interp_minimal_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/browser/verify_interp_browser.sh` |
|
| LinuxCNC interpreter regression fixtures | `tests/interp/do-while-break/*`, `tests/interp/oword-bug315/*`, `tests/interp/oword-bug315-p2/*`, `tests/interp/exists/*`, `tests/interp/return-value/*`, `tests/interp/subs-follow-main/*`, `tests/interp/fractional-linenumbers/*`, `tests/interp/namedparam-bug424/*`, selected `tests/interp/rotation/*` pure interpreter cases, `tests/interp/iniparam/*`, `tests/interp/iniparam-failassign/*`, `tests/interp/m19/*`, `tests/interp/magic_comments/param_format_printing/*`, selected `tests/interp/m98m99/*` pure interpreter cases, `tests/interp/sub-call-from-sub/*`, `tests/interp/sequence-number/*`, `tests/interp/nested-sub-error/*`, `tests/interp/nested-sub-in-file-error/*`, `tests/interp/abort-hot-comment/*`, plus vendored interpreter/O-word sources including `interp_o_word.cc`, `interp_read.cc`, `interp_execute.cc`, `interp_find.cc`, `interp_namedparams.cc`, and `rs274ngc_pre.cc` | Copy unchanged | The upstream do/while/break, O-word bug315, `EXISTS[]`, subroutine return-value, subs-after-main, fractional line-number, named-parameter, selected rotation/G53/G28 absolute-position and endpoint, INI named-parameter lookup/read-only protection, M19 spindle-orient offset/timeout handling, magic-comment parameter formatting, selected Fanuc `M98/M99` and O-expression call regressions, external-subroutine-call, external-subroutine line-number, nested-subroutine-definition rejection, blocked forward-seek-to-later-numbered-sub, and `(ABORT,...)` hot-comment parameter-expansion regressions remain LinuxCNC interpreter file-execution tests. The standalone boundary only vendors the original upstream assets, copies `*.ngc`, `test.ini`, `test.tbl`, `subs/*.ngc`, and referenced external subroutine `.ngc` files into native or WASM filesystems where applicable, sets the LinuxCNC `INI_FILE_NAME` runtime edge for `_ini[...]`, applies LinuxCNC INI machine settings such as `[RS274NGC]ORIENT_OFFSET`, reads LinuxCNC INI `SUBROUTINE_PATH`, captures LinuxCNC `(PRINT,...)` output through the existing stdout/Emscripten `print` boundary, and calls vendored `Interp::open()`, `read()`, and `execute()`; it does not implement O-word loop, break, subroutine, dynamic call, `M98/M99`, `EXISTS[]`, named-parameter, absolute-position named-parameter, G28/G53 endpoint, INI-variable, read-only parameter, line-number, spindle-speed, spindle-orient, magic-comment formatting, subroutine lookup, ABORT hot-comment, error, or branch semantics | Vendor byte sync, `linuxcnc_interp_minimal_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/browser/verify_interp_browser.sh` |
|
||||||
| Additional non-switchable kinematics | `src/emc/kinematics/corexykins.c`, `rotatekins.c`, `rosekins.c`, `maxkins.c`, `lineardeltakins.c`, `lineardeltakins-common.h`, `rotarydeltakins.c`, `rotarydeltakins-common.h`, `scorbot-kins.c`, `tripodkins.c`, `scarakins.c`, `pumakins.c`, `pumakins.h`, `genhexkins.c`, `genhexkins.h`, `genserfuncs.c`, `genserkins.c`, `genserkins.h`, `ugenserkins.c`, `pentakins.c`, `pentakins.h`, `cubic.c` | Copy unchanged | HAL pin allocation, HAL parameter allocation, HAL component lifecycle, RTAPI module metadata, Go math C/C++ linkage, switchkins iterative-forward warmup, and userspace test-program process entry remain standalone runtime edges; forward/inverse behavior remains LinuxCNC source where the module exposes it | Vendor byte sync, per-file source probes, `linuxcnc_corexy_kinematics_probe`, `linuxcnc_rotate_kinematics_probe`, `linuxcnc_rose_kinematics_probe`, `linuxcnc_max_kinematics_probe`, `linuxcnc_lineardelta_kinematics_probe`, `linuxcnc_rotarydelta_kinematics_probe`, `linuxcnc_scorbot_kinematics_probe`, `linuxcnc_tripod_kinematics_probe`, `linuxcnc_scara_kinematics_probe`, `linuxcnc_puma_kinematics_probe`, `linuxcnc_genser_kinematics_probe`, `linuxcnc_genhex_kinematics_probe`, `linuxcnc_pentakins_kinematics_probe` |
|
| Additional non-switchable kinematics | `src/emc/kinematics/corexykins.c`, `rotatekins.c`, `rosekins.c`, `maxkins.c`, `lineardeltakins.c`, `lineardeltakins-common.h`, `rotarydeltakins.c`, `rotarydeltakins-common.h`, `scorbot-kins.c`, `tripodkins.c`, `scarakins.c`, `pumakins.c`, `pumakins.h`, `genhexkins.c`, `genhexkins.h`, `genserfuncs.c`, `genserkins.c`, `genserkins.h`, `ugenserkins.c`, `pentakins.c`, `pentakins.h`, `cubic.c` | Copy unchanged | HAL pin allocation, HAL parameter allocation, HAL component lifecycle, RTAPI module metadata, Go math C/C++ linkage, switchkins iterative-forward warmup, and userspace test-program process entry remain standalone runtime edges; forward/inverse behavior remains LinuxCNC source where the module exposes it | Vendor byte sync, per-file source probes, `linuxcnc_corexy_kinematics_probe`, `linuxcnc_rotate_kinematics_probe`, `linuxcnc_rose_kinematics_probe`, `linuxcnc_max_kinematics_probe`, `linuxcnc_lineardelta_kinematics_probe`, `linuxcnc_rotarydelta_kinematics_probe`, `linuxcnc_scorbot_kinematics_probe`, `linuxcnc_tripod_kinematics_probe`, `linuxcnc_scara_kinematics_probe`, `linuxcnc_puma_kinematics_probe`, `linuxcnc_genser_kinematics_probe`, `linuxcnc_genhex_kinematics_probe`, `linuxcnc_pentakins_kinematics_probe` |
|
||||||
|
|||||||
@@ -158,6 +158,61 @@ std::vector<std::string> load_program(int argc, char **argv)
|
|||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_uri_unreserved(char value)
|
||||||
|
{
|
||||||
|
return (value >= 'A' && value <= 'Z') ||
|
||||||
|
(value >= 'a' && value <= 'z') ||
|
||||||
|
(value >= '0' && value <= '9') ||
|
||||||
|
value == '-' || value == '_' || value == '.' || value == '~';
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_percent_encoded_text(std::ostream &output, const char *text)
|
||||||
|
{
|
||||||
|
constexpr char hex[] = "0123456789ABCDEF";
|
||||||
|
for (const char *cursor = text ? text : ""; *cursor; ++cursor) {
|
||||||
|
char value = *cursor;
|
||||||
|
switch (*cursor) {
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
case '\t':
|
||||||
|
value = ' ';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (is_uri_unreserved(value)) {
|
||||||
|
output << value;
|
||||||
|
} else {
|
||||||
|
const auto byte = static_cast<unsigned char>(value);
|
||||||
|
output << '%' << hex[(byte >> 4) & 0x0f] << hex[byte & 0x0f];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_run_step(std::ostream &output,
|
||||||
|
const Interp &interp,
|
||||||
|
const char *phase,
|
||||||
|
int step,
|
||||||
|
int rc)
|
||||||
|
{
|
||||||
|
output << "run_step phase=" << phase
|
||||||
|
<< " step=" << step
|
||||||
|
<< " rc=" << rc
|
||||||
|
<< " line=" << interp._setup.sequence_number
|
||||||
|
<< " x=" << interp._setup.current_x
|
||||||
|
<< " y=" << interp._setup.current_y
|
||||||
|
<< " z=" << interp._setup.current_z
|
||||||
|
<< " a=" << interp._setup.AA_current
|
||||||
|
<< " b=" << interp._setup.BB_current
|
||||||
|
<< " c=" << interp._setup.CC_current
|
||||||
|
<< " u=" << interp._setup.u_current
|
||||||
|
<< " v=" << interp._setup.v_current
|
||||||
|
<< " w=" << interp._setup.w_current
|
||||||
|
<< " statement_uri=";
|
||||||
|
append_percent_encoded_text(output, interp._setup.linetext);
|
||||||
|
output << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
@@ -228,6 +283,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
++file_read_count;
|
++file_read_count;
|
||||||
std::cout << "file_read_" << file_read_count << "=" << file_read_rc << "\n";
|
std::cout << "file_read_" << file_read_count << "=" << file_read_rc << "\n";
|
||||||
|
append_run_step(std::cout, file_interp, "read", file_read_count, file_read_rc);
|
||||||
if ((file_read_rc != INTERP_OK) && (file_read_rc != INTERP_EXECUTE_FINISH)) {
|
if ((file_read_rc != INTERP_OK) && (file_read_rc != INTERP_EXECUTE_FINISH)) {
|
||||||
if (file_read_rc > INTERP_MIN_ERROR) {
|
if (file_read_rc > INTERP_MIN_ERROR) {
|
||||||
char error_buf[LINELEN] = {0};
|
char error_buf[LINELEN] = {0};
|
||||||
@@ -244,6 +300,7 @@ int main(int argc, char **argv)
|
|||||||
const int file_execute_rc = file_interp.execute();
|
const int file_execute_rc = file_interp.execute();
|
||||||
++file_execute_count;
|
++file_execute_count;
|
||||||
std::cout << "file_execute_" << file_execute_count << "=" << file_execute_rc << "\n";
|
std::cout << "file_execute_" << file_execute_count << "=" << file_execute_rc << "\n";
|
||||||
|
append_run_step(std::cout, file_interp, "execute", file_execute_count, file_execute_rc);
|
||||||
if (file_execute_rc > INTERP_MIN_ERROR) {
|
if (file_execute_rc > INTERP_MIN_ERROR) {
|
||||||
char error_buf[LINELEN] = {0};
|
char error_buf[LINELEN] = {0};
|
||||||
file_interp.error_text(file_execute_rc, error_buf, sizeof(error_buf));
|
file_interp.error_text(file_execute_rc, error_buf, sizeof(error_buf));
|
||||||
|
|||||||
@@ -264,6 +264,61 @@ void append_tool_table_state(std::ostringstream &output)
|
|||||||
output << "tool_index_for_tool_2=" << standalone::find_tool_index_for_tool(2) << "\n";
|
output << "tool_index_for_tool_2=" << standalone::find_tool_index_for_tool(2) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_uri_unreserved(char value)
|
||||||
|
{
|
||||||
|
return (value >= 'A' && value <= 'Z') ||
|
||||||
|
(value >= 'a' && value <= 'z') ||
|
||||||
|
(value >= '0' && value <= '9') ||
|
||||||
|
value == '-' || value == '_' || value == '.' || value == '~';
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_percent_encoded_text(std::ostringstream &output, const char *text)
|
||||||
|
{
|
||||||
|
constexpr char hex[] = "0123456789ABCDEF";
|
||||||
|
for (const char *cursor = text ? text : ""; *cursor; ++cursor) {
|
||||||
|
char value = *cursor;
|
||||||
|
switch (*cursor) {
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
case '\t':
|
||||||
|
value = ' ';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (is_uri_unreserved(value)) {
|
||||||
|
output << value;
|
||||||
|
} else {
|
||||||
|
const auto byte = static_cast<unsigned char>(value);
|
||||||
|
output << '%' << hex[(byte >> 4) & 0x0f] << hex[byte & 0x0f];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_run_step(std::ostringstream &output,
|
||||||
|
const Interp &interp,
|
||||||
|
const char *phase,
|
||||||
|
int step,
|
||||||
|
int rc)
|
||||||
|
{
|
||||||
|
output << "run_step phase=" << phase
|
||||||
|
<< " step=" << step
|
||||||
|
<< " rc=" << rc
|
||||||
|
<< " line=" << interp._setup.sequence_number
|
||||||
|
<< " x=" << interp._setup.current_x
|
||||||
|
<< " y=" << interp._setup.current_y
|
||||||
|
<< " z=" << interp._setup.current_z
|
||||||
|
<< " a=" << interp._setup.AA_current
|
||||||
|
<< " b=" << interp._setup.BB_current
|
||||||
|
<< " c=" << interp._setup.CC_current
|
||||||
|
<< " u=" << interp._setup.u_current
|
||||||
|
<< " v=" << interp._setup.v_current
|
||||||
|
<< " w=" << interp._setup.w_current
|
||||||
|
<< " statement_uri=";
|
||||||
|
append_percent_encoded_text(output, interp._setup.linetext);
|
||||||
|
output << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
void append_error_text(std::ostringstream &output, Interp &interp, const char *prefix, int rc)
|
void append_error_text(std::ostringstream &output, Interp &interp, const char *prefix, int rc)
|
||||||
{
|
{
|
||||||
if (rc > INTERP_MIN_ERROR) {
|
if (rc > INTERP_MIN_ERROR) {
|
||||||
@@ -539,6 +594,7 @@ char *run_file_with_ini_internal(const char *path, const char *ini_path, bool co
|
|||||||
|
|
||||||
++file_read_count;
|
++file_read_count;
|
||||||
output << "file_read_" << file_read_count << "=" << read_rc << "\n";
|
output << "file_read_" << file_read_count << "=" << read_rc << "\n";
|
||||||
|
append_run_step(output, interp, "read", file_read_count, read_rc);
|
||||||
if ((read_rc != INTERP_OK) && (read_rc != INTERP_EXECUTE_FINISH)) {
|
if ((read_rc != INTERP_OK) && (read_rc != INTERP_EXECUTE_FINISH)) {
|
||||||
if (read_rc > INTERP_MIN_ERROR) {
|
if (read_rc > INTERP_MIN_ERROR) {
|
||||||
char error_buf[LINELEN] = {0};
|
char error_buf[LINELEN] = {0};
|
||||||
@@ -555,6 +611,7 @@ char *run_file_with_ini_internal(const char *path, const char *ini_path, bool co
|
|||||||
const int execute_rc = interp.execute();
|
const int execute_rc = interp.execute();
|
||||||
++file_execute_count;
|
++file_execute_count;
|
||||||
output << "file_execute_" << file_execute_count << "=" << execute_rc << "\n";
|
output << "file_execute_" << file_execute_count << "=" << execute_rc << "\n";
|
||||||
|
append_run_step(output, interp, "execute", file_execute_count, execute_rc);
|
||||||
if (execute_rc > INTERP_MIN_ERROR) {
|
if (execute_rc > INTERP_MIN_ERROR) {
|
||||||
char error_buf[LINELEN] = {0};
|
char error_buf[LINELEN] = {0};
|
||||||
interp.error_text(execute_rc, error_buf, sizeof(error_buf));
|
interp.error_text(execute_rc, error_buf, sizeof(error_buf));
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ Use `src/index.js` for stable imports:
|
|||||||
import {
|
import {
|
||||||
createLinuxCncIniSdk,
|
createLinuxCncIniSdk,
|
||||||
createLinuxCncInterpSdk,
|
createLinuxCncInterpSdk,
|
||||||
|
planSimConfigStaging,
|
||||||
} from "./src/index.js";
|
} from "./src/index.js";
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -85,6 +86,15 @@ into the Emscripten filesystem, applies executable bits for user M-code files,
|
|||||||
then forwards to `runFileWithIni()` by default or to `runFiveAxisRemapFile()`
|
then forwards to `runFileWithIni()` by default or to `runFiveAxisRemapFile()`
|
||||||
when `executionMode: "fiveAxisRemap"` is explicitly requested.
|
when `executionMode: "fiveAxisRemap"` is explicitly requested.
|
||||||
|
|
||||||
|
`planSimConfigStaging()` is the companion file-staging planner for
|
||||||
|
representative LinuxCNC `configs/sim` programs. Callers provide the vendored
|
||||||
|
source manifest text, machine relative path, INI file name, and INI text. The
|
||||||
|
planner reads only INI file references and the manifest, then returns the INI,
|
||||||
|
`[DISPLAY]OPEN_FILE`, `[EMCIO]TOOL_TABLE`, `[RS274NGC]PARAMETER_FILE`,
|
||||||
|
`[RS274NGC]SUBROUTINE_PATH`, `[RS274NGC]USER_M_PATH`, and remap-NGC files that
|
||||||
|
should be copied into the Emscripten filesystem. It does not implement G-code,
|
||||||
|
tool, parameter, remap, or user-M semantics.
|
||||||
|
|
||||||
`runFileWithIniContinueOnError()` uses the same LinuxCNC-backed file execution
|
`runFileWithIniContinueOnError()` uses the same LinuxCNC-backed file execution
|
||||||
path but keeps the runner loop going after LinuxCNC reports an error, matching
|
path but keeps the runner loop going after LinuxCNC reports an error, matching
|
||||||
upstream `rs274 -n 0` regression tests such as `tests/interp/oword-unwind`.
|
upstream `rs274 -n 0` regression tests such as `tests/interp/oword-unwind`.
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
export { createLinuxCncIniSdk } from "./linuxcnc-ini.js";
|
export { createLinuxCncIniSdk } from "./linuxcnc-ini.js";
|
||||||
export { createLinuxCncInterpSdk } from "./linuxcnc-interp.js";
|
export { createLinuxCncInterpSdk } from "./linuxcnc-interp.js";
|
||||||
|
export { planSimConfigStaging } from "./sim-config-staging.js";
|
||||||
|
|||||||
252
wasm-port/runtime/sdk/src/sim-config-staging.js
Normal file
252
wasm-port/runtime/sdk/src/sim-config-staging.js
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
function cleanManifest(manifestText) {
|
||||||
|
return manifestText
|
||||||
|
.split("\n")
|
||||||
|
.map((line) => line.trim())
|
||||||
|
.filter((line) => line && !line.startsWith("#"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeRel(path) {
|
||||||
|
const parts = [];
|
||||||
|
for (const part of path.split("/")) {
|
||||||
|
if (!part || part === ".") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (part === "..") {
|
||||||
|
parts.pop();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parts.push(part);
|
||||||
|
}
|
||||||
|
return parts.join("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
function dirname(path) {
|
||||||
|
const clean = normalizeRel(path);
|
||||||
|
const index = clean.lastIndexOf("/");
|
||||||
|
return index === -1 ? "" : clean.slice(0, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
function basename(path) {
|
||||||
|
const clean = normalizeRel(path);
|
||||||
|
const index = clean.lastIndexOf("/");
|
||||||
|
return index === -1 ? clean : clean.slice(index + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stripIniComment(line) {
|
||||||
|
const hash = line.indexOf("#");
|
||||||
|
const semicolon = line.indexOf(";");
|
||||||
|
const indexes = [hash, semicolon].filter((index) => index >= 0);
|
||||||
|
if (indexes.length === 0) {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
return line.slice(0, Math.min(...indexes));
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseIni(iniText) {
|
||||||
|
const values = new Map();
|
||||||
|
let section = "";
|
||||||
|
for (const rawLine of iniText.split("\n")) {
|
||||||
|
const sectionMatch = rawLine.match(/^\s*\[([^\]]+)\]/);
|
||||||
|
if (sectionMatch) {
|
||||||
|
section = sectionMatch[1].trim().toUpperCase();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const line = stripIniComment(rawLine);
|
||||||
|
const equals = line.indexOf("=");
|
||||||
|
if (equals === -1 || !section) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const key = line.slice(0, equals).trim().toUpperCase();
|
||||||
|
const value = line.slice(equals + 1).trim();
|
||||||
|
if (!key || !value) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const mapKey = `${section}.${key}`;
|
||||||
|
const existing = values.get(mapKey) ?? [];
|
||||||
|
existing.push(value);
|
||||||
|
values.set(mapKey, existing);
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
function firstIniValue(values, section, key) {
|
||||||
|
return values.get(`${section.toUpperCase()}.${key.toUpperCase()}`)?.[0] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function allIniValues(values, section, key) {
|
||||||
|
return values.get(`${section.toUpperCase()}.${key.toUpperCase()}`) ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitSearchPath(value) {
|
||||||
|
return value.split(":").map((entry) => entry.trim()).filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sourceRelFor(machineRel, path) {
|
||||||
|
return normalizeRel(`configs/sim/${machineRel}/${path}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function targetPathFor(wasmDir, targetRel) {
|
||||||
|
return `${wasmDir}/${normalizeRel(targetRel)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isUserMCodePath(path) {
|
||||||
|
return /^M1\d\d$/i.test(basename(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSubroutinePath(path) {
|
||||||
|
return path.toLowerCase().endsWith(".ngc");
|
||||||
|
}
|
||||||
|
|
||||||
|
function findUpwardByBasename(manifestSet, sourceDir, fileName) {
|
||||||
|
let current = sourceDir;
|
||||||
|
while (current.startsWith("configs/sim")) {
|
||||||
|
const candidate = normalizeRel(`${current}/${fileName}`);
|
||||||
|
if (manifestSet.has(candidate)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
if (current === "configs/sim") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
current = dirname(current);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sourceForReference(manifestSet, sourceDir, reference) {
|
||||||
|
if (!reference || reference.startsWith("/")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const sourceRel = normalizeRel(`${sourceDir}/${reference}`);
|
||||||
|
if (manifestSet.has(sourceRel)) {
|
||||||
|
return sourceRel;
|
||||||
|
}
|
||||||
|
return findUpwardByBasename(manifestSet, sourceDir, basename(reference));
|
||||||
|
}
|
||||||
|
|
||||||
|
function addPlannedFile(plan, manifestSet, sourceRel, targetRel, options = {}) {
|
||||||
|
if (!sourceRel || !manifestSet.has(sourceRel)) {
|
||||||
|
if (options.required) {
|
||||||
|
throw new Error(`missing vendored sim-config file: ${sourceRel}`);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existing = plan.get(sourceRel);
|
||||||
|
const executable = options.executable || isUserMCodePath(sourceRel);
|
||||||
|
if (existing) {
|
||||||
|
existing.executable ||= executable;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
plan.set(sourceRel, {
|
||||||
|
sourceRel,
|
||||||
|
path: targetPathFor(options.wasmDir, targetRel),
|
||||||
|
executable,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addDirectoryFiles(plan, manifestEntries, sourceDir, targetDir, predicate, options) {
|
||||||
|
const prefix = sourceDir ? `${sourceDir}/` : "";
|
||||||
|
for (const sourceRel of manifestEntries) {
|
||||||
|
if (!sourceRel.startsWith(prefix)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const childRel = sourceRel.slice(prefix.length);
|
||||||
|
if (childRel.includes("/") || !predicate(sourceRel)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
addPlannedFile(plan, new Set(manifestEntries), sourceRel, normalizeRel(`${targetDir}/${childRel}`), options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function remapNgcNames(iniValues) {
|
||||||
|
const names = [];
|
||||||
|
for (const remap of allIniValues(iniValues, "RS274NGC", "REMAP")) {
|
||||||
|
const match = remap.match(/(?:^|\s)ngc=([^\s]+)/i);
|
||||||
|
if (match) {
|
||||||
|
names.push(`${match[1]}.ngc`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function planSimConfigStaging({
|
||||||
|
manifestText,
|
||||||
|
machineRel,
|
||||||
|
iniFile,
|
||||||
|
iniText,
|
||||||
|
programFile = null,
|
||||||
|
wasmDir = `/work/sim/${machineRel}`,
|
||||||
|
}) {
|
||||||
|
const manifestEntries = cleanManifest(manifestText);
|
||||||
|
const manifestSet = new Set(manifestEntries);
|
||||||
|
const iniValues = parseIni(iniText);
|
||||||
|
const plan = new Map();
|
||||||
|
const sourceDir = sourceRelFor(machineRel, dirname(iniFile));
|
||||||
|
const iniSourceRel = sourceRelFor(machineRel, iniFile);
|
||||||
|
const programReference = programFile ?? firstIniValue(iniValues, "DISPLAY", "OPEN_FILE");
|
||||||
|
|
||||||
|
addPlannedFile(plan, manifestSet, iniSourceRel, iniFile, { wasmDir, required: true });
|
||||||
|
if (programReference) {
|
||||||
|
const programSourceRel = sourceForReference(manifestSet, sourceDir, programReference);
|
||||||
|
addPlannedFile(plan, manifestSet, programSourceRel, programReference, {
|
||||||
|
wasmDir,
|
||||||
|
required: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [section, key] of [
|
||||||
|
["EMCIO", "TOOL_TABLE"],
|
||||||
|
["RS274NGC", "PARAMETER_FILE"],
|
||||||
|
]) {
|
||||||
|
const reference = firstIniValue(iniValues, section, key);
|
||||||
|
if (!reference) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const sourceRel = sourceForReference(manifestSet, sourceDir, reference);
|
||||||
|
addPlannedFile(plan, manifestSet, sourceRel, reference, { wasmDir });
|
||||||
|
}
|
||||||
|
|
||||||
|
const subroutineDirs = splitSearchPath(
|
||||||
|
firstIniValue(iniValues, "RS274NGC", "SUBROUTINE_PATH") ?? "",
|
||||||
|
);
|
||||||
|
for (const dirEntry of subroutineDirs) {
|
||||||
|
if (dirEntry.startsWith("/")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const sourceSubdir = normalizeRel(`${sourceDir}/${dirEntry}`);
|
||||||
|
const targetSubdir = normalizeRel(dirEntry);
|
||||||
|
addDirectoryFiles(plan, manifestEntries, sourceSubdir, targetSubdir, isSubroutinePath, {
|
||||||
|
wasmDir,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const dirEntry of splitSearchPath(firstIniValue(iniValues, "RS274NGC", "USER_M_PATH") ?? "")) {
|
||||||
|
if (dirEntry.startsWith("/")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const sourceUserMDir = normalizeRel(`${sourceDir}/${dirEntry}`);
|
||||||
|
const targetUserMDir = normalizeRel(dirEntry);
|
||||||
|
addDirectoryFiles(plan, manifestEntries, sourceUserMDir, targetUserMDir, isUserMCodePath, {
|
||||||
|
wasmDir,
|
||||||
|
executable: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const remapName of remapNgcNames(iniValues)) {
|
||||||
|
for (const dirEntry of subroutineDirs) {
|
||||||
|
const sourceRel = sourceForReference(manifestSet, normalizeRel(`${sourceDir}/${dirEntry}`), remapName);
|
||||||
|
addPlannedFile(plan, manifestSet, sourceRel, normalizeRel(`${dirEntry}/${remapName}`), {
|
||||||
|
wasmDir,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
wasmDir,
|
||||||
|
iniPath: targetPathFor(wasmDir, iniFile),
|
||||||
|
programPath: programReference ? targetPathFor(wasmDir, programReference) : null,
|
||||||
|
files: [...plan.values()],
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -179,6 +179,52 @@ function parseRunMotion(resultText, programText) {
|
|||||||
const axes = { x: 0, y: 0, z: 0, a: 0, b: 0, c: 0, u: 0, v: 0, w: 0 };
|
const axes = { x: 0, y: 0, z: 0, a: 0, b: 0, c: 0, u: 0, v: 0, w: 0 };
|
||||||
const snapshots = [];
|
const snapshots = [];
|
||||||
const sourceLines = programLineMap(programText);
|
const sourceLines = programLineMap(programText);
|
||||||
|
const motionByLine = new Map();
|
||||||
|
|
||||||
|
for (const line of resultText.split("\n")) {
|
||||||
|
const motion = line.match(/^canon_event=(STRAIGHT_TRAVERSE|STRAIGHT_FEED|ARC_FEED)\b/);
|
||||||
|
if (!motion) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const sourceLine = readCanonicalNumber(line, "line");
|
||||||
|
if (Number.isFinite(sourceLine)) {
|
||||||
|
motionByLine.set(sourceLine, motion[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const line of resultText.split("\n")) {
|
||||||
|
if (!line.startsWith("run_step phase=execute ")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const axis of Object.keys(axes)) {
|
||||||
|
const value = readCanonicalNumber(line, axis);
|
||||||
|
if (value !== null && Number.isFinite(value)) {
|
||||||
|
axes[axis] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceLine = readCanonicalNumber(line, "line");
|
||||||
|
const statementIndex = line.indexOf(" statement_uri=");
|
||||||
|
const statementValue =
|
||||||
|
statementIndex >= 0 ? line.slice(statementIndex + " statement_uri=".length).trim() : "";
|
||||||
|
let statement = "";
|
||||||
|
try {
|
||||||
|
statement = statementValue ? decodeURIComponent(statementValue) : "";
|
||||||
|
} catch {
|
||||||
|
statement = statementValue;
|
||||||
|
}
|
||||||
|
snapshots.push({
|
||||||
|
type: motionByLine.get(sourceLine) ?? "EXECUTE",
|
||||||
|
line: sourceLine,
|
||||||
|
statement: statement || (Number.isFinite(sourceLine) ? (sourceLines.get(sourceLine) ?? "-") : "-"),
|
||||||
|
axes: { ...axes },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshots.length > 0) {
|
||||||
|
return snapshots;
|
||||||
|
}
|
||||||
|
|
||||||
for (const line of resultText.split("\n")) {
|
for (const line of resultText.split("\n")) {
|
||||||
const motion = line.match(/^canon_event=(STRAIGHT_TRAVERSE|STRAIGHT_FEED|ARC_FEED)\b/);
|
const motion = line.match(/^canon_event=(STRAIGHT_TRAVERSE|STRAIGHT_FEED|ARC_FEED)\b/);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
import {
|
import {
|
||||||
createLinuxCncIniSdk,
|
createLinuxCncIniSdk,
|
||||||
createLinuxCncInterpSdk,
|
createLinuxCncInterpSdk,
|
||||||
|
planSimConfigStaging,
|
||||||
} from "../../runtime/sdk/src/index.js";
|
} from "../../runtime/sdk/src/index.js";
|
||||||
import {
|
import {
|
||||||
saveMachineParametersToOpfs,
|
saveMachineParametersToOpfs,
|
||||||
@@ -101,21 +102,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadSimMachineFiles(machineRel, files, executableFiles = []) {
|
async function loadSimMachineFiles(machineRel, iniFile, programFile = null) {
|
||||||
const sourceDir = `../../vendor/linuxcnc/configs/sim/${machineRel}`;
|
const iniText = await fetchText(
|
||||||
const wasmDir = `/work/browser-sim/${machineRel}`;
|
`../../vendor/linuxcnc/configs/sim/${machineRel}/${iniFile}`,
|
||||||
const executableSet = new Set(executableFiles);
|
);
|
||||||
const machineFiles = [];
|
const plan = planSimConfigStaging({
|
||||||
|
manifestText: await fetchText("../../tools/source-manifest.txt"),
|
||||||
|
machineRel,
|
||||||
|
iniFile,
|
||||||
|
iniText,
|
||||||
|
programFile,
|
||||||
|
wasmDir: `/work/browser-sim/${machineRel}`,
|
||||||
|
});
|
||||||
|
|
||||||
for (const filename of files) {
|
return {
|
||||||
machineFiles.push({
|
...plan,
|
||||||
path: `${wasmDir}/${filename}`,
|
files: await Promise.all(plan.files.map(async (file) => ({
|
||||||
text: await fetchText(`${sourceDir}/${filename}`),
|
path: file.path,
|
||||||
executable: executableSet.has(filename),
|
text: await fetchText(`../../vendor/linuxcnc/${file.sourceRel}`),
|
||||||
});
|
executable: file.executable,
|
||||||
}
|
}))),
|
||||||
|
};
|
||||||
return { wasmDir, files: machineFiles };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function writeFiveAxisTrtMachineFiles(interp) {
|
async function writeFiveAxisTrtMachineFiles(interp) {
|
||||||
@@ -275,6 +282,36 @@
|
|||||||
return interp.runFile(wasmPath);
|
return interp.runFile(wasmPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function runVendorNcFileWithToolTable(interp, filename) {
|
||||||
|
const wasmDir = "/work/browser-nc-files-context";
|
||||||
|
const wasmPath = `${wasmDir}/${filename}`;
|
||||||
|
const iniPath = `${wasmDir}/nc_files_context.ini`;
|
||||||
|
await writeFetchedTextFile(
|
||||||
|
interp,
|
||||||
|
`../../vendor/linuxcnc/nc_files/${filename}`,
|
||||||
|
wasmPath,
|
||||||
|
);
|
||||||
|
interp.writeTextFile(
|
||||||
|
`${wasmDir}/tool.tbl`,
|
||||||
|
"T1 P1 D10.000000 Z+0.000000 ; nc_files representative context tool\n",
|
||||||
|
);
|
||||||
|
interp.writeTextFile(
|
||||||
|
iniPath,
|
||||||
|
[
|
||||||
|
"[RS274NGC]",
|
||||||
|
"SUBROUTINE_PATH = .",
|
||||||
|
"",
|
||||||
|
"[TRAJ]",
|
||||||
|
"COORDINATES = X Y Z A B C U V W",
|
||||||
|
"",
|
||||||
|
"[EMCIO]",
|
||||||
|
"TOOL_TABLE = tool.tbl",
|
||||||
|
"",
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
return interp.runFileWithIni(wasmPath, iniPath);
|
||||||
|
}
|
||||||
|
|
||||||
async function verifyRejects(fixtureName, operation, expectedPattern) {
|
async function verifyRejects(fixtureName, operation, expectedPattern) {
|
||||||
try {
|
try {
|
||||||
await operation();
|
await operation();
|
||||||
@@ -507,6 +544,18 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verifyExpectedOutput(
|
||||||
|
"browser_minimal_linear_run_steps",
|
||||||
|
interp.runFile("/work/minimal_linear.ngc"),
|
||||||
|
[
|
||||||
|
"run_step phase=read step=1 rc=0 line=1",
|
||||||
|
"run_step phase=execute step=1 rc=0 line=1 x=1 y=2 z=0",
|
||||||
|
"statement_uri=G0%20X1.0%20Y2.0%20%28Comment%29",
|
||||||
|
"run_step phase=execute step=2 rc=0 line=2 x=3 y=4 z=0",
|
||||||
|
"statement_uri=G1%20X3.0%20Y4.0%20F120.0",
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
|
||||||
const namedParamPath = `/work/${INTERP_INI_FIXTURE}.ngc`;
|
const namedParamPath = `/work/${INTERP_INI_FIXTURE}.ngc`;
|
||||||
interp.writeTextFile(namedParamPath, namedParamProgramText);
|
interp.writeTextFile(namedParamPath, namedParamProgramText);
|
||||||
verifyExpectedOutput(
|
verifyExpectedOutput(
|
||||||
@@ -564,6 +613,28 @@
|
|||||||
].join("\n"),
|
].join("\n"),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
verifyExpectedOutput(
|
||||||
|
"browser_nc_files_3d_chips_context",
|
||||||
|
await runVendorNcFileWithToolTable(interp, "3D_Chips.ngc"),
|
||||||
|
[
|
||||||
|
"file_open=0",
|
||||||
|
"file_read_count=4706",
|
||||||
|
"file_execute_count=4706",
|
||||||
|
"file_saw_error=0",
|
||||||
|
"run_step phase=execute step=18 rc=2 line=18",
|
||||||
|
"statement_uri=N50T%23%3Ctoolno%3EM6",
|
||||||
|
"run_step phase=execute step=19 rc=0 line=19",
|
||||||
|
"statement_uri=N60M8",
|
||||||
|
"canon_event=CHANGE_TOOL",
|
||||||
|
"canon_event=START_SPINDLE_CLOCKWISE spindle=0",
|
||||||
|
"canon_event=STRAIGHT_TRAVERSE line=21 x=0 y=0 z=10",
|
||||||
|
"canon_event=STRAIGHT_FEED line=23 x=53 y=-56.128 z=-25.372",
|
||||||
|
"canon_event=PROGRAM_END",
|
||||||
|
"absent=file_error_text=",
|
||||||
|
"absent=Requested tool 1 not found",
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
|
||||||
verifyExpectedOutput(
|
verifyExpectedOutput(
|
||||||
"browser_nc_files_arcspiral",
|
"browser_nc_files_arcspiral",
|
||||||
await runVendorNcFile(interp, "arcspiral.ngc"),
|
await runVendorNcFile(interp, "arcspiral.ngc"),
|
||||||
@@ -622,16 +693,13 @@
|
|||||||
].join("\n"),
|
].join("\n"),
|
||||||
);
|
);
|
||||||
|
|
||||||
const foam = await loadSimMachineFiles("axis/foam", [
|
const foam = await loadSimMachineFiles("axis/foam", "axis_foam.ini", "foam.ngc");
|
||||||
"axis_foam.ini",
|
|
||||||
"foam.ngc",
|
|
||||||
]);
|
|
||||||
verifyExpectedOutput(
|
verifyExpectedOutput(
|
||||||
"browser_sim_axis_foam_uv",
|
"browser_sim_axis_foam_uv",
|
||||||
interp.runSimConfigProgram({
|
interp.runSimConfigProgram({
|
||||||
files: foam.files,
|
files: foam.files,
|
||||||
programPath: `${foam.wasmDir}/foam.ngc`,
|
programPath: foam.programPath,
|
||||||
iniPath: `${foam.wasmDir}/axis_foam.ini`,
|
iniPath: foam.iniPath,
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
"file_open=0",
|
"file_open=0",
|
||||||
@@ -644,21 +712,15 @@
|
|||||||
|
|
||||||
const bridgeMillSim = await loadSimMachineFiles(
|
const bridgeMillSim = await loadSimMachineFiles(
|
||||||
"axis/vismach/5axis/bridgemill",
|
"axis/vismach/5axis/bridgemill",
|
||||||
[
|
"5axis.ini",
|
||||||
"5axis.ini",
|
"5axisgui.ngc",
|
||||||
"5axis.tbl",
|
|
||||||
"5axisgui.ngc",
|
|
||||||
"remap_subs/428remap.ngc",
|
|
||||||
"remap_subs/429remap.ngc",
|
|
||||||
"remap_subs/430remap.ngc",
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
verifyExpectedOutput(
|
verifyExpectedOutput(
|
||||||
"browser_sim_axis_bridgemill_w",
|
"browser_sim_axis_bridgemill_w",
|
||||||
interp.runSimConfigProgram({
|
interp.runSimConfigProgram({
|
||||||
files: bridgeMillSim.files,
|
files: bridgeMillSim.files,
|
||||||
programPath: `${bridgeMillSim.wasmDir}/5axisgui.ngc`,
|
programPath: bridgeMillSim.programPath,
|
||||||
iniPath: `${bridgeMillSim.wasmDir}/5axis.ini`,
|
iniPath: bridgeMillSim.iniPath,
|
||||||
executionMode: "fiveAxisRemap",
|
executionMode: "fiveAxisRemap",
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
@@ -682,19 +744,15 @@
|
|||||||
|
|
||||||
const geometry = await loadSimMachineFiles(
|
const geometry = await loadSimMachineFiles(
|
||||||
"axis/geometry",
|
"axis/geometry",
|
||||||
[
|
"xyzc.ini",
|
||||||
"M110",
|
"xyzc.ngc",
|
||||||
"xyzc.ini",
|
|
||||||
"xyzc.ngc",
|
|
||||||
],
|
|
||||||
["M110"],
|
|
||||||
);
|
);
|
||||||
verifyExpectedOutput(
|
verifyExpectedOutput(
|
||||||
"browser_sim_axis_geometry_xyzc_user_m110",
|
"browser_sim_axis_geometry_xyzc_user_m110",
|
||||||
interp.runSimConfigProgram({
|
interp.runSimConfigProgram({
|
||||||
files: geometry.files,
|
files: geometry.files,
|
||||||
programPath: `${geometry.wasmDir}/xyzc.ngc`,
|
programPath: geometry.programPath,
|
||||||
iniPath: `${geometry.wasmDir}/xyzc.ini`,
|
iniPath: geometry.iniPath,
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
"file_open=0",
|
"file_open=0",
|
||||||
@@ -706,30 +764,67 @@
|
|||||||
].join("\n"),
|
].join("\n"),
|
||||||
);
|
);
|
||||||
|
|
||||||
const externalOffsets = await loadSimMachineFiles(
|
for (const externalOffsetCase of [
|
||||||
"axis/external_offsets",
|
{
|
||||||
[
|
name: "dyn_demo",
|
||||||
"M111",
|
program: "dyn_demo.ngc",
|
||||||
"dyn_demo.ngc",
|
ini: "dynamic_offsets.ini",
|
||||||
"dynamic_offsets.ini",
|
readCount: 833,
|
||||||
],
|
firstTraverse: "canon_event=STRAIGHT_TRAVERSE line=21 x=0 y=0 z=0",
|
||||||
["M111"],
|
firstFeed: "canon_event=STRAIGHT_FEED line=26 x=9 y=0 z=1.5",
|
||||||
);
|
},
|
||||||
verifyExpectedOutput(
|
{
|
||||||
"browser_sim_axis_external_offsets_user_m111",
|
name: "eoffsets",
|
||||||
interp.runSimConfigProgram({
|
program: "eoffsets.ngc",
|
||||||
files: externalOffsets.files,
|
ini: "eoffsets.ini",
|
||||||
programPath: `${externalOffsets.wasmDir}/dyn_demo.ngc`,
|
readCount: 35,
|
||||||
iniPath: `${externalOffsets.wasmDir}/dynamic_offsets.ini`,
|
firstTraverse: "canon_event=STRAIGHT_TRAVERSE line=24 x=0 y=0 z=0",
|
||||||
}),
|
firstFeed: "canon_event=STRAIGHT_FEED line=27 x=2.25 y=2.64 z=0",
|
||||||
[
|
},
|
||||||
"file_open=0",
|
{
|
||||||
"file_saw_error=0",
|
name: "jwp_z",
|
||||||
"canon_event=USER_M_COMMAND code=M111",
|
program: "jwp_z.ngc",
|
||||||
"canon_event=PROGRAM_END",
|
ini: "jwp_z.ini",
|
||||||
"absent=Unknown m code used: M111",
|
readCount: 35,
|
||||||
].join("\n"),
|
firstTraverse: "canon_event=STRAIGHT_TRAVERSE line=17 x=0 y=0 z=0.5",
|
||||||
);
|
firstFeed: "canon_event=STRAIGHT_FEED line=24 x=2.5 y=3.3 z=0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "opa_demo",
|
||||||
|
program: "opa_demo.ngc",
|
||||||
|
ini: "opa.ini",
|
||||||
|
readCount: 58,
|
||||||
|
firstTraverse: "canon_event=STRAIGHT_TRAVERSE line=13 x=1 y=0 z=0",
|
||||||
|
firstFeed: "canon_event=STRAIGHT_FEED line=35 x=1 y=0 z=0",
|
||||||
|
},
|
||||||
|
]) {
|
||||||
|
const externalOffsets = await loadSimMachineFiles(
|
||||||
|
"axis/external_offsets",
|
||||||
|
externalOffsetCase.ini,
|
||||||
|
externalOffsetCase.program,
|
||||||
|
);
|
||||||
|
verifyExpectedOutput(
|
||||||
|
`browser_sim_axis_external_offsets_${externalOffsetCase.name}_user_m111`,
|
||||||
|
interp.runSimConfigProgram({
|
||||||
|
files: externalOffsets.files,
|
||||||
|
programPath: externalOffsets.programPath,
|
||||||
|
iniPath: externalOffsets.iniPath,
|
||||||
|
}),
|
||||||
|
[
|
||||||
|
"file_open=0",
|
||||||
|
`file_read_count=${externalOffsetCase.readCount}`,
|
||||||
|
`file_execute_count=${externalOffsetCase.readCount}`,
|
||||||
|
"file_saw_error=0",
|
||||||
|
"canon_event=USER_M_COMMAND code=M111",
|
||||||
|
externalOffsetCase.firstTraverse,
|
||||||
|
externalOffsetCase.firstFeed,
|
||||||
|
"canon_event=PROGRAM_END",
|
||||||
|
"absent=Unknown m code used: M111",
|
||||||
|
"absent=Bad character",
|
||||||
|
"absent=Cannot use axis values",
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const fiveAxisTrtDir = await writeFiveAxisTrtMachineFiles(interp);
|
const fiveAxisTrtDir = await writeFiveAxisTrtMachineFiles(interp);
|
||||||
verifyExpectedOutput(
|
verifyExpectedOutput(
|
||||||
|
|||||||
@@ -81,9 +81,33 @@ find_nearest_ini() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
find_ini_by_open_file() {
|
||||||
|
local ngc="$1"
|
||||||
|
local ngc_dir="$2"
|
||||||
|
local ini open_file resolved
|
||||||
|
while IFS= read -r ini; do
|
||||||
|
open_file="$(ini_value "$ini" DISPLAY OPEN_FILE || true)"
|
||||||
|
[[ -z "$open_file" ]] && continue
|
||||||
|
if [[ "$open_file" = /* ]]; then
|
||||||
|
resolved="$open_file"
|
||||||
|
else
|
||||||
|
resolved="$(realpath -m "$(dirname "$ini")/$open_file")"
|
||||||
|
fi
|
||||||
|
if [[ "$resolved" == "$(realpath -m "$ngc")" ]]; then
|
||||||
|
printf '%s\n' "$ini"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done < <(find "$ngc_dir" -maxdepth 1 -type f -name '*.ini' | sort)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
find_sim_ini() {
|
find_sim_ini() {
|
||||||
local rel="$1"
|
local rel="$1"
|
||||||
local ngc_dir="$2"
|
local ngc_dir="$2"
|
||||||
|
local ngc="$3"
|
||||||
|
if find_ini_by_open_file "$ngc" "$ngc_dir"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
case "$rel" in
|
case "$rel" in
|
||||||
axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/*)
|
axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/*)
|
||||||
printf '%s\n' "$SIM_DIR/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzacb-trsrn_twp/xyzacb-trsrn.ini"
|
printf '%s\n' "$SIM_DIR/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzacb-trsrn_twp/xyzacb-trsrn.ini"
|
||||||
@@ -289,7 +313,7 @@ while IFS= read -r ngc; do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ini="$(find_sim_ini "$rel" "$(dirname "$ngc")" || true)"
|
ini="$(find_sim_ini "$rel" "$(dirname "$ngc")" "$ngc" || true)"
|
||||||
if [[ -z "$ini" ]]; then
|
if [[ -z "$ini" ]]; then
|
||||||
printf '%s\tunsupported_runtime_edge\tmissing-ini\n' "$rel" >> "$BUILD_DIR/skipped.tsv"
|
printf '%s\tunsupported_runtime_edge\tmissing-ini\n' "$rel" >> "$BUILD_DIR/skipped.tsv"
|
||||||
skip=$((skip + 1))
|
skip=$((skip + 1))
|
||||||
|
|||||||
@@ -446,6 +446,18 @@ for (const fixtureName of INTERP_FILE_FIXTURES) {
|
|||||||
verifyExpectedOutput(fixtureName, interp.runFile(programPath), expectedEvents);
|
verifyExpectedOutput(fixtureName, interp.runFile(programPath), expectedEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verifyExpectedOutput(
|
||||||
|
"minimal_linear_run_steps",
|
||||||
|
interp.runFile("/work/minimal_linear.ngc"),
|
||||||
|
[
|
||||||
|
"run_step phase=read step=1 rc=0 line=1",
|
||||||
|
"run_step phase=execute step=1 rc=0 line=1 x=1 y=2 z=0",
|
||||||
|
"statement_uri=G0%20X1.0%20Y2.0%20%28Comment%29",
|
||||||
|
"run_step phase=execute step=2 rc=0 line=2 x=3 y=4 z=0",
|
||||||
|
"statement_uri=G1%20X3.0%20Y4.0%20F120.0",
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
|
||||||
const namedParamFilePath = `/work/${INTERP_INI_FIXTURE}.ngc`;
|
const namedParamFilePath = `/work/${INTERP_INI_FIXTURE}.ngc`;
|
||||||
interp.writeTextFile(namedParamFilePath, namedParamProgramText);
|
interp.writeTextFile(namedParamFilePath, namedParamProgramText);
|
||||||
verifyExpectedOutput(
|
verifyExpectedOutput(
|
||||||
|
|||||||
@@ -47,6 +47,54 @@ function runVendorNcFile(filename) {
|
|||||||
return interp.runFile(wasmPath);
|
return interp.runFile(wasmPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function runVendorNcFileWithToolTable(filename) {
|
||||||
|
const wasmDir = "/work/nc-files-context";
|
||||||
|
const wasmPath = `${wasmDir}/${filename}`;
|
||||||
|
const iniPath = `${wasmDir}/nc_files_context.ini`;
|
||||||
|
interp.writeTextFile(wasmPath, readFileSync(resolve(ncFilesDir, filename), "utf8"));
|
||||||
|
interp.writeTextFile(
|
||||||
|
`${wasmDir}/tool.tbl`,
|
||||||
|
"T1 P1 D10.000000 Z+0.000000 ; nc_files representative context tool\n",
|
||||||
|
);
|
||||||
|
interp.writeTextFile(
|
||||||
|
iniPath,
|
||||||
|
[
|
||||||
|
"[RS274NGC]",
|
||||||
|
"SUBROUTINE_PATH = .",
|
||||||
|
"",
|
||||||
|
"[TRAJ]",
|
||||||
|
"COORDINATES = X Y Z A B C U V W",
|
||||||
|
"",
|
||||||
|
"[EMCIO]",
|
||||||
|
"TOOL_TABLE = tool.tbl",
|
||||||
|
"",
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
return interp.runFileWithIni(wasmPath, iniPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyExpectedOutput(
|
||||||
|
"nc_files_3d_chips_context_wasm",
|
||||||
|
runVendorNcFileWithToolTable("3D_Chips.ngc"),
|
||||||
|
[
|
||||||
|
"file_open=0",
|
||||||
|
"file_read_count=4706",
|
||||||
|
"file_execute_count=4706",
|
||||||
|
"file_saw_error=0",
|
||||||
|
"run_step phase=execute step=18 rc=2 line=18",
|
||||||
|
"statement_uri=N50T%23%3Ctoolno%3EM6",
|
||||||
|
"run_step phase=execute step=19 rc=0 line=19",
|
||||||
|
"statement_uri=N60M8",
|
||||||
|
"canon_event=CHANGE_TOOL",
|
||||||
|
"canon_event=START_SPINDLE_CLOCKWISE spindle=0",
|
||||||
|
"canon_event=STRAIGHT_TRAVERSE line=21 x=0 y=0 z=10",
|
||||||
|
"canon_event=STRAIGHT_FEED line=23 x=53 y=-56.128 z=-25.372",
|
||||||
|
"canon_event=PROGRAM_END",
|
||||||
|
"absent=file_error_text=",
|
||||||
|
"absent=Requested tool 1 not found",
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
|
||||||
verifyExpectedOutput(
|
verifyExpectedOutput(
|
||||||
"nc_files_arcspiral_wasm",
|
"nc_files_arcspiral_wasm",
|
||||||
runVendorNcFile("arcspiral.ngc"),
|
runVendorNcFile("arcspiral.ngc"),
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ import { fileURLToPath } from "node:url";
|
|||||||
import { dirname, resolve } from "node:path";
|
import { dirname, resolve } from "node:path";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
|
|
||||||
import { createLinuxCncInterpSdk } from "../../../runtime/sdk/src/index.js";
|
import {
|
||||||
|
createLinuxCncInterpSdk,
|
||||||
|
planSimConfigStaging,
|
||||||
|
} from "../../../runtime/sdk/src/index.js";
|
||||||
|
|
||||||
function verifyExpectedOutput(fixtureName, output, expectedText) {
|
function verifyExpectedOutput(fixtureName, output, expectedText) {
|
||||||
const expectedLines = expectedText.split("\n").filter(Boolean);
|
const expectedLines = expectedText.split("\n").filter(Boolean);
|
||||||
@@ -32,6 +35,7 @@ const __dirname = dirname(__filename);
|
|||||||
const rootDir = resolve(__dirname, "../../..");
|
const rootDir = resolve(__dirname, "../../..");
|
||||||
const wasmPath = resolve(rootDir, "build/wasm/core/linuxcnc_interp.wasm");
|
const wasmPath = resolve(rootDir, "build/wasm/core/linuxcnc_interp.wasm");
|
||||||
const vendorRoot = resolve(rootDir, "vendor/linuxcnc");
|
const vendorRoot = resolve(rootDir, "vendor/linuxcnc");
|
||||||
|
const manifestText = readFileSync(resolve(rootDir, "tools/source-manifest.txt"), "utf8");
|
||||||
|
|
||||||
const interp = await createLinuxCncInterpSdk({
|
const interp = await createLinuxCncInterpSdk({
|
||||||
wasmBinary: readFileSync(wasmPath),
|
wasmBinary: readFileSync(wasmPath),
|
||||||
@@ -41,35 +45,72 @@ const interp = await createLinuxCncInterpSdk({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function vendorFile(sourceRel, wasmPath) {
|
const syntheticPlan = planSimConfigStaging({
|
||||||
const sourcePath = resolve(vendorRoot, sourceRel);
|
manifestText: [
|
||||||
|
"configs/sim/example/test.ini",
|
||||||
|
"configs/sim/example/test.ngc",
|
||||||
|
"configs/sim/example/tool.tbl",
|
||||||
|
"configs/sim/example/linuxcnc.var",
|
||||||
|
"configs/sim/example/subs/helper.ngc",
|
||||||
|
"configs/sim/example/M123",
|
||||||
|
].join("\n"),
|
||||||
|
machineRel: "example",
|
||||||
|
iniFile: "test.ini",
|
||||||
|
iniText: [
|
||||||
|
"[DISPLAY]",
|
||||||
|
"OPEN_FILE = test.ngc",
|
||||||
|
"[RS274NGC]",
|
||||||
|
"PARAMETER_FILE = linuxcnc.var",
|
||||||
|
"SUBROUTINE_PATH = subs",
|
||||||
|
"USER_M_PATH = .",
|
||||||
|
"[EMCIO]",
|
||||||
|
"TOOL_TABLE = tool.tbl",
|
||||||
|
].join("\n"),
|
||||||
|
});
|
||||||
|
assert.deepEqual(
|
||||||
|
syntheticPlan.files.map((file) => [file.sourceRel, file.executable]).sort(),
|
||||||
|
[
|
||||||
|
["configs/sim/example/M123", true],
|
||||||
|
["configs/sim/example/linuxcnc.var", false],
|
||||||
|
["configs/sim/example/subs/helper.ngc", false],
|
||||||
|
["configs/sim/example/test.ini", false],
|
||||||
|
["configs/sim/example/test.ngc", false],
|
||||||
|
["configs/sim/example/tool.tbl", false],
|
||||||
|
],
|
||||||
|
"synthetic sim-config staging plan",
|
||||||
|
);
|
||||||
|
|
||||||
|
function simMachine(machineRel, iniFile, programFile = null) {
|
||||||
|
const iniText = readFileSync(
|
||||||
|
resolve(vendorRoot, `configs/sim/${machineRel}/${iniFile}`),
|
||||||
|
"utf8",
|
||||||
|
);
|
||||||
|
const plan = planSimConfigStaging({
|
||||||
|
manifestText,
|
||||||
|
machineRel,
|
||||||
|
iniFile,
|
||||||
|
iniText,
|
||||||
|
programFile,
|
||||||
|
wasmDir: `/work/sim/${machineRel}`,
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
path: wasmPath,
|
...plan,
|
||||||
text: readFileSync(sourcePath, "utf8"),
|
files: plan.files.map((file) => ({
|
||||||
executable: (statSync(sourcePath).mode & 0o111) !== 0,
|
path: file.path,
|
||||||
|
text: readFileSync(resolve(vendorRoot, file.sourceRel), "utf8"),
|
||||||
|
executable:
|
||||||
|
file.executable || (statSync(resolve(vendorRoot, file.sourceRel)).mode & 0o111) !== 0,
|
||||||
|
})),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function simMachine(machineRel, files) {
|
const foam = simMachine("axis/foam", "axis_foam.ini", "foam.ngc");
|
||||||
const wasmDir = `/work/sim/${machineRel}`;
|
|
||||||
return {
|
|
||||||
wasmDir,
|
|
||||||
files: files.map((file) =>
|
|
||||||
vendorFile(`configs/sim/${machineRel}/${file}`, `${wasmDir}/${file}`),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const foam = simMachine("axis/foam", [
|
|
||||||
"axis_foam.ini",
|
|
||||||
"foam.ngc",
|
|
||||||
]);
|
|
||||||
verifyExpectedOutput(
|
verifyExpectedOutput(
|
||||||
"sim_axis_foam_uv_wasm",
|
"sim_axis_foam_uv_wasm",
|
||||||
interp.runSimConfigProgram({
|
interp.runSimConfigProgram({
|
||||||
files: foam.files,
|
files: foam.files,
|
||||||
programPath: `${foam.wasmDir}/foam.ngc`,
|
programPath: foam.programPath,
|
||||||
iniPath: `${foam.wasmDir}/axis_foam.ini`,
|
iniPath: foam.iniPath,
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
"file_open=0",
|
"file_open=0",
|
||||||
@@ -80,20 +121,17 @@ verifyExpectedOutput(
|
|||||||
].join("\n"),
|
].join("\n"),
|
||||||
);
|
);
|
||||||
|
|
||||||
const bridgeMill = simMachine("axis/vismach/5axis/bridgemill", [
|
const bridgeMill = simMachine(
|
||||||
|
"axis/vismach/5axis/bridgemill",
|
||||||
"5axis.ini",
|
"5axis.ini",
|
||||||
"5axis.tbl",
|
|
||||||
"5axisgui.ngc",
|
"5axisgui.ngc",
|
||||||
"remap_subs/428remap.ngc",
|
);
|
||||||
"remap_subs/429remap.ngc",
|
|
||||||
"remap_subs/430remap.ngc",
|
|
||||||
]);
|
|
||||||
verifyExpectedOutput(
|
verifyExpectedOutput(
|
||||||
"sim_axis_bridgemill_w_wasm",
|
"sim_axis_bridgemill_w_wasm",
|
||||||
interp.runSimConfigProgram({
|
interp.runSimConfigProgram({
|
||||||
files: bridgeMill.files,
|
files: bridgeMill.files,
|
||||||
programPath: `${bridgeMill.wasmDir}/5axisgui.ngc`,
|
programPath: bridgeMill.programPath,
|
||||||
iniPath: `${bridgeMill.wasmDir}/5axis.ini`,
|
iniPath: bridgeMill.iniPath,
|
||||||
executionMode: "fiveAxisRemap",
|
executionMode: "fiveAxisRemap",
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
@@ -115,17 +153,13 @@ verifyExpectedOutput(
|
|||||||
].join("\n"),
|
].join("\n"),
|
||||||
);
|
);
|
||||||
|
|
||||||
const geometry = simMachine("axis/geometry", [
|
const geometry = simMachine("axis/geometry", "xyzc.ini", "xyzc.ngc");
|
||||||
"M110",
|
|
||||||
"xyzc.ini",
|
|
||||||
"xyzc.ngc",
|
|
||||||
]);
|
|
||||||
verifyExpectedOutput(
|
verifyExpectedOutput(
|
||||||
"sim_axis_geometry_xyzc_user_m110_wasm",
|
"sim_axis_geometry_xyzc_user_m110_wasm",
|
||||||
interp.runSimConfigProgram({
|
interp.runSimConfigProgram({
|
||||||
files: geometry.files,
|
files: geometry.files,
|
||||||
programPath: `${geometry.wasmDir}/xyzc.ngc`,
|
programPath: geometry.programPath,
|
||||||
iniPath: `${geometry.wasmDir}/xyzc.ini`,
|
iniPath: geometry.iniPath,
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
"file_open=0",
|
"file_open=0",
|
||||||
@@ -137,25 +171,66 @@ verifyExpectedOutput(
|
|||||||
].join("\n"),
|
].join("\n"),
|
||||||
);
|
);
|
||||||
|
|
||||||
const externalOffsets = simMachine("axis/external_offsets", [
|
for (const externalOffsetCase of [
|
||||||
"M111",
|
{
|
||||||
"dyn_demo.ngc",
|
name: "dyn_demo",
|
||||||
"dynamic_offsets.ini",
|
program: "dyn_demo.ngc",
|
||||||
]);
|
ini: "dynamic_offsets.ini",
|
||||||
verifyExpectedOutput(
|
readCount: 833,
|
||||||
"sim_axis_external_offsets_user_m111_wasm",
|
firstTraverse: "canon_event=STRAIGHT_TRAVERSE line=21 x=0 y=0 z=0",
|
||||||
interp.runSimConfigProgram({
|
firstFeed: "canon_event=STRAIGHT_FEED line=26 x=9 y=0 z=1.5",
|
||||||
files: externalOffsets.files,
|
},
|
||||||
programPath: `${externalOffsets.wasmDir}/dyn_demo.ngc`,
|
{
|
||||||
iniPath: `${externalOffsets.wasmDir}/dynamic_offsets.ini`,
|
name: "eoffsets",
|
||||||
}),
|
program: "eoffsets.ngc",
|
||||||
[
|
ini: "eoffsets.ini",
|
||||||
"file_open=0",
|
readCount: 35,
|
||||||
"file_saw_error=0",
|
firstTraverse: "canon_event=STRAIGHT_TRAVERSE line=24 x=0 y=0 z=0",
|
||||||
"canon_event=USER_M_COMMAND code=M111",
|
firstFeed: "canon_event=STRAIGHT_FEED line=27 x=2.25 y=2.64 z=0",
|
||||||
"canon_event=PROGRAM_END",
|
},
|
||||||
"absent=Unknown m code used: M111",
|
{
|
||||||
].join("\n"),
|
name: "jwp_z",
|
||||||
);
|
program: "jwp_z.ngc",
|
||||||
|
ini: "jwp_z.ini",
|
||||||
|
readCount: 35,
|
||||||
|
firstTraverse: "canon_event=STRAIGHT_TRAVERSE line=17 x=0 y=0 z=0.5",
|
||||||
|
firstFeed: "canon_event=STRAIGHT_FEED line=24 x=2.5 y=3.3 z=0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "opa_demo",
|
||||||
|
program: "opa_demo.ngc",
|
||||||
|
ini: "opa.ini",
|
||||||
|
readCount: 58,
|
||||||
|
firstTraverse: "canon_event=STRAIGHT_TRAVERSE line=13 x=1 y=0 z=0",
|
||||||
|
firstFeed: "canon_event=STRAIGHT_FEED line=35 x=1 y=0 z=0",
|
||||||
|
},
|
||||||
|
]) {
|
||||||
|
const externalOffsets = simMachine(
|
||||||
|
"axis/external_offsets",
|
||||||
|
externalOffsetCase.ini,
|
||||||
|
externalOffsetCase.program,
|
||||||
|
);
|
||||||
|
verifyExpectedOutput(
|
||||||
|
`sim_axis_external_offsets_${externalOffsetCase.name}_user_m111_wasm`,
|
||||||
|
interp.runSimConfigProgram({
|
||||||
|
files: externalOffsets.files,
|
||||||
|
programPath: externalOffsets.programPath,
|
||||||
|
iniPath: externalOffsets.iniPath,
|
||||||
|
}),
|
||||||
|
[
|
||||||
|
"file_open=0",
|
||||||
|
`file_read_count=${externalOffsetCase.readCount}`,
|
||||||
|
`file_execute_count=${externalOffsetCase.readCount}`,
|
||||||
|
"file_saw_error=0",
|
||||||
|
"canon_event=USER_M_COMMAND code=M111",
|
||||||
|
externalOffsetCase.firstTraverse,
|
||||||
|
externalOffsetCase.firstFeed,
|
||||||
|
"canon_event=PROGRAM_END",
|
||||||
|
"absent=Unknown m code used: M111",
|
||||||
|
"absent=Bad character",
|
||||||
|
"absent=Cannot use axis values",
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
console.log("sim_configs_wasm_node_smoke=ok");
|
console.log("sim_configs_wasm_node_smoke=ok");
|
||||||
|
|||||||
@@ -346,9 +346,16 @@ tests/interp/abort-hot-comment/test.ngc
|
|||||||
tests/interp/abort-hot-comment/test.sh
|
tests/interp/abort-hot-comment/test.sh
|
||||||
configs/sim/axis/sim.tbl
|
configs/sim/axis/sim.tbl
|
||||||
configs/sim/axis/external_offsets/M111
|
configs/sim/axis/external_offsets/M111
|
||||||
|
configs/sim/axis/external_offsets/circles.ngc
|
||||||
configs/sim/axis/external_offsets/dyn_demo.ngc
|
configs/sim/axis/external_offsets/dyn_demo.ngc
|
||||||
configs/sim/axis/external_offsets/dynamic_offsets.ini
|
configs/sim/axis/external_offsets/dynamic_offsets.ini
|
||||||
configs/sim/axis/external_offsets/eoffset.tbl
|
configs/sim/axis/external_offsets/eoffset.tbl
|
||||||
|
configs/sim/axis/external_offsets/eoffsets.ini
|
||||||
|
configs/sim/axis/external_offsets/eoffsets.ngc
|
||||||
|
configs/sim/axis/external_offsets/jwp_z.ini
|
||||||
|
configs/sim/axis/external_offsets/jwp_z.ngc
|
||||||
|
configs/sim/axis/external_offsets/opa.ini
|
||||||
|
configs/sim/axis/external_offsets/opa_demo.ngc
|
||||||
configs/sim/axis/foam/axis_foam.ini
|
configs/sim/axis/foam/axis_foam.ini
|
||||||
configs/sim/axis/foam/foam.ngc
|
configs/sim/axis/foam/foam.ngc
|
||||||
configs/sim/axis/geometry/M110
|
configs/sim/axis/geometry/M110
|
||||||
@@ -403,6 +410,7 @@ configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini
|
|||||||
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.tbl
|
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.tbl
|
||||||
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.txt
|
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.txt
|
||||||
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.xml
|
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.xml
|
||||||
|
nc_files/3D_Chips.ngc
|
||||||
nc_files/arcspiral.ngc
|
nc_files/arcspiral.ngc
|
||||||
nc_files/factorial.ngc
|
nc_files/factorial.ngc
|
||||||
nc_files/hole-circle.ngc
|
nc_files/hole-circle.ngc
|
||||||
|
|||||||
43
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/circles.ngc
vendored
Normal file
43
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/circles.ngc
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
(info: Multiple circles at radius R, use 0 for current val)
|
||||||
|
;Notes:
|
||||||
|
; 1) z axis not altered (remains at current z)
|
||||||
|
; 2) for inside polygon cutting (fnum==0):
|
||||||
|
; start with rfraction negative
|
||||||
|
; and gradually increase rfraction to zero as program runs
|
||||||
|
; multiple circles
|
||||||
|
; 3) for outside polygon cutting (fnum==1):
|
||||||
|
; start with rfraction positive
|
||||||
|
; and gradually decrease to zero as program runs multiple
|
||||||
|
; circles
|
||||||
|
;
|
||||||
|
; Alternate method for polygons:
|
||||||
|
; 1) use #<radius>=0 and jog to safe starting position
|
||||||
|
; 2) use #<revs>=1, run program for one revolution
|
||||||
|
; 3) Run program repeatedly and manually jog x (radius)
|
||||||
|
; before each program start to increase/decrease
|
||||||
|
; current radius for inside/outside polygon respectively
|
||||||
|
|
||||||
|
o<circles> sub
|
||||||
|
#<radius> = #1 (= 1 R 0==>current)
|
||||||
|
#<aspeed> = #2 (= 8 aspeed: RPM)
|
||||||
|
#<lspeed> = #3 (= 10 lspeed: units/sec)
|
||||||
|
#<revs> = #4 (= 1 +/- Revolutions)
|
||||||
|
|
||||||
|
#<c> = #<_c> ;starting value
|
||||||
|
#<ctarget> = [#<c> + #<revs> * 360]
|
||||||
|
#<arate> = [#<aspeed> * 360]
|
||||||
|
|
||||||
|
m111 ;clear prior info messages
|
||||||
|
o<if1> if [#<radius> EQ 0]
|
||||||
|
#<ref_radius> = #<_x> ;use current x
|
||||||
|
o<if1> else
|
||||||
|
#<ref_radius> = #<radius>
|
||||||
|
f#<lspeed> g1 x#<ref_radius>
|
||||||
|
o<if1> endif
|
||||||
|
(debug, ref_radius=#<ref_radius>)
|
||||||
|
|
||||||
|
m68 e0 q#<ref_radius> ; set ref_radius for eoffsets
|
||||||
|
|
||||||
|
f#<arate> g1 c#<ctarget> ; circles at arate
|
||||||
|
|
||||||
|
o<circles> endsub
|
||||||
104
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini
vendored
Normal file
104
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini
vendored
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# Notes:
|
||||||
|
# 1) [AXIS_n]OFFSET_AV_RATIO= controls external offsets a,v
|
||||||
|
# Allowed values are 0.0 <= OFFSET_AV_RATIO <= 0.9
|
||||||
|
# Value of 0.0 disables external offsets
|
||||||
|
# Disallowed values are superseded with msg to stdout
|
||||||
|
# 2) Immediate homing herein
|
||||||
|
# ([JOINT_*]HOME_SEQUENCE=0, other HOME_* items omitted)
|
||||||
|
# 3) uncomment [JOINT_0]HOME_SEARCH_VEL,HOME_LATCH_VEL
|
||||||
|
# to demonstrate non-zero joint.0.motor-offset
|
||||||
|
|
||||||
|
[APPLICATIONS]
|
||||||
|
APP = sim_pin --title "MPG Simulator" \
|
||||||
|
e:xcounts \
|
||||||
|
e:ycounts \
|
||||||
|
e:zcounts
|
||||||
|
|
||||||
|
# make sure [xyz]:ecounts are zero if machine off:
|
||||||
|
APP = eoffsets_monitor.tcl
|
||||||
|
|
||||||
|
[HAL]
|
||||||
|
HALUI = halui
|
||||||
|
HALFILE = LIB:basic_sim.tcl -no_use_hal_manualtoolchange
|
||||||
|
HALFILE = eoffsets.hal
|
||||||
|
POSTGUI_HALFILE = eoffsets_panel.hal
|
||||||
|
|
||||||
|
[EMC]
|
||||||
|
MACHINE = External Offsets Demo
|
||||||
|
VERSION = 1.1
|
||||||
|
|
||||||
|
[DISPLAY]
|
||||||
|
PYVCP = eoffsets_panel.xml
|
||||||
|
DISPLAY = axis
|
||||||
|
POSITION_OFFSET = RELATIVE
|
||||||
|
POSITION_FEEDBACK = ACTUAL
|
||||||
|
MAX_LINEAR_VELOCITY = 2
|
||||||
|
OPEN_FILE = ./eoffsets.ngc
|
||||||
|
|
||||||
|
TKPKG = Ngcgui 1.0
|
||||||
|
NGCGUI_FONT = Helvetica -12 normal
|
||||||
|
NGCGUI_SUBFILE = queuebuster.ngc
|
||||||
|
|
||||||
|
[TASK]
|
||||||
|
TASK = milltask
|
||||||
|
CYCLE_TIME = 0.001
|
||||||
|
|
||||||
|
[RS274NGC]
|
||||||
|
SUBROUTINE_PATH = .
|
||||||
|
USER_M_PATH = .
|
||||||
|
PARAMETER_FILE = sim.var
|
||||||
|
|
||||||
|
[EMCIO]
|
||||||
|
TOOL_TABLE = eoffset.tbl
|
||||||
|
|
||||||
|
[EMCMOT]
|
||||||
|
EMCMOT = motmod
|
||||||
|
SERVO_PERIOD = 1000000
|
||||||
|
|
||||||
|
[TRAJ]
|
||||||
|
COORDINATES = XYZ
|
||||||
|
LINEAR_UNITS = inch
|
||||||
|
ANGULAR_UNITS = degree
|
||||||
|
|
||||||
|
[KINS]
|
||||||
|
JOINTS = 3
|
||||||
|
KINEMATICS = trivkins coordinates=XYZ
|
||||||
|
|
||||||
|
[AXIS_X]
|
||||||
|
OFFSET_AV_RATIO = 0.2
|
||||||
|
MAX_VELOCITY = 2
|
||||||
|
MAX_ACCELERATION = 20
|
||||||
|
MIN_LIMIT = -0.1
|
||||||
|
MAX_LIMIT = 10
|
||||||
|
|
||||||
|
[AXIS_Y]
|
||||||
|
OFFSET_AV_RATIO = 0.2
|
||||||
|
MAX_VELOCITY = 2
|
||||||
|
MAX_ACCELERATION = 20
|
||||||
|
MIN_LIMIT = -0.1
|
||||||
|
MAX_LIMIT = 5
|
||||||
|
|
||||||
|
[AXIS_Z]
|
||||||
|
OFFSET_AV_RATIO = 0.2
|
||||||
|
MAX_VELOCITY = 2
|
||||||
|
MAX_ACCELERATION = 20
|
||||||
|
MIN_LIMIT = -1
|
||||||
|
MAX_LIMIT = 1
|
||||||
|
|
||||||
|
[JOINT_0]
|
||||||
|
TYPE = LINEAR
|
||||||
|
HOME_SEQUENCE = 0
|
||||||
|
MAX_VELOCITY = 2
|
||||||
|
MAX_ACCELERATION = 20
|
||||||
|
|
||||||
|
[JOINT_1]
|
||||||
|
TYPE = LINEAR
|
||||||
|
HOME_SEQUENCE = 0
|
||||||
|
MAX_VELOCITY = 2
|
||||||
|
MAX_ACCELERATION = 20
|
||||||
|
|
||||||
|
[JOINT_2]
|
||||||
|
TYPE = LINEAR
|
||||||
|
HOME_SEQUENCE = 0
|
||||||
|
MAX_VELOCITY = 2
|
||||||
|
MAX_ACCELERATION = 20
|
||||||
35
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc
vendored
Normal file
35
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#<xmax> = 9
|
||||||
|
#<ymax> = 4
|
||||||
|
#<zdepth> = 0
|
||||||
|
#<feed> = 20
|
||||||
|
|
||||||
|
#<x1> = [0.25 * #<xmax>]
|
||||||
|
#<y1> = [0.66 * #<ymax>]
|
||||||
|
#<z1> = 0
|
||||||
|
|
||||||
|
#<x2> = [0.50 * #<xmax>]
|
||||||
|
#<y2> = 0
|
||||||
|
#<z2> = -.5
|
||||||
|
|
||||||
|
#<x3> = [0.75 * #<xmax>]
|
||||||
|
#<y3> = 0
|
||||||
|
#<z3> = 0
|
||||||
|
|
||||||
|
#<x4> = #<x3>
|
||||||
|
#<y4> = #<y1>
|
||||||
|
#<z4> = 0
|
||||||
|
|
||||||
|
m111 ;clear notifications
|
||||||
|
g61
|
||||||
|
g0x0y0z0
|
||||||
|
|
||||||
|
f #<feed>
|
||||||
|
g1 x #<x1> y #<y1> z #<z1>
|
||||||
|
g1 x #<x2> y #<y2> z #<z2>
|
||||||
|
g1 x #<x3> y #<y3> z #<z3>
|
||||||
|
g1 x #<x4> y #<y4> z #<z4>
|
||||||
|
g1 x #<xmax> y #<ymax>
|
||||||
|
g0x0y0z0
|
||||||
|
|
||||||
|
m111 ;clear notifications
|
||||||
|
m2
|
||||||
86
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/jwp_z.ini
vendored
Normal file
86
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/jwp_z.ini
vendored
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# Notes:
|
||||||
|
# 1) [AXIS_n]OFFSET_AV_RATIO= controls external offsets a,v
|
||||||
|
# Allowed values are 0.0 <= OFFSET_AV_RATIO <= 0.9
|
||||||
|
# Value of 0.0 disables external offsets
|
||||||
|
# Disallowed values are superseded with msg to stdout
|
||||||
|
# 2) Immediate homing herein
|
||||||
|
# ([JOINT_*]HOME_SEQUENCE=0, other HOME_* items omitted)
|
||||||
|
# 3) uncomment [JOINT_0]HOME_SEARCH_VEL,HOME_LATCH_VEL
|
||||||
|
# to demonstrate non-zero joint.0.motor-offset
|
||||||
|
|
||||||
|
|
||||||
|
[HAL]
|
||||||
|
HALUI = halui
|
||||||
|
HALFILE = LIB:basic_sim.tcl
|
||||||
|
POSTGUI_HALFILE = jwp_z_panel.hal
|
||||||
|
|
||||||
|
[EMC]
|
||||||
|
MACHINE = Jog-While-Pause Z Demo
|
||||||
|
VERSION = 1.1
|
||||||
|
|
||||||
|
[DISPLAY]
|
||||||
|
PYVCP = jwp_z_panel.xml
|
||||||
|
DISPLAY = axis
|
||||||
|
POSITION_OFFSET = RELATIVE
|
||||||
|
POSITION_FEEDBACK = ACTUAL
|
||||||
|
MAX_LINEAR_VELOCITY = 2
|
||||||
|
OPEN_FILE = ./jwp_z.ngc
|
||||||
|
|
||||||
|
[TASK]
|
||||||
|
TASK = milltask
|
||||||
|
CYCLE_TIME = 0.001
|
||||||
|
|
||||||
|
[RS274NGC]
|
||||||
|
USER_M_PATH = .
|
||||||
|
PARAMETER_FILE = sim.var
|
||||||
|
|
||||||
|
[EMCMOT]
|
||||||
|
EMCMOT = motmod
|
||||||
|
SERVO_PERIOD = 1000000
|
||||||
|
|
||||||
|
[TRAJ]
|
||||||
|
COORDINATES = XYZ
|
||||||
|
LINEAR_UNITS = inch
|
||||||
|
ANGULAR_UNITS = degree
|
||||||
|
|
||||||
|
[KINS]
|
||||||
|
JOINTS = 3
|
||||||
|
KINEMATICS = trivkins coordinates=XYZ
|
||||||
|
|
||||||
|
[AXIS_X]
|
||||||
|
MIN_LIMIT = -1
|
||||||
|
MAX_LIMIT = 11
|
||||||
|
MAX_VELOCITY = 2
|
||||||
|
MAX_ACCELERATION = 20
|
||||||
|
|
||||||
|
[AXIS_Y]
|
||||||
|
MIN_LIMIT = -1
|
||||||
|
MAX_LIMIT = 5
|
||||||
|
MAX_VELOCITY = 2
|
||||||
|
MAX_ACCELERATION = 20
|
||||||
|
|
||||||
|
[AXIS_Z]
|
||||||
|
# Note: low OFFSET_AV_RATIO:
|
||||||
|
OFFSET_AV_RATIO = 0.05
|
||||||
|
MIN_LIMIT = -1
|
||||||
|
MAX_LIMIT = 1
|
||||||
|
MAX_VELOCITY = 2
|
||||||
|
MAX_ACCELERATION = 20
|
||||||
|
|
||||||
|
[JOINT_0]
|
||||||
|
TYPE = LINEAR
|
||||||
|
HOME_SEQUENCE = 0
|
||||||
|
MAX_VELOCITY = 2
|
||||||
|
MAX_ACCELERATION = 20
|
||||||
|
|
||||||
|
[JOINT_1]
|
||||||
|
TYPE = LINEAR
|
||||||
|
HOME_SEQUENCE = 0
|
||||||
|
MAX_VELOCITY = 2
|
||||||
|
MAX_ACCELERATION = 20
|
||||||
|
|
||||||
|
[JOINT_2]
|
||||||
|
TYPE = LINEAR
|
||||||
|
HOME_SEQUENCE = 0
|
||||||
|
MAX_VELOCITY = 2
|
||||||
|
MAX_ACCELERATION = 20
|
||||||
35
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/jwp_z.ngc
vendored
Normal file
35
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/jwp_z.ngc
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#<xmax> = 10
|
||||||
|
#<ymax> = 5
|
||||||
|
#<zsafe> = 0.5
|
||||||
|
#<feed> = 100
|
||||||
|
|
||||||
|
#<x1> = [0.25 * #<xmax>]
|
||||||
|
#<y1> = [0.66 * #<ymax>]
|
||||||
|
|
||||||
|
#<x2> = [0.50 * #<xmax>]
|
||||||
|
#<y2> = [0.33 * #<ymax>]
|
||||||
|
|
||||||
|
#<x3> = [0.75 * #<xmax>]
|
||||||
|
#<y3> = [0.33 * #<ymax>]
|
||||||
|
|
||||||
|
m111 ;clear notifications
|
||||||
|
g61
|
||||||
|
g0 x0 y0 z#<zsafe>
|
||||||
|
(debug, Enter offsets only when paused, s to continue)
|
||||||
|
m0
|
||||||
|
m111
|
||||||
|
|
||||||
|
f #<feed>
|
||||||
|
g0 z0
|
||||||
|
g1 x #<x1> y #<y1>
|
||||||
|
g1 x #<x2> y #<y2>
|
||||||
|
g1 x #<x3> y #<y3>
|
||||||
|
g1 x #<xmax> y #<ymax>
|
||||||
|
|
||||||
|
g0 z#<zsafe>
|
||||||
|
(debug, Program End: Clear offsets, s to continue)
|
||||||
|
m0
|
||||||
|
g0 x0 y0
|
||||||
|
|
||||||
|
m111 ;clear notifications
|
||||||
|
m2
|
||||||
87
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/opa.ini
vendored
Normal file
87
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/opa.ini
vendored
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
[APPLICATIONS]
|
||||||
|
DELAY = 3
|
||||||
|
# For assessing system accel/vel:
|
||||||
|
# (particularly when using func3 square wave modulation)
|
||||||
|
APP = sim_pin ini.x.max_acceleration ini.x.max_velocity
|
||||||
|
|
||||||
|
[HAL]
|
||||||
|
HALUI = halui
|
||||||
|
HALFILE = LIB:basic_sim.tcl
|
||||||
|
HALFILE = opa.hal
|
||||||
|
POSTGUI_HALFILE = opa_panel.hal
|
||||||
|
|
||||||
|
[EMC]
|
||||||
|
MACHINE = External Offset(X) per Angle(C) Demo
|
||||||
|
VERSION = 1.1
|
||||||
|
|
||||||
|
[DISPLAY]
|
||||||
|
PYVCP = opa_panel.xml
|
||||||
|
DISPLAY = axis
|
||||||
|
OPEN_FILE = opa_demo.ngc
|
||||||
|
GEOMETRY = !CXZ
|
||||||
|
POSITION_OFFSET = RELATIVE
|
||||||
|
POSITION_FEEDBACK = ACTUAL
|
||||||
|
MAX_LINEAR_VELOCITY = 2
|
||||||
|
MAX_ANGULAR_VELOCITY = 60
|
||||||
|
|
||||||
|
TKPKG = Ngcgui 1.0
|
||||||
|
NGCGUI_FONT = Helvetica -12 normal
|
||||||
|
NGCGUI_SUBFILE = circles.ngc
|
||||||
|
|
||||||
|
[TASK]
|
||||||
|
TASK = milltask
|
||||||
|
CYCLE_TIME = 0.001
|
||||||
|
|
||||||
|
[RS274NGC]
|
||||||
|
SUBROUTINE_PATH = .
|
||||||
|
USER_M_PATH = .
|
||||||
|
PARAMETER_FILE = sim.var
|
||||||
|
|
||||||
|
[EMCIO]
|
||||||
|
TOOL_TABLE = eoffset.tbl
|
||||||
|
|
||||||
|
[EMCMOT]
|
||||||
|
EMCMOT = motmod
|
||||||
|
SERVO_PERIOD = 1000000
|
||||||
|
|
||||||
|
[TRAJ]
|
||||||
|
COORDINATES = XZC
|
||||||
|
LINEAR_UNITS = inch
|
||||||
|
ANGULAR_UNITS = degree
|
||||||
|
|
||||||
|
[KINS]
|
||||||
|
JOINTS = 3
|
||||||
|
KINEMATICS = trivkins coordinates=XZC
|
||||||
|
|
||||||
|
[AXIS_X]
|
||||||
|
OFFSET_AV_RATIO = 0.5
|
||||||
|
MAX_VELOCITY = 5
|
||||||
|
# increase MAX_ACCELERATION to improve
|
||||||
|
# waveform tracking:
|
||||||
|
MAX_ACCELERATION = 50
|
||||||
|
|
||||||
|
[AXIS_Z]
|
||||||
|
MAX_VELOCITY = 5
|
||||||
|
MAX_ACCELERATION = 10
|
||||||
|
|
||||||
|
[AXIS_C]
|
||||||
|
MAX_VELOCITY = 60
|
||||||
|
MAX_ACCELERATION = 600
|
||||||
|
|
||||||
|
[JOINT_0]
|
||||||
|
TYPE = LINEAR
|
||||||
|
HOME_SEQUENCE = 0
|
||||||
|
MAX_VELOCITY = 5
|
||||||
|
MAX_ACCELERATION = 50
|
||||||
|
|
||||||
|
[JOINT_1]
|
||||||
|
TYPE = LINEAR
|
||||||
|
HOME_SEQUENCE = 0
|
||||||
|
MAX_VELOCITY = 5
|
||||||
|
MAX_ACCELERATION = 10
|
||||||
|
|
||||||
|
[JOINT_2]
|
||||||
|
TYPE = ANGULAR
|
||||||
|
HOME_SEQUENCE = 0
|
||||||
|
MAX_VELOCITY = 60
|
||||||
|
MAX_ACCELERATION = 600
|
||||||
15
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/opa_demo.ngc
vendored
Normal file
15
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/opa_demo.ngc
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
; opa_demo.ngc:
|
||||||
|
; invoke subroutine circles.ngc for multiple circles (#<revs>)
|
||||||
|
; with:
|
||||||
|
; x = #<radius>
|
||||||
|
; z = #<_z>
|
||||||
|
|
||||||
|
#<radius> = 1
|
||||||
|
#<z> = #<_z> ; current value
|
||||||
|
#<aspeed> = 8 ; angular speed (RPM)
|
||||||
|
#<lspeed> = 10 ; linear speed (units/minute)
|
||||||
|
#<revs> = 100
|
||||||
|
|
||||||
|
g0 x#<radius> z#<z>
|
||||||
|
o<circles> call [#<radius>][#<aspeed>][#<lspeed>][#<revs>]
|
||||||
|
m2
|
||||||
4711
wasm-port/vendor/linuxcnc/nc_files/3D_Chips.ngc
vendored
Normal file
4711
wasm-port/vendor/linuxcnc/nc_files/3D_Chips.ngc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user