From 7cdfc458f9523c36a18f9ffe82b994f150937bb3 Mon Sep 17 00:00:00 2001 From: wangdequan Date: Mon, 8 Jun 2026 18:12:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=89=E8=A7=84=E5=88=92=E6=8C=81=E7=BB=AD?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 结论:浏览器 interpreter smoke 和 INI panel UI 已接入 vendored LinuxCNC 五轴 switchkins remap 执行路径,只复制 LinuxCNC sample machine 文件到 WASM FS 并调用 SDK C ABI;host 聚合 smoke 通过,未新增 JavaScript M428/M429/M430 或运动学语义。 --- wasm-port/docs/compatibility-validation.md | 17 +++- wasm-port/docs/porting-steps-standalone.md | 11 ++- wasm-port/docs/source-reuse-map.md | 11 +-- wasm-port/runtime/sdk/README.md | 6 ++ wasm-port/runtime/ui/ini-panel/app.js | 70 ++++++++++++++++ wasm-port/runtime/ui/ini-panel/index.html | 3 + wasm-port/tests/browser/ini_panel_smoke.html | 20 +++++ wasm-port/tests/browser/interp_smoke.html | 86 ++++++++++++++++++++ 8 files changed, 211 insertions(+), 13 deletions(-) diff --git a/wasm-port/docs/compatibility-validation.md b/wasm-port/docs/compatibility-validation.md index c765d89..86dbf78 100644 --- a/wasm-port/docs/compatibility-validation.md +++ b/wasm-port/docs/compatibility-validation.md @@ -158,7 +158,12 @@ snapshot filename/envelope, machine file, G-code text round trip, and G-code filename path-model rejection. It also verifies that the INI panel UI exposes LinuxCNC-backed `[RS274NGC]PARAMETER_FILE` and `[EMCIO]TOOL_TABLE` query results, plus the default OPFS parameter-file and tool-table mappings used -when a machine session is copied into the interpreter WASM filesystem. +when a machine session is copied into the interpreter WASM filesystem. It also +clicks the INI panel's 5-axis remap demo action and verifies that the UI +copies vendored LinuxCNC `xyzac-trt` machine/remap/demo files into the +interpreter WASM filesystem, calls the LinuxCNC-backed SDK remap execution +path, and displays the resulting `fiveaxis_*` status lines without JavaScript +M-code or kinematics semantics. The browser interpreter smoke script serves `wasm-port/` over localhost and runs Chromium headless against a test page that loads the interpreter-core @@ -189,7 +194,11 @@ path model after the names are parsed by the LinuxCNC-backed INI WASM SDK. It also verifies that explicit session parameter/tool-table file-name options override INI-derived names before OPFS text is copied into the LinuxCNC-backed WASM filesystem, and that absent INI file-name values use the default OPFS -parameter/tool-table paths in a real browser session. +parameter/tool-table paths in a real browser session. It also writes vendored +LinuxCNC `xyzac-trt`/`xyzbc-trt` INI, remap subroutines, and switchkins demo +files into the browser WASM filesystem and verifies `runFiveAxisRemapFile()` +for both sample machines through the exported LinuxCNC remap/file execution +path. The aggregate host smoke script builds the INI, interpreter-core, and trajectory-planner WASM artifacts once, then runs the Node WASM smokes, the @@ -247,8 +256,8 @@ The validation fails if: | `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 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_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/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, and canonical-event display paths 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 through vendored LinuxCNC `Interp::execute()` plus `Interp::open()`/`read()`/`execute()` via the exported C ABI, including direct browser SDK and OPFS-backed parameter-file restore/save plus non-random/random tool-table load/save through vendored LinuxCNC source. | +| `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_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 through vendored LinuxCNC `Interp::execute()` plus `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, and vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo execution. | | `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 diff --git a/wasm-port/docs/porting-steps-standalone.md b/wasm-port/docs/porting-steps-standalone.md index 420ab4e..e79ae22 100644 --- a/wasm-port/docs/porting-steps-standalone.md +++ b/wasm-port/docs/porting-steps-standalone.md @@ -810,13 +810,16 @@ Current five-axis switchkins status: Python-only runtime edge stub, and the Node WASM smoke runs vendored `xyzac_switchkins.ngc` and `xyzbc_switchkins.ngc` through the SDK C ABI without JavaScript M-code or kinematics semantics. +8. Browser smoke and the INI panel UI now expose the same validated 5-axis + remap execution path by copying vendored LinuxCNC sample-machine files into + the interpreter WASM filesystem and calling the SDK C ABI. Next work: -1. Add browser smoke/UI exposure for the validated switchkins/remap status - without adding JavaScript CNC semantics. -2. Continue broadening five-axis fixture coverage after the browser path is - stable. +1. Continue broadening five-axis fixture coverage after the native, Node WASM, + browser, and UI remap paths are stable. +2. Evaluate larger vendored LinuxCNC TRT demos such as boat/impeller through + the same source-backed execution boundary. Involved LinuxCNC source: diff --git a/wasm-port/docs/source-reuse-map.md b/wasm-port/docs/source-reuse-map.md index 9379067..87192fb 100644 --- a/wasm-port/docs/source-reuse-map.md +++ b/wasm-port/docs/source-reuse-map.md @@ -40,7 +40,7 @@ Current validation is intentionally mechanical: | Identity/trivial kinematics | `src/emc/kinematics/kinematics.h`, `cubic.h`, `kins_util.c`, `trivkins.c` | Copy unchanged | HAL component lifecycle and RTAPI module metadata are replaced by standalone shims; forward/inverse mapping behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_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` | -| 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`, browser INI panel sample loaded from vendored `xyzab-tdr.ini` | +| 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/browser/verify_interp_browser.sh`, `tests/browser/verify_ini_panel_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` | | Trajectory planner | `src/emc/tp/tp.c`, `tc.c`, `tcq.c`, `spherical_arc.c`, `blendmath.c`, `sp_scurve.c`, `ruckig_wrapper.c`, plus matching `*.h` files | Copy unchanged | Native realtime scheduling and motion process state are replaced by standalone probe setup; the WASM TP probe uses the same deterministic status/config boundary and calls vendored TP APIs through a narrow C ABI | Vendor byte sync, per-file source probes, `linuxcnc_tp_api_probe`, `tests/wasm/node/verify_tp_wasm.sh` | | Ruckig C planner support | Selected `src/emc/tp/cruckig/*.c` and `*.h` files in the manifest | Copy unchanged | Used as LinuxCNC planner support code through vendored TP sources | Vendor byte sync, per-file source probes, `tests/wasm/node/verify_tp_wasm.sh` | @@ -74,10 +74,11 @@ Current validation is intentionally mechanical: dual-rotary, and table-rotary-tilting LinuxCNC sample machines. NGC remap descriptors for the TRT sample machines are parsed through vendored `Interp::parse_remap()` and `find_ngc_file()` by - `linuxcnc_remap_parse_harness`; native and WASM Node validation execute the - selected TRT switchkins demo files through vendored LinuxCNC O-word remap - dispatch, file `open()`/`read()`/`execute()`, and the standalone HAL adapter - boundary for `M68`/`M66` plus `_hal[motion.switchkins-type]` readback. + `linuxcnc_remap_parse_harness`; native, WASM Node, browser interpreter, and + INI panel UI validation execute the selected TRT switchkins demo files + through vendored LinuxCNC O-word remap dispatch, file + `open()`/`read()`/`execute()`, and the standalone HAL adapter boundary for + `M68`/`M66` plus `_hal[motion.switchkins-type]` readback. - Cutter compensation positive motion and negative interpreter paths are fixture-covered through vendored `interp_convert.cc` and `interp_queue.cc`. - Browser/WASM C ABI and JS SDK layers are now present for the INI parser, the diff --git a/wasm-port/runtime/sdk/README.md b/wasm-port/runtime/sdk/README.md index a319c23..9807777 100644 --- a/wasm-port/runtime/sdk/README.md +++ b/wasm-port/runtime/sdk/README.md @@ -39,6 +39,7 @@ vendored LinuxCNC RS274NGC sources and exposes: - `runProgramWithIni(programText, iniPath)` - `runFile(path)` - `runFileWithIni(path, iniPath)` +- `runFiveAxisRemapFile(path, iniPath)` - `restoreParameters(path)` - `saveParameters(path, values)` - `loadToolTable(path, options)` @@ -49,3 +50,8 @@ vendored LinuxCNC RS274NGC sources and exposes: `loadToolTable()` accepts `{ randomToolChanger: true }` to select the LinuxCNC random-toolchanger branch before calling vendored `tooldata_load()`. The SDK only forwards that runtime boundary flag. + +`runFiveAxisRemapFile()` is a narrow host boundary for vendored LinuxCNC +sample-machine remap validation. Callers provide INI/remap/demo files in the +WASM filesystem; the C ABI runs vendored LinuxCNC `REMAP`, O-word, file +execution, and HAL adapter paths. diff --git a/wasm-port/runtime/ui/ini-panel/app.js b/wasm-port/runtime/ui/ini-panel/app.js index 868c3b5..ac1f346 100644 --- a/wasm-port/runtime/ui/ini-panel/app.js +++ b/wasm-port/runtime/ui/ini-panel/app.js @@ -20,6 +20,19 @@ import { const SAMPLE_PATH = "../../../vendor/linuxcnc/configs/sim/axis/vismach/5axis/table-dual-rotary/xyzab-tdr.ini"; +const FIVEAXIS_TRT_SOURCE_PATH = + "../../../vendor/linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting"; +const FIVEAXIS_TRT_WASM_DIR = "/work/ui-fiveaxis/table-rotary-tilting"; +const FIVEAXIS_REMAP_FILES = [ + "428remap.ngc", + "429remap.ngc", + "430remap.ngc", + "centering.ngc", + "helix_ac.ngc", + "helix_bc.ngc", + "xyzac_switchkins_sub.ngc", + "xyzbc_switchkins_sub.ngc", +]; const MACHINE_ID = "xyzab-tdr"; const MACHINE_PATHS = machineFilePaths(MACHINE_ID); const OPFS_FILE = MACHINE_PATHS.ini; @@ -68,6 +81,7 @@ const fields = { sessionToolTable: document.getElementById("field-session-tool-table"), sessionGcode: document.getElementById("field-session-gcode"), runStatus: document.getElementById("field-run-status"), + fiveaxisRemap: document.getElementById("field-fiveaxis-remap"), }; let iniSdk = null; @@ -133,6 +147,38 @@ async function loadSample() { setLog("Loaded LinuxCNC sample INI into the standalone editor."); } +async function fetchTextFile(path) { + const response = await fetch(path); + if (!response.ok) { + throw new Error(`Cannot fetch ${path} (${response.status})`); + } + return response.text(); +} + +async function writeFetchedTextFile(interp, sourcePath, wasmPath) { + interp.writeTextFile(wasmPath, await fetchTextFile(sourcePath)); +} + +async function writeFiveAxisTrtMachineFiles(interp) { + await writeFetchedTextFile( + interp, + `${FIVEAXIS_TRT_SOURCE_PATH}/xyzac-trt.ini`, + `${FIVEAXIS_TRT_WASM_DIR}/xyzac-trt.ini`, + ); + for (const filename of FIVEAXIS_REMAP_FILES) { + await writeFetchedTextFile( + interp, + `${FIVEAXIS_TRT_SOURCE_PATH}/remap_subs/${filename}`, + `${FIVEAXIS_TRT_WASM_DIR}/remap_subs/${filename}`, + ); + } + await writeFetchedTextFile( + interp, + `${FIVEAXIS_TRT_SOURCE_PATH}/demos/xyzac_switchkins.ngc`, + `${FIVEAXIS_TRT_WASM_DIR}/demos/xyzac_switchkins.ngc`, + ); +} + async function boot() { try { iniSdk = await createLinuxCncIniSdk(); @@ -255,6 +301,30 @@ document.getElementById("run-gcode").addEventListener("click", async () => { } }); +document.getElementById("run-fiveaxis-remap").addEventListener("click", async () => { + try { + const interp = requireInterpSdk(); + await writeFiveAxisTrtMachineFiles(interp); + const iniPath = `${FIVEAXIS_TRT_WASM_DIR}/xyzac-trt.ini`; + const programPath = `${FIVEAXIS_TRT_WASM_DIR}/demos/xyzac_switchkins.ngc`; + const result = interp.runFiveAxisRemapFile(programPath, iniPath); + setField("fiveaxisRemap", "ok"); + setCanonicalEvents(result.trim()); + setLog( + [ + "Ran LinuxCNC 5-axis switchkins remap demo through interpreter WASM.", + `Program: ${programPath}`, + `INI: ${iniPath}`, + result.trim(), + ].join("\n"), + ); + } catch (error) { + setField("fiveaxisRemap", "failed"); + setCanonicalEvents(""); + setLog(`5-axis remap run failed: ${error.message}`, true); + } +}); + document.getElementById("load-opfs").addEventListener("click", async () => { try { editor.value = await loadTextFile(OPFS_FILE); diff --git a/wasm-port/runtime/ui/ini-panel/index.html b/wasm-port/runtime/ui/ini-panel/index.html index 4dbd5a0..760fcaa 100644 --- a/wasm-port/runtime/ui/ini-panel/index.html +++ b/wasm-port/runtime/ui/ini-panel/index.html @@ -180,6 +180,7 @@ + @@ -221,6 +222,8 @@
-
Run Status
-
+
5-Axis Remap
+
-
diff --git a/wasm-port/tests/browser/ini_panel_smoke.html b/wasm-port/tests/browser/ini_panel_smoke.html index 509727b..cf175c8 100644 --- a/wasm-port/tests/browser/ini_panel_smoke.html +++ b/wasm-port/tests/browser/ini_panel_smoke.html @@ -360,6 +360,26 @@ TOOL_TABLE = browser-tool.tbl "UI canonical event count", ); + uiDocument.getElementById("run-fiveaxis-remap").click(); + await waitFor( + () => uiDocument.getElementById("log")?.textContent.includes("Ran LinuxCNC 5-axis"), + "5-axis remap run", + ); + assertEqual( + uiDocument.getElementById("field-fiveaxis-remap").textContent, + "ok", + "UI 5-axis remap status", + ); + const remapLog = uiDocument.getElementById("log").textContent; + if ( + !remapLog.includes("fiveaxis_ini_open=1") || + !remapLog.includes("fiveaxis_file_read_count=620") || + !remapLog.includes("fiveaxis_hal_switchkins: rc=0 found=1 value=0") || + !remapLog.includes("fiveaxis_linuxcnc_remap_file_execute=1") + ) { + throw new Error(`UI 5-axis remap run missing LinuxCNC result: ${remapLog}`); + } + status.textContent = "browser_ini_opfs_smoke=ok"; } catch (error) { status.textContent = `browser_ini_opfs_smoke=fail ${error.stack || error.message}`; diff --git a/wasm-port/tests/browser/interp_smoke.html b/wasm-port/tests/browser/interp_smoke.html index a78f4c0..0ac37b5 100644 --- a/wasm-port/tests/browser/interp_smoke.html +++ b/wasm-port/tests/browser/interp_smoke.html @@ -93,6 +93,50 @@ } } + async function writeFetchedTextFile(interp, sourcePath, wasmPath) { + interp.writeTextFile(wasmPath, await fetchText(sourcePath)); + } + + async function writeFiveAxisTrtMachineFiles(interp) { + const sourceDir = + "../../vendor/linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting"; + const wasmDir = "/work/browser-fiveaxis/table-rotary-tilting"; + const remapFiles = [ + "428remap.ngc", + "429remap.ngc", + "430remap.ngc", + "centering.ngc", + "helix_ac.ngc", + "helix_bc.ngc", + "xyzac_switchkins_sub.ngc", + "xyzbc_switchkins_sub.ngc", + ]; + + await writeFetchedTextFile(interp, `${sourceDir}/xyzac-trt.ini`, `${wasmDir}/xyzac-trt.ini`); + await writeFetchedTextFile(interp, `${sourceDir}/xyzbc-trt.ini`, `${wasmDir}/xyzbc-trt.ini`); + + for (const filename of remapFiles) { + await writeFetchedTextFile( + interp, + `${sourceDir}/remap_subs/${filename}`, + `${wasmDir}/remap_subs/${filename}`, + ); + } + + await writeFetchedTextFile( + interp, + `${sourceDir}/demos/xyzac_switchkins.ngc`, + `${wasmDir}/demos/xyzac_switchkins.ngc`, + ); + await writeFetchedTextFile( + interp, + `${sourceDir}/demos/xyzbc_switchkins.ngc`, + `${wasmDir}/demos/xyzbc_switchkins.ngc`, + ); + + return wasmDir; + } + async function verifyRejects(fixtureName, operation, expectedPattern) { try { await operation(); @@ -310,6 +354,48 @@ baselineIniExpectedText, ); + const fiveAxisTrtDir = await writeFiveAxisTrtMachineFiles(interp); + verifyExpectedOutput( + "browser_fiveaxis_xyzac_switchkins", + interp.runFiveAxisRemapFile( + `${fiveAxisTrtDir}/demos/xyzac_switchkins.ngc`, + `${fiveAxisTrtDir}/xyzac-trt.ini`, + ), + [ + "fiveaxis_ini_open=1", + "fiveaxis_parse_remap_1=0", + "fiveaxis_parse_remap_2=0", + "fiveaxis_parse_remap_3=0", + "fiveaxis_file_open=0", + "fiveaxis_file_read_count=620", + "fiveaxis_file_execute_count=620", + "fiveaxis_file_finish_count=21", + "fiveaxis_file_reached_exit=1", + "fiveaxis_hal_switchkins: rc=0 found=1 value=0", + "fiveaxis_linuxcnc_remap_file_execute=1", + ].join("\n"), + ); + verifyExpectedOutput( + "browser_fiveaxis_xyzbc_switchkins", + interp.runFiveAxisRemapFile( + `${fiveAxisTrtDir}/demos/xyzbc_switchkins.ngc`, + `${fiveAxisTrtDir}/xyzbc-trt.ini`, + ), + [ + "fiveaxis_ini_open=1", + "fiveaxis_parse_remap_1=0", + "fiveaxis_parse_remap_2=0", + "fiveaxis_parse_remap_3=0", + "fiveaxis_file_open=0", + "fiveaxis_file_read_count=620", + "fiveaxis_file_execute_count=620", + "fiveaxis_file_finish_count=21", + "fiveaxis_file_reached_exit=1", + "fiveaxis_hal_switchkins: rc=0 found=1 value=0", + "fiveaxis_linuxcnc_remap_file_execute=1", + ].join("\n"), + ); + verifyExpectedOutput( "restore_parameters_missing_file", interp.restoreParameters("/work/browser-missing.var"),