LinuxCNC Web/WASM CNC Simulator
本目录是把 LinuxCNC 面向浏览器仿真的改写入口。目标不是把完整 LinuxCNC 直接搬进浏览器,而是复用可移植的解释器、运动学和刀路算法,替换实时 HAL/NML/GUI 层,输出适合 Web Worker、Three.js/WebGPU 和后续碰撞/去料仿真的事件流。
关键判断
- 不能按“整套 LinuxCNC 编译为 wasm”做。LinuxCNC 包含实时线程、HAL、NML、动态模块、Python/Boost.Python remap、桌面 GUI 和 POSIX 依赖,这些都不是浏览器仿真核心。
- 可以先复用
src/emc/rs274ngc解释器,接管canon.hh中的 Canonical Machining Functions,把STRAIGHT_FEED、ARC_FEED、DWELL、CHANGE_TOOL等调用记录为仿真事件。 - Fanuc、Siemens 等主流系统应作为“方言层”实现:先把宏变量、固定循环、坐标旋转、RTCP/TRAORI/CYCLE800 等控制器特性归一化为内部 IR,再交给同一个仿真内核。
- 浏览器端不做实时控制,只做可重复、可暂停、可回放的离线仿真,所以速度规划、前瞻、碰撞和去料可以使用非实时算法。
分层
-
dialect- LinuxCNC RS274/NGC
- Fanuc Macro B / common milling and turning extensions
- Siemens 840D-style cycles and transforms
-
interp- LinuxCNC interpreter compiled to wasm where possible
- Canon callback adapter records normalized motion/tool/state events
-
sim-core- Units, modal state, work offsets, tool table
- Arc/NURBS segmentation
- 3/4/5-axis kinematics and RTCP
- Feed/time estimation and non-realtime lookahead
-
verification- Golden G-code corpus
- Controller dialect compatibility matrix
- Numeric tolerance checks against LinuxCNC native output
-
web- Web Worker wrapper around wasm
- Toolpath display
- Machine model, fixtures, stock, collision and material removal
First milestone
The first useful target is:
- compile a small wasm module exposing
cnc_sim_*C ABI; - connect LinuxCNC RS274 interpreter to a Canon event sink;
- return a JSON event stream to TypeScript;
- render rapid/feed/arc events in the browser;
- compare the event stream against native LinuxCNC for a small test corpus.
当前进度
- 已有稳定 C ABI 和 Web 调用封装。
- 已有数控系统风格网页面板。
- 已有临时 smoke parser,用于在 LinuxCNC 后端接入前测试 UI 和 wasm 回调链路。
- 已有 native smoke test 和 JSON dump 工具。
- 已有 LinuxCNC
canon.hhbridge,并已通过独立 smoke test。 - 已有 native
librs274runner,可以让 LinuxCNC 解释器输出CncSimEvent。 - 已有最小 LinuxCNC tooldata 初始化,native runner 和 API 后端都能覆盖
T... M6换刀路径。 - 已有 LinuxCNC RS274 源码级链接 smoke:本项目直接编译 23 个解释器 core 源文件,不再通过
librs274取得解释器主体。 - 已有五轴 RTCP 第一版几何内核,可根据编程刀尖点、A/B/C 姿态和刀长计算枢轴/主轴点补偿位置。
- 已有坐标系事件回归语料,覆盖
G10 L2、G10 L20的 G5X/XY 旋转事件和G92.1清零事件。 - 已有探针事件回归语料,LinuxCNC
G38.3会输出独立probe事件,不再混作普通直线进给。 - 已有主轴方向状态回归语料,
M3/M4/M5会通过set-spindle.reserved输出1=顺时针、2=逆时针、0=停止。 - 已有注释事件行号回归语料,LinuxCNC
COMMENT事件会保留当前 G-code 行号。 - 已有当前刀号事件行号回归语料,LinuxCNC
M61 Q...会输出带行号的tool-change事件。 - 已有停止类事件回归语料,
M0/M1/M60会通过program-end.reserved输出1=程序停、2=可选停、3=托盘交换。 - 已有冷却液状态回归语料,
M7/M8/M9会通过comment.reserved临时输出10/11=mist off/on、20/21=flood off/on。 - 已有进给模式回归语料,
G93/G94/G95会通过comment.reserved临时输出93/94/95,并通过set-feed记录 Canon feed mode 回调。 - 已有运动控制模式回归语料,
G61/G61.1/G64会通过comment.reserved临时输出611/612/640,feed暂存 G64 tolerance。 - smoke parser 已有固定循环第一版展开,覆盖
G73高速啄钻、G81普通钻、G82孔底暂停钻、G83啄钻、G85镗孔进给退刀、G86镗孔停主轴快速退刀、G89镗孔暂停后进给退刀,以及G80取消、G98/G99返回模式和L重复次数。 - LinuxCNC native/source 对照已扩展到
G82孔底暂停和G83啄钻关键事件,覆盖孔底 dwell、啄钻深度序列和 R 平面退刀。 - smoke parser 已有 Fanuc 风格
M98 P... L.../M99子程序调用第一版,支持同文件O...子程序块和重复调用展开;未知子程序、裸M99和过深嵌套会返回明确错误。 - smoke parser 已有 LinuxCNC 风格 O-word 子程序第一版,覆盖数字
O100 ...和命名O<name> ...的sub/call [args]/return/endsub,支持简单数字实参、#1 = ...编号参数赋值、#<name> = ...命名参数赋值、X#1/X#<name>参数引用、+ - * /可嵌套方括号表达式,以及ABS[]、SQRT[]、EXP[]、LN[]、角度制SIN[]/COS[]/TAN[]/ASIN[]/ACOS[]、LinuxCNC 双参数ATAN[]/[]、FIX[]/FUP[]/ROUND[],并拒绝和M98/M99风格混用。 - LinuxCNC native/source runner 已支持显式文件模式执行,O-word 子程序语料会通过 LinuxCNC 自身
open/read/execute路径验证,而不是逐行模拟。 - LinuxCNC Canon bridge 会把当前解释行号补到没有自带
lineno的回调事件上,方便 Web 端诊断和源码高亮。 - 下一步是继续替换源码级链接中残留的 Python、INI/HAL、文件系统和动态加载依赖,并把 RTCP 内核接入 canon 事件流和机型配置。
本地测试
./test-all-native.sh
当前 native 测试覆盖:
- smoke parser
- Canon event sink
- LinuxCNC Canon bridge
- 直接链接 LinuxCNC
librs274的 runner - 通过
cnc_sim_api选择linuxcnc-rs274后端 - LinuxCNC RS274 源文件语法探针和对象编译探针
- LinuxCNC RS274 源码级链接 smoke
- 五轴 RTCP 几何内核 smoke
M3/M4/M5主轴方向事件回归M61 Q...当前刀号事件行号回归- LinuxCNC 注释事件行号回归
M0/M1/M60停止类事件回归M7/M8/M9冷却液状态回归G93/G94/G95进给模式回归G61/G61.1/G64运动控制模式回归- smoke parser
G73/G81/G82/G83/G85/G86/G89/G80/G98/G99/L固定循环展开回归 - LinuxCNC native/source
G82/G83固定循环对照回归 - smoke parser
M98 P... L.../M99子程序调用回归 - smoke parser LinuxCNC 风格
O... sub/call/return/endsub子程序调用回归 G10 L2/G10 L20/G92.1坐标系事件回归G38.3探针事件回归
后端选择
公共 API 使用同一个入口解析程序,后端通过 JSON 配置选择:
{"backend":"smoke"}
smoke 是默认后端,用于 wasm 和 UI 联调。
native 构建启用 LinuxCNC 后端后,可以使用:
{"backend":"linuxcnc-rs274"}
网页面板右上角的 BACKEND 下拉框会把该配置传给 wasm/core。当前默认 wasm 构建不包含 LinuxCNC 后端,选择 LINUXCNC 会返回明确错误;native API 测试已验证该后端可用。
RTCP 配置
RTCP 默认关闭。开启后,原有 rapid、linear-feed、arc-feed 事件仍表示编程刀尖轨迹;core 会额外发出 rtcp-pivot 事件,start/end 是按刀长和 A/B/C 姿态补偿后的枢轴/主轴点轨迹,center 的 x/y/z 暂存当前刀具向量。
{
"backend": "linuxcnc-rs274",
"rtcp": {
"enabled": true,
"toolLength": 100,
"toolLengths": {
"7": 125
}
}
}
当前 RTCP 内核是第一版头头/摆头类几何模型:编程 XYZ 视为刀尖点,刀长沿本地 -Z,A/B/C 按 Rz(C) * Ry(B) * Rx(A) 旋转。后续会继续加入机型拓扑、旋转中心偏置、刀表刀长和不同五轴构型。
RTCP G 码控制已开始标准化:
G43.4 H...:开启 RTCP,H号进入事件,实际刀长优先从 JSON 配置中的toolLengths按 H 号读取,未配置时回退到toolLength。G43.5 H...:同样作为 RTCP 开启处理。G49:关闭 RTCP。
解析后会发出 rtcp-state 事件。事件中的 feed 表示 RTCP 状态:0=关闭、1=开启;tool 表示 H 号;dwell_seconds 暂存当前配置刀长。
运动学切换 M 码
core 已对原型中的运动学切换 M 码做标准化解析:
M429:切换到三轴恒等运动学IDENTITY,关闭 RTCP。M428:恢复到原始五轴运动学,开启 RTCP。M430:切换到FIVEAXIS_BC,开启 RTCP。
解析后会发出 kinematics-switch 事件。事件中的 reserved 字段表示运动学类型:0=IDENTITY、1=ORIGINAL、2=FIVEAXIS_BC;feed 字段临时表示 RTCP 状态:0=关闭、1=开启。同一行中的 M428 M429 M430 会按出现顺序产生三个切换事件。
linuxcnc-rs274 native API backend 会在送入 LinuxCNC 解释器前拦截只包含这些切换 M 码的行,避免 LinuxCNC 去查找外部用户 M-code 文件。
坐标系事件
Canon bridge 已不再丢弃坐标系相关回调,会输出:
set-g5x-offset:来自SET_G5X_OFFSET,tool字段存 G5X index,start存 XYZABCUVW offset。set-g92-offset:来自SET_G92_OFFSET,start存 XYZABCUVW offset。set-xy-rotation:来自SET_XY_ROTATION,feed暂存旋转角度。
这些事件先保证 LinuxCNC Canon 层信息完整进入 Web/core。具体 G-code(如 G10、G92、坐标旋转)是否触发这些回调,还要继续按 LinuxCNC 解释器参数路径逐项补回归语料。
目前已有两组回归语料:tests/gcode/linuxcnc_coordinate_offsets.ngc 覆盖 G10 L2 P1 X... Y... Z... R... 触发 set-g5x-offset / set-xy-rotation,以及 G92.1 触发 set-g92-offset 清零;tests/gcode/linuxcnc_coordinate_l20.ngc 覆盖 G10 L20 P2 按当前位置和目标工件坐标计算 G55 偏置。测试脚本会在坐标系语料之间重置参数文件,避免 LinuxCNC 持久参数互相污染。后续继续扩展到更多坐标系 P 号、持久参数文件读写策略和旋转叠加运动路径。
LinuxCNC 中部分 Canon 函数不携带行号参数,bridge 会在调用解释器 read/execute 前记录当前输入行,并用它填充这类事件的 line 字段。
CMake native LinuxCNC 后端
手写测试脚本仍是当前主验证路径。如果使用 CMake,启用 native LinuxCNC 后端的配置为:
cmake -S core -B build/native-linuxcnc \
-DCNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND=ON \
-DCNC_SIM_LINUXCNC_ROOT=/home/cnc/桌面/cnc/linuxcnc
该选项是 native-only,会链接 LinuxCNC 已构建的 librs274 和 libtooldata。
Legal note
LinuxCNC is GPL licensed. If this wasm module links LinuxCNC code, the combined simulator core must be distributed under GPL-compatible terms unless you replace that part with an independently written interpreter.