Compare commits
355 Commits
a227ad14a6
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c81f9d0111 | ||
|
|
c75eec1057 | ||
|
|
23e67bb6cd | ||
|
|
42e5b0784d | ||
|
|
64f336d6f2 | ||
|
|
fc56b11d8f | ||
|
|
fb9561ccc7 | ||
|
|
4e246738ac | ||
|
|
92562db29f | ||
|
|
de5f28f7ee | ||
|
|
82f222ba44 | ||
|
|
cdc30dda7e | ||
|
|
1d96aa8a55 | ||
|
|
25cb6885bf | ||
|
|
ccd51ff373 | ||
|
|
10bf0a5897 | ||
|
|
ced3e5de0e | ||
|
|
7ba3a22441 | ||
|
|
5aa328b413 | ||
|
|
586c28656d | ||
|
|
6efb77b8e4 | ||
|
|
ebb29f8cb6 | ||
|
|
8544872198 | ||
|
|
e320d6d420 | ||
|
|
ba2d680500 | ||
|
|
9af3443d95 | ||
|
|
4adcd82b74 | ||
|
|
66ea34a76d | ||
|
|
5bc568eaa9 | ||
|
|
23a4679c28 | ||
|
|
3c05202097 | ||
|
|
ba0d973f4f | ||
|
|
f69e10bedf | ||
|
|
a8f6a9d907 | ||
|
|
0850954ca8 | ||
|
|
6bd1c6a429 | ||
|
|
e928b32e69 | ||
|
|
36763c6bcd | ||
|
|
03080afe24 | ||
|
|
120a294f62 | ||
|
|
a3daa829fc | ||
|
|
71c61fca84 | ||
|
|
ff2980569c | ||
|
|
695186ddfc | ||
|
|
8394042d18 | ||
|
|
7e18c6cd40 | ||
|
|
09e2259669 | ||
|
|
867bf09c5d | ||
|
|
d35766e387 | ||
|
|
9c73577ade | ||
|
|
55149b0a0a | ||
|
|
6a886be52d | ||
|
|
acbf5b4686 | ||
|
|
77c6674905 | ||
|
|
eb91ced792 | ||
|
|
1b60bc2b2e | ||
|
|
37879f2a67 | ||
|
|
a7cd889b3a | ||
|
|
4887b2f64e | ||
|
|
cb315ce1cd | ||
|
|
9a4e0e3712 | ||
|
|
98755528e4 | ||
|
|
504b9b6d23 | ||
|
|
284afa1c64 | ||
|
|
428fc46f4e | ||
|
|
d5c6b7555a | ||
|
|
b773946c45 | ||
|
|
7a2a80ea71 | ||
|
|
41db47f440 | ||
|
|
27ac0bfb25 | ||
|
|
cd71eff8a5 | ||
|
|
eb1d31bfee | ||
|
|
2892f2ca9d | ||
|
|
a301965452 | ||
|
|
0737d5ea65 | ||
|
|
3a478ca335 | ||
|
|
a144576e90 | ||
|
|
60745adeef | ||
|
|
6506d23dc2 | ||
|
|
440a61be32 | ||
|
|
9b9e942dd6 | ||
|
|
3c72356c92 | ||
|
|
a89c107676 | ||
|
|
035b25862a | ||
|
|
167703b87a | ||
|
|
b600d6a516 | ||
|
|
0a2d37fae8 | ||
|
|
111cb5f9b9 | ||
|
|
218ac523b8 | ||
|
|
abaebe7940 | ||
|
|
77e92b0116 | ||
|
|
cf3154b043 | ||
|
|
9da6ffcd6a | ||
|
|
c71d2964ee | ||
|
|
c1a130f5fb | ||
|
|
baf8429736 | ||
|
|
2e2fb34cc3 | ||
|
|
810bd92ddc | ||
|
|
6d99ca67a9 | ||
|
|
6a2f63c894 | ||
|
|
bc80d74d1f | ||
|
|
71676ac1be | ||
|
|
89af73298e | ||
|
|
dc5cdeacc2 | ||
|
|
b170ccd95a | ||
|
|
29197b25cc | ||
|
|
5ce3c18103 | ||
|
|
79077fa695 | ||
|
|
f64db24060 | ||
|
|
fb2b5c4920 | ||
|
|
9c52e426f7 | ||
|
|
d80405ccb3 | ||
|
|
a48c02f5cc | ||
|
|
f56468b664 | ||
|
|
ba2d576f8b | ||
|
|
7f45abe93c | ||
|
|
ae7de73a7c | ||
|
|
7471444781 | ||
|
|
f36e2a96c4 | ||
|
|
aaa6dce99a | ||
|
|
b89d6311ff | ||
|
|
a12c0166b5 | ||
|
|
9fd23192dd | ||
|
|
a46910b6c0 | ||
|
|
0b387db8ca | ||
|
|
22c1c311ff | ||
|
|
3079656cfb | ||
|
|
7502684780 | ||
|
|
340966b6f7 | ||
|
|
1f314b7e9e | ||
|
|
1bfb7426d4 | ||
|
|
abd96dfdde | ||
|
|
7b171c605b | ||
|
|
cb22ecd8ef | ||
|
|
a0f6228908 | ||
|
|
8fe468ba3c | ||
|
|
b3b1117ec9 | ||
|
|
4eb694164f | ||
|
|
59b8e2a832 | ||
|
|
f9ac38251b | ||
|
|
002c8a2d53 | ||
|
|
decc008609 | ||
|
|
3c2df90872 | ||
|
|
81c7b061a8 | ||
|
|
2223e6d601 | ||
|
|
708b2bee17 | ||
|
|
0a270c73a0 | ||
|
|
52d7a49861 | ||
|
|
802e85cd63 | ||
|
|
0de612651e | ||
|
|
6f21d22912 | ||
|
|
f8902b3f8d | ||
|
|
3d368b2564 | ||
|
|
8b89b5b4c6 | ||
|
|
21c242c9a4 | ||
|
|
945e839e9d | ||
|
|
feb04102e7 | ||
|
|
aaa2573bba | ||
|
|
d7b9006ba5 | ||
|
|
51b415a701 | ||
|
|
856b526acb | ||
|
|
bc54b5f8f8 | ||
|
|
8151829643 | ||
|
|
5fb041f1a5 | ||
|
|
bba306ccfe | ||
|
|
4a3d87045e | ||
|
|
951dcc7980 | ||
|
|
aa6e79ac64 | ||
|
|
39f6f9133c | ||
|
|
bc7b947d14 | ||
|
|
1ce460d1d5 | ||
|
|
96b5973e1b | ||
|
|
c8b834e36b | ||
|
|
32b4a96a9f | ||
|
|
ee0a3130bf | ||
|
|
c031bc0a2c | ||
|
|
dcf246c0a0 | ||
|
|
1f4044efe2 | ||
|
|
3cc7590121 | ||
|
|
180c0f6dbe | ||
|
|
702f94cc52 | ||
|
|
b366d220f5 | ||
|
|
3090b9a79a | ||
|
|
c851476007 | ||
|
|
ddc20eeb98 | ||
|
|
1ef3f2c7df | ||
|
|
eef30e1831 | ||
|
|
1433435121 | ||
|
|
46807f05a5 | ||
|
|
77f9754833 | ||
|
|
457557dee8 | ||
|
|
aff6f85d8a | ||
|
|
4086445900 | ||
|
|
18f14ca111 | ||
|
|
7d28d0a025 | ||
|
|
0d4e248811 | ||
|
|
5481ab3bff | ||
|
|
8ff22065dd | ||
|
|
5c2d5cfa05 | ||
|
|
f98a715ed7 | ||
|
|
1928ff3b6a | ||
|
|
6cf7c73392 | ||
|
|
028825cd9c | ||
|
|
e778a37fdb | ||
|
|
6cc07c2950 | ||
|
|
c5a1d655b0 | ||
|
|
0895c04ab1 | ||
|
|
c932e10801 | ||
|
|
d1e0152eb8 | ||
|
|
a134dcef7d | ||
|
|
bbd5739e7a | ||
|
|
611e6417b4 | ||
|
|
fa4296d730 | ||
|
|
2dd9847a7b | ||
|
|
9bf9206869 | ||
|
|
090a5fb89c | ||
|
|
2f7a46758b | ||
|
|
1b16d3e0b5 | ||
|
|
d0a7a9fcec | ||
|
|
dbf27a4e6b | ||
|
|
e71b9146e1 | ||
|
|
59287b9920 | ||
|
|
33e1ee5a06 | ||
|
|
b26620dc32 | ||
|
|
74cb5f826c | ||
|
|
2ba8cd7fb8 | ||
|
|
e3d47e8267 | ||
|
|
3df61e8da5 | ||
|
|
28aa1956b7 | ||
|
|
4e3df07b8a | ||
|
|
b7610d1b96 | ||
|
|
55c75ffe80 | ||
|
|
ad3720713e | ||
|
|
ba526a6042 | ||
|
|
93f2a903b5 | ||
|
|
c52ecc09eb | ||
|
|
cc05532528 | ||
|
|
ecec27aa64 | ||
|
|
c25b0eff22 | ||
|
|
777d29651c | ||
|
|
138fe862ae | ||
|
|
d985b13a8e | ||
|
|
030074b8c5 | ||
|
|
84fdc8a1c5 | ||
|
|
9c03f91fa8 | ||
|
|
868f20382a | ||
|
|
cde0bdaba6 | ||
|
|
3a60624108 | ||
|
|
4d0cf788b1 | ||
|
|
e875496fe0 | ||
|
|
7e15a99d28 | ||
|
|
3435c3556a | ||
|
|
318220b766 | ||
|
|
43a3e66106 | ||
|
|
4f1042c548 | ||
|
|
cc708b1ccc | ||
|
|
25519b5bc4 | ||
|
|
a44199eb48 | ||
|
|
9a9b931982 | ||
|
|
7bd1dc640f | ||
|
|
b83bc47c45 | ||
|
|
6ffcada028 | ||
|
|
b2945cf57f | ||
|
|
05ece027c4 | ||
|
|
b4d0bfae46 | ||
|
|
3f5c3faf25 | ||
|
|
dd4c62fce6 | ||
|
|
4861287138 | ||
|
|
7319e18810 | ||
|
|
df5c459b1d | ||
|
|
23284e528f | ||
|
|
952d3ecfd2 | ||
|
|
6e0a5627f0 | ||
|
|
6266887fec | ||
|
|
b8ad3a0346 | ||
|
|
0abf801856 | ||
|
|
31e1e4499e | ||
|
|
4780dd8621 | ||
|
|
303b6bfa36 | ||
|
|
854cc682b3 | ||
|
|
dda5b4973e | ||
|
|
ce0605d20d | ||
|
|
67154a70fa | ||
|
|
5c7093ba39 | ||
|
|
0e1e22a864 | ||
|
|
cee1bf3a3f | ||
|
|
d807464cf7 | ||
|
|
303b7f7a72 | ||
|
|
154fc7578a | ||
|
|
08978b82de | ||
|
|
dfd41bb7fc | ||
|
|
1f37c979e9 | ||
|
|
23f88a619a | ||
|
|
34aa884a22 | ||
|
|
56f78b3054 | ||
|
|
c3ec85196f | ||
|
|
c2e5e8f2c8 | ||
|
|
10c1b70ed8 | ||
|
|
68b6c19392 | ||
|
|
e1fe284078 | ||
|
|
082495d3ad | ||
|
|
e117ac8a5b | ||
|
|
518628bfea | ||
|
|
89f9930ec4 | ||
|
|
7bf4300c84 | ||
|
|
16ac5cbfef | ||
|
|
820ac7e72b | ||
|
|
5f4e918663 | ||
|
|
de13d8efeb | ||
|
|
8826f2ee73 | ||
|
|
e1708c96ee | ||
|
|
cc7faef3a7 | ||
|
|
d8c2364816 | ||
|
|
93e83d52bf | ||
|
|
c4e174f011 | ||
|
|
00d62bd61a | ||
|
|
c9c5db8e9c | ||
|
|
26da1e6d9d | ||
|
|
d5c99f99c0 | ||
|
|
158fd343c6 | ||
|
|
35d341de70 | ||
|
|
d6cae8bf56 | ||
|
|
0a0083b2d3 | ||
|
|
ad7a461b3e | ||
|
|
dab7b9e2ef | ||
|
|
0db23b4a5d | ||
|
|
fbe1c31961 | ||
|
|
87fcf74135 | ||
|
|
f5013ec745 | ||
|
|
1250638f22 | ||
|
|
37c2f08dfb | ||
|
|
c474d45cdc | ||
|
|
04b3bc3a47 | ||
|
|
110c3ba76e | ||
|
|
57733f424a | ||
|
|
f98aa9ebb1 | ||
|
|
8387f48130 | ||
|
|
d8909b5d8a | ||
|
|
2c24909a47 | ||
|
|
d7cac10c3b | ||
|
|
bbaf9f4da6 | ||
|
|
89fd49c604 | ||
|
|
5ec10abf38 | ||
|
|
6f9431a389 | ||
|
|
4c55ab3435 | ||
|
|
1498d9830d | ||
|
|
c2d1aa6fe3 | ||
|
|
de273bf830 | ||
|
|
b40914747d | ||
|
|
40a63c76f7 | ||
|
|
ce2f3f3769 | ||
|
|
86734622d7 | ||
|
|
dd4b7d9314 | ||
|
|
efc92d0380 | ||
|
|
b4861fd618 |
@@ -116,19 +116,13 @@ The first useful target is:
|
|||||||
|
|
||||||
公共 API 使用同一个入口解析程序,后端通过 JSON 配置选择:
|
公共 API 使用同一个入口解析程序,后端通过 JSON 配置选择:
|
||||||
|
|
||||||
```json
|
|
||||||
{"backend":"smoke"}
|
|
||||||
```
|
|
||||||
|
|
||||||
`smoke` 是默认后端,用于 wasm 和 UI 联调。
|
|
||||||
|
|
||||||
native 构建启用 LinuxCNC 后端后,可以使用:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"backend":"linuxcnc-rs274"}
|
{"backend":"linuxcnc-rs274"}
|
||||||
```
|
```
|
||||||
|
|
||||||
网页面板右上角的 `BACKEND` 下拉框会把该配置传给 wasm/core。当前默认 wasm 构建不包含 LinuxCNC 后端,选择 `LINUXCNC` 会返回明确错误;native API 测试已验证该后端可用。
|
`linuxcnc-rs274` 是默认后端,wasm 和 UI 默认通过 LinuxCNC RS274 源码路径解析;`smoke` 仅用于显式编译/选择的 legacy 联调路径。
|
||||||
|
|
||||||
|
网页面板右上角的 `BACKEND` 下拉框会把该配置传给 wasm/core。`./build-wasm.sh` 会生成 `web/public/cnc_sim.js` 和 `web/public/cnc_sim.wasm`,随后运行 `test-web-wasm-node-smoke.cjs` 和 `test-web-wasm-browser-smoke.sh`;这些 smoke 会验证 wasm 中的 LinuxCNC RS274 后端可在 Node 和 Chromium 浏览器中加载、可解析基础运动,并保留 `M428/M429/M430` remap 触发的运动学切换事件。
|
||||||
|
|
||||||
## RTCP 配置
|
## RTCP 配置
|
||||||
|
|
||||||
@@ -143,11 +137,19 @@ RTCP 默认关闭。开启后,原有 `rapid`、`linear-feed`、`arc-feed` 事
|
|||||||
"toolLengths": {
|
"toolLengths": {
|
||||||
"7": 125
|
"7": 125
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"xyzbcTrt": {
|
||||||
|
"xRotPoint": 0,
|
||||||
|
"yRotPoint": 0,
|
||||||
|
"zRotPoint": 0,
|
||||||
|
"xOffset": -20,
|
||||||
|
"zOffset": -15,
|
||||||
|
"conventionalDirections": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
当前 RTCP 内核是第一版头头/摆头类几何模型:编程 XYZ 视为刀尖点,刀长沿本地 `-Z`,A/B/C 按 `Rz(C) * Ry(B) * Rx(A)` 旋转。后续会继续加入机型拓扑、旋转中心偏置、刀表刀长和不同五轴构型。
|
RTCP pivot 事件只在已知 LinuxCNC switchkins 类型下输出。`M428` 切换到 `XYZBC_TRT` 后,`xyzbcTrt` 对应 LinuxCNC `xyzbc-trt-kins` 的 HAL pin:`x-rot-point`、`y-rot-point`、`z-rot-point`、`x-offset`、`z-offset`、`conventional-directions`;刀长仍来自 `toolLength` / `toolLengths`。`M430` 使用 LinuxCNC `userkfuncs.c` 经 `kins_util.c` identity 运动学路径。未支持或未知的 switchkins 类型不会回退到自研 RTCP 几何。
|
||||||
|
|
||||||
RTCP G 码控制已开始标准化:
|
RTCP G 码控制已开始标准化:
|
||||||
|
|
||||||
@@ -161,11 +163,11 @@ RTCP G 码控制已开始标准化:
|
|||||||
|
|
||||||
core 已对原型中的运动学切换 M 码做标准化解析:
|
core 已对原型中的运动学切换 M 码做标准化解析:
|
||||||
|
|
||||||
- `M429`:切换到三轴恒等运动学 `IDENTITY`,关闭 RTCP。
|
- `M429`:切换到三轴恒等运动学 `IDENTITY`。
|
||||||
- `M428`:恢复到原始五轴运动学,开启 RTCP。
|
- `M428`:切换到 LinuxCNC `xyzbc-trt-kins` 的 XYZBC TRT 运动学。
|
||||||
- `M430`:切换到 `FIVEAXIS_BC`,开启 RTCP。
|
- `M430`:切换到 LinuxCNC 默认 `userk` 运动学;当前对齐 `userkfuncs.c` 的 identity 正/逆解。
|
||||||
|
|
||||||
解析后会发出 `kinematics-switch` 事件。事件中的 `reserved` 字段表示运动学类型:`0=IDENTITY`、`1=ORIGINAL`、`2=FIVEAXIS_BC`;`feed` 字段临时表示 RTCP 状态:`0=关闭`、`1=开启`。同一行中的 `M428 M429 M430` 会按出现顺序产生三个切换事件。
|
解析后会发出 `kinematics-switch` 事件。事件中的 `reserved` 字段表示运动学类型:`0=IDENTITY`、`1=XYZBC_TRT`、`2=USERK_IDENTITY`。这些 M 码对齐 LinuxCNC `remap_subs/428remap.ngc`、`429remap.ngc`、`430remap.ngc`,只设置 `motion.switchkins-type`,不隐式开启或关闭 RTCP;RTCP 状态仍由 `G43.4`、`G43.5`、`G49` 控制。同一行中的 `M428 M429 M430` 会按出现顺序产生三个切换事件。
|
||||||
|
|
||||||
`linuxcnc-rs274` native API backend 会在送入 LinuxCNC 解释器前拦截只包含这些切换 M 码的行,避免 LinuxCNC 去查找外部用户 M-code 文件。
|
`linuxcnc-rs274` native API backend 会在送入 LinuxCNC 解释器前拦截只包含这些切换 M 码的行,避免 LinuxCNC 去查找外部用户 M-code 文件。
|
||||||
|
|
||||||
|
|||||||
214
analyze-linuxcnc-wasm-blockers.sh
Executable file
214
analyze-linuxcnc-wasm-blockers.sh
Executable file
@@ -0,0 +1,214 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: this blocker scan is constrained to the RS274/WASM
|
||||||
|
# manifest. Python and Boost.Python blockers come from
|
||||||
|
# src/emc/rs274ngc/gcodemodule.cc, interp_namedparams.cc, interp_o_word.cc,
|
||||||
|
# and the py*.cc module bindings; tooldata/native-backend blockers come from
|
||||||
|
# src/emc/tooldata/tooldata_mmap.cc and tooldata_db.cc; native filesystem
|
||||||
|
# coverage comes from LinuxCNC RS274 sources such as interp_o_word.cc
|
||||||
|
# directory traversal and rs274ngc_pre.cc parameter-file replacement.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||||
|
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs-cached.sh "$manifest"
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
python_blockers=()
|
||||||
|
python_compile_covered=()
|
||||||
|
core_python_sources=()
|
||||||
|
dlopen_blockers=()
|
||||||
|
core_dlopen_sources=()
|
||||||
|
tooldata_blockers=()
|
||||||
|
core_tooldata_sources=()
|
||||||
|
shimmed_tooldata_users=()
|
||||||
|
core_tooldata_users=()
|
||||||
|
native_backend_blockers=()
|
||||||
|
native_fs_blockers=()
|
||||||
|
core_native_fs_sources=()
|
||||||
|
core_count=0
|
||||||
|
blocked_count=0
|
||||||
|
blocked_replacements=()
|
||||||
|
shim_source_output=$(./list-linuxcnc-wasm-safe-shims.sh)
|
||||||
|
mapfile -t wasm_safe_shims <<<"$shim_source_output"
|
||||||
|
|
||||||
|
blocked_replacement_for() {
|
||||||
|
case "$1" in
|
||||||
|
src/emc/tooldata/tooldata_mmap.cc)
|
||||||
|
./list-linuxcnc-wasm-safe-shims.sh tooldata_mmap_backend.cc
|
||||||
|
;;
|
||||||
|
src/emc/rs274ngc/canonmodule.cc|src/emc/rs274ngc/gcodemodule.cc|src/emc/rs274ngc/interpmodule.cc)
|
||||||
|
./list-linuxcnc-wasm-safe-shims.sh linuxcnc_runtime_shim.cc
|
||||||
|
;;
|
||||||
|
src/emc/rs274ngc/pyarrays.cc|src/emc/rs274ngc/pyblock.cc|src/emc/rs274ngc/pyemctypes.cc|src/emc/rs274ngc/pyinterp1.cc|src/emc/rs274ngc/pyparamclass.cc)
|
||||||
|
./list-linuxcnc-wasm-safe-shims.sh python_c_api_shim.cc
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
wasm_safe_shim_in_build() {
|
||||||
|
local shim=$1
|
||||||
|
local candidate
|
||||||
|
for candidate in "${wasm_safe_shims[@]}"; do
|
||||||
|
if [[ "$candidate" == "$shim" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
python_compile_probe_covers() {
|
||||||
|
grep -F "$1" test-linuxcnc-wasm-python-c-api-symbols.sh >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
core_sources=()
|
||||||
|
blocked_sources=()
|
||||||
|
manifest_line_number=0
|
||||||
|
while IFS= read -r manifest_line || [[ -n "$manifest_line" ]]; do
|
||||||
|
manifest_line_number=$((manifest_line_number + 1))
|
||||||
|
case "$manifest_line" in
|
||||||
|
""|\#*)
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
IFS=: read -r group path note extra <<<"$manifest_line"
|
||||||
|
if [[ -z "$group" || -z "$path" || -z "$note" || -n "${extra:-}" ]]; then
|
||||||
|
echo "bad manifest line $manifest_line_number: $manifest_line" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
case "$group" in
|
||||||
|
core)
|
||||||
|
core_sources+=("$path")
|
||||||
|
;;
|
||||||
|
blocked)
|
||||||
|
blocked_sources+=("$path")
|
||||||
|
;;
|
||||||
|
header|metadata|blocked-header)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "unknown manifest group: $group" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done < "$manifest"
|
||||||
|
core_count=${#core_sources[@]}
|
||||||
|
blocked_count=${#blocked_sources[@]}
|
||||||
|
|
||||||
|
scan_source() {
|
||||||
|
local group=$1
|
||||||
|
local path=$2
|
||||||
|
full_path="$linuxcnc_root/$path"
|
||||||
|
if [[ ! -f "$full_path" ]]; then
|
||||||
|
echo "missing manifest source: $path" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "$group" == "blocked" ]]; then
|
||||||
|
if ! replacement=$(blocked_replacement_for "$path"); then
|
||||||
|
echo "missing blocked replacement mapping: $path" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ ! -f "$replacement" ]]; then
|
||||||
|
echo "missing blocked replacement source: $replacement" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! wasm_safe_shim_in_build "$replacement"; then
|
||||||
|
echo "blocked replacement is not in wasm shim build set: $path -> $replacement" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
blocked_replacements+=("$path -> $replacement")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$path" == src/emc/tooldata/* ]]; then
|
||||||
|
if [[ "$group" == "blocked" ]]; then
|
||||||
|
tooldata_blockers+=("$path")
|
||||||
|
else
|
||||||
|
core_tooldata_sources+=("$path")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$path" == "src/emc/tooldata/tooldata_mmap.cc" ]]; then
|
||||||
|
native_backend_blockers+=("$path")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -Eq 'Python\.h|boost/python|pythonplugin|PyObject|PyInit_' "$full_path"; then
|
||||||
|
if [[ "$group" == "blocked" ]]; then
|
||||||
|
python_blockers+=("$path")
|
||||||
|
if python_compile_probe_covers "$path"; then
|
||||||
|
python_compile_covered+=("$path")
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
core_python_sources+=("$path")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -Eq 'dlopen|dlsym|RTLD_' "$full_path"; then
|
||||||
|
if [[ "$group" == "blocked" ]]; then
|
||||||
|
dlopen_blockers+=("$path")
|
||||||
|
else
|
||||||
|
core_dlopen_sources+=("$path")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -Eq 'mkstemp|mkstemps|dirent\.h|opendir|readdir|unistd\.h' "$full_path"; then
|
||||||
|
if [[ "$group" == "blocked" ]]; then
|
||||||
|
native_fs_blockers+=("$path")
|
||||||
|
else
|
||||||
|
core_native_fs_sources+=("$path")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$path" != src/emc/tooldata/* ]] && grep -Eq 'tooldata/tooldata.hh|tooldata_' "$full_path"; then
|
||||||
|
if [[ "$group" == "blocked" ]]; then
|
||||||
|
shimmed_tooldata_users+=("$path")
|
||||||
|
else
|
||||||
|
core_tooldata_users+=("$path")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
for path in "${core_sources[@]}"; do
|
||||||
|
[[ -z "$path" ]] && continue
|
||||||
|
scan_source core "$path"
|
||||||
|
done
|
||||||
|
|
||||||
|
for path in "${blocked_sources[@]}"; do
|
||||||
|
[[ -z "$path" ]] && continue
|
||||||
|
scan_source blocked "$path"
|
||||||
|
done
|
||||||
|
|
||||||
|
print_group() {
|
||||||
|
local title=$1
|
||||||
|
shift
|
||||||
|
echo "[$title]"
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
echo "(none)"
|
||||||
|
else
|
||||||
|
printf '%s\n' "$@" | LC_ALL=C sort -u
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "[manifest]"
|
||||||
|
echo "core=$core_count"
|
||||||
|
echo "blocked=$blocked_count"
|
||||||
|
echo
|
||||||
|
|
||||||
|
print_group "python" "${python_blockers[@]}"
|
||||||
|
print_group "python-compile-covered" "${python_compile_covered[@]}"
|
||||||
|
print_group "dlopen" "${dlopen_blockers[@]}"
|
||||||
|
print_group "tooldata" "${tooldata_blockers[@]}"
|
||||||
|
print_group "tooldata-users" "${shimmed_tooldata_users[@]}"
|
||||||
|
print_group "native-backend" "${native_backend_blockers[@]}"
|
||||||
|
print_group "native-fs" "${native_fs_blockers[@]}"
|
||||||
|
print_group "blocked-replacements" "${blocked_replacements[@]}"
|
||||||
|
print_group "core-python-shimmed" "${core_python_sources[@]}"
|
||||||
|
print_group "core-dlopen-shimmed" "${core_dlopen_sources[@]}"
|
||||||
|
print_group "core-tooldata-shimmed" "${core_tooldata_sources[@]}"
|
||||||
|
print_group "core-tooldata-users-shimmed" "${core_tooldata_users[@]}"
|
||||||
|
print_group "core-native-fs-shimmed" "${core_native_fs_sources[@]}"
|
||||||
105
build-linuxcnc-native-bridge-objects.sh
Executable file
105
build-linuxcnc-native-bridge-objects.sh
Executable file
@@ -0,0 +1,105 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: native bridge object caches compile only project
|
||||||
|
# canon/kinematics bridge sources that wrap LinuxCNC src/emc/nml_intf/canon.hh
|
||||||
|
# and src/emc/kinematics implementations; G-code behavior remains in
|
||||||
|
# LinuxCNC RS274 objects linked by the caller.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
cxx=${CXX:-g++}
|
||||||
|
if [[ -z ${CXX:-} ]] && command -v ccache >/dev/null 2>&1; then
|
||||||
|
cxx="ccache $cxx"
|
||||||
|
fi
|
||||||
|
build_jobs=${CNC_SIM_BUILD_JOBS:-8}
|
||||||
|
if ! [[ "$build_jobs" =~ ^[1-9][0-9]*$ ]]; then
|
||||||
|
echo "CNC_SIM_BUILD_JOBS must be a positive integer: $build_jobs" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cache_dir=${CNC_SIM_NATIVE_BRIDGE_OBJECT_CACHE_DIR-build/native-bridge-object-cache}
|
||||||
|
if [[ -z "$cache_dir" ]]; then
|
||||||
|
echo "CNC_SIM_NATIVE_BRIDGE_OBJECT_CACHE_DIR must not be empty" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "$cache_dir" =~ [[:space:]] ]]; then
|
||||||
|
echo "CNC_SIM_NATIVE_BRIDGE_OBJECT_CACHE_DIR must not contain whitespace: $cache_dir" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mkdir -p "$cache_dir"
|
||||||
|
cache_dir=$(cd "$cache_dir" && pwd)
|
||||||
|
if [[ "$cache_dir" == "/" ]]; then
|
||||||
|
echo "CNC_SIM_NATIVE_BRIDGE_OBJECT_CACHE_DIR must not be the filesystem root" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
exec 8>"$cache_dir/native-bridge-objects.lock"
|
||||||
|
flock 8
|
||||||
|
|
||||||
|
preflight_cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-"$cache_dir/preflight-cache"}
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs-cached.sh --cache-dir "$preflight_cache_dir" --root-only
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
source_output=$(./list-linuxcnc-bridge-smoke-project-sources.sh)
|
||||||
|
mapfile -t sources <<<"$source_output"
|
||||||
|
common_flag_output=$(
|
||||||
|
CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" \
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-common-cxxflags.sh \
|
||||||
|
--no-ulapi \
|
||||||
|
--core-include \
|
||||||
|
--core-src
|
||||||
|
)
|
||||||
|
mapfile -t common_flags <<<"$common_flag_output"
|
||||||
|
|
||||||
|
objects=()
|
||||||
|
source_index=0
|
||||||
|
for source in "${sources[@]}"; do
|
||||||
|
objects+=("$cache_dir/source_${source_index}.o")
|
||||||
|
source_index=$((source_index + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
signature="$cache_dir/native-bridge-objects.signature"
|
||||||
|
next_signature="$cache_dir/native-bridge-objects.signature.next"
|
||||||
|
{
|
||||||
|
printf 'CXX=%s\n' "$cxx"
|
||||||
|
printf 'PWD=%s\n' "$PWD"
|
||||||
|
printf 'LINUXCNC_ROOT=%s\n' "$linuxcnc_root"
|
||||||
|
printf 'BUILD_RULE_VERSION=1\n'
|
||||||
|
printf 'COMMON_FLAGS='
|
||||||
|
printf ' %s' "${common_flags[@]}"
|
||||||
|
printf '\n'
|
||||||
|
printf 'SOURCES:\n'
|
||||||
|
printf '%s\n' "${sources[@]}"
|
||||||
|
} > "$next_signature"
|
||||||
|
if [[ ! -f "$signature" ]] || ! cmp -s "$signature" "$next_signature"; then
|
||||||
|
rm -f "$cache_dir"/source_*.o "$cache_dir"/source_*.d
|
||||||
|
fi
|
||||||
|
mv "$next_signature" "$signature"
|
||||||
|
|
||||||
|
makefile="$cache_dir/native-bridge-objects.mk"
|
||||||
|
{
|
||||||
|
printf 'CXX := %s\n' "$cxx"
|
||||||
|
printf 'COMMON_FLAGS :='
|
||||||
|
printf ' %s' "${common_flags[@]}"
|
||||||
|
printf '\n\n'
|
||||||
|
printf 'OBJECTS :='
|
||||||
|
printf ' %s' "${objects[@]}"
|
||||||
|
printf '\n\n'
|
||||||
|
printf 'DEP_FILES :=\n'
|
||||||
|
for object in "${objects[@]}"; do
|
||||||
|
printf 'DEP_FILES += %s.d\n' "$object"
|
||||||
|
done
|
||||||
|
printf '\n.PHONY: all\n'
|
||||||
|
printf 'all: $(OBJECTS)\n\n'
|
||||||
|
|
||||||
|
source_index=0
|
||||||
|
for source in "${sources[@]}"; do
|
||||||
|
printf '%s: %s\n' "${objects[$source_index]}" "$source"
|
||||||
|
printf '\t@$(CXX) $(COMMON_FLAGS) -MMD -MP -MF %s.d -c %s -o %s\n\n' \
|
||||||
|
"${objects[$source_index]}" "$source" "${objects[$source_index]}"
|
||||||
|
source_index=$((source_index + 1))
|
||||||
|
done
|
||||||
|
printf '\n-include $(DEP_FILES)\n'
|
||||||
|
} > "$makefile"
|
||||||
|
make --output-sync=target -j"$build_jobs" -f "$makefile" >/dev/null
|
||||||
|
|
||||||
|
printf '%s\n' "${objects[@]}"
|
||||||
152
build-linuxcnc-wasm-link-probe.sh
Executable file
152
build-linuxcnc-wasm-link-probe.sh
Executable file
@@ -0,0 +1,152 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: link probe modes reuse wasm-safe objects built from
|
||||||
|
# linuxcnc-rs274-wasm-source-files.txt and add only a narrow probe main that
|
||||||
|
# asserts LinuxCNC rs274ngc_pre/runtime symbols stay linked.
|
||||||
|
usage() {
|
||||||
|
echo "usage: $0 --mode rs274ngc-pre|runtime [manifest]" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
mode=
|
||||||
|
manifest=linuxcnc-rs274-wasm-source-files.txt
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--mode)
|
||||||
|
if [[ "$#" -lt 2 ]]; then
|
||||||
|
echo "missing --mode value" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mode=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--help|-h)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--*)
|
||||||
|
usage
|
||||||
|
echo "unknown wasm link probe option: $1" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
manifest=$1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
case "$mode" in
|
||||||
|
rs274ngc-pre|runtime)
|
||||||
|
;;
|
||||||
|
"")
|
||||||
|
usage
|
||||||
|
echo "missing --mode" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
echo "unknown wasm link probe mode: $mode" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
cxx=${CXX:-g++}
|
||||||
|
if [[ -z ${CXX:-} ]] && command -v ccache >/dev/null 2>&1; then
|
||||||
|
cxx="ccache $cxx"
|
||||||
|
fi
|
||||||
|
build_jobs=${CNC_SIM_BUILD_JOBS:-8}
|
||||||
|
if ! [[ "$build_jobs" =~ ^[1-9][0-9]*$ ]]; then
|
||||||
|
echo "CNC_SIM_BUILD_JOBS must be a positive integer: $build_jobs" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cache_dir=${CNC_SIM_WASM_LINK_PROBE_CACHE_DIR-build/wasm-link-probe-cache}
|
||||||
|
if [[ -z "$cache_dir" ]]; then
|
||||||
|
echo "CNC_SIM_WASM_LINK_PROBE_CACHE_DIR must not be empty" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "$cache_dir" =~ [[:space:]] ]]; then
|
||||||
|
echo "CNC_SIM_WASM_LINK_PROBE_CACHE_DIR must not contain whitespace: $cache_dir" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mkdir -p "$cache_dir"
|
||||||
|
cache_dir=$(cd "$cache_dir" && pwd)
|
||||||
|
if [[ "$cache_dir" == "/" ]]; then
|
||||||
|
echo "CNC_SIM_WASM_LINK_PROBE_CACHE_DIR must not be the filesystem root" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
preflight_cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-"$cache_dir/preflight-cache"}
|
||||||
|
object_mode=$mode
|
||||||
|
main_source=core/wasm_shims/rs274ngc_pre_probe_main.cc
|
||||||
|
target_name=rs274ngc_pre_probe
|
||||||
|
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh --profile core20-sections)
|
||||||
|
mapfile -t common_flags <<<"$common_flag_output"
|
||||||
|
case "$mode" in
|
||||||
|
rs274ngc-pre)
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc provides' "$main_source" >/dev/null
|
||||||
|
;;
|
||||||
|
runtime)
|
||||||
|
object_mode=runtime
|
||||||
|
main_source=core/wasm_shims/cnc_sim_wasm_runtime_probe_main.cc
|
||||||
|
target_name=cnc_sim_wasm_runtime_probe
|
||||||
|
common_flags+=(-DCNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc provides read(),' "$main_source" >/dev/null
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
object_output=$(CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" LINUXCNC_ROOT="$linuxcnc_root" ./build-linuxcnc-wasm-probe-objects.sh --mode "$object_mode" "$manifest")
|
||||||
|
mapfile -t objects <<<"$object_output"
|
||||||
|
manifest=$(cd "$(dirname "$manifest")" && pwd)/$(basename "$manifest")
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
mode_dir="$cache_dir/$mode"
|
||||||
|
mkdir -p "$mode_dir"
|
||||||
|
exec 8>"$mode_dir/link.lock"
|
||||||
|
flock 8
|
||||||
|
|
||||||
|
main_object="$mode_dir/main.o"
|
||||||
|
target="$mode_dir/$target_name"
|
||||||
|
signature="$mode_dir/link.signature"
|
||||||
|
next_signature="$mode_dir/link.signature.next"
|
||||||
|
{
|
||||||
|
printf 'CXX=%s\n' "$cxx"
|
||||||
|
printf 'PWD=%s\n' "$PWD"
|
||||||
|
printf 'LINUXCNC_ROOT=%s\n' "$linuxcnc_root"
|
||||||
|
printf 'MANIFEST=%s\n' "$manifest"
|
||||||
|
printf 'MODE=%s\n' "$mode"
|
||||||
|
printf 'BUILD_RULE_VERSION=1\n'
|
||||||
|
printf 'COMMON_FLAGS='
|
||||||
|
printf ' %s' "${common_flags[@]}"
|
||||||
|
printf '\n'
|
||||||
|
printf 'MAIN_SOURCE=%s\n' "$main_source"
|
||||||
|
printf 'OBJECTS:\n'
|
||||||
|
printf '%s\n' "${objects[@]}"
|
||||||
|
} > "$next_signature"
|
||||||
|
if [[ ! -f "$signature" ]] || ! cmp -s "$signature" "$next_signature"; then
|
||||||
|
rm -f "$main_object" "$main_object.d" "$target" "$mode_dir/runtime.symbols"
|
||||||
|
fi
|
||||||
|
mv "$next_signature" "$signature"
|
||||||
|
|
||||||
|
makefile="$mode_dir/link.mk"
|
||||||
|
{
|
||||||
|
printf 'CXX := %s\n' "$cxx"
|
||||||
|
printf 'COMMON_FLAGS :='
|
||||||
|
printf ' %s' "${common_flags[@]}"
|
||||||
|
printf '\n\n'
|
||||||
|
printf 'OBJECTS :='
|
||||||
|
printf ' %s' "${objects[@]}"
|
||||||
|
printf '\n\n'
|
||||||
|
printf '.PHONY: all\n'
|
||||||
|
printf 'all: %s\n\n' "$target"
|
||||||
|
printf '%s: %s\n' "$main_object" "$main_source"
|
||||||
|
printf '\t@$(CXX) $(COMMON_FLAGS) -MMD -MP -MF %s.d -c %s -o %s\n\n' "$main_object" "$main_source" "$main_object"
|
||||||
|
printf '%s: $(OBJECTS) %s\n' "$target" "$main_object"
|
||||||
|
printf '\t@$(CXX) $(OBJECTS) %s -Wl,--gc-sections -lfmt -o %s\n\n' "$main_object" "$target"
|
||||||
|
printf '\n-include %s.d\n' "$main_object"
|
||||||
|
} > "$makefile"
|
||||||
|
make --output-sync=target -j"$build_jobs" -f "$makefile" >/dev/null
|
||||||
|
|
||||||
|
printf '%s\n' "$target"
|
||||||
197
build-linuxcnc-wasm-probe-objects.sh
Executable file
197
build-linuxcnc-wasm-probe-objects.sh
Executable file
@@ -0,0 +1,197 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: object probes compile the core entries selected from
|
||||||
|
# linuxcnc-rs274-wasm-source-files.txt, including src/emc/rs274ngc,
|
||||||
|
# src/emc/tooldata/tooldata_common.cc, src/emc/ini/inifile.cc, and
|
||||||
|
# src/emc/nml_intf/emcops.cc, together with CMake-listed wasm-safe project
|
||||||
|
# bridge sources and shims that replace the manifest's blocked Python, dlopen,
|
||||||
|
# tooldata mmap, HAL, and runtime edges.
|
||||||
|
usage() {
|
||||||
|
echo "usage: $0 --mode source-objects|rs274ngc-pre|runtime [manifest]" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
mode=
|
||||||
|
manifest=linuxcnc-rs274-wasm-source-files.txt
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--mode)
|
||||||
|
if [[ "$#" -lt 2 ]]; then
|
||||||
|
echo "missing --mode value" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mode=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--help|-h)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--*)
|
||||||
|
usage
|
||||||
|
echo "unknown wasm probe object cache option: $1" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
manifest=$1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
case "$mode" in
|
||||||
|
source-objects|rs274ngc-pre|runtime)
|
||||||
|
;;
|
||||||
|
"")
|
||||||
|
usage
|
||||||
|
echo "missing --mode" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
echo "unknown wasm probe object cache mode: $mode" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
cxx=${CXX:-g++}
|
||||||
|
if [[ -z ${CXX:-} ]] && command -v ccache >/dev/null 2>&1; then
|
||||||
|
cxx="ccache $cxx"
|
||||||
|
fi
|
||||||
|
build_jobs=${CNC_SIM_BUILD_JOBS:-8}
|
||||||
|
if ! [[ "$build_jobs" =~ ^[1-9][0-9]*$ ]]; then
|
||||||
|
echo "CNC_SIM_BUILD_JOBS must be a positive integer: $build_jobs" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cache_dir=${CNC_SIM_WASM_PROBE_OBJECT_CACHE_DIR-build/wasm-probe-object-cache}
|
||||||
|
if [[ -z "$cache_dir" ]]; then
|
||||||
|
echo "CNC_SIM_WASM_PROBE_OBJECT_CACHE_DIR must not be empty" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "$cache_dir" =~ [[:space:]] ]]; then
|
||||||
|
echo "CNC_SIM_WASM_PROBE_OBJECT_CACHE_DIR must not contain whitespace: $cache_dir" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mkdir -p "$cache_dir"
|
||||||
|
cache_dir=$(cd "$cache_dir" && pwd)
|
||||||
|
if [[ "$cache_dir" == "/" ]]; then
|
||||||
|
echo "CNC_SIM_WASM_PROBE_OBJECT_CACHE_DIR must not be the filesystem root" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
preflight_cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-"$cache_dir/preflight-cache"}
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs-cached.sh --cache-dir "$preflight_cache_dir" "$manifest" --require-rs274-complete
|
||||||
|
manifest=$(cd "$(dirname "$manifest")" && pwd)/$(basename "$manifest")
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
common_flag_profile=core20-sections
|
||||||
|
case "$mode" in
|
||||||
|
source-objects)
|
||||||
|
common_flag_profile=core20
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh --profile "$common_flag_profile")
|
||||||
|
mapfile -t common_flags <<<"$common_flag_output"
|
||||||
|
case "$mode" in
|
||||||
|
runtime)
|
||||||
|
common_flags+=(-DCNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC source basis: wasm-safe project probe sources are the thin bridge' list-linuxcnc-wasm-safe-project-sources.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: wasm-safe shim probe sources are limited to the' list-linuxcnc-wasm-safe-shims.sh >/dev/null
|
||||||
|
|
||||||
|
sources=()
|
||||||
|
shim_output=$(./list-linuxcnc-wasm-safe-shims.sh)
|
||||||
|
mapfile -t shim_sources <<<"$shim_output"
|
||||||
|
sources+=("${shim_sources[@]}")
|
||||||
|
case "$mode" in
|
||||||
|
source-objects)
|
||||||
|
;;
|
||||||
|
rs274ngc-pre|runtime)
|
||||||
|
project_source_output=$(./list-linuxcnc-wasm-safe-project-sources.sh)
|
||||||
|
if [[ -n "$project_source_output" ]]; then
|
||||||
|
mapfile -t project_sources <<<"$project_source_output"
|
||||||
|
sources+=("${project_sources[@]}")
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
source_output=$(CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core full)
|
||||||
|
mapfile -t linuxcnc_sources <<<"$source_output"
|
||||||
|
sources+=("${linuxcnc_sources[@]}")
|
||||||
|
for source in "${sources[@]}"; do
|
||||||
|
if [[ -z "$source" ]]; then
|
||||||
|
echo "wasm probe object source list contains an empty path" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
mode_dir="$cache_dir/$mode"
|
||||||
|
mkdir -p "$mode_dir"
|
||||||
|
exec 8>"$mode_dir/objects.lock"
|
||||||
|
flock 8
|
||||||
|
|
||||||
|
objects=()
|
||||||
|
object_index=0
|
||||||
|
for source in "${sources[@]}"; do
|
||||||
|
objects+=("$mode_dir/source_${object_index}.o")
|
||||||
|
object_index=$((object_index + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
signature="$mode_dir/objects.signature"
|
||||||
|
next_signature="$mode_dir/objects.signature.next"
|
||||||
|
{
|
||||||
|
printf 'CXX=%s\n' "$cxx"
|
||||||
|
printf 'PWD=%s\n' "$PWD"
|
||||||
|
printf 'LINUXCNC_ROOT=%s\n' "$linuxcnc_root"
|
||||||
|
printf 'MANIFEST=%s\n' "$manifest"
|
||||||
|
printf 'MODE=%s\n' "$mode"
|
||||||
|
printf 'BUILD_RULE_VERSION=1\n'
|
||||||
|
printf 'COMMON_FLAGS='
|
||||||
|
printf ' %s' "${common_flags[@]}"
|
||||||
|
printf '\n'
|
||||||
|
printf 'SOURCES:\n'
|
||||||
|
printf '%s\n' "${sources[@]}"
|
||||||
|
} > "$next_signature"
|
||||||
|
if [[ ! -f "$signature" ]] || ! cmp -s "$signature" "$next_signature"; then
|
||||||
|
rm -f "$mode_dir"/source_*.o "$mode_dir"/source_*.d
|
||||||
|
fi
|
||||||
|
mv "$next_signature" "$signature"
|
||||||
|
|
||||||
|
makefile="$mode_dir/objects.mk"
|
||||||
|
{
|
||||||
|
printf 'CXX := %s\n' "$cxx"
|
||||||
|
printf 'COMMON_FLAGS :='
|
||||||
|
printf ' %s' "${common_flags[@]}"
|
||||||
|
printf '\n\n'
|
||||||
|
printf 'OBJECTS :='
|
||||||
|
printf ' %s' "${objects[@]}"
|
||||||
|
printf '\n\n'
|
||||||
|
printf 'DEP_FILES :=\n'
|
||||||
|
for object in "${objects[@]}"; do
|
||||||
|
printf 'DEP_FILES += %s.d\n' "$object"
|
||||||
|
done
|
||||||
|
printf '\n.PHONY: all\n'
|
||||||
|
printf 'all: $(OBJECTS)\n\n'
|
||||||
|
|
||||||
|
object_index=0
|
||||||
|
for source in "${sources[@]}"; do
|
||||||
|
source_flags=()
|
||||||
|
case "$source" in
|
||||||
|
core/src/linuxcnc_corexykins_adapter.c|core/src/linuxcnc_genserfuncs_adapter.c|core/src/linuxcnc_xyzab_tdr_kins_adapter.c)
|
||||||
|
source_flags+=(-fpermissive)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
printf '%s: %s\n' "${objects[$object_index]}" "$source"
|
||||||
|
printf '\t@$(CXX) $(COMMON_FLAGS)'
|
||||||
|
printf ' %s' "${source_flags[@]}"
|
||||||
|
printf ' -MMD -MP -MF %s.d -c %s -o %s\n\n' "${objects[$object_index]}" "$source" "${objects[$object_index]}"
|
||||||
|
object_index=$((object_index + 1))
|
||||||
|
done
|
||||||
|
printf '\n-include $(DEP_FILES)\n'
|
||||||
|
} > "$makefile"
|
||||||
|
make --output-sync=target -j"$build_jobs" -f "$makefile" >/dev/null
|
||||||
|
|
||||||
|
printf '%s\n' "${objects[@]}"
|
||||||
211
build-linuxcnc-wasm-standalone-probe.sh
Executable file
211
build-linuxcnc-wasm-standalone-probe.sh
Executable file
@@ -0,0 +1,211 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: standalone probe modes either compile LinuxCNC
|
||||||
|
# rs274/tooldata sources directly or link wasm-safe shims whose source basis is
|
||||||
|
# checked against LinuxCNC source comments before building.
|
||||||
|
usage() {
|
||||||
|
echo "usage: $0 --mode tooldata-link|tooldata-common-link|interp-base-link|python-plugin-link|python-plugin-inittab-link|rs274ngc-pre-object" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
mode=
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--mode)
|
||||||
|
if [[ "$#" -lt 2 ]]; then
|
||||||
|
echo "missing --mode value" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mode=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--help|-h)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
echo "unknown wasm standalone probe option: $1" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
case "$mode" in
|
||||||
|
tooldata-link|tooldata-common-link|interp-base-link|python-plugin-link|python-plugin-inittab-link|rs274ngc-pre-object)
|
||||||
|
;;
|
||||||
|
"")
|
||||||
|
usage
|
||||||
|
echo "missing --mode" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
echo "unknown wasm standalone probe mode: $mode" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
cxx=${CXX:-g++}
|
||||||
|
if [[ -z ${CXX:-} ]] && command -v ccache >/dev/null 2>&1; then
|
||||||
|
cxx="ccache $cxx"
|
||||||
|
fi
|
||||||
|
build_jobs=${CNC_SIM_BUILD_JOBS:-8}
|
||||||
|
if ! [[ "$build_jobs" =~ ^[1-9][0-9]*$ ]]; then
|
||||||
|
echo "CNC_SIM_BUILD_JOBS must be a positive integer: $build_jobs" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cache_dir=${CNC_SIM_WASM_STANDALONE_PROBE_CACHE_DIR-build/wasm-standalone-probe-cache}
|
||||||
|
if [[ -z "$cache_dir" ]]; then
|
||||||
|
echo "CNC_SIM_WASM_STANDALONE_PROBE_CACHE_DIR must not be empty" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "$cache_dir" =~ [[:space:]] ]]; then
|
||||||
|
echo "CNC_SIM_WASM_STANDALONE_PROBE_CACHE_DIR must not contain whitespace: $cache_dir" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mkdir -p "$cache_dir"
|
||||||
|
cache_dir=$(cd "$cache_dir" && pwd)
|
||||||
|
if [[ "$cache_dir" == "/" ]]; then
|
||||||
|
echo "CNC_SIM_WASM_STANDALONE_PROBE_CACHE_DIR must not be the filesystem root" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
preflight_cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-"$cache_dir/preflight-cache"}
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs-cached.sh --cache-dir "$preflight_cache_dir" --root-only
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
common_flag_args=()
|
||||||
|
sources=()
|
||||||
|
target_name=
|
||||||
|
case "$mode" in
|
||||||
|
tooldata-link|tooldata-common-link)
|
||||||
|
if [[ "$mode" == "tooldata-common-link" ]]; then
|
||||||
|
common_flag_args+=(--tooldata-include)
|
||||||
|
fi
|
||||||
|
tooldata_mmap_backend_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_mmap_backend.cc)
|
||||||
|
tooldata_runtime_stubs_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_runtime_stubs.cc)
|
||||||
|
tooldata_common_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/tooldata/tooldata_common.cc)
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/tooldata/tooldata_common.cc provides' core/wasm_shims/tooldata/tooldata_common_probe_main.cc >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/tooldata/tooldata_mmap.cc, tooldata_nml.cc,' core/wasm_shims/tooldata/tooldata_probe_main.cc >/dev/null
|
||||||
|
sources+=(
|
||||||
|
"$tooldata_common_source"
|
||||||
|
"$tooldata_mmap_backend_shim"
|
||||||
|
"$tooldata_runtime_stubs_shim"
|
||||||
|
)
|
||||||
|
if [[ "$mode" == "tooldata-link" ]]; then
|
||||||
|
sources+=(core/wasm_shims/tooldata/tooldata_probe_main.cc)
|
||||||
|
target_name=tooldata_probe
|
||||||
|
else
|
||||||
|
sources+=(core/wasm_shims/tooldata/tooldata_common_probe_main.cc)
|
||||||
|
target_name=tooldata_common_probe
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
interp-base-link)
|
||||||
|
dlfcn_shim=$(./list-linuxcnc-wasm-safe-shims.sh dlfcn.cc)
|
||||||
|
interp_base_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/rs274ngc/interp_base.cc)
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/interp_base.cc provides' core/wasm_shims/interp_base_probe_main.cc >/dev/null
|
||||||
|
sources+=(
|
||||||
|
"$dlfcn_shim"
|
||||||
|
"$interp_base_source"
|
||||||
|
core/wasm_shims/interp_base_probe_main.cc
|
||||||
|
)
|
||||||
|
target_name=interp_base_probe
|
||||||
|
;;
|
||||||
|
python-plugin-link|python-plugin-inittab-link)
|
||||||
|
python_plugin_shim=$(./list-linuxcnc-wasm-safe-shims.sh python_plugin.cc)
|
||||||
|
if [[ "$mode" == "python-plugin-link" ]]; then
|
||||||
|
probe_source=core/wasm_shims/pythonplugin/python_plugin_probe_main.cc
|
||||||
|
target_name=python_plugin_probe
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc and' "$probe_source" >/dev/null
|
||||||
|
else
|
||||||
|
probe_source=core/wasm_shims/pythonplugin/python_plugin_inittab_probe_main.cc
|
||||||
|
target_name=python_plugin_inittab_probe
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc' "$probe_source" >/dev/null
|
||||||
|
fi
|
||||||
|
sources+=(
|
||||||
|
"$python_plugin_shim"
|
||||||
|
"$probe_source"
|
||||||
|
)
|
||||||
|
;;
|
||||||
|
rs274ngc-pre-object)
|
||||||
|
rs274ngc_pre_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/rs274ngc/rs274ngc_pre.cc)
|
||||||
|
grep -F 'core:src/emc/rs274ngc/rs274ngc_pre.cc:Interp implementation covered by rs274ngc_pre link probe' linuxcnc-rs274-wasm-source-files.txt >/dev/null
|
||||||
|
sources+=("$rs274ngc_pre_source")
|
||||||
|
target_name=rs274ngc_pre.o
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh "${common_flag_args[@]}")
|
||||||
|
mapfile -t common_flags <<<"$common_flag_output"
|
||||||
|
|
||||||
|
mode_dir="$cache_dir/$mode"
|
||||||
|
mkdir -p "$mode_dir"
|
||||||
|
exec 8>"$mode_dir/probe.lock"
|
||||||
|
flock 8
|
||||||
|
|
||||||
|
objects=()
|
||||||
|
object_index=0
|
||||||
|
for source in "${sources[@]}"; do
|
||||||
|
objects+=("$mode_dir/source_${object_index}.o")
|
||||||
|
object_index=$((object_index + 1))
|
||||||
|
done
|
||||||
|
target="$mode_dir/$target_name"
|
||||||
|
if [[ "$mode" == "rs274ngc-pre-object" ]]; then
|
||||||
|
target=${objects[0]}
|
||||||
|
fi
|
||||||
|
|
||||||
|
signature="$mode_dir/probe.signature"
|
||||||
|
next_signature="$mode_dir/probe.signature.next"
|
||||||
|
{
|
||||||
|
printf 'CXX=%s\n' "$cxx"
|
||||||
|
printf 'PWD=%s\n' "$PWD"
|
||||||
|
printf 'LINUXCNC_ROOT=%s\n' "$linuxcnc_root"
|
||||||
|
printf 'MODE=%s\n' "$mode"
|
||||||
|
printf 'BUILD_RULE_VERSION=1\n'
|
||||||
|
printf 'COMMON_FLAGS='
|
||||||
|
printf ' %s' "${common_flags[@]}"
|
||||||
|
printf '\n'
|
||||||
|
printf 'SOURCES:\n'
|
||||||
|
printf '%s\n' "${sources[@]}"
|
||||||
|
} > "$next_signature"
|
||||||
|
if [[ ! -f "$signature" ]] || ! cmp -s "$signature" "$next_signature"; then
|
||||||
|
rm -f "$mode_dir"/source_*.o "$mode_dir"/source_*.d "$target"
|
||||||
|
fi
|
||||||
|
mv "$next_signature" "$signature"
|
||||||
|
|
||||||
|
makefile="$mode_dir/probe.mk"
|
||||||
|
{
|
||||||
|
printf 'CXX := %s\n' "$cxx"
|
||||||
|
printf 'COMMON_FLAGS :='
|
||||||
|
printf ' %s' "${common_flags[@]}"
|
||||||
|
printf '\n\n'
|
||||||
|
printf 'OBJECTS :='
|
||||||
|
printf ' %s' "${objects[@]}"
|
||||||
|
printf '\n\n'
|
||||||
|
printf 'DEP_FILES :=\n'
|
||||||
|
for object in "${objects[@]}"; do
|
||||||
|
printf 'DEP_FILES += %s.d\n' "$object"
|
||||||
|
done
|
||||||
|
printf '\n.PHONY: all\n'
|
||||||
|
printf 'all: %s\n\n' "$target"
|
||||||
|
|
||||||
|
object_index=0
|
||||||
|
for source in "${sources[@]}"; do
|
||||||
|
printf '%s: %s\n' "${objects[$object_index]}" "$source"
|
||||||
|
printf '\t@$(CXX) $(COMMON_FLAGS) -MMD -MP -MF %s.d -c %s -o %s\n\n' \
|
||||||
|
"${objects[$object_index]}" "$source" "${objects[$object_index]}"
|
||||||
|
object_index=$((object_index + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$mode" != "rs274ngc-pre-object" ]]; then
|
||||||
|
printf '%s: $(OBJECTS)\n' "$target"
|
||||||
|
printf '\t@$(CXX) $(OBJECTS) -o %s\n\n' "$target"
|
||||||
|
fi
|
||||||
|
printf '\n-include $(DEP_FILES)\n'
|
||||||
|
} > "$makefile"
|
||||||
|
make --output-sync=target -j"$build_jobs" -f "$makefile" >/dev/null
|
||||||
|
|
||||||
|
printf '%s\n' "$target"
|
||||||
206
build-wasm.sh
206
build-wasm.sh
@@ -3,14 +3,208 @@ set -euo pipefail
|
|||||||
|
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
if ! command -v emcmake >/dev/null 2>&1; then
|
# LinuxCNC source basis: the wasm build preflights and compiles the
|
||||||
echo "Emscripten is required. Install/activate emsdk so emcmake and emcc are in PATH." >&2
|
# linuxcnc-rs274-wasm-source-files.txt manifest entries from
|
||||||
|
# src/emc/rs274ngc/tooldata plus source-basis-checked shims before copying the
|
||||||
|
# browser artifacts; it must not add independent interpreter behavior.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||||
|
build_jobs=${CNC_SIM_BUILD_JOBS:-8}
|
||||||
|
if ! [[ "$build_jobs" =~ ^[1-9][0-9]*$ ]]; then
|
||||||
|
echo "CNC_SIM_BUILD_JOBS must be a positive integer: $build_jobs" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cmake_compiler_launcher_mode=none
|
||||||
|
cmake_compiler_launcher_args=()
|
||||||
|
if [[ -z ${CXX:-} ]] && command -v ccache >/dev/null 2>&1; then
|
||||||
|
cmake_compiler_launcher_mode=ccache
|
||||||
|
cmake_compiler_launcher_args+=(
|
||||||
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache
|
||||||
|
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
preflight_cache_dir=build/wasm-preflight-cache
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs-cached.sh --cache-dir "$preflight_cache_dir" "$manifest"
|
||||||
|
./check-linuxcnc-rs274-source-map.sh
|
||||||
|
./check-linuxcnc-kinematics-source-map.sh
|
||||||
|
./check-linuxcnc-opfs-source-map.sh
|
||||||
|
./check-linuxcnc-switchkins-remap-source-map.sh
|
||||||
|
./check-linuxcnc-wasm-smoke-source-map.sh
|
||||||
|
./check-linuxcnc-build-source-map.sh
|
||||||
|
./check-linuxcnc-browser-app-source-map.sh
|
||||||
|
./check-linuxcnc-workstreams-source-map.sh
|
||||||
|
./check-linuxcnc-tooldata-source-map.sh
|
||||||
|
./check-linuxcnc-wasm-shims-source-map.sh
|
||||||
|
./check-linuxcnc-wasm-blockers-source-map.sh
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-switchkins-remap-table-cached.sh --cache-dir "$preflight_cache_dir" linuxcnc-kinematics-source-files.txt
|
||||||
|
manifest=$(cd "$(dirname "$manifest")" && pwd)/$(basename "$manifest")
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
default_manifest="$PWD/linuxcnc-rs274-wasm-source-files.txt"
|
||||||
|
|
||||||
|
count_nonempty_lines() {
|
||||||
|
local text=${1-}
|
||||||
|
local count=0
|
||||||
|
local line
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if [[ -n "$line" ]]; then
|
||||||
|
count=$((count + 1))
|
||||||
|
fi
|
||||||
|
done <<<"$text"
|
||||||
|
|
||||||
|
printf '%s\n' "$count"
|
||||||
|
}
|
||||||
|
|
||||||
|
parallel_probe_labels=()
|
||||||
|
parallel_probe_logs=()
|
||||||
|
parallel_probe_pids=()
|
||||||
|
|
||||||
|
run_parallel_wasm_probe() {
|
||||||
|
local label=$1
|
||||||
|
shift
|
||||||
|
local probe_index=${#parallel_probe_pids[@]}
|
||||||
|
local log_dir=build/wasm-preflight-cache/parallel-probe-logs
|
||||||
|
local log="$log_dir/probe_${probe_index}.log"
|
||||||
|
|
||||||
|
mkdir -p "$log_dir"
|
||||||
|
(
|
||||||
|
CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" "$@"
|
||||||
|
) >"$log" 2>&1 &
|
||||||
|
parallel_probe_labels+=("$label")
|
||||||
|
parallel_probe_logs+=("$log")
|
||||||
|
parallel_probe_pids+=("$!")
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_parallel_wasm_probes() {
|
||||||
|
local failed=0
|
||||||
|
local probe_index
|
||||||
|
local status
|
||||||
|
|
||||||
|
for probe_index in "${!parallel_probe_pids[@]}"; do
|
||||||
|
echo "${parallel_probe_labels[$probe_index]}"
|
||||||
|
if wait "${parallel_probe_pids[$probe_index]}"; then
|
||||||
|
cat "${parallel_probe_logs[$probe_index]}"
|
||||||
|
else
|
||||||
|
status=$?
|
||||||
|
cat "${parallel_probe_logs[$probe_index]}" >&2 || true
|
||||||
|
echo "${parallel_probe_labels[$probe_index]} failed with status $status" >&2
|
||||||
|
failed=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
parallel_probe_labels=()
|
||||||
|
parallel_probe_logs=()
|
||||||
|
parallel_probe_pids=()
|
||||||
|
|
||||||
|
if [[ "$failed" -ne 0 ]]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# This script writes fixed build and public artifact paths, so serialize it.
|
||||||
|
if [[ "${CNC_SIM_BUILD_WASM_SKIP_LOCK:-0}" != "1" ]]; then
|
||||||
|
exec 9>"${TMPDIR:-/tmp}/cnc_sim_build_wasm.lock"
|
||||||
|
flock 9
|
||||||
|
fi
|
||||||
|
|
||||||
|
manifest_core_count=0
|
||||||
|
manifest_blocked_count=0
|
||||||
|
manifest_core_output=$(CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core)
|
||||||
|
manifest_blocked_output=$(CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" blocked)
|
||||||
|
manifest_core_count=$(count_nonempty_lines "$manifest_core_output")
|
||||||
|
manifest_blocked_count=$(count_nonempty_lines "$manifest_blocked_output")
|
||||||
|
|
||||||
|
if [[ "$manifest_core_count" -eq 0 || "$manifest_blocked_count" -eq 0 ]]; then
|
||||||
|
echo "unexpected wasm manifest partition: core=$manifest_core_count blocked=$manifest_blocked_count" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "$manifest" == "$default_manifest" ]] && [[ "$manifest_core_count" -ne 26 || "$manifest_blocked_count" -ne 9 ]]; then
|
||||||
|
echo "unexpected wasm manifest partition: core=$manifest_core_count blocked=$manifest_blocked_count" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs-cached.sh --cache-dir "$preflight_cache_dir" "$manifest" --require-rs274-complete
|
||||||
|
|
||||||
|
echo "LinuxCNC wasm blocker scan"
|
||||||
|
CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" ./test-linuxcnc-wasm-blockers.sh "$manifest"
|
||||||
|
|
||||||
|
echo "LinuxCNC wasm-safe source syntax probe"
|
||||||
|
CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" ./test-linuxcnc-wasm-source-syntax.sh "$manifest"
|
||||||
|
|
||||||
|
echo "LinuxCNC wasm-safe source object probe"
|
||||||
|
CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" ./test-linuxcnc-wasm-source-objects.sh "$manifest"
|
||||||
|
|
||||||
|
echo "LinuxCNC wasm-safe CMake probe target"
|
||||||
|
CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" ./test-linuxcnc-wasm-cmake-safe-probe.sh "$manifest"
|
||||||
|
|
||||||
|
run_parallel_wasm_probe "LinuxCNC wasm tooldata shim link probe" ./test-linuxcnc-wasm-tooldata-link.sh
|
||||||
|
run_parallel_wasm_probe "LinuxCNC wasm tooldata_common link probe" ./test-linuxcnc-wasm-tooldata-common-link.sh
|
||||||
|
run_parallel_wasm_probe "LinuxCNC wasm tooldata_mmap symbol probe" ./test-linuxcnc-wasm-tooldata-mmap-symbols.sh
|
||||||
|
run_parallel_wasm_probe "LinuxCNC wasm tooldata runtime symbol probe" ./test-linuxcnc-wasm-tooldata-runtime-symbols.sh
|
||||||
|
run_parallel_wasm_probe "LinuxCNC wasm interp_base link probe" ./test-linuxcnc-wasm-interp-base-link.sh
|
||||||
|
run_parallel_wasm_probe "LinuxCNC wasm interp_find link probe" ./test-linuxcnc-wasm-interp-find-link.sh
|
||||||
|
run_parallel_wasm_probe "LinuxCNC wasm python_plugin link probe" ./test-linuxcnc-wasm-python-plugin-link.sh
|
||||||
|
run_parallel_wasm_probe "LinuxCNC wasm Python C API symbol probe" ./test-linuxcnc-wasm-python-c-api-symbols.sh
|
||||||
|
run_parallel_wasm_probe "LinuxCNC wasm Python binding link probe" ./test-linuxcnc-wasm-python-binding-link.sh
|
||||||
|
run_parallel_wasm_probe "LinuxCNC wasm rs274ngc_pre object probe" ./test-linuxcnc-wasm-rs274ngc-pre-object.sh
|
||||||
|
wait_parallel_wasm_probes
|
||||||
|
|
||||||
|
echo "LinuxCNC wasm rs274ngc_pre link blocker scan"
|
||||||
|
CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" ./test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh "$manifest"
|
||||||
|
|
||||||
|
echo "LinuxCNC wasm rs274ngc_pre link probe"
|
||||||
|
CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" ./test-linuxcnc-wasm-rs274ngc-pre-link.sh "$manifest"
|
||||||
|
|
||||||
|
echo "LinuxCNC wasm runtime link probe"
|
||||||
|
CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" ./test-linuxcnc-wasm-runtime-link.sh "$manifest"
|
||||||
|
|
||||||
|
missing_tools=()
|
||||||
|
for required_tool in cmake emcmake emcc node; do
|
||||||
|
if ! command -v "$required_tool" >/dev/null 2>&1; then
|
||||||
|
missing_tools+=("$required_tool")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if ((${#missing_tools[@]} > 0)); then
|
||||||
|
echo "WASM build tools are required. Missing: ${missing_tools[*]}." >&2
|
||||||
|
echo "Install/activate cmake, emsdk, and Node.js so cmake, emcmake, emcc, and node are in PATH." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
emcmake cmake -S core -B build/wasm -DCMAKE_BUILD_TYPE=Release
|
wasm_build_signature=build/wasm/wasm-build.signature
|
||||||
cmake --build build/wasm
|
wasm_build_next_signature=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_build.signature.XXXXXX")
|
||||||
|
{
|
||||||
|
printf 'CXX=%s\n' "${CXX:-g++}"
|
||||||
|
printf 'PWD=%s\n' "$PWD"
|
||||||
|
printf 'LINUXCNC_ROOT=%s\n' "$linuxcnc_root"
|
||||||
|
printf 'MANIFEST=%s\n' "$manifest"
|
||||||
|
printf 'MANIFEST_HASH='
|
||||||
|
sha256sum "$manifest"
|
||||||
|
printf 'COMPILER_LAUNCHER=%s\n' "$cmake_compiler_launcher_mode"
|
||||||
|
printf 'CMAKE_LISTS='
|
||||||
|
sha256sum core/CMakeLists.txt
|
||||||
|
printf 'CONFIGURE_RULE_VERSION=2\n'
|
||||||
|
} > "$wasm_build_next_signature"
|
||||||
|
configure_wasm=1
|
||||||
|
if [[ ! -f "$wasm_build_signature" ]] || ! cmp -s "$wasm_build_signature" "$wasm_build_next_signature"; then
|
||||||
|
mkdir -p build/wasm
|
||||||
|
elif [[ -f build/wasm/CMakeCache.txt ]]; then
|
||||||
|
configure_wasm=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$configure_wasm" == "1" ]]; then
|
||||||
|
emcmake cmake -S core -B build/wasm \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DCNC_SIM_LINUXCNC_ROOT="$linuxcnc_root" \
|
||||||
|
-DCNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST="$manifest" \
|
||||||
|
-DCNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE=ON \
|
||||||
|
-DCNC_SIM_ENABLE_SMOKE_BACKEND=OFF \
|
||||||
|
"${cmake_compiler_launcher_args[@]}"
|
||||||
|
fi
|
||||||
|
mv "$wasm_build_next_signature" "$wasm_build_signature"
|
||||||
|
cmake --build build/wasm --target cnc_sim_wasm_runtime_probe cnc_sim_wasm --parallel "$build_jobs"
|
||||||
mkdir -p web/public
|
mkdir -p web/public
|
||||||
cp build/wasm/cnc_sim.js web/public/
|
cp build/wasm/cnc_sim.js web/public/cnc_sim.js
|
||||||
cp build/wasm/cnc_sim.wasm web/public/
|
cp build/wasm/cnc_sim.wasm web/public/cnc_sim.wasm
|
||||||
|
cmp -s build/wasm/cnc_sim.js web/public/cnc_sim.js
|
||||||
|
cmp -s build/wasm/cnc_sim.wasm web/public/cnc_sim.wasm
|
||||||
|
./test-web-wasm-node-smoke.sh
|
||||||
|
./test-web-wasm-browser-smoke.sh
|
||||||
|
|||||||
130
check-linuxcnc-browser-app-source-map.sh
Executable file
130
check-linuxcnc-browser-app-source-map.sh
Executable file
@@ -0,0 +1,130 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: this guard ties the browser app entry point to
|
||||||
|
# LinuxCNC RS274 parameter-file defaults, rs274ngc_pre.cc restore/save/read
|
||||||
|
# file semantics, and the existing OPFS-backed wasm-core bridge. It validates
|
||||||
|
# app integration policy only; it does not add CNC behavior or expand smoke
|
||||||
|
# parsing, or interpret G-code.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
grep -F '#define RS274NGC_PARAMETER_FILE_NAME_DEFAULT "rs274ngc.var"' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_internal.hh" >/dev/null
|
||||||
|
grep -F '#define RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX ".bak"' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_internal.hh" >/dev/null
|
||||||
|
grep -F 'int Interp::restore_parameters(const char *filename)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'int Interp::save_parameters(const char *filename,' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'std::string tempfile = std::string(filename) + ".new";' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F '+ RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX;' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'unlink(bakfile.c_str());' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'if(link(filename, bakfile.c_str()) < 0)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'if(rename(tempfile.c_str(), filename) < 0)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'read_text(command, _setup.file_pointer, _setup.linetext,' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC browser app source map' docs/linuxcnc-browser-app-source-map.md >/dev/null
|
||||||
|
grep -F 'must not add CNC behavior' docs/linuxcnc-browser-app-source-map.md >/dev/null
|
||||||
|
grep -F 'must not expand the temporary smoke parser' docs/linuxcnc-browser-app-source-map.md >/dev/null
|
||||||
|
grep -F '`RS274NGC_PARAMETER_FILE_NAME_DEFAULT` as `rs274ngc.var`' \
|
||||||
|
docs/linuxcnc-browser-app-source-map.md >/dev/null
|
||||||
|
grep -F '`parseFileWithParameterFile(programPath, parameterPath, "linuxcnc", ...)`' \
|
||||||
|
docs/linuxcnc-browser-app-source-map.md >/dev/null
|
||||||
|
grep -F 'orders parameter saves as backup unlink' \
|
||||||
|
docs/linuxcnc-browser-app-source-map.md >/dev/null
|
||||||
|
|
||||||
|
grep -F '<script type="module" src="/src/app.js"></script>' web/index.html >/dev/null
|
||||||
|
grep -F '<option value="linuxcnc-rs274">LINUXCNC</option>' web/index.html >/dev/null
|
||||||
|
if [[ "$(grep -Fc '<option value=' web/index.html)" -ne 1 ]]; then
|
||||||
|
echo "browser app backend selector must expose only the LinuxCNC RS274 backend" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
grep -F 'import { createWasmSimulator } from "./wasm-core.js";' web/src/app.js >/dev/null
|
||||||
|
grep -F 'const programPath = "programs/current.ngc";' web/src/app.js >/dev/null
|
||||||
|
grep -F 'const linuxCncParameterFileName = "rs274ngc.var";' web/src/app.js >/dev/null
|
||||||
|
grep -F 'const parameterPath = `parameters/${linuxCncParameterFileName}`;' web/src/app.js >/dev/null
|
||||||
|
grep -F 'const linuxCncBackend = "linuxcnc-rs274";' web/src/app.js >/dev/null
|
||||||
|
grep -F 'const opfsOptions = { required: true, mountPoint: "/cnc", workspacePath: "cnc-simulator" };' \
|
||||||
|
web/src/app.js >/dev/null
|
||||||
|
grep -F 'simulatorPromise = createWasmSimulator({' web/src/app.js >/dev/null
|
||||||
|
grep -F 'opfs: opfsOptions,' web/src/app.js >/dev/null
|
||||||
|
grep -F 'OPFS workspace is required for browser program parsing' web/src/app.js >/dev/null
|
||||||
|
grep -F 'await simulator.fs.opfs.writeFile(programPath, elements.input.value);' web/src/app.js >/dev/null
|
||||||
|
grep -F 'const events = await simulator.parseFileWithParameterFile(programPath, parameterPath, "linuxcnc", parseOptions);' \
|
||||||
|
web/src/app.js >/dev/null
|
||||||
|
grep -F 'elements.backendSelect.value = linuxCncBackend;' web/src/app.js >/dev/null
|
||||||
|
grep -F 'globalThis.__cncSimulatorForTest = simulatorPromise;' web/src/app.js >/dev/null
|
||||||
|
|
||||||
|
grep -F 'app frame did not persist current program into OPFS' \
|
||||||
|
web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
||||||
|
grep -F 'app frame did not persist LinuxCNC parameter state into OPFS' \
|
||||||
|
web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
||||||
|
grep -F 'app frame did not persist LinuxCNC parameter backup into OPFS' \
|
||||||
|
web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
||||||
|
grep -F 'app frame did not clean up LinuxCNC temporary parameter file in OPFS' \
|
||||||
|
web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
||||||
|
grep -F 'OPFS PROGRAM RESTORED' web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
||||||
|
grep -F 'app frame did not reload LinuxCNC parameter state from OPFS after reload' \
|
||||||
|
web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
||||||
|
grep -F 'runSection("browser app opfs save"' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'runSection("browser app opfs restore"' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
|
||||||
|
if grep -R -n -E 'localStorage|sessionStorage|indexedDB|showOpenFilePicker|showSaveFilePicker|showDirectoryPicker|webkitRequestFileSystem|FileReader' web/src; then
|
||||||
|
echo "browser app/wasm code must not add filesystem persistence outside OPFS" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
python3 - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
source_map = Path("docs/linuxcnc-browser-app-source-map.md").read_text(encoding="utf-8")
|
||||||
|
for entry in [
|
||||||
|
"web/index.html",
|
||||||
|
"web/src/app.js",
|
||||||
|
"web/test-browser-wasm-smoke-app-sections.js",
|
||||||
|
]:
|
||||||
|
if f"| `{entry}` |" not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-browser-app-source-map.md missing app entry: {entry}")
|
||||||
|
|
||||||
|
for phrase in [
|
||||||
|
"must not add CNC behavior",
|
||||||
|
"must not expand the temporary smoke parser",
|
||||||
|
"existing `createWasmSimulator()` OPFS API",
|
||||||
|
"programs/current.ngc",
|
||||||
|
"parameters/rs274ngc.var",
|
||||||
|
"visible backend selector must stay limited",
|
||||||
|
"./check-linuxcnc-browser-app-source-map.sh",
|
||||||
|
"does not interpret G-code",
|
||||||
|
]:
|
||||||
|
if phrase not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-browser-app-source-map.md missing boundary phrase: {phrase}")
|
||||||
|
|
||||||
|
for entry in [
|
||||||
|
"test-native.sh",
|
||||||
|
"test-linuxcnc-source-link.sh",
|
||||||
|
"build-wasm.sh",
|
||||||
|
]:
|
||||||
|
text = Path(entry).read_text(encoding="utf-8")
|
||||||
|
if "./check-linuxcnc-browser-app-source-map.sh" not in text:
|
||||||
|
raise SystemExit(f"{entry} must run ./check-linuxcnc-browser-app-source-map.sh")
|
||||||
|
|
||||||
|
app = Path("web/src/app.js").read_text(encoding="utf-8")
|
||||||
|
if "parse(" in app.replace("parseProgram", ""):
|
||||||
|
raise SystemExit("browser app should route program execution through parseFileWithParameterFile, not direct parse")
|
||||||
|
if app.count("elements.backendSelect.value = linuxCncBackend;") != 2:
|
||||||
|
raise SystemExit("browser app backend selector must only be forced to the LinuxCNC backend")
|
||||||
|
if "backendSelect.value" in app.replace("elements.backendSelect.value = linuxCncBackend;", ""):
|
||||||
|
raise SystemExit("browser app must not read the backend selector as a dynamic backend source")
|
||||||
|
if 'backend: linuxCncBackend' not in app:
|
||||||
|
raise SystemExit("browser app parse options must force the LinuxCNC backend")
|
||||||
|
PY
|
||||||
202
check-linuxcnc-build-source-map.sh
Executable file
202
check-linuxcnc-build-source-map.sh
Executable file
@@ -0,0 +1,202 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: this guard ties native/source-link/WASM build entry
|
||||||
|
# points to LinuxCNC Submakefile source ownership, source manifests, persistent
|
||||||
|
# build signatures, and source-backed WASM artifact ordering. It validates
|
||||||
|
# build policy only; it does not add CNC behavior, expand smoke parsing, or
|
||||||
|
# interpret G-code.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
grep -F 'LIBRS274SRCS := $(addprefix emc/rs274ngc/,' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/Submakefile" >/dev/null
|
||||||
|
grep -F 'rs274ngc_pre.cc \' "$linuxcnc_root/src/emc/rs274ngc/Submakefile" >/dev/null
|
||||||
|
grep -F '../lib/libtooldata.so.0' "$linuxcnc_root/src/emc/rs274ngc/Submakefile" >/dev/null
|
||||||
|
grep -F 'LIBTOOLDATA_SRCS += emc/tooldata/tooldata_common.cc' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/Submakefile" >/dev/null
|
||||||
|
grep -F 'LIBTOOLDATA_SRCS += emc/tooldata/tooldata_mmap.cc' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/Submakefile" >/dev/null
|
||||||
|
grep -F 'LIBTOOLDATA_SRCS += emc/tooldata/tooldata_db.cc' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/Submakefile" >/dev/null
|
||||||
|
grep -F 'LIBLCNCINISRCS := emc/ini/inifile.cc' \
|
||||||
|
"$linuxcnc_root/src/emc/ini/Submakefile" >/dev/null
|
||||||
|
grep -F 'LIBPPSRCS := $(addprefix emc/pythonplugin/,' \
|
||||||
|
"$linuxcnc_root/src/emc/pythonplugin/Submakefile" >/dev/null
|
||||||
|
grep -F 'GENSERKINSSRCS := emc/kinematics/ugenserkins.c' \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics/Submakefile" >/dev/null
|
||||||
|
grep -F 'extern int kinematicsInverse(const struct EmcPose * world,' \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics/kinematics.h" >/dev/null
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC build source map' docs/linuxcnc-build-source-map.md >/dev/null
|
||||||
|
grep -F 'must not add CNC' docs/linuxcnc-build-source-map.md >/dev/null
|
||||||
|
grep -F 'must not expand the temporary smoke parser' docs/linuxcnc-build-source-map.md >/dev/null
|
||||||
|
grep -F '`src/emc/rs274ngc/Submakefile` defines `LIBRS274SRCS`' \
|
||||||
|
docs/linuxcnc-build-source-map.md >/dev/null
|
||||||
|
grep -F '`src/emc/tooldata/Submakefile` defines the LinuxCNC tooldata' \
|
||||||
|
docs/linuxcnc-build-source-map.md >/dev/null
|
||||||
|
grep -F 'Default WASM manifest partition must remain 26 wasm-safe `core` sources and' \
|
||||||
|
docs/linuxcnc-build-source-map.md >/dev/null
|
||||||
|
grep -F '`build-wasm.sh` must configure with `CNC_SIM_ENABLE_SMOKE_BACKEND=OFF`' \
|
||||||
|
docs/linuxcnc-build-source-map.md >/dev/null
|
||||||
|
grep -F '`test-native.sh`, `test-linuxcnc-source-link.sh`, and `build-wasm.sh` must' \
|
||||||
|
docs/linuxcnc-build-source-map.md >/dev/null
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC source basis: the wasm build preflights and compiles the' build-wasm.sh >/dev/null
|
||||||
|
source_map_guards=(
|
||||||
|
'./check-linuxcnc-rs274-source-map.sh'
|
||||||
|
'./check-linuxcnc-kinematics-source-map.sh'
|
||||||
|
'./check-linuxcnc-opfs-source-map.sh'
|
||||||
|
'./check-linuxcnc-switchkins-remap-source-map.sh'
|
||||||
|
'./check-linuxcnc-wasm-smoke-source-map.sh'
|
||||||
|
'./check-linuxcnc-build-source-map.sh'
|
||||||
|
'./check-linuxcnc-browser-app-source-map.sh'
|
||||||
|
'./check-linuxcnc-workstreams-source-map.sh'
|
||||||
|
'./check-linuxcnc-tooldata-source-map.sh'
|
||||||
|
'./check-linuxcnc-wasm-shims-source-map.sh'
|
||||||
|
'./check-linuxcnc-wasm-blockers-source-map.sh'
|
||||||
|
)
|
||||||
|
for guarded_entry in test-native.sh test-linuxcnc-source-link.sh build-wasm.sh; do
|
||||||
|
for source_map_guard in "${source_map_guards[@]}"; do
|
||||||
|
grep -F "$source_map_guard" "$guarded_entry" >/dev/null
|
||||||
|
done
|
||||||
|
done
|
||||||
|
grep -F 'manifest_core_count=$(count_nonempty_lines "$manifest_core_output")' build-wasm.sh >/dev/null
|
||||||
|
grep -F 'manifest_blocked_count=$(count_nonempty_lines "$manifest_blocked_output")' build-wasm.sh >/dev/null
|
||||||
|
grep -F 'manifest_core_count" -ne 26 || "$manifest_blocked_count" -ne 9' build-wasm.sh >/dev/null
|
||||||
|
grep -F 'run_parallel_wasm_probe "LinuxCNC wasm tooldata shim link probe" ./test-linuxcnc-wasm-tooldata-link.sh' build-wasm.sh >/dev/null
|
||||||
|
grep -F 'run_parallel_wasm_probe "LinuxCNC wasm rs274ngc_pre object probe" ./test-linuxcnc-wasm-rs274ngc-pre-object.sh' build-wasm.sh >/dev/null
|
||||||
|
grep -F 'wait_parallel_wasm_probes' build-wasm.sh >/dev/null
|
||||||
|
grep -F 'for required_tool in cmake emcmake emcc node; do' build-wasm.sh >/dev/null
|
||||||
|
grep -F 'CONFIGURE_RULE_VERSION=2' build-wasm.sh >/dev/null
|
||||||
|
grep -F -- '-DCNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE=ON' build-wasm.sh >/dev/null
|
||||||
|
grep -F -- '-DCNC_SIM_ENABLE_SMOKE_BACKEND=OFF' build-wasm.sh >/dev/null
|
||||||
|
grep -F 'cmake --build build/wasm --target cnc_sim_wasm_runtime_probe cnc_sim_wasm --parallel "$build_jobs"' build-wasm.sh >/dev/null
|
||||||
|
grep -F 'cmp -s build/wasm/cnc_sim.js web/public/cnc_sim.js' build-wasm.sh >/dev/null
|
||||||
|
grep -F 'cmp -s build/wasm/cnc_sim.wasm web/public/cnc_sim.wasm' build-wasm.sh >/dev/null
|
||||||
|
grep -F './test-web-wasm-node-smoke.sh' build-wasm.sh >/dev/null
|
||||||
|
grep -F './test-web-wasm-browser-smoke.sh' build-wasm.sh >/dev/null
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC source basis: this source-link test compiles the manifest-selected' \
|
||||||
|
test-linuxcnc-source-link.sh >/dev/null
|
||||||
|
grep -F 'BUILD_RULE_VERSION=1' test-linuxcnc-source-link.sh >/dev/null
|
||||||
|
grep -F 'make --output-sync=target -j"$build_jobs" -f "$source_link_makefile"' \
|
||||||
|
test-linuxcnc-source-link.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: this syntax probe checks the native RS274 manifest' \
|
||||||
|
test-linuxcnc-source-syntax.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: the wasm syntax probe compiles the' \
|
||||||
|
test-linuxcnc-wasm-source-syntax.sh >/dev/null
|
||||||
|
grep -F "printf 'CONFIGURE_RULE_VERSION=1\n'" \
|
||||||
|
test-linuxcnc-wasm-cmake-safe-probe.sh >/dev/null
|
||||||
|
grep -F 'cmake --build "$build_dir" --target linuxcnc_rs274_wasm_safe_probe cnc_sim_wasm_runtime_probe --parallel "$build_jobs"' \
|
||||||
|
test-linuxcnc-wasm-cmake-safe-probe.sh >/dev/null
|
||||||
|
|
||||||
|
if grep -F 'printf '\''BUILD_JOBS=%s\n'\'' "$build_jobs"' build-wasm.sh >/dev/null; then
|
||||||
|
echo "build-wasm configure signature must not depend on CNC_SIM_BUILD_JOBS" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
for hot_signature_script in \
|
||||||
|
build-linuxcnc-wasm-link-probe.sh \
|
||||||
|
build-linuxcnc-wasm-probe-objects.sh \
|
||||||
|
build-linuxcnc-wasm-standalone-probe.sh \
|
||||||
|
build-linuxcnc-native-bridge-objects.sh \
|
||||||
|
test-linuxcnc-api-native.sh \
|
||||||
|
test-linuxcnc-bridge-native.sh \
|
||||||
|
test-linuxcnc-rs274-native.sh \
|
||||||
|
test-linuxcnc-source-link.sh \
|
||||||
|
test-linuxcnc-source-objects.sh \
|
||||||
|
test-linuxcnc-source-syntax.sh \
|
||||||
|
test-native.sh; do
|
||||||
|
if grep -F "sha256sum $hot_signature_script" "$hot_signature_script" >/dev/null; then
|
||||||
|
echo "$hot_signature_script hot object signature must use BUILD_RULE_VERSION instead of the whole script hash" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
python3 - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
source_map = Path("docs/linuxcnc-build-source-map.md").read_text(encoding="utf-8")
|
||||||
|
wasm_manifest = Path("linuxcnc-rs274-wasm-source-files.txt")
|
||||||
|
core_count = len(subprocess.check_output(
|
||||||
|
["./list-linuxcnc-wasm-manifest-sources.sh", str(wasm_manifest), "core"],
|
||||||
|
text=True,
|
||||||
|
).splitlines())
|
||||||
|
blocked_count = len(subprocess.check_output(
|
||||||
|
["./list-linuxcnc-wasm-manifest-sources.sh", str(wasm_manifest), "blocked"],
|
||||||
|
text=True,
|
||||||
|
).splitlines())
|
||||||
|
if core_count != 26 or blocked_count != 9:
|
||||||
|
raise SystemExit(f"unexpected default WASM manifest partition: core={core_count} blocked={blocked_count}")
|
||||||
|
|
||||||
|
for entry in [
|
||||||
|
"test-native.sh",
|
||||||
|
"test-linuxcnc-source-link.sh",
|
||||||
|
"test-linuxcnc-source-syntax.sh",
|
||||||
|
"test-linuxcnc-wasm-cmake-safe-probe.sh",
|
||||||
|
"build-wasm.sh",
|
||||||
|
]:
|
||||||
|
if f"| `{entry}` |" not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-build-source-map.md missing build entry: {entry}")
|
||||||
|
|
||||||
|
for phrase in [
|
||||||
|
"must not add CNC",
|
||||||
|
"must not expand the temporary smoke parser",
|
||||||
|
"CNC_SIM_BUILD_JOBS",
|
||||||
|
"BUILD_RULE_VERSION",
|
||||||
|
"CONFIGURE_RULE_VERSION",
|
||||||
|
"CNC_SIM_ENABLE_SMOKE_BACKEND=OFF",
|
||||||
|
"Node smoke before browser smoke",
|
||||||
|
"does not interpret",
|
||||||
|
"G-code",
|
||||||
|
]:
|
||||||
|
if phrase not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-build-source-map.md missing boundary phrase: {phrase}")
|
||||||
|
|
||||||
|
build_wasm = Path("build-wasm.sh").read_text(encoding="utf-8").splitlines()
|
||||||
|
positions = {}
|
||||||
|
for index, line in enumerate(build_wasm, start=1):
|
||||||
|
if 'run_parallel_wasm_probe "LinuxCNC wasm tooldata shim link probe"' in line:
|
||||||
|
positions["parallel_start"] = index
|
||||||
|
if "wait_parallel_wasm_probes" in line and "parallel_start" in positions and "wait" not in positions:
|
||||||
|
positions["wait"] = index
|
||||||
|
if "LinuxCNC wasm rs274ngc_pre link blocker scan" in line:
|
||||||
|
positions["pre_link"] = index
|
||||||
|
if "for required_tool in cmake emcmake emcc node; do" in line:
|
||||||
|
positions["tools"] = index
|
||||||
|
if "emcmake cmake -S core -B build/wasm" in line:
|
||||||
|
positions["configure"] = index
|
||||||
|
if "cmake --build build/wasm --target cnc_sim_wasm_runtime_probe cnc_sim_wasm" in line:
|
||||||
|
positions["build"] = index
|
||||||
|
if "cp build/wasm/cnc_sim.js web/public/cnc_sim.js" in line:
|
||||||
|
positions["cp_js"] = index
|
||||||
|
if "cp build/wasm/cnc_sim.wasm web/public/cnc_sim.wasm" in line:
|
||||||
|
positions["cp_wasm"] = index
|
||||||
|
if "cmp -s build/wasm/cnc_sim.js web/public/cnc_sim.js" in line:
|
||||||
|
positions["cmp_js"] = index
|
||||||
|
if "cmp -s build/wasm/cnc_sim.wasm web/public/cnc_sim.wasm" in line:
|
||||||
|
positions["cmp_wasm"] = index
|
||||||
|
if "./test-web-wasm-node-smoke.sh" in line:
|
||||||
|
positions["node"] = index
|
||||||
|
if "./test-web-wasm-browser-smoke.sh" in line:
|
||||||
|
positions["browser"] = index
|
||||||
|
|
||||||
|
required = [
|
||||||
|
"parallel_start", "wait", "pre_link", "tools", "configure", "build",
|
||||||
|
"cp_js", "cp_wasm", "cmp_js", "cmp_wasm", "node", "browser",
|
||||||
|
]
|
||||||
|
missing = [name for name in required if name not in positions]
|
||||||
|
if missing:
|
||||||
|
raise SystemExit(f"build-wasm.sh missing ordered build anchors: {', '.join(missing)}")
|
||||||
|
if not (positions["parallel_start"] < positions["wait"] < positions["pre_link"]):
|
||||||
|
raise SystemExit("build-wasm.sh must wait for parallel probes before rs274ngc_pre link checks")
|
||||||
|
if not (positions["tools"] < positions["configure"] < positions["build"]):
|
||||||
|
raise SystemExit("build-wasm.sh must check tools, then configure, then build")
|
||||||
|
if not (positions["cp_js"] < positions["cmp_js"] < positions["node"] < positions["browser"]):
|
||||||
|
raise SystemExit("build-wasm.js artifact JS copy/compare or smoke ordering changed")
|
||||||
|
if not (positions["cp_wasm"] < positions["cmp_wasm"] < positions["node"] < positions["browser"]):
|
||||||
|
raise SystemExit("build-wasm.wasm artifact copy/compare or smoke ordering changed")
|
||||||
|
PY
|
||||||
136
check-linuxcnc-inputs-cached.sh
Executable file
136
check-linuxcnc-inputs-cached.sh
Executable file
@@ -0,0 +1,136 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: the cached input checker keys check-linuxcnc-inputs.sh
|
||||||
|
# results by manifest contents and LinuxCNC source mtimes so source-backed
|
||||||
|
# rs274/kinematics coverage is not silently reused after upstream changes.
|
||||||
|
cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-}
|
||||||
|
check_args=("$@")
|
||||||
|
if [[ "${1:-}" == "--cache-dir" ]]; then
|
||||||
|
if [[ "$#" -lt 2 ]]; then
|
||||||
|
echo "missing --cache-dir value" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cache_dir=$2
|
||||||
|
shift 2
|
||||||
|
check_args=("$@")
|
||||||
|
fi
|
||||||
|
|
||||||
|
manifest=${1:-}
|
||||||
|
require_complete=${2:-}
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
|
||||||
|
if [[ -z "$cache_dir" ]]; then
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "${check_args[@]}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [[ "$cache_dir" =~ [[:space:]] ]]; then
|
||||||
|
echo "CNC_SIM_PREFLIGHT_CACHE_DIR must not contain whitespace: $cache_dir" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$cache_dir"
|
||||||
|
cache_dir=$(cd "$cache_dir" && pwd)
|
||||||
|
if [[ "$cache_dir" == "/" ]]; then
|
||||||
|
echo "CNC_SIM_PREFLIGHT_CACHE_DIR must not be the filesystem root" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
exec 8>"$cache_dir/check-linuxcnc-inputs.lock"
|
||||||
|
flock 8
|
||||||
|
|
||||||
|
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "${check_args[@]}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
manifest_key=ROOT_ONLY
|
||||||
|
manifest_path=
|
||||||
|
if [[ -n "$manifest" && "$manifest" != "--root-only" ]]; then
|
||||||
|
if [[ ! -f "$manifest" ]]; then
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "${check_args[@]}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
manifest_path=$(cd "$(dirname "$manifest")" && pwd)/$(basename "$manifest")
|
||||||
|
manifest_key=$(printf '%s' "$manifest_path" | sha256sum | awk '{ print $1 }')
|
||||||
|
fi
|
||||||
|
|
||||||
|
safe_require=${require_complete:-none}
|
||||||
|
safe_require=${safe_require//[^A-Za-z0-9_.-]/_}
|
||||||
|
args_key=$(
|
||||||
|
{
|
||||||
|
printf 'ARGS='
|
||||||
|
printf ' %q' "${check_args[@]}"
|
||||||
|
printf '\n'
|
||||||
|
} | sha256sum | awk '{ print $1 }'
|
||||||
|
)
|
||||||
|
cache_file="$cache_dir/check-linuxcnc-inputs.${manifest_key}.${safe_require}.${args_key}.signature"
|
||||||
|
next_signature=$(mktemp "$cache_file.next.XXXXXX")
|
||||||
|
|
||||||
|
write_source_stat_signature() {
|
||||||
|
local source_path
|
||||||
|
[[ -z "$manifest_path" ]] && return 0
|
||||||
|
while IFS=: read -r group path note extra; do
|
||||||
|
case "$group" in
|
||||||
|
""|\#*)
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
[[ -z "${path:-}" ]] && continue
|
||||||
|
source_path="$linuxcnc_root/$path"
|
||||||
|
if [[ ! -f "$source_path" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
stat -c 'SOURCE=%n:%s:%y' "$source_path"
|
||||||
|
done < "$manifest_path"
|
||||||
|
}
|
||||||
|
|
||||||
|
write_complete_mode_signature() {
|
||||||
|
case "$require_complete" in
|
||||||
|
--require-rs274-complete)
|
||||||
|
find "$linuxcnc_root/src/emc/rs274ngc" -maxdepth 1 -type f \
|
||||||
|
-printf 'RS274=%P:%s:%T@\n' | sort
|
||||||
|
;;
|
||||||
|
--require-kinematics-complete)
|
||||||
|
for source_dir in \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics" \
|
||||||
|
"$linuxcnc_root/src/libnml/posemath" \
|
||||||
|
"$linuxcnc_root/configs/sim"; do
|
||||||
|
[[ -d "$source_dir" ]] || return 1
|
||||||
|
find "$source_dir" -type f -printf "KIN=$source_dir/%P:%s:%T@\n" | sort
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
if ! {
|
||||||
|
printf 'CACHED_SCRIPT='
|
||||||
|
sha256sum check-linuxcnc-inputs-cached.sh
|
||||||
|
printf 'CHECK_SCRIPT='
|
||||||
|
sha256sum check-linuxcnc-inputs.sh
|
||||||
|
printf 'LINUXCNC_ROOT=%s\n' "$linuxcnc_root"
|
||||||
|
printf 'ARGS='
|
||||||
|
printf ' %q' "${check_args[@]}"
|
||||||
|
printf '\n'
|
||||||
|
if [[ -n "$manifest_path" ]]; then
|
||||||
|
printf 'MANIFEST_PATH=%s\n' "$manifest_path"
|
||||||
|
printf 'MANIFEST='
|
||||||
|
sha256sum "$manifest_path"
|
||||||
|
write_source_stat_signature
|
||||||
|
fi
|
||||||
|
write_complete_mode_signature
|
||||||
|
} > "$next_signature"; then
|
||||||
|
rm -f "$next_signature"
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "${check_args[@]}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "$cache_file" ]] && cmp -s "$cache_file" "$next_signature"; then
|
||||||
|
rm -f "$next_signature"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "${check_args[@]}"
|
||||||
|
mv "$next_signature" "$cache_file"
|
||||||
1443
check-linuxcnc-inputs.sh
Executable file
1443
check-linuxcnc-inputs.sh
Executable file
File diff suppressed because it is too large
Load Diff
97
check-linuxcnc-kinematics-source-map.sh
Executable file
97
check-linuxcnc-kinematics-source-map.sh
Executable file
@@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: this guard keeps the kinematics source map aligned
|
||||||
|
# with linuxcnc-kinematics-source-files.txt, which enumerates LinuxCNC
|
||||||
|
# kinematics, posemath, switchkins INI/HAL/remap/tooldata/assets, and adjacent
|
||||||
|
# build metadata. It validates source coverage documentation only; it does not
|
||||||
|
# add CNC behavior, expand smoke parsing, or interpret G-code.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
grep -F 'GENSERKINSSRCS := emc/kinematics/ugenserkins.c' \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics/Submakefile" >/dev/null
|
||||||
|
grep -F 'extern int kinematicsInverse(const struct EmcPose * world,' \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics/kinematics.h" >/dev/null
|
||||||
|
grep -F 'extern int kinematicsSwitch(int switchkins_type);' \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics/kinematics.h" >/dev/null
|
||||||
|
grep -F 'motion.switchkins-type' \
|
||||||
|
"$linuxcnc_root/configs/sim/axis/vismach/5axis/bridgemill/5axis.ini" >/dev/null
|
||||||
|
grep -F '#<kinstype>' \
|
||||||
|
"$linuxcnc_root/configs/sim/axis/vismach/5axis/bridgemill/remap_subs/428remap.ngc" >/dev/null
|
||||||
|
|
||||||
|
python3 - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
|
||||||
|
manifest = Path("linuxcnc-kinematics-source-files.txt").read_text(encoding="utf-8").splitlines()
|
||||||
|
source_map = Path("docs/linuxcnc-kinematics-source-map.md").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
expected_groups = [
|
||||||
|
"core",
|
||||||
|
"config",
|
||||||
|
"remap",
|
||||||
|
"component",
|
||||||
|
"generated",
|
||||||
|
"header",
|
||||||
|
"metadata",
|
||||||
|
"asset",
|
||||||
|
"tooldata",
|
||||||
|
]
|
||||||
|
counts = {group: 0 for group in expected_groups}
|
||||||
|
for line in manifest:
|
||||||
|
if not line or line.startswith("#"):
|
||||||
|
continue
|
||||||
|
group = line.split(":", 1)[0]
|
||||||
|
if group not in counts:
|
||||||
|
raise SystemExit(f"unexpected kinematics manifest group in source map guard: {group}")
|
||||||
|
counts[group] += 1
|
||||||
|
|
||||||
|
for group, count in counts.items():
|
||||||
|
pattern = rf"\| `{re.escape(group)}` \| {count} \|"
|
||||||
|
if not re.search(pattern, source_map):
|
||||||
|
raise SystemExit(
|
||||||
|
f"docs/linuxcnc-kinematics-source-map.md {group} count no longer matches linuxcnc-kinematics-source-files.txt"
|
||||||
|
)
|
||||||
|
|
||||||
|
for group in expected_groups:
|
||||||
|
if f"`{group}`" not in source_map:
|
||||||
|
raise SystemExit(
|
||||||
|
f"docs/linuxcnc-kinematics-source-map.md is missing kinematics manifest group {group}"
|
||||||
|
)
|
||||||
|
|
||||||
|
required_phrases = [
|
||||||
|
"LinuxCNC Source Anchors",
|
||||||
|
"must not add CNC behavior",
|
||||||
|
"must not",
|
||||||
|
"expand the temporary smoke parser",
|
||||||
|
"`src/emc/kinematics/Submakefile`",
|
||||||
|
"`src/emc/kinematics/kinematics.h`",
|
||||||
|
"motion.switchkins-type",
|
||||||
|
"`#<kinstype>` remap assignment",
|
||||||
|
"not browser API surface",
|
||||||
|
"OPFS-only",
|
||||||
|
"derive M428/M429/M430 cases from",
|
||||||
|
"RTCP and five-axis coverage",
|
||||||
|
"./check-linuxcnc-kinematics-source-map.sh",
|
||||||
|
"./check-linuxcnc-inputs.sh linuxcnc-kinematics-source-files.txt --require-kinematics-complete",
|
||||||
|
"./check-linuxcnc-switchkins-remap-table.sh linuxcnc-kinematics-source-files.txt",
|
||||||
|
"does not interpret G-code",
|
||||||
|
]
|
||||||
|
for phrase in required_phrases:
|
||||||
|
if phrase not in source_map:
|
||||||
|
raise SystemExit(
|
||||||
|
f"docs/linuxcnc-kinematics-source-map.md is missing source-coverage boundary phrase: {phrase}"
|
||||||
|
)
|
||||||
|
|
||||||
|
for entry in [
|
||||||
|
"test-native.sh",
|
||||||
|
"test-linuxcnc-source-link.sh",
|
||||||
|
"build-wasm.sh",
|
||||||
|
]:
|
||||||
|
text = Path(entry).read_text(encoding="utf-8")
|
||||||
|
if "./check-linuxcnc-kinematics-source-map.sh" not in text:
|
||||||
|
raise SystemExit(f"{entry} must run ./check-linuxcnc-kinematics-source-map.sh")
|
||||||
|
PY
|
||||||
182
check-linuxcnc-opfs-source-map.sh
Executable file
182
check-linuxcnc-opfs-source-map.sh
Executable file
@@ -0,0 +1,182 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: this guard ties browser OPFS parameter persistence to
|
||||||
|
# interp_internal.hh defaults and rs274ngc_pre.cc restore_parameters() /
|
||||||
|
# save_parameters() file semantics. It validates bridge policy only; it does not
|
||||||
|
# add CNC behavior, expand smoke parsing, or interpret G-code.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
grep -F '#define RS274NGC_PARAMETER_FILE_NAME_DEFAULT "rs274ngc.var"' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_internal.hh" >/dev/null
|
||||||
|
grep -F '#define RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX ".bak"' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_internal.hh" >/dev/null
|
||||||
|
grep -F 'int Interp::restore_parameters(const char *filename)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'int Interp::open(const char *filename)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F '_setup.file_pointer = fopen(filename, "r");' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'read_text(command, _setup.file_pointer, _setup.linetext,' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'int Interp::save_parameters(const char *filename,' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'std::string tempfile = std::string(filename) + ".new";' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F '+ RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX;' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'unlink(bakfile.c_str());' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'if(link(filename, bakfile.c_str()) < 0)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'if(rename(tempfile.c_str(), filename) < 0)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
|
||||||
|
grep -F 'RS274NGC_PARAMETER_FILE_NAME_DEFAULT` as `rs274ngc.var`' \
|
||||||
|
docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F 'RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX` as `.bak`' \
|
||||||
|
docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '`Interp::restore_parameters()` for parameter-file reads' \
|
||||||
|
docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '`Interp::open()` by opening' \
|
||||||
|
docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '`fopen(filename, "r")`, then `Interp::_read()`' \
|
||||||
|
docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '`read_text()`' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '`Interp::save_parameters()` for `filename + ".new"`' \
|
||||||
|
docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F 'unlinks `filename + ".bak"`, links the' \
|
||||||
|
docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F 'must not add independent filesystem behavior or expand the temporary smoke parser' \
|
||||||
|
docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F 'parseFileWithParameterFile()' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F 'OPFS Coverage' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '| `web/src/wasm-core.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '| `web/src/wasm-core.d.ts` |' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '| `web/src/app.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '| `web/test-browser-wasm-smoke-opfs-basic-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '| `web/test-browser-wasm-smoke-opfs-parameter-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '| `web/test-browser-wasm-smoke-opfs-workspace-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '| `web/test-browser-wasm-smoke-opfs-mirror-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '| `web/test-browser-wasm-smoke-opfs-directory-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '| `web/test-browser-wasm-smoke-opfs-policy-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
grep -F '| `web/test-browser-wasm-smoke-app-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null
|
||||||
|
|
||||||
|
grep -F 'const LINUXCNC_DEFAULT_PARAMETER_FILE = "rs274ngc.var";' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'async parseFile(path, dialect = "linuxcnc", options = {})' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'OPFS workspace is not available for program file parsing' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'const program = new TextDecoder().decode(await opfs.readFile(path));' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'async parseFileWithParameterFile(path, parameterPath, dialect = "linuxcnc", options = {})' \
|
||||||
|
web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'OPFS workspace is not available for program and parameter file parsing' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F '`${LINUXCNC_DEFAULT_PARAMETER_FILE}.new`' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F '`${LINUXCNC_DEFAULT_PARAMETER_FILE}.bak`' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: rs274ngc_pre.cc restore_parameters() reads the' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'before replacing the main file and managing filename + ".bak".' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'app frame did not clean up LinuxCNC temporary parameter file in OPFS' \
|
||||||
|
web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
||||||
|
grep -F 'OPFS cannot be disabled in browser contexts with OPFS support' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'OPFS path must stay inside the CNC workspace' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'OPFS mount point must stay inside the Emscripten filesystem' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'async persistDirectory(path)' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'async readDirectory(path)' web/src/wasm-core.js >/dev/null
|
||||||
|
grep -F 'export type WasmOpfsWorkspace = {' web/src/wasm-core.d.ts >/dev/null
|
||||||
|
grep -F 'readDirectory(path: string): Promise<string[]>;' web/src/wasm-core.d.ts >/dev/null
|
||||||
|
grep -F 'persistDirectory(path: string): Promise<string[]>;' web/src/wasm-core.d.ts >/dev/null
|
||||||
|
grep -F 'loadParameterFile(path: string): Promise<Uint8Array | null>;' web/src/wasm-core.d.ts >/dev/null
|
||||||
|
grep -F 'persistParameterFile(path: string): Promise<Uint8Array>;' web/src/wasm-core.d.ts >/dev/null
|
||||||
|
grep -F 'opfs?: false | {' web/src/wasm-core.d.ts >/dev/null
|
||||||
|
grep -F 'mountPoint?: string;' web/src/wasm-core.d.ts >/dev/null
|
||||||
|
grep -F 'workspacePath?: string;' web/src/wasm-core.d.ts >/dev/null
|
||||||
|
grep -F 'const events = await simulator.parseFileWithParameterFile(programPath, parameterPath, "linuxcnc", parseOptions);' \
|
||||||
|
web/src/app.js >/dev/null
|
||||||
|
grep -F 'OPFS workspace is required for browser program parsing' web/src/app.js >/dev/null
|
||||||
|
grep -F 'runBrowserOpfsBasicSections(context, simulator)' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null
|
||||||
|
grep -F 'runBrowserOpfsParameterSections(context, simulator)' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null
|
||||||
|
grep -F 'runBrowserOpfsMirrorSections(context, simulator)' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null
|
||||||
|
grep -F 'runBrowserOpfsDirectorySections(context, simulator)' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null
|
||||||
|
grep -F 'runBrowserOpfsPolicySections(context)' web/test-browser-wasm-smoke-sections.js >/dev/null
|
||||||
|
grep -F 'runSection("opfs directory persist and load"' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-directory-sections.js >/dev/null
|
||||||
|
grep -F 'runSection("opfs metadata queries avoid wasm mirror pollution"' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-directory-sections.js >/dev/null
|
||||||
|
grep -F 'runSection("opfs copy and move mirror files"' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-mirror-sections.js >/dev/null
|
||||||
|
grep -F 'runSection("browser opfs policy"' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-policy-sections.js >/dev/null
|
||||||
|
grep -F 'runSection("opfs parameter restore in new instance"' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'runSection("opfs invalid parameter restore failures"' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'runSection("opfs stale parameter state cleanup"' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'runSection("opfs program parse and restore"' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'runSection("browser app opfs restore"' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
|
||||||
|
if grep -R -n -E 'localStorage|sessionStorage|indexedDB|showOpenFilePicker|showSaveFilePicker|showDirectoryPicker|webkitRequestFileSystem|FileReader' web/src; then
|
||||||
|
echo "browser app/wasm code must not add filesystem persistence outside OPFS" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if grep -n -E 'localStorage|sessionStorage|indexedDB|showOpenFilePicker|showSaveFilePicker|showDirectoryPicker|webkitRequestFileSystem|FileReader' \
|
||||||
|
web/test-browser-wasm-smoke-*.js \
|
||||||
|
web/test-browser-wasm-smoke.html \
|
||||||
|
test-web-wasm-browser-smoke.sh; then
|
||||||
|
echo "browser OPFS smoke harness must not add filesystem persistence outside OPFS" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
python3 - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
source_map = Path("docs/linuxcnc-opfs-source-map.md").read_text(encoding="utf-8")
|
||||||
|
coverage_entries = [
|
||||||
|
"web/src/wasm-core.js",
|
||||||
|
"web/src/wasm-core.d.ts",
|
||||||
|
"web/src/app.js",
|
||||||
|
"web/test-browser-wasm-smoke-opfs-basic-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-opfs-parameter-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-opfs-workspace-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-opfs-mirror-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-opfs-directory-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-opfs-policy-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-app-sections.js",
|
||||||
|
]
|
||||||
|
for entry in coverage_entries:
|
||||||
|
if f"| `{entry}` |" not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-opfs-source-map.md missing OPFS coverage entry: {entry}")
|
||||||
|
|
||||||
|
required_phrases = [
|
||||||
|
"programs/current.ngc",
|
||||||
|
"parameters/rs274ngc.var",
|
||||||
|
'fopen(filename, "r")',
|
||||||
|
"LinuxCNC `read_text()`",
|
||||||
|
"program reads and parameter restore/save bridge files under the OPFS workspace",
|
||||||
|
"`.new`, `.bak`, failure, and stale-state semantics",
|
||||||
|
'unlinks `filename + ".bak"`',
|
||||||
|
"OPFS/WASM mirror persistence",
|
||||||
|
"OPFS directory persistence and WASM mirror refresh",
|
||||||
|
"OPFS workspace and mount policy",
|
||||||
|
"Browser OPFS smoke harness files must also stay free of Local Storage",
|
||||||
|
"they may only verify OPFS-backed browser persistence",
|
||||||
|
"OPFS-backed workspace, directory, parameter-file, and mount/workspace option types",
|
||||||
|
"app-level OPFS program, parameter, backup, and reload behavior",
|
||||||
|
"./check-linuxcnc-opfs-source-map.sh",
|
||||||
|
"does not interpret G-code",
|
||||||
|
]
|
||||||
|
for phrase in required_phrases:
|
||||||
|
if phrase not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-opfs-source-map.md missing OPFS coverage phrase: {phrase}")
|
||||||
|
|
||||||
|
for entry in [
|
||||||
|
"test-native.sh",
|
||||||
|
"test-linuxcnc-source-link.sh",
|
||||||
|
"build-wasm.sh",
|
||||||
|
]:
|
||||||
|
text = Path(entry).read_text(encoding="utf-8")
|
||||||
|
if "./check-linuxcnc-opfs-source-map.sh" not in text:
|
||||||
|
raise SystemExit(f"{entry} must run ./check-linuxcnc-opfs-source-map.sh")
|
||||||
|
PY
|
||||||
102
check-linuxcnc-rs274-source-map.sh
Executable file
102
check-linuxcnc-rs274-source-map.sh
Executable file
@@ -0,0 +1,102 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: this guard keeps the local source map aligned with the
|
||||||
|
# LinuxCNC-root relative rs274 manifests that drive native and WASM source-link
|
||||||
|
# probes. It validates documentation/manifest drift only; it does not add CNC
|
||||||
|
# behavior, expand smoke parsing, or interpret G-code.
|
||||||
|
python3 - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
source_map = Path("docs/linuxcnc-rs274-source-map.md").read_text(encoding="utf-8")
|
||||||
|
native_manifest = Path("linuxcnc-rs274-source-files.txt").read_text(encoding="utf-8").splitlines()
|
||||||
|
wasm_manifest = Path("linuxcnc-rs274-wasm-source-files.txt").read_text(encoding="utf-8").splitlines()
|
||||||
|
|
||||||
|
expected = {
|
||||||
|
"### Interpreter core": [
|
||||||
|
Path(line.split(":", 2)[1]).name
|
||||||
|
for line in native_manifest
|
||||||
|
if line.startswith("core:")
|
||||||
|
],
|
||||||
|
"### Python binding modules": [
|
||||||
|
Path(line.split(":", 2)[1]).name
|
||||||
|
for line in native_manifest
|
||||||
|
if line.startswith("binding:")
|
||||||
|
],
|
||||||
|
"### WASM-safe source core": [
|
||||||
|
line.split(":", 2)[1]
|
||||||
|
for line in wasm_manifest
|
||||||
|
if line.startswith("core:")
|
||||||
|
],
|
||||||
|
"### WASM-blocked sources": [
|
||||||
|
line.split(":", 2)[1]
|
||||||
|
for line in wasm_manifest
|
||||||
|
if line.startswith("blocked:")
|
||||||
|
],
|
||||||
|
"### WASM-tracked headers": [
|
||||||
|
line.split(":", 2)[1]
|
||||||
|
for line in wasm_manifest
|
||||||
|
if line.startswith("header:")
|
||||||
|
],
|
||||||
|
"### WASM-blocked headers": [
|
||||||
|
line.split(":", 2)[1]
|
||||||
|
for line in wasm_manifest
|
||||||
|
if line.startswith("blocked-header:")
|
||||||
|
],
|
||||||
|
"### WASM metadata sources": [
|
||||||
|
line.split(":", 2)[1]
|
||||||
|
for line in wasm_manifest
|
||||||
|
if line.startswith("metadata:")
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
actual = {section: [] for section in expected}
|
||||||
|
active_section = None
|
||||||
|
for line in source_map.splitlines():
|
||||||
|
if line in expected:
|
||||||
|
active_section = line
|
||||||
|
continue
|
||||||
|
if active_section and line.startswith("### "):
|
||||||
|
active_section = None
|
||||||
|
if active_section and line.startswith("- `"):
|
||||||
|
actual[active_section].append(line.split("`", 2)[1])
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"### Interpreter core": "interpreter core",
|
||||||
|
"### Python binding modules": "Python binding module",
|
||||||
|
"### WASM-safe source core": "WASM-safe source core",
|
||||||
|
"### WASM-blocked sources": "WASM-blocked source",
|
||||||
|
"### WASM-tracked headers": "WASM-tracked header",
|
||||||
|
"### WASM-blocked headers": "WASM-blocked header",
|
||||||
|
"### WASM metadata sources": "WASM metadata source",
|
||||||
|
}
|
||||||
|
for section, expected_entries in expected.items():
|
||||||
|
if actual[section] != expected_entries:
|
||||||
|
raise SystemExit(
|
||||||
|
f"docs/linuxcnc-rs274-source-map.md {labels[section]} list no longer matches source manifest"
|
||||||
|
)
|
||||||
|
|
||||||
|
for phrase in [
|
||||||
|
"must not add CNC behavior",
|
||||||
|
"must not expand the temporary smoke parser",
|
||||||
|
"source coverage only",
|
||||||
|
"must not become browser API fields",
|
||||||
|
"temporary smoke parser fallback behavior",
|
||||||
|
"Browser-hostile dependencies must remain tracked blockers",
|
||||||
|
"./check-linuxcnc-rs274-source-map.sh",
|
||||||
|
"does not interpret G-code",
|
||||||
|
]:
|
||||||
|
if phrase not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-rs274-source-map.md missing boundary phrase: {phrase}")
|
||||||
|
|
||||||
|
for entry in [
|
||||||
|
"test-native.sh",
|
||||||
|
"test-linuxcnc-source-link.sh",
|
||||||
|
"build-wasm.sh",
|
||||||
|
]:
|
||||||
|
text = Path(entry).read_text(encoding="utf-8")
|
||||||
|
if "./check-linuxcnc-rs274-source-map.sh" not in text:
|
||||||
|
raise SystemExit(f"{entry} must run ./check-linuxcnc-rs274-source-map.sh")
|
||||||
|
PY
|
||||||
107
check-linuxcnc-switchkins-remap-source-map.sh
Executable file
107
check-linuxcnc-switchkins-remap-source-map.sh
Executable file
@@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: this guard ties generated switchkins/remap aliases and
|
||||||
|
# config cases to LinuxCNC configs/sim INI REMAP entries, remap_subs
|
||||||
|
# #<kinstype> assignments, and halcmd loadusr parsing sources. It validates
|
||||||
|
# generator/table policy only; it does not add CNC behavior, expand smoke
|
||||||
|
# parsing, or interpret G-code.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC source basis: generated switchkins/remap tables are extracted from' \
|
||||||
|
generate-linuxcnc-switchkins-remap-table.sh >/dev/null
|
||||||
|
grep -F 'src/hal/utils/halcmd_commands.cc do_loadusr_cmd()' \
|
||||||
|
generate-linuxcnc-switchkins-remap-table.sh >/dev/null
|
||||||
|
grep -F 'getopt("+wWin:")' generate-linuxcnc-switchkins-remap-table.sh >/dev/null
|
||||||
|
grep -F 'src/hal/utils/halcmd_completion.c lists the common -W/-Wn/-w/-iw forms' \
|
||||||
|
generate-linuxcnc-switchkins-remap-table.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC TOOL_TABLE source is not listed as tooldata' \
|
||||||
|
generate-linuxcnc-switchkins-remap-table.sh >/dev/null
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC source basis: switchkins/remap table validation derives M428/M429/M430' \
|
||||||
|
check-linuxcnc-switchkins-remap-table.sh >/dev/null
|
||||||
|
grep -F 'validate_tool_table_source_coverage_only' \
|
||||||
|
check-linuxcnc-switchkins-remap-table.sh >/dev/null
|
||||||
|
grep -F 'exposes TOOL_TABLE through switchkins API/web bridge' \
|
||||||
|
check-linuxcnc-switchkins-remap-table.sh >/dev/null
|
||||||
|
|
||||||
|
grep -F 'int do_loadusr_cmd(const char *args[])' "$linuxcnc_root/src/hal/utils/halcmd_commands.cc" >/dev/null
|
||||||
|
grep -F 'getopt(argc,' "$linuxcnc_root/src/hal/utils/halcmd_commands.cc" >/dev/null
|
||||||
|
grep -F '"+wWin:"' "$linuxcnc_root/src/hal/utils/halcmd_commands.cc" >/dev/null
|
||||||
|
grep -F -- '-Wn' "$linuxcnc_root/src/hal/utils/halcmd_completion.c" >/dev/null
|
||||||
|
|
||||||
|
python3 - "$linuxcnc_root" <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
linuxcnc_root = Path(sys.argv[1])
|
||||||
|
source_map = Path("docs/linuxcnc-switchkins-remap-source-map.md").read_text(encoding="utf-8")
|
||||||
|
table = Path("core/src/linuxcnc_switchkins_remap_table.inc").read_text(encoding="utf-8")
|
||||||
|
cpp_cases = Path("core/tests/linuxcnc_switchkins_remap_config_cases.inc").read_text(encoding="utf-8")
|
||||||
|
json_cases = json.loads(Path("web/public/linuxcnc_switchkins_remap_config_cases.json").read_text(encoding="utf-8"))
|
||||||
|
|
||||||
|
counts = {
|
||||||
|
"core/src/linuxcnc_switchkins_remap_table.inc": len(re.findall(r'^\s*\{"', table, re.M)),
|
||||||
|
"core/tests/linuxcnc_switchkins_remap_config_cases.inc": len(re.findall(r'^\s*\{"', cpp_cases, re.M)),
|
||||||
|
"web/public/linuxcnc_switchkins_remap_config_cases.json": len(json_cases),
|
||||||
|
}
|
||||||
|
for path, count in counts.items():
|
||||||
|
if f"| `{path}` | {count} |" not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-switchkins-remap-source-map.md count mismatch for {path}")
|
||||||
|
|
||||||
|
remap_sources = [
|
||||||
|
path
|
||||||
|
for path in (linuxcnc_root / "configs/sim").rglob("*remap.ngc")
|
||||||
|
if path.name in {"428remap.ngc", "429remap.ngc", "430remap.ngc"}
|
||||||
|
]
|
||||||
|
remap_ini_re = re.compile(r"REMAP\s*=\s*M(428|429|430)(?:\D|$)", re.I)
|
||||||
|
remap_inis = [
|
||||||
|
path
|
||||||
|
for path in (linuxcnc_root / "configs/sim").rglob("*.ini")
|
||||||
|
if remap_ini_re.search(path.read_text(encoding="utf-8", errors="ignore"))
|
||||||
|
]
|
||||||
|
if f"| LinuxCNC M428/M429/M430 remap sources | {len(remap_sources)} |" not in source_map:
|
||||||
|
raise SystemExit("docs/linuxcnc-switchkins-remap-source-map.md remap source count mismatch")
|
||||||
|
if f"| LinuxCNC switchkins REMAP INI sources | {len(remap_inis)} |" not in source_map:
|
||||||
|
raise SystemExit("docs/linuxcnc-switchkins-remap-source-map.md REMAP INI source count mismatch")
|
||||||
|
|
||||||
|
required_phrases = [
|
||||||
|
"must not add CNC behavior",
|
||||||
|
"must not expand the temporary smoke parser",
|
||||||
|
"`#<kinstype>` assignments",
|
||||||
|
"[EMCIO] TOOL_TABLE` entries are source coverage only",
|
||||||
|
"must not become generated switchkins aliases",
|
||||||
|
"./check-linuxcnc-switchkins-remap-source-map.sh",
|
||||||
|
"./check-linuxcnc-switchkins-remap-table.sh linuxcnc-kinematics-source-files.txt",
|
||||||
|
"does not interpret G-code",
|
||||||
|
]
|
||||||
|
for phrase in required_phrases:
|
||||||
|
if phrase not in source_map:
|
||||||
|
raise SystemExit(
|
||||||
|
f"docs/linuxcnc-switchkins-remap-source-map.md is missing boundary phrase: {phrase}"
|
||||||
|
)
|
||||||
|
|
||||||
|
for entry in [
|
||||||
|
"test-native.sh",
|
||||||
|
"test-linuxcnc-source-link.sh",
|
||||||
|
"build-wasm.sh",
|
||||||
|
]:
|
||||||
|
text = Path(entry).read_text(encoding="utf-8")
|
||||||
|
if "./check-linuxcnc-switchkins-remap-source-map.sh" not in text:
|
||||||
|
raise SystemExit(f"{entry} must run ./check-linuxcnc-switchkins-remap-source-map.sh")
|
||||||
|
|
||||||
|
case_fields = {case["field"] for case in json_cases}
|
||||||
|
source_only_field_re = re.compile(r"asset|metadata|tool|tooldata|tool_table|TOOL_TABLE", re.I)
|
||||||
|
bad_fields = [field for field in case_fields if source_only_field_re.search(field)]
|
||||||
|
if bad_fields:
|
||||||
|
raise SystemExit(f"generated switchkins config cases expose source-only fields: {bad_fields}")
|
||||||
|
api_surface_re = re.compile(r'\b(?:asset|metadata|toolData|tooldata|toolTable|tooltable|tool_table|TOOL_TABLE)\b')
|
||||||
|
for api_path in ["web/src/wasm-core.js", "web/src/index.ts", "core/include/cnc_sim_api.h"]:
|
||||||
|
if api_surface_re.search(Path(api_path).read_text(encoding="utf-8")):
|
||||||
|
raise SystemExit(f"{api_path} exposes source-only switchkins inputs through API surface")
|
||||||
|
PY
|
||||||
123
check-linuxcnc-switchkins-remap-table-cached.sh
Executable file
123
check-linuxcnc-switchkins-remap-table-cached.sh
Executable file
@@ -0,0 +1,123 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: cached switchkins/remap validation hashes the LinuxCNC
|
||||||
|
# kinematics manifest, referenced configs/remaps, generator script, and bridge
|
||||||
|
# outputs before reusing table-check results.
|
||||||
|
cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-}
|
||||||
|
check_args=("$@")
|
||||||
|
if [[ "${1:-}" == "--cache-dir" ]]; then
|
||||||
|
if [[ "$#" -lt 2 ]]; then
|
||||||
|
echo "missing --cache-dir value" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cache_dir=$2
|
||||||
|
shift 2
|
||||||
|
check_args=("$@")
|
||||||
|
fi
|
||||||
|
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
manifest=${1:-linuxcnc-kinematics-source-files.txt}
|
||||||
|
|
||||||
|
if [[ -z "$cache_dir" ]]; then
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-switchkins-remap-table.sh "${check_args[@]}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [[ "$cache_dir" =~ [[:space:]] ]]; then
|
||||||
|
echo "CNC_SIM_PREFLIGHT_CACHE_DIR must not contain whitespace: $cache_dir" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$cache_dir"
|
||||||
|
cache_dir=$(cd "$cache_dir" && pwd)
|
||||||
|
if [[ "$cache_dir" == "/" ]]; then
|
||||||
|
echo "CNC_SIM_PREFLIGHT_CACHE_DIR must not be the filesystem root" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
exec 8>"$cache_dir/check-linuxcnc-switchkins-remap-table.lock"
|
||||||
|
flock 8
|
||||||
|
|
||||||
|
if [[ ! -d "$linuxcnc_root" || ! -f "$manifest" ]]; then
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-switchkins-remap-table.sh "${check_args[@]}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
manifest_path=$(cd "$(dirname "$manifest")" && pwd)/$(basename "$manifest")
|
||||||
|
manifest_key=$(printf '%s' "$manifest_path" | sha256sum | awk '{ print $1 }')
|
||||||
|
args_key=$(
|
||||||
|
{
|
||||||
|
printf 'ARGS='
|
||||||
|
printf ' %q' "${check_args[@]}"
|
||||||
|
printf '\n'
|
||||||
|
} | sha256sum | awk '{ print $1 }'
|
||||||
|
)
|
||||||
|
cache_file="$cache_dir/check-linuxcnc-switchkins-remap-table.${manifest_key}.${args_key}.signature"
|
||||||
|
next_signature=$(mktemp "$cache_file.next.XXXXXX")
|
||||||
|
|
||||||
|
write_manifest_source_stats() {
|
||||||
|
local source_path
|
||||||
|
while IFS=: read -r group path note extra; do
|
||||||
|
case "$group" in
|
||||||
|
""|\#*)
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
[[ -z "${path:-}" ]] && continue
|
||||||
|
source_path="$linuxcnc_root/$path"
|
||||||
|
if [[ ! -f "$source_path" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
stat -c 'SOURCE=%n:%s:%y' "$source_path"
|
||||||
|
done < "$manifest_path"
|
||||||
|
}
|
||||||
|
|
||||||
|
write_project_output_hashes() {
|
||||||
|
local project_output
|
||||||
|
for project_output in \
|
||||||
|
core/src/cnc_sim_api.cpp \
|
||||||
|
core/src/linuxcnc_switchkins_remap_table.inc \
|
||||||
|
core/tests/linuxcnc_switchkins_remap_config_cases.inc \
|
||||||
|
web/public/linuxcnc_switchkins_remap_config_cases.json \
|
||||||
|
web/src/index.ts \
|
||||||
|
web/src/wasm-core.js; do
|
||||||
|
[[ -f "$project_output" ]] || return 1
|
||||||
|
sha256sum "$project_output"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
if ! {
|
||||||
|
printf 'CACHED_SCRIPT='
|
||||||
|
sha256sum check-linuxcnc-switchkins-remap-table-cached.sh
|
||||||
|
printf 'CHECK_SCRIPT='
|
||||||
|
sha256sum check-linuxcnc-switchkins-remap-table.sh
|
||||||
|
printf 'INPUT_CACHED_SCRIPT='
|
||||||
|
sha256sum check-linuxcnc-inputs-cached.sh
|
||||||
|
printf 'INPUT_CHECK_SCRIPT='
|
||||||
|
sha256sum check-linuxcnc-inputs.sh
|
||||||
|
printf 'GENERATOR_SCRIPT='
|
||||||
|
sha256sum generate-linuxcnc-switchkins-remap-table.sh
|
||||||
|
printf 'LINUXCNC_ROOT=%s\n' "$linuxcnc_root"
|
||||||
|
printf 'ARGS='
|
||||||
|
printf ' %q' "${check_args[@]}"
|
||||||
|
printf '\n'
|
||||||
|
printf 'MANIFEST_PATH=%s\n' "$manifest_path"
|
||||||
|
printf 'MANIFEST='
|
||||||
|
sha256sum "$manifest_path"
|
||||||
|
write_manifest_source_stats
|
||||||
|
printf 'PROJECT_OUTPUTS:\n'
|
||||||
|
write_project_output_hashes
|
||||||
|
} > "$next_signature"; then
|
||||||
|
rm -f "$next_signature"
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-switchkins-remap-table.sh "${check_args[@]}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "$cache_file" ]] && cmp -s "$cache_file" "$next_signature"; then
|
||||||
|
rm -f "$next_signature"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-switchkins-remap-table.sh "${check_args[@]}"
|
||||||
|
mv "$next_signature" "$cache_file"
|
||||||
3080
check-linuxcnc-switchkins-remap-table.sh
Executable file
3080
check-linuxcnc-switchkins-remap-table.sh
Executable file
File diff suppressed because it is too large
Load Diff
333
check-linuxcnc-tooldata-source-map.sh
Executable file
333
check-linuxcnc-tooldata-source-map.sh
Executable file
@@ -0,0 +1,333 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: this guard ties LinuxCNC tooldata/Submakefile,
|
||||||
|
# src/emc/tooldata sources, native/WASM manifests, and wasm-safe tooldata shims
|
||||||
|
# to the tooldata source map. It validates source coverage only; it does not
|
||||||
|
# add CNC behavior, expand smoke parsing, or interpret G-code.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
grep -F 'LIBTOOLDATA_SRCS += emc/tooldata/tooldata_nml.cc' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/Submakefile" >/dev/null
|
||||||
|
grep -F 'LIBTOOLDATA_SRCS += emc/tooldata/tooldata_mmap.cc' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/Submakefile" >/dev/null
|
||||||
|
grep -F 'LIBTOOLDATA_SRCS += emc/tooldata/tooldata_common.cc' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/Submakefile" >/dev/null
|
||||||
|
grep -F 'LIBTOOLDATA_SRCS += emc/tooldata/tooldata_db.cc' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/Submakefile" >/dev/null
|
||||||
|
grep -F 'TOOL_MMAP_READ_SRCS = emc/tooldata/tool_mmap_read.cc' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/Submakefile" >/dev/null
|
||||||
|
grep -F 'TOOL_WATCH_SRCS = emc/tooldata/tool_watch.cc' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/Submakefile" >/dev/null
|
||||||
|
grep -F 'int main (int argc,char**argv)' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tool_mmap_read.cc" >/dev/null
|
||||||
|
grep -F 'if (tool_mmap_user())' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tool_mmap_read.cc" >/dev/null
|
||||||
|
grep -F 'idx_last = tooldata_last_index_get();' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tool_mmap_read.cc" >/dev/null
|
||||||
|
grep -F 'if (tooldata_get(&tdata,idx) != IDX_OK)' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tool_mmap_read.cc" >/dev/null
|
||||||
|
grep -F 'RCS_STAT_CHANNEL *stat = 0;' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tool_watch.cc" >/dev/null
|
||||||
|
grep -F 'stat = new RCS_STAT_CHANNEL(emcFormat, "emcStatus", "xemc", nmlfile);' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tool_watch.cc" >/dev/null
|
||||||
|
grep -F 'EMC_STAT *emcStatus = static_cast<EMC_STAT*>(stat->get_address());' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tool_watch.cc" >/dev/null
|
||||||
|
grep -F 'emcStatus->io.tool.pocketPrepped' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tool_watch.cc" >/dev/null
|
||||||
|
grep -F '#define TOOL_MMAP_FILENAME ".tool.mmap"' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'bool tool_mmap_is_random_toolchanger(void)' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'ans = hptr->is_random_toolchanger;' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'int tool_mmap_creator(EMC_TOOL_STAT const * ptr,int random_toolchanger)' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'static int inited=0;' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'if (inited) {' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'inited = 1;' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'hptr->is_random_toolchanger = random_toolchanger;' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'hptr->last_index = 0;' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'int tool_mmap_user()' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'fprintf(stderr,"tool_mmap_user(): tool mmap not available\n");' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'return(-1);' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'void tool_mmap_close()' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'if (!tool_mmap_base) { return; }' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'int tooldata_last_index_get(void)' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'tool_mmap_mutex_give(); return -1;' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'int tooldata_find_index_for_tool(int toolno)' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'if (toolno == -1) {tool_mmap_mutex_give(); return -1;}' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'if (!hptr->is_random_toolchanger && toolno == 0)' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'int tool_nml_register(CANON_TOOL_TABLE *tblptr)' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_nml.cc" >/dev/null
|
||||||
|
grep -F 'int tooldata_db_init(char progname_plus_args[]' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_db.cc" >/dev/null
|
||||||
|
grep -F '#define MAX_DB_PROGRAM_ARGS 10' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_db.cc" >/dev/null
|
||||||
|
grep -F 'char* token = strtok_r(progname_plus_args, " ", &saveptr);' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_db.cc" >/dev/null
|
||||||
|
grep -F 'if (child_argc >= MAX_DB_PROGRAM_ARGS)' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_db.cc" >/dev/null
|
||||||
|
grep -F 'if (access(child_argv[0],X_OK))' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_db.cc" >/dev/null
|
||||||
|
grep -F 'int tooldata_db_getall() {' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_db.cc" >/dev/null
|
||||||
|
grep -F 'if (!db_live) {return -1;}' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_db.cc" >/dev/null
|
||||||
|
grep -F 'int tooldata_db_notify(tool_notify_t ntype,' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_db.cc" >/dev/null
|
||||||
|
grep -F 'if (!db_live) return 0;' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_db.cc" >/dev/null
|
||||||
|
grep -F 'int tooldata_read_entry(const char *input_line)' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/tooldata_common.cc" >/dev/null
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC tooldata source map' docs/linuxcnc-tooldata-source-map.md >/dev/null
|
||||||
|
grep -F 'must not add CNC behavior' docs/linuxcnc-tooldata-source-map.md >/dev/null
|
||||||
|
grep -F 'must not expand the temporary smoke parser' docs/linuxcnc-tooldata-source-map.md >/dev/null
|
||||||
|
grep -F '`src/emc/tooldata/Submakefile` selects `tooldata_mmap.cc`' \
|
||||||
|
docs/linuxcnc-tooldata-source-map.md >/dev/null
|
||||||
|
grep -F 'Tool table files referenced by switchkins INI files are source coverage only' \
|
||||||
|
docs/linuxcnc-tooldata-source-map.md >/dev/null
|
||||||
|
grep -F '`src/emc/tooldata/tool_mmap_read.cc` is the mmap tool table reader utility' \
|
||||||
|
docs/linuxcnc-tooldata-source-map.md >/dev/null
|
||||||
|
grep -F '`tool_mmap_user()`, `tooldata_last_index_get()`, and `tooldata_get()`' \
|
||||||
|
docs/linuxcnc-tooldata-source-map.md >/dev/null
|
||||||
|
grep -F "single-creator process boundary from" docs/linuxcnc-tooldata-source-map.md >/dev/null
|
||||||
|
grep -F "including after" docs/linuxcnc-tooldata-source-map.md >/dev/null
|
||||||
|
grep -F '`src/emc/tooldata/tool_watch.cc` is the NML/mmap tool table watcher utility' \
|
||||||
|
docs/linuxcnc-tooldata-source-map.md >/dev/null
|
||||||
|
grep -F '`EMC_STAT::io.tool` fields through `RCS_STAT_CHANNEL`' \
|
||||||
|
docs/linuxcnc-tooldata-source-map.md >/dev/null
|
||||||
|
|
||||||
|
grep -F 'tooldata:src/emc/tooldata/tooldata_common.cc:shared tool table parser/format logic' \
|
||||||
|
linuxcnc-rs274-source-files.txt >/dev/null
|
||||||
|
grep -F 'tooldata:src/emc/tooldata/tooldata_mmap.cc:native mmap implementation; replace for wasm' \
|
||||||
|
linuxcnc-rs274-source-files.txt >/dev/null
|
||||||
|
grep -F 'tooldata:src/emc/tooldata/tooldata_db.cc:external database integration; exclude from wasm core' \
|
||||||
|
linuxcnc-rs274-source-files.txt >/dev/null
|
||||||
|
grep -F 'tooldata:src/emc/tooldata/tooldata_nml.cc:NML tool table backend selected by LinuxCNC TOOL_NML_FLAG' \
|
||||||
|
linuxcnc-rs274-source-files.txt >/dev/null
|
||||||
|
grep -F 'header:src/emc/tooldata/tooldata.hh:LinuxCNC tooldata declarations used by RS274 and wasm-safe tooldata shims' \
|
||||||
|
linuxcnc-rs274-source-files.txt >/dev/null
|
||||||
|
grep -F 'metadata:src/emc/tooldata/Submakefile:LinuxCNC tooldata build metadata defining mmap and NML backend source selection' \
|
||||||
|
linuxcnc-rs274-source-files.txt >/dev/null
|
||||||
|
grep -F 'core:src/emc/tooldata/tooldata_common.cc:shared tool table parser/format logic linked with wasm-safe mmap backend' \
|
||||||
|
linuxcnc-rs274-wasm-source-files.txt >/dev/null
|
||||||
|
grep -F 'blocked:src/emc/tooldata/tooldata_mmap.cc:native mmap implementation' \
|
||||||
|
linuxcnc-rs274-wasm-source-files.txt >/dev/null
|
||||||
|
grep -F 'metadata:src/emc/tooldata/tooldata_db.cc:source basis for wasm-safe tooldata runtime export shim' \
|
||||||
|
linuxcnc-rs274-wasm-source-files.txt >/dev/null
|
||||||
|
grep -F 'metadata:src/emc/tooldata/tooldata_nml.cc:source basis for wasm-safe tooldata runtime NML export shim' \
|
||||||
|
linuxcnc-rs274-wasm-source-files.txt >/dev/null
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/tooldata/tooldata_mmap.cc provides these' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'bool mmap_created = false;' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'bool mmap_random_toolchanger = false;' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'bool mmap_creator_called = false;' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'int tool_mmap_creator(EMC_TOOL_STAT const *ptr, int random_toolchanger)' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'Error: tool_mmap_creator already called BYE' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'mmap_created = true;' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'mmap_random_toolchanger = random_toolchanger;' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'last_index = 0;' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'int tool_mmap_user(void)' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'tool_mmap_user(): tool mmap not available' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'void tool_mmap_close(void)' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'mmap_created = false;' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'bool tool_mmap_is_random_toolchanger(void)' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'return mmap_random_toolchanger;' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'int tooldata_last_index_get(void)' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'return -1;' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_mmap_backend.cc >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/tooldata/tooldata_nml.cc and tooldata_db.cc' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc >/dev/null
|
||||||
|
grep -F 'constexpr int MAX_DB_PROGRAM_ARGS = 10;' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc >/dev/null
|
||||||
|
grep -F 'strtok_r(progname_plus_args, " ", &saveptr)' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc >/dev/null
|
||||||
|
grep -F 'argc exceeds MAX_DB_PROGRAM_ARGS=%d' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc >/dev/null
|
||||||
|
grep -F 'access(program, X_OK) != 0' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc >/dev/null
|
||||||
|
grep -F 'returns 0 when' core/wasm_shims/tooldata/tooldata_runtime_stubs.cc >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/tooldata/tooldata_common.cc provides' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_common_probe_main.cc >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/tooldata/tooldata_mmap.cc, tooldata_nml.cc,' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_probe_main.cc >/dev/null
|
||||||
|
grep -F 'tooldata_db_notify() returns 0 without side effects while db_live is' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_probe_main.cc >/dev/null
|
||||||
|
grep -F 'tooldata_db_init(missing_db_program_with_arg.data(), 1) != -1' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_probe_main.cc >/dev/null
|
||||||
|
grep -F 'missing_db_program_with_arg[separator] != 0' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_probe_main.cc >/dev/null
|
||||||
|
grep -F 'tooldata_db_init(too_many_db_args, 1) != -1' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_probe_main.cc >/dev/null
|
||||||
|
grep -F 'tooldata_db_init(non_db_program, 1) != -1' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_probe_main.cc >/dev/null
|
||||||
|
grep -F 'tool_mmap_creator(nullptr, 1);' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_probe_main.cc >/dev/null
|
||||||
|
grep -F 'WEXITSTATUS(recreate_status) == 0' \
|
||||||
|
core/wasm_shims/tooldata/tooldata_probe_main.cc >/dev/null
|
||||||
|
grep -F 'core/wasm_shims/tooldata/tooldata_mmap_backend.cc' docs/linuxcnc-wasm-shims-source-map.md >/dev/null
|
||||||
|
grep -F 'core/wasm_shims/tooldata/tooldata_runtime_stubs.cc' docs/linuxcnc-wasm-shims-source-map.md >/dev/null
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC source basis: this link probe runs the wasm-safe tooldata shim' \
|
||||||
|
test-linuxcnc-wasm-tooldata-link.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: this link probe runs tooldata_common through the' \
|
||||||
|
test-linuxcnc-wasm-tooldata-common-link.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: this symbol probe compares the wasm mmap backend shim' \
|
||||||
|
test-linuxcnc-wasm-tooldata-mmap-symbols.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: this probe compares wasm-safe tooldata runtime stubs' \
|
||||||
|
test-linuxcnc-wasm-tooldata-runtime-symbols.sh >/dev/null
|
||||||
|
grep -F '!!!!db_init: argc exceeds MAX_DB_PROGRAM_ARGS=10' \
|
||||||
|
test-linuxcnc-wasm-tooldata-link.sh >/dev/null
|
||||||
|
grep -F 'not executable' test-linuxcnc-wasm-tooldata-link.sh >/dev/null
|
||||||
|
grep -F 'Error: tool_mmap_creator already called BYE' \
|
||||||
|
test-linuxcnc-wasm-tooldata-link.sh >/dev/null
|
||||||
|
grep -F 'run_parallel_wasm_probe "LinuxCNC wasm tooldata shim link probe" ./test-linuxcnc-wasm-tooldata-link.sh' \
|
||||||
|
build-wasm.sh >/dev/null
|
||||||
|
grep -F 'run_parallel_wasm_probe "LinuxCNC wasm tooldata_common link probe" ./test-linuxcnc-wasm-tooldata-common-link.sh' \
|
||||||
|
build-wasm.sh >/dev/null
|
||||||
|
grep -F 'run_parallel_wasm_probe "LinuxCNC wasm tooldata_mmap symbol probe" ./test-linuxcnc-wasm-tooldata-mmap-symbols.sh' \
|
||||||
|
build-wasm.sh >/dev/null
|
||||||
|
grep -F 'run_parallel_wasm_probe "LinuxCNC wasm tooldata runtime symbol probe" ./test-linuxcnc-wasm-tooldata-runtime-symbols.sh' \
|
||||||
|
build-wasm.sh >/dev/null
|
||||||
|
|
||||||
|
python3 - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
doc = Path("docs/linuxcnc-tooldata-source-map.md").read_text(encoding="utf-8")
|
||||||
|
build_wasm_lines = Path("build-wasm.sh").read_text(encoding="utf-8").splitlines()
|
||||||
|
native_tooldata = subprocess.check_output(
|
||||||
|
["./list-linuxcnc-source-manifest-sources.sh", "linuxcnc-rs274-source-files.txt", "tooldata"],
|
||||||
|
text=True,
|
||||||
|
).splitlines()
|
||||||
|
expected_native = [
|
||||||
|
"src/emc/tooldata/tooldata_common.cc",
|
||||||
|
"src/emc/tooldata/tooldata_mmap.cc",
|
||||||
|
"src/emc/tooldata/tooldata_db.cc",
|
||||||
|
"src/emc/tooldata/tooldata_nml.cc",
|
||||||
|
"src/emc/tooldata/tool_mmap_read.cc",
|
||||||
|
"src/emc/tooldata/tool_watch.cc",
|
||||||
|
]
|
||||||
|
for source in expected_native:
|
||||||
|
if source not in native_tooldata:
|
||||||
|
raise SystemExit(f"native RS274 manifest missing LinuxCNC tooldata source: {source}")
|
||||||
|
|
||||||
|
kin_tooldata = subprocess.check_output(
|
||||||
|
["./list-linuxcnc-kinematics-manifest-sources.sh", "linuxcnc-kinematics-source-files.txt", "tooldata"],
|
||||||
|
text=True,
|
||||||
|
).splitlines()
|
||||||
|
if len([source for source in kin_tooldata if source.endswith(".tbl")]) != 10:
|
||||||
|
raise SystemExit("kinematics manifest must track exactly 10 LinuxCNC TOOL_TABLE sources")
|
||||||
|
|
||||||
|
positions = {}
|
||||||
|
for index, line in enumerate(build_wasm_lines, start=1):
|
||||||
|
if 'run_parallel_wasm_probe "LinuxCNC wasm tooldata shim link probe"' in line:
|
||||||
|
positions["tooldata_link"] = index
|
||||||
|
if 'run_parallel_wasm_probe "LinuxCNC wasm tooldata_common link probe"' in line:
|
||||||
|
positions["tooldata_common"] = index
|
||||||
|
if 'run_parallel_wasm_probe "LinuxCNC wasm tooldata_mmap symbol probe"' in line:
|
||||||
|
positions["tooldata_mmap"] = index
|
||||||
|
if 'run_parallel_wasm_probe "LinuxCNC wasm tooldata runtime symbol probe"' in line:
|
||||||
|
positions["tooldata_runtime"] = index
|
||||||
|
if "cp build/wasm/cnc_sim.js web/public/cnc_sim.js" in line:
|
||||||
|
positions["copy_js"] = index
|
||||||
|
if "cp build/wasm/cnc_sim.wasm web/public/cnc_sim.wasm" in line:
|
||||||
|
positions["copy_wasm"] = index
|
||||||
|
|
||||||
|
missing = [
|
||||||
|
name for name in (
|
||||||
|
"tooldata_link",
|
||||||
|
"tooldata_common",
|
||||||
|
"tooldata_mmap",
|
||||||
|
"tooldata_runtime",
|
||||||
|
"copy_js",
|
||||||
|
"copy_wasm",
|
||||||
|
)
|
||||||
|
if name not in positions
|
||||||
|
]
|
||||||
|
if missing:
|
||||||
|
raise SystemExit(f"build-wasm.sh missing tooldata/copy ordering anchor: {', '.join(missing)}")
|
||||||
|
for probe in ("tooldata_link", "tooldata_common", "tooldata_mmap", "tooldata_runtime"):
|
||||||
|
if not (positions[probe] < positions["copy_js"] and positions[probe] < positions["copy_wasm"]):
|
||||||
|
raise SystemExit("build-wasm.sh must run all tooldata link/symbol probes before copying browser artifacts")
|
||||||
|
|
||||||
|
for path in [
|
||||||
|
"core/wasm_shims/tooldata/tooldata_mmap_backend.cc",
|
||||||
|
"core/wasm_shims/tooldata/tooldata_runtime_stubs.cc",
|
||||||
|
"test-linuxcnc-wasm-tooldata-link.sh",
|
||||||
|
"test-linuxcnc-wasm-tooldata-common-link.sh",
|
||||||
|
"test-linuxcnc-wasm-tooldata-mmap-symbols.sh",
|
||||||
|
"test-linuxcnc-wasm-tooldata-runtime-symbols.sh",
|
||||||
|
]:
|
||||||
|
if path not in doc:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-tooldata-source-map.md missing coverage path: {path}")
|
||||||
|
|
||||||
|
for phrase in [
|
||||||
|
"must not add CNC behavior",
|
||||||
|
"must not expand the temporary smoke parser",
|
||||||
|
"source coverage only",
|
||||||
|
"must not become browser API fields",
|
||||||
|
"WASM-safe tooldata shims must preserve the LinuxCNC export surface",
|
||||||
|
"must keep external DB services unavailable",
|
||||||
|
"must not fork, exec, poll",
|
||||||
|
"MAX_DB_PROGRAM_ARGS=10",
|
||||||
|
"`strtok_r()` argument splitting",
|
||||||
|
"access(..., X_OK)",
|
||||||
|
"mmap tool table reader utility",
|
||||||
|
"NML/mmap tool table watcher utility",
|
||||||
|
"mmap creator/user/close lifecycle",
|
||||||
|
"random-toolchanger flag",
|
||||||
|
"last-index unavailable return",
|
||||||
|
"in-memory replacement for native mmap",
|
||||||
|
"inactive-DB return values",
|
||||||
|
"./check-linuxcnc-tooldata-source-map.sh",
|
||||||
|
"does not interpret G-code",
|
||||||
|
]:
|
||||||
|
if phrase not in doc:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-tooldata-source-map.md missing boundary phrase: {phrase}")
|
||||||
|
|
||||||
|
for entry in [
|
||||||
|
"test-native.sh",
|
||||||
|
"test-linuxcnc-source-link.sh",
|
||||||
|
"build-wasm.sh",
|
||||||
|
]:
|
||||||
|
text = Path(entry).read_text(encoding="utf-8")
|
||||||
|
if "./check-linuxcnc-tooldata-source-map.sh" not in text:
|
||||||
|
raise SystemExit(f"{entry} must run ./check-linuxcnc-tooldata-source-map.sh")
|
||||||
|
PY
|
||||||
194
check-linuxcnc-wasm-blockers-source-map.sh
Executable file
194
check-linuxcnc-wasm-blockers-source-map.sh
Executable file
@@ -0,0 +1,194 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: this guard ties the documented WASM blocker map to
|
||||||
|
# LinuxCNC RS274/Python/remap/tooldata sources, the rs274 WASM manifest, and
|
||||||
|
# wasm-safe shim replacement sources. It validates source coverage only; it
|
||||||
|
# does not add CNC behavior, expand smoke parsing, or interpret G-code.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||||
|
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs-cached.sh "$manifest"
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC source basis: this blocker scan is constrained to the RS274/WASM' \
|
||||||
|
analyze-linuxcnc-wasm-blockers.sh >/dev/null
|
||||||
|
grep -F 'blocked replacement is not in wasm shim build set' \
|
||||||
|
analyze-linuxcnc-wasm-blockers.sh >/dev/null
|
||||||
|
grep -F 'shim_source_output=$(./list-linuxcnc-wasm-safe-shims.sh)' \
|
||||||
|
analyze-linuxcnc-wasm-blockers.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: this guardrail locks the blocker categories reported' \
|
||||||
|
test-linuxcnc-wasm-blockers.sh >/dev/null
|
||||||
|
grep -F 'Cache wasm blocker analyzer output' docs/linuxcnc-source-policy.md >/dev/null
|
||||||
|
|
||||||
|
grep -F '#include <Python.h>' "$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F 'PyInit_gcode' "$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F '#include <boost/python/module.hpp>' "$linuxcnc_root/src/emc/rs274ngc/interpmodule.cc" >/dev/null
|
||||||
|
grep -F '#include "pythonplugin/python_plugin.hh"' "$linuxcnc_root/src/emc/rs274ngc/interp_python.cc" >/dev/null
|
||||||
|
grep -F 'dlopen' "$linuxcnc_root/src/emc/rs274ngc/interp_base.cc" >/dev/null
|
||||||
|
grep -F 'opendir(direct)' "$linuxcnc_root/src/emc/rs274ngc/interp_o_word.cc" >/dev/null
|
||||||
|
grep -F 'readdir(aDir)' "$linuxcnc_root/src/emc/rs274ngc/interp_o_word.cc" >/dev/null
|
||||||
|
grep -F 'std::string tempfile = std::string(filename) + ".new";' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F '+ RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX;' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'unlink(bakfile.c_str());' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'if(link(filename, bakfile.c_str()) < 0)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'if(rename(tempfile.c_str(), filename) < 0)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F '#define TOOL_MMAP_FILENAME ".tool.mmap"' "$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'int tool_mmap_creator(' "$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
|
||||||
|
python3 - "$linuxcnc_root" "$manifest" <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
linuxcnc_root = Path(sys.argv[1])
|
||||||
|
manifest = Path(sys.argv[2])
|
||||||
|
source_map = Path("docs/linuxcnc-wasm-blockers-source-map.md").read_text(encoding="utf-8")
|
||||||
|
manifest_lines = [
|
||||||
|
line for line in manifest.read_text(encoding="utf-8").splitlines()
|
||||||
|
if line and not line.startswith("#")
|
||||||
|
]
|
||||||
|
manifest_counts = {"core": 0, "blocked": 0, "header": 0, "blocked-header": 0, "metadata": 0}
|
||||||
|
for line in manifest_lines:
|
||||||
|
group = line.split(":", 1)[0]
|
||||||
|
if group not in manifest_counts:
|
||||||
|
raise SystemExit(f"unexpected WASM manifest group in blocker source map guard: {group}")
|
||||||
|
manifest_counts[group] += 1
|
||||||
|
for group, count in manifest_counts.items():
|
||||||
|
if f"| `{group}` | {count} |" not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-wasm-blockers-source-map.md count mismatch for {group}")
|
||||||
|
|
||||||
|
output = subprocess.check_output(
|
||||||
|
["./analyze-linuxcnc-wasm-blockers.sh", str(manifest)],
|
||||||
|
text=True,
|
||||||
|
env={"LINUXCNC_ROOT": str(linuxcnc_root)},
|
||||||
|
)
|
||||||
|
sections = {}
|
||||||
|
current = None
|
||||||
|
for line in output.splitlines():
|
||||||
|
if line.startswith("[") and line.endswith("]"):
|
||||||
|
current = line[1:-1]
|
||||||
|
sections[current] = []
|
||||||
|
elif current and line:
|
||||||
|
sections[current].append(line)
|
||||||
|
|
||||||
|
expected_counts = {
|
||||||
|
"manifest-core": "core=26",
|
||||||
|
"manifest-blocked": "blocked=9",
|
||||||
|
"python": 8,
|
||||||
|
"python-compile-covered": 8,
|
||||||
|
"tooldata": 1,
|
||||||
|
"native-backend": 1,
|
||||||
|
"native-fs": 1,
|
||||||
|
"blocked-replacements": 9,
|
||||||
|
"core-python-shimmed": 6,
|
||||||
|
"core-dlopen-shimmed": 1,
|
||||||
|
"core-tooldata-shimmed": 1,
|
||||||
|
"core-tooldata-users-shimmed": 2,
|
||||||
|
"core-native-fs-shimmed": 16,
|
||||||
|
}
|
||||||
|
manifest_section = sections.get("manifest", [])
|
||||||
|
if expected_counts["manifest-core"] not in manifest_section:
|
||||||
|
raise SystemExit("WASM blocker analyzer core count changed")
|
||||||
|
if expected_counts["manifest-blocked"] not in manifest_section:
|
||||||
|
raise SystemExit("WASM blocker analyzer blocked count changed")
|
||||||
|
for section, count in expected_counts.items():
|
||||||
|
if section.startswith("manifest-"):
|
||||||
|
continue
|
||||||
|
entries = [entry for entry in sections.get(section, []) if entry != "(none)"]
|
||||||
|
if len(entries) != count:
|
||||||
|
raise SystemExit(f"WASM blocker analyzer section {section} count changed: {len(entries)}")
|
||||||
|
if f"| `{section}` | {count} |" not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-wasm-blockers-source-map.md analyzer count mismatch for {section}")
|
||||||
|
if sections.get("dlopen") != ["(none)"]:
|
||||||
|
raise SystemExit("blocked dlopen section is no longer empty")
|
||||||
|
if sections.get("tooldata-users") != ["(none)"]:
|
||||||
|
raise SystemExit("blocked tooldata-users section is no longer empty")
|
||||||
|
if sections.get("python") != sections.get("python-compile-covered"):
|
||||||
|
raise SystemExit("blocked Python sources are no longer fully compile-covered by the inert Python C API probe")
|
||||||
|
|
||||||
|
shim_paths = set(Path(line).as_posix() for line in subprocess.check_output(
|
||||||
|
["./list-linuxcnc-wasm-safe-shims.sh"],
|
||||||
|
text=True,
|
||||||
|
).splitlines() if line)
|
||||||
|
required_tracked_entries = [
|
||||||
|
"src/emc/rs274ngc/interp_base.cc -> core/wasm_shims/dlfcn.cc",
|
||||||
|
"src/emc/rs274ngc/gcodemodule.cc",
|
||||||
|
"src/emc/rs274ngc/interpmodule.cc",
|
||||||
|
"src/emc/tooldata/tooldata_mmap.cc",
|
||||||
|
"src/emc/rs274ngc/interp_base.cc",
|
||||||
|
"src/emc/rs274ngc/interp_o_word.cc",
|
||||||
|
"src/emc/rs274ngc/rs274ngc_pre.cc",
|
||||||
|
]
|
||||||
|
required_replacements = [
|
||||||
|
"src/emc/rs274ngc/canonmodule.cc -> core/wasm_shims/linuxcnc_runtime_shim.cc",
|
||||||
|
"src/emc/rs274ngc/gcodemodule.cc -> core/wasm_shims/linuxcnc_runtime_shim.cc",
|
||||||
|
"src/emc/rs274ngc/interpmodule.cc -> core/wasm_shims/linuxcnc_runtime_shim.cc",
|
||||||
|
"src/emc/rs274ngc/pyarrays.cc -> core/wasm_shims/python_c_api_shim.cc",
|
||||||
|
"src/emc/rs274ngc/pyblock.cc -> core/wasm_shims/python_c_api_shim.cc",
|
||||||
|
"src/emc/rs274ngc/pyemctypes.cc -> core/wasm_shims/python_c_api_shim.cc",
|
||||||
|
"src/emc/rs274ngc/pyinterp1.cc -> core/wasm_shims/python_c_api_shim.cc",
|
||||||
|
"src/emc/rs274ngc/pyparamclass.cc -> core/wasm_shims/python_c_api_shim.cc",
|
||||||
|
"src/emc/tooldata/tooldata_mmap.cc -> core/wasm_shims/tooldata/tooldata_mmap_backend.cc",
|
||||||
|
]
|
||||||
|
for entry in required_tracked_entries:
|
||||||
|
if " -> " in entry:
|
||||||
|
source, shim = entry.split(" -> ", 1)
|
||||||
|
if source not in sections.get("core-dlopen-shimmed", []):
|
||||||
|
raise SystemExit(f"WASM blocker analyzer output missing core dlopen shimmed source: {source}")
|
||||||
|
if shim not in shim_paths:
|
||||||
|
raise SystemExit(f"WASM blocker analyzer core dlopen shim is absent from wasm-safe shim set: {shim}")
|
||||||
|
elif entry not in output:
|
||||||
|
raise SystemExit(f"WASM blocker analyzer output missing required entry: {entry}")
|
||||||
|
if entry not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-wasm-blockers-source-map.md missing required entry: {entry}")
|
||||||
|
replacement_entries = [entry for entry in sections.get("blocked-replacements", []) if entry != "(none)"]
|
||||||
|
if replacement_entries != required_replacements:
|
||||||
|
raise SystemExit(f"WASM blocker replacement set changed: {replacement_entries}")
|
||||||
|
if "Required replacement set:" not in source_map:
|
||||||
|
raise SystemExit("docs/linuxcnc-wasm-blockers-source-map.md must document the complete replacement set")
|
||||||
|
for entry in required_replacements:
|
||||||
|
if entry not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-wasm-blockers-source-map.md missing required replacement: {entry}")
|
||||||
|
|
||||||
|
for replacement in re.findall(r"-> (core/wasm_shims/[^\s]+)", output):
|
||||||
|
if replacement not in shim_paths:
|
||||||
|
raise SystemExit(f"blocked replacement is absent from wasm-safe shim set: {replacement}")
|
||||||
|
for phrase in [
|
||||||
|
"does not add CNC behavior",
|
||||||
|
"must not become smoke parser behavior",
|
||||||
|
"blocked `dlopen` and blocked tooldata-users remain empty",
|
||||||
|
'parameter-file replacement through `filename + ".new"`',
|
||||||
|
"O-word lookup and parameter-file replacement",
|
||||||
|
"Python/Boost.Python remap paths remain tracked blockers",
|
||||||
|
"Python/Boost.Python blockers are compile-covered by the inert Python C API probe",
|
||||||
|
"./check-linuxcnc-wasm-blockers-source-map.sh",
|
||||||
|
"does not interpret G-code",
|
||||||
|
]:
|
||||||
|
if phrase not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-wasm-blockers-source-map.md missing boundary phrase: {phrase}")
|
||||||
|
|
||||||
|
for entry in [
|
||||||
|
"test-native.sh",
|
||||||
|
"test-linuxcnc-source-link.sh",
|
||||||
|
"build-wasm.sh",
|
||||||
|
]:
|
||||||
|
text = Path(entry).read_text(encoding="utf-8")
|
||||||
|
if "./check-linuxcnc-wasm-blockers-source-map.sh" not in text:
|
||||||
|
raise SystemExit(f"{entry} must run ./check-linuxcnc-wasm-blockers-source-map.sh")
|
||||||
|
for entry in [
|
||||||
|
"test-native.sh",
|
||||||
|
"test-linuxcnc-source-link.sh",
|
||||||
|
]:
|
||||||
|
text = Path(entry).read_text(encoding="utf-8")
|
||||||
|
if "CNC_SIM_WASM_BLOCKERS_SELF_CHECKS=1" not in text:
|
||||||
|
raise SystemExit(f"{entry} must run wasm blocker analyzer self-checks")
|
||||||
|
PY
|
||||||
499
check-linuxcnc-wasm-shims-source-map.sh
Executable file
499
check-linuxcnc-wasm-shims-source-map.sh
Executable file
@@ -0,0 +1,499 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: this guard ties the documented wasm-safe shim map to
|
||||||
|
# the linuxcnc_wasm_safe_probe_shims CMake set, the RS274/WASM source manifest,
|
||||||
|
# and the LinuxCNC sources each shim cites. It validates source coverage only;
|
||||||
|
# it does not add CNC behavior, expand smoke parsing, or interpret G-code.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||||
|
|
||||||
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs-cached.sh "$manifest"
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC source basis: wasm-safe shim probe sources are limited to the' \
|
||||||
|
list-linuxcnc-wasm-safe-shims.sh >/dev/null
|
||||||
|
grep -F 'set(linuxcnc_wasm_safe_probe_shims' core/CMakeLists.txt >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: this guard ties the documented WASM blocker map' \
|
||||||
|
check-linuxcnc-wasm-blockers-source-map.sh >/dev/null
|
||||||
|
|
||||||
|
grep -F 'dlopen(NULL, RTLD_GLOBAL);' "$linuxcnc_root/src/emc/rs274ngc/interp_base.cc" >/dev/null
|
||||||
|
grep -F 'interp_lib = dlopen(interp_path, RTLD_NOW);' "$linuxcnc_root/src/emc/rs274ngc/interp_base.cc" >/dev/null
|
||||||
|
grep -F 'Constructor constructor = (Constructor)dlsym(interp_lib, "makeInterp");' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_base.cc" >/dev/null
|
||||||
|
grep -F 'dlerror()' "$linuxcnc_root/src/emc/rs274ngc/interp_base.cc" >/dev/null
|
||||||
|
grep -F '#include "libintl.h"' "$linuxcnc_root/src/emc/rs274ngc/interp_internal.hh" >/dev/null
|
||||||
|
grep -F '#define _(s) gettext(s)' "$linuxcnc_root/src/emc/rs274ngc/interp_internal.hh" >/dev/null
|
||||||
|
grep -F 'CHKS((!_readers[(int)' "$linuxcnc_root/src/emc/rs274ngc/interp_internal.cc" >/dev/null
|
||||||
|
grep -F 'Cannot use polar coordinate on a machine lacking X or Y axes' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_internal.cc" >/dev/null
|
||||||
|
grep -F 'int _task = 0;' "$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F 'int _task = 1;' "$linuxcnc_root/src/emc/task/emctaskmain.cc" >/dev/null
|
||||||
|
grep -F '{ "interpreter", PyInit_interpreter },' "$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F '{ "emccanon", PyInit_emccanon },' "$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F 'struct _inittab builtin_modules[]' "$linuxcnc_root/src/emc/task/taskclass.cc" >/dev/null
|
||||||
|
grep -F 'int Interp::fetch_hal_param(' "$linuxcnc_root/src/emc/rs274ngc/interp_namedparams.cc" >/dev/null
|
||||||
|
grep -F 'hal_get_pin_value_by_name(hal_name, &type, &ptr, &conn)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_namedparams.cc" >/dev/null
|
||||||
|
grep -F 'hal_get_signal_value_by_name(hal_name, &type, &ptr, &conn)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_namedparams.cc" >/dev/null
|
||||||
|
grep -F 'hal_get_param_value_by_name(hal_name, &type, &ptr)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_namedparams.cc" >/dev/null
|
||||||
|
grep -F 'HAL_TYPE_UNINITIALIZED = 0,' "$linuxcnc_root/include/hal.h" >/dev/null
|
||||||
|
grep -F 'extern int hal_get_pin_value_by_name(' "$linuxcnc_root/include/hal.h" >/dev/null
|
||||||
|
grep -F 'extern int hal_get_signal_value_by_name(' "$linuxcnc_root/include/hal.h" >/dev/null
|
||||||
|
grep -F 'extern int hal_get_param_value_by_name(' "$linuxcnc_root/include/hal.h" >/dev/null
|
||||||
|
grep -F 'int hal_get_pin_value_by_name(' "$linuxcnc_root/src/hal/hal_lib.c" >/dev/null
|
||||||
|
grep -F 'int hal_get_signal_value_by_name(' "$linuxcnc_root/src/hal/hal_lib.c" >/dev/null
|
||||||
|
grep -F 'int hal_get_param_value_by_name(' "$linuxcnc_root/src/hal/hal_lib.c" >/dev/null
|
||||||
|
grep -F 'wordexp(basename, &exp_result, 0);' "$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'wordexp(settings->program_prefix, &exp_result, 0);' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'wordexp(settings->subroutines[dct], &exp_result, 0);' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'wordfree(&exp_result);' "$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F '#include "nml_intf/emc_nml.hh"' "$linuxcnc_root/src/emc/sai/dummyemcstat.cc" >/dev/null
|
||||||
|
grep -F 'EMC_STAT *emcStatus = new EMC_STAT;' "$linuxcnc_root/src/emc/sai/dummyemcstat.cc" >/dev/null
|
||||||
|
grep -F 'int NMLmsg::automatically_clear = 1;' \
|
||||||
|
"$linuxcnc_root/src/libnml/nml/nmlmsg.cc" >/dev/null
|
||||||
|
grep -F 'NMLmsg::NMLmsg' "$linuxcnc_root/src/libnml/nml/nmlmsg.cc" >/dev/null
|
||||||
|
grep -F 'void NMLmsg::clear()' "$linuxcnc_root/src/libnml/nml/nmlmsg.cc" >/dev/null
|
||||||
|
grep -F 'memset((void *) this, 0, size);' \
|
||||||
|
"$linuxcnc_root/src/libnml/nml/nmlmsg.cc" >/dev/null
|
||||||
|
grep -F 'RCS_STAT_MSG::RCS_STAT_MSG' "$linuxcnc_root/src/libnml/nml/stat_msg.cc" >/dev/null
|
||||||
|
grep -F 'command_type = -1;' "$linuxcnc_root/src/libnml/nml/stat_msg.cc" >/dev/null
|
||||||
|
grep -F 'echo_serial_number = -1;' "$linuxcnc_root/src/libnml/nml/stat_msg.cc" >/dev/null
|
||||||
|
grep -F 'status = RCS_STATUS::UNINITIALIZED;' "$linuxcnc_root/src/libnml/nml/stat_msg.cc" >/dev/null
|
||||||
|
grep -F '_state = -1;' "$linuxcnc_root/src/libnml/nml/stat_msg.cc" >/dev/null
|
||||||
|
grep -F 'extern int set_print_rcs_error_info(const char *file, int line);' \
|
||||||
|
"$linuxcnc_root/src/libnml/rcs/rcs_print.hh" >/dev/null
|
||||||
|
grep -F 'extern int print_rcs_error_new(const char *_fmt, ...)' \
|
||||||
|
"$linuxcnc_root/src/libnml/rcs/rcs_print.hh" >/dev/null
|
||||||
|
grep -F '#define rcs_print_error set_print_rcs_error_info( __FILE__, __LINE__); print_rcs_error_new' \
|
||||||
|
"$linuxcnc_root/src/libnml/rcs/rcs_print.hh" >/dev/null
|
||||||
|
grep -F 'int set_print_rcs_error_info(const char *file, int line)' \
|
||||||
|
"$linuxcnc_root/src/libnml/rcs/rcs_print.cc" >/dev/null
|
||||||
|
grep -F 'print_rcs_error_new' "$linuxcnc_root/src/libnml/rcs/rcs_print.cc" >/dev/null
|
||||||
|
grep -F 'retval = rcs_vprint(_fmt, args, 1);' \
|
||||||
|
"$linuxcnc_root/src/libnml/rcs/rcs_print.cc" >/dev/null
|
||||||
|
grep -F 'extern int rtapi_snprintf(char *buf, unsigned long int size,' \
|
||||||
|
"$linuxcnc_root/src/rtapi/rtapi.h" >/dev/null
|
||||||
|
grep -F 'extern int rtapi_vsnprintf(char *buf, unsigned long size,' \
|
||||||
|
"$linuxcnc_root/src/rtapi/rtapi.h" >/dev/null
|
||||||
|
grep -F 'int rtapi_snprintf(char *buffer, unsigned long int size, const char *msg, ...) {' \
|
||||||
|
"$linuxcnc_root/src/rtapi/uspace_common.h" >/dev/null
|
||||||
|
grep -F 'result = vsnprintf(buffer, size, msg, args);' \
|
||||||
|
"$linuxcnc_root/src/rtapi/uspace_common.h" >/dev/null
|
||||||
|
grep -F 'int rtapi_vsnprintf(char *buffer, unsigned long int size, const char *fmt,' \
|
||||||
|
"$linuxcnc_root/src/rtapi/uspace_common.h" >/dev/null
|
||||||
|
grep -F 'return vsnprintf(buffer, size, fmt, args);' \
|
||||||
|
"$linuxcnc_root/src/rtapi/uspace_common.h" >/dev/null
|
||||||
|
grep -F 'class PythonPlugin' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
|
grep -F 'PLUGIN_PYTHON_NOT_INITIALIZED = -12,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
|
grep -F 'PLUGIN_BAD_PATH = -5,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
|
grep -F 'PLUGIN_INITTAB_FAILED = -7 ,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
|
grep -F 'PLUGIN_EXCEPTION_DURING_PATH_PREPEND = -9,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
|
grep -F 'PLUGIN_EXCEPTION_DURING_PATH_APPEND = -10,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
|
grep -F 'PLUGIN_NO_CALLABLE = 1,' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
|
grep -F 'PLUGIN_EXCEPTION = 2' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.hh" >/dev/null
|
||||||
|
grep -F 'PythonPlugin::instantiate' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'for (int i = 0; inittab[i].name != NULL; i++) {' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'if (module == NULL) {' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'status = PLUGIN_INITTAB_FAILED;' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'if (status < PLUGIN_OK)' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'if (auto inistring = inifile.findString("TOPLEVEL", section)) {' \
|
||||||
|
"$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'if (realpath(toplevel, real_path) == NULL) {' \
|
||||||
|
"$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'status = PLUGIN_BAD_PATH;' "$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'while (auto inistring = inifile.findString(n, "PATH_PREPEND", "PYTHON")) {' \
|
||||||
|
"$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'while (auto inistring = inifile.findString(n, "PATH_APPEND", "PYTHON")) {' \
|
||||||
|
"$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'status = PLUGIN_EXCEPTION_DURING_PATH_PREPEND;' \
|
||||||
|
"$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'status = PLUGIN_EXCEPTION_DURING_PATH_APPEND;' \
|
||||||
|
"$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'int IniFile::tildeExpand(const std::string &path, std::string &result)' \
|
||||||
|
"$linuxcnc_root/src/emc/ini/inifile.cc" >/dev/null
|
||||||
|
grep -F "if(!home)" "$linuxcnc_root/src/emc/ini/inifile.cc" >/dev/null
|
||||||
|
grep -F 'IniFile::trim(sect);' "$linuxcnc_root/src/emc/ini/inifile.cc" >/dev/null
|
||||||
|
grep -F 'Section header has trailing content, ignored' "$linuxcnc_root/src/emc/ini/inifile.cc" >/dev/null
|
||||||
|
grep -F 'retval = bp::exec_file(cmd, main_namespace, main_namespace);' \
|
||||||
|
"$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'retval = bp::exec(cmd, main_namespace, main_namespace);' \
|
||||||
|
"$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'PyObject *rv = PyObject_Call(function.ptr(), tupleargs.ptr(), kwargs.ptr());' \
|
||||||
|
"$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F 'PyErr_Fetch(&exc,&val,&tb);' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_python.cc" >/dev/null
|
||||||
|
grep -F 'PyErr_NormalizeException(&exc,&val,&tb);' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_python.cc" >/dev/null
|
||||||
|
grep -F 'if (Py_IsInitialized()) {' \
|
||||||
|
"$linuxcnc_root/src/emc/pythonplugin/python_plugin.cc" >/dev/null
|
||||||
|
grep -F '#define callmethod(o, m, f, ...) PyObject_CallMethod((o), (char*)(m), (char*)(f), ## __VA_ARGS__)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F 'PyObject *result = PyObject_GetAttrString(callback, "parameter_file");' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F 'PyErr_Format(PyExc_TypeError,' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F 'return Py_BuildValue("[ddd][ddd][ddd][ddd]",' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F 'PyObject *m = PyModule_Create(&gcode_moduledef);' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F 'PyType_Ready(&LineCodeType);' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F 'PyModule_AddObject(m, "linecode", (PyObject*)&LineCodeType);' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F 'PyObject_SetAttrString(m, "MAX_ERROR", PyLong_FromLong(maxerror));' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/gcodemodule.cc" >/dev/null
|
||||||
|
grep -F '#define TOOL_MMAP_FILENAME ".tool.mmap"' "$linuxcnc_root/src/emc/tooldata/tooldata_mmap.cc" >/dev/null
|
||||||
|
grep -F 'int tool_nml_register(CANON_TOOL_TABLE *tblptr)' "$linuxcnc_root/src/emc/tooldata/tooldata_nml.cc" >/dev/null
|
||||||
|
grep -F 'int tooldata_db_init(char progname_plus_args[]' "$linuxcnc_root/src/emc/tooldata/tooldata_db.cc" >/dev/null
|
||||||
|
grep -F 'if (!db_live) {return -1;}' "$linuxcnc_root/src/emc/tooldata/tooldata_db.cc" >/dev/null
|
||||||
|
grep -F 'if (!db_live) return 0;' "$linuxcnc_root/src/emc/tooldata/tooldata_db.cc" >/dev/null
|
||||||
|
|
||||||
|
python3 - "$manifest" <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
manifest = Path(sys.argv[1])
|
||||||
|
source_map = Path("docs/linuxcnc-wasm-shims-source-map.md").read_text(encoding="utf-8")
|
||||||
|
manifest_text = manifest.read_text(encoding="utf-8")
|
||||||
|
shim_paths = [
|
||||||
|
line for line in subprocess.check_output(["./list-linuxcnc-wasm-safe-shims.sh"], text=True).splitlines()
|
||||||
|
if line
|
||||||
|
]
|
||||||
|
if len(shim_paths) != 11:
|
||||||
|
raise SystemExit(f"expected 11 wasm-safe CMake shim sources, found {len(shim_paths)}")
|
||||||
|
if f"| CMake `linuxcnc_wasm_safe_probe_shims` sources | {len(shim_paths)} |" not in source_map:
|
||||||
|
raise SystemExit("docs/linuxcnc-wasm-shims-source-map.md shim count mismatch")
|
||||||
|
|
||||||
|
expected_shims = {
|
||||||
|
"core/wasm_shims/dlfcn.cc": ["src/emc/rs274ngc/interp_base.cc"],
|
||||||
|
"core/wasm_shims/emc_status_shim.cc": ["src/emc/sai/dummyemcstat.cc"],
|
||||||
|
"core/wasm_shims/gettext_shim.cc": ["src/emc/rs274ngc/interp_internal.hh"],
|
||||||
|
"core/wasm_shims/linuxcnc_runtime_shim.cc": [
|
||||||
|
"src/emc/rs274ngc/gcodemodule.cc",
|
||||||
|
"src/emc/task/emctaskmain.cc",
|
||||||
|
"src/emc/task/taskclass.cc",
|
||||||
|
"src/emc/rs274ngc/interp_namedparams.cc",
|
||||||
|
"include/hal.h",
|
||||||
|
"src/hal/hal_lib.c",
|
||||||
|
"src/emc/rs274ngc/rs274ngc_pre.cc",
|
||||||
|
],
|
||||||
|
"core/wasm_shims/nml_status_shim.cc": [
|
||||||
|
"src/libnml/nml/nmlmsg.cc",
|
||||||
|
"src/libnml/nml/stat_msg.cc",
|
||||||
|
],
|
||||||
|
"core/wasm_shims/python_c_api_shim.cc": [
|
||||||
|
"src/emc/rs274ngc/interp_python.cc",
|
||||||
|
"src/emc/rs274ngc/interp_namedparams.cc",
|
||||||
|
"src/emc/rs274ngc/gcodemodule.cc",
|
||||||
|
"src/emc/pythonplugin/python_plugin.cc",
|
||||||
|
],
|
||||||
|
"core/wasm_shims/rcs_print_shim.cc": [
|
||||||
|
"src/libnml/rcs/rcs_print.cc",
|
||||||
|
"src/libnml/rcs/rcs_print.hh",
|
||||||
|
],
|
||||||
|
"core/wasm_shims/rtapi_compat.cc": [
|
||||||
|
"src/rtapi/uspace_common.h",
|
||||||
|
"src/rtapi/rtapi.h",
|
||||||
|
],
|
||||||
|
"core/wasm_shims/tooldata/tooldata_mmap_backend.cc": [
|
||||||
|
"src/emc/tooldata/tooldata_mmap.cc",
|
||||||
|
],
|
||||||
|
"core/wasm_shims/tooldata/tooldata_runtime_stubs.cc": [
|
||||||
|
"src/emc/tooldata/tooldata_nml.cc",
|
||||||
|
"src/emc/tooldata/tooldata_db.cc",
|
||||||
|
],
|
||||||
|
"core/wasm_shims/pythonplugin/python_plugin.cc": [
|
||||||
|
"src/emc/pythonplugin/python_plugin.cc",
|
||||||
|
"src/emc/pythonplugin/python_plugin.hh",
|
||||||
|
"src/emc/ini/inifile.cc",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
if shim_paths != list(expected_shims):
|
||||||
|
raise SystemExit("wasm-safe shim CMake order no longer matches docs/linuxcnc-wasm-shims-source-map.md")
|
||||||
|
|
||||||
|
for shim_path, linuxcnc_sources in expected_shims.items():
|
||||||
|
shim_text = Path(shim_path).read_text(encoding="utf-8")
|
||||||
|
if "LinuxCNC source basis:" not in shim_text:
|
||||||
|
raise SystemExit(f"{shim_path} is missing a LinuxCNC source basis comment")
|
||||||
|
if f"| `{shim_path}` |" not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-wasm-shims-source-map.md missing shim row: {shim_path}")
|
||||||
|
for source in linuxcnc_sources:
|
||||||
|
if source not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-wasm-shims-source-map.md missing source {source} for {shim_path}")
|
||||||
|
if source not in manifest_text:
|
||||||
|
raise SystemExit(f"{source} is not tracked in {manifest}")
|
||||||
|
|
||||||
|
runtime_shim = Path("core/wasm_shims/linuxcnc_runtime_shim.cc").read_text(encoding="utf-8")
|
||||||
|
runtime_probe = Path("core/wasm_shims/cnc_sim_wasm_runtime_probe_main.cc").read_text(encoding="utf-8")
|
||||||
|
dlfcn_shim = Path("core/wasm_shims/dlfcn.cc").read_text(encoding="utf-8")
|
||||||
|
dlfcn_header = Path("core/wasm_shims/dlfcn.h").read_text(encoding="utf-8")
|
||||||
|
emc_status_shim = Path("core/wasm_shims/emc_status_shim.cc").read_text(encoding="utf-8")
|
||||||
|
gettext_shim = Path("core/wasm_shims/gettext_shim.cc").read_text(encoding="utf-8")
|
||||||
|
for needle in [
|
||||||
|
"#define RTLD_GLOBAL 0x00100",
|
||||||
|
"#define RTLD_NOW 0x00002",
|
||||||
|
"void *dlopen(const char *filename, int flags);",
|
||||||
|
"void *dlsym(void *handle, const char *symbol);",
|
||||||
|
"char *dlerror(void);",
|
||||||
|
"int dlclose(void *handle);",
|
||||||
|
]:
|
||||||
|
if needle not in dlfcn_header:
|
||||||
|
raise SystemExit(f"dlfcn shim header missing LinuxCNC loader boundary: {needle}")
|
||||||
|
for needle in [
|
||||||
|
"dynamic loading is unavailable in wasm-safe probe",
|
||||||
|
"void *dlopen(const char *, int)",
|
||||||
|
"return nullptr;",
|
||||||
|
"void *dlsym(void *, const char *)",
|
||||||
|
"char *dlerror(void)",
|
||||||
|
"return last_error;",
|
||||||
|
"int dlclose(void *)",
|
||||||
|
"return 0;",
|
||||||
|
]:
|
||||||
|
if needle not in dlfcn_shim:
|
||||||
|
raise SystemExit(f"dlfcn shim missing unavailable-loader boundary: {needle}")
|
||||||
|
for needle in [
|
||||||
|
'#include "nml_intf/emc_nml.hh"',
|
||||||
|
"EMC_STAT *emcStatus = new EMC_STAT;",
|
||||||
|
]:
|
||||||
|
if needle not in emc_status_shim:
|
||||||
|
raise SystemExit(f"EMC status shim missing detached LinuxCNC status singleton: {needle}")
|
||||||
|
for needle in [
|
||||||
|
"extern \"C\" char *gettext(const char *msgid)",
|
||||||
|
"return const_cast<char *>(msgid ? msgid : \"\");",
|
||||||
|
]:
|
||||||
|
if needle not in gettext_shim:
|
||||||
|
raise SystemExit(f"gettext shim missing diagnostic passthrough boundary: {needle}")
|
||||||
|
nml_status_shim = Path("core/wasm_shims/nml_status_shim.cc").read_text(encoding="utf-8")
|
||||||
|
for needle in [
|
||||||
|
"int NMLmsg::automatically_clear = 1;",
|
||||||
|
"void NMLmsg::clear()",
|
||||||
|
"std::memset(static_cast<void *>(this), 0, static_cast<size_t>(size));",
|
||||||
|
"command_type = -1;",
|
||||||
|
"echo_serial_number = -1;",
|
||||||
|
"status = RCS_STATUS::UNINITIALIZED;",
|
||||||
|
"_state = -1;",
|
||||||
|
]:
|
||||||
|
if needle not in nml_status_shim:
|
||||||
|
raise SystemExit(f"NML status shim missing LinuxCNC constructor boundary: {needle}")
|
||||||
|
for needle in [
|
||||||
|
"int _task = 0;",
|
||||||
|
'extern "C" PyObject *PyInit_interpreter(void)',
|
||||||
|
'extern "C" PyObject *PyInit_emccanon(void)',
|
||||||
|
'extern "C" PyObject *PyInit_gcode(void)',
|
||||||
|
"return nullptr;",
|
||||||
|
'struct _inittab builtin_modules[] = {',
|
||||||
|
'{"interpreter", PyInit_interpreter}',
|
||||||
|
'{"emccanon", PyInit_emccanon}',
|
||||||
|
]:
|
||||||
|
if needle not in runtime_shim:
|
||||||
|
raise SystemExit(f"linuxcnc runtime shim missing preview/builtin module boundary: {needle}")
|
||||||
|
for needle in [
|
||||||
|
"std::string expand_home_directory(const char *words)",
|
||||||
|
"std::string expand_environment_variables(const std::string &words)",
|
||||||
|
"extern \"C\" int wordexp(const char *words, wordexp_t *pwordexp, int)",
|
||||||
|
"return WRDE_BADVAL;",
|
||||||
|
"return WRDE_NOSPACE;",
|
||||||
|
"pwordexp->we_wordc = 1;",
|
||||||
|
"pwordexp->we_offs = 0;",
|
||||||
|
"extern \"C\" void wordfree(wordexp_t *pwordexp)",
|
||||||
|
"pwordexp->we_wordc = 0;",
|
||||||
|
"pwordexp->we_wordv = nullptr;",
|
||||||
|
]:
|
||||||
|
if needle not in runtime_shim:
|
||||||
|
raise SystemExit(f"linuxcnc runtime shim missing limited wordexp boundary: {needle}")
|
||||||
|
for needle in [
|
||||||
|
'extern "C" int hal_get_pin_value_by_name',
|
||||||
|
'extern "C" int hal_get_signal_value_by_name',
|
||||||
|
'extern "C" int hal_get_param_value_by_name',
|
||||||
|
"*type = HAL_TYPE_UNINITIALIZED;",
|
||||||
|
"*data = nullptr;",
|
||||||
|
"return -1;",
|
||||||
|
]:
|
||||||
|
if needle not in runtime_shim:
|
||||||
|
raise SystemExit(f"linuxcnc runtime shim missing HAL unavailable boundary: {needle}")
|
||||||
|
for needle in [
|
||||||
|
"bool hal_lookup_is_unavailable()",
|
||||||
|
'hal_get_pin_value_by_name("cnc-sim.missing-pin", &type, &data, &connected) != -1',
|
||||||
|
'hal_get_signal_value_by_name("cnc-sim.missing-signal", &type, &data, &has_writers) != -1',
|
||||||
|
'hal_get_param_value_by_name("cnc-sim.missing-param", &type, &data) != -1',
|
||||||
|
"type != HAL_TYPE_UNINITIALIZED",
|
||||||
|
"data != nullptr",
|
||||||
|
]:
|
||||||
|
if needle not in runtime_probe:
|
||||||
|
raise SystemExit(f"runtime probe missing HAL unavailable assertion: {needle}")
|
||||||
|
|
||||||
|
python_plugin_shim = Path("core/wasm_shims/pythonplugin/python_plugin.cc").read_text(encoding="utf-8")
|
||||||
|
python_plugin_probe = Path("core/wasm_shims/pythonplugin/python_plugin_probe_main.cc").read_text(encoding="utf-8")
|
||||||
|
python_plugin_inittab_probe = Path("core/wasm_shims/pythonplugin/python_plugin_inittab_probe_main.cc").read_text(encoding="utf-8")
|
||||||
|
python_c_api_shim = Path("core/wasm_shims/python_c_api_shim.cc").read_text(encoding="utf-8")
|
||||||
|
for forbidden in [
|
||||||
|
"bp::exec(",
|
||||||
|
"bp::exec_file(",
|
||||||
|
"PyObject_Call(",
|
||||||
|
]:
|
||||||
|
if forbidden in python_plugin_shim:
|
||||||
|
raise SystemExit(f"PythonPlugin wasm shim must not execute Python: {forbidden}")
|
||||||
|
for needle in [
|
||||||
|
"python disabled in wasm-safe probe",
|
||||||
|
'find_ini_value(iniFilename, section, "TOPLEVEL", toplevel)',
|
||||||
|
"realpath(toplevel.c_str(), resolved_path) == nullptr",
|
||||||
|
"status = PLUGIN_BAD_PATH;",
|
||||||
|
"status = PLUGIN_INITTAB_FAILED;",
|
||||||
|
"failed to initialize built-in module",
|
||||||
|
"read_ini_section(text, section_name)",
|
||||||
|
"section_name = trim_ini_value(text.substr(1, close - 1));",
|
||||||
|
'check_python_path_entries(iniFilename,',
|
||||||
|
"PLUGIN_EXCEPTION_DURING_PATH_PREPEND",
|
||||||
|
"PLUGIN_EXCEPTION_DURING_PATH_APPEND",
|
||||||
|
"tilde_expand_path(entry, expanded)",
|
||||||
|
"status = PLUGIN_PYTHON_NOT_INITIALIZED;",
|
||||||
|
"return PLUGIN_NO_CALLABLE;",
|
||||||
|
"status = PLUGIN_EXCEPTION;",
|
||||||
|
"if (status < PLUGIN_OK)",
|
||||||
|
]:
|
||||||
|
if needle not in python_plugin_shim:
|
||||||
|
raise SystemExit(f"PythonPlugin wasm shim missing disabled-python boundary: {needle}")
|
||||||
|
for needle in [
|
||||||
|
"PythonPlugin::PythonPlugin(struct _inittab*) reports PLUGIN_INITTAB_FAILED",
|
||||||
|
"PythonPlugin *plugin = PythonPlugin::instantiate(bad_modules);",
|
||||||
|
"plugin != nullptr",
|
||||||
|
"python_plugin->plugin_status() != PLUGIN_INITTAB_FAILED",
|
||||||
|
"python_plugin->usable()",
|
||||||
|
'python_plugin->last_errmsg() != "failed to initialize built-in module"',
|
||||||
|
]:
|
||||||
|
if needle not in python_plugin_inittab_probe:
|
||||||
|
raise SystemExit(f"PythonPlugin inittab probe missing first-caller status assertion: {needle}")
|
||||||
|
for needle in [
|
||||||
|
"[ PYTHON ] ; section comment",
|
||||||
|
"PLUGIN_NO_SECTION",
|
||||||
|
"PLUGIN_BAD_INIFILE",
|
||||||
|
"PLUGIN_BAD_PATH",
|
||||||
|
"PLUGIN_EXCEPTION_DURING_PATH_PREPEND",
|
||||||
|
"PLUGIN_EXCEPTION_DURING_PATH_APPEND",
|
||||||
|
"PLUGIN_PYTHON_NOT_INITIALIZED",
|
||||||
|
"PLUGIN_NO_CALLABLE",
|
||||||
|
"PLUGIN_EXCEPTION",
|
||||||
|
"handle_pyerror().empty()",
|
||||||
|
]:
|
||||||
|
if needle not in python_plugin_probe:
|
||||||
|
raise SystemExit(f"PythonPlugin probe missing disabled-python status assertion: {needle}")
|
||||||
|
for needle in [
|
||||||
|
"static PyTypeObject none_type = {\"NoneType\"};",
|
||||||
|
"static PyObject none_object = {&none_type};",
|
||||||
|
"PyObject *_Py_NoneStructPtr = &none_object;",
|
||||||
|
"int Py_IsInitialized(void)",
|
||||||
|
"return 1;",
|
||||||
|
"PyObject *PyErr_Occurred(void)",
|
||||||
|
"return nullptr;",
|
||||||
|
"void PyErr_Fetch(PyObject **exc, PyObject **val, PyObject **tb)",
|
||||||
|
"*exc = nullptr;",
|
||||||
|
"*val = nullptr;",
|
||||||
|
"*tb = nullptr;",
|
||||||
|
"int PyCallable_Check(PyObject *)",
|
||||||
|
"return 0;",
|
||||||
|
"PyObject *PyObject_CallMethod(PyObject *, char *, char *, ...)",
|
||||||
|
"PyObject *PyObject_GetAttrString(PyObject *, const char *)",
|
||||||
|
"return &none_object;",
|
||||||
|
"PyObject *Py_BuildValue(const char *, ...)",
|
||||||
|
"PyObject *PyModule_Create(PyModuleDef *)",
|
||||||
|
"int PyModule_AddObject(PyObject *, const char *, PyObject *)",
|
||||||
|
"int PyType_Ready(PyTypeObject *)",
|
||||||
|
"void *PyObject_NewShim(std::size_t size, PyTypeObject *type)",
|
||||||
|
"std::calloc(1, size)",
|
||||||
|
]:
|
||||||
|
if needle not in python_c_api_shim:
|
||||||
|
raise SystemExit(f"Python C API shim missing symbol boundary: {needle}")
|
||||||
|
|
||||||
|
rcs_print_shim = Path("core/wasm_shims/rcs_print_shim.cc").read_text(encoding="utf-8")
|
||||||
|
for needle in [
|
||||||
|
"set_print_rcs_error_info",
|
||||||
|
"print_rcs_error_new",
|
||||||
|
"std::vfprintf(stderr, format, args)",
|
||||||
|
]:
|
||||||
|
if needle not in rcs_print_shim:
|
||||||
|
raise SystemExit(f"RCS print shim missing split print-error boundary: {needle}")
|
||||||
|
|
||||||
|
rtapi_compat_shim = Path("core/wasm_shims/rtapi_compat.cc").read_text(encoding="utf-8")
|
||||||
|
for needle in [
|
||||||
|
"rtapi_snprintf",
|
||||||
|
"std::vsnprintf(buf, static_cast<std::size_t>(size), fmt, ap)",
|
||||||
|
]:
|
||||||
|
if needle not in rtapi_compat_shim:
|
||||||
|
raise SystemExit(f"RTAPI compatibility shim missing userspace snprintf boundary: {needle}")
|
||||||
|
|
||||||
|
for phrase in [
|
||||||
|
"must not add CNC behavior",
|
||||||
|
"must not expand the temporary smoke parser",
|
||||||
|
"CMake `linuxcnc_wasm_safe_probe_shims` set",
|
||||||
|
"RS274/WASM manifest",
|
||||||
|
"browser-safe LinuxCNC adaptations",
|
||||||
|
"LinuxCNC `interp_base.cc` dynamic loader calls",
|
||||||
|
"unavailable-loader returns",
|
||||||
|
"detached LinuxCNC `EMC_STAT` singleton",
|
||||||
|
"LinuxCNC `_()` diagnostic call sites",
|
||||||
|
"browser gettext catalogs unavailable",
|
||||||
|
"LinuxCNC NML status constructors",
|
||||||
|
"`RCS_STAT_MSG` default status fields",
|
||||||
|
"dynamic loading unavailable",
|
||||||
|
"unavailable HAL lookup",
|
||||||
|
"must leave HAL values unavailable",
|
||||||
|
"preview `_task=0`",
|
||||||
|
"builtin module stubs",
|
||||||
|
"must not switch browser-safe probes into task mode",
|
||||||
|
"single-word `wordexp()` path expansion",
|
||||||
|
"`wordfree()` cleanup",
|
||||||
|
"must not become a shell expansion feature",
|
||||||
|
"must not become Python execution",
|
||||||
|
"Python C API shim must return inert objects",
|
||||||
|
"must not call into CPython runtime",
|
||||||
|
"keeping Python execution disabled",
|
||||||
|
"must not execute `bp::exec`, `bp::exec_file`, or",
|
||||||
|
"inactive-DB return values",
|
||||||
|
"negative-status short-circuit behavior",
|
||||||
|
"first-caller `_inittab` `PLUGIN_INITTAB_FAILED` edge",
|
||||||
|
"preserve the `TOPLEVEL` missing-path `PLUGIN_BAD_PATH` edge",
|
||||||
|
"preserve `PATH_PREPEND` and `PATH_APPEND` tilde-expansion failure statuses",
|
||||||
|
"preserve LinuxCNC INI section-name trimming and trailing section-comment handling",
|
||||||
|
"LinuxCNC `rcs_print_error` split entry points",
|
||||||
|
"without native print routing",
|
||||||
|
"LinuxCNC userspace `rtapi_snprintf()` formatting",
|
||||||
|
"`uspace_common.h` `vsnprintf()` implementation path",
|
||||||
|
"./check-linuxcnc-wasm-shims-source-map.sh",
|
||||||
|
"does not interpret G-code",
|
||||||
|
]:
|
||||||
|
if phrase not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-wasm-shims-source-map.md missing boundary phrase: {phrase}")
|
||||||
|
|
||||||
|
for entry in [
|
||||||
|
"test-native.sh",
|
||||||
|
"test-linuxcnc-source-link.sh",
|
||||||
|
"build-wasm.sh",
|
||||||
|
]:
|
||||||
|
text = Path(entry).read_text(encoding="utf-8")
|
||||||
|
if "./check-linuxcnc-wasm-shims-source-map.sh" not in text:
|
||||||
|
raise SystemExit(f"{entry} must run ./check-linuxcnc-wasm-shims-source-map.sh")
|
||||||
|
|
||||||
|
cmake_text = Path("core/CMakeLists.txt").read_text(encoding="utf-8")
|
||||||
|
for shim_path in shim_paths:
|
||||||
|
cmake_suffix = shim_path.removeprefix("core/")
|
||||||
|
if cmake_suffix not in cmake_text:
|
||||||
|
raise SystemExit(f"{shim_path} is not listed in linuxcnc_wasm_safe_probe_shims")
|
||||||
|
|
||||||
|
blocker_map = Path("docs/linuxcnc-wasm-blockers-source-map.md").read_text(encoding="utf-8")
|
||||||
|
for shim_path in [
|
||||||
|
"core/wasm_shims/linuxcnc_runtime_shim.cc",
|
||||||
|
"core/wasm_shims/python_c_api_shim.cc",
|
||||||
|
"core/wasm_shims/tooldata/tooldata_mmap_backend.cc",
|
||||||
|
]:
|
||||||
|
if shim_path not in blocker_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-wasm-blockers-source-map.md no longer references {shim_path}")
|
||||||
|
PY
|
||||||
204
check-linuxcnc-wasm-smoke-source-map.sh
Executable file
204
check-linuxcnc-wasm-smoke-source-map.sh
Executable file
@@ -0,0 +1,204 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: this guard ties Node/browser WASM smoke coverage to
|
||||||
|
# LinuxCNC RS274 parameter/INI handling, M-code canon side effects, generated
|
||||||
|
# switchkins/remap config cases, kinematics sources, and OPFS-only browser
|
||||||
|
# persistence. It validates smoke-test source coverage only; it does not add
|
||||||
|
# CNC behavior, expand smoke parsing, or interpret G-code.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
grep -F 'int Interp::ini_load(const char *filename)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'int Interp::restore_parameters(const char *filename)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'int Interp::save_parameters(const char *filename,' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'std::string tempfile = std::string(filename) + ".new";' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'unlink(bakfile.c_str());' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'if(link(filename, bakfile.c_str()) < 0)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'if(rename(tempfile.c_str(), filename) < 0)' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'read_text(command, _setup.file_pointer, _setup.linetext,' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'int read_text(const char *command, FILE * inport, char *raw_line,' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_interp.hh" >/dev/null
|
||||||
|
|
||||||
|
grep -F 'int Interp::convert_m(block_pointer block' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_convert.cc" >/dev/null
|
||||||
|
grep -F 'int ret = WAIT(round_to_int(block->p_number), DIGITAL_INPUT, type, timeout);' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_convert.cc" >/dev/null
|
||||||
|
grep -F 'SET_AUX_OUTPUT_VALUE(round_to_int(block->e_number), block->q_number);' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_convert.cc" >/dev/null
|
||||||
|
grep -F 'extern int WAIT(int index' "$linuxcnc_root/src/emc/nml_intf/canon.hh" >/dev/null
|
||||||
|
grep -F 'extern void SET_AUX_OUTPUT_VALUE(int index, double value);' \
|
||||||
|
"$linuxcnc_root/src/emc/nml_intf/canon.hh" >/dev/null
|
||||||
|
|
||||||
|
grep -F 'kp->kinsname = "5axiskins";' "$linuxcnc_root/src/emc/kinematics/5axiskins.c" >/dev/null
|
||||||
|
grep -F 'int xyzbcKinematicsInverse(const EmcPose * pos' \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics/trtfuncs.c" >/dev/null
|
||||||
|
grep -F 'int xyzacKinematicsInverse(const EmcPose * pos' \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics/trtfuncs.c" >/dev/null
|
||||||
|
grep -F '*kinv1 = xyzacKinematicsInverse;' \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics/xyzac-trt-kins.c" >/dev/null
|
||||||
|
grep -F '*kinv1 = xyzbcKinematicsInverse;' \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics/xyzbc-trt-kins.c" >/dev/null
|
||||||
|
grep -F 'int userkKinematicsInverse(const EmcPose * pos' \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics/userkfuncs.c" >/dev/null
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC WASM smoke source map' docs/linuxcnc-wasm-smoke-source-map.md >/dev/null
|
||||||
|
grep -F 'must not expand the temporary smoke parser' docs/linuxcnc-wasm-smoke-source-map.md >/dev/null
|
||||||
|
grep -F 'OPFS-only' docs/linuxcnc-wasm-smoke-source-map.md >/dev/null
|
||||||
|
grep -F '`src/emc/rs274ngc/interp_convert.cc` provides `convert_m()` coverage' \
|
||||||
|
docs/linuxcnc-wasm-smoke-source-map.md >/dev/null
|
||||||
|
grep -F 'unlinking `filename + ".bak"`' docs/linuxcnc-wasm-smoke-source-map.md >/dev/null
|
||||||
|
grep -F '`src/emc/kinematics/5axiskins.c`, `src/emc/kinematics/trtfuncs.c`' \
|
||||||
|
docs/linuxcnc-wasm-smoke-source-map.md >/dev/null
|
||||||
|
grep -F 'Generated switchkins config smoke cases must continue to come from' \
|
||||||
|
docs/linuxcnc-wasm-smoke-source-map.md >/dev/null
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC source basis: Node smoke only verifies the wasm/API bridge around' \
|
||||||
|
test-web-wasm-node-smoke.sh >/dev/null
|
||||||
|
grep -F 'minimum_steps=${WASM_NODE_SMOKE_MIN_STEPS:-50}' test-web-wasm-node-smoke.sh >/dev/null
|
||||||
|
grep -F 'WASM Node smoke covered $passed_steps steps, expected at least $minimum_steps' \
|
||||||
|
test-web-wasm-node-smoke.sh >/dev/null
|
||||||
|
grep -F 'expected Node wasm-core wrapper to leave OPFS disabled' test-web-wasm-node-smoke.cjs >/dev/null
|
||||||
|
grep -F 'expected Node wasm-core parseFile to require OPFS' test-web-wasm-node-smoke.cjs >/dev/null
|
||||||
|
grep -F 'linuxcnc_switchkins_remap_config_cases.json' test-web-wasm-node-smoke.cjs >/dev/null
|
||||||
|
grep -F 'expected LinuxCNC WASM M68 E3 Q${kinstype} remap side effect' \
|
||||||
|
test-web-wasm-node-smoke.cjs >/dev/null
|
||||||
|
grep -F 'expected LinuxCNC WASM M66 E0 L0 remap side effect' \
|
||||||
|
test-web-wasm-node-smoke.cjs >/dev/null
|
||||||
|
grep -F 'expected LinuxCNC WASM 5axiskins RTCP pivot from LinuxCNC 5axiskins inverse' \
|
||||||
|
test-web-wasm-node-smoke.cjs >/dev/null
|
||||||
|
grep -F 'expected LinuxCNC WASM configured xyzbc-trt RTCP pivot from LinuxCNC trtfuncs inverse' \
|
||||||
|
test-web-wasm-node-smoke.cjs >/dev/null
|
||||||
|
grep -F 'expected LinuxCNC WASM configured xyzac-trt RTCP pivot from LinuxCNC xyzab_tdr inverse' \
|
||||||
|
test-web-wasm-node-smoke.cjs >/dev/null
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC source basis: browser smoke verifies OPFS-backed wasm/API/app flows' \
|
||||||
|
test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'minimum_sections=${BROWSER_SMOKE_MIN_SECTIONS:-50}' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'BROWSER_SMOKE_MIN_SECTIONS must be a positive integer' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'browser WASM smoke covered $passed_sections sections, expected at least $minimum_sections' \
|
||||||
|
test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'required_browser_sections = {' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'runSection("linuxcnc generated switchkins cases load"' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'runSection("opfs parameter restore in new instance"' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'runSection("opfs directory persist and load"' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'runSection("browser opfs policy"' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'runSection("browser app opfs restore"' test-web-wasm-browser-smoke.sh >/dev/null
|
||||||
|
grep -F 'runLinuxCncBrowserSections(context, simulator)' web/test-browser-wasm-smoke-sections.js >/dev/null
|
||||||
|
grep -F 'runBrowserOpfsWorkspaceSections(context, simulator)' web/test-browser-wasm-smoke-sections.js >/dev/null
|
||||||
|
grep -F 'runBrowserOpfsPolicySections(context)' web/test-browser-wasm-smoke-sections.js >/dev/null
|
||||||
|
grep -F 'runBrowserAppOpfsSections(context)' web/test-browser-wasm-smoke-sections.js >/dev/null
|
||||||
|
grep -F 'runBrowserOpfsBasicSections(context, simulator)' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null
|
||||||
|
grep -F 'runBrowserOpfsParameterSections(context, simulator)' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null
|
||||||
|
grep -F 'runBrowserOpfsMirrorSections(context, simulator)' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null
|
||||||
|
grep -F 'runBrowserOpfsDirectorySections(context, simulator)' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null
|
||||||
|
grep -F 'linuxcnc_switchkins_remap_config_cases.json' \
|
||||||
|
web/test-browser-wasm-smoke-linuxcnc-sections.js >/dev/null
|
||||||
|
grep -F 'missing LinuxCNC switchkins config cases after INI_FILE_NAME remap-load filtering' \
|
||||||
|
web/test-browser-wasm-smoke-linuxcnc-sections.js >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: rs274ngc_pre.cc restore_parameters()' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-parameter-sections.js >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: rs274ngc_pre.cc save_parameters()' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-parameter-sections.js >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: rs274ngc_pre.cc read_text() reads' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-basic-sections.js >/dev/null
|
||||||
|
grep -F 'runSection("opfs directory persist and load"' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-directory-sections.js >/dev/null
|
||||||
|
grep -F 'runSection("opfs metadata queries avoid wasm mirror pollution"' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-directory-sections.js >/dev/null
|
||||||
|
grep -F 'runSection("browser opfs policy"' \
|
||||||
|
web/test-browser-wasm-smoke-opfs-policy-sections.js >/dev/null
|
||||||
|
grep -F 'app frame did not persist current program into OPFS' \
|
||||||
|
web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
||||||
|
grep -F 'app frame did not persist LinuxCNC parameter backup into OPFS' \
|
||||||
|
web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
||||||
|
grep -F 'app frame did not clean up LinuxCNC temporary parameter file in OPFS' \
|
||||||
|
web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
||||||
|
|
||||||
|
if grep -R -n -E 'localStorage|sessionStorage|indexedDB|showOpenFilePicker|showSaveFilePicker|showDirectoryPicker|webkitRequestFileSystem|FileReader' web/src; then
|
||||||
|
echo "browser app/wasm code must not add filesystem persistence outside OPFS" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if grep -n -E 'localStorage|sessionStorage|indexedDB|showOpenFilePicker|showSaveFilePicker|showDirectoryPicker|webkitRequestFileSystem|FileReader' \
|
||||||
|
web/test-browser-wasm-smoke-*.js \
|
||||||
|
web/test-browser-wasm-smoke.html \
|
||||||
|
test-web-wasm-browser-smoke.sh; then
|
||||||
|
echo "browser WASM smoke harness must not add filesystem persistence outside OPFS" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
python3 - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
|
||||||
|
source_map = Path("docs/linuxcnc-wasm-smoke-source-map.md").read_text(encoding="utf-8")
|
||||||
|
json_cases = json.loads(Path("web/public/linuxcnc_switchkins_remap_config_cases.json").read_text(encoding="utf-8"))
|
||||||
|
if not isinstance(json_cases, list) or len(json_cases) == 0:
|
||||||
|
raise SystemExit("generated LinuxCNC switchkins browser config cases are missing")
|
||||||
|
|
||||||
|
node_wrapper = Path("test-web-wasm-node-smoke.sh").read_text(encoding="utf-8")
|
||||||
|
browser_wrapper = Path("test-web-wasm-browser-smoke.sh").read_text(encoding="utf-8")
|
||||||
|
node_min = re.search(r"minimum_steps=\$\{WASM_NODE_SMOKE_MIN_STEPS:-(\d+)\}", node_wrapper)
|
||||||
|
browser_min = re.search(r"minimum_sections=\$\{BROWSER_SMOKE_MIN_SECTIONS:-(\d+)\}", browser_wrapper)
|
||||||
|
if not node_min or int(node_min.group(1)) < 50:
|
||||||
|
raise SystemExit("Node WASM smoke minimum step threshold is missing or below 50")
|
||||||
|
if not browser_min or int(browser_min.group(1)) < 50:
|
||||||
|
raise SystemExit("browser WASM smoke minimum section threshold is missing or below 50")
|
||||||
|
|
||||||
|
for path in [
|
||||||
|
"test-web-wasm-node-smoke.sh",
|
||||||
|
"test-web-wasm-node-smoke.cjs",
|
||||||
|
"test-web-wasm-browser-smoke.sh",
|
||||||
|
"web/test-browser-wasm-smoke-linuxcnc-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-opfs-workspace-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-opfs-basic-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-opfs-parameter-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-opfs-mirror-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-opfs-directory-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-opfs-policy-sections.js",
|
||||||
|
"web/test-browser-wasm-smoke-app-sections.js",
|
||||||
|
]:
|
||||||
|
if f"| `{path}` |" not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-wasm-smoke-source-map.md missing smoke entry: {path}")
|
||||||
|
|
||||||
|
required_phrases = [
|
||||||
|
"must not add CNC behavior",
|
||||||
|
"must not expand the temporary smoke parser",
|
||||||
|
"persistence OPFS-only",
|
||||||
|
"Node smoke must leave OPFS disabled",
|
||||||
|
"Browser smoke harness files must not use Local Storage",
|
||||||
|
"Generated switchkins config smoke cases",
|
||||||
|
"browser smoke shell guard also pins required section names",
|
||||||
|
"OPFS workspace/policy/directory handling",
|
||||||
|
'unlinking `filename + ".bak"`',
|
||||||
|
"./check-linuxcnc-wasm-smoke-source-map.sh",
|
||||||
|
"does not interpret G-code",
|
||||||
|
]
|
||||||
|
for phrase in required_phrases:
|
||||||
|
if phrase not in source_map:
|
||||||
|
raise SystemExit(f"docs/linuxcnc-wasm-smoke-source-map.md missing boundary phrase: {phrase}")
|
||||||
|
|
||||||
|
for entry in [
|
||||||
|
"test-native.sh",
|
||||||
|
"test-linuxcnc-source-link.sh",
|
||||||
|
"build-wasm.sh",
|
||||||
|
]:
|
||||||
|
text = Path(entry).read_text(encoding="utf-8")
|
||||||
|
if "./check-linuxcnc-wasm-smoke-source-map.sh" not in text:
|
||||||
|
raise SystemExit(f"{entry} must run ./check-linuxcnc-wasm-smoke-source-map.sh")
|
||||||
|
PY
|
||||||
132
check-linuxcnc-workstreams-source-map.sh
Executable file
132
check-linuxcnc-workstreams-source-map.sh
Executable file
@@ -0,0 +1,132 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: this guard ties the six active workstream contexts to
|
||||||
|
# their source-map guards and to LinuxCNC source/config anchors. It validates
|
||||||
|
# coordination policy only; it does not add CNC behavior or expand smoke
|
||||||
|
# parsing.
|
||||||
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||||
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
|
grep -F '1. `switchkins/remap` generator and tables' docs/architecture.md >/dev/null
|
||||||
|
grep -F '2. `linuxcnc-kinematics` source manifest' docs/architecture.md >/dev/null
|
||||||
|
grep -F '3. WASM filesystem and OPFS persistence' docs/architecture.md >/dev/null
|
||||||
|
grep -F '4. browser app integration' docs/architecture.md >/dev/null
|
||||||
|
grep -F '5. Node and browser smoke coverage' docs/architecture.md >/dev/null
|
||||||
|
grep -F '6. source-link, build, and documentation constraints' docs/architecture.md >/dev/null
|
||||||
|
grep -F 'The synchronized source-map guard for these contexts is' docs/architecture.md >/dev/null
|
||||||
|
grep -F '`docs/linuxcnc-workstreams-source-map.md`.' docs/architecture.md >/dev/null
|
||||||
|
|
||||||
|
grep -F 'REMAP = M428' "$linuxcnc_root/configs/sim/axis/vismach/5axis/bridgemill/5axis.ini" >/dev/null
|
||||||
|
grep -F '#<kinstype>' "$linuxcnc_root/configs/sim/axis/vismach/5axis/bridgemill/remap_subs/428remap.ngc" >/dev/null
|
||||||
|
grep -F 'GENSERKINSSRCS := emc/kinematics/ugenserkins.c' \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics/Submakefile" >/dev/null
|
||||||
|
grep -F 'extern int kinematicsInverse(const struct EmcPose * world,' \
|
||||||
|
"$linuxcnc_root/src/emc/kinematics/kinematics.h" >/dev/null
|
||||||
|
grep -F '#define RS274NGC_PARAMETER_FILE_NAME_DEFAULT "rs274ngc.var"' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/interp_internal.hh" >/dev/null
|
||||||
|
grep -F 'int Interp::save_parameters(const char *filename,' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
||||||
|
grep -F 'LIBRS274SRCS := $(addprefix emc/rs274ngc/,' \
|
||||||
|
"$linuxcnc_root/src/emc/rs274ngc/Submakefile" >/dev/null
|
||||||
|
grep -F 'LIBTOOLDATA_SRCS += emc/tooldata/tooldata_common.cc' \
|
||||||
|
"$linuxcnc_root/src/emc/tooldata/Submakefile" >/dev/null
|
||||||
|
grep -F 'LIBLCNCINISRCS := emc/ini/inifile.cc' \
|
||||||
|
"$linuxcnc_root/src/emc/ini/Submakefile" >/dev/null
|
||||||
|
grep -F 'LIBPPSRCS := $(addprefix emc/pythonplugin/,' \
|
||||||
|
"$linuxcnc_root/src/emc/pythonplugin/Submakefile" >/dev/null
|
||||||
|
|
||||||
|
grep -F 'LinuxCNC workstreams source map' docs/linuxcnc-workstreams-source-map.md >/dev/null
|
||||||
|
grep -F 'must not add CNC' docs/linuxcnc-workstreams-source-map.md >/dev/null
|
||||||
|
grep -F 'temporary smoke parser' docs/linuxcnc-workstreams-source-map.md >/dev/null
|
||||||
|
grep -F 'Every active workstream must have at least one source-map document and guard' \
|
||||||
|
docs/linuxcnc-workstreams-source-map.md >/dev/null
|
||||||
|
grep -F 'docs/linuxcnc-source-policy.md` must keep the same one-context workflow' \
|
||||||
|
docs/linuxcnc-workstreams-source-map.md >/dev/null
|
||||||
|
grep -F 'Browser filesystem persistence remains OPFS-only.' docs/linuxcnc-workstreams-source-map.md >/dev/null
|
||||||
|
grep -F 'Smoke coverage remains verification only' docs/linuxcnc-workstreams-source-map.md >/dev/null
|
||||||
|
grep -F 'Keep the change inside one active workstream context unless a dependency is' \
|
||||||
|
docs/linuxcnc-source-policy.md >/dev/null
|
||||||
|
grep -F 'Each pass should advance one reasonable, reviewable context.' \
|
||||||
|
docs/linuxcnc-source-policy.md >/dev/null
|
||||||
|
grep -F 'Keep the six active workstream contexts synchronized with' \
|
||||||
|
docs/linuxcnc-source-policy.md >/dev/null
|
||||||
|
grep -F '`docs/linuxcnc-workstreams-source-map.md` so source-map guards' \
|
||||||
|
docs/linuxcnc-source-policy.md >/dev/null
|
||||||
|
grep -F 'Smoke tests are verification guardrails. They must not be expanded with new' \
|
||||||
|
docs/linuxcnc-source-policy.md >/dev/null
|
||||||
|
grep -F 'Do not mix generator/table work, manifests, OPFS/browser work, and build' \
|
||||||
|
docs/linuxcnc-source-policy.md >/dev/null
|
||||||
|
grep -F 'Browser-side wasm filesystem behavior must use OPFS-backed storage.' \
|
||||||
|
docs/linuxcnc-source-policy.md >/dev/null
|
||||||
|
|
||||||
|
python3 - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
doc = Path("docs/linuxcnc-workstreams-source-map.md").read_text(encoding="utf-8")
|
||||||
|
policy = Path("docs/linuxcnc-source-policy.md").read_text(encoding="utf-8")
|
||||||
|
expected = {
|
||||||
|
"switchkins/remap": [
|
||||||
|
"docs/linuxcnc-switchkins-remap-source-map.md",
|
||||||
|
"check-linuxcnc-switchkins-remap-source-map.sh",
|
||||||
|
],
|
||||||
|
"linuxcnc-kinematics": [
|
||||||
|
"docs/linuxcnc-kinematics-source-map.md",
|
||||||
|
"check-linuxcnc-kinematics-source-map.sh",
|
||||||
|
],
|
||||||
|
"WASM filesystem and OPFS persistence": [
|
||||||
|
"docs/linuxcnc-opfs-source-map.md",
|
||||||
|
"docs/linuxcnc-wasm-shims-source-map.md",
|
||||||
|
"docs/linuxcnc-wasm-blockers-source-map.md",
|
||||||
|
"docs/linuxcnc-tooldata-source-map.md",
|
||||||
|
"check-linuxcnc-opfs-source-map.sh",
|
||||||
|
"check-linuxcnc-wasm-shims-source-map.sh",
|
||||||
|
"check-linuxcnc-wasm-blockers-source-map.sh",
|
||||||
|
"check-linuxcnc-tooldata-source-map.sh",
|
||||||
|
],
|
||||||
|
"browser app integration": [
|
||||||
|
"docs/linuxcnc-browser-app-source-map.md",
|
||||||
|
"check-linuxcnc-browser-app-source-map.sh",
|
||||||
|
],
|
||||||
|
"Node and browser smoke coverage": [
|
||||||
|
"docs/linuxcnc-wasm-smoke-source-map.md",
|
||||||
|
"check-linuxcnc-wasm-smoke-source-map.sh",
|
||||||
|
],
|
||||||
|
"source-link, build, and documentation constraints": [
|
||||||
|
"docs/linuxcnc-rs274-source-map.md",
|
||||||
|
"docs/linuxcnc-build-source-map.md",
|
||||||
|
"docs/linuxcnc-tooldata-source-map.md",
|
||||||
|
"check-linuxcnc-rs274-source-map.sh",
|
||||||
|
"check-linuxcnc-build-source-map.sh",
|
||||||
|
"check-linuxcnc-tooldata-source-map.sh",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
for workstream, paths in expected.items():
|
||||||
|
if workstream not in doc:
|
||||||
|
raise SystemExit(f"missing workstream row in docs/linuxcnc-workstreams-source-map.md: {workstream}")
|
||||||
|
policy_terms = {
|
||||||
|
"switchkins/remap": ["switchkins/remap", "M428/M429/M430"],
|
||||||
|
"linuxcnc-kinematics": ["kinematics manifest", "RTCP coverage"],
|
||||||
|
"WASM filesystem and OPFS persistence": ["OPFS", "filesystem"],
|
||||||
|
"browser app integration": ["Browser app", "wasm bridge"],
|
||||||
|
"Node and browser smoke coverage": ["Smoke tests are verification guardrails", "temporary smoke parser"],
|
||||||
|
"source-link, build, and documentation constraints": ["source-link", "build-policy"],
|
||||||
|
}[workstream]
|
||||||
|
if not any(term in policy for term in policy_terms):
|
||||||
|
raise SystemExit(f"docs/linuxcnc-source-policy.md no longer references workstream boundary: {workstream}")
|
||||||
|
for path in paths:
|
||||||
|
if path not in doc:
|
||||||
|
raise SystemExit(f"missing source-map path in workstream index: {path}")
|
||||||
|
if not Path(path).exists():
|
||||||
|
raise SystemExit(f"source-map path listed in workstream index does not exist: {path}")
|
||||||
|
if path.startswith("check-") and not Path(path).stat().st_mode & 0o111:
|
||||||
|
raise SystemExit(f"source-map guard is not executable: {path}")
|
||||||
|
|
||||||
|
for test_entry in ["test-native.sh", "test-linuxcnc-source-link.sh", "build-wasm.sh"]:
|
||||||
|
text = Path(test_entry).read_text(encoding="utf-8")
|
||||||
|
for guard in sorted({path for paths in expected.values() for path in paths if path.startswith("check-")}):
|
||||||
|
if f"./{guard}" not in text:
|
||||||
|
raise SystemExit(f"{test_entry} does not run workstream source-map guard: {guard}")
|
||||||
|
PY
|
||||||
@@ -1,31 +1,224 @@
|
|||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
project(cnc_sim_wasm_core LANGUAGES CXX)
|
project(cnc_sim_wasm_core LANGUAGES C CXX)
|
||||||
|
|
||||||
option(CNC_SIM_ENABLE_LINUXCNC_BRIDGE "Build the experimental LinuxCNC canon bridge" OFF)
|
option(CNC_SIM_ENABLE_LINUXCNC_BRIDGE "Build the experimental LinuxCNC canon bridge" OFF)
|
||||||
option(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND "Build the native LinuxCNC librs274 backend" OFF)
|
option(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND "Build the native LinuxCNC librs274 backend" OFF)
|
||||||
|
option(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE "Compile the browser-safe subset of LinuxCNC rs274 sources" OFF)
|
||||||
|
option(CNC_SIM_ENABLE_SMOKE_BACKEND "Build the legacy explicit smoke G-code backend test harness" OFF)
|
||||||
|
if(CNC_SIM_ENABLE_SMOKE_BACKEND AND CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||||
|
message(FATAL_ERROR "CNC_SIM_ENABLE_SMOKE_BACKEND cannot be combined with CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE")
|
||||||
|
endif()
|
||||||
set(CNC_SIM_LINUXCNC_ROOT "" CACHE PATH "LinuxCNC source root for the experimental bridge")
|
set(CNC_SIM_LINUXCNC_ROOT "" CACHE PATH "LinuxCNC source root for the experimental bridge")
|
||||||
|
set(CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/../linuxcnc-rs274-wasm-source-files.txt"
|
||||||
|
CACHE FILEPATH
|
||||||
|
"Manifest that partitions LinuxCNC rs274 sources into wasm-safe core and blocked groups"
|
||||||
|
)
|
||||||
|
|
||||||
set(cnc_sim_core_sources
|
set(cnc_sim_core_sources
|
||||||
src/canon_event_sink.cpp
|
src/canon_event_sink.cpp
|
||||||
src/cnc_sim_api.cpp
|
src/cnc_sim_api.cpp
|
||||||
src/gcode_backend.cpp
|
src/gcode_backend.cpp
|
||||||
|
src/linuxcnc_5axiskins_adapter.c
|
||||||
|
src/linuxcnc_5axiskins_adapter.cpp
|
||||||
|
src/linuxcnc_corexykins_adapter.c
|
||||||
|
src/linuxcnc_corexykins_adapter.cpp
|
||||||
|
src/linuxcnc_cubic_adapter.c
|
||||||
|
src/linuxcnc_cubic_adapter.cpp
|
||||||
|
src/linuxcnc_genserfuncs_adapter.c
|
||||||
|
src/linuxcnc_genserfuncs_adapter.cpp
|
||||||
|
src/linuxcnc_genhexkins_adapter.c
|
||||||
|
src/linuxcnc_genhexkins_adapter.cpp
|
||||||
|
src/linuxcnc_kins_util_adapter.c
|
||||||
|
src/linuxcnc_kins_util_adapter.cpp
|
||||||
|
src/linuxcnc_lineardeltakins_adapter.c
|
||||||
|
src/linuxcnc_lineardeltakins_adapter.cpp
|
||||||
|
src/linuxcnc_maxkins_adapter.c
|
||||||
|
src/linuxcnc_maxkins_adapter.cpp
|
||||||
|
src/linuxcnc_pentakins_adapter.c
|
||||||
|
src/linuxcnc_pentakins_adapter.cpp
|
||||||
|
src/linuxcnc_pumakins_adapter.c
|
||||||
|
src/linuxcnc_pumakins_adapter.cpp
|
||||||
|
src/linuxcnc_rotatekins_adapter.c
|
||||||
|
src/linuxcnc_rotatekins_adapter.cpp
|
||||||
|
src/linuxcnc_rosekins_adapter.c
|
||||||
|
src/linuxcnc_rosekins_adapter.cpp
|
||||||
|
src/linuxcnc_rotarydeltakins_adapter.c
|
||||||
|
src/linuxcnc_rotarydeltakins_adapter.cpp
|
||||||
|
src/linuxcnc_scarakins_adapter.c
|
||||||
|
src/linuxcnc_scarakins_adapter.cpp
|
||||||
|
src/linuxcnc_scorbot_kins_adapter.c
|
||||||
|
src/linuxcnc_scorbot_kins_adapter.cpp
|
||||||
|
src/linuxcnc_tripodkins_adapter.c
|
||||||
|
src/linuxcnc_tripodkins_adapter.cpp
|
||||||
|
src/linuxcnc_trtfuncs_adapter.c
|
||||||
|
src/linuxcnc_trtfuncs_adapter.cpp
|
||||||
|
src/linuxcnc_userkfuncs_adapter.c
|
||||||
|
src/linuxcnc_userkfuncs_adapter.cpp
|
||||||
|
src/linuxcnc_xyzab_tdr_kins_adapter.c
|
||||||
|
src/linuxcnc_xyzab_tdr_kins_adapter.cpp
|
||||||
src/rtcp_kinematics.cpp
|
src/rtcp_kinematics.cpp
|
||||||
src/simulator_gcode_controls.cpp
|
src/simulator_gcode_controls.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(cnc_sim_smoke_backend_sources
|
||||||
src/smoke_gcode_parser.cpp
|
src/smoke_gcode_parser.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(cnc_sim_linuxcnc_rs274_backend_sources
|
||||||
|
src/linuxcnc_canon_bridge.cpp
|
||||||
|
src/linuxcnc_rs274_backend.cpp
|
||||||
|
src/linuxcnc_tooldata_fixture.cpp
|
||||||
|
)
|
||||||
|
|
||||||
if(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
if(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
||||||
|
if(CNC_SIM_ENABLE_SMOKE_BACKEND)
|
||||||
|
message(FATAL_ERROR "CNC_SIM_ENABLE_SMOKE_BACKEND cannot be combined with CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND")
|
||||||
|
endif()
|
||||||
if(EMSCRIPTEN)
|
if(EMSCRIPTEN)
|
||||||
message(FATAL_ERROR "CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND is native-only; it links LinuxCNC librs274")
|
message(FATAL_ERROR "CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND is native-only; it links LinuxCNC librs274")
|
||||||
endif()
|
endif()
|
||||||
if(NOT CNC_SIM_LINUXCNC_ROOT)
|
if(NOT CNC_SIM_LINUXCNC_ROOT)
|
||||||
message(FATAL_ERROR "Set CNC_SIM_LINUXCNC_ROOT to the LinuxCNC source root")
|
message(FATAL_ERROR "Set CNC_SIM_LINUXCNC_ROOT to the LinuxCNC source root")
|
||||||
endif()
|
endif()
|
||||||
list(APPEND cnc_sim_core_sources
|
list(APPEND cnc_sim_core_sources ${cnc_sim_linuxcnc_rs274_backend_sources})
|
||||||
src/linuxcnc_canon_bridge.cpp
|
elseif(CNC_SIM_ENABLE_SMOKE_BACKEND)
|
||||||
src/linuxcnc_rs274_backend.cpp
|
list(APPEND cnc_sim_core_sources ${cnc_sim_smoke_backend_sources})
|
||||||
src/linuxcnc_tooldata_fixture.cpp
|
endif()
|
||||||
|
|
||||||
|
if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||||
|
if(NOT CNC_SIM_LINUXCNC_ROOT)
|
||||||
|
message(FATAL_ERROR "Set CNC_SIM_LINUXCNC_ROOT to the LinuxCNC source root")
|
||||||
|
endif()
|
||||||
|
get_filename_component(CNC_SIM_LINUXCNC_ROOT_ABS
|
||||||
|
"${CNC_SIM_LINUXCNC_ROOT}"
|
||||||
|
ABSOLUTE
|
||||||
|
BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.."
|
||||||
)
|
)
|
||||||
|
if(NOT IS_DIRECTORY "${CNC_SIM_LINUXCNC_ROOT_ABS}")
|
||||||
|
message(FATAL_ERROR "LinuxCNC source root does not exist: ${CNC_SIM_LINUXCNC_ROOT_ABS}")
|
||||||
|
endif()
|
||||||
|
if(NOT EXISTS "${CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST}")
|
||||||
|
message(FATAL_ERROR "Missing LinuxCNC wasm source manifest: ${CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST}")
|
||||||
|
endif()
|
||||||
|
if(IS_DIRECTORY "${CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST}")
|
||||||
|
message(FATAL_ERROR "LinuxCNC wasm source manifest is not a file: ${CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(linuxcnc_wasm_safe_probe_sources)
|
||||||
|
set(linuxcnc_wasm_blocked_sources)
|
||||||
|
file(STRINGS "${CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST}" linuxcnc_wasm_manifest_lines)
|
||||||
|
foreach(manifest_line IN LISTS linuxcnc_wasm_manifest_lines)
|
||||||
|
string(STRIP "${manifest_line}" manifest_line)
|
||||||
|
if(manifest_line STREQUAL "" OR manifest_line MATCHES "^#")
|
||||||
|
continue()
|
||||||
|
endif()
|
||||||
|
if(NOT manifest_line MATCHES "^([^:]+):([^:]+):(.*)$")
|
||||||
|
message(FATAL_ERROR "Bad LinuxCNC wasm source manifest line: ${manifest_line}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(manifest_group "${CMAKE_MATCH_1}")
|
||||||
|
set(manifest_path "${CMAKE_MATCH_2}")
|
||||||
|
if(NOT manifest_group STREQUAL "core"
|
||||||
|
AND NOT manifest_group STREQUAL "blocked"
|
||||||
|
AND NOT manifest_group STREQUAL "header"
|
||||||
|
AND NOT manifest_group STREQUAL "metadata"
|
||||||
|
AND NOT manifest_group STREQUAL "blocked-header")
|
||||||
|
message(FATAL_ERROR "Unknown LinuxCNC wasm source manifest group: ${manifest_group}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(manifest_source "${CNC_SIM_LINUXCNC_ROOT_ABS}/${manifest_path}")
|
||||||
|
if(NOT EXISTS "${manifest_source}")
|
||||||
|
message(FATAL_ERROR "LinuxCNC wasm manifest source does not exist: ${manifest_source}")
|
||||||
|
endif()
|
||||||
|
if(IS_DIRECTORY "${manifest_source}")
|
||||||
|
message(FATAL_ERROR "LinuxCNC wasm manifest source is not a file: ${manifest_source}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(manifest_group STREQUAL "core")
|
||||||
|
list(APPEND linuxcnc_wasm_safe_probe_sources "${manifest_source}")
|
||||||
|
elseif(manifest_group STREQUAL "blocked")
|
||||||
|
list(APPEND linuxcnc_wasm_blocked_sources "${manifest_source}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
list(LENGTH linuxcnc_wasm_safe_probe_sources linuxcnc_wasm_safe_probe_source_count)
|
||||||
|
list(LENGTH linuxcnc_wasm_blocked_sources linuxcnc_wasm_blocked_source_count)
|
||||||
|
if(linuxcnc_wasm_safe_probe_source_count EQUAL 0)
|
||||||
|
message(FATAL_ERROR "LinuxCNC wasm source manifest has no core entries")
|
||||||
|
endif()
|
||||||
|
if(linuxcnc_wasm_blocked_source_count EQUAL 0)
|
||||||
|
message(FATAL_ERROR "LinuxCNC wasm source manifest has no blocked entries")
|
||||||
|
endif()
|
||||||
|
message(STATUS "LinuxCNC wasm-safe core sources: ${linuxcnc_wasm_safe_probe_source_count}")
|
||||||
|
message(STATUS "LinuxCNC wasm blocked sources: ${linuxcnc_wasm_blocked_source_count}")
|
||||||
|
|
||||||
|
set(cnc_sim_wasm_safe_preinclude_options "SHELL:-include wctype.h")
|
||||||
|
set(cnc_sim_wasm_safe_section_options -ffunction-sections -fdata-sections)
|
||||||
|
set(cnc_sim_wasm_safe_link_options "-Wl,--gc-sections")
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
list(APPEND cnc_sim_wasm_safe_preinclude_options "SHELL:-include libgen.h")
|
||||||
|
find_path(CNC_SIM_FMT_INCLUDE_DIR fmt/format.h
|
||||||
|
PATHS /usr/include /usr/local/include
|
||||||
|
NO_CMAKE_FIND_ROOT_PATH
|
||||||
|
REQUIRED
|
||||||
|
)
|
||||||
|
list(APPEND cnc_sim_wasm_safe_preinclude_options "SHELL:-idirafter ${CNC_SIM_FMT_INCLUDE_DIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(linuxcnc_wasm_safe_probe_shims
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/dlfcn.cc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/emc_status_shim.cc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/gettext_shim.cc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/linuxcnc_runtime_shim.cc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/nml_status_shim.cc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/python_c_api_shim.cc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/rcs_print_shim.cc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/rtapi_compat.cc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/tooldata/tooldata_mmap_backend.cc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/tooldata/tooldata_runtime_stubs.cc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/pythonplugin/python_plugin.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(linuxcnc_rs274_wasm_safe_probe_objects OBJECT
|
||||||
|
${linuxcnc_wasm_safe_probe_shims}
|
||||||
|
${linuxcnc_wasm_safe_probe_sources}
|
||||||
|
)
|
||||||
|
target_compile_features(linuxcnc_rs274_wasm_safe_probe_objects PUBLIC cxx_std_20)
|
||||||
|
target_compile_definitions(linuxcnc_rs274_wasm_safe_probe_objects PRIVATE ULAPI)
|
||||||
|
target_compile_options(linuxcnc_rs274_wasm_safe_probe_objects PRIVATE
|
||||||
|
${cnc_sim_wasm_safe_preinclude_options}
|
||||||
|
${cnc_sim_wasm_safe_section_options}
|
||||||
|
)
|
||||||
|
target_include_directories(linuxcnc_rs274_wasm_safe_probe_objects
|
||||||
|
PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/nml_intf
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/rs274ngc
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/motion
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/include
|
||||||
|
)
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
target_compile_definitions(linuxcnc_rs274_wasm_safe_probe_objects PRIVATE FMT_HEADER_ONLY=1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(cnc_sim_wasm_runtime_probe_main
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/cnc_sim_wasm_runtime_probe_main.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
if(linuxcnc_wasm_blocked_sources)
|
||||||
|
add_custom_target(linuxcnc_rs274_wasm_blocked_sources
|
||||||
|
SOURCES ${linuxcnc_wasm_blocked_sources}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||||
|
list(APPEND cnc_sim_core_sources ${cnc_sim_linuxcnc_rs274_backend_sources})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(cnc_sim_objects OBJECT
|
add_library(cnc_sim_objects OBJECT
|
||||||
@@ -37,9 +230,36 @@ target_include_directories(cnc_sim_objects
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
PRIVATE
|
PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../../linuxcnc/include
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_features(cnc_sim_objects PUBLIC cxx_std_17)
|
target_compile_features(cnc_sim_objects PUBLIC cxx_std_17)
|
||||||
|
set(cnc_sim_linuxcnc_kinematics_c_sources
|
||||||
|
src/linuxcnc_5axiskins_adapter.c
|
||||||
|
src/linuxcnc_corexykins_adapter.c
|
||||||
|
src/linuxcnc_cubic_adapter.c
|
||||||
|
src/linuxcnc_genserfuncs_adapter.c
|
||||||
|
src/linuxcnc_genhexkins_adapter.c
|
||||||
|
src/linuxcnc_kins_util_adapter.c
|
||||||
|
src/linuxcnc_lineardeltakins_adapter.c
|
||||||
|
src/linuxcnc_maxkins_adapter.c
|
||||||
|
src/linuxcnc_pentakins_adapter.c
|
||||||
|
src/linuxcnc_pumakins_adapter.c
|
||||||
|
src/linuxcnc_rotatekins_adapter.c
|
||||||
|
src/linuxcnc_rosekins_adapter.c
|
||||||
|
src/linuxcnc_rotarydeltakins_adapter.c
|
||||||
|
src/linuxcnc_scarakins_adapter.c
|
||||||
|
src/linuxcnc_scorbot_kins_adapter.c
|
||||||
|
src/linuxcnc_tripodkins_adapter.c
|
||||||
|
src/linuxcnc_trtfuncs_adapter.c
|
||||||
|
src/linuxcnc_userkfuncs_adapter.c
|
||||||
|
src/linuxcnc_xyzab_tdr_kins_adapter.c
|
||||||
|
)
|
||||||
|
set_source_files_properties(
|
||||||
|
${cnc_sim_linuxcnc_kinematics_c_sources}
|
||||||
|
PROPERTIES
|
||||||
|
COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>"
|
||||||
|
)
|
||||||
|
|
||||||
if(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
if(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
||||||
find_package(Python3 REQUIRED COMPONENTS Development)
|
find_package(Python3 REQUIRED COMPONENTS Development)
|
||||||
@@ -59,6 +279,97 @@ if(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||||
|
target_compile_definitions(cnc_sim_objects
|
||||||
|
PRIVATE
|
||||||
|
CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
||||||
|
CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
|
||||||
|
ULAPI
|
||||||
|
)
|
||||||
|
target_compile_options(cnc_sim_objects PRIVATE ${cnc_sim_wasm_safe_preinclude_options})
|
||||||
|
target_include_directories(cnc_sim_objects
|
||||||
|
PRIVATE
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/nml_intf
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/rs274ngc
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/motion
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims
|
||||||
|
)
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
target_compile_definitions(cnc_sim_objects PRIVATE FMT_HEADER_ONLY=1)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||||
|
add_executable(linuxcnc_rs274_wasm_safe_probe EXCLUDE_FROM_ALL
|
||||||
|
$<TARGET_OBJECTS:linuxcnc_rs274_wasm_safe_probe_objects>
|
||||||
|
$<TARGET_OBJECTS:cnc_sim_objects>
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/rs274ngc_pre_probe_main.cc
|
||||||
|
)
|
||||||
|
target_compile_features(linuxcnc_rs274_wasm_safe_probe PRIVATE cxx_std_20)
|
||||||
|
target_compile_definitions(linuxcnc_rs274_wasm_safe_probe
|
||||||
|
PRIVATE
|
||||||
|
CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
||||||
|
CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
|
||||||
|
ULAPI
|
||||||
|
)
|
||||||
|
target_compile_options(linuxcnc_rs274_wasm_safe_probe PRIVATE ${cnc_sim_wasm_safe_preinclude_options})
|
||||||
|
target_link_options(linuxcnc_rs274_wasm_safe_probe PRIVATE ${cnc_sim_wasm_safe_link_options})
|
||||||
|
target_include_directories(linuxcnc_rs274_wasm_safe_probe
|
||||||
|
PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/nml_intf
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/rs274ngc
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/motion
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/include
|
||||||
|
)
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
target_compile_definitions(linuxcnc_rs274_wasm_safe_probe PRIVATE FMT_HEADER_ONLY=1)
|
||||||
|
else()
|
||||||
|
target_link_libraries(linuxcnc_rs274_wasm_safe_probe PRIVATE fmt)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(cnc_sim_wasm_runtime_probe EXCLUDE_FROM_ALL
|
||||||
|
$<TARGET_OBJECTS:linuxcnc_rs274_wasm_safe_probe_objects>
|
||||||
|
$<TARGET_OBJECTS:cnc_sim_objects>
|
||||||
|
${cnc_sim_wasm_runtime_probe_main}
|
||||||
|
)
|
||||||
|
target_compile_features(cnc_sim_wasm_runtime_probe PRIVATE cxx_std_20)
|
||||||
|
target_compile_definitions(cnc_sim_wasm_runtime_probe PRIVATE ULAPI)
|
||||||
|
target_compile_options(cnc_sim_wasm_runtime_probe PRIVATE ${cnc_sim_wasm_safe_preinclude_options})
|
||||||
|
target_link_options(cnc_sim_wasm_runtime_probe PRIVATE ${cnc_sim_wasm_safe_link_options})
|
||||||
|
target_include_directories(cnc_sim_wasm_runtime_probe
|
||||||
|
PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/nml_intf
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/rs274ngc
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/motion
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/include
|
||||||
|
)
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
target_compile_definitions(cnc_sim_wasm_runtime_probe PRIVATE FMT_HEADER_ONLY=1)
|
||||||
|
else()
|
||||||
|
target_link_libraries(cnc_sim_wasm_runtime_probe PRIVATE fmt)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CNC_SIM_ENABLE_SMOKE_BACKEND)
|
||||||
|
target_compile_definitions(cnc_sim_objects
|
||||||
|
PRIVATE
|
||||||
|
CNC_SIM_ENABLE_SMOKE_BACKEND
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_library(cnc_sim_core STATIC
|
add_library(cnc_sim_core STATIC
|
||||||
$<TARGET_OBJECTS:cnc_sim_objects>
|
$<TARGET_OBJECTS:cnc_sim_objects>
|
||||||
)
|
)
|
||||||
@@ -88,11 +399,13 @@ if(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT EMSCRIPTEN)
|
if(NOT EMSCRIPTEN)
|
||||||
|
if(CNC_SIM_ENABLE_SMOKE_BACKEND)
|
||||||
add_executable(cnc_sim_api_smoke
|
add_executable(cnc_sim_api_smoke
|
||||||
tests/cnc_sim_api_smoke.cpp
|
tests/cnc_sim_api_smoke.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(cnc_sim_api_smoke PRIVATE cnc_sim_core)
|
target_link_libraries(cnc_sim_api_smoke PRIVATE cnc_sim_core)
|
||||||
target_include_directories(cnc_sim_api_smoke PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
target_include_directories(cnc_sim_api_smoke PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_executable(canon_event_sink_smoke
|
add_executable(canon_event_sink_smoke
|
||||||
tests/canon_event_sink_smoke.cpp
|
tests/canon_event_sink_smoke.cpp
|
||||||
@@ -106,17 +419,24 @@ if(NOT EMSCRIPTEN)
|
|||||||
target_link_libraries(rtcp_kinematics_smoke PRIVATE cnc_sim_core)
|
target_link_libraries(rtcp_kinematics_smoke PRIVATE cnc_sim_core)
|
||||||
target_include_directories(rtcp_kinematics_smoke PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
target_include_directories(rtcp_kinematics_smoke PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
|
||||||
|
add_executable(linuxcnc_gees_table_smoke
|
||||||
|
tests/linuxcnc_gees_table_smoke.cpp
|
||||||
|
)
|
||||||
|
target_include_directories(linuxcnc_gees_table_smoke PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
|
||||||
add_executable(simulator_gcode_controls_smoke
|
add_executable(simulator_gcode_controls_smoke
|
||||||
tests/simulator_gcode_controls_smoke.cpp
|
tests/simulator_gcode_controls_smoke.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(simulator_gcode_controls_smoke PRIVATE cnc_sim_core)
|
target_link_libraries(simulator_gcode_controls_smoke PRIVATE cnc_sim_core)
|
||||||
target_include_directories(simulator_gcode_controls_smoke PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
target_include_directories(simulator_gcode_controls_smoke PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
|
||||||
|
if(CNC_SIM_ENABLE_SMOKE_BACKEND)
|
||||||
add_executable(cnc_sim_dump
|
add_executable(cnc_sim_dump
|
||||||
tools/cnc_sim_dump.cpp
|
tools/cnc_sim_dump.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(cnc_sim_dump PRIVATE cnc_sim_core)
|
target_link_libraries(cnc_sim_dump PRIVATE cnc_sim_core)
|
||||||
target_include_directories(cnc_sim_dump PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
target_include_directories(cnc_sim_dump PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
if(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
||||||
add_executable(cnc_sim_api_linuxcnc_rs274_smoke
|
add_executable(cnc_sim_api_linuxcnc_rs274_smoke
|
||||||
@@ -156,7 +476,11 @@ if(CNC_SIM_ENABLE_LINUXCNC_BRIDGE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(EMSCRIPTEN)
|
if(EMSCRIPTEN)
|
||||||
|
if(NOT CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||||
|
message(FATAL_ERROR "WASM builds must enable CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE so LinuxCNC rs274 sources are linked")
|
||||||
|
endif()
|
||||||
add_executable(cnc_sim_wasm
|
add_executable(cnc_sim_wasm
|
||||||
|
$<TARGET_OBJECTS:linuxcnc_rs274_wasm_safe_probe_objects>
|
||||||
$<TARGET_OBJECTS:cnc_sim_objects>
|
$<TARGET_OBJECTS:cnc_sim_objects>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -164,7 +488,15 @@ if(EMSCRIPTEN)
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/nml_intf
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/rs274ngc
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/motion
|
||||||
|
${CNC_SIM_LINUXCNC_ROOT_ABS}/include
|
||||||
)
|
)
|
||||||
|
target_compile_definitions(cnc_sim_wasm PRIVATE FMT_HEADER_ONLY=1)
|
||||||
|
|
||||||
set_target_properties(cnc_sim_wasm PROPERTIES
|
set_target_properties(cnc_sim_wasm PROPERTIES
|
||||||
OUTPUT_NAME "cnc_sim"
|
OUTPUT_NAME "cnc_sim"
|
||||||
@@ -172,12 +504,14 @@ if(EMSCRIPTEN)
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_link_options(cnc_sim_wasm PRIVATE
|
target_link_options(cnc_sim_wasm PRIVATE
|
||||||
|
${cnc_sim_wasm_safe_link_options}
|
||||||
"--no-entry"
|
"--no-entry"
|
||||||
"-sMODULARIZE=1"
|
"-sMODULARIZE=1"
|
||||||
"-sEXPORT_NAME=createCncSimModule"
|
"-sEXPORT_NAME=createCncSimModule"
|
||||||
"-sALLOW_MEMORY_GROWTH=1"
|
"-sALLOW_MEMORY_GROWTH=1"
|
||||||
"-sALLOW_TABLE_GROWTH=1"
|
"-sALLOW_TABLE_GROWTH=1"
|
||||||
|
"-sFORCE_FILESYSTEM=1"
|
||||||
"-sEXPORTED_FUNCTIONS=['_malloc','_free','_cnc_sim_create','_cnc_sim_destroy','_cnc_sim_reset','_cnc_sim_set_dialect','_cnc_sim_set_event_callback','_cnc_sim_load_config_json','_cnc_sim_parse_program','_cnc_sim_last_error']"
|
"-sEXPORTED_FUNCTIONS=['_malloc','_free','_cnc_sim_create','_cnc_sim_destroy','_cnc_sim_reset','_cnc_sim_set_dialect','_cnc_sim_set_event_callback','_cnc_sim_load_config_json','_cnc_sim_parse_program','_cnc_sim_last_error']"
|
||||||
"-sEXPORTED_RUNTIME_METHODS=['ccall','cwrap','UTF8ToString','stringToUTF8','lengthBytesUTF8','addFunction','removeFunction']"
|
"-sEXPORTED_RUNTIME_METHODS=['FS','ccall','cwrap','UTF8ToString','stringToUTF8','lengthBytesUTF8','addFunction','removeFunction']"
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,6 +1,23 @@
|
|||||||
#include "canon_event_sink.h"
|
#include "canon_event_sink.h"
|
||||||
|
|
||||||
#include "rtcp_kinematics.h"
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr int kCssSpindleModeEvent = 960;
|
||||||
|
constexpr int kConstantRpmSpindleModeEvent = 970;
|
||||||
|
|
||||||
|
void rotate_xy(double *x, double *y, double degrees) {
|
||||||
|
const double radians = degrees * std::acos(-1.0) / 180.0;
|
||||||
|
const double c = std::cos(radians);
|
||||||
|
const double s = std::sin(radians);
|
||||||
|
const double nx = *x * c - *y * s;
|
||||||
|
const double ny = *x * s + *y * c;
|
||||||
|
*x = nx;
|
||||||
|
*y = ny;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void CanonEventSink::reset() {
|
void CanonEventSink::reset() {
|
||||||
position_ = {};
|
position_ = {};
|
||||||
@@ -14,14 +31,19 @@ void CanonEventSink::reset() {
|
|||||||
probe_position_ = {};
|
probe_position_ = {};
|
||||||
probe_tripped_ = false;
|
probe_tripped_ = false;
|
||||||
tool_length_offset_ = {};
|
tool_length_offset_ = {};
|
||||||
|
xy_rotation_degrees_ = 0.0;
|
||||||
callback_status_ = 0;
|
callback_status_ = 0;
|
||||||
kinematics_type_ = 1;
|
// LinuxCNC xyzbc-trt-kins with sparm=identityfirst starts at switchkins-type 0.
|
||||||
|
// Source: linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini.
|
||||||
|
kinematics_type_ = 0;
|
||||||
feed_override_ = false;
|
feed_override_ = false;
|
||||||
speed_override_ = false;
|
speed_override_ = false;
|
||||||
adaptive_feed_ = false;
|
adaptive_feed_ = false;
|
||||||
feed_hold_ = false;
|
feed_hold_ = false;
|
||||||
mist_on_ = false;
|
mist_on_ = false;
|
||||||
flood_on_ = false;
|
flood_on_ = false;
|
||||||
|
has_pending_motion_start_ = false;
|
||||||
|
pending_motion_start_ = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanonEventSink::set_callback(CncSimEventCallback callback, void *user_data) {
|
void CanonEventSink::set_callback(CncSimEventCallback callback, void *user_data) {
|
||||||
@@ -38,12 +60,41 @@ bool CanonEventSink::callback_aborted() const {
|
|||||||
return callback_status_ != 0;
|
return callback_status_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CanonEventSink::set_block_delete(bool enabled) {
|
||||||
|
block_delete_ = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
void CanonEventSink::configure_rtcp(bool enabled, double tool_length) {
|
void CanonEventSink::configure_rtcp(bool enabled, double tool_length) {
|
||||||
rtcp_enabled_ = enabled;
|
rtcp_enabled_ = enabled;
|
||||||
default_rtcp_tool_length_ = tool_length;
|
default_rtcp_tool_length_ = tool_length;
|
||||||
rtcp_tool_length_ = tool_length;
|
rtcp_tool_length_ = tool_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CanonEventSink::configure_xyzbc_trt(const LinuxCncXyzbcTrtParameters ¶meters) {
|
||||||
|
xyzbc_trt_parameters_ = parameters;
|
||||||
|
xyzbc_trt_parameters_configured_ = true;
|
||||||
|
use_xyzac_trt_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanonEventSink::configure_xyzac_trt(const LinuxCncXyzbcTrtParameters ¶meters) {
|
||||||
|
xyzbc_trt_parameters_ = parameters;
|
||||||
|
xyzbc_trt_parameters_configured_ = true;
|
||||||
|
use_xyzac_trt_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanonEventSink::configure_fiveaxis(double pivot_length, int kinematics_type) {
|
||||||
|
fiveaxis_configured_ = true;
|
||||||
|
fiveaxis_pivot_length_ = pivot_length;
|
||||||
|
fiveaxis_kinematics_type_ = kinematics_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanonEventSink::configure_switchkins_remap(int m428_type, int m429_type, int m430_type) {
|
||||||
|
switchkins_remap_configured_ = true;
|
||||||
|
switchkins_m428_type_ = m428_type;
|
||||||
|
switchkins_m429_type_ = m429_type;
|
||||||
|
switchkins_m430_type_ = m430_type;
|
||||||
|
}
|
||||||
|
|
||||||
void CanonEventSink::set_tool_length(int h_code, double tool_length) {
|
void CanonEventSink::set_tool_length(int h_code, double tool_length) {
|
||||||
if (h_code <= 0) {
|
if (h_code <= 0) {
|
||||||
default_rtcp_tool_length_ = tool_length;
|
default_rtcp_tool_length_ = tool_length;
|
||||||
@@ -62,6 +113,26 @@ void CanonEventSink::set_tool_length_offset(const CncSimPose &offset) {
|
|||||||
tool_length_offset_ = offset;
|
tool_length_offset_ = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CanonEventSink::apply_tool_length_offset(const CncSimPose &offset) {
|
||||||
|
if (!has_pending_motion_start_) {
|
||||||
|
pending_motion_start_ = position_;
|
||||||
|
has_pending_motion_start_ = true;
|
||||||
|
}
|
||||||
|
double dx = tool_length_offset_.x - offset.x;
|
||||||
|
double dy = tool_length_offset_.y - offset.y;
|
||||||
|
rotate_xy(&dx, &dy, -xy_rotation_degrees_);
|
||||||
|
position_.x += dx;
|
||||||
|
position_.y += dy;
|
||||||
|
position_.z += tool_length_offset_.z - offset.z;
|
||||||
|
position_.a += tool_length_offset_.a - offset.a;
|
||||||
|
position_.b += tool_length_offset_.b - offset.b;
|
||||||
|
position_.c += tool_length_offset_.c - offset.c;
|
||||||
|
position_.u += tool_length_offset_.u - offset.u;
|
||||||
|
position_.v += tool_length_offset_.v - offset.v;
|
||||||
|
position_.w += tool_length_offset_.w - offset.w;
|
||||||
|
tool_length_offset_ = offset;
|
||||||
|
}
|
||||||
|
|
||||||
void CanonEventSink::set_rtcp_state(bool enabled, int h_code, int line) {
|
void CanonEventSink::set_rtcp_state(bool enabled, int h_code, int line) {
|
||||||
rtcp_enabled_ = enabled;
|
rtcp_enabled_ = enabled;
|
||||||
rtcp_h_code_ = enabled ? h_code : 0;
|
rtcp_h_code_ = enabled ? h_code : 0;
|
||||||
@@ -76,15 +147,72 @@ void CanonEventSink::set_rtcp_state(bool enabled, int h_code, int line) {
|
|||||||
emit(event);
|
emit(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanonEventSink::switch_kinematics(int kinematics_type, bool rtcp_enabled, int line) {
|
void CanonEventSink::switch_kinematics(int kinematics_type, int line) {
|
||||||
kinematics_type_ = kinematics_type;
|
kinematics_type_ = kinematics_type;
|
||||||
rtcp_enabled_ = rtcp_enabled;
|
// Source: linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/{428,429,430}remap.ngc.
|
||||||
|
// M68 E3 Q#<kinstype>, then M66 E0 L0 to force synchronization.
|
||||||
|
set_analog_output(3, static_cast<double>(kinematics_type_), false, line);
|
||||||
|
wait_input(0, 0, 0, 0.0, line);
|
||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_KINEMATICS_SWITCH, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_KINEMATICS_SWITCH, line);
|
||||||
event.reserved = kinematics_type_;
|
event.reserved = kinematics_type_;
|
||||||
event.feed = rtcp_enabled_ ? 1.0 : 0.0;
|
|
||||||
emit(event);
|
emit(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CanonEventSink::can_switch_m_code_kinematics(int m_code) const {
|
||||||
|
if (!switchkins_remap_configured_) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m_code == 428) {
|
||||||
|
return switchkins_m428_type_ >= 0;
|
||||||
|
}
|
||||||
|
if (m_code == 429) {
|
||||||
|
return switchkins_m429_type_ >= 0;
|
||||||
|
}
|
||||||
|
if (m_code == 430) {
|
||||||
|
return switchkins_m430_type_ >= 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanonEventSink::switch_m_code_kinematics(int m_code, int default_kinematics_type, int line) {
|
||||||
|
if (switchkins_remap_configured_) {
|
||||||
|
int kinematics_type = -1;
|
||||||
|
if (m_code == 428) {
|
||||||
|
kinematics_type = switchkins_m428_type_;
|
||||||
|
} else if (m_code == 429) {
|
||||||
|
kinematics_type = switchkins_m429_type_;
|
||||||
|
} else if (m_code == 430) {
|
||||||
|
kinematics_type = switchkins_m430_type_;
|
||||||
|
}
|
||||||
|
if (kinematics_type >= 0) {
|
||||||
|
switch_kinematics(kinematics_type, line);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fiveaxis_configured_) {
|
||||||
|
// Sources:
|
||||||
|
// - linuxcnc/configs/sim/axis/vismach/5axis/bridgemill/remap_subs/{428,429,430}remap.ngc
|
||||||
|
// - linuxcnc/configs/sim/axis/vismach/scara/remap_subs/{428,429,430}remap.ngc
|
||||||
|
// - linuxcnc/configs/sim/axis/vismach/melfa-sim/remap_subs/{428,429,430}remap.ngc
|
||||||
|
// These remaps select kinstype 0, 1, and 2 respectively.
|
||||||
|
if (m_code == 428) {
|
||||||
|
switch_kinematics(0, line);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m_code == 429) {
|
||||||
|
switch_kinematics(1, line);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m_code == 430) {
|
||||||
|
switch_kinematics(2, line);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch_kinematics(default_kinematics_type, line);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void CanonEventSink::set_g5x_offset(int index, const CncSimPose &offset, int line) {
|
void CanonEventSink::set_g5x_offset(int index, const CncSimPose &offset, int line) {
|
||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_G5X_OFFSET, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_G5X_OFFSET, line);
|
||||||
event.tool = index;
|
event.tool = index;
|
||||||
@@ -99,12 +227,48 @@ void CanonEventSink::set_g92_offset(const CncSimPose &offset, int line) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CanonEventSink::set_xy_rotation(double angle_degrees, int line) {
|
void CanonEventSink::set_xy_rotation(double angle_degrees, int line) {
|
||||||
|
xy_rotation_degrees_ = angle_degrees;
|
||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_XY_ROTATION, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_XY_ROTATION, line);
|
||||||
event.feed = angle_degrees;
|
event.feed = angle_degrees;
|
||||||
emit(event);
|
emit(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanonEventSink::use_length_units(double scale, int line) {
|
void CanonEventSink::use_length_units(double scale, int line) {
|
||||||
|
use_length_units(scale, line, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanonEventSink::use_length_units(double scale, int line, bool rescale_linear_state) {
|
||||||
|
if (rescale_linear_state && unit_scale_ != 0.0 && scale != unit_scale_) {
|
||||||
|
const double factor = unit_scale_ / scale;
|
||||||
|
// LinuxCNC src/emc/rs274ngc/interp_convert.cc convert_length_units()
|
||||||
|
// rescales linear current axes on G20/G21; A/B/C remain angular.
|
||||||
|
position_.x *= factor;
|
||||||
|
position_.y *= factor;
|
||||||
|
position_.z *= factor;
|
||||||
|
position_.u *= factor;
|
||||||
|
position_.v *= factor;
|
||||||
|
position_.w *= factor;
|
||||||
|
tool_length_offset_.x *= factor;
|
||||||
|
tool_length_offset_.y *= factor;
|
||||||
|
tool_length_offset_.z *= factor;
|
||||||
|
tool_length_offset_.u *= factor;
|
||||||
|
tool_length_offset_.v *= factor;
|
||||||
|
tool_length_offset_.w *= factor;
|
||||||
|
probe_position_.x *= factor;
|
||||||
|
probe_position_.y *= factor;
|
||||||
|
probe_position_.z *= factor;
|
||||||
|
probe_position_.u *= factor;
|
||||||
|
probe_position_.v *= factor;
|
||||||
|
probe_position_.w *= factor;
|
||||||
|
if (has_pending_motion_start_) {
|
||||||
|
pending_motion_start_.x *= factor;
|
||||||
|
pending_motion_start_.y *= factor;
|
||||||
|
pending_motion_start_.z *= factor;
|
||||||
|
pending_motion_start_.u *= factor;
|
||||||
|
pending_motion_start_.v *= factor;
|
||||||
|
pending_motion_start_.w *= factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
unit_scale_ = scale;
|
unit_scale_ = scale;
|
||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_UNITS, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_UNITS, line);
|
||||||
event.feed = scale;
|
event.feed = scale;
|
||||||
@@ -138,8 +302,13 @@ void CanonEventSink::set_feed_mode(int spindle, int mode, int line) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CanonEventSink::set_spindle_speed(double spindle, int line) {
|
void CanonEventSink::set_spindle_speed(double spindle, int line) {
|
||||||
spindle_ = spindle;
|
set_spindle_speed(0, spindle, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanonEventSink::set_spindle_speed(int spindle, double speed, int line) {
|
||||||
|
spindle_ = speed;
|
||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_SPINDLE, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_SPINDLE, line);
|
||||||
|
event.tool = spindle;
|
||||||
event.spindle = spindle_;
|
event.spindle = spindle_;
|
||||||
event.reserved = spindle_direction_;
|
event.reserved = spindle_direction_;
|
||||||
emit(event);
|
emit(event);
|
||||||
@@ -149,7 +318,7 @@ void CanonEventSink::set_spindle_mode(int spindle, double mode, int line) {
|
|||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_COMMENT, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_COMMENT, line);
|
||||||
event.tool = spindle;
|
event.tool = spindle;
|
||||||
event.feed = mode;
|
event.feed = mode;
|
||||||
event.reserved = mode == 0.0 ? 970 : 960;
|
event.reserved = mode == 0.0 ? kConstantRpmSpindleModeEvent : kCssSpindleModeEvent;
|
||||||
emit(event);
|
emit(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,16 +398,26 @@ void CanonEventSink::set_override_control(int control, bool enabled, int spindle
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CanonEventSink::start_spindle(int direction, int line) {
|
void CanonEventSink::start_spindle(int direction, int line) {
|
||||||
|
start_spindle(0, direction, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanonEventSink::start_spindle(int spindle, int direction, int line) {
|
||||||
spindle_direction_ = direction < 0 ? 2 : 1;
|
spindle_direction_ = direction < 0 ? 2 : 1;
|
||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_SPINDLE, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_SPINDLE, line);
|
||||||
|
event.tool = spindle;
|
||||||
event.spindle = spindle_;
|
event.spindle = spindle_;
|
||||||
event.reserved = spindle_direction_;
|
event.reserved = spindle_direction_;
|
||||||
emit(event);
|
emit(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanonEventSink::stop_spindle(int line) {
|
void CanonEventSink::stop_spindle(int line) {
|
||||||
|
stop_spindle(0, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanonEventSink::stop_spindle(int spindle, int line) {
|
||||||
spindle_direction_ = 0;
|
spindle_direction_ = 0;
|
||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_SPINDLE, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_SPINDLE, line);
|
||||||
|
event.tool = spindle;
|
||||||
event.spindle = 0.0;
|
event.spindle = 0.0;
|
||||||
event.reserved = spindle_direction_;
|
event.reserved = spindle_direction_;
|
||||||
emit(event);
|
emit(event);
|
||||||
@@ -256,41 +435,45 @@ void CanonEventSink::change_tool(int line) {
|
|||||||
|
|
||||||
void CanonEventSink::straight_traverse(int line, const CncSimPose &end) {
|
void CanonEventSink::straight_traverse(int line, const CncSimPose &end) {
|
||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_RAPID, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_RAPID, line);
|
||||||
event.start = position_;
|
event.start = has_pending_motion_start_ ? pending_motion_start_ : position_;
|
||||||
event.end = end;
|
event.end = end;
|
||||||
emit(event);
|
emit(event);
|
||||||
emit_rtcp_pivot(line, position_, end);
|
emit_rtcp_pivot(line, event.start, end);
|
||||||
|
has_pending_motion_start_ = false;
|
||||||
position_ = end;
|
position_ = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanonEventSink::straight_feed(int line, const CncSimPose &end) {
|
void CanonEventSink::straight_feed(int line, const CncSimPose &end) {
|
||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_LINEAR_FEED, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_LINEAR_FEED, line);
|
||||||
event.start = position_;
|
event.start = has_pending_motion_start_ ? pending_motion_start_ : position_;
|
||||||
event.end = end;
|
event.end = end;
|
||||||
emit(event);
|
emit(event);
|
||||||
emit_rtcp_pivot(line, position_, end);
|
emit_rtcp_pivot(line, event.start, end);
|
||||||
|
has_pending_motion_start_ = false;
|
||||||
position_ = end;
|
position_ = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanonEventSink::arc_feed(int line, const CncSimPose &end, const CncSimPose ¢er, int turns) {
|
void CanonEventSink::arc_feed(int line, const CncSimPose &end, const CncSimPose ¢er, int turns) {
|
||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_ARC_FEED, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_ARC_FEED, line);
|
||||||
event.start = position_;
|
event.start = has_pending_motion_start_ ? pending_motion_start_ : position_;
|
||||||
event.end = end;
|
event.end = end;
|
||||||
event.center = center;
|
event.center = center;
|
||||||
event.arc_turns = turns;
|
event.arc_turns = turns;
|
||||||
emit(event);
|
emit(event);
|
||||||
emit_rtcp_pivot(line, position_, end);
|
emit_rtcp_pivot(line, event.start, end);
|
||||||
|
has_pending_motion_start_ = false;
|
||||||
position_ = end;
|
position_ = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanonEventSink::straight_probe(int line, const CncSimPose &end, int probe_type) {
|
void CanonEventSink::straight_probe(int line, const CncSimPose &end, int probe_type) {
|
||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_PROBE, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_PROBE, line);
|
||||||
event.start = position_;
|
event.start = has_pending_motion_start_ ? pending_motion_start_ : position_;
|
||||||
event.end = end;
|
event.end = end;
|
||||||
event.reserved = probe_type;
|
event.reserved = probe_type;
|
||||||
emit(event);
|
emit(event);
|
||||||
probe_position_ = end;
|
probe_position_ = end;
|
||||||
probe_tripped_ = (probe_type & 2) == 0;
|
probe_tripped_ = (probe_type & 2) == 0;
|
||||||
|
has_pending_motion_start_ = false;
|
||||||
position_ = end;
|
position_ = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,6 +580,10 @@ bool CanonEventSink::flood_on() const {
|
|||||||
return flood_on_;
|
return flood_on_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CanonEventSink::block_delete() const {
|
||||||
|
return block_delete_;
|
||||||
|
}
|
||||||
|
|
||||||
void CanonEventSink::set_mist_on(bool enabled) {
|
void CanonEventSink::set_mist_on(bool enabled) {
|
||||||
mist_on_ = enabled;
|
mist_on_ = enabled;
|
||||||
}
|
}
|
||||||
@@ -412,16 +599,67 @@ void CanonEventSink::emit(CncSimEvent event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CanonEventSink::emit_rtcp_pivot(int line, const CncSimPose &start, const CncSimPose &end) {
|
void CanonEventSink::emit_rtcp_pivot(int line, const CncSimPose &start, const CncSimPose &end) {
|
||||||
if (!rtcp_enabled_ || rtcp_tool_length_ == 0.0 || callback_status_ != 0) {
|
if (!rtcp_enabled_ || callback_status_ != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CncSimEvent event = base_event(CNC_SIM_EVENT_RTCP_PIVOT, line);
|
CncSimEvent event = base_event(CNC_SIM_EVENT_RTCP_PIVOT, line);
|
||||||
event.start = rtcp_pivot_from_tool_tip(start, rtcp_tool_length_);
|
if (fiveaxis_configured_ && kinematics_type_ == fiveaxis_kinematics_type_) {
|
||||||
event.end = rtcp_pivot_from_tool_tip(end, rtcp_tool_length_);
|
const LinuxCncFiveAxisJoints start_joints =
|
||||||
const RtcpVector tool = rtcp_tool_vector_from_pose(end, rtcp_tool_length_);
|
linuxcnc_5axis_inverse(start, fiveaxis_pivot_length_);
|
||||||
event.center.x = tool.x;
|
const LinuxCncFiveAxisJoints end_joints =
|
||||||
event.center.y = tool.y;
|
linuxcnc_5axis_inverse(end, fiveaxis_pivot_length_);
|
||||||
event.center.z = tool.z;
|
event.start.x = start_joints.x;
|
||||||
|
event.start.y = start_joints.y;
|
||||||
|
event.start.z = start_joints.z;
|
||||||
|
event.start.b = start_joints.b;
|
||||||
|
event.start.c = start_joints.c;
|
||||||
|
event.start.w = start_joints.w;
|
||||||
|
event.end.x = end_joints.x;
|
||||||
|
event.end.y = end_joints.y;
|
||||||
|
event.end.z = end_joints.z;
|
||||||
|
event.end.b = end_joints.b;
|
||||||
|
event.end.c = end_joints.c;
|
||||||
|
event.end.w = end_joints.w;
|
||||||
|
event.reserved = kinematics_type_;
|
||||||
|
event.dwell_seconds = fiveaxis_pivot_length_;
|
||||||
|
} else if (kinematics_type_ == 1 || kinematics_type_ == 2) {
|
||||||
|
LinuxCncFiveAxisJoints start_joints{};
|
||||||
|
LinuxCncFiveAxisJoints end_joints{};
|
||||||
|
if (kinematics_type_ == 1) {
|
||||||
|
LinuxCncXyzbcTrtParameters parameters = xyzbc_trt_parameters_configured_
|
||||||
|
? xyzbc_trt_parameters_
|
||||||
|
: linuxcnc_xyzbc_trt_default_parameters(rtcp_tool_length_);
|
||||||
|
parameters.tool_offset = rtcp_tool_length_;
|
||||||
|
if (use_xyzac_trt_) {
|
||||||
|
start_joints = linuxcnc_xyzac_trt_inverse(start, parameters);
|
||||||
|
end_joints = linuxcnc_xyzac_trt_inverse(end, parameters);
|
||||||
|
} else {
|
||||||
|
start_joints = linuxcnc_xyzbc_trt_inverse(start, parameters);
|
||||||
|
end_joints = linuxcnc_xyzbc_trt_inverse(end, parameters);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
start_joints = linuxcnc_xyzbc_userk_inverse(start);
|
||||||
|
end_joints = linuxcnc_xyzbc_userk_inverse(end);
|
||||||
|
}
|
||||||
|
event.start.x = start_joints.x;
|
||||||
|
event.start.y = start_joints.y;
|
||||||
|
event.start.z = start_joints.z;
|
||||||
|
event.start.a = start_joints.a;
|
||||||
|
event.start.b = start_joints.b;
|
||||||
|
event.start.c = start_joints.c;
|
||||||
|
event.start.w = start_joints.w;
|
||||||
|
event.end.x = end_joints.x;
|
||||||
|
event.end.y = end_joints.y;
|
||||||
|
event.end.z = end_joints.z;
|
||||||
|
event.end.a = end_joints.a;
|
||||||
|
event.end.b = end_joints.b;
|
||||||
|
event.end.c = end_joints.c;
|
||||||
|
event.end.w = end_joints.w;
|
||||||
|
event.reserved = kinematics_type_;
|
||||||
|
event.dwell_seconds = rtcp_tool_length_;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
emit(event);
|
emit(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "cnc_sim_api.h"
|
#include "cnc_sim_api.h"
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
@@ -10,21 +11,31 @@ public:
|
|||||||
void set_callback(CncSimEventCallback callback, void *user_data);
|
void set_callback(CncSimEventCallback callback, void *user_data);
|
||||||
void clear_callback_status();
|
void clear_callback_status();
|
||||||
bool callback_aborted() const;
|
bool callback_aborted() const;
|
||||||
|
void set_block_delete(bool enabled);
|
||||||
void configure_rtcp(bool enabled, double tool_length);
|
void configure_rtcp(bool enabled, double tool_length);
|
||||||
|
void configure_xyzbc_trt(const LinuxCncXyzbcTrtParameters ¶meters);
|
||||||
|
void configure_xyzac_trt(const LinuxCncXyzbcTrtParameters ¶meters);
|
||||||
|
void configure_fiveaxis(double pivot_length, int kinematics_type);
|
||||||
|
void configure_switchkins_remap(int m428_type, int m429_type, int m430_type);
|
||||||
void set_tool_length(int h_code, double tool_length);
|
void set_tool_length(int h_code, double tool_length);
|
||||||
void set_tool_length_offset(const CncSimPose &offset);
|
void set_tool_length_offset(const CncSimPose &offset);
|
||||||
|
void apply_tool_length_offset(const CncSimPose &offset);
|
||||||
void set_rtcp_state(bool enabled, int h_code, int line);
|
void set_rtcp_state(bool enabled, int h_code, int line);
|
||||||
void switch_kinematics(int kinematics_type, bool rtcp_enabled, int line);
|
void switch_kinematics(int kinematics_type, int line);
|
||||||
|
bool can_switch_m_code_kinematics(int m_code) const;
|
||||||
|
bool switch_m_code_kinematics(int m_code, int default_kinematics_type, int line);
|
||||||
void set_g5x_offset(int index, const CncSimPose &offset, int line);
|
void set_g5x_offset(int index, const CncSimPose &offset, int line);
|
||||||
void set_g92_offset(const CncSimPose &offset, int line);
|
void set_g92_offset(const CncSimPose &offset, int line);
|
||||||
void set_xy_rotation(double angle_degrees, int line);
|
void set_xy_rotation(double angle_degrees, int line);
|
||||||
|
|
||||||
void use_length_units(double scale, int line);
|
void use_length_units(double scale, int line);
|
||||||
|
void use_length_units(double scale, int line, bool rescale_linear_state);
|
||||||
void select_plane(int plane, int line);
|
void select_plane(int plane, int line);
|
||||||
void set_traverse_rate(double rate);
|
void set_traverse_rate(double rate);
|
||||||
void set_feed_rate(double feed, int line);
|
void set_feed_rate(double feed, int line);
|
||||||
void set_feed_mode(int spindle, int mode, int line);
|
void set_feed_mode(int spindle, int mode, int line);
|
||||||
void set_spindle_speed(double spindle, int line);
|
void set_spindle_speed(double spindle, int line);
|
||||||
|
void set_spindle_speed(int spindle, double speed, int line);
|
||||||
void set_spindle_mode(int spindle, double mode, int line);
|
void set_spindle_mode(int spindle, double mode, int line);
|
||||||
void set_speed_feed_sync(int spindle, double feed_per_revolution, bool velocity_mode, bool enabled, int line);
|
void set_speed_feed_sync(int spindle, double feed_per_revolution, bool velocity_mode, bool enabled, int line);
|
||||||
void orient_spindle(int spindle, double orientation, int mode, int line);
|
void orient_spindle(int spindle, double orientation, int mode, int line);
|
||||||
@@ -34,7 +45,9 @@ public:
|
|||||||
void wait_input(int index, int input_type, int wait_type, double timeout, int line);
|
void wait_input(int index, int input_type, int wait_type, double timeout, int line);
|
||||||
void set_override_control(int control, bool enabled, int spindle, int line);
|
void set_override_control(int control, bool enabled, int spindle, int line);
|
||||||
void start_spindle(int direction, int line);
|
void start_spindle(int direction, int line);
|
||||||
|
void start_spindle(int spindle, int direction, int line);
|
||||||
void stop_spindle(int line);
|
void stop_spindle(int line);
|
||||||
|
void stop_spindle(int spindle, int line);
|
||||||
void select_tool(int tool);
|
void select_tool(int tool);
|
||||||
void change_tool(int line);
|
void change_tool(int line);
|
||||||
void straight_traverse(int line, const CncSimPose &end);
|
void straight_traverse(int line, const CncSimPose &end);
|
||||||
@@ -66,6 +79,7 @@ public:
|
|||||||
bool feed_hold() const;
|
bool feed_hold() const;
|
||||||
bool mist_on() const;
|
bool mist_on() const;
|
||||||
bool flood_on() const;
|
bool flood_on() const;
|
||||||
|
bool block_delete() const;
|
||||||
void set_mist_on(bool enabled);
|
void set_mist_on(bool enabled);
|
||||||
void set_flood_on(bool enabled);
|
void set_flood_on(bool enabled);
|
||||||
|
|
||||||
@@ -91,13 +105,27 @@ private:
|
|||||||
double default_rtcp_tool_length_ = 0.0;
|
double default_rtcp_tool_length_ = 0.0;
|
||||||
double rtcp_tool_length_ = 0.0;
|
double rtcp_tool_length_ = 0.0;
|
||||||
int rtcp_h_code_ = 0;
|
int rtcp_h_code_ = 0;
|
||||||
|
LinuxCncXyzbcTrtParameters xyzbc_trt_parameters_{};
|
||||||
|
bool xyzbc_trt_parameters_configured_ = false;
|
||||||
|
bool use_xyzac_trt_ = false;
|
||||||
|
bool fiveaxis_configured_ = false;
|
||||||
|
double fiveaxis_pivot_length_ = 250.0;
|
||||||
|
int fiveaxis_kinematics_type_ = 0;
|
||||||
|
bool switchkins_remap_configured_ = false;
|
||||||
|
int switchkins_m428_type_ = 1;
|
||||||
|
int switchkins_m429_type_ = 0;
|
||||||
|
int switchkins_m430_type_ = 2;
|
||||||
CncSimPose tool_length_offset_{};
|
CncSimPose tool_length_offset_{};
|
||||||
int kinematics_type_ = 1;
|
double xy_rotation_degrees_ = 0.0;
|
||||||
|
int kinematics_type_ = 0;
|
||||||
bool feed_override_ = false;
|
bool feed_override_ = false;
|
||||||
bool speed_override_ = false;
|
bool speed_override_ = false;
|
||||||
bool adaptive_feed_ = false;
|
bool adaptive_feed_ = false;
|
||||||
bool feed_hold_ = false;
|
bool feed_hold_ = false;
|
||||||
bool mist_on_ = false;
|
bool mist_on_ = false;
|
||||||
bool flood_on_ = false;
|
bool flood_on_ = false;
|
||||||
|
bool block_delete_ = false;
|
||||||
std::unordered_map<int, double> tool_lengths_;
|
std::unordered_map<int, double> tool_lengths_;
|
||||||
|
bool has_pending_motion_start_ = false;
|
||||||
|
CncSimPose pending_motion_start_{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,12 +4,14 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct CncSimHandle {
|
struct CncSimHandle {
|
||||||
CncSimDialect dialect = CNC_SIM_DIALECT_LINUXCNC;
|
CncSimDialect dialect = CNC_SIM_DIALECT_LINUXCNC;
|
||||||
GcodeBackendKind backend = GcodeBackendKind::Smoke;
|
GcodeBackendKind backend = GcodeBackendKind::LinuxCncRs274;
|
||||||
|
GcodeBackendOptions backend_options;
|
||||||
std::string last_error;
|
std::string last_error;
|
||||||
CanonEventSink sink;
|
CanonEventSink sink;
|
||||||
};
|
};
|
||||||
@@ -73,6 +75,116 @@ bool contains_bool_value(const std::string &compact, const char *key, bool *valu
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool contains_string_value(const std::string &compact, const char *key, const char *value) {
|
||||||
|
const std::string quoted_needle = std::string("\"") + key + "\":\"" + value + "\"";
|
||||||
|
if (compact.find(quoted_needle) != std::string::npos) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const std::string prefix_needle = std::string("\"") + key + "\":\"";
|
||||||
|
size_t pos = 0;
|
||||||
|
while ((pos = compact.find(prefix_needle, pos)) != std::string::npos) {
|
||||||
|
pos += prefix_needle.size();
|
||||||
|
const size_t end = compact.find('"', pos);
|
||||||
|
if (end == std::string::npos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const std::string field_value = compact.substr(pos, end - pos);
|
||||||
|
if (field_value.find(value) != std::string::npos) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
pos = end + 1;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool find_json_string_value(const std::string &json, const char *key, std::string *value) {
|
||||||
|
const std::string needle = std::string("\"") + key + "\"";
|
||||||
|
size_t pos = 0;
|
||||||
|
while ((pos = json.find(needle, pos)) != std::string::npos) {
|
||||||
|
pos += needle.size();
|
||||||
|
while (pos < json.size() && std::isspace(static_cast<unsigned char>(json[pos]))) {
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
if (pos >= json.size() || json[pos] != ':') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++pos;
|
||||||
|
while (pos < json.size() && std::isspace(static_cast<unsigned char>(json[pos]))) {
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
if (pos >= json.size() || json[pos] != '"') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++pos;
|
||||||
|
std::string parsed;
|
||||||
|
bool escaped = false;
|
||||||
|
for (; pos < json.size(); ++pos) {
|
||||||
|
const char ch = json[pos];
|
||||||
|
if (escaped) {
|
||||||
|
switch (ch) {
|
||||||
|
case '"':
|
||||||
|
case '\\':
|
||||||
|
case '/':
|
||||||
|
parsed.push_back(ch);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
parsed.push_back('\n');
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
parsed.push_back('\r');
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
parsed.push_back('\t');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
parsed.push_back(ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
escaped = false;
|
||||||
|
} else if (ch == '\\') {
|
||||||
|
escaped = true;
|
||||||
|
} else if (ch == '"') {
|
||||||
|
*value = parsed;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
parsed.push_back(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool find_json_string_any(const std::string &json, std::string *value, const char *first) {
|
||||||
|
return find_json_string_value(json, first, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Keys>
|
||||||
|
bool find_json_string_any(const std::string &json, std::string *value, const char *first, Keys... rest) {
|
||||||
|
return find_json_string_value(json, first, value) || find_json_string_any(json, value, rest...);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains_switchkins_config_alias(const std::string &compact, const char *alias) {
|
||||||
|
return contains_string_value(compact, "switchkins", alias) ||
|
||||||
|
contains_string_value(compact, "remap", alias) ||
|
||||||
|
contains_string_value(compact, "machine", alias) ||
|
||||||
|
contains_string_value(compact, "kinematics", alias) ||
|
||||||
|
contains_string_value(compact, "halfile", alias) ||
|
||||||
|
contains_string_value(compact, "hal_file", alias) ||
|
||||||
|
contains_string_value(compact, "postguihalfile", alias) ||
|
||||||
|
contains_string_value(compact, "postgui_halfile", alias) ||
|
||||||
|
contains_string_value(compact, "postgui_hal_file", alias) ||
|
||||||
|
contains_string_value(compact, "subroutinepath", alias) ||
|
||||||
|
contains_string_value(compact, "subroutine_path", alias) ||
|
||||||
|
contains_string_value(compact, "config", alias) ||
|
||||||
|
contains_string_value(compact, "configpath", alias) ||
|
||||||
|
contains_string_value(compact, "config_path", alias) ||
|
||||||
|
contains_string_value(compact, "ini", alias) ||
|
||||||
|
contains_string_value(compact, "inifile", alias) ||
|
||||||
|
contains_string_value(compact, "inifilename", alias) ||
|
||||||
|
contains_string_value(compact, "ini_file", alias) ||
|
||||||
|
contains_string_value(compact, "ini_file_name", alias);
|
||||||
|
}
|
||||||
|
|
||||||
bool find_number_value(const std::string &compact, const char *key, double *value) {
|
bool find_number_value(const std::string &compact, const char *key, double *value) {
|
||||||
const std::string needle = std::string("\"") + key + "\":";
|
const std::string needle = std::string("\"") + key + "\":";
|
||||||
const size_t pos = compact.find(needle);
|
const size_t pos = compact.find(needle);
|
||||||
@@ -128,6 +240,118 @@ void apply_tool_length_table(CanonEventSink &sink, const std::string &compact) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool find_number_any(const std::string &compact, double *value, const char *first) {
|
||||||
|
return find_number_value(compact, first, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Keys>
|
||||||
|
bool find_number_any(const std::string &compact, double *value, const char *first, Keys... rest) {
|
||||||
|
return find_number_value(compact, first, value) || find_number_any(compact, value, rest...);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains_bool_any(const std::string &compact, bool *value, const char *first) {
|
||||||
|
return contains_bool_value(compact, first, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Keys>
|
||||||
|
bool contains_bool_any(const std::string &compact, bool *value, const char *first, Keys... rest) {
|
||||||
|
return contains_bool_value(compact, first, value) || contains_bool_any(compact, value, rest...);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_xyzbc_trt_config(CanonEventSink &sink, const std::string &compact) {
|
||||||
|
LinuxCncXyzbcTrtParameters parameters = linuxcnc_xyzbc_trt_default_parameters(0.0);
|
||||||
|
bool configured = false;
|
||||||
|
const bool xyzac = compact.find("\"trt\":\"xyzac\"") != std::string::npos ||
|
||||||
|
compact.find("\"kinematics\":\"xyzac-trt\"") != std::string::npos ||
|
||||||
|
compact.find("\"switchkins\":\"xyzac-trt\"") != std::string::npos;
|
||||||
|
const bool xyzbc = compact.find("\"trt\":\"xyzbc\"") != std::string::npos ||
|
||||||
|
compact.find("\"kinematics\":\"xyzbc-trt\"") != std::string::npos ||
|
||||||
|
compact.find("\"switchkins\":\"xyzbc-trt\"") != std::string::npos;
|
||||||
|
|
||||||
|
configured = find_number_any(compact, ¶meters.x_rot_point, "xrotpoint", "x_rot_point", "x-rot-point") ||
|
||||||
|
configured;
|
||||||
|
configured = find_number_any(compact, ¶meters.y_rot_point, "yrotpoint", "y_rot_point", "y-rot-point") ||
|
||||||
|
configured;
|
||||||
|
configured = find_number_any(compact, ¶meters.z_rot_point, "zrotpoint", "z_rot_point", "z-rot-point") ||
|
||||||
|
configured;
|
||||||
|
configured = find_number_any(compact, ¶meters.x_offset, "xoffset", "x_offset", "x-offset") ||
|
||||||
|
configured;
|
||||||
|
configured = find_number_any(compact, ¶meters.y_offset, "yoffset", "y_offset", "y-offset") ||
|
||||||
|
configured;
|
||||||
|
configured = find_number_any(compact, ¶meters.z_offset, "zoffset", "z_offset", "z-offset") ||
|
||||||
|
configured;
|
||||||
|
configured = contains_bool_any(compact,
|
||||||
|
¶meters.conventional_directions,
|
||||||
|
"conventionaldirections",
|
||||||
|
"conventional_directions",
|
||||||
|
"conventional-directions") ||
|
||||||
|
configured;
|
||||||
|
|
||||||
|
if (configured || xyzac || xyzbc) {
|
||||||
|
configured = true;
|
||||||
|
}
|
||||||
|
if (configured && xyzac) {
|
||||||
|
sink.configure_xyzac_trt(parameters);
|
||||||
|
} else if (configured) {
|
||||||
|
sink.configure_xyzbc_trt(parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_fiveaxis_config(CanonEventSink &sink, const std::string &compact) {
|
||||||
|
const bool fiveaxis = compact.find("\"kinematics\":\"5axiskins\"") != std::string::npos ||
|
||||||
|
compact.find("\"switchkins\":\"5axiskins\"") != std::string::npos ||
|
||||||
|
compact.find("\"kinematics\":\"5axis\"") != std::string::npos;
|
||||||
|
double pivot_length = 250.0;
|
||||||
|
const bool has_pivot_length = find_number_any(compact,
|
||||||
|
&pivot_length,
|
||||||
|
"pivotlength",
|
||||||
|
"pivot_length",
|
||||||
|
"pivot-length");
|
||||||
|
double kinematics_type = 0.0;
|
||||||
|
const bool has_kinematics_type = find_number_any(compact,
|
||||||
|
&kinematics_type,
|
||||||
|
"fiveaxiskinematicstype",
|
||||||
|
"fiveaxis_kinematics_type",
|
||||||
|
"fiveaxis-kinematics-type",
|
||||||
|
"kinematicstype",
|
||||||
|
"kinematics_type");
|
||||||
|
if (fiveaxis || has_pivot_length || has_kinematics_type) {
|
||||||
|
sink.configure_fiveaxis(pivot_length, static_cast<int>(kinematics_type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_switchkins_remap_config(CanonEventSink &sink, const std::string &compact) {
|
||||||
|
struct RemapSource {
|
||||||
|
const char *alias;
|
||||||
|
int m428_type;
|
||||||
|
int m429_type;
|
||||||
|
int m430_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generated from LinuxCNC INI REMAP/SUBROUTINE_PATH entries and the
|
||||||
|
// adjacent remap_subs #<kinstype> assignments.
|
||||||
|
static constexpr RemapSource kSources[] = {
|
||||||
|
#include "linuxcnc_switchkins_remap_table.inc"
|
||||||
|
};
|
||||||
|
|
||||||
|
const RemapSource *matched_source = nullptr;
|
||||||
|
size_t matched_alias_length = 0;
|
||||||
|
for (const RemapSource &source : kSources) {
|
||||||
|
if (contains_switchkins_config_alias(compact, source.alias)) {
|
||||||
|
const size_t alias_length = std::strlen(source.alias);
|
||||||
|
if (alias_length > matched_alias_length) {
|
||||||
|
matched_source = &source;
|
||||||
|
matched_alias_length = alias_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (matched_source) {
|
||||||
|
sink.configure_switchkins_remap(matched_source->m428_type,
|
||||||
|
matched_source->m429_type,
|
||||||
|
matched_source->m430_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int apply_config(CncSimHandle *handle, const std::string &json) {
|
int apply_config(CncSimHandle *handle, const std::string &json) {
|
||||||
if (json.empty()) {
|
if (json.empty()) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -143,6 +367,20 @@ int apply_config(CncSimHandle *handle, const std::string &json) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ini_file_name;
|
||||||
|
if (find_json_string_any(json,
|
||||||
|
&ini_file_name,
|
||||||
|
"ini",
|
||||||
|
"iniFile",
|
||||||
|
"inifile",
|
||||||
|
"iniFileName",
|
||||||
|
"inifilename",
|
||||||
|
"ini_file",
|
||||||
|
"ini_file_name",
|
||||||
|
"INI_FILE_NAME")) {
|
||||||
|
handle->backend_options.ini_file_name = ini_file_name;
|
||||||
|
}
|
||||||
|
|
||||||
bool rtcp_enabled = false;
|
bool rtcp_enabled = false;
|
||||||
double tool_length = 0.0;
|
double tool_length = 0.0;
|
||||||
const bool has_rtcp_enabled = contains_bool_value(compact, "rtcp", &rtcp_enabled) ||
|
const bool has_rtcp_enabled = contains_bool_value(compact, "rtcp", &rtcp_enabled) ||
|
||||||
@@ -152,7 +390,15 @@ int apply_config(CncSimHandle *handle, const std::string &json) {
|
|||||||
if (has_rtcp_enabled || has_tool_length) {
|
if (has_rtcp_enabled || has_tool_length) {
|
||||||
handle->sink.configure_rtcp(rtcp_enabled, tool_length);
|
handle->sink.configure_rtcp(rtcp_enabled, tool_length);
|
||||||
}
|
}
|
||||||
|
bool block_delete = false;
|
||||||
|
if (contains_bool_value(compact, "blockdelete", &block_delete) ||
|
||||||
|
contains_bool_value(compact, "block_delete", &block_delete)) {
|
||||||
|
handle->sink.set_block_delete(block_delete);
|
||||||
|
}
|
||||||
apply_tool_length_table(handle->sink, compact);
|
apply_tool_length_table(handle->sink, compact);
|
||||||
|
apply_switchkins_remap_config(handle->sink, compact);
|
||||||
|
apply_xyzbc_trt_config(handle->sink, compact);
|
||||||
|
apply_fiveaxis_config(handle->sink, compact);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +464,12 @@ int cnc_sim_parse_program(CncSimHandle *handle, const char *program, size_t prog
|
|||||||
}
|
}
|
||||||
|
|
||||||
handle->last_error.clear();
|
handle->last_error.clear();
|
||||||
const int rc = parse_gcode_with_backend(handle->backend, handle->sink, program, program_len, &handle->last_error);
|
const int rc = parse_gcode_with_backend(handle->backend,
|
||||||
|
handle->sink,
|
||||||
|
program,
|
||||||
|
program_len,
|
||||||
|
handle->backend_options,
|
||||||
|
&handle->last_error);
|
||||||
if (rc != 0 && handle->last_error.empty()) {
|
if (rc != 0 && handle->last_error.empty()) {
|
||||||
handle->last_error = "program parse failed";
|
handle->last_error = "program parse failed";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
#ifdef CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
#ifdef CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
||||||
#include "linuxcnc_rs274_backend.h"
|
#include "linuxcnc_rs274_backend.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CNC_SIM_ENABLE_SMOKE_BACKEND
|
||||||
#include "smoke_gcode_parser.h"
|
#include "smoke_gcode_parser.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
const char *gcode_backend_name(GcodeBackendKind backend) {
|
const char *gcode_backend_name(GcodeBackendKind backend) {
|
||||||
switch (backend) {
|
switch (backend) {
|
||||||
@@ -20,15 +22,23 @@ int parse_gcode_with_backend(GcodeBackendKind backend,
|
|||||||
CanonEventSink &sink,
|
CanonEventSink &sink,
|
||||||
const char *program,
|
const char *program,
|
||||||
size_t program_len,
|
size_t program_len,
|
||||||
|
const GcodeBackendOptions &options,
|
||||||
std::string *error) {
|
std::string *error) {
|
||||||
switch (backend) {
|
switch (backend) {
|
||||||
case GcodeBackendKind::Smoke: {
|
case GcodeBackendKind::Smoke: {
|
||||||
|
#ifdef CNC_SIM_ENABLE_SMOKE_BACKEND
|
||||||
SmokeGcodeParser parser(sink);
|
SmokeGcodeParser parser(sink);
|
||||||
return parser.parse(program, program_len, error);
|
return parser.parse(program, program_len, error);
|
||||||
|
#else
|
||||||
|
if (error) {
|
||||||
|
*error = "smoke backend is not compiled into this build";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
case GcodeBackendKind::LinuxCncRs274:
|
case GcodeBackendKind::LinuxCncRs274:
|
||||||
#ifdef CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
#ifdef CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
||||||
return parse_linuxcnc_rs274_backend(sink, program, program_len, error);
|
return parse_linuxcnc_rs274_backend(sink, program, program_len, options, error);
|
||||||
#else
|
#else
|
||||||
if (error) {
|
if (error) {
|
||||||
*error = "linuxcnc-rs274 backend is not compiled into this build";
|
*error = "linuxcnc-rs274 backend is not compiled into this build";
|
||||||
|
|||||||
@@ -10,11 +10,15 @@ enum class GcodeBackendKind {
|
|||||||
LinuxCncRs274,
|
LinuxCncRs274,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GcodeBackendOptions {
|
||||||
|
std::string ini_file_name;
|
||||||
|
};
|
||||||
|
|
||||||
const char *gcode_backend_name(GcodeBackendKind backend);
|
const char *gcode_backend_name(GcodeBackendKind backend);
|
||||||
|
|
||||||
int parse_gcode_with_backend(GcodeBackendKind backend,
|
int parse_gcode_with_backend(GcodeBackendKind backend,
|
||||||
CanonEventSink &sink,
|
CanonEventSink &sink,
|
||||||
const char *program,
|
const char *program,
|
||||||
size_t program_len,
|
size_t program_len,
|
||||||
|
const GcodeBackendOptions &options,
|
||||||
std::string *error);
|
std::string *error);
|
||||||
|
|
||||||
|
|||||||
266
core/src/linuxcnc_5axiskins_adapter.c
Normal file
266
core/src/linuxcnc_5axiskins_adapter.c
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_STRING_H
|
||||||
|
#define __LINUXCNC_RTAPI_CTYPE_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_EMCMOTCFG_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
#define SWITCHKINS_H
|
||||||
|
|
||||||
|
#define RTAPI_MSG_ERR 1
|
||||||
|
#define PM_PI 3.1415926535897932384626433832795029
|
||||||
|
#define TO_RAD (PM_PI / 180.0)
|
||||||
|
#define EMCMOT_MAX_JOINTS 16
|
||||||
|
#define EMCMOT_MAX_AXIS 9
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef int hal_s32_t;
|
||||||
|
typedef bool hal_bit_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
typedef int (*KF)(const double *joint,
|
||||||
|
EmcPose *pos,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags);
|
||||||
|
typedef int (*KI)(const struct EmcPose *world,
|
||||||
|
double *joint,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags);
|
||||||
|
typedef int (*KS)(const int comp_id, const char *coordinates, kparms *ksetup_parms);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int cnc_sim_axis_idx_for_jno[EMCMOT_MAX_JOINTS];
|
||||||
|
static int cnc_sim_max_joints;
|
||||||
|
|
||||||
|
void cnc_sim_5axis_rtapi_print(const char *fmt, ...) {
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_5axis_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||||
|
(void)level;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_5axis_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_5axis_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||||
|
hal_float_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_5axis_map_coordinates_to_jnumbers(const char *coordinates,
|
||||||
|
const int max_joints,
|
||||||
|
const int allow_duplicates,
|
||||||
|
int axis_idx_for_jno[]) {
|
||||||
|
(void)allow_duplicates;
|
||||||
|
const char *letters = "XYZABCUVW";
|
||||||
|
int jno = 0;
|
||||||
|
for (int i = 0; i < EMCMOT_MAX_JOINTS; ++i) {
|
||||||
|
axis_idx_for_jno[i] = -1;
|
||||||
|
cnc_sim_axis_idx_for_jno[i] = -1;
|
||||||
|
}
|
||||||
|
while (*coordinates) {
|
||||||
|
const char *found = strchr(letters, toupper((unsigned char)*coordinates));
|
||||||
|
if (!found || jno >= max_joints) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
axis_idx_for_jno[jno++] = (int)(found - letters);
|
||||||
|
++coordinates;
|
||||||
|
}
|
||||||
|
cnc_sim_max_joints = jno;
|
||||||
|
for (int i = 0; i < EMCMOT_MAX_JOINTS; ++i) {
|
||||||
|
cnc_sim_axis_idx_for_jno[i] = axis_idx_for_jno[i];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_5axis_position_to_mapped_joints(const int max_joints, const EmcPose *pos, double *joints) {
|
||||||
|
for (int jno = 0; jno < max_joints; ++jno) {
|
||||||
|
switch (cnc_sim_axis_idx_for_jno[jno]) {
|
||||||
|
case 0: joints[jno] = pos->tran.x; break;
|
||||||
|
case 1: joints[jno] = pos->tran.y; break;
|
||||||
|
case 2: joints[jno] = pos->tran.z; break;
|
||||||
|
case 3: joints[jno] = pos->a; break;
|
||||||
|
case 4: joints[jno] = pos->b; break;
|
||||||
|
case 5: joints[jno] = pos->c; break;
|
||||||
|
case 6: joints[jno] = pos->u; break;
|
||||||
|
case 7: joints[jno] = pos->v; break;
|
||||||
|
case 8: joints[jno] = pos->w; break;
|
||||||
|
default: joints[jno] = 0.0; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_5axis_identityKinematicsSetup(const int comp_id, const char *coordinates, kparms *ksetup_parms) {
|
||||||
|
(void)comp_id;
|
||||||
|
(void)coordinates;
|
||||||
|
(void)ksetup_parms;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_5axis_identityKinematicsForward(const double *joint,
|
||||||
|
EmcPose *world,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||||
|
(void)joint;
|
||||||
|
(void)world;
|
||||||
|
(void)fflags;
|
||||||
|
(void)iflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_5axis_identityKinematicsInverse(const EmcPose *world,
|
||||||
|
double *joint,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||||
|
(void)world;
|
||||||
|
(void)joint;
|
||||||
|
(void)iflags;
|
||||||
|
(void)fflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_5axis_userkKinematicsSetup(const int comp_id, const char *coordinates, kparms *ksetup_parms) {
|
||||||
|
(void)comp_id;
|
||||||
|
(void)coordinates;
|
||||||
|
(void)ksetup_parms;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_5axis_userkKinematicsForward(const double *joint,
|
||||||
|
EmcPose *world,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||||
|
(void)joint;
|
||||||
|
(void)world;
|
||||||
|
(void)fflags;
|
||||||
|
(void)iflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_5axis_userkKinematicsInverse(const EmcPose *pos,
|
||||||
|
double *joint,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||||
|
(void)pos;
|
||||||
|
(void)joint;
|
||||||
|
(void)iflags;
|
||||||
|
(void)fflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define rtapi_print cnc_sim_5axis_rtapi_print
|
||||||
|
#define rtapi_print_msg cnc_sim_5axis_rtapi_print_msg
|
||||||
|
#define hal_pin_float_newf cnc_sim_5axis_hal_pin_float_newf
|
||||||
|
#define map_coordinates_to_jnumbers cnc_sim_5axis_map_coordinates_to_jnumbers
|
||||||
|
#define position_to_mapped_joints cnc_sim_5axis_position_to_mapped_joints
|
||||||
|
#define identityKinematicsSetup cnc_sim_5axis_identityKinematicsSetup
|
||||||
|
#define identityKinematicsForward cnc_sim_5axis_identityKinematicsForward
|
||||||
|
#define identityKinematicsInverse cnc_sim_5axis_identityKinematicsInverse
|
||||||
|
#define userkKinematicsSetup cnc_sim_5axis_userkKinematicsSetup
|
||||||
|
#define userkKinematicsForward cnc_sim_5axis_userkKinematicsForward
|
||||||
|
#define userkKinematicsInverse cnc_sim_5axis_userkKinematicsInverse
|
||||||
|
#define switchkinsSetup cnc_sim_5axis_switchkinsSetup
|
||||||
|
#define haldata cnc_sim_5axis_haldata
|
||||||
|
#define hal_malloc(size) ((struct haldata *)cnc_sim_5axis_hal_malloc(size))
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/5axiskins.c"
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef haldata
|
||||||
|
#undef switchkinsSetup
|
||||||
|
#undef userkKinematicsInverse
|
||||||
|
#undef userkKinematicsForward
|
||||||
|
#undef userkKinematicsSetup
|
||||||
|
#undef identityKinematicsInverse
|
||||||
|
#undef identityKinematicsForward
|
||||||
|
#undef identityKinematicsSetup
|
||||||
|
#undef position_to_mapped_joints
|
||||||
|
#undef map_coordinates_to_jnumbers
|
||||||
|
#undef hal_pin_float_newf
|
||||||
|
#undef rtapi_print_msg
|
||||||
|
#undef rtapi_print
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_5axiskins_setup(void) {
|
||||||
|
kparms kp = {0};
|
||||||
|
static char kinsname[] = "5axiskins";
|
||||||
|
static char halprefix[] = "5axiskins";
|
||||||
|
static char required_coordinates[] = "XYZBCW";
|
||||||
|
kp.kinsname = kinsname;
|
||||||
|
kp.halprefix = halprefix;
|
||||||
|
kp.required_coordinates = required_coordinates;
|
||||||
|
kp.max_joints = EMCMOT_MAX_JOINTS;
|
||||||
|
kp.allow_duplicates = 1;
|
||||||
|
return fiveaxis_KinematicsSetup(0, "XYZBCW", &kp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_linuxcnc_5axiskins_set_pivot_length(double pivot_length) {
|
||||||
|
*cnc_sim_5axis_haldata->pivot_length = pivot_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_5axiskins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return fiveaxis_KinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_5axiskins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return fiveaxis_KinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
122
core/src/linuxcnc_5axiskins_adapter.cpp
Normal file
122
core/src/linuxcnc_5axiskins_adapter.cpp
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
#include "linuxcnc_5axiskins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_5axiskins_setup(void);
|
||||||
|
void cnc_sim_linuxcnc_5axiskins_set_pivot_length(double pivot_length);
|
||||||
|
int cnc_sim_linuxcnc_5axiskins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_5axiskins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_5axiskins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncFiveAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.b;
|
||||||
|
out[4] = joints.c;
|
||||||
|
out[5] = joints.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncFiveAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncFiveAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.b = joints[3];
|
||||||
|
out.c = joints[4];
|
||||||
|
out.w = joints[5];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_5axiskins_forward(const LinuxCncFiveAxisJoints &joints,
|
||||||
|
double pivot_length,
|
||||||
|
CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cnc_sim_linuxcnc_5axiskins_set_pivot_length(pivot_length);
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_5axiskins_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_5axiskins_inverse(const CncSimPose &pose,
|
||||||
|
double pivot_length,
|
||||||
|
LinuxCncFiveAxisJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cnc_sim_linuxcnc_5axiskins_set_pivot_length(pivot_length);
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
if (cnc_sim_linuxcnc_5axiskins_inverse(&in, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
10
core/src/linuxcnc_5axiskins_adapter.h
Normal file
10
core/src/linuxcnc_5axiskins_adapter.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_5axiskins_forward(const LinuxCncFiveAxisJoints &joints,
|
||||||
|
double pivot_length,
|
||||||
|
CncSimPose *pose);
|
||||||
|
bool linuxcnc_5axiskins_inverse(const CncSimPose &pose,
|
||||||
|
double pivot_length,
|
||||||
|
LinuxCncFiveAxisJoints *joints);
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr int kToolLengthOffsetEvent = 430;
|
||||||
|
|
||||||
CanonEventSink *active_sink = nullptr;
|
CanonEventSink *active_sink = nullptr;
|
||||||
int active_line = 0;
|
int active_line = 0;
|
||||||
bool flood_on = false;
|
bool flood_on = false;
|
||||||
@@ -26,6 +28,19 @@ double motion_control_tolerance = 0.0;
|
|||||||
double naivecam_tolerance = 0.0;
|
double naivecam_tolerance = 0.0;
|
||||||
std::string parameter_file_name = "rs274ngc.var";
|
std::string parameter_file_name = "rs274ngc.var";
|
||||||
|
|
||||||
|
void load_nonrandom_tool_to_spindle(int pocket) {
|
||||||
|
// LinuxCNC Task::load_tool() uses pocket 0 as the non-random
|
||||||
|
// toolchanger unload handshake. Do not eagerly mirror nonzero
|
||||||
|
// loads here; the source-linked interpreter observes its own
|
||||||
|
// post-canonical state before external task-side load completion.
|
||||||
|
if (pocket == 0) {
|
||||||
|
CANON_TOOL_TABLE unloaded = tooldata_entry_init();
|
||||||
|
unloaded.toolno = 0;
|
||||||
|
unloaded.pocketno = 0;
|
||||||
|
tooldata_put(unloaded, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CncSimPose make_pose(double x, double y, double z,
|
CncSimPose make_pose(double x, double y, double z,
|
||||||
double a, double b, double c,
|
double a, double b, double c,
|
||||||
double u, double v, double w) {
|
double u, double v, double w) {
|
||||||
@@ -50,6 +65,12 @@ int plane_to_g_code(CANON_PLANE plane) {
|
|||||||
return 18;
|
return 18;
|
||||||
case CANON_PLANE::YZ:
|
case CANON_PLANE::YZ:
|
||||||
return 19;
|
return 19;
|
||||||
|
case CANON_PLANE::UV:
|
||||||
|
return 171;
|
||||||
|
case CANON_PLANE::UW:
|
||||||
|
return 181;
|
||||||
|
case CANON_PLANE::VW:
|
||||||
|
return 191;
|
||||||
default:
|
default:
|
||||||
return 17;
|
return 17;
|
||||||
}
|
}
|
||||||
@@ -73,6 +94,12 @@ CANON_PLANE g_code_to_plane(int plane) {
|
|||||||
return CANON_PLANE::XZ;
|
return CANON_PLANE::XZ;
|
||||||
case 19:
|
case 19:
|
||||||
return CANON_PLANE::YZ;
|
return CANON_PLANE::YZ;
|
||||||
|
case 171:
|
||||||
|
return CANON_PLANE::UV;
|
||||||
|
case 181:
|
||||||
|
return CANON_PLANE::UW;
|
||||||
|
case 191:
|
||||||
|
return CANON_PLANE::VW;
|
||||||
case 17:
|
case 17:
|
||||||
default:
|
default:
|
||||||
return CANON_PLANE::XY;
|
return CANON_PLANE::XY;
|
||||||
@@ -84,6 +111,27 @@ const CncSimPose ¤t_position() {
|
|||||||
return active_sink ? active_sink->position() : zero;
|
return active_sink ? active_sink->position() : zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename NurbsPoint>
|
||||||
|
CncSimPose nurbs_plane_point_to_pose(const NurbsPoint &point, CANON_PLANE plane) {
|
||||||
|
CncSimPose end = current_position();
|
||||||
|
switch (plane) {
|
||||||
|
case CANON_PLANE::YZ:
|
||||||
|
end.y = point.NURBS_X;
|
||||||
|
end.z = point.NURBS_Y;
|
||||||
|
break;
|
||||||
|
case CANON_PLANE::XZ:
|
||||||
|
end.x = point.NURBS_Y;
|
||||||
|
end.z = point.NURBS_X;
|
||||||
|
break;
|
||||||
|
case CANON_PLANE::XY:
|
||||||
|
default:
|
||||||
|
end.x = point.NURBS_X;
|
||||||
|
end.y = point.NURBS_Y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
void trace_call(const char *name) {
|
void trace_call(const char *name) {
|
||||||
if (std::getenv("CNC_SIM_TRACE_CANON")) {
|
if (std::getenv("CNC_SIM_TRACE_CANON")) {
|
||||||
std::fprintf(stderr, "canon:%s\n", name);
|
std::fprintf(stderr, "canon:%s\n", name);
|
||||||
@@ -145,7 +193,7 @@ void INIT_CANON() {
|
|||||||
void USE_LENGTH_UNITS(CANON_UNITS units) {
|
void USE_LENGTH_UNITS(CANON_UNITS units) {
|
||||||
trace_call("USE_LENGTH_UNITS");
|
trace_call("USE_LENGTH_UNITS");
|
||||||
if (active_sink) {
|
if (active_sink) {
|
||||||
active_sink->use_length_units(units_to_scale(units), event_line());
|
active_sink->use_length_units(units_to_scale(units), event_line(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,10 +211,10 @@ void SET_FEED_RATE(double rate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SET_SPINDLE_SPEED(int, double speed) {
|
void SET_SPINDLE_SPEED(int spindle, double speed) {
|
||||||
trace_call("SET_SPINDLE_SPEED");
|
trace_call("SET_SPINDLE_SPEED");
|
||||||
if (active_sink) {
|
if (active_sink) {
|
||||||
active_sink->set_spindle_speed(speed, event_line());
|
active_sink->set_spindle_speed(spindle, speed, event_line());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +228,10 @@ void SELECT_TOOL(int tool) {
|
|||||||
void CHANGE_TOOL() {
|
void CHANGE_TOOL() {
|
||||||
trace_call("CHANGE_TOOL");
|
trace_call("CHANGE_TOOL");
|
||||||
if (active_sink) {
|
if (active_sink) {
|
||||||
|
const int selected_tool = active_sink->selected_tool();
|
||||||
|
if (selected_tool == 0) {
|
||||||
|
load_nonrandom_tool_to_spindle(0);
|
||||||
|
}
|
||||||
active_sink->change_tool(event_line());
|
active_sink->change_tool(event_line());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,6 +402,15 @@ void SET_MOTION_CONTROL_MODE(CANON_MOTION_MODE mode, double tolerance) {
|
|||||||
|
|
||||||
void SET_NAIVECAM_TOLERANCE(double tolerance) {
|
void SET_NAIVECAM_TOLERANCE(double tolerance) {
|
||||||
naivecam_tolerance = tolerance;
|
naivecam_tolerance = tolerance;
|
||||||
|
if (active_sink) {
|
||||||
|
CncSimEvent event{};
|
||||||
|
event.version = 1;
|
||||||
|
event.type = CNC_SIM_EVENT_COMMENT;
|
||||||
|
event.line = event_line();
|
||||||
|
event.feed = tolerance;
|
||||||
|
event.reserved = 641;
|
||||||
|
active_sink->emit_raw(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SET_CUTTER_RADIUS_COMPENSATION(double) {
|
void SET_CUTTER_RADIUS_COMPENSATION(double) {
|
||||||
@@ -373,27 +434,21 @@ void STOP_SPEED_FEED_SYNCH() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NURBS_G5_FEED(int lineno, const std::vector<NURBS_CONTROL_POINT> &points, unsigned int, CANON_PLANE) {
|
void NURBS_G5_FEED(int lineno, const std::vector<NURBS_CONTROL_POINT> &points, unsigned int, CANON_PLANE plane) {
|
||||||
if (!active_sink) {
|
if (!active_sink) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const auto &point : points) {
|
for (const auto &point : points) {
|
||||||
CncSimPose end = active_sink->position();
|
active_sink->straight_feed(event_line(lineno), nurbs_plane_point_to_pose(point, plane));
|
||||||
end.x = point.NURBS_X;
|
|
||||||
end.y = point.NURBS_Y;
|
|
||||||
active_sink->straight_feed(lineno, end);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NURBS_G6_FEED(int lineno, const std::vector<NURBS_G6_CONTROL_POINT> &points, unsigned int, double, int, CANON_PLANE) {
|
void NURBS_G6_FEED(int lineno, const std::vector<NURBS_G6_CONTROL_POINT> &points, unsigned int, double, int, CANON_PLANE plane) {
|
||||||
if (!active_sink) {
|
if (!active_sink) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const auto &point : points) {
|
for (const auto &point : points) {
|
||||||
CncSimPose end = active_sink->position();
|
active_sink->straight_feed(event_line(lineno), nurbs_plane_point_to_pose(point, plane));
|
||||||
end.x = point.NURBS_X;
|
|
||||||
end.y = point.NURBS_Y;
|
|
||||||
active_sink->straight_feed(lineno, end);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,21 +486,21 @@ void SET_SPINDLE_MODE(int spindle, double mode) {
|
|||||||
void SPINDLE_RETRACT_TRAVERSE() {
|
void SPINDLE_RETRACT_TRAVERSE() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void START_SPINDLE_CLOCKWISE(int, int) {
|
void START_SPINDLE_CLOCKWISE(int spindle, int) {
|
||||||
if (active_sink) {
|
if (active_sink) {
|
||||||
active_sink->start_spindle(1, event_line());
|
active_sink->start_spindle(spindle, 1, event_line());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void START_SPINDLE_COUNTERCLOCKWISE(int, int) {
|
void START_SPINDLE_COUNTERCLOCKWISE(int spindle, int) {
|
||||||
if (active_sink) {
|
if (active_sink) {
|
||||||
active_sink->start_spindle(-1, event_line());
|
active_sink->start_spindle(spindle, -1, event_line());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void STOP_SPINDLE_TURNING(int) {
|
void STOP_SPINDLE_TURNING(int spindle) {
|
||||||
if (active_sink) {
|
if (active_sink) {
|
||||||
active_sink->stop_spindle(event_line());
|
active_sink->stop_spindle(spindle, event_line());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,13 +543,14 @@ void USE_TOOL_LENGTH_OFFSET(const EmcPose &offset) {
|
|||||||
event.version = 1;
|
event.version = 1;
|
||||||
event.type = CNC_SIM_EVENT_COMMENT;
|
event.type = CNC_SIM_EVENT_COMMENT;
|
||||||
event.line = event_line();
|
event.line = event_line();
|
||||||
event.reserved = 430;
|
event.reserved = kToolLengthOffsetEvent;
|
||||||
event.start = tool_offset;
|
event.start = tool_offset;
|
||||||
active_sink->emit_raw(event);
|
active_sink->emit_raw(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHANGE_TOOL_NUMBER(int number) {
|
void CHANGE_TOOL_NUMBER(int number) {
|
||||||
if (active_sink) {
|
if (active_sink) {
|
||||||
|
load_nonrandom_tool_to_spindle(number);
|
||||||
active_sink->select_tool(number);
|
active_sink->select_tool(number);
|
||||||
active_sink->change_tool(event_line());
|
active_sink->change_tool(event_line());
|
||||||
}
|
}
|
||||||
@@ -726,11 +782,16 @@ int GET_EXTERNAL_FLOOD() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CANON_UNITS GET_EXTERNAL_LENGTH_UNIT_TYPE() {
|
CANON_UNITS GET_EXTERNAL_LENGTH_UNIT_TYPE() {
|
||||||
return active_sink && active_sink->unit_scale() == 25.4 ? CANON_UNITS_INCHES : CANON_UNITS_MM;
|
// LinuxCNC src/emc/task/emccanon.cc derives this from INI machine/user
|
||||||
|
// units, not from the active G20/G21 program units.
|
||||||
|
return CANON_UNITS_MM;
|
||||||
}
|
}
|
||||||
|
|
||||||
double GET_EXTERNAL_LENGTH_UNITS() {
|
double GET_EXTERNAL_LENGTH_UNITS() {
|
||||||
return active_sink ? active_sink->unit_scale() : 1.0;
|
// LinuxCNC src/emc/task/emccanon.cc returns traj.linearUnits here:
|
||||||
|
// external/user units per internal millimeter. The simulator has no INI
|
||||||
|
// machine-units bridge yet, so the source-linked default is metric.
|
||||||
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double GET_EXTERNAL_ANGLE_UNITS() {
|
double GET_EXTERNAL_ANGLE_UNITS() {
|
||||||
|
|||||||
127
core/src/linuxcnc_corexykins_adapter.c
Normal file
127
core/src/linuxcnc_corexykins_adapter.c
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_APP_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_STRING_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_EMCMOTCFG_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
|
||||||
|
#define MODULE_LICENSE(...)
|
||||||
|
#define EXPORT_SYMBOL(symbol)
|
||||||
|
#define RTAPI_MSG_ERR 1
|
||||||
|
#define EMCMOT_MAX_JOINTS 16
|
||||||
|
typedef int hal_s32_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#define KINS_NOT_SWITCHABLE \
|
||||||
|
extern int kinematicsSwitchable() { return 0; } \
|
||||||
|
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int cnc_sim_corexykins_hal_init(const char *name) {
|
||||||
|
(void)name;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_corexykins_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_corexykins_hal_ready(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_corexykins_hal_exit(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define hal_init cnc_sim_corexykins_hal_init
|
||||||
|
#define hal_malloc(size) ((struct data *)cnc_sim_corexykins_hal_malloc(size))
|
||||||
|
#define hal_ready cnc_sim_corexykins_hal_ready
|
||||||
|
#define hal_exit cnc_sim_corexykins_hal_exit
|
||||||
|
#define kinematicsType cnc_sim_corexykins_kinematicsType
|
||||||
|
#define kinematicsForward cnc_sim_corexykins_kinematicsForward
|
||||||
|
#define kinematicsInverse cnc_sim_corexykins_kinematicsInverse
|
||||||
|
#define kinematicsHome cnc_sim_corexykins_kinematicsHome
|
||||||
|
#define kinematicsSwitchable cnc_sim_corexykins_kinematicsSwitchable
|
||||||
|
#define kinematicsSwitch cnc_sim_corexykins_kinematicsSwitch
|
||||||
|
#define rtapi_app_main cnc_sim_corexykins_rtapi_app_main
|
||||||
|
#define rtapi_app_exit cnc_sim_corexykins_rtapi_app_exit
|
||||||
|
#define comp_id cnc_sim_corexykins_comp_id
|
||||||
|
#define data cnc_sim_corexykins_data
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/corexykins.c"
|
||||||
|
#undef data
|
||||||
|
#undef comp_id
|
||||||
|
#undef rtapi_app_exit
|
||||||
|
#undef rtapi_app_main
|
||||||
|
#undef kinematicsSwitch
|
||||||
|
#undef kinematicsSwitchable
|
||||||
|
#undef kinematicsHome
|
||||||
|
#undef kinematicsInverse
|
||||||
|
#undef kinematicsForward
|
||||||
|
#undef kinematicsType
|
||||||
|
#undef hal_exit
|
||||||
|
#undef hal_ready
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef hal_init
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_corexykins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_corexykins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_corexykins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_corexykins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
104
core/src/linuxcnc_corexykins_adapter.cpp
Normal file
104
core/src/linuxcnc_corexykins_adapter.cpp
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#include "linuxcnc_corexykins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_corexykins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_corexykins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.a;
|
||||||
|
out[4] = joints.b;
|
||||||
|
out[5] = joints.c;
|
||||||
|
out[6] = joints.u;
|
||||||
|
out[7] = joints.v;
|
||||||
|
out[8] = joints.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.a = joints[3];
|
||||||
|
out.b = joints[4];
|
||||||
|
out.c = joints[5];
|
||||||
|
out.u = joints[6];
|
||||||
|
out.v = joints[7];
|
||||||
|
out.w = joints[8];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_corexykins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose) {
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_corexykins_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_corexykins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints) {
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
if (cnc_sim_linuxcnc_corexykins_inverse(&in, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
6
core/src/linuxcnc_corexykins_adapter.h
Normal file
6
core/src/linuxcnc_corexykins_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_corexykins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose);
|
||||||
|
bool linuxcnc_corexykins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints);
|
||||||
117
core/src/linuxcnc_cubic_adapter.c
Normal file
117
core/src/linuxcnc_cubic_adapter.c
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double d;
|
||||||
|
} CUBIC_COEFF;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int configured;
|
||||||
|
double segmentTime;
|
||||||
|
int interpolationRate;
|
||||||
|
double interpolationTime;
|
||||||
|
double interpolationIncrement;
|
||||||
|
double x0, x1, x2, x3;
|
||||||
|
double wp0, wp1;
|
||||||
|
double velp0, velp1;
|
||||||
|
int filled;
|
||||||
|
int needNextPoint;
|
||||||
|
CUBIC_COEFF coeff;
|
||||||
|
} CUBIC_STRUCT;
|
||||||
|
|
||||||
|
#define CUBIC_H
|
||||||
|
#define cubicInit cnc_sim_cubic_cubicInit
|
||||||
|
#define cubicSetSegmentTime cnc_sim_cubic_cubicSetSegmentTime
|
||||||
|
#define cubicGetSegmentTime cnc_sim_cubic_cubicGetSegmentTime
|
||||||
|
#define cubicSetInterpolationRate cnc_sim_cubic_cubicSetInterpolationRate
|
||||||
|
#define cubicGetInterpolationRate cnc_sim_cubic_cubicGetInterpolationRate
|
||||||
|
#define cubicAddPoint cnc_sim_cubic_cubicAddPoint
|
||||||
|
#define cubicOffset cnc_sim_cubic_cubicOffset
|
||||||
|
#define cubicGetInterpolationIncrement cnc_sim_cubic_cubicGetInterpolationIncrement
|
||||||
|
#define cubicGetCubicCoeff cnc_sim_cubic_cubicGetCubicCoeff
|
||||||
|
#define cubicFilled cnc_sim_cubic_cubicFilled
|
||||||
|
#define cubicInterpolate cnc_sim_cubic_cubicInterpolate
|
||||||
|
#define cubicNeedNextPoint cnc_sim_cubic_cubicNeedNextPoint
|
||||||
|
#define cubicDrain cnc_sim_cubic_cubicDrain
|
||||||
|
int cubicInit(CUBIC_STRUCT *ci);
|
||||||
|
int cubicSetSegmentTime(CUBIC_STRUCT *ci, double time);
|
||||||
|
double cubicGetSegmentTime(CUBIC_STRUCT *ci);
|
||||||
|
int cubicSetInterpolationRate(CUBIC_STRUCT *ci, int rate);
|
||||||
|
int cubicGetInterpolationRate(CUBIC_STRUCT *ci);
|
||||||
|
int cubicAddPoint(CUBIC_STRUCT *ci, double point);
|
||||||
|
int cubicOffset(CUBIC_STRUCT *ci, double offset);
|
||||||
|
double cubicGetInterpolationIncrement(CUBIC_STRUCT *ci);
|
||||||
|
CUBIC_COEFF cubicGetCubicCoeff(CUBIC_STRUCT *ci);
|
||||||
|
int cubicFilled(CUBIC_STRUCT *ci);
|
||||||
|
double cubicInterpolate(CUBIC_STRUCT *ci, double *x, double *v, double *a, double *j);
|
||||||
|
int cubicNeedNextPoint(CUBIC_STRUCT *ci);
|
||||||
|
int cubicDrain(CUBIC_STRUCT *ci);
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/cubic.c"
|
||||||
|
#undef cubicDrain
|
||||||
|
#undef cubicNeedNextPoint
|
||||||
|
#undef cubicInterpolate
|
||||||
|
#undef cubicFilled
|
||||||
|
#undef cubicGetCubicCoeff
|
||||||
|
#undef cubicGetInterpolationIncrement
|
||||||
|
#undef cubicOffset
|
||||||
|
#undef cubicAddPoint
|
||||||
|
#undef cubicGetInterpolationRate
|
||||||
|
#undef cubicSetInterpolationRate
|
||||||
|
#undef cubicGetSegmentTime
|
||||||
|
#undef cubicSetSegmentTime
|
||||||
|
#undef cubicInit
|
||||||
|
#undef CUBIC_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_cubic_second_segment_samples(double *x,
|
||||||
|
double *v,
|
||||||
|
double *a,
|
||||||
|
double *j,
|
||||||
|
int sample_count) {
|
||||||
|
if (!x || !v || !a || !j || sample_count != 4) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUBIC_STRUCT cubic;
|
||||||
|
if (cnc_sim_cubic_cubicInit(&cubic) != 0 ||
|
||||||
|
cnc_sim_cubic_cubicSetSegmentTime(&cubic, 1.0) != 0 ||
|
||||||
|
cnc_sim_cubic_cubicSetInterpolationRate(&cubic, 4) != 0 ||
|
||||||
|
cnc_sim_cubic_cubicAddPoint(&cubic, 0.0) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
cnc_sim_cubic_cubicInterpolate(&cubic, NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
if (!cnc_sim_cubic_cubicNeedNextPoint(&cubic) ||
|
||||||
|
cnc_sim_cubic_cubicAddPoint(&cubic, 10.0) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < sample_count; ++i) {
|
||||||
|
x[i] = cnc_sim_cubic_cubicInterpolate(&cubic, &x[i], &v[i], &a[i], &j[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cnc_sim_cubic_cubicNeedNextPoint(&cubic) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_cubic_rejects_invalid_configuration(void) {
|
||||||
|
CUBIC_STRUCT cubic;
|
||||||
|
return cnc_sim_cubic_cubicInit(&cubic) == 0 &&
|
||||||
|
cnc_sim_cubic_cubicSetSegmentTime(&cubic, 0.0) != 0 &&
|
||||||
|
cnc_sim_cubic_cubicSetInterpolationRate(&cubic, 0) != 0 &&
|
||||||
|
cnc_sim_cubic_cubicAddPoint(&cubic, 1.0) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
36
core/src/linuxcnc_cubic_adapter.cpp
Normal file
36
core/src/linuxcnc_cubic_adapter.cpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include "linuxcnc_cubic_adapter.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
int cnc_sim_linuxcnc_cubic_second_segment_samples(double *x,
|
||||||
|
double *v,
|
||||||
|
double *a,
|
||||||
|
double *j,
|
||||||
|
int sample_count);
|
||||||
|
int cnc_sim_linuxcnc_cubic_rejects_invalid_configuration(void);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_cubic_source_second_segment_samples(LinuxCncCubicSample *samples, int sample_count) {
|
||||||
|
if (!samples || sample_count != 4) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double x[4] = {};
|
||||||
|
double v[4] = {};
|
||||||
|
double a[4] = {};
|
||||||
|
double j[4] = {};
|
||||||
|
if (cnc_sim_linuxcnc_cubic_second_segment_samples(x, v, a, j, sample_count) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < sample_count; ++i) {
|
||||||
|
samples[i].x = x[i];
|
||||||
|
samples[i].v = v[i];
|
||||||
|
samples[i].a = a[i];
|
||||||
|
samples[i].j = j[i];
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_cubic_source_rejects_invalid_configuration() {
|
||||||
|
return cnc_sim_linuxcnc_cubic_rejects_invalid_configuration() != 0;
|
||||||
|
}
|
||||||
11
core/src/linuxcnc_cubic_adapter.h
Normal file
11
core/src/linuxcnc_cubic_adapter.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct LinuxCncCubicSample {
|
||||||
|
double x;
|
||||||
|
double v;
|
||||||
|
double a;
|
||||||
|
double j;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool linuxcnc_cubic_source_second_segment_samples(LinuxCncCubicSample *samples, int sample_count);
|
||||||
|
bool linuxcnc_cubic_source_rejects_invalid_configuration();
|
||||||
223
core/src/linuxcnc_genhexkins_adapter.c
Normal file
223
core/src/linuxcnc_genhexkins_adapter.c
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_STRING_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_EMCMOTCFG_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
#define SWITCHKINS_H
|
||||||
|
|
||||||
|
#define RTAPI_MSG_ERR 1
|
||||||
|
#define RTAPI_MSG_INFO 2
|
||||||
|
#define EMCMOT_MAX_JOINTS 16
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef int hal_bit_t;
|
||||||
|
typedef uint32_t hal_u32_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
#include "../../../linuxcnc/src/libnml/posemath/posemath.h"
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
typedef int (*KF)(const double *joint,
|
||||||
|
EmcPose *pos,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags);
|
||||||
|
typedef int (*KI)(const EmcPose *world,
|
||||||
|
double *joint,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags);
|
||||||
|
typedef int (*KS)(const int comp_id, const char *coordinates, kparms *ksetup_parms);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void cnc_sim_genhex_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||||
|
(void)level;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_genhex_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_genhex_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||||
|
hal_float_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_genhex_hal_pin_u32_newf(hal_pin_dir_t dir,
|
||||||
|
hal_u32_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_u32_t *)calloc(1, sizeof(hal_u32_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_genhex_hal_pin_bit_newf(hal_pin_dir_t dir,
|
||||||
|
hal_bit_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_bit_t *)calloc(1, sizeof(hal_bit_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_genhex_identityKinematicsSetup(const int comp_id, const char *coordinates, kparms *ksetup_parms) {
|
||||||
|
(void)comp_id;
|
||||||
|
(void)coordinates;
|
||||||
|
(void)ksetup_parms;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_genhex_identityKinematicsForward(const double *joint,
|
||||||
|
EmcPose *world,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||||
|
(void)joint;
|
||||||
|
(void)world;
|
||||||
|
(void)fflags;
|
||||||
|
(void)iflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_genhex_identityKinematicsInverse(const EmcPose *world,
|
||||||
|
double *joint,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||||
|
(void)world;
|
||||||
|
(void)joint;
|
||||||
|
(void)iflags;
|
||||||
|
(void)fflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_genhex_userkKinematicsSetup(const int comp_id, const char *coordinates, kparms *ksetup_parms) {
|
||||||
|
(void)comp_id;
|
||||||
|
(void)coordinates;
|
||||||
|
(void)ksetup_parms;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_genhex_userkKinematicsForward(const double *joint,
|
||||||
|
EmcPose *world,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||||
|
(void)joint;
|
||||||
|
(void)world;
|
||||||
|
(void)fflags;
|
||||||
|
(void)iflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_genhex_userkKinematicsInverse(const EmcPose *world,
|
||||||
|
double *joint,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||||
|
(void)world;
|
||||||
|
(void)joint;
|
||||||
|
(void)iflags;
|
||||||
|
(void)fflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define rtapi_print_msg cnc_sim_genhex_rtapi_print_msg
|
||||||
|
#define hal_pin_float_newf cnc_sim_genhex_hal_pin_float_newf
|
||||||
|
#define hal_pin_u32_newf cnc_sim_genhex_hal_pin_u32_newf
|
||||||
|
#define hal_pin_bit_newf cnc_sim_genhex_hal_pin_bit_newf
|
||||||
|
#define identityKinematicsSetup cnc_sim_genhex_identityKinematicsSetup
|
||||||
|
#define identityKinematicsForward cnc_sim_genhex_identityKinematicsForward
|
||||||
|
#define identityKinematicsInverse cnc_sim_genhex_identityKinematicsInverse
|
||||||
|
#define userkKinematicsSetup cnc_sim_genhex_userkKinematicsSetup
|
||||||
|
#define userkKinematicsForward cnc_sim_genhex_userkKinematicsForward
|
||||||
|
#define userkKinematicsInverse cnc_sim_genhex_userkKinematicsInverse
|
||||||
|
#define switchkinsSetup cnc_sim_genhex_switchkinsSetup
|
||||||
|
#define haldata cnc_sim_genhex_haldata
|
||||||
|
#define hal_malloc(size) ((struct haldata *)cnc_sim_genhex_hal_malloc(size))
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/genhexkins.c"
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef haldata
|
||||||
|
#undef switchkinsSetup
|
||||||
|
#undef userkKinematicsInverse
|
||||||
|
#undef userkKinematicsForward
|
||||||
|
#undef userkKinematicsSetup
|
||||||
|
#undef identityKinematicsInverse
|
||||||
|
#undef identityKinematicsForward
|
||||||
|
#undef identityKinematicsSetup
|
||||||
|
#undef hal_pin_bit_newf
|
||||||
|
#undef hal_pin_u32_newf
|
||||||
|
#undef hal_pin_float_newf
|
||||||
|
#undef rtapi_print_msg
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_genhexkins_setup(void) {
|
||||||
|
kparms kp;
|
||||||
|
memset(&kp, 0, sizeof(kp));
|
||||||
|
static char kinsname[] = "genhexkins";
|
||||||
|
static char halprefix[] = "genhexkins";
|
||||||
|
kp.kinsname = kinsname;
|
||||||
|
kp.halprefix = halprefix;
|
||||||
|
kp.max_joints = NUM_STRUTS;
|
||||||
|
return genhexKinematicsSetup(0, "XYZABC", &kp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_genhexkins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return genhexKinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_genhexkins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return genhexKinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
96
core/src/linuxcnc_genhexkins_adapter.cpp
Normal file
96
core/src/linuxcnc_genhexkins_adapter.cpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include "linuxcnc_genhexkins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_genhexkins_setup(void);
|
||||||
|
int cnc_sim_linuxcnc_genhexkins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_genhexkins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_genhexkins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_genhexkins_source_forward(const LinuxCncGenhexJoints &joints,
|
||||||
|
const CncSimPose &initial_pose,
|
||||||
|
CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
double raw_joints[6];
|
||||||
|
std::memcpy(raw_joints, joints.strut, sizeof(raw_joints));
|
||||||
|
EmcPose emc_pose = to_emc_pose(initial_pose);
|
||||||
|
if (cnc_sim_linuxcnc_genhexkins_forward(raw_joints, &emc_pose) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(emc_pose);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_genhexkins_source_inverse(const CncSimPose &pose, LinuxCncGenhexJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const EmcPose emc_pose = to_emc_pose(pose);
|
||||||
|
double raw_joints[6] = {};
|
||||||
|
if (cnc_sim_linuxcnc_genhexkins_inverse(&emc_pose, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::memcpy(joints->strut, raw_joints, sizeof(raw_joints));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
8
core/src/linuxcnc_genhexkins_adapter.h
Normal file
8
core/src/linuxcnc_genhexkins_adapter.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_genhexkins_source_forward(const LinuxCncGenhexJoints &joints,
|
||||||
|
const CncSimPose &initial_pose,
|
||||||
|
CncSimPose *pose);
|
||||||
|
bool linuxcnc_genhexkins_source_inverse(const CncSimPose &pose, LinuxCncGenhexJoints *joints);
|
||||||
206
core/src/linuxcnc_genserfuncs_adapter.c
Normal file
206
core/src/linuxcnc_genserfuncs_adapter.c
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_STRING_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
|
||||||
|
#define RTAPI_MSG_ERR 1
|
||||||
|
#define PM_PI 3.1415926535897932384626433832795029
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef unsigned int hal_u32_t;
|
||||||
|
typedef int hal_s32_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void cnc_sim_genser_rtapi_print(const char *fmt, ...) {
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_genser_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||||
|
(void)level;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_genser_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_genser_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||||
|
hal_float_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_genser_hal_pin_u32_newf(hal_pin_dir_t dir,
|
||||||
|
hal_u32_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_u32_t *)calloc(1, sizeof(hal_u32_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_genser_hal_pin_s32_newf(hal_pin_dir_t dir,
|
||||||
|
hal_s32_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_s32_t *)calloc(1, sizeof(hal_s32_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define rtapi_print cnc_sim_genser_rtapi_print
|
||||||
|
#define rtapi_print_msg cnc_sim_genser_rtapi_print_msg
|
||||||
|
#define hal_pin_float_newf cnc_sim_genser_hal_pin_float_newf
|
||||||
|
#define hal_pin_u32_newf cnc_sim_genser_hal_pin_u32_newf
|
||||||
|
#define hal_pin_s32_newf cnc_sim_genser_hal_pin_s32_newf
|
||||||
|
#define pm_sincos cnc_sim_genser_pm_sincos
|
||||||
|
#include "../../../linuxcnc/src/libnml/posemath/sincos.c"
|
||||||
|
#include "../../../linuxcnc/src/libnml/posemath/gomath.c"
|
||||||
|
#define hal_malloc(size) cnc_sim_genser_hal_malloc(size)
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/genserfuncs.c"
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef pm_sincos
|
||||||
|
#undef hal_pin_s32_newf
|
||||||
|
#undef hal_pin_u32_newf
|
||||||
|
#undef hal_pin_float_newf
|
||||||
|
#undef rtapi_print_msg
|
||||||
|
#undef rtapi_print
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_genserfuncs_setup(void) {
|
||||||
|
kparms kp = {0};
|
||||||
|
static char kinsname[] = "genserkins";
|
||||||
|
static char halprefix[] = "genserkins";
|
||||||
|
kp.kinsname = kinsname;
|
||||||
|
kp.halprefix = halprefix;
|
||||||
|
kp.max_joints = 6;
|
||||||
|
return genserKinematicsSetup(0, "XYZABC", &kp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_linuxcnc_genserfuncs_set_parameters(const double *a,
|
||||||
|
const double *alpha,
|
||||||
|
const double *d,
|
||||||
|
const int *unrotate,
|
||||||
|
int max_iterations) {
|
||||||
|
for (int i = 0; i < GENSER_MAX_JOINTS; ++i) {
|
||||||
|
*haldata->a[i] = a[i];
|
||||||
|
*haldata->alpha[i] = alpha[i];
|
||||||
|
*haldata->d[i] = d[i];
|
||||||
|
*haldata->unrotate[i] = unrotate[i];
|
||||||
|
}
|
||||||
|
*haldata->max_iterations = (hal_u32_t)max_iterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_linuxcnc_genserfuncs_default_parameters(double *a,
|
||||||
|
double *alpha,
|
||||||
|
double *d,
|
||||||
|
int *unrotate,
|
||||||
|
int *max_iterations) {
|
||||||
|
const double default_a[GENSER_MAX_JOINTS] = {
|
||||||
|
DEFAULT_A1,
|
||||||
|
DEFAULT_A2,
|
||||||
|
DEFAULT_A3,
|
||||||
|
DEFAULT_A4,
|
||||||
|
DEFAULT_A5,
|
||||||
|
DEFAULT_A6,
|
||||||
|
};
|
||||||
|
const double default_alpha[GENSER_MAX_JOINTS] = {
|
||||||
|
DEFAULT_ALPHA1,
|
||||||
|
DEFAULT_ALPHA2,
|
||||||
|
DEFAULT_ALPHA3,
|
||||||
|
DEFAULT_ALPHA4,
|
||||||
|
DEFAULT_ALPHA5,
|
||||||
|
DEFAULT_ALPHA6,
|
||||||
|
};
|
||||||
|
const double default_d[GENSER_MAX_JOINTS] = {
|
||||||
|
DEFAULT_D1,
|
||||||
|
DEFAULT_D2,
|
||||||
|
DEFAULT_D3,
|
||||||
|
DEFAULT_D4,
|
||||||
|
DEFAULT_D5,
|
||||||
|
DEFAULT_D6,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < GENSER_MAX_JOINTS; ++i) {
|
||||||
|
a[i] = default_a[i];
|
||||||
|
alpha[i] = default_alpha[i];
|
||||||
|
d[i] = default_d[i];
|
||||||
|
unrotate[i] = 0;
|
||||||
|
}
|
||||||
|
*max_iterations = GENSER_DEFAULT_MAX_ITERATIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_genserfuncs_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return genserKinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_genserfuncs_inverse(const EmcPose *pos, double *joints, int *iterations) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
const int result = genserKinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
if (iterations) {
|
||||||
|
*iterations = genser_kin_inv_iterations(KINS_PTR);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
166
core/src/linuxcnc_genserfuncs_adapter.cpp
Normal file
166
core/src/linuxcnc_genserfuncs_adapter.cpp
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
#include "linuxcnc_genserfuncs_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_genserfuncs_setup(void);
|
||||||
|
void cnc_sim_linuxcnc_genserfuncs_set_parameters(const double *a,
|
||||||
|
const double *alpha,
|
||||||
|
const double *d,
|
||||||
|
const int *unrotate,
|
||||||
|
int max_iterations);
|
||||||
|
void cnc_sim_linuxcnc_genserfuncs_default_parameters(double *a,
|
||||||
|
double *alpha,
|
||||||
|
double *d,
|
||||||
|
int *unrotate,
|
||||||
|
int *max_iterations);
|
||||||
|
int cnc_sim_linuxcnc_genserfuncs_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_genserfuncs_inverse(const EmcPose *pos, double *joints, int *iterations);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_genserfuncs_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_parameters(const LinuxCncGenserParameters ¶meters, int max_iterations) {
|
||||||
|
cnc_sim_linuxcnc_genserfuncs_set_parameters(parameters.a,
|
||||||
|
parameters.alpha,
|
||||||
|
parameters.d,
|
||||||
|
parameters.unrotate,
|
||||||
|
max_iterations);
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.a;
|
||||||
|
out[4] = joints.b;
|
||||||
|
out[5] = joints.c;
|
||||||
|
out[6] = joints.u;
|
||||||
|
out[7] = joints.v;
|
||||||
|
out[8] = joints.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.a = joints[3];
|
||||||
|
out.b = joints[4];
|
||||||
|
out.c = joints[5];
|
||||||
|
out.u = joints[6];
|
||||||
|
out.v = joints[7];
|
||||||
|
out.w = joints[8];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_genserfuncs_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncGenserParameters ¶meters,
|
||||||
|
CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
apply_parameters(parameters, 100);
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_genserfuncs_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_genserfuncs_source_default_parameters(LinuxCncGenserParameters *parameters,
|
||||||
|
int *max_iterations) {
|
||||||
|
if (!parameters) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int raw_max_iterations = 0;
|
||||||
|
cnc_sim_linuxcnc_genserfuncs_default_parameters(parameters->a,
|
||||||
|
parameters->alpha,
|
||||||
|
parameters->d,
|
||||||
|
parameters->unrotate,
|
||||||
|
&raw_max_iterations);
|
||||||
|
if (max_iterations) {
|
||||||
|
*max_iterations = raw_max_iterations;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_genserfuncs_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncAxisJoints &joint_estimate,
|
||||||
|
const LinuxCncGenserParameters ¶meters,
|
||||||
|
int max_iterations,
|
||||||
|
LinuxCncAxisJoints *joints,
|
||||||
|
int *iterations) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
apply_parameters(parameters, max_iterations);
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joint_estimate, raw_joints);
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
if (cnc_sim_linuxcnc_genserfuncs_inverse(&in, raw_joints, iterations) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
15
core/src/linuxcnc_genserfuncs_adapter.h
Normal file
15
core/src/linuxcnc_genserfuncs_adapter.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_genserfuncs_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncGenserParameters ¶meters,
|
||||||
|
CncSimPose *pose);
|
||||||
|
bool linuxcnc_genserfuncs_source_default_parameters(LinuxCncGenserParameters *parameters,
|
||||||
|
int *max_iterations);
|
||||||
|
bool linuxcnc_genserfuncs_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncAxisJoints &joint_estimate,
|
||||||
|
const LinuxCncGenserParameters ¶meters,
|
||||||
|
int max_iterations,
|
||||||
|
LinuxCncAxisJoints *joints,
|
||||||
|
int *iterations);
|
||||||
116
core/src/linuxcnc_kins_util_adapter.c
Normal file
116
core/src/linuxcnc_kins_util_adapter.c
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_STRING_H
|
||||||
|
#define __LINUXCNC_EMCMOTCFG_H
|
||||||
|
#define __LINUXCNC_EMCPOS_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
|
||||||
|
#define RTAPI_MSG_ERR 1
|
||||||
|
#define EMCMOT_MAX_JOINTS 16
|
||||||
|
#define EMCMOT_MAX_AXIS 9
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void cnc_sim_kins_util_rtapi_print(const char *fmt, ...) {
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_kins_util_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||||
|
(void)level;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
KINEMATICS_TYPE kinematicsType(void) {
|
||||||
|
return KINEMATICS_BOTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define rtapi_print cnc_sim_kins_util_rtapi_print
|
||||||
|
#define rtapi_print_msg cnc_sim_kins_util_rtapi_print_msg
|
||||||
|
#define map_coordinates_to_jnumbers cnc_sim_kins_util_map_coordinates_to_jnumbers
|
||||||
|
#define mapped_joints_to_position cnc_sim_kins_util_mapped_joints_to_position
|
||||||
|
#define position_to_mapped_joints cnc_sim_kins_util_position_to_mapped_joints
|
||||||
|
#define identityKinematicsSetup cnc_sim_kins_util_identityKinematicsSetup
|
||||||
|
#define identityKinematicsForward cnc_sim_kins_util_identityKinematicsForward
|
||||||
|
#define identityKinematicsInverse cnc_sim_kins_util_identityKinematicsInverse
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/kins_util.c"
|
||||||
|
#undef identityKinematicsInverse
|
||||||
|
#undef identityKinematicsForward
|
||||||
|
#undef identityKinematicsSetup
|
||||||
|
#undef position_to_mapped_joints
|
||||||
|
#undef mapped_joints_to_position
|
||||||
|
#undef map_coordinates_to_jnumbers
|
||||||
|
#undef rtapi_print_msg
|
||||||
|
#undef rtapi_print
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_kins_util_setup(void) {
|
||||||
|
kparms kp = {0};
|
||||||
|
static char kinsname[] = "kins_util_identity";
|
||||||
|
static char halprefix[] = "identity";
|
||||||
|
kp.kinsname = kinsname;
|
||||||
|
kp.halprefix = halprefix;
|
||||||
|
kp.max_joints = EMCMOT_MAX_JOINTS;
|
||||||
|
kp.allow_duplicates = 0;
|
||||||
|
return cnc_sim_kins_util_identityKinematicsSetup(0, "XYZABCUVW", &kp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_kins_util_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_kins_util_identityKinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_kins_util_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_kins_util_identityKinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
121
core/src/linuxcnc_kins_util_adapter.cpp
Normal file
121
core/src/linuxcnc_kins_util_adapter.cpp
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
#include "linuxcnc_kins_util_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_kins_util_setup(void);
|
||||||
|
int cnc_sim_linuxcnc_kins_util_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_kins_util_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_kins_util_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.a;
|
||||||
|
out[4] = joints.b;
|
||||||
|
out[5] = joints.c;
|
||||||
|
out[6] = joints.u;
|
||||||
|
out[7] = joints.v;
|
||||||
|
out[8] = joints.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.a = joints[3];
|
||||||
|
out.b = joints[4];
|
||||||
|
out.c = joints[5];
|
||||||
|
out.u = joints[6];
|
||||||
|
out.v = joints[7];
|
||||||
|
out.w = joints[8];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_kins_util_identity_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_kins_util_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_kins_util_identity_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
if (cnc_sim_linuxcnc_kins_util_inverse(&in, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
6
core/src/linuxcnc_kins_util_adapter.h
Normal file
6
core/src/linuxcnc_kins_util_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_kins_util_identity_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose);
|
||||||
|
bool linuxcnc_kins_util_identity_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints);
|
||||||
155
core/src/linuxcnc_lineardeltakins_adapter.c
Normal file
155
core/src/linuxcnc_lineardeltakins_adapter.c
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_APP_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
#define __LINUXCNC_EMCPOS_H
|
||||||
|
|
||||||
|
#define MODULE_LICENSE(...)
|
||||||
|
#define EXPORT_SYMBOL(symbol)
|
||||||
|
#define EMCMOT_MAX_JOINTS 16
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#define KINS_NOT_SWITCHABLE \
|
||||||
|
extern int kinematicsSwitchable() { return 0; } \
|
||||||
|
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int cnc_sim_lineardelta_hal_init(const char *name) {
|
||||||
|
(void)name;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_lineardelta_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_lineardelta_hal_ready(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_lineardelta_hal_exit(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_lineardelta_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||||
|
hal_float_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define hal_init cnc_sim_lineardelta_hal_init
|
||||||
|
#define hal_malloc(size) ((struct haldata *)cnc_sim_lineardelta_hal_malloc(size))
|
||||||
|
#define hal_pin_float_newf cnc_sim_lineardelta_hal_pin_float_newf
|
||||||
|
#define hal_ready cnc_sim_lineardelta_hal_ready
|
||||||
|
#define hal_exit cnc_sim_lineardelta_hal_exit
|
||||||
|
#define kinematicsType cnc_sim_lineardelta_kinematicsType
|
||||||
|
#define kinematicsForward cnc_sim_lineardelta_kinematicsForward
|
||||||
|
#define kinematicsInverse cnc_sim_lineardelta_kinematicsInverse
|
||||||
|
#define kinematicsSwitchable cnc_sim_lineardelta_kinematicsSwitchable
|
||||||
|
#define kinematicsSwitch cnc_sim_lineardelta_kinematicsSwitch
|
||||||
|
#define rtapi_app_main cnc_sim_lineardelta_rtapi_app_main
|
||||||
|
#define rtapi_app_exit cnc_sim_lineardelta_rtapi_app_exit
|
||||||
|
#define comp_id cnc_sim_lineardelta_comp_id
|
||||||
|
#define haldata cnc_sim_lineardelta_haldata
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/lineardeltakins.c"
|
||||||
|
#undef haldata
|
||||||
|
#undef comp_id
|
||||||
|
#undef rtapi_app_exit
|
||||||
|
#undef rtapi_app_main
|
||||||
|
#undef kinematicsSwitch
|
||||||
|
#undef kinematicsSwitchable
|
||||||
|
#undef kinematicsInverse
|
||||||
|
#undef kinematicsForward
|
||||||
|
#undef kinematicsType
|
||||||
|
#undef hal_exit
|
||||||
|
#undef hal_ready
|
||||||
|
#undef hal_pin_float_newf
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef hal_init
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_lineardeltakins_setup(void) {
|
||||||
|
return cnc_sim_lineardelta_rtapi_app_main();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_linuxcnc_lineardeltakins_default_parameters(double *r, double *l) {
|
||||||
|
*r = DELTA_RADIUS;
|
||||||
|
*l = DELTA_DIAGONAL_ROD;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_linuxcnc_lineardeltakins_set_parameters(double r, double l) {
|
||||||
|
*cnc_sim_lineardelta_haldata->r = r;
|
||||||
|
*cnc_sim_lineardelta_haldata->l = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_lineardeltakins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_lineardelta_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_lineardeltakins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_lineardelta_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
138
core/src/linuxcnc_lineardeltakins_adapter.cpp
Normal file
138
core/src/linuxcnc_lineardeltakins_adapter.cpp
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
#include "linuxcnc_lineardeltakins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_lineardeltakins_setup(void);
|
||||||
|
void cnc_sim_linuxcnc_lineardeltakins_default_parameters(double *r, double *l);
|
||||||
|
void cnc_sim_linuxcnc_lineardeltakins_set_parameters(double r, double l);
|
||||||
|
int cnc_sim_linuxcnc_lineardeltakins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_lineardeltakins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_lineardeltakins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.a;
|
||||||
|
out[4] = joints.b;
|
||||||
|
out[5] = joints.c;
|
||||||
|
out[6] = joints.u;
|
||||||
|
out[7] = joints.v;
|
||||||
|
out[8] = joints.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.a = joints[3];
|
||||||
|
out.b = joints[4];
|
||||||
|
out.c = joints[5];
|
||||||
|
out.u = joints[6];
|
||||||
|
out.v = joints[7];
|
||||||
|
out.w = joints[8];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_lineardeltakins_source_default_parameters(LinuxCncLinearDeltaParameters *parameters) {
|
||||||
|
double r = 0.0;
|
||||||
|
double l = 0.0;
|
||||||
|
cnc_sim_linuxcnc_lineardeltakins_default_parameters(&r, &l);
|
||||||
|
parameters->r = r;
|
||||||
|
parameters->l = l;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_lineardeltakins_source_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncLinearDeltaParameters ¶meters,
|
||||||
|
CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cnc_sim_linuxcnc_lineardeltakins_set_parameters(parameters.r, parameters.l);
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_lineardeltakins_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_lineardeltakins_source_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncLinearDeltaParameters ¶meters,
|
||||||
|
LinuxCncAxisJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cnc_sim_linuxcnc_lineardeltakins_set_parameters(parameters.r, parameters.l);
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
if (cnc_sim_linuxcnc_lineardeltakins_inverse(&in, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
11
core/src/linuxcnc_lineardeltakins_adapter.h
Normal file
11
core/src/linuxcnc_lineardeltakins_adapter.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_lineardeltakins_source_default_parameters(LinuxCncLinearDeltaParameters *parameters);
|
||||||
|
bool linuxcnc_lineardeltakins_source_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncLinearDeltaParameters ¶meters,
|
||||||
|
CncSimPose *pose);
|
||||||
|
bool linuxcnc_lineardeltakins_source_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncLinearDeltaParameters ¶meters,
|
||||||
|
LinuxCncAxisJoints *joints);
|
||||||
168
core/src/linuxcnc_maxkins_adapter.c
Normal file
168
core/src/linuxcnc_maxkins_adapter.c
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_APP_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
#define __LINUXCNC_EMCPOS_H
|
||||||
|
|
||||||
|
#define MODULE_LICENSE(...)
|
||||||
|
#define EXPORT_SYMBOL(symbol)
|
||||||
|
#define EMCMOT_MAX_JOINTS 16
|
||||||
|
#define PM_PI 3.1415926535897932384626433832795029
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef bool hal_bit_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#define KINS_NOT_SWITCHABLE \
|
||||||
|
extern int kinematicsSwitchable() { return 0; } \
|
||||||
|
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int cnc_sim_maxkins_hal_init(const char *name) {
|
||||||
|
(void)name;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_maxkins_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_maxkins_hal_ready(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_maxkins_hal_exit(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_maxkins_hal_pin_float_new(const char *name,
|
||||||
|
hal_pin_dir_t dir,
|
||||||
|
hal_float_t **data_ptr_addr,
|
||||||
|
int comp_id) {
|
||||||
|
(void)name;
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_maxkins_hal_pin_bit_new(const char *name,
|
||||||
|
hal_pin_dir_t dir,
|
||||||
|
hal_bit_t **data_ptr_addr,
|
||||||
|
int comp_id) {
|
||||||
|
(void)name;
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
*data_ptr_addr = (hal_bit_t *)calloc(1, sizeof(hal_bit_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define hal_init cnc_sim_maxkins_hal_init
|
||||||
|
#define hal_malloc(size) ((struct haldata *)cnc_sim_maxkins_hal_malloc(size))
|
||||||
|
#define hal_pin_float_new cnc_sim_maxkins_hal_pin_float_new
|
||||||
|
#define hal_pin_bit_new cnc_sim_maxkins_hal_pin_bit_new
|
||||||
|
#define hal_ready cnc_sim_maxkins_hal_ready
|
||||||
|
#define hal_exit cnc_sim_maxkins_hal_exit
|
||||||
|
#define kinematicsType cnc_sim_maxkins_kinematicsType
|
||||||
|
#define kinematicsForward cnc_sim_maxkins_kinematicsForward
|
||||||
|
#define kinematicsInverse cnc_sim_maxkins_kinematicsInverse
|
||||||
|
#define kinematicsSwitchable cnc_sim_maxkins_kinematicsSwitchable
|
||||||
|
#define kinematicsSwitch cnc_sim_maxkins_kinematicsSwitch
|
||||||
|
#define rtapi_app_main cnc_sim_maxkins_rtapi_app_main
|
||||||
|
#define rtapi_app_exit cnc_sim_maxkins_rtapi_app_exit
|
||||||
|
#define comp_id cnc_sim_maxkins_comp_id
|
||||||
|
#define haldata cnc_sim_maxkins_haldata
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/maxkins.c"
|
||||||
|
#undef haldata
|
||||||
|
#undef comp_id
|
||||||
|
#undef rtapi_app_exit
|
||||||
|
#undef rtapi_app_main
|
||||||
|
#undef kinematicsSwitch
|
||||||
|
#undef kinematicsSwitchable
|
||||||
|
#undef kinematicsInverse
|
||||||
|
#undef kinematicsForward
|
||||||
|
#undef kinematicsType
|
||||||
|
#undef hal_exit
|
||||||
|
#undef hal_ready
|
||||||
|
#undef hal_pin_bit_new
|
||||||
|
#undef hal_pin_float_new
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef hal_init
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_maxkins_setup(void) {
|
||||||
|
return cnc_sim_maxkins_rtapi_app_main();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_linuxcnc_maxkins_default_parameters(double *pivot_length, int *conventional_directions) {
|
||||||
|
*pivot_length = 0.666;
|
||||||
|
*conventional_directions = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_linuxcnc_maxkins_set_parameters(double pivot_length, int conventional_directions) {
|
||||||
|
*cnc_sim_maxkins_haldata->pivot_length = pivot_length;
|
||||||
|
*cnc_sim_maxkins_haldata->conventional_directions = conventional_directions != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_maxkins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_maxkins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_maxkins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_maxkins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
140
core/src/linuxcnc_maxkins_adapter.cpp
Normal file
140
core/src/linuxcnc_maxkins_adapter.cpp
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
#include "linuxcnc_maxkins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_maxkins_setup(void);
|
||||||
|
void cnc_sim_linuxcnc_maxkins_default_parameters(double *pivot_length, int *conventional_directions);
|
||||||
|
void cnc_sim_linuxcnc_maxkins_set_parameters(double pivot_length, int conventional_directions);
|
||||||
|
int cnc_sim_linuxcnc_maxkins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_maxkins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_maxkins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.a;
|
||||||
|
out[4] = joints.b;
|
||||||
|
out[5] = joints.c;
|
||||||
|
out[6] = joints.u;
|
||||||
|
out[7] = joints.v;
|
||||||
|
out[8] = joints.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.a = joints[3];
|
||||||
|
out.b = joints[4];
|
||||||
|
out.c = joints[5];
|
||||||
|
out.u = joints[6];
|
||||||
|
out.v = joints[7];
|
||||||
|
out.w = joints[8];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_maxkins_source_default_parameters(LinuxCncMaxkinsParameters *parameters) {
|
||||||
|
double pivot_length = 0.0;
|
||||||
|
int conventional_directions = 0;
|
||||||
|
cnc_sim_linuxcnc_maxkins_default_parameters(&pivot_length, &conventional_directions);
|
||||||
|
parameters->pivot_length = pivot_length;
|
||||||
|
parameters->conventional_directions = conventional_directions != 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_maxkins_source_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncMaxkinsParameters ¶meters,
|
||||||
|
CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cnc_sim_linuxcnc_maxkins_set_parameters(parameters.pivot_length,
|
||||||
|
parameters.conventional_directions ? 1 : 0);
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_maxkins_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_maxkins_source_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncMaxkinsParameters ¶meters,
|
||||||
|
LinuxCncAxisJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cnc_sim_linuxcnc_maxkins_set_parameters(parameters.pivot_length,
|
||||||
|
parameters.conventional_directions ? 1 : 0);
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
if (cnc_sim_linuxcnc_maxkins_inverse(&in, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
11
core/src/linuxcnc_maxkins_adapter.h
Normal file
11
core/src/linuxcnc_maxkins_adapter.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_maxkins_source_default_parameters(LinuxCncMaxkinsParameters *parameters);
|
||||||
|
bool linuxcnc_maxkins_source_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncMaxkinsParameters ¶meters,
|
||||||
|
CncSimPose *pose);
|
||||||
|
bool linuxcnc_maxkins_source_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncMaxkinsParameters ¶meters,
|
||||||
|
LinuxCncAxisJoints *joints);
|
||||||
172
core/src/linuxcnc_pentakins_adapter.c
Normal file
172
core/src/linuxcnc_pentakins_adapter.c
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_APP_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
#define __LINUXCNC_EMCPOS_H
|
||||||
|
|
||||||
|
#define MODULE_LICENSE(...)
|
||||||
|
#define EXPORT_SYMBOL(symbol)
|
||||||
|
#define EMCMOT_MAX_JOINTS 16
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef uint32_t hal_u32_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
typedef enum { HAL_RO = 64, HAL_RW = (HAL_RO | 128) } hal_param_dir_t;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
#include "../../../linuxcnc/src/libnml/posemath/posemath.h"
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#define KINS_NOT_SWITCHABLE \
|
||||||
|
extern int kinematicsSwitchable() { return 0; } \
|
||||||
|
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int cnc_sim_pentakins_hal_init(const char *name) {
|
||||||
|
(void)name;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_pentakins_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_pentakins_hal_ready(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_pentakins_hal_exit(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_pentakins_hal_param_float_newf(hal_param_dir_t dir,
|
||||||
|
hal_float_t *data_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)data_addr;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_pentakins_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||||
|
hal_float_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_pentakins_hal_pin_u32_newf(hal_pin_dir_t dir,
|
||||||
|
hal_u32_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_u32_t *)calloc(1, sizeof(hal_u32_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define hal_init cnc_sim_pentakins_hal_init
|
||||||
|
#define hal_malloc(size) ((struct haldata *)cnc_sim_pentakins_hal_malloc(size))
|
||||||
|
#define hal_param_float_newf cnc_sim_pentakins_hal_param_float_newf
|
||||||
|
#define hal_pin_float_newf cnc_sim_pentakins_hal_pin_float_newf
|
||||||
|
#define hal_pin_u32_newf cnc_sim_pentakins_hal_pin_u32_newf
|
||||||
|
#define hal_ready cnc_sim_pentakins_hal_ready
|
||||||
|
#define hal_exit cnc_sim_pentakins_hal_exit
|
||||||
|
#define kinematicsType cnc_sim_pentakins_kinematicsType
|
||||||
|
#define kinematicsForward cnc_sim_pentakins_kinematicsForward
|
||||||
|
#define kinematicsInverse cnc_sim_pentakins_kinematicsInverse
|
||||||
|
#define kinematicsSwitchable cnc_sim_pentakins_kinematicsSwitchable
|
||||||
|
#define kinematicsSwitch cnc_sim_pentakins_kinematicsSwitch
|
||||||
|
#define rtapi_app_main cnc_sim_pentakins_rtapi_app_main
|
||||||
|
#define rtapi_app_exit cnc_sim_pentakins_rtapi_app_exit
|
||||||
|
#define comp_id cnc_sim_pentakins_comp_id
|
||||||
|
#define haldata cnc_sim_pentakins_haldata
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/pentakins.c"
|
||||||
|
#undef haldata
|
||||||
|
#undef comp_id
|
||||||
|
#undef rtapi_app_exit
|
||||||
|
#undef rtapi_app_main
|
||||||
|
#undef kinematicsSwitch
|
||||||
|
#undef kinematicsSwitchable
|
||||||
|
#undef kinematicsInverse
|
||||||
|
#undef kinematicsForward
|
||||||
|
#undef kinematicsType
|
||||||
|
#undef hal_exit
|
||||||
|
#undef hal_ready
|
||||||
|
#undef hal_pin_u32_newf
|
||||||
|
#undef hal_pin_float_newf
|
||||||
|
#undef hal_param_float_newf
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef hal_init
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_pentakins_setup(void) {
|
||||||
|
return cnc_sim_pentakins_rtapi_app_main();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_pentakins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_pentakins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_pentakins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_pentakins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
97
core/src/linuxcnc_pentakins_adapter.cpp
Normal file
97
core/src/linuxcnc_pentakins_adapter.cpp
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#include "linuxcnc_pentakins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_pentakins_setup(void);
|
||||||
|
int cnc_sim_linuxcnc_pentakins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_pentakins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_pentakins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_pentakins_source_forward(const LinuxCncPentakinsJoints &joints,
|
||||||
|
const CncSimPose &initial_pose,
|
||||||
|
CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
double raw_joints[5];
|
||||||
|
std::memcpy(raw_joints, joints.strut, sizeof(raw_joints));
|
||||||
|
EmcPose emc_pose = to_emc_pose(initial_pose);
|
||||||
|
if (cnc_sim_linuxcnc_pentakins_forward(raw_joints, &emc_pose) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(emc_pose);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_pentakins_source_inverse(const CncSimPose &pose,
|
||||||
|
LinuxCncPentakinsJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const EmcPose emc_pose = to_emc_pose(pose);
|
||||||
|
double raw_joints[5] = {};
|
||||||
|
if (cnc_sim_linuxcnc_pentakins_inverse(&emc_pose, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::memcpy(joints->strut, raw_joints, sizeof(raw_joints));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
9
core/src/linuxcnc_pentakins_adapter.h
Normal file
9
core/src/linuxcnc_pentakins_adapter.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_pentakins_source_forward(const LinuxCncPentakinsJoints &joints,
|
||||||
|
const CncSimPose &initial_pose,
|
||||||
|
CncSimPose *pose);
|
||||||
|
bool linuxcnc_pentakins_source_inverse(const CncSimPose &pose,
|
||||||
|
LinuxCncPentakinsJoints *joints);
|
||||||
218
core/src/linuxcnc_pumakins_adapter.c
Normal file
218
core/src/linuxcnc_pumakins_adapter.c
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_STRING_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
#define SWITCHKINS_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define CNC_SIM_EXTERN_C extern "C"
|
||||||
|
#else
|
||||||
|
#define CNC_SIM_EXTERN_C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef int hal_s32_t;
|
||||||
|
typedef bool hal_bit_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
#include "../../../linuxcnc/src/libnml/posemath/sincos.c"
|
||||||
|
#include "../../../linuxcnc/src/libnml/posemath/_posemath.c"
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
typedef int (*KF)(const double *joint,
|
||||||
|
EmcPose *pos,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags);
|
||||||
|
typedef int (*KI)(const EmcPose *world,
|
||||||
|
double *joint,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags);
|
||||||
|
typedef int (*KS)(const int comp_id, const char *coordinates, kparms *ksetup_parms);
|
||||||
|
|
||||||
|
void cnc_sim_puma_rtapi_print(const char *fmt, ...) {
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_puma_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||||
|
(void)level;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_puma_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_puma_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||||
|
hal_float_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_puma_identityKinematicsSetup(const int comp_id, const char *coordinates, kparms *ksetup_parms) {
|
||||||
|
(void)comp_id;
|
||||||
|
(void)coordinates;
|
||||||
|
(void)ksetup_parms;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_puma_identityKinematicsForward(const double *joint,
|
||||||
|
EmcPose *world,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||||
|
(void)joint;
|
||||||
|
(void)world;
|
||||||
|
(void)fflags;
|
||||||
|
(void)iflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_puma_identityKinematicsInverse(const EmcPose *world,
|
||||||
|
double *joint,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||||
|
(void)world;
|
||||||
|
(void)joint;
|
||||||
|
(void)iflags;
|
||||||
|
(void)fflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_puma_userkKinematicsSetup(const int comp_id, const char *coordinates, kparms *ksetup_parms) {
|
||||||
|
(void)comp_id;
|
||||||
|
(void)coordinates;
|
||||||
|
(void)ksetup_parms;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_puma_userkKinematicsForward(const double *joint,
|
||||||
|
EmcPose *world,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||||
|
(void)joint;
|
||||||
|
(void)world;
|
||||||
|
(void)fflags;
|
||||||
|
(void)iflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_puma_userkKinematicsInverse(const EmcPose *world,
|
||||||
|
double *joint,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||||
|
(void)world;
|
||||||
|
(void)joint;
|
||||||
|
(void)iflags;
|
||||||
|
(void)fflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define rtapi_print cnc_sim_puma_rtapi_print
|
||||||
|
#define rtapi_print_msg cnc_sim_puma_rtapi_print_msg
|
||||||
|
#define hal_pin_float_newf cnc_sim_puma_hal_pin_float_newf
|
||||||
|
#define identityKinematicsSetup cnc_sim_puma_identityKinematicsSetup
|
||||||
|
#define identityKinematicsForward cnc_sim_puma_identityKinematicsForward
|
||||||
|
#define identityKinematicsInverse cnc_sim_puma_identityKinematicsInverse
|
||||||
|
#define userkKinematicsSetup cnc_sim_puma_userkKinematicsSetup
|
||||||
|
#define userkKinematicsForward cnc_sim_puma_userkKinematicsForward
|
||||||
|
#define userkKinematicsInverse cnc_sim_puma_userkKinematicsInverse
|
||||||
|
#define switchkinsSetup cnc_sim_puma_switchkinsSetup
|
||||||
|
#define haldata cnc_sim_puma_haldata
|
||||||
|
#define hal_malloc(size) ((struct haldata *)cnc_sim_puma_hal_malloc(size))
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/pumakins.c"
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef haldata
|
||||||
|
#undef switchkinsSetup
|
||||||
|
#undef userkKinematicsInverse
|
||||||
|
#undef userkKinematicsForward
|
||||||
|
#undef userkKinematicsSetup
|
||||||
|
#undef identityKinematicsInverse
|
||||||
|
#undef identityKinematicsForward
|
||||||
|
#undef identityKinematicsSetup
|
||||||
|
#undef hal_pin_float_newf
|
||||||
|
#undef rtapi_print_msg
|
||||||
|
#undef rtapi_print
|
||||||
|
|
||||||
|
CNC_SIM_EXTERN_C int cnc_sim_linuxcnc_pumakins_setup(void) {
|
||||||
|
kparms kp = {0};
|
||||||
|
static char kinsname[] = "pumakins";
|
||||||
|
static char halprefix[] = "pumakins";
|
||||||
|
kp.kinsname = kinsname;
|
||||||
|
kp.halprefix = halprefix;
|
||||||
|
return pumaKinematicsSetup(0, "XYZABC", &kp);
|
||||||
|
}
|
||||||
|
|
||||||
|
CNC_SIM_EXTERN_C void cnc_sim_linuxcnc_pumakins_set_parameters(double a2,
|
||||||
|
double a3,
|
||||||
|
double d3,
|
||||||
|
double d4,
|
||||||
|
double d6) {
|
||||||
|
*cnc_sim_puma_haldata->a2 = a2;
|
||||||
|
*cnc_sim_puma_haldata->a3 = a3;
|
||||||
|
*cnc_sim_puma_haldata->d3 = d3;
|
||||||
|
*cnc_sim_puma_haldata->d4 = d4;
|
||||||
|
*cnc_sim_puma_haldata->d6 = d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
CNC_SIM_EXTERN_C int cnc_sim_linuxcnc_pumakins_forward(const double *joints,
|
||||||
|
struct EmcPose *pos,
|
||||||
|
int *iflags) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS raw_iflags = 0;
|
||||||
|
const int result = pumaKinematicsForward(joints, pos, &fflags, &raw_iflags);
|
||||||
|
if (iflags) {
|
||||||
|
*iflags = (int)raw_iflags;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CNC_SIM_EXTERN_C int cnc_sim_linuxcnc_pumakins_inverse(const struct EmcPose *pos,
|
||||||
|
double *joints,
|
||||||
|
int iflags,
|
||||||
|
int *fflags) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS raw_iflags = (KINEMATICS_INVERSE_FLAGS)iflags;
|
||||||
|
KINEMATICS_FORWARD_FLAGS raw_fflags = 0;
|
||||||
|
const int result = pumaKinematicsInverse(pos, joints, &raw_iflags, &raw_fflags);
|
||||||
|
if (fflags) {
|
||||||
|
*fflags = (int)raw_fflags;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
156
core/src/linuxcnc_pumakins_adapter.cpp
Normal file
156
core/src/linuxcnc_pumakins_adapter.cpp
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
#include "linuxcnc_pumakins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_pumakins_setup(void);
|
||||||
|
void cnc_sim_linuxcnc_pumakins_set_parameters(double a2,
|
||||||
|
double a3,
|
||||||
|
double d3,
|
||||||
|
double d4,
|
||||||
|
double d6);
|
||||||
|
int cnc_sim_linuxcnc_pumakins_forward(const double *joints, EmcPose *pos, int *iflags);
|
||||||
|
int cnc_sim_linuxcnc_pumakins_inverse(const EmcPose *pos,
|
||||||
|
double *joints,
|
||||||
|
int iflags,
|
||||||
|
int *fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_pumakins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_parameters(const LinuxCncPumaParameters ¶meters) {
|
||||||
|
cnc_sim_linuxcnc_pumakins_set_parameters(parameters.a2,
|
||||||
|
parameters.a3,
|
||||||
|
parameters.d3,
|
||||||
|
parameters.d4,
|
||||||
|
parameters.d6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.a;
|
||||||
|
out[4] = joints.b;
|
||||||
|
out[5] = joints.c;
|
||||||
|
out[6] = joints.u;
|
||||||
|
out[7] = joints.v;
|
||||||
|
out[8] = joints.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.a = joints[3];
|
||||||
|
out.b = joints[4];
|
||||||
|
out.c = joints[5];
|
||||||
|
out.u = joints[6];
|
||||||
|
out.v = joints[7];
|
||||||
|
out.w = joints[8];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_pumakins_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncPumaParameters ¶meters,
|
||||||
|
CncSimPose *pose,
|
||||||
|
int *iflags) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
apply_parameters(parameters);
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
int raw_iflags = 0;
|
||||||
|
if (cnc_sim_linuxcnc_pumakins_forward(raw_joints, &out, &raw_iflags) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (iflags) {
|
||||||
|
*iflags = raw_iflags;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_pumakins_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncAxisJoints ¤t_joints,
|
||||||
|
const LinuxCncPumaParameters ¶meters,
|
||||||
|
int iflags,
|
||||||
|
LinuxCncAxisJoints *joints,
|
||||||
|
int *fflags) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
apply_parameters(parameters);
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(current_joints, raw_joints);
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
int raw_fflags = 0;
|
||||||
|
if (cnc_sim_linuxcnc_pumakins_inverse(&in, raw_joints, iflags, &raw_fflags) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fflags) {
|
||||||
|
*fflags = raw_fflags;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
14
core/src/linuxcnc_pumakins_adapter.h
Normal file
14
core/src/linuxcnc_pumakins_adapter.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_pumakins_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncPumaParameters ¶meters,
|
||||||
|
CncSimPose *pose,
|
||||||
|
int *iflags);
|
||||||
|
bool linuxcnc_pumakins_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncAxisJoints ¤t_joints,
|
||||||
|
const LinuxCncPumaParameters ¶meters,
|
||||||
|
int iflags,
|
||||||
|
LinuxCncAxisJoints *joints,
|
||||||
|
int *fflags);
|
||||||
147
core/src/linuxcnc_rosekins_adapter.c
Normal file
147
core/src/linuxcnc_rosekins_adapter.c
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_APP_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
#define __LINUXCNC_EMCPOS_H
|
||||||
|
|
||||||
|
#define MODULE_LICENSE(...)
|
||||||
|
#define EXPORT_SYMBOL(symbol)
|
||||||
|
#define EMCMOT_MAX_JOINTS 16
|
||||||
|
#define PM_PI 3.1415926535897932384626433832795029
|
||||||
|
#define PM_2_PI (2.0 * PM_PI)
|
||||||
|
#define TO_RAD (PM_PI / 180.0)
|
||||||
|
#define TO_DEG (180.0 / PM_PI)
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#define KINS_NOT_SWITCHABLE \
|
||||||
|
extern int kinematicsSwitchable() { return 0; } \
|
||||||
|
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int cnc_sim_rosekins_hal_init(const char *name) {
|
||||||
|
(void)name;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_rosekins_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_rosekins_hal_ready(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_rosekins_hal_exit(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_rosekins_hal_pin_float_new(const char *name,
|
||||||
|
hal_pin_dir_t dir,
|
||||||
|
hal_float_t **data_ptr_addr,
|
||||||
|
int comp_id) {
|
||||||
|
(void)name;
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define hal_init cnc_sim_rosekins_hal_init
|
||||||
|
#define hal_malloc(size) ((struct haldata *)cnc_sim_rosekins_hal_malloc(size))
|
||||||
|
#define hal_pin_float_new cnc_sim_rosekins_hal_pin_float_new
|
||||||
|
#define hal_ready cnc_sim_rosekins_hal_ready
|
||||||
|
#define hal_exit cnc_sim_rosekins_hal_exit
|
||||||
|
#define kinematicsType cnc_sim_rosekins_kinematicsType
|
||||||
|
#define kinematicsForward cnc_sim_rosekins_kinematicsForward
|
||||||
|
#define kinematicsInverse cnc_sim_rosekins_kinematicsInverse
|
||||||
|
#define kinematicsSwitchable cnc_sim_rosekins_kinematicsSwitchable
|
||||||
|
#define kinematicsSwitch cnc_sim_rosekins_kinematicsSwitch
|
||||||
|
#define rtapi_app_main cnc_sim_rosekins_rtapi_app_main
|
||||||
|
#define rtapi_app_exit cnc_sim_rosekins_rtapi_app_exit
|
||||||
|
#define comp_id cnc_sim_rosekins_comp_id
|
||||||
|
#define haldata cnc_sim_rosekins_haldata
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/rosekins.c"
|
||||||
|
#undef haldata
|
||||||
|
#undef comp_id
|
||||||
|
#undef rtapi_app_exit
|
||||||
|
#undef rtapi_app_main
|
||||||
|
#undef kinematicsSwitch
|
||||||
|
#undef kinematicsSwitchable
|
||||||
|
#undef kinematicsInverse
|
||||||
|
#undef kinematicsForward
|
||||||
|
#undef kinematicsType
|
||||||
|
#undef hal_exit
|
||||||
|
#undef hal_ready
|
||||||
|
#undef hal_pin_float_new
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef hal_init
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_rosekins_setup(void) {
|
||||||
|
return cnc_sim_rosekins_rtapi_app_main();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_rosekins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_rosekins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_rosekins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_rosekins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
121
core/src/linuxcnc_rosekins_adapter.cpp
Normal file
121
core/src/linuxcnc_rosekins_adapter.cpp
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
#include "linuxcnc_rosekins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_rosekins_setup(void);
|
||||||
|
int cnc_sim_linuxcnc_rosekins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_rosekins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_rosekins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.a;
|
||||||
|
out[4] = joints.b;
|
||||||
|
out[5] = joints.c;
|
||||||
|
out[6] = joints.u;
|
||||||
|
out[7] = joints.v;
|
||||||
|
out[8] = joints.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.a = joints[3];
|
||||||
|
out.b = joints[4];
|
||||||
|
out.c = joints[5];
|
||||||
|
out.u = joints[6];
|
||||||
|
out.v = joints[7];
|
||||||
|
out.w = joints[8];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_rosekins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_rosekins_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_rosekins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
if (cnc_sim_linuxcnc_rosekins_inverse(&in, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
6
core/src/linuxcnc_rosekins_adapter.h
Normal file
6
core/src/linuxcnc_rosekins_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_rosekins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose);
|
||||||
|
bool linuxcnc_rosekins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints);
|
||||||
165
core/src/linuxcnc_rotarydeltakins_adapter.c
Normal file
165
core/src/linuxcnc_rotarydeltakins_adapter.c
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_APP_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
#define __LINUXCNC_EMCPOS_H
|
||||||
|
|
||||||
|
#define MODULE_LICENSE(...)
|
||||||
|
#define EXPORT_SYMBOL(symbol)
|
||||||
|
#define EMCMOT_MAX_JOINTS 16
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#define KINS_NOT_SWITCHABLE \
|
||||||
|
extern int kinematicsSwitchable() { return 0; } \
|
||||||
|
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int cnc_sim_rotarydelta_hal_init(const char *name) {
|
||||||
|
(void)name;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_rotarydelta_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_rotarydelta_hal_ready(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_rotarydelta_hal_exit(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_rotarydelta_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||||
|
hal_float_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define hal_init cnc_sim_rotarydelta_hal_init
|
||||||
|
#define hal_malloc(size) ((struct haldata *)cnc_sim_rotarydelta_hal_malloc(size))
|
||||||
|
#define hal_pin_float_newf cnc_sim_rotarydelta_hal_pin_float_newf
|
||||||
|
#define hal_ready cnc_sim_rotarydelta_hal_ready
|
||||||
|
#define hal_exit cnc_sim_rotarydelta_hal_exit
|
||||||
|
#define kinematicsType cnc_sim_rotarydelta_kinematicsType
|
||||||
|
#define kinematicsForward cnc_sim_rotarydelta_kinematicsForward
|
||||||
|
#define kinematicsInverse cnc_sim_rotarydelta_kinematicsInverse
|
||||||
|
#define kinematicsSwitchable cnc_sim_rotarydelta_kinematicsSwitchable
|
||||||
|
#define kinematicsSwitch cnc_sim_rotarydelta_kinematicsSwitch
|
||||||
|
#define rtapi_app_main cnc_sim_rotarydelta_rtapi_app_main
|
||||||
|
#define rtapi_app_exit cnc_sim_rotarydelta_rtapi_app_exit
|
||||||
|
#define comp_id cnc_sim_rotarydelta_comp_id
|
||||||
|
#define haldata cnc_sim_rotarydelta_haldata
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/rotarydeltakins.c"
|
||||||
|
#undef haldata
|
||||||
|
#undef comp_id
|
||||||
|
#undef rtapi_app_exit
|
||||||
|
#undef rtapi_app_main
|
||||||
|
#undef kinematicsSwitch
|
||||||
|
#undef kinematicsSwitchable
|
||||||
|
#undef kinematicsInverse
|
||||||
|
#undef kinematicsForward
|
||||||
|
#undef kinematicsType
|
||||||
|
#undef hal_exit
|
||||||
|
#undef hal_ready
|
||||||
|
#undef hal_pin_float_newf
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef hal_init
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_rotarydeltakins_setup(void) {
|
||||||
|
return cnc_sim_rotarydelta_rtapi_app_main();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_linuxcnc_rotarydeltakins_default_parameters(double *platformradius,
|
||||||
|
double *thighlength,
|
||||||
|
double *shinlength,
|
||||||
|
double *footradius) {
|
||||||
|
*platformradius = RDELTA_PFR;
|
||||||
|
*thighlength = RDELTA_TL;
|
||||||
|
*shinlength = RDELTA_SL;
|
||||||
|
*footradius = RDELTA_FR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_linuxcnc_rotarydeltakins_set_parameters(double platformradius,
|
||||||
|
double thighlength,
|
||||||
|
double shinlength,
|
||||||
|
double footradius) {
|
||||||
|
*cnc_sim_rotarydelta_haldata->pfr = platformradius;
|
||||||
|
*cnc_sim_rotarydelta_haldata->tl = thighlength;
|
||||||
|
*cnc_sim_rotarydelta_haldata->sl = shinlength;
|
||||||
|
*cnc_sim_rotarydelta_haldata->fr = footradius;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_rotarydeltakins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_rotarydelta_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_rotarydeltakins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_rotarydelta_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
157
core/src/linuxcnc_rotarydeltakins_adapter.cpp
Normal file
157
core/src/linuxcnc_rotarydeltakins_adapter.cpp
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
#include "linuxcnc_rotarydeltakins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_rotarydeltakins_setup(void);
|
||||||
|
void cnc_sim_linuxcnc_rotarydeltakins_default_parameters(double *platformradius,
|
||||||
|
double *thighlength,
|
||||||
|
double *shinlength,
|
||||||
|
double *footradius);
|
||||||
|
void cnc_sim_linuxcnc_rotarydeltakins_set_parameters(double platformradius,
|
||||||
|
double thighlength,
|
||||||
|
double shinlength,
|
||||||
|
double footradius);
|
||||||
|
int cnc_sim_linuxcnc_rotarydeltakins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_rotarydeltakins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_rotarydeltakins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.a;
|
||||||
|
out[4] = joints.b;
|
||||||
|
out[5] = joints.c;
|
||||||
|
out[6] = joints.u;
|
||||||
|
out[7] = joints.v;
|
||||||
|
out[8] = joints.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.a = joints[3];
|
||||||
|
out.b = joints[4];
|
||||||
|
out.c = joints[5];
|
||||||
|
out.u = joints[6];
|
||||||
|
out.v = joints[7];
|
||||||
|
out.w = joints[8];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_rotarydeltakins_source_default_parameters(LinuxCncRotaryDeltaParameters *parameters) {
|
||||||
|
double platformradius = 0.0;
|
||||||
|
double thighlength = 0.0;
|
||||||
|
double shinlength = 0.0;
|
||||||
|
double footradius = 0.0;
|
||||||
|
cnc_sim_linuxcnc_rotarydeltakins_default_parameters(&platformradius,
|
||||||
|
&thighlength,
|
||||||
|
&shinlength,
|
||||||
|
&footradius);
|
||||||
|
parameters->platformradius = platformradius;
|
||||||
|
parameters->thighlength = thighlength;
|
||||||
|
parameters->shinlength = shinlength;
|
||||||
|
parameters->footradius = footradius;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_rotarydeltakins_source_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncRotaryDeltaParameters ¶meters,
|
||||||
|
CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cnc_sim_linuxcnc_rotarydeltakins_set_parameters(parameters.platformradius,
|
||||||
|
parameters.thighlength,
|
||||||
|
parameters.shinlength,
|
||||||
|
parameters.footradius);
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_rotarydeltakins_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_rotarydeltakins_source_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncRotaryDeltaParameters ¶meters,
|
||||||
|
LinuxCncAxisJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cnc_sim_linuxcnc_rotarydeltakins_set_parameters(parameters.platformradius,
|
||||||
|
parameters.thighlength,
|
||||||
|
parameters.shinlength,
|
||||||
|
parameters.footradius);
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
if (cnc_sim_linuxcnc_rotarydeltakins_inverse(&in, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
11
core/src/linuxcnc_rotarydeltakins_adapter.h
Normal file
11
core/src/linuxcnc_rotarydeltakins_adapter.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_rotarydeltakins_source_default_parameters(LinuxCncRotaryDeltaParameters *parameters);
|
||||||
|
bool linuxcnc_rotarydeltakins_source_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncRotaryDeltaParameters ¶meters,
|
||||||
|
CncSimPose *pose);
|
||||||
|
bool linuxcnc_rotarydeltakins_source_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncRotaryDeltaParameters ¶meters,
|
||||||
|
LinuxCncAxisJoints *joints);
|
||||||
118
core/src/linuxcnc_rotatekins_adapter.c
Normal file
118
core/src/linuxcnc_rotatekins_adapter.c
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_APP_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
|
||||||
|
#define MODULE_LICENSE(...)
|
||||||
|
#define EXPORT_SYMBOL(symbol)
|
||||||
|
#define RTAPI_MSG_ERR 1
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#define KINS_NOT_SWITCHABLE \
|
||||||
|
extern int kinematicsSwitchable() { return 0; } \
|
||||||
|
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int cnc_sim_rotatekins_hal_init(const char *name) {
|
||||||
|
(void)name;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_rotatekins_hal_ready(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_rotatekins_hal_exit(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define hal_init cnc_sim_rotatekins_hal_init
|
||||||
|
#define hal_ready cnc_sim_rotatekins_hal_ready
|
||||||
|
#define hal_exit cnc_sim_rotatekins_hal_exit
|
||||||
|
#define kinematicsType cnc_sim_rotatekins_kinematicsType
|
||||||
|
#define kinematicsForward cnc_sim_rotatekins_kinematicsForward
|
||||||
|
#define kinematicsInverse cnc_sim_rotatekins_kinematicsInverse
|
||||||
|
#define kinematicsHome cnc_sim_rotatekins_kinematicsHome
|
||||||
|
#define kinematicsSwitchable cnc_sim_rotatekins_kinematicsSwitchable
|
||||||
|
#define kinematicsSwitch cnc_sim_rotatekins_kinematicsSwitch
|
||||||
|
#define rtapi_app_main cnc_sim_rotatekins_rtapi_app_main
|
||||||
|
#define rtapi_app_exit cnc_sim_rotatekins_rtapi_app_exit
|
||||||
|
#define comp_id cnc_sim_rotatekins_comp_id
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/rotatekins.c"
|
||||||
|
#undef comp_id
|
||||||
|
#undef rtapi_app_exit
|
||||||
|
#undef rtapi_app_main
|
||||||
|
#undef kinematicsSwitch
|
||||||
|
#undef kinematicsSwitchable
|
||||||
|
#undef kinematicsHome
|
||||||
|
#undef kinematicsInverse
|
||||||
|
#undef kinematicsForward
|
||||||
|
#undef kinematicsType
|
||||||
|
#undef hal_exit
|
||||||
|
#undef hal_ready
|
||||||
|
#undef hal_init
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_rotatekins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_rotatekins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_rotatekins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_rotatekins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
104
core/src/linuxcnc_rotatekins_adapter.cpp
Normal file
104
core/src/linuxcnc_rotatekins_adapter.cpp
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#include "linuxcnc_rotatekins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_rotatekins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_rotatekins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.a;
|
||||||
|
out[4] = joints.b;
|
||||||
|
out[5] = joints.c;
|
||||||
|
out[6] = joints.u;
|
||||||
|
out[7] = joints.v;
|
||||||
|
out[8] = joints.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.a = joints[3];
|
||||||
|
out.b = joints[4];
|
||||||
|
out.c = joints[5];
|
||||||
|
out.u = joints[6];
|
||||||
|
out.v = joints[7];
|
||||||
|
out.w = joints[8];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_rotatekins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose) {
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_rotatekins_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_rotatekins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints) {
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
if (cnc_sim_linuxcnc_rotatekins_inverse(&in, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
6
core/src/linuxcnc_rotatekins_adapter.h
Normal file
6
core/src/linuxcnc_rotatekins_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_rotatekins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose);
|
||||||
|
bool linuxcnc_rotatekins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints);
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
#include "linuxcnc_rs274_backend.h"
|
#include "linuxcnc_rs274_backend.h"
|
||||||
|
|
||||||
|
#ifdef CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
|
||||||
|
#include "boost/python/object.hpp"
|
||||||
|
#else
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "linuxcnc_canon_bridge.h"
|
#include "linuxcnc_canon_bridge.h"
|
||||||
#include "linuxcnc_tooldata_fixture.h"
|
#include "linuxcnc_tooldata_fixture.h"
|
||||||
@@ -16,11 +20,15 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#ifndef CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
int _task = 0;
|
|
||||||
char _parameter_file_name[LINELEN];
|
char _parameter_file_name[LINELEN];
|
||||||
|
|
||||||
|
#ifndef CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
|
||||||
|
int _task = 0;
|
||||||
|
|
||||||
extern "C" PyObject *PyInit_interpreter(void);
|
extern "C" PyObject *PyInit_interpreter(void);
|
||||||
extern "C" PyObject *PyInit_emccanon(void);
|
extern "C" PyObject *PyInit_emccanon(void);
|
||||||
extern "C" struct _inittab builtin_modules[];
|
extern "C" struct _inittab builtin_modules[];
|
||||||
@@ -29,6 +37,7 @@ struct _inittab builtin_modules[] = {
|
|||||||
{"emccanon", PyInit_emccanon},
|
{"emccanon", PyInit_emccanon},
|
||||||
{nullptr, nullptr},
|
{nullptr, nullptr},
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -73,12 +82,48 @@ bool file_mode_enabled() {
|
|||||||
return std::getenv("CNC_SIM_RS274_FILE_MODE") != nullptr;
|
return std::getenv("CNC_SIM_RS274_FILE_MODE") != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ScopedEnvironmentVariable {
|
||||||
|
public:
|
||||||
|
ScopedEnvironmentVariable(const char *name, const std::string &value) : name_(name), active_(!value.empty()) {
|
||||||
|
if (!active_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (const char *old = std::getenv(name_)) {
|
||||||
|
had_old_ = true;
|
||||||
|
old_ = old;
|
||||||
|
}
|
||||||
|
setenv(name_, value.c_str(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ScopedEnvironmentVariable() {
|
||||||
|
if (!active_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (had_old_) {
|
||||||
|
setenv(name_, old_.c_str(), 1);
|
||||||
|
} else {
|
||||||
|
unsetenv(name_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char *name_;
|
||||||
|
bool active_;
|
||||||
|
bool had_old_ = false;
|
||||||
|
std::string old_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
|
||||||
bool write_temp_program(const char *program,
|
bool write_temp_program(const char *program,
|
||||||
size_t program_len,
|
size_t program_len,
|
||||||
std::string *path,
|
std::string *path,
|
||||||
std::string *error) {
|
std::string *error) {
|
||||||
char tmpl[] = "/tmp/cnc_sim_api_XXXXXX.ngc";
|
const char *tmpdir = std::getenv("TMPDIR");
|
||||||
const int fd = mkstemps(tmpl, 4);
|
std::string tmpl = std::string(tmpdir ? tmpdir : "/tmp") + "/cnc_sim_api_XXXXXX.ngc";
|
||||||
|
std::vector<char> tmpl_buffer(tmpl.begin(), tmpl.end());
|
||||||
|
tmpl_buffer.push_back('\0');
|
||||||
|
|
||||||
|
const int fd = mkstemps(tmpl_buffer.data(), 4);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (error) {
|
if (error) {
|
||||||
*error = "failed to create temporary ngc file";
|
*error = "failed to create temporary ngc file";
|
||||||
@@ -100,15 +145,16 @@ bool write_temp_program(const char *program,
|
|||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
unlink(tmpl);
|
unlink(tmpl_buffer.data());
|
||||||
if (error) {
|
if (error) {
|
||||||
*error = "failed to write temporary ngc file";
|
*error = "failed to write temporary ngc file";
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*path = tmpl;
|
*path = tmpl_buffer.data();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int execute_file_mode(InterpBase *interp,
|
int execute_file_mode(InterpBase *interp,
|
||||||
CanonEventSink &sink,
|
CanonEventSink &sink,
|
||||||
@@ -160,6 +206,7 @@ int execute_file_mode(InterpBase *interp,
|
|||||||
int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
||||||
const char *program,
|
const char *program,
|
||||||
size_t program_len,
|
size_t program_len,
|
||||||
|
const GcodeBackendOptions &options,
|
||||||
std::string *error) {
|
std::string *error) {
|
||||||
if (!program && program_len != 0) {
|
if (!program && program_len != 0) {
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -168,14 +215,36 @@ int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LinuxCNC source basis: rs274ngc_pre.cc uses
|
||||||
|
// RS274NGC_PARAMETER_FILE_NAME_DEFAULT when the external parameter file
|
||||||
|
// name is empty. Reset the bridge every parse so a prior native env
|
||||||
|
// override does not leak into later default parses.
|
||||||
if (const char *parameter_file = std::getenv("CNC_SIM_RS274_VAR")) {
|
if (const char *parameter_file = std::getenv("CNC_SIM_RS274_VAR")) {
|
||||||
SET_PARAMETER_FILE_NAME(parameter_file);
|
SET_PARAMETER_FILE_NAME(parameter_file);
|
||||||
|
} else {
|
||||||
|
SET_PARAMETER_FILE_NAME("rs274ngc.var");
|
||||||
}
|
}
|
||||||
cnc_sim_init_minimal_linuxcnc_tooldata();
|
cnc_sim_init_minimal_linuxcnc_tooldata();
|
||||||
sink.clear_callback_status();
|
sink.clear_callback_status();
|
||||||
cnc_sim_linuxcnc_set_canon_sink(&sink);
|
cnc_sim_linuxcnc_set_canon_sink(&sink);
|
||||||
|
|
||||||
|
// LinuxCNC source basis: rs274ngc_pre.cc and interp_namedparams.cc read
|
||||||
|
// INI_FILE_NAME for startup and #<_ini[section]key> named parameters.
|
||||||
|
ScopedEnvironmentVariable ini_file_env("INI_FILE_NAME", options.ini_file_name);
|
||||||
InterpBase *interp = makeInterp();
|
InterpBase *interp = makeInterp();
|
||||||
|
if (!options.ini_file_name.empty()) {
|
||||||
|
// LinuxCNC source basis: emctask.cc calls Interp::ini_load() before
|
||||||
|
// Interp::init(), and rs274ngc_pre.cc ini_load() maps
|
||||||
|
// [RS274NGC] PARAMETER_FILE through SET_PARAMETER_FILE_NAME().
|
||||||
|
if (interp->ini_load(options.ini_file_name.c_str()) != INTERP_OK) {
|
||||||
|
if (error) {
|
||||||
|
*error = "ini_load failed: " + options.ini_file_name;
|
||||||
|
}
|
||||||
|
delete interp;
|
||||||
|
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
int status = interp->init();
|
int status = interp->init();
|
||||||
if (status != INTERP_OK) {
|
if (status != INTERP_OK) {
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -185,8 +254,18 @@ int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
|||||||
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
SET_BLOCK_DELETE(sink.block_delete());
|
||||||
|
|
||||||
if (file_mode_enabled()) {
|
if (file_mode_enabled()) {
|
||||||
|
#ifdef CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
|
||||||
|
if (error) {
|
||||||
|
*error = "linuxcnc-rs274 file mode is not available in wasm-safe builds";
|
||||||
|
}
|
||||||
|
interp->exit();
|
||||||
|
delete interp;
|
||||||
|
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
std::string temp_path;
|
std::string temp_path;
|
||||||
if (!write_temp_program(program, program_len, &temp_path, error)) {
|
if (!write_temp_program(program, program_len, &temp_path, error)) {
|
||||||
interp->exit();
|
interp->exit();
|
||||||
@@ -202,6 +281,7 @@ int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
|||||||
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
std::string source(program, program + program_len);
|
std::string source(program, program + program_len);
|
||||||
std::istringstream input(source);
|
std::istringstream input(source);
|
||||||
@@ -212,21 +292,47 @@ int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
|||||||
++line_number;
|
++line_number;
|
||||||
cnc_sim_linuxcnc_set_current_line(line_number);
|
cnc_sim_linuxcnc_set_current_line(line_number);
|
||||||
std::vector<SimulatorGcodeControlAction> control_actions;
|
std::vector<SimulatorGcodeControlAction> control_actions;
|
||||||
if (parse_simulator_gcode_control_line(line, &control_actions)) {
|
if (parse_simulator_gcode_control_line(line, sink.block_delete(), &control_actions)) {
|
||||||
bool simulator_only_line = true;
|
bool simulator_only_line = true;
|
||||||
|
bool all_control_actions_handled = true;
|
||||||
for (const auto &action : control_actions) {
|
for (const auto &action : control_actions) {
|
||||||
emit_simulator_gcode_control_action(sink, action, line_number);
|
if (!can_emit_simulator_gcode_control_action(sink, action)) {
|
||||||
|
all_control_actions_handled = false;
|
||||||
|
simulator_only_line = false;
|
||||||
|
}
|
||||||
if (action.kind == SimulatorGcodeControlKind::RtcpState &&
|
if (action.kind == SimulatorGcodeControlKind::RtcpState &&
|
||||||
!action.rtcp_enabled) {
|
!action.rtcp_enabled) {
|
||||||
simulator_only_line = false;
|
simulator_only_line = false;
|
||||||
}
|
}
|
||||||
if (stop_if_callback_aborted(sink, error)) {
|
}
|
||||||
interp->exit();
|
if (!all_control_actions_handled && control_actions.size() > 1) {
|
||||||
delete interp;
|
for (const auto &action : control_actions) {
|
||||||
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
if (!can_emit_simulator_gcode_control_action(sink, action) &&
|
||||||
return -1;
|
action.kind == SimulatorGcodeControlKind::KinematicsSwitch) {
|
||||||
|
if (error) {
|
||||||
|
*error = "M-code greater than 199: M" + std::to_string(action.m_code);
|
||||||
|
}
|
||||||
|
interp->exit();
|
||||||
|
delete interp;
|
||||||
|
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (all_control_actions_handled) {
|
||||||
|
for (const auto &action : control_actions) {
|
||||||
|
emit_simulator_gcode_control_action(sink, action, line_number);
|
||||||
|
if (stop_if_callback_aborted(sink, error)) {
|
||||||
|
interp->exit();
|
||||||
|
delete interp;
|
||||||
|
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!all_control_actions_handled) {
|
||||||
|
simulator_only_line = false;
|
||||||
|
}
|
||||||
if (simulator_only_line) {
|
if (simulator_only_line) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "canon_event_sink.h"
|
#include "canon_event_sink.h"
|
||||||
|
#include "gcode_backend.h"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -8,5 +9,5 @@
|
|||||||
int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
||||||
const char *program,
|
const char *program,
|
||||||
size_t program_len,
|
size_t program_len,
|
||||||
|
const GcodeBackendOptions &options,
|
||||||
std::string *error);
|
std::string *error);
|
||||||
|
|
||||||
|
|||||||
224
core/src/linuxcnc_scarakins_adapter.c
Normal file
224
core/src/linuxcnc_scarakins_adapter.c
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_STRING_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
#define SWITCHKINS_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define CNC_SIM_EXTERN_C extern "C"
|
||||||
|
#else
|
||||||
|
#define CNC_SIM_EXTERN_C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PM_PI 3.1415926535897932384626433832795029
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef int hal_s32_t;
|
||||||
|
typedef bool hal_bit_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
typedef int (*KF)(const double *joint,
|
||||||
|
EmcPose *pos,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags);
|
||||||
|
typedef int (*KI)(const struct EmcPose *world,
|
||||||
|
double *joint,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags);
|
||||||
|
typedef int (*KS)(const int comp_id, const char *coordinates, kparms *ksetup_parms);
|
||||||
|
|
||||||
|
void cnc_sim_scara_rtapi_print(const char *fmt, ...) {
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_scara_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||||
|
(void)level;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_scara_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_scara_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||||
|
hal_float_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_scara_identityKinematicsSetup(const int comp_id,
|
||||||
|
const char *coordinates,
|
||||||
|
kparms *ksetup_parms) {
|
||||||
|
(void)comp_id;
|
||||||
|
(void)coordinates;
|
||||||
|
(void)ksetup_parms;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_scara_identityKinematicsForward(const double *joint,
|
||||||
|
struct EmcPose *world,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||||
|
(void)joint;
|
||||||
|
(void)world;
|
||||||
|
(void)fflags;
|
||||||
|
(void)iflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_scara_identityKinematicsInverse(const struct EmcPose *world,
|
||||||
|
double *joint,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||||
|
(void)world;
|
||||||
|
(void)joint;
|
||||||
|
(void)iflags;
|
||||||
|
(void)fflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_scara_userkKinematicsSetup(const int comp_id,
|
||||||
|
const char *coordinates,
|
||||||
|
kparms *ksetup_parms) {
|
||||||
|
(void)comp_id;
|
||||||
|
(void)coordinates;
|
||||||
|
(void)ksetup_parms;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_scara_userkKinematicsForward(const double *joint,
|
||||||
|
struct EmcPose *world,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||||
|
(void)joint;
|
||||||
|
(void)world;
|
||||||
|
(void)fflags;
|
||||||
|
(void)iflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_scara_userkKinematicsInverse(const struct EmcPose *world,
|
||||||
|
double *joint,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||||
|
(void)world;
|
||||||
|
(void)joint;
|
||||||
|
(void)iflags;
|
||||||
|
(void)fflags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define rtapi_print cnc_sim_scara_rtapi_print
|
||||||
|
#define rtapi_print_msg cnc_sim_scara_rtapi_print_msg
|
||||||
|
#define hal_pin_float_newf cnc_sim_scara_hal_pin_float_newf
|
||||||
|
#define identityKinematicsSetup cnc_sim_scara_identityKinematicsSetup
|
||||||
|
#define identityKinematicsForward cnc_sim_scara_identityKinematicsForward
|
||||||
|
#define identityKinematicsInverse cnc_sim_scara_identityKinematicsInverse
|
||||||
|
#define userkKinematicsSetup cnc_sim_scara_userkKinematicsSetup
|
||||||
|
#define userkKinematicsForward cnc_sim_scara_userkKinematicsForward
|
||||||
|
#define userkKinematicsInverse cnc_sim_scara_userkKinematicsInverse
|
||||||
|
#define switchkinsSetup cnc_sim_scara_switchkinsSetup
|
||||||
|
#define haldata cnc_sim_scara_haldata
|
||||||
|
#define hal_malloc(size) ((struct scara_data *)cnc_sim_scara_hal_malloc(size))
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/scarakins.c"
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef haldata
|
||||||
|
#undef switchkinsSetup
|
||||||
|
#undef userkKinematicsInverse
|
||||||
|
#undef userkKinematicsForward
|
||||||
|
#undef userkKinematicsSetup
|
||||||
|
#undef identityKinematicsInverse
|
||||||
|
#undef identityKinematicsForward
|
||||||
|
#undef identityKinematicsSetup
|
||||||
|
#undef hal_pin_float_newf
|
||||||
|
#undef rtapi_print_msg
|
||||||
|
#undef rtapi_print
|
||||||
|
|
||||||
|
CNC_SIM_EXTERN_C int cnc_sim_linuxcnc_scarakins_setup(void) {
|
||||||
|
kparms kp = {0};
|
||||||
|
static char kinsname[] = "scarakins";
|
||||||
|
static char halprefix[] = "scarakins";
|
||||||
|
kp.kinsname = kinsname;
|
||||||
|
kp.halprefix = halprefix;
|
||||||
|
return scaraKinematicsSetup(0, "XYZABC", &kp);
|
||||||
|
}
|
||||||
|
|
||||||
|
CNC_SIM_EXTERN_C void cnc_sim_linuxcnc_scarakins_set_parameters(double d1,
|
||||||
|
double d2,
|
||||||
|
double d3,
|
||||||
|
double d4,
|
||||||
|
double d5,
|
||||||
|
double d6) {
|
||||||
|
*cnc_sim_scara_haldata->d1 = d1;
|
||||||
|
*cnc_sim_scara_haldata->d2 = d2;
|
||||||
|
*cnc_sim_scara_haldata->d3 = d3;
|
||||||
|
*cnc_sim_scara_haldata->d4 = d4;
|
||||||
|
*cnc_sim_scara_haldata->d5 = d5;
|
||||||
|
*cnc_sim_scara_haldata->d6 = d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
CNC_SIM_EXTERN_C int cnc_sim_linuxcnc_scarakins_forward(const double *joints,
|
||||||
|
struct EmcPose *pos,
|
||||||
|
int *iflags) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS raw_iflags = 0;
|
||||||
|
const int result = scaraKinematicsForward(joints, pos, &fflags, &raw_iflags);
|
||||||
|
if (iflags) {
|
||||||
|
*iflags = (int)raw_iflags;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CNC_SIM_EXTERN_C int cnc_sim_linuxcnc_scarakins_inverse(const struct EmcPose *pos,
|
||||||
|
double *joints,
|
||||||
|
int iflags) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS raw_iflags = (KINEMATICS_INVERSE_FLAGS)iflags;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return scaraKinematicsInverse(pos, joints, &raw_iflags, &fflags);
|
||||||
|
}
|
||||||
144
core/src/linuxcnc_scarakins_adapter.cpp
Normal file
144
core/src/linuxcnc_scarakins_adapter.cpp
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
#include "linuxcnc_scarakins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_scarakins_setup(void);
|
||||||
|
void cnc_sim_linuxcnc_scarakins_set_parameters(double d1,
|
||||||
|
double d2,
|
||||||
|
double d3,
|
||||||
|
double d4,
|
||||||
|
double d5,
|
||||||
|
double d6);
|
||||||
|
int cnc_sim_linuxcnc_scarakins_forward(const double *joints, EmcPose *pos, int *iflags);
|
||||||
|
int cnc_sim_linuxcnc_scarakins_inverse(const EmcPose *pos,
|
||||||
|
double *joints,
|
||||||
|
int iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_scarakins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_parameters(const LinuxCncScaraParameters ¶meters) {
|
||||||
|
cnc_sim_linuxcnc_scarakins_set_parameters(parameters.d1,
|
||||||
|
parameters.d2,
|
||||||
|
parameters.d3,
|
||||||
|
parameters.d4,
|
||||||
|
parameters.d5,
|
||||||
|
parameters.d6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncScaraJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.j0;
|
||||||
|
out[1] = joints.j1;
|
||||||
|
out[2] = joints.j2;
|
||||||
|
out[3] = joints.j3;
|
||||||
|
out[4] = joints.j4;
|
||||||
|
out[5] = joints.j5;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncScaraJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncScaraJoints out{};
|
||||||
|
out.j0 = joints[0];
|
||||||
|
out.j1 = joints[1];
|
||||||
|
out.j2 = joints[2];
|
||||||
|
out.j3 = joints[3];
|
||||||
|
out.j4 = joints[4];
|
||||||
|
out.j5 = joints[5];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_scarakins_forward(const LinuxCncScaraJoints &joints,
|
||||||
|
const LinuxCncScaraParameters ¶meters,
|
||||||
|
CncSimPose *pose,
|
||||||
|
int *iflags) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
apply_parameters(parameters);
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
int raw_iflags = 0;
|
||||||
|
if (cnc_sim_linuxcnc_scarakins_forward(raw_joints, &out, &raw_iflags) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (iflags) {
|
||||||
|
*iflags = raw_iflags;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_scarakins_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncScaraParameters ¶meters,
|
||||||
|
int iflags,
|
||||||
|
LinuxCncScaraJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
apply_parameters(parameters);
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
if (cnc_sim_linuxcnc_scarakins_inverse(&in, raw_joints, iflags) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
12
core/src/linuxcnc_scarakins_adapter.h
Normal file
12
core/src/linuxcnc_scarakins_adapter.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_scarakins_forward(const LinuxCncScaraJoints &joints,
|
||||||
|
const LinuxCncScaraParameters ¶meters,
|
||||||
|
CncSimPose *pose,
|
||||||
|
int *iflags);
|
||||||
|
bool linuxcnc_scarakins_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncScaraParameters ¶meters,
|
||||||
|
int iflags,
|
||||||
|
LinuxCncScaraJoints *joints);
|
||||||
121
core/src/linuxcnc_scorbot_kins_adapter.c
Normal file
121
core/src/linuxcnc_scorbot_kins_adapter.c
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_APP_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_GO_TYPES_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
#define __LINUXCNC_EMCPOS_H
|
||||||
|
|
||||||
|
#define MODULE_LICENSE(...)
|
||||||
|
#define EXPORT_SYMBOL(symbol)
|
||||||
|
|
||||||
|
#define PM_PI 3.1415926535897932384626433832795029
|
||||||
|
#define TO_RAD (PM_PI / 180.0)
|
||||||
|
#define TO_DEG (180.0 / PM_PI)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#define KINS_NOT_SWITCHABLE \
|
||||||
|
extern int kinematicsSwitchable() { return 0; } \
|
||||||
|
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int cnc_sim_scorbot_kins_hal_init(const char *name) {
|
||||||
|
(void)name;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_scorbot_kins_hal_ready(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_scorbot_kins_hal_exit(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define hal_init cnc_sim_scorbot_kins_hal_init
|
||||||
|
#define hal_ready cnc_sim_scorbot_kins_hal_ready
|
||||||
|
#define hal_exit cnc_sim_scorbot_kins_hal_exit
|
||||||
|
#define kinematicsType cnc_sim_scorbot_kins_kinematicsType
|
||||||
|
#define kinematicsForward cnc_sim_scorbot_kins_kinematicsForward
|
||||||
|
#define kinematicsInverse cnc_sim_scorbot_kins_kinematicsInverse
|
||||||
|
#define kinematicsSwitchable cnc_sim_scorbot_kins_kinematicsSwitchable
|
||||||
|
#define kinematicsSwitch cnc_sim_scorbot_kins_kinematicsSwitch
|
||||||
|
#define rtapi_app_main cnc_sim_scorbot_kins_rtapi_app_main
|
||||||
|
#define rtapi_app_exit cnc_sim_scorbot_kins_rtapi_app_exit
|
||||||
|
#define comp_id cnc_sim_scorbot_kins_comp_id
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/scorbot-kins.c"
|
||||||
|
#undef comp_id
|
||||||
|
#undef rtapi_app_exit
|
||||||
|
#undef rtapi_app_main
|
||||||
|
#undef kinematicsSwitch
|
||||||
|
#undef kinematicsSwitchable
|
||||||
|
#undef kinematicsInverse
|
||||||
|
#undef kinematicsForward
|
||||||
|
#undef kinematicsType
|
||||||
|
#undef hal_exit
|
||||||
|
#undef hal_ready
|
||||||
|
#undef hal_init
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_scorbot_kins_setup(void) {
|
||||||
|
return cnc_sim_scorbot_kins_rtapi_app_main();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_scorbot_kins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_scorbot_kins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_scorbot_kins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_scorbot_kins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
110
core/src/linuxcnc_scorbot_kins_adapter.cpp
Normal file
110
core/src/linuxcnc_scorbot_kins_adapter.cpp
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#include "linuxcnc_scorbot_kins_adapter.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_scorbot_kins_setup(void);
|
||||||
|
int cnc_sim_linuxcnc_scorbot_kins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_scorbot_kins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_scorbot_kins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncScorbotJoints &joints, double out[5]) {
|
||||||
|
out[0] = joints.j0;
|
||||||
|
out[1] = joints.j1;
|
||||||
|
out[2] = joints.j2;
|
||||||
|
out[3] = joints.j3;
|
||||||
|
out[4] = joints.j4;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncScorbotJoints from_joints(const double joints[5]) {
|
||||||
|
LinuxCncScorbotJoints out{};
|
||||||
|
out.j0 = joints[0];
|
||||||
|
out.j1 = joints[1];
|
||||||
|
out.j2 = joints[2];
|
||||||
|
out.j3 = joints[3];
|
||||||
|
out.j4 = joints[4];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_scorbot_kins_source_forward(const LinuxCncScorbotJoints &joints, CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
double raw_joints[5] = {};
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_scorbot_kins_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_scorbot_kins_source_inverse(const CncSimPose &pose, LinuxCncScorbotJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[5] = {};
|
||||||
|
if (cnc_sim_linuxcnc_scorbot_kins_inverse(&in, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
6
core/src/linuxcnc_scorbot_kins_adapter.h
Normal file
6
core/src/linuxcnc_scorbot_kins_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_scorbot_kins_source_forward(const LinuxCncScorbotJoints &joints, CncSimPose *pose);
|
||||||
|
bool linuxcnc_scorbot_kins_source_inverse(const CncSimPose &pose, LinuxCncScorbotJoints *joints);
|
||||||
180
core/src/linuxcnc_switchkins_remap_table.inc
Normal file
180
core/src/linuxcnc_switchkins_remap_table.inc
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
// Generated by ./generate-linuxcnc-switchkins-remap-table.sh.
|
||||||
|
// Source: LinuxCNC INI MACHINE/KINEMATICS/HALFILE/POSTGUI_HALFILE/SUBROUTINE_PATH/REMAP entries and
|
||||||
|
// adjacent remap_subs/{428,429,430}remap.ngc #<kinstype> assignments.
|
||||||
|
{"configs/sim/axis/vismach/5axis/bridgemill/5axis.ini", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/bridgemill", 0, 1, 2},
|
||||||
|
{"bridgemill", 0, 1, 2},
|
||||||
|
{"5axis", 0, 1, 2},
|
||||||
|
{"sim-5axisbridgemill(xyzbcw)", 0, 1, 2},
|
||||||
|
{"sim-5axisbridgemill", 0, 1, 2},
|
||||||
|
{"5axiskinscoordinates=xyzbcwy", 0, 1, 2},
|
||||||
|
{"5axiskins", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/bridgemill/5axisgui.hal", 0, 1, 2},
|
||||||
|
{"5axisgui.hal", 0, 1, 2},
|
||||||
|
{"5axisgui", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/bridgemill/5axis_postgui.hal", 0, 1, 2},
|
||||||
|
{"5axis_postgui.hal", 0, 1, 2},
|
||||||
|
{"5axis_postgui", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/bridgemill/remap_subs/428remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/bridgemill/remap_subs", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/bridgemill/remap_subs/429remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/bridgemill/remap_subs/430remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-dual-rotary/xyzab-tdr.ini", 1, 0, -1},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-dual-rotary", 1, 0, -1},
|
||||||
|
{"table-dual-rotary", 1, 0, -1},
|
||||||
|
{"xyzab-tdr", 1, 0, -1},
|
||||||
|
{"sim-xyzab-tdr-kins(switchkins)", 1, 0, -1},
|
||||||
|
{"sim-xyzab-tdr-kins", 1, 0, -1},
|
||||||
|
{"xyzab_tdr_kins", 1, 0, -1},
|
||||||
|
{"xyzab_tdr", 1, 0, -1},
|
||||||
|
{"xyzab-tdr-kins", 1, 0, -1},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-dual-rotary/xyzab-tdr-postgui.hal", 1, 0, -1},
|
||||||
|
{"xyzab-tdr-postgui.hal", 1, 0, -1},
|
||||||
|
{"xyzab-tdr-postgui", 1, 0, -1},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-dual-rotary/remap_subs/428remap.ngc", 1, 0, -1},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-dual-rotary/remap_subs", 1, 0, -1},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-dual-rotary/remap_subs/429remap.ngc", 1, 0, -1},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini", 1, 0, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary-tilting", 1, 0, 2},
|
||||||
|
{"table-rotary-tilting", 1, 0, 2},
|
||||||
|
{"xyzac-trt", 1, 0, 2},
|
||||||
|
{"sim-xyzac-trt-kins(switchkins)", 1, 0, 2},
|
||||||
|
{"sim-xyzac-trt-kins", 1, 0, 2},
|
||||||
|
{"xyzac-trt-kinssparm=identityfirst", 1, 0, 2},
|
||||||
|
{"xyzac-trt-kins", 1, 0, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary-tilting/switchkins_postgui.hal", 1, 0, 2},
|
||||||
|
{"switchkins_postgui.hal", 1, 0, 2},
|
||||||
|
{"switchkins_postgui", 1, 0, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc", 1, 0, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs", 1, 0, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc", 1, 0, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc", 1, 0, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini", 1, 0, 2},
|
||||||
|
{"xyzbc-trt", 1, 0, 2},
|
||||||
|
{"sim-xyzbc-trt-kins(switchkins)", 1, 0, 2},
|
||||||
|
{"sim-xyzbc-trt-kins", 1, 0, 2},
|
||||||
|
{"xyzbc-trt-kinssparm=identityfirst", 1, 0, 2},
|
||||||
|
{"xyzbc-trt-kins", 1, 0, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzacb-trsrn_twp/xyzacb-trsrn.ini", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzacb-trsrn_twp", 0, 1, 2},
|
||||||
|
{"xyzacb-trsrn_twp", 0, 1, 2},
|
||||||
|
{"xyzacb-trsrn", 0, 1, 2},
|
||||||
|
{"xyzacb-trsrn(switchkins)", 0, 1, 2},
|
||||||
|
{"xyzacb_trsrn", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzacb-trsrn_twp/xyzacb-trsrn_postgui.hal", 0, 1, 2},
|
||||||
|
{"xyzacb-trsrn_postgui.hal", 0, 1, 2},
|
||||||
|
{"xyzacb-trsrn_postgui", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/428remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating", 0, 1, 2},
|
||||||
|
{"table-rotary_spindle-rotary-nutating", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/429remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/remap_subs/430remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzbca-trsrn_twp/xyzbca-trsrn.ini", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzbca-trsrn_twp", 0, 1, 2},
|
||||||
|
{"xyzbca-trsrn_twp", 0, 1, 2},
|
||||||
|
{"xyzbca-trsrn", 0, 1, 2},
|
||||||
|
{"xyzbca-trsrn(switchkins)", 0, 1, 2},
|
||||||
|
{"xyzbca_trsrn", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzbca-trsrn_twp/xyzbca-trsrn_postgui.hal", 0, 1, 2},
|
||||||
|
{"xyzbca-trsrn_postgui.hal", 0, 1, 2},
|
||||||
|
{"xyzbca-trsrn_postgui", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/hexapod-sim/hexapod.ini", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/hexapod-sim", 0, 1, 2},
|
||||||
|
{"hexapod-sim", 0, 1, 2},
|
||||||
|
{"hexapod", 0, 1, 2},
|
||||||
|
{"hexapod(switchkins)", 0, 1, 2},
|
||||||
|
{"genhexkins", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/hexapod-sim/kinematics.hal", 0, 1, 2},
|
||||||
|
{"kinematics.hal", 0, 1, 2},
|
||||||
|
{"kinematics", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/hexapod-sim/hexapod_postgui.hal", 0, 1, 2},
|
||||||
|
{"hexapod_postgui.hal", 0, 1, 2},
|
||||||
|
{"hexapod_postgui", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/hexapod-sim/remap_subs/428remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/hexapod-sim/remap_subs", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/hexapod-sim/remap_subs/429remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/hexapod-sim/remap_subs/430remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/melfa-sim/melfa.ini", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/melfa-sim", 0, 1, 2},
|
||||||
|
{"melfa-sim", 0, 1, 2},
|
||||||
|
{"melfa", 0, 1, 2},
|
||||||
|
{"melfa(mm)", 0, 1, 2},
|
||||||
|
{"genserkins", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/melfa-sim/melfa_dh.hal", 0, 1, 2},
|
||||||
|
{"melfa_dh.hal", 0, 1, 2},
|
||||||
|
{"melfa_dh", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/melfa-sim/melfa-postgui.hal", 0, 1, 2},
|
||||||
|
{"melfa-postgui.hal", 0, 1, 2},
|
||||||
|
{"melfa-postgui", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/melfa-sim/remap_subs/428remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/melfa-sim/remap_subs", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/melfa-sim/remap_subs/429remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/melfa-sim/remap_subs/430remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/millturn/millturn.ini", 0, 1, -1},
|
||||||
|
{"configs/sim/axis/vismach/millturn", 0, 1, -1},
|
||||||
|
{"millturn", 0, 1, -1},
|
||||||
|
{"millturn(mm)", 0, 1, -1},
|
||||||
|
{"configs/sim/axis/vismach/millturn/millturn.hal", 0, 1, -1},
|
||||||
|
{"millturn.hal", 0, 1, -1},
|
||||||
|
{"configs/sim/axis/vismach/millturn/millturn-postgui.hal", 0, 1, -1},
|
||||||
|
{"millturn-postgui.hal", 0, 1, -1},
|
||||||
|
{"millturn-postgui", 0, 1, -1},
|
||||||
|
{"configs/sim/axis/vismach/millturn/remap_subs/428remap.ngc", 0, 1, -1},
|
||||||
|
{"configs/sim/axis/vismach/millturn/remap_subs", 0, 1, -1},
|
||||||
|
{"configs/sim/axis/vismach/millturn/remap_subs/429remap.ngc", 0, 1, -1},
|
||||||
|
{"configs/sim/axis/vismach/puma/puma.ini", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/puma", 0, 1, 2},
|
||||||
|
{"puma", 0, 1, 2},
|
||||||
|
{"puma(pumakins,switchkins)", 0, 1, 2},
|
||||||
|
{"pumakins", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/puma/puma_dh.hal", 0, 1, 2},
|
||||||
|
{"puma_dh.hal", 0, 1, 2},
|
||||||
|
{"puma_dh", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/puma/puma_postgui.hal", 0, 1, 2},
|
||||||
|
{"puma_postgui.hal", 0, 1, 2},
|
||||||
|
{"puma_postgui", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/puma/remap_subs/428remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/puma/remap_subs", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/puma/remap_subs/429remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/puma/remap_subs/430remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/puma/puma_cube.ini", 0, 1, 2},
|
||||||
|
{"puma_cube", 0, 1, 2},
|
||||||
|
{"puma_cube.ini(pumakins)", 0, 1, 2},
|
||||||
|
{"puma_cube.ini", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/puma/puma560.ini", 0, 1, 2},
|
||||||
|
{"puma560", 0, 1, 2},
|
||||||
|
{"puma560(switchkins)(inch)", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/puma/puma560_dh.hal", 0, 1, 2},
|
||||||
|
{"puma560_dh.hal", 0, 1, 2},
|
||||||
|
{"puma560_dh", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/puma/puma560_postgui.hal", 0, 1, 2},
|
||||||
|
{"puma560_postgui.hal", 0, 1, 2},
|
||||||
|
{"puma560_postgui", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/puma/puma560_uvw.ini", 0, 1, 2},
|
||||||
|
{"puma560_uvw", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/scara/scara.ini", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/scara", 0, 1, 2},
|
||||||
|
{"scara", 0, 1, 2},
|
||||||
|
{"scara(genserkins,switchkins)", 0, 1, 2},
|
||||||
|
{"scarakinscoordinates=xyzcab", 0, 1, 2},
|
||||||
|
{"scarakins", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/scara/scara_postgui.hal", 0, 1, 2},
|
||||||
|
{"scara_postgui.hal", 0, 1, 2},
|
||||||
|
{"scara_postgui", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/scara/remap_subs/428remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/scara/remap_subs", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/scara/remap_subs/429remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/axis/vismach/scara/remap_subs/430remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/qtaxis/non-trivial/scara/scara.ini", 0, 1, 2},
|
||||||
|
{"configs/sim/qtaxis/non-trivial/scara", 0, 1, 2},
|
||||||
|
{"configs/sim/qtaxis/non-trivial/scara/remap_subs/428remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/qtaxis/non-trivial/scara/remap_subs", 0, 1, 2},
|
||||||
|
{"configs/sim/qtaxis/non-trivial/scara/remap_subs/429remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/qtaxis/non-trivial/scara/remap_subs/430remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/qtvcp_screens/non-trivial/scara/scara.ini", 0, 1, 2},
|
||||||
|
{"configs/sim/qtvcp_screens/non-trivial/scara", 0, 1, 2},
|
||||||
|
{"configs/sim/qtvcp_screens/non-trivial/scara/remap_subs/428remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/qtvcp_screens/non-trivial/scara/remap_subs", 0, 1, 2},
|
||||||
|
{"configs/sim/qtvcp_screens/non-trivial/scara/remap_subs/429remap.ngc", 0, 1, 2},
|
||||||
|
{"configs/sim/qtvcp_screens/non-trivial/scara/remap_subs/430remap.ngc", 0, 1, 2},
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "emc/tooldata/tooldata.hh"
|
#include "emc/tooldata/tooldata.hh"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
void cnc_sim_init_minimal_linuxcnc_tooldata() {
|
void cnc_sim_init_minimal_linuxcnc_tooldata() {
|
||||||
static bool created = false;
|
static bool created = false;
|
||||||
if (!created) {
|
if (!created) {
|
||||||
@@ -22,5 +24,29 @@ void cnc_sim_init_minimal_linuxcnc_tooldata() {
|
|||||||
tool.diameter = 6.0;
|
tool.diameter = 6.0;
|
||||||
tool.offset.tran.z = 12.5;
|
tool.offset.tran.z = 12.5;
|
||||||
tooldata_put(tool, 1);
|
tooldata_put(tool, 1);
|
||||||
tooldata_last_index_set(1);
|
|
||||||
|
CANON_TOOL_TABLE thread_tool = tooldata_entry_init();
|
||||||
|
thread_tool.toolno = 4;
|
||||||
|
thread_tool.pocketno = 4;
|
||||||
|
thread_tool.diameter = 1.0;
|
||||||
|
thread_tool.offset.tran.z = 0.7;
|
||||||
|
tooldata_put(thread_tool, 4);
|
||||||
|
|
||||||
|
if (const char *spindle_tool = std::getenv("CNC_SIM_TOOL_IN_SPINDLE")) {
|
||||||
|
const int tool_id = std::atoi(spindle_tool);
|
||||||
|
if (tool_id == 1) {
|
||||||
|
CANON_TOOL_TABLE spindle_tooldata = tool;
|
||||||
|
spindle_tooldata.pocketno = 0;
|
||||||
|
spindle_tooldata.frontangle = 12.0;
|
||||||
|
spindle_tooldata.backangle = 34.0;
|
||||||
|
spindle_tooldata.orientation = 5;
|
||||||
|
tooldata_put(spindle_tooldata, 0);
|
||||||
|
} else if (tool_id == 4) {
|
||||||
|
CANON_TOOL_TABLE spindle_tooldata = thread_tool;
|
||||||
|
spindle_tooldata.pocketno = 0;
|
||||||
|
tooldata_put(spindle_tooldata, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tooldata_last_index_set(4);
|
||||||
}
|
}
|
||||||
|
|||||||
142
core/src/linuxcnc_tripodkins_adapter.c
Normal file
142
core/src/linuxcnc_tripodkins_adapter.c
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_APP_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
#define __LINUXCNC_EMCPOS_H
|
||||||
|
|
||||||
|
#define MODULE_LICENSE(...)
|
||||||
|
#define EXPORT_SYMBOL(symbol)
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#define KINS_NOT_SWITCHABLE \
|
||||||
|
extern int kinematicsSwitchable() { return 0; } \
|
||||||
|
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int cnc_sim_tripodkins_hal_init(const char *name) {
|
||||||
|
(void)name;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_tripodkins_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_tripodkins_hal_ready(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_tripodkins_hal_exit(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_tripodkins_hal_pin_float_new(const char *name,
|
||||||
|
hal_pin_dir_t dir,
|
||||||
|
hal_float_t **data_ptr_addr,
|
||||||
|
int comp_id) {
|
||||||
|
(void)name;
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define hal_init cnc_sim_tripodkins_hal_init
|
||||||
|
#define hal_malloc(size) ((struct haldata *)cnc_sim_tripodkins_hal_malloc(size))
|
||||||
|
#define hal_pin_float_new cnc_sim_tripodkins_hal_pin_float_new
|
||||||
|
#define hal_ready cnc_sim_tripodkins_hal_ready
|
||||||
|
#define hal_exit cnc_sim_tripodkins_hal_exit
|
||||||
|
#define kinematicsType cnc_sim_tripodkins_kinematicsType
|
||||||
|
#define kinematicsForward cnc_sim_tripodkins_kinematicsForward
|
||||||
|
#define kinematicsInverse cnc_sim_tripodkins_kinematicsInverse
|
||||||
|
#define kinematicsSwitchable cnc_sim_tripodkins_kinematicsSwitchable
|
||||||
|
#define kinematicsSwitch cnc_sim_tripodkins_kinematicsSwitch
|
||||||
|
#define rtapi_app_main cnc_sim_tripodkins_rtapi_app_main
|
||||||
|
#define rtapi_app_exit cnc_sim_tripodkins_rtapi_app_exit
|
||||||
|
#define comp_id cnc_sim_tripodkins_comp_id
|
||||||
|
#define haldata cnc_sim_tripodkins_haldata
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/tripodkins.c"
|
||||||
|
#undef haldata
|
||||||
|
#undef comp_id
|
||||||
|
#undef rtapi_app_exit
|
||||||
|
#undef rtapi_app_main
|
||||||
|
#undef kinematicsSwitch
|
||||||
|
#undef kinematicsSwitchable
|
||||||
|
#undef kinematicsInverse
|
||||||
|
#undef kinematicsForward
|
||||||
|
#undef kinematicsType
|
||||||
|
#undef hal_exit
|
||||||
|
#undef hal_ready
|
||||||
|
#undef hal_pin_float_new
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef hal_init
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_tripodkins_setup(void) {
|
||||||
|
return cnc_sim_tripodkins_rtapi_app_main();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_tripodkins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_tripodkins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_tripodkins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_tripodkins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
94
core/src/linuxcnc_tripodkins_adapter.cpp
Normal file
94
core/src/linuxcnc_tripodkins_adapter.cpp
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#include "linuxcnc_tripodkins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_tripodkins_setup(void);
|
||||||
|
int cnc_sim_linuxcnc_tripodkins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_tripodkins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_tripodkins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_tripodkins_source_forward(const LinuxCncTripodJoints &joints, CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
double raw_joints[3];
|
||||||
|
std::memcpy(raw_joints, joints.strut, sizeof(raw_joints));
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_tripodkins_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_tripodkins_source_inverse(const CncSimPose &pose, LinuxCncTripodJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const EmcPose emc_pose = to_emc_pose(pose);
|
||||||
|
double raw_joints[3] = {};
|
||||||
|
if (cnc_sim_linuxcnc_tripodkins_inverse(&emc_pose, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::memcpy(joints->strut, raw_joints, sizeof(raw_joints));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
6
core/src/linuxcnc_tripodkins_adapter.h
Normal file
6
core/src/linuxcnc_tripodkins_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_tripodkins_source_forward(const LinuxCncTripodJoints &joints, CncSimPose *pose);
|
||||||
|
bool linuxcnc_tripodkins_source_inverse(const CncSimPose &pose, LinuxCncTripodJoints *joints);
|
||||||
163
core/src/linuxcnc_trivkins_adapter.c
Normal file
163
core/src/linuxcnc_trivkins_adapter.c
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_APP_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_STRING_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_EMCMOTCFG_H
|
||||||
|
#define __LINUXCNC_EMCPOS_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
|
||||||
|
#define MODULE_LICENSE(...)
|
||||||
|
#define EXPORT_SYMBOL(symbol)
|
||||||
|
#define RTAPI_MP_STRING(name, desc)
|
||||||
|
#define RTAPI_MSG_ERR 1
|
||||||
|
#define EMCMOT_MAX_JOINTS 16
|
||||||
|
#define EMCMOT_MAX_AXIS 9
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#define KINS_NOT_SWITCHABLE \
|
||||||
|
extern int kinematicsSwitchable() { return 0; } \
|
||||||
|
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void cnc_sim_trivkins_rtapi_print(const char *fmt, ...) {
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_trivkins_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||||
|
(void)level;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_trivkins_hal_init(const char *name) {
|
||||||
|
(void)name;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_trivkins_hal_ready(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_trivkins_hal_exit(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define rtapi_print cnc_sim_trivkins_rtapi_print
|
||||||
|
#define rtapi_print_msg cnc_sim_trivkins_rtapi_print_msg
|
||||||
|
#define kinematicsType cnc_sim_trivkins_kinematicsType
|
||||||
|
KINEMATICS_TYPE kinematicsType(void);
|
||||||
|
#define map_coordinates_to_jnumbers cnc_sim_trivkins_map_coordinates_to_jnumbers
|
||||||
|
#define mapped_joints_to_position cnc_sim_trivkins_mapped_joints_to_position
|
||||||
|
#define position_to_mapped_joints cnc_sim_trivkins_position_to_mapped_joints
|
||||||
|
#define identityKinematicsSetup cnc_sim_trivkins_identityKinematicsSetup
|
||||||
|
#define identityKinematicsForward cnc_sim_trivkins_identityKinematicsForward
|
||||||
|
#define identityKinematicsInverse cnc_sim_trivkins_identityKinematicsInverse
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/kins_util.c"
|
||||||
|
|
||||||
|
#define hal_init cnc_sim_trivkins_hal_init
|
||||||
|
#define hal_ready cnc_sim_trivkins_hal_ready
|
||||||
|
#define hal_exit cnc_sim_trivkins_hal_exit
|
||||||
|
#define kinematicsForward cnc_sim_trivkins_kinematicsForward
|
||||||
|
#define kinematicsInverse cnc_sim_trivkins_kinematicsInverse
|
||||||
|
#define kinematicsSwitchable cnc_sim_trivkins_kinematicsSwitchable
|
||||||
|
#define kinematicsSwitch cnc_sim_trivkins_kinematicsSwitch
|
||||||
|
#define rtapi_app_main cnc_sim_trivkins_rtapi_app_main
|
||||||
|
#define rtapi_app_exit cnc_sim_trivkins_rtapi_app_exit
|
||||||
|
#define comp_id cnc_sim_trivkins_comp_id
|
||||||
|
#define coordinates cnc_sim_trivkins_coordinates
|
||||||
|
#define kinstype cnc_sim_trivkins_kinstype
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/trivkins.c"
|
||||||
|
#undef kinstype
|
||||||
|
#undef coordinates
|
||||||
|
#undef comp_id
|
||||||
|
#undef rtapi_app_exit
|
||||||
|
#undef rtapi_app_main
|
||||||
|
#undef kinematicsSwitch
|
||||||
|
#undef kinematicsSwitchable
|
||||||
|
#undef kinematicsInverse
|
||||||
|
#undef kinematicsForward
|
||||||
|
#undef hal_exit
|
||||||
|
#undef hal_ready
|
||||||
|
#undef hal_init
|
||||||
|
#undef identityKinematicsInverse
|
||||||
|
#undef identityKinematicsForward
|
||||||
|
#undef identityKinematicsSetup
|
||||||
|
#undef position_to_mapped_joints
|
||||||
|
#undef mapped_joints_to_position
|
||||||
|
#undef map_coordinates_to_jnumbers
|
||||||
|
#undef kinematicsType
|
||||||
|
#undef rtapi_print_msg
|
||||||
|
#undef rtapi_print
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_trivkins_setup(void) {
|
||||||
|
return cnc_sim_trivkins_rtapi_app_main();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_trivkins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_trivkins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_trivkins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_trivkins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_trivkins_type(void) {
|
||||||
|
return (int)cnc_sim_trivkins_kinematicsType();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
129
core/src/linuxcnc_trivkins_adapter.cpp
Normal file
129
core/src/linuxcnc_trivkins_adapter.cpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#include "linuxcnc_trivkins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_trivkins_setup(void);
|
||||||
|
int cnc_sim_linuxcnc_trivkins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_trivkins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
int cnc_sim_linuxcnc_trivkins_type(void);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_trivkins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.a;
|
||||||
|
out[4] = joints.b;
|
||||||
|
out[5] = joints.c;
|
||||||
|
out[6] = joints.u;
|
||||||
|
out[7] = joints.v;
|
||||||
|
out[8] = joints.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.a = joints[3];
|
||||||
|
out.b = joints[4];
|
||||||
|
out.c = joints[5];
|
||||||
|
out.u = joints[6];
|
||||||
|
out.v = joints[7];
|
||||||
|
out.w = joints[8];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_trivkins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_trivkins_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_trivkins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
if (cnc_sim_linuxcnc_trivkins_inverse(&in, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int linuxcnc_trivkins_source_kinematics_type() {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return cnc_sim_linuxcnc_trivkins_type();
|
||||||
|
}
|
||||||
7
core/src/linuxcnc_trivkins_adapter.h
Normal file
7
core/src/linuxcnc_trivkins_adapter.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_trivkins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose);
|
||||||
|
bool linuxcnc_trivkins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints);
|
||||||
|
int linuxcnc_trivkins_source_kinematics_type();
|
||||||
207
core/src/linuxcnc_trtfuncs_adapter.c
Normal file
207
core/src/linuxcnc_trtfuncs_adapter.c
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_STRING_H
|
||||||
|
#define __LINUXCNC_RTAPI_CTYPE_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_EMCMOTCFG_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
|
||||||
|
#define RTAPI_MSG_ERR 1
|
||||||
|
#define PM_PI 3.1415926535897932384626433832795029
|
||||||
|
#define TO_RAD (PM_PI / 180.0)
|
||||||
|
#define EMCMOT_MAX_JOINTS 16
|
||||||
|
#define EMCMOT_MAX_AXIS 9
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef bool hal_bit_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
static int cnc_sim_axis_idx_for_jno[EMCMOT_MAX_JOINTS];
|
||||||
|
static int cnc_sim_max_joints;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void rtapi_print(const char *fmt, ...) {
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtapi_print_msg(int level, const char *fmt, ...) {
|
||||||
|
(void)level;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hal_pin_float_newf(hal_pin_dir_t dir, hal_float_t **data_ptr_addr, int comp_id, const char *fmt, ...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hal_pin_bit_newf(hal_pin_dir_t dir, hal_bit_t **data_ptr_addr, int comp_id, const char *fmt, ...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_bit_t *)calloc(1, sizeof(hal_bit_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int map_coordinates_to_jnumbers(const char *coordinates,
|
||||||
|
const int max_joints,
|
||||||
|
const int allow_duplicates,
|
||||||
|
int axis_idx_for_jno[]) {
|
||||||
|
(void)allow_duplicates;
|
||||||
|
const char *letters = "XYZABCUVW";
|
||||||
|
int jno = 0;
|
||||||
|
for (int i = 0; i < EMCMOT_MAX_JOINTS; ++i) {
|
||||||
|
axis_idx_for_jno[i] = -1;
|
||||||
|
cnc_sim_axis_idx_for_jno[i] = -1;
|
||||||
|
}
|
||||||
|
while (*coordinates) {
|
||||||
|
const char *found = strchr(letters, toupper((unsigned char)*coordinates));
|
||||||
|
if (!found || jno >= max_joints) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
axis_idx_for_jno[jno++] = (int)(found - letters);
|
||||||
|
++coordinates;
|
||||||
|
}
|
||||||
|
cnc_sim_max_joints = jno;
|
||||||
|
for (int i = 0; i < EMCMOT_MAX_JOINTS; ++i) {
|
||||||
|
cnc_sim_axis_idx_for_jno[i] = axis_idx_for_jno[i];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int position_to_mapped_joints(const int max_joints, const EmcPose *pos, double *joints) {
|
||||||
|
for (int jno = 0; jno < max_joints; ++jno) {
|
||||||
|
switch (cnc_sim_axis_idx_for_jno[jno]) {
|
||||||
|
case 0: joints[jno] = pos->tran.x; break;
|
||||||
|
case 1: joints[jno] = pos->tran.y; break;
|
||||||
|
case 2: joints[jno] = pos->tran.z; break;
|
||||||
|
case 3: joints[jno] = pos->a; break;
|
||||||
|
case 4: joints[jno] = pos->b; break;
|
||||||
|
case 5: joints[jno] = pos->c; break;
|
||||||
|
case 6: joints[jno] = pos->u; break;
|
||||||
|
case 7: joints[jno] = pos->v; break;
|
||||||
|
case 8: joints[jno] = pos->w; break;
|
||||||
|
default: joints[jno] = 0.0; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define hal_malloc(size) ((struct haldata *)cnc_sim_hal_malloc(size))
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/trtfuncs.c"
|
||||||
|
#undef hal_malloc
|
||||||
|
|
||||||
|
void cnc_sim_linuxcnc_trtfuncs_reset_setup_state(void) {
|
||||||
|
trtfuncs_max_joints = 0;
|
||||||
|
JX = -1;
|
||||||
|
JY = -1;
|
||||||
|
JZ = -1;
|
||||||
|
JA = -1;
|
||||||
|
JB = -1;
|
||||||
|
JC = -1;
|
||||||
|
JU = -1;
|
||||||
|
JV = -1;
|
||||||
|
JW = -1;
|
||||||
|
haldata = NULL;
|
||||||
|
cnc_sim_max_joints = 0;
|
||||||
|
for (int i = 0; i < EMCMOT_MAX_JOINTS; ++i) {
|
||||||
|
cnc_sim_axis_idx_for_jno[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_trtfuncs_setup_xyzbc(void) {
|
||||||
|
kparms kp = {0};
|
||||||
|
static char kinsname[] = "xyzbc-trt-kins";
|
||||||
|
static char halprefix[] = "xyzbc-trt-kins";
|
||||||
|
static char required_coordinates[] = "XYZBC";
|
||||||
|
kp.kinsname = kinsname;
|
||||||
|
kp.halprefix = halprefix;
|
||||||
|
kp.required_coordinates = required_coordinates;
|
||||||
|
kp.max_joints = EMCMOT_MAX_JOINTS;
|
||||||
|
kp.allow_duplicates = 1;
|
||||||
|
return trtKinematicsSetup(0, "XYZBC", &kp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_trtfuncs_setup_xyzac(void) {
|
||||||
|
kparms kp = {0};
|
||||||
|
static char kinsname[] = "xyzac-trt-kins";
|
||||||
|
static char halprefix[] = "xyzac-trt-kins";
|
||||||
|
static char required_coordinates[] = "XYZAC";
|
||||||
|
kp.kinsname = kinsname;
|
||||||
|
kp.halprefix = halprefix;
|
||||||
|
kp.required_coordinates = required_coordinates;
|
||||||
|
kp.max_joints = EMCMOT_MAX_JOINTS;
|
||||||
|
kp.allow_duplicates = 1;
|
||||||
|
return trtKinematicsSetup(0, "XYZAC", &kp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_linuxcnc_trtfuncs_set_pins(double x_rot_point,
|
||||||
|
double y_rot_point,
|
||||||
|
double z_rot_point,
|
||||||
|
double x_offset,
|
||||||
|
double y_offset,
|
||||||
|
double z_offset,
|
||||||
|
double tool_offset,
|
||||||
|
bool conventional_directions) {
|
||||||
|
*haldata->x_rot_point = x_rot_point;
|
||||||
|
*haldata->y_rot_point = y_rot_point;
|
||||||
|
*haldata->z_rot_point = z_rot_point;
|
||||||
|
*haldata->x_offset = x_offset;
|
||||||
|
*haldata->y_offset = y_offset;
|
||||||
|
*haldata->z_offset = z_offset;
|
||||||
|
*haldata->tool_offset = tool_offset;
|
||||||
|
*haldata->conventional_directions = conventional_directions;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
241
core/src/linuxcnc_trtfuncs_adapter.cpp
Normal file
241
core/src/linuxcnc_trtfuncs_adapter.cpp
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
#include "linuxcnc_trtfuncs_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_trtfuncs_setup_xyzbc(void);
|
||||||
|
int cnc_sim_linuxcnc_trtfuncs_setup_xyzac(void);
|
||||||
|
void cnc_sim_linuxcnc_trtfuncs_set_pins(double x_rot_point,
|
||||||
|
double y_rot_point,
|
||||||
|
double z_rot_point,
|
||||||
|
double x_offset,
|
||||||
|
double y_offset,
|
||||||
|
double z_offset,
|
||||||
|
double tool_offset,
|
||||||
|
bool conventional_directions);
|
||||||
|
void cnc_sim_linuxcnc_trtfuncs_reset_setup_state(void);
|
||||||
|
int xyzbcKinematicsForward(const double *joints,
|
||||||
|
EmcPose *pos,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags);
|
||||||
|
int xyzbcKinematicsInverse(const EmcPose *pos,
|
||||||
|
double *joints,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags);
|
||||||
|
int xyzacKinematicsForward(const double *joints,
|
||||||
|
EmcPose *pos,
|
||||||
|
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||||
|
KINEMATICS_INVERSE_FLAGS *iflags);
|
||||||
|
int xyzacKinematicsInverse(const EmcPose *pos,
|
||||||
|
double *joints,
|
||||||
|
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||||
|
KINEMATICS_FORWARD_FLAGS *fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
enum class TrtSetup {
|
||||||
|
None,
|
||||||
|
Xyzbc,
|
||||||
|
Xyzac,
|
||||||
|
};
|
||||||
|
|
||||||
|
TrtSetup current_setup = TrtSetup::None;
|
||||||
|
|
||||||
|
bool ensure_xyzbc() {
|
||||||
|
if (current_setup == TrtSetup::Xyzbc) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
cnc_sim_linuxcnc_trtfuncs_reset_setup_state();
|
||||||
|
if (cnc_sim_linuxcnc_trtfuncs_setup_xyzbc() != 0) {
|
||||||
|
current_setup = TrtSetup::None;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
current_setup = TrtSetup::Xyzbc;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ensure_xyzac() {
|
||||||
|
if (current_setup == TrtSetup::Xyzac) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
cnc_sim_linuxcnc_trtfuncs_reset_setup_state();
|
||||||
|
if (cnc_sim_linuxcnc_trtfuncs_setup_xyzac() != 0) {
|
||||||
|
current_setup = TrtSetup::None;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
current_setup = TrtSetup::Xyzac;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_parameters(const LinuxCncXyzbcTrtParameters ¶meters) {
|
||||||
|
cnc_sim_linuxcnc_trtfuncs_set_pins(parameters.x_rot_point,
|
||||||
|
parameters.y_rot_point,
|
||||||
|
parameters.z_rot_point,
|
||||||
|
parameters.x_offset,
|
||||||
|
parameters.y_offset,
|
||||||
|
parameters.z_offset,
|
||||||
|
parameters.tool_offset,
|
||||||
|
parameters.conventional_directions);
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_xyzbc_joints(const LinuxCncFiveAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.b;
|
||||||
|
out[4] = joints.c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_xyzac_joints(const LinuxCncFiveAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.a;
|
||||||
|
out[4] = joints.c;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncFiveAxisJoints from_xyzbc_joints(const double joints[16]) {
|
||||||
|
LinuxCncFiveAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.b = joints[3];
|
||||||
|
out.c = joints[4];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncFiveAxisJoints from_xyzac_joints(const double joints[16]) {
|
||||||
|
LinuxCncFiveAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.a = joints[3];
|
||||||
|
out.c = joints[4];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_trtfuncs_xyzbc_forward(const LinuxCncFiveAxisJoints &joints,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||||
|
CncSimPose *pose) {
|
||||||
|
if (!ensure_xyzbc()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
apply_parameters(parameters);
|
||||||
|
double raw_joints[16];
|
||||||
|
to_xyzbc_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
if (xyzbcKinematicsForward(raw_joints, &out, &fflags, &iflags) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_trtfuncs_xyzbc_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||||
|
LinuxCncFiveAxisJoints *joints) {
|
||||||
|
if (!ensure_xyzbc()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
apply_parameters(parameters);
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
if (xyzbcKinematicsInverse(&in, raw_joints, &iflags, &fflags) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_xyzbc_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_trtfuncs_xyzac_forward(const LinuxCncFiveAxisJoints &joints,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||||
|
CncSimPose *pose) {
|
||||||
|
if (!ensure_xyzac()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
apply_parameters(parameters);
|
||||||
|
double raw_joints[16];
|
||||||
|
to_xyzac_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
if (xyzacKinematicsForward(raw_joints, &out, &fflags, &iflags) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_trtfuncs_xyzac_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||||
|
LinuxCncFiveAxisJoints *joints) {
|
||||||
|
if (!ensure_xyzac()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
apply_parameters(parameters);
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
if (xyzacKinematicsInverse(&in, raw_joints, &iflags, &fflags) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_xyzac_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
16
core/src/linuxcnc_trtfuncs_adapter.h
Normal file
16
core/src/linuxcnc_trtfuncs_adapter.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_trtfuncs_xyzbc_forward(const LinuxCncFiveAxisJoints &joints,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||||
|
CncSimPose *pose);
|
||||||
|
bool linuxcnc_trtfuncs_xyzbc_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||||
|
LinuxCncFiveAxisJoints *joints);
|
||||||
|
bool linuxcnc_trtfuncs_xyzac_forward(const LinuxCncFiveAxisJoints &joints,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||||
|
CncSimPose *pose);
|
||||||
|
bool linuxcnc_trtfuncs_xyzac_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||||
|
LinuxCncFiveAxisJoints *joints);
|
||||||
154
core/src/linuxcnc_userkfuncs_adapter.c
Normal file
154
core/src/linuxcnc_userkfuncs_adapter.c
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_STRING_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_EMCMOTCFG_H
|
||||||
|
#define __LINUXCNC_EMCPOS_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
|
||||||
|
#define RTAPI_MSG_ERR 1
|
||||||
|
#define EMCMOT_MAX_JOINTS 16
|
||||||
|
#define EMCMOT_MAX_AXIS 9
|
||||||
|
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef int hal_s32_t;
|
||||||
|
typedef bool hal_bit_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void cnc_sim_userk_rtapi_print(const char *fmt, ...) {
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_userk_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||||
|
(void)level;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_userk_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_userk_hal_pin_s32_new(const char *name,
|
||||||
|
hal_pin_dir_t dir,
|
||||||
|
hal_s32_t **data_ptr_addr,
|
||||||
|
int comp_id) {
|
||||||
|
(void)name;
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
*data_ptr_addr = (hal_s32_t *)calloc(1, sizeof(hal_s32_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
KINEMATICS_TYPE cnc_sim_userk_kinematicsType(void) {
|
||||||
|
return KINEMATICS_BOTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define rtapi_print cnc_sim_userk_rtapi_print
|
||||||
|
#define rtapi_print_msg cnc_sim_userk_rtapi_print_msg
|
||||||
|
#define kinematicsType cnc_sim_userk_kinematicsType
|
||||||
|
#define hal_pin_s32_new cnc_sim_userk_hal_pin_s32_new
|
||||||
|
#define map_coordinates_to_jnumbers cnc_sim_userk_map_coordinates_to_jnumbers
|
||||||
|
#define mapped_joints_to_position cnc_sim_userk_mapped_joints_to_position
|
||||||
|
#define position_to_mapped_joints cnc_sim_userk_position_to_mapped_joints
|
||||||
|
#define identityKinematicsSetup cnc_sim_userk_identityKinematicsSetup
|
||||||
|
#define identityKinematicsForward cnc_sim_userk_identityKinematicsForward
|
||||||
|
#define identityKinematicsInverse cnc_sim_userk_identityKinematicsInverse
|
||||||
|
#define userkKinematicsSetup cnc_sim_userk_userkKinematicsSetup
|
||||||
|
#define userkKinematicsForward cnc_sim_userk_userkKinematicsForward
|
||||||
|
#define userkKinematicsInverse cnc_sim_userk_userkKinematicsInverse
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/kins_util.c"
|
||||||
|
#define hal_malloc(size) ((struct udata *)cnc_sim_userk_hal_malloc(size))
|
||||||
|
#include "../../../linuxcnc/src/emc/kinematics/userkfuncs.c"
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef userkKinematicsInverse
|
||||||
|
#undef userkKinematicsForward
|
||||||
|
#undef userkKinematicsSetup
|
||||||
|
#undef identityKinematicsInverse
|
||||||
|
#undef identityKinematicsForward
|
||||||
|
#undef identityKinematicsSetup
|
||||||
|
#undef position_to_mapped_joints
|
||||||
|
#undef mapped_joints_to_position
|
||||||
|
#undef map_coordinates_to_jnumbers
|
||||||
|
#undef hal_pin_s32_new
|
||||||
|
#undef kinematicsType
|
||||||
|
#undef rtapi_print_msg
|
||||||
|
#undef rtapi_print
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_userkfuncs_setup(void) {
|
||||||
|
kparms kp = {0};
|
||||||
|
static char kinsname[] = "userkfuncs";
|
||||||
|
static char halprefix[] = "userk";
|
||||||
|
kp.kinsname = kinsname;
|
||||||
|
kp.halprefix = halprefix;
|
||||||
|
kp.max_joints = EMCMOT_MAX_JOINTS;
|
||||||
|
kp.allow_duplicates = 1;
|
||||||
|
if (cnc_sim_userk_identityKinematicsSetup(0, "XYZBC", &kp) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return cnc_sim_userk_userkKinematicsSetup(0, "XYZBC", &kp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_userkfuncs_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_userk_userkKinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_userkfuncs_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_userk_userkKinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
113
core/src/linuxcnc_userkfuncs_adapter.cpp
Normal file
113
core/src/linuxcnc_userkfuncs_adapter.cpp
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#include "linuxcnc_userkfuncs_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_userkfuncs_setup(void);
|
||||||
|
int cnc_sim_linuxcnc_userkfuncs_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_userkfuncs_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_userkfuncs_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncFiveAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.b;
|
||||||
|
out[4] = joints.c;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncFiveAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncFiveAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.b = joints[3];
|
||||||
|
out.c = joints[4];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_userkfuncs_forward(const LinuxCncFiveAxisJoints &joints, CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_userkfuncs_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_userkfuncs_inverse(const CncSimPose &pose, LinuxCncFiveAxisJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
if (cnc_sim_linuxcnc_userkfuncs_inverse(&in, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
6
core/src/linuxcnc_userkfuncs_adapter.h
Normal file
6
core/src/linuxcnc_userkfuncs_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_userkfuncs_forward(const LinuxCncFiveAxisJoints &joints, CncSimPose *pose);
|
||||||
|
bool linuxcnc_userkfuncs_inverse(const CncSimPose &pose, LinuxCncFiveAxisJoints *joints);
|
||||||
241
core/src/linuxcnc_xyzab_tdr_kins_adapter.c
Normal file
241
core/src/linuxcnc_xyzab_tdr_kins_adapter.c
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define __LINUXCNC_RTAPI_H
|
||||||
|
#define __LINUXCNC_RTAPI_APP_H
|
||||||
|
#define __LINUXCNC_RTAPI_STRING_H
|
||||||
|
#define __LINUXCNC_RTAPI_ERRNO_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH_H
|
||||||
|
#define __LINUXCNC_RTAPI_MATH64_H
|
||||||
|
#define __LINUXCNC_HAL_H
|
||||||
|
#define __LINUXCNC_KINEMATICS_H
|
||||||
|
|
||||||
|
#define MODULE_INFO(...)
|
||||||
|
#define MODULE_LICENSE(...)
|
||||||
|
#define EXPORT_SYMBOL(symbol)
|
||||||
|
#define RTAPI_MP_INT(name, description)
|
||||||
|
#define RTAPI_MP_STRING(name, description)
|
||||||
|
|
||||||
|
#define RTAPI_MSG_ERR 1
|
||||||
|
#define RTAPI_MSG_INFO 2
|
||||||
|
#define HAL_NAME_LEN 47
|
||||||
|
#define EINVAL 22
|
||||||
|
#define PM_PI 3.1415926535897932384626433832795029
|
||||||
|
#define TO_RAD (PM_PI / 180.0)
|
||||||
|
|
||||||
|
typedef double real_t;
|
||||||
|
typedef double hal_float_t;
|
||||||
|
typedef int hal_s32_t;
|
||||||
|
typedef unsigned int hal_u32_t;
|
||||||
|
typedef bool hal_bit_t;
|
||||||
|
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} PmCartesian;
|
||||||
|
|
||||||
|
typedef struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
} EmcPose;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KINEMATICS_IDENTITY = 1,
|
||||||
|
KINEMATICS_FORWARD_ONLY,
|
||||||
|
KINEMATICS_INVERSE_ONLY,
|
||||||
|
KINEMATICS_BOTH
|
||||||
|
} KINEMATICS_TYPE;
|
||||||
|
|
||||||
|
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||||
|
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||||
|
|
||||||
|
typedef struct kinematics_parms {
|
||||||
|
char *sparm;
|
||||||
|
char *kinsname;
|
||||||
|
char *halprefix;
|
||||||
|
char *required_coordinates;
|
||||||
|
int max_joints;
|
||||||
|
int allow_duplicates;
|
||||||
|
int fwd_iterates_mask;
|
||||||
|
int gui_kinstype;
|
||||||
|
} kparms;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int __attribute__((weak)) rtapi_snprintf(char *str, unsigned long int size, const char *fmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
const int result = vsnprintf(str, (size_t)size, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_xyzab_tdr_rtapi_print(const char *fmt, ...) {
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_xyzab_tdr_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||||
|
(void)level;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cnc_sim_xyzab_tdr_hal_malloc(long int size) {
|
||||||
|
return calloc(1, (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_xyzab_tdr_hal_init(const char *name) {
|
||||||
|
(void)name;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_xyzab_tdr_hal_exit(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_xyzab_tdr_hal_ready(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_xyzab_tdr_hal_set_unready(int comp_id) {
|
||||||
|
(void)comp_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_xyzab_tdr_hal_pin_s32_newf(hal_pin_dir_t dir,
|
||||||
|
hal_s32_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_s32_t *)calloc(1, sizeof(hal_s32_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_xyzab_tdr_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||||
|
hal_float_t **data_ptr_addr,
|
||||||
|
int comp_id,
|
||||||
|
const char *fmt,
|
||||||
|
...) {
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
(void)fmt;
|
||||||
|
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_xyzab_tdr_hal_pin_bit_new(const char *name,
|
||||||
|
hal_pin_dir_t dir,
|
||||||
|
hal_bit_t **data_ptr_addr,
|
||||||
|
int comp_id) {
|
||||||
|
(void)name;
|
||||||
|
(void)dir;
|
||||||
|
(void)comp_id;
|
||||||
|
*data_ptr_addr = (hal_bit_t *)calloc(1, sizeof(hal_bit_t));
|
||||||
|
return *data_ptr_addr ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define rtapi_print cnc_sim_xyzab_tdr_rtapi_print
|
||||||
|
#define rtapi_print_msg cnc_sim_xyzab_tdr_rtapi_print_msg
|
||||||
|
#define hal_malloc(size) cnc_sim_xyzab_tdr_hal_malloc(size)
|
||||||
|
#define hal_init cnc_sim_xyzab_tdr_hal_init
|
||||||
|
#define hal_exit cnc_sim_xyzab_tdr_hal_exit
|
||||||
|
#define hal_ready cnc_sim_xyzab_tdr_hal_ready
|
||||||
|
#define hal_set_unready cnc_sim_xyzab_tdr_hal_set_unready
|
||||||
|
#define hal_pin_s32_newf cnc_sim_xyzab_tdr_hal_pin_s32_newf
|
||||||
|
#define hal_pin_float_newf cnc_sim_xyzab_tdr_hal_pin_float_newf
|
||||||
|
#define hal_pin_bit_new cnc_sim_xyzab_tdr_hal_pin_bit_new
|
||||||
|
#define kinematicsType cnc_sim_xyzab_tdr_kinematicsType
|
||||||
|
#define kinematicsSwitchable cnc_sim_xyzab_tdr_kinematicsSwitchable
|
||||||
|
#define kinematicsSwitch cnc_sim_xyzab_tdr_kinematicsSwitch
|
||||||
|
#define kinematicsForward cnc_sim_xyzab_tdr_kinematicsForward
|
||||||
|
#define kinematicsInverse cnc_sim_xyzab_tdr_kinematicsInverse
|
||||||
|
#define rtapi_app_main cnc_sim_xyzab_tdr_rtapi_app_main
|
||||||
|
#define rtapi_app_exit cnc_sim_xyzab_tdr_rtapi_app_exit
|
||||||
|
#define export cnc_sim_xyzab_tdr_export
|
||||||
|
#include "../../../linuxcnc/src/objects/hal/components/xyzab_tdr_kins.c"
|
||||||
|
#undef export
|
||||||
|
#undef rtapi_app_exit
|
||||||
|
#undef rtapi_app_main
|
||||||
|
#undef kinematicsInverse
|
||||||
|
#undef kinematicsForward
|
||||||
|
#undef kinematicsSwitch
|
||||||
|
#undef kinematicsSwitchable
|
||||||
|
#undef kinematicsType
|
||||||
|
#undef hal_pin_bit_new
|
||||||
|
#undef hal_pin_float_newf
|
||||||
|
#undef hal_pin_s32_newf
|
||||||
|
#undef hal_set_unready
|
||||||
|
#undef hal_ready
|
||||||
|
#undef hal_exit
|
||||||
|
#undef hal_init
|
||||||
|
#undef hal_malloc
|
||||||
|
#undef rtapi_print_msg
|
||||||
|
#undef rtapi_print
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_xyzab_tdr_kins_setup(void) {
|
||||||
|
return cnc_sim_xyzab_tdr_kinematicsType() == KINEMATICS_BOTH ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnc_sim_linuxcnc_xyzab_tdr_kins_set_parameters(double tool_offset_z,
|
||||||
|
double x_offset,
|
||||||
|
double z_offset,
|
||||||
|
double x_rot_point,
|
||||||
|
double y_rot_point,
|
||||||
|
double z_rot_point) {
|
||||||
|
*haldata->tool_offset_z = tool_offset_z;
|
||||||
|
*haldata->x_offset = x_offset;
|
||||||
|
*haldata->z_offset = z_offset;
|
||||||
|
*haldata->x_rot_point = x_rot_point;
|
||||||
|
*haldata->y_rot_point = y_rot_point;
|
||||||
|
*haldata->z_rot_point = z_rot_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_xyzab_tdr_kins_switch(int switchkins_type) {
|
||||||
|
return cnc_sim_xyzab_tdr_kinematicsSwitch(switchkins_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_xyzab_tdr_kins_switch_state(int *kinstype_is_0, int *kinstype_is_1) {
|
||||||
|
if (!haldata || !haldata->kinstype_is_0 || !haldata->kinstype_is_1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (kinstype_is_0) {
|
||||||
|
*kinstype_is_0 = *haldata->kinstype_is_0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
if (kinstype_is_1) {
|
||||||
|
*kinstype_is_1 = *haldata->kinstype_is_1 ? 1 : 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_xyzab_tdr_kins_forward(const double *joints, EmcPose *pos) {
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
return cnc_sim_xyzab_tdr_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_xyzab_tdr_kins_inverse(const EmcPose *pos, double *joints) {
|
||||||
|
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||||
|
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||||
|
return cnc_sim_xyzab_tdr_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
177
core/src/linuxcnc_xyzab_tdr_kins_adapter.cpp
Normal file
177
core/src/linuxcnc_xyzab_tdr_kins_adapter.cpp
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
#include "linuxcnc_xyzab_tdr_kins_adapter.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct PmCartesian {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmcPose {
|
||||||
|
PmCartesian tran;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cnc_sim_linuxcnc_xyzab_tdr_kins_setup(void);
|
||||||
|
void cnc_sim_linuxcnc_xyzab_tdr_kins_set_parameters(double tool_offset_z,
|
||||||
|
double x_offset,
|
||||||
|
double z_offset,
|
||||||
|
double x_rot_point,
|
||||||
|
double y_rot_point,
|
||||||
|
double z_rot_point);
|
||||||
|
int cnc_sim_linuxcnc_xyzab_tdr_kins_switch(int switchkins_type);
|
||||||
|
int cnc_sim_linuxcnc_xyzab_tdr_kins_switch_state(int *kinstype_is_0, int *kinstype_is_1);
|
||||||
|
int cnc_sim_linuxcnc_xyzab_tdr_kins_forward(const double *joints, EmcPose *pos);
|
||||||
|
int cnc_sim_linuxcnc_xyzab_tdr_kins_inverse(const EmcPose *pos, double *joints);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
bool ensure_initialized() {
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
initialized = cnc_sim_linuxcnc_xyzab_tdr_kins_setup() == 0;
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_parameters(const LinuxCncXyzabTdrParameters ¶meters) {
|
||||||
|
cnc_sim_linuxcnc_xyzab_tdr_kins_set_parameters(parameters.tool_offset_z,
|
||||||
|
parameters.x_offset,
|
||||||
|
parameters.z_offset,
|
||||||
|
parameters.x_rot_point,
|
||||||
|
parameters.y_rot_point,
|
||||||
|
parameters.z_rot_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||||
|
std::memset(out, 0, sizeof(double) * 16);
|
||||||
|
out[0] = joints.x;
|
||||||
|
out[1] = joints.y;
|
||||||
|
out[2] = joints.z;
|
||||||
|
out[3] = joints.a;
|
||||||
|
out[4] = joints.b;
|
||||||
|
out[5] = joints.c;
|
||||||
|
out[6] = joints.u;
|
||||||
|
out[7] = joints.v;
|
||||||
|
out[8] = joints.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||||
|
LinuxCncAxisJoints out{};
|
||||||
|
out.x = joints[0];
|
||||||
|
out.y = joints[1];
|
||||||
|
out.z = joints[2];
|
||||||
|
out.a = joints[3];
|
||||||
|
out.b = joints[4];
|
||||||
|
out.c = joints[5];
|
||||||
|
out.u = joints[6];
|
||||||
|
out.v = joints[7];
|
||||||
|
out.w = joints[8];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||||
|
EmcPose emc{};
|
||||||
|
emc.tran.x = pose.x;
|
||||||
|
emc.tran.y = pose.y;
|
||||||
|
emc.tran.z = pose.z;
|
||||||
|
emc.a = pose.a;
|
||||||
|
emc.b = pose.b;
|
||||||
|
emc.c = pose.c;
|
||||||
|
emc.u = pose.u;
|
||||||
|
emc.v = pose.v;
|
||||||
|
emc.w = pose.w;
|
||||||
|
return emc;
|
||||||
|
}
|
||||||
|
|
||||||
|
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
pose.x = emc.tran.x;
|
||||||
|
pose.y = emc.tran.y;
|
||||||
|
pose.z = emc.tran.z;
|
||||||
|
pose.a = emc.a;
|
||||||
|
pose.b = emc.b;
|
||||||
|
pose.c = emc.c;
|
||||||
|
pose.u = emc.u;
|
||||||
|
pose.v = emc.v;
|
||||||
|
pose.w = emc.w;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool linuxcnc_xyzab_tdr_kins_switch(int switchkins_type) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return cnc_sim_linuxcnc_xyzab_tdr_kins_switch(switchkins_type) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_xyzab_tdr_kins_switch_state(bool *kinstype_is_0, bool *kinstype_is_1) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int raw_kinstype_is_0 = 0;
|
||||||
|
int raw_kinstype_is_1 = 0;
|
||||||
|
if (cnc_sim_linuxcnc_xyzab_tdr_kins_switch_state(&raw_kinstype_is_0, &raw_kinstype_is_1) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (kinstype_is_0) {
|
||||||
|
*kinstype_is_0 = raw_kinstype_is_0 != 0;
|
||||||
|
}
|
||||||
|
if (kinstype_is_1) {
|
||||||
|
*kinstype_is_1 = raw_kinstype_is_1 != 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_xyzab_tdr_kins_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncXyzabTdrParameters ¶meters,
|
||||||
|
int switchkins_type,
|
||||||
|
CncSimPose *pose) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
apply_parameters(parameters);
|
||||||
|
if (!linuxcnc_xyzab_tdr_kins_switch(switchkins_type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
double raw_joints[16];
|
||||||
|
to_joints(joints, raw_joints);
|
||||||
|
EmcPose out{};
|
||||||
|
if (cnc_sim_linuxcnc_xyzab_tdr_kins_forward(raw_joints, &out) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pose = from_emc_pose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_xyzab_tdr_kins_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncXyzabTdrParameters ¶meters,
|
||||||
|
int switchkins_type,
|
||||||
|
LinuxCncAxisJoints *joints) {
|
||||||
|
if (!ensure_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
apply_parameters(parameters);
|
||||||
|
if (!linuxcnc_xyzab_tdr_kins_switch(switchkins_type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const EmcPose in = to_emc_pose(pose);
|
||||||
|
double raw_joints[16] = {};
|
||||||
|
if (cnc_sim_linuxcnc_xyzab_tdr_kins_inverse(&in, raw_joints) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*joints = from_joints(raw_joints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
14
core/src/linuxcnc_xyzab_tdr_kins_adapter.h
Normal file
14
core/src/linuxcnc_xyzab_tdr_kins_adapter.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
|
bool linuxcnc_xyzab_tdr_kins_switch(int switchkins_type);
|
||||||
|
bool linuxcnc_xyzab_tdr_kins_switch_state(bool *kinstype_is_0, bool *kinstype_is_1);
|
||||||
|
bool linuxcnc_xyzab_tdr_kins_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncXyzabTdrParameters ¶meters,
|
||||||
|
int switchkins_type,
|
||||||
|
CncSimPose *pose);
|
||||||
|
bool linuxcnc_xyzab_tdr_kins_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncXyzabTdrParameters ¶meters,
|
||||||
|
int switchkins_type,
|
||||||
|
LinuxCncAxisJoints *joints);
|
||||||
@@ -1,72 +1,497 @@
|
|||||||
#include "rtcp_kinematics.h"
|
#include "rtcp_kinematics.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include "linuxcnc_5axiskins_adapter.h"
|
||||||
|
#include "linuxcnc_corexykins_adapter.h"
|
||||||
|
#include "linuxcnc_genhexkins_adapter.h"
|
||||||
|
#include "linuxcnc_genserfuncs_adapter.h"
|
||||||
|
#include "linuxcnc_kins_util_adapter.h"
|
||||||
|
#include "linuxcnc_lineardeltakins_adapter.h"
|
||||||
|
#include "linuxcnc_maxkins_adapter.h"
|
||||||
|
#include "linuxcnc_pentakins_adapter.h"
|
||||||
|
#include "linuxcnc_pumakins_adapter.h"
|
||||||
|
#include "linuxcnc_rotatekins_adapter.h"
|
||||||
|
#include "linuxcnc_rosekins_adapter.h"
|
||||||
|
#include "linuxcnc_rotarydeltakins_adapter.h"
|
||||||
|
#include "linuxcnc_scarakins_adapter.h"
|
||||||
|
#include "linuxcnc_scorbot_kins_adapter.h"
|
||||||
|
#include "linuxcnc_tripodkins_adapter.h"
|
||||||
|
#include "linuxcnc_trtfuncs_adapter.h"
|
||||||
|
#include "linuxcnc_userkfuncs_adapter.h"
|
||||||
|
#include "linuxcnc_xyzab_tdr_kins_adapter.h"
|
||||||
|
|
||||||
namespace {
|
LinuxCncAxisJoints linuxcnc_identity_default_joints() {
|
||||||
|
return {};
|
||||||
constexpr double kPi = 3.141592653589793238462643383279502884;
|
|
||||||
|
|
||||||
double radians(double degrees) {
|
|
||||||
return degrees * kPi / 180.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RtcpVector rotate_x(RtcpVector vector, double angle) {
|
// Source: linuxcnc/src/emc/kinematics/kins_util.c
|
||||||
const double c = std::cos(angle);
|
// Mirrors identityKinematicsForward() with default XYZABCUVW coordinate mapping.
|
||||||
const double s = std::sin(angle);
|
CncSimPose linuxcnc_identity_forward(const LinuxCncAxisJoints &joints) {
|
||||||
return {
|
CncSimPose pose{};
|
||||||
vector.x,
|
linuxcnc_kins_util_identity_forward(joints, &pose);
|
||||||
vector.y * c - vector.z * s,
|
return pose;
|
||||||
vector.y * s + vector.z * c,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RtcpVector rotate_y(RtcpVector vector, double angle) {
|
// Source: linuxcnc/src/emc/kinematics/kins_util.c
|
||||||
const double c = std::cos(angle);
|
// Mirrors identityKinematicsInverse() with default XYZABCUVW coordinate mapping.
|
||||||
const double s = std::sin(angle);
|
LinuxCncAxisJoints linuxcnc_identity_inverse(const CncSimPose &pose) {
|
||||||
return {
|
LinuxCncAxisJoints joints{};
|
||||||
vector.x * c + vector.z * s,
|
linuxcnc_kins_util_identity_inverse(pose, &joints);
|
||||||
vector.y,
|
return joints;
|
||||||
-vector.x * s + vector.z * c,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RtcpVector rotate_z(RtcpVector vector, double angle) {
|
// Source: linuxcnc/src/emc/kinematics/trivkins.c
|
||||||
const double c = std::cos(angle);
|
// kinematicsForward()/kinematicsInverse() delegate to identityKinematics*().
|
||||||
const double s = std::sin(angle);
|
|
||||||
return {
|
// Source: linuxcnc/src/emc/kinematics/corexykins.c
|
||||||
vector.x * c - vector.y * s,
|
// Mirrors kinematicsForward().
|
||||||
vector.x * s + vector.y * c,
|
CncSimPose linuxcnc_corexykins_forward(const LinuxCncAxisJoints &joints) {
|
||||||
vector.z,
|
CncSimPose pose{};
|
||||||
};
|
linuxcnc_corexykins_source_forward(joints, &pose);
|
||||||
|
return pose;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
// Source: linuxcnc/src/emc/kinematics/corexykins.c
|
||||||
|
// Mirrors kinematicsInverse().
|
||||||
RtcpVector rtcp_rotate_abc_degrees(RtcpVector vector, double a_deg, double b_deg, double c_deg) {
|
LinuxCncAxisJoints linuxcnc_corexykins_inverse(const CncSimPose &pose) {
|
||||||
vector = rotate_x(vector, radians(a_deg));
|
LinuxCncAxisJoints joints{};
|
||||||
vector = rotate_y(vector, radians(b_deg));
|
linuxcnc_corexykins_source_inverse(pose, &joints);
|
||||||
vector = rotate_z(vector, radians(c_deg));
|
return joints;
|
||||||
return vector;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RtcpVector rtcp_tool_vector_from_pose(const CncSimPose &pose, double tool_length) {
|
// Source: linuxcnc/src/emc/kinematics/rotatekins.c
|
||||||
return rtcp_rotate_abc_degrees({0.0, 0.0, -tool_length}, pose.a, pose.b, pose.c);
|
// Mirrors kinematicsForward().
|
||||||
|
CncSimPose linuxcnc_rotatekins_forward(const LinuxCncAxisJoints &joints) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_rotatekins_source_forward(joints, &pose);
|
||||||
|
return pose;
|
||||||
}
|
}
|
||||||
|
|
||||||
CncSimPose rtcp_pivot_from_tool_tip(const CncSimPose &tool_tip, double tool_length) {
|
// Source: linuxcnc/src/emc/kinematics/rotatekins.c
|
||||||
const RtcpVector tool = rtcp_tool_vector_from_pose(tool_tip, tool_length);
|
// Mirrors kinematicsInverse().
|
||||||
CncSimPose pivot = tool_tip;
|
LinuxCncAxisJoints linuxcnc_rotatekins_inverse(const CncSimPose &pose) {
|
||||||
pivot.x = tool_tip.x - tool.x;
|
LinuxCncAxisJoints joints{};
|
||||||
pivot.y = tool_tip.y - tool.y;
|
linuxcnc_rotatekins_source_inverse(pose, &joints);
|
||||||
pivot.z = tool_tip.z - tool.z;
|
return joints;
|
||||||
return pivot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CncSimPose rtcp_tool_tip_from_pivot(const CncSimPose &pivot, double tool_length) {
|
// Source: linuxcnc/src/emc/kinematics/genhexkins.c
|
||||||
const RtcpVector tool = rtcp_tool_vector_from_pose(pivot, tool_length);
|
// Mirrors genhexKinematicsInverse().
|
||||||
CncSimPose tool_tip = pivot;
|
LinuxCncGenhexJoints linuxcnc_genhex_inverse(const CncSimPose &pose) {
|
||||||
tool_tip.x = pivot.x + tool.x;
|
LinuxCncGenhexJoints joints{};
|
||||||
tool_tip.y = pivot.y + tool.y;
|
linuxcnc_genhexkins_source_inverse(pose, &joints);
|
||||||
tool_tip.z = pivot.z + tool.z;
|
return joints;
|
||||||
return tool_tip;
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/genhexkins.c
|
||||||
|
// Mirrors genhexKinematicsForward().
|
||||||
|
CncSimPose linuxcnc_genhex_forward(const LinuxCncGenhexJoints &joints, const CncSimPose &initial_pose) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_genhexkins_source_forward(joints, initial_pose, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/pentakins.c
|
||||||
|
// Mirrors kinematicsInverse().
|
||||||
|
LinuxCncPentakinsJoints linuxcnc_pentakins_inverse(const CncSimPose &pose) {
|
||||||
|
LinuxCncPentakinsJoints joints{};
|
||||||
|
linuxcnc_pentakins_source_inverse(pose, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/pentakins.c
|
||||||
|
// Mirrors kinematicsForward().
|
||||||
|
CncSimPose linuxcnc_pentakins_forward(const LinuxCncPentakinsJoints &joints,
|
||||||
|
const CncSimPose &initial_pose) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_pentakins_source_forward(joints, initial_pose, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/tripodkins.c
|
||||||
|
// Mirrors kinematicsInverse().
|
||||||
|
LinuxCncTripodJoints linuxcnc_tripodkins_inverse(const CncSimPose &pose) {
|
||||||
|
LinuxCncTripodJoints joints{};
|
||||||
|
linuxcnc_tripodkins_source_inverse(pose, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/tripodkins.c
|
||||||
|
// Mirrors kinematicsForward() with the default positive-Z forward flag.
|
||||||
|
CncSimPose linuxcnc_tripodkins_forward(const LinuxCncTripodJoints &joints) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_tripodkins_source_forward(joints, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/scorbot-kins.c
|
||||||
|
// Mirrors kinematicsInverse().
|
||||||
|
LinuxCncScorbotJoints linuxcnc_scorbot_kins_inverse(const CncSimPose &pose) {
|
||||||
|
LinuxCncScorbotJoints joints{};
|
||||||
|
linuxcnc_scorbot_kins_source_inverse(pose, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/scorbot-kins.c
|
||||||
|
// Mirrors kinematicsForward().
|
||||||
|
CncSimPose linuxcnc_scorbot_kins_forward(const LinuxCncScorbotJoints &joints) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_scorbot_kins_source_forward(joints, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source defaults: linuxcnc/src/emc/kinematics/lineardeltakins-common.h
|
||||||
|
LinuxCncLinearDeltaParameters linuxcnc_lineardelta_default_parameters() {
|
||||||
|
LinuxCncLinearDeltaParameters parameters{};
|
||||||
|
linuxcnc_lineardeltakins_source_default_parameters(¶meters);
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/lineardeltakins.c
|
||||||
|
// Mirrors kinematicsForward().
|
||||||
|
CncSimPose linuxcnc_lineardelta_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncLinearDeltaParameters ¶meters) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_lineardeltakins_source_forward(joints, parameters, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/lineardeltakins.c
|
||||||
|
// Mirrors kinematicsInverse().
|
||||||
|
LinuxCncAxisJoints linuxcnc_lineardelta_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncLinearDeltaParameters ¶meters) {
|
||||||
|
LinuxCncAxisJoints joints{};
|
||||||
|
linuxcnc_lineardeltakins_source_inverse(pose, parameters, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source defaults: linuxcnc/src/emc/kinematics/rotarydeltakins-common.h
|
||||||
|
LinuxCncRotaryDeltaParameters linuxcnc_rotarydelta_default_parameters() {
|
||||||
|
LinuxCncRotaryDeltaParameters parameters{};
|
||||||
|
linuxcnc_rotarydeltakins_source_default_parameters(¶meters);
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/rotarydeltakins.c
|
||||||
|
// Mirrors kinematicsForward().
|
||||||
|
CncSimPose linuxcnc_rotarydelta_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncRotaryDeltaParameters ¶meters) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_rotarydeltakins_source_forward(joints, parameters, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/rotarydeltakins.c
|
||||||
|
// Mirrors kinematicsInverse().
|
||||||
|
LinuxCncAxisJoints linuxcnc_rotarydelta_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncRotaryDeltaParameters ¶meters) {
|
||||||
|
LinuxCncAxisJoints joints{};
|
||||||
|
linuxcnc_rotarydeltakins_source_inverse(pose, parameters, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source defaults: linuxcnc/src/emc/kinematics/maxkins.c
|
||||||
|
LinuxCncMaxkinsParameters linuxcnc_maxkins_default_parameters() {
|
||||||
|
LinuxCncMaxkinsParameters parameters{};
|
||||||
|
linuxcnc_maxkins_source_default_parameters(¶meters);
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/maxkins.c
|
||||||
|
// Mirrors kinematicsForward().
|
||||||
|
CncSimPose linuxcnc_maxkins_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncMaxkinsParameters ¶meters) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_maxkins_source_forward(joints, parameters, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/maxkins.c
|
||||||
|
// Mirrors kinematicsInverse().
|
||||||
|
LinuxCncAxisJoints linuxcnc_maxkins_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncMaxkinsParameters ¶meters) {
|
||||||
|
LinuxCncAxisJoints joints{};
|
||||||
|
linuxcnc_maxkins_source_inverse(pose, parameters, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/rosekins.c
|
||||||
|
// Mirrors kinematicsForward().
|
||||||
|
CncSimPose linuxcnc_rosekins_forward(const LinuxCncAxisJoints &joints) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_rosekins_source_forward(joints, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/rosekins.c
|
||||||
|
// Mirrors kinematicsInverse().
|
||||||
|
LinuxCncAxisJoints linuxcnc_rosekins_inverse(const CncSimPose &pose) {
|
||||||
|
LinuxCncAxisJoints joints{};
|
||||||
|
linuxcnc_rosekins_source_inverse(pose, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/5axiskins.c
|
||||||
|
// Mirrors s2r(), fiveaxis_KinematicsForward().
|
||||||
|
CncSimPose linuxcnc_5axis_forward(const LinuxCncFiveAxisJoints &joints, double pivot_length) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_5axiskins_forward(joints, pivot_length, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/5axiskins.c
|
||||||
|
// Mirrors s2r(), fiveaxis_KinematicsInverse().
|
||||||
|
LinuxCncFiveAxisJoints linuxcnc_5axis_inverse(const CncSimPose &pose, double pivot_length) {
|
||||||
|
LinuxCncFiveAxisJoints joints{};
|
||||||
|
linuxcnc_5axiskins_inverse(pose, pivot_length, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source defaults: linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini
|
||||||
|
LinuxCncXyzbcTrtParameters linuxcnc_xyzbc_trt_default_parameters(double tool_offset) {
|
||||||
|
LinuxCncXyzbcTrtParameters parameters{};
|
||||||
|
parameters.x_offset = -20.0;
|
||||||
|
parameters.y_offset = 0.0;
|
||||||
|
parameters.z_offset = -15.0;
|
||||||
|
parameters.tool_offset = tool_offset;
|
||||||
|
parameters.conventional_directions = false;
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/trtfuncs.c
|
||||||
|
// Mirrors xyzbcKinematicsForward().
|
||||||
|
CncSimPose linuxcnc_xyzbc_trt_forward(const LinuxCncFiveAxisJoints &joints,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_trtfuncs_xyzbc_forward(joints, parameters, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/trtfuncs.c
|
||||||
|
// Mirrors xyzbcKinematicsInverse().
|
||||||
|
LinuxCncFiveAxisJoints linuxcnc_xyzbc_trt_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters) {
|
||||||
|
LinuxCncFiveAxisJoints joints{};
|
||||||
|
linuxcnc_trtfuncs_xyzbc_inverse(pose, parameters, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/trtfuncs.c
|
||||||
|
// Mirrors xyzacKinematicsForward().
|
||||||
|
CncSimPose linuxcnc_xyzac_trt_forward(const LinuxCncFiveAxisJoints &joints,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_trtfuncs_xyzac_forward(joints, parameters, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/trtfuncs.c
|
||||||
|
// Mirrors xyzacKinematicsInverse().
|
||||||
|
LinuxCncFiveAxisJoints linuxcnc_xyzac_trt_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters) {
|
||||||
|
LinuxCncFiveAxisJoints joints{};
|
||||||
|
linuxcnc_trtfuncs_xyzac_inverse(pose, parameters, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/userkfuncs.c
|
||||||
|
// userkKinematicsForward() delegates to identityKinematicsForward(),
|
||||||
|
// implemented in linuxcnc/src/emc/kinematics/kins_util.c.
|
||||||
|
CncSimPose linuxcnc_xyzbc_userk_forward(const LinuxCncFiveAxisJoints &joints) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_userkfuncs_forward(joints, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/userkfuncs.c
|
||||||
|
// userkKinematicsInverse() delegates to identityKinematicsInverse(),
|
||||||
|
// implemented in linuxcnc/src/emc/kinematics/kins_util.c.
|
||||||
|
LinuxCncFiveAxisJoints linuxcnc_xyzbc_userk_inverse(const CncSimPose &pose) {
|
||||||
|
LinuxCncFiveAxisJoints joints{};
|
||||||
|
linuxcnc_userkfuncs_inverse(pose, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source defaults: linuxcnc/src/emc/kinematics/scarakins.c
|
||||||
|
LinuxCncScaraParameters linuxcnc_scara_default_parameters() {
|
||||||
|
LinuxCncScaraParameters parameters{};
|
||||||
|
parameters.d1 = 490.0;
|
||||||
|
parameters.d2 = 340.0;
|
||||||
|
parameters.d3 = 50.0;
|
||||||
|
parameters.d4 = 250.0;
|
||||||
|
parameters.d5 = 50.0;
|
||||||
|
parameters.d6 = 50.0;
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/scarakins.c
|
||||||
|
CncSimPose linuxcnc_scara_forward(const LinuxCncScaraJoints &joints,
|
||||||
|
const LinuxCncScaraParameters ¶meters,
|
||||||
|
int *iflags) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_scarakins_forward(joints, parameters, &pose, iflags);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/scarakins.c
|
||||||
|
LinuxCncScaraJoints linuxcnc_scara_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncScaraParameters ¶meters,
|
||||||
|
int iflags) {
|
||||||
|
LinuxCncScaraJoints joints{};
|
||||||
|
linuxcnc_scarakins_inverse(pose, parameters, iflags, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncXyzabTdrParameters linuxcnc_xyzab_tdr_default_parameters(double tool_offset_z) {
|
||||||
|
LinuxCncXyzabTdrParameters parameters{};
|
||||||
|
parameters.tool_offset_z = tool_offset_z;
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/hal/components/xyzab_tdr_kins.comp
|
||||||
|
// Mirrors kinematicsForward() switchkins type 0.
|
||||||
|
CncSimPose linuxcnc_xyzab_tdr_identity_forward(const LinuxCncAxisJoints &joints) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
LinuxCncXyzabTdrParameters parameters{};
|
||||||
|
linuxcnc_xyzab_tdr_kins_forward(joints, parameters, 0, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/hal/components/xyzab_tdr_kins.comp
|
||||||
|
// Mirrors kinematicsInverse() switchkins type 0.
|
||||||
|
LinuxCncAxisJoints linuxcnc_xyzab_tdr_identity_inverse(const CncSimPose &pose) {
|
||||||
|
LinuxCncAxisJoints joints{};
|
||||||
|
LinuxCncXyzabTdrParameters parameters{};
|
||||||
|
linuxcnc_xyzab_tdr_kins_inverse(pose, parameters, 0, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/hal/components/xyzab_tdr_kins.comp
|
||||||
|
// Mirrors kinematicsForward() switchkins type 1.
|
||||||
|
CncSimPose linuxcnc_xyzab_tdr_tcp_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncXyzabTdrParameters ¶meters) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_xyzab_tdr_kins_forward(joints, parameters, 1, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/hal/components/xyzab_tdr_kins.comp
|
||||||
|
// Mirrors kinematicsInverse() switchkins type 1.
|
||||||
|
LinuxCncAxisJoints linuxcnc_xyzab_tdr_tcp_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncXyzabTdrParameters ¶meters) {
|
||||||
|
LinuxCncAxisJoints joints{};
|
||||||
|
linuxcnc_xyzab_tdr_kins_inverse(pose, parameters, 1, &joints);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncPumaParameters linuxcnc_puma_default_parameters() {
|
||||||
|
LinuxCncPumaParameters parameters{};
|
||||||
|
parameters.a2 = 300.0;
|
||||||
|
parameters.a3 = 50.0;
|
||||||
|
parameters.d3 = 70.0;
|
||||||
|
parameters.d4 = 400.0;
|
||||||
|
parameters.d6 = 70.0;
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/pumakins.c
|
||||||
|
CncSimPose linuxcnc_puma_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncPumaParameters ¶meters,
|
||||||
|
int *iflags) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_pumakins_forward(joints, parameters, &pose, iflags);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/pumakins.c
|
||||||
|
LinuxCncAxisJoints linuxcnc_puma_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncAxisJoints ¤t_joints,
|
||||||
|
const LinuxCncPumaParameters ¶meters,
|
||||||
|
int iflags,
|
||||||
|
int *fflags) {
|
||||||
|
LinuxCncAxisJoints joints{};
|
||||||
|
linuxcnc_pumakins_inverse(pose, current_joints, parameters, iflags, &joints, fflags);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncGenserParameters linuxcnc_genser_puma560_parameters() {
|
||||||
|
LinuxCncGenserParameters parameters{};
|
||||||
|
// Source: linuxcnc/configs/sim/axis/vismach/puma/puma560_dh.hal.
|
||||||
|
parameters.a[0] = 0.0;
|
||||||
|
parameters.a[1] = 0.0;
|
||||||
|
parameters.a[2] = 17.0;
|
||||||
|
parameters.a[3] = 0.0;
|
||||||
|
parameters.a[4] = 0.0;
|
||||||
|
parameters.a[5] = 0.0;
|
||||||
|
|
||||||
|
parameters.alpha[0] = 0.0;
|
||||||
|
parameters.alpha[1] = 1.570796326;
|
||||||
|
parameters.alpha[2] = 0.0;
|
||||||
|
parameters.alpha[3] = 1.570796326;
|
||||||
|
parameters.alpha[4] = -1.570796326;
|
||||||
|
parameters.alpha[5] = 1.570796326;
|
||||||
|
|
||||||
|
parameters.d[0] = 26.45;
|
||||||
|
parameters.d[1] = -5.5;
|
||||||
|
parameters.d[2] = 0.0;
|
||||||
|
parameters.d[3] = 17.05;
|
||||||
|
parameters.d[4] = 0.0;
|
||||||
|
parameters.d[5] = 2.2;
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxCncGenserParameters linuxcnc_genser_default_parameters(int *max_iterations) {
|
||||||
|
LinuxCncGenserParameters parameters{};
|
||||||
|
linuxcnc_genserfuncs_source_default_parameters(¶meters, max_iterations);
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/genserfuncs.c
|
||||||
|
// Mirrors genserKinematicsForward() -> genser_kin_fwd() -> go_link_pose_build()
|
||||||
|
// for the six angular DH joints used by the LinuxCNC puma560 M428 configuration.
|
||||||
|
CncSimPose linuxcnc_genser_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncGenserParameters ¶meters) {
|
||||||
|
CncSimPose pose{};
|
||||||
|
linuxcnc_genserfuncs_forward(joints, parameters, &pose);
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/genserfuncs.c
|
||||||
|
// Mirrors genserKinematicsInverse() for the six angular DH joints used by
|
||||||
|
// the LinuxCNC puma560 M428 configuration.
|
||||||
|
LinuxCncAxisJoints linuxcnc_genser_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncAxisJoints &joint_estimate,
|
||||||
|
const LinuxCncGenserParameters ¶meters,
|
||||||
|
int *iterations,
|
||||||
|
int max_iterations) {
|
||||||
|
if (iterations) {
|
||||||
|
*iterations = -1;
|
||||||
|
}
|
||||||
|
LinuxCncAxisJoints joints = joint_estimate;
|
||||||
|
linuxcnc_genserfuncs_inverse(pose, joint_estimate, parameters, max_iterations, &joints, iterations);
|
||||||
|
return joints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: linuxcnc/src/emc/kinematics/genserfuncs.c
|
||||||
|
// Exposes genserKinematicsInverse() success/failure without changing the
|
||||||
|
// LinuxCNC-computed joint buffer.
|
||||||
|
bool linuxcnc_genser_inverse_checked(const CncSimPose &pose,
|
||||||
|
const LinuxCncAxisJoints &joint_estimate,
|
||||||
|
const LinuxCncGenserParameters ¶meters,
|
||||||
|
LinuxCncAxisJoints *joints,
|
||||||
|
int *iterations,
|
||||||
|
int max_iterations) {
|
||||||
|
if (iterations) {
|
||||||
|
*iterations = -1;
|
||||||
|
}
|
||||||
|
LinuxCncAxisJoints out = joint_estimate;
|
||||||
|
const bool ok = linuxcnc_genserfuncs_inverse(pose,
|
||||||
|
joint_estimate,
|
||||||
|
parameters,
|
||||||
|
max_iterations,
|
||||||
|
&out,
|
||||||
|
iterations);
|
||||||
|
if (joints) {
|
||||||
|
*joints = out;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,207 @@ struct RtcpVector {
|
|||||||
double z;
|
double z;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rotation order is intrinsic tool orientation A then B then C, represented as
|
struct LinuxCncFiveAxisJoints {
|
||||||
// Rz(C) * Ry(B) * Rx(A) applied to a local tool vector.
|
double x;
|
||||||
RtcpVector rtcp_rotate_abc_degrees(RtcpVector vector, double a_deg, double b_deg, double c_deg);
|
double y;
|
||||||
|
double z;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
RtcpVector rtcp_tool_vector_from_pose(const CncSimPose &pose, double tool_length);
|
struct LinuxCncAxisJoints {
|
||||||
CncSimPose rtcp_pivot_from_tool_tip(const CncSimPose &tool_tip, double tool_length);
|
double x;
|
||||||
CncSimPose rtcp_tool_tip_from_pivot(const CncSimPose &pivot, double tool_length);
|
double y;
|
||||||
|
double z;
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double c;
|
||||||
|
double u;
|
||||||
|
double v;
|
||||||
|
double w;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncXyzbcTrtParameters {
|
||||||
|
double x_rot_point;
|
||||||
|
double y_rot_point;
|
||||||
|
double z_rot_point;
|
||||||
|
double x_offset;
|
||||||
|
double y_offset;
|
||||||
|
double z_offset;
|
||||||
|
double tool_offset;
|
||||||
|
bool conventional_directions;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncScaraParameters {
|
||||||
|
double d1;
|
||||||
|
double d2;
|
||||||
|
double d3;
|
||||||
|
double d4;
|
||||||
|
double d5;
|
||||||
|
double d6;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncXyzabTdrParameters {
|
||||||
|
double tool_offset_z;
|
||||||
|
double x_offset;
|
||||||
|
double z_offset;
|
||||||
|
double x_rot_point;
|
||||||
|
double y_rot_point;
|
||||||
|
double z_rot_point;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncPumaParameters {
|
||||||
|
double a2;
|
||||||
|
double a3;
|
||||||
|
double d3;
|
||||||
|
double d4;
|
||||||
|
double d6;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncGenserParameters {
|
||||||
|
double a[6];
|
||||||
|
double alpha[6];
|
||||||
|
double d[6];
|
||||||
|
int unrotate[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncScaraJoints {
|
||||||
|
double j0;
|
||||||
|
double j1;
|
||||||
|
double j2;
|
||||||
|
double j3;
|
||||||
|
double j4;
|
||||||
|
double j5;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncGenhexJoints {
|
||||||
|
double strut[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncPentakinsJoints {
|
||||||
|
double strut[5];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncTripodJoints {
|
||||||
|
double strut[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncScorbotJoints {
|
||||||
|
double j0;
|
||||||
|
double j1;
|
||||||
|
double j2;
|
||||||
|
double j3;
|
||||||
|
double j4;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncLinearDeltaParameters {
|
||||||
|
double r;
|
||||||
|
double l;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncRotaryDeltaParameters {
|
||||||
|
double platformradius;
|
||||||
|
double thighlength;
|
||||||
|
double shinlength;
|
||||||
|
double footradius;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinuxCncMaxkinsParameters {
|
||||||
|
double pivot_length;
|
||||||
|
bool conventional_directions;
|
||||||
|
};
|
||||||
|
|
||||||
|
LinuxCncAxisJoints linuxcnc_identity_default_joints();
|
||||||
|
CncSimPose linuxcnc_identity_forward(const LinuxCncAxisJoints &joints);
|
||||||
|
LinuxCncAxisJoints linuxcnc_identity_inverse(const CncSimPose &pose);
|
||||||
|
|
||||||
|
CncSimPose linuxcnc_corexykins_forward(const LinuxCncAxisJoints &joints);
|
||||||
|
LinuxCncAxisJoints linuxcnc_corexykins_inverse(const CncSimPose &pose);
|
||||||
|
|
||||||
|
CncSimPose linuxcnc_rotatekins_forward(const LinuxCncAxisJoints &joints);
|
||||||
|
LinuxCncAxisJoints linuxcnc_rotatekins_inverse(const CncSimPose &pose);
|
||||||
|
LinuxCncGenhexJoints linuxcnc_genhex_inverse(const CncSimPose &pose);
|
||||||
|
CncSimPose linuxcnc_genhex_forward(const LinuxCncGenhexJoints &joints, const CncSimPose &initial_pose);
|
||||||
|
LinuxCncPentakinsJoints linuxcnc_pentakins_inverse(const CncSimPose &pose);
|
||||||
|
CncSimPose linuxcnc_pentakins_forward(const LinuxCncPentakinsJoints &joints,
|
||||||
|
const CncSimPose &initial_pose);
|
||||||
|
LinuxCncTripodJoints linuxcnc_tripodkins_inverse(const CncSimPose &pose);
|
||||||
|
CncSimPose linuxcnc_tripodkins_forward(const LinuxCncTripodJoints &joints);
|
||||||
|
LinuxCncScorbotJoints linuxcnc_scorbot_kins_inverse(const CncSimPose &pose);
|
||||||
|
CncSimPose linuxcnc_scorbot_kins_forward(const LinuxCncScorbotJoints &joints);
|
||||||
|
LinuxCncLinearDeltaParameters linuxcnc_lineardelta_default_parameters();
|
||||||
|
CncSimPose linuxcnc_lineardelta_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncLinearDeltaParameters ¶meters);
|
||||||
|
LinuxCncAxisJoints linuxcnc_lineardelta_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncLinearDeltaParameters ¶meters);
|
||||||
|
LinuxCncRotaryDeltaParameters linuxcnc_rotarydelta_default_parameters();
|
||||||
|
CncSimPose linuxcnc_rotarydelta_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncRotaryDeltaParameters ¶meters);
|
||||||
|
LinuxCncAxisJoints linuxcnc_rotarydelta_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncRotaryDeltaParameters ¶meters);
|
||||||
|
LinuxCncMaxkinsParameters linuxcnc_maxkins_default_parameters();
|
||||||
|
CncSimPose linuxcnc_maxkins_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncMaxkinsParameters ¶meters);
|
||||||
|
LinuxCncAxisJoints linuxcnc_maxkins_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncMaxkinsParameters ¶meters);
|
||||||
|
CncSimPose linuxcnc_rosekins_forward(const LinuxCncAxisJoints &joints);
|
||||||
|
LinuxCncAxisJoints linuxcnc_rosekins_inverse(const CncSimPose &pose);
|
||||||
|
|
||||||
|
CncSimPose linuxcnc_5axis_forward(const LinuxCncFiveAxisJoints &joints, double pivot_length);
|
||||||
|
LinuxCncFiveAxisJoints linuxcnc_5axis_inverse(const CncSimPose &pose, double pivot_length);
|
||||||
|
|
||||||
|
LinuxCncXyzbcTrtParameters linuxcnc_xyzbc_trt_default_parameters(double tool_offset);
|
||||||
|
CncSimPose linuxcnc_xyzbc_trt_forward(const LinuxCncFiveAxisJoints &joints,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters);
|
||||||
|
LinuxCncFiveAxisJoints linuxcnc_xyzbc_trt_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters);
|
||||||
|
CncSimPose linuxcnc_xyzac_trt_forward(const LinuxCncFiveAxisJoints &joints,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters);
|
||||||
|
LinuxCncFiveAxisJoints linuxcnc_xyzac_trt_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncXyzbcTrtParameters ¶meters);
|
||||||
|
CncSimPose linuxcnc_xyzbc_userk_forward(const LinuxCncFiveAxisJoints &joints);
|
||||||
|
LinuxCncFiveAxisJoints linuxcnc_xyzbc_userk_inverse(const CncSimPose &pose);
|
||||||
|
|
||||||
|
LinuxCncScaraParameters linuxcnc_scara_default_parameters();
|
||||||
|
CncSimPose linuxcnc_scara_forward(const LinuxCncScaraJoints &joints,
|
||||||
|
const LinuxCncScaraParameters ¶meters,
|
||||||
|
int *iflags);
|
||||||
|
LinuxCncScaraJoints linuxcnc_scara_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncScaraParameters ¶meters,
|
||||||
|
int iflags);
|
||||||
|
|
||||||
|
LinuxCncXyzabTdrParameters linuxcnc_xyzab_tdr_default_parameters(double tool_offset_z);
|
||||||
|
CncSimPose linuxcnc_xyzab_tdr_identity_forward(const LinuxCncAxisJoints &joints);
|
||||||
|
LinuxCncAxisJoints linuxcnc_xyzab_tdr_identity_inverse(const CncSimPose &pose);
|
||||||
|
CncSimPose linuxcnc_xyzab_tdr_tcp_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncXyzabTdrParameters ¶meters);
|
||||||
|
LinuxCncAxisJoints linuxcnc_xyzab_tdr_tcp_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncXyzabTdrParameters ¶meters);
|
||||||
|
|
||||||
|
LinuxCncPumaParameters linuxcnc_puma_default_parameters();
|
||||||
|
CncSimPose linuxcnc_puma_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncPumaParameters ¶meters,
|
||||||
|
int *iflags);
|
||||||
|
LinuxCncAxisJoints linuxcnc_puma_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncAxisJoints ¤t_joints,
|
||||||
|
const LinuxCncPumaParameters ¶meters,
|
||||||
|
int iflags,
|
||||||
|
int *fflags);
|
||||||
|
|
||||||
|
LinuxCncGenserParameters linuxcnc_genser_puma560_parameters();
|
||||||
|
LinuxCncGenserParameters linuxcnc_genser_default_parameters(int *max_iterations = nullptr);
|
||||||
|
CncSimPose linuxcnc_genser_forward(const LinuxCncAxisJoints &joints,
|
||||||
|
const LinuxCncGenserParameters ¶meters);
|
||||||
|
LinuxCncAxisJoints linuxcnc_genser_inverse(const CncSimPose &pose,
|
||||||
|
const LinuxCncAxisJoints &joint_estimate,
|
||||||
|
const LinuxCncGenserParameters ¶meters,
|
||||||
|
int *iterations,
|
||||||
|
int max_iterations = 100);
|
||||||
|
bool linuxcnc_genser_inverse_checked(const CncSimPose &pose,
|
||||||
|
const LinuxCncAxisJoints &joint_estimate,
|
||||||
|
const LinuxCncGenserParameters ¶meters,
|
||||||
|
LinuxCncAxisJoints *joints,
|
||||||
|
int *iterations,
|
||||||
|
int max_iterations = 100);
|
||||||
|
|||||||
@@ -6,31 +6,155 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
std::string strip_line_comment(const std::string &line) {
|
bool strip_line_comment(const std::string &line, bool block_delete, std::string *stripped) {
|
||||||
std::string out;
|
std::string out;
|
||||||
bool in_paren = false;
|
bool in_paren = false;
|
||||||
|
bool saw_code = false;
|
||||||
for (char raw : line) {
|
for (char raw : line) {
|
||||||
const char ch = static_cast<char>(std::toupper(static_cast<unsigned char>(raw)));
|
const char ch = static_cast<char>(std::toupper(static_cast<unsigned char>(raw)));
|
||||||
if (in_paren) {
|
if (in_paren) {
|
||||||
|
if (ch == '(') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (ch == ')') {
|
if (ch == ')') {
|
||||||
in_paren = false;
|
in_paren = false;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ch == '(') {
|
if (ch == '(') {
|
||||||
|
saw_code = true;
|
||||||
in_paren = true;
|
in_paren = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ch == ';') {
|
if (ch == ';') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!saw_code && std::isspace(static_cast<unsigned char>(ch))) {
|
||||||
|
out.push_back(ch);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!saw_code && ch == '/') {
|
||||||
|
if (block_delete) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
saw_code = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
saw_code = true;
|
||||||
out.push_back(ch);
|
out.push_back(ch);
|
||||||
}
|
}
|
||||||
return out;
|
if (in_paren) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*stripped = out;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool g_code_is(double actual, double expected) {
|
bool linuxcnc_integer_word_value(double value, int *integer) {
|
||||||
return std::fabs(actual - expected) < 0.0001;
|
*integer = static_cast<int>(std::floor(value));
|
||||||
|
const double fraction = value - *integer;
|
||||||
|
if (fraction > 0.9999) {
|
||||||
|
*integer = static_cast<int>(std::ceil(value));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return fraction <= 0.0001;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linuxcnc_g_word_value(double value, int *g_code) {
|
||||||
|
const double scaled = value * 10.0;
|
||||||
|
int parsed = static_cast<int>(std::floor(scaled));
|
||||||
|
const double fraction = scaled - parsed;
|
||||||
|
if (fraction > 0.999) {
|
||||||
|
parsed = static_cast<int>(std::ceil(scaled));
|
||||||
|
} else if (fraction > 0.001) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (parsed < 0 || parsed > 999) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*g_code = parsed;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read_linuxcnc_real_number(const char *text, size_t start, double *value, size_t *end_index) {
|
||||||
|
const char first = text[start];
|
||||||
|
const char next = text[start + 1];
|
||||||
|
if (first == '[') {
|
||||||
|
double nested = 0.0;
|
||||||
|
size_t nested_end = start + 1;
|
||||||
|
if (!read_linuxcnc_real_number(text, start + 1, &nested, &nested_end) ||
|
||||||
|
text[nested_end] != ']') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*value = nested;
|
||||||
|
*end_index = nested_end + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((first == '+' || first == '-') &&
|
||||||
|
next != '\0' &&
|
||||||
|
!std::isdigit(static_cast<unsigned char>(next)) &&
|
||||||
|
next != '.') {
|
||||||
|
double nested = 0.0;
|
||||||
|
size_t nested_end = start + 1;
|
||||||
|
if (!read_linuxcnc_real_number(text, start + 1, &nested, &nested_end)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*value = first == '-' ? -nested : nested;
|
||||||
|
*end_index = nested_end;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i = start;
|
||||||
|
while (text[i] == '+' || text[i] == '-') {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
const size_t number_start = i;
|
||||||
|
while (std::isdigit(static_cast<unsigned char>(text[i])) || text[i] == '.') {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if (i == start || i == number_start) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::string token(text + start, i - start);
|
||||||
|
char *end = nullptr;
|
||||||
|
const double parsed = std::strtod(token.c_str(), &end);
|
||||||
|
if (end != token.c_str() + token.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*value = parsed;
|
||||||
|
*end_index = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool skip_linuxcnc_leading_n_number(const std::string &stripped, std::string *without_n) {
|
||||||
|
size_t i = 0;
|
||||||
|
while (std::isspace(static_cast<unsigned char>(stripped[i]))) {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if (stripped[i] != 'N') {
|
||||||
|
*without_n = stripped;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
const size_t integer_start = i;
|
||||||
|
while (std::isdigit(static_cast<unsigned char>(stripped[i]))) {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if (i == integer_start) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (stripped[i] == '.') {
|
||||||
|
++i;
|
||||||
|
const size_t fraction_start = i;
|
||||||
|
while (std::isdigit(static_cast<unsigned char>(stripped[i]))) {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if (i == fraction_start) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*without_n = stripped.substr(i);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_m_control_line(const std::string &stripped,
|
bool parse_m_control_line(const std::string &stripped,
|
||||||
@@ -46,9 +170,13 @@ bool parse_m_control_line(const std::string &stripped,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
char *end = nullptr;
|
double raw_value = 0.0;
|
||||||
const long value = std::strtol(text + i, &end, 10);
|
size_t end = i;
|
||||||
if (end == text + i) {
|
if (!read_linuxcnc_real_number(text, i, &raw_value, &end)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int value = 0;
|
||||||
|
if (!linuxcnc_integer_word_value(raw_value, &value) || value < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,19 +184,19 @@ bool parse_m_control_line(const std::string &stripped,
|
|||||||
action.kind = SimulatorGcodeControlKind::KinematicsSwitch;
|
action.kind = SimulatorGcodeControlKind::KinematicsSwitch;
|
||||||
if (value == 428) {
|
if (value == 428) {
|
||||||
action.value = 1;
|
action.value = 1;
|
||||||
action.rtcp_enabled = true;
|
action.m_code = 428;
|
||||||
} else if (value == 429) {
|
} else if (value == 429) {
|
||||||
action.value = 0;
|
action.value = 0;
|
||||||
action.rtcp_enabled = false;
|
action.m_code = 429;
|
||||||
} else if (value == 430) {
|
} else if (value == 430) {
|
||||||
action.value = 2;
|
action.value = 2;
|
||||||
action.rtcp_enabled = true;
|
action.m_code = 430;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
actions->push_back(action);
|
actions->push_back(action);
|
||||||
saw_code = true;
|
saw_code = true;
|
||||||
i = static_cast<size_t>(end - text);
|
i = end;
|
||||||
}
|
}
|
||||||
return saw_code;
|
return saw_code;
|
||||||
}
|
}
|
||||||
@@ -78,7 +206,9 @@ bool parse_rtcp_control_line(const std::string &stripped,
|
|||||||
const char *text = stripped.c_str();
|
const char *text = stripped.c_str();
|
||||||
std::vector<SimulatorGcodeControlAction> parsed;
|
std::vector<SimulatorGcodeControlAction> parsed;
|
||||||
int h_code = 0;
|
int h_code = 0;
|
||||||
|
bool saw_h_word = false;
|
||||||
bool saw_rtcp_code = false;
|
bool saw_rtcp_code = false;
|
||||||
|
bool saw_rtcp_g_word = false;
|
||||||
|
|
||||||
for (size_t i = 0; text[i] != '\0';) {
|
for (size_t i = 0; text[i] != '\0';) {
|
||||||
if (std::isspace(static_cast<unsigned char>(text[i]))) {
|
if (std::isspace(static_cast<unsigned char>(text[i]))) {
|
||||||
@@ -90,26 +220,44 @@ bool parse_rtcp_control_line(const std::string &stripped,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
char *end = nullptr;
|
double value = 0.0;
|
||||||
const double value = std::strtod(text + i, &end);
|
size_t end = i;
|
||||||
if (end == text + i) {
|
if (!read_linuxcnc_real_number(text, i, &value, &end)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (letter == 'H') {
|
if (letter == 'H') {
|
||||||
h_code = static_cast<int>(std::lround(value));
|
if (saw_h_word) {
|
||||||
} else if (g_code_is(value, 43.4) || g_code_is(value, 43.5) || g_code_is(value, 49.0)) {
|
return false;
|
||||||
|
}
|
||||||
|
if (!linuxcnc_integer_word_value(value, &h_code) || h_code < -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
saw_h_word = true;
|
||||||
|
} else {
|
||||||
|
int g_code = 0;
|
||||||
|
if (!linuxcnc_g_word_value(value, &g_code) ||
|
||||||
|
(g_code != 434 && g_code != 435 && g_code != 490)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (saw_rtcp_g_word) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
SimulatorGcodeControlAction action{};
|
SimulatorGcodeControlAction action{};
|
||||||
action.kind = SimulatorGcodeControlKind::RtcpState;
|
action.kind = SimulatorGcodeControlKind::RtcpState;
|
||||||
action.value = static_cast<int>(std::lround(value * 10.0));
|
action.value = g_code;
|
||||||
action.rtcp_enabled = g_code_is(value, 43.4) || g_code_is(value, 43.5);
|
action.rtcp_enabled = g_code == 434 || g_code == 435;
|
||||||
parsed.push_back(action);
|
parsed.push_back(action);
|
||||||
saw_rtcp_code = true;
|
saw_rtcp_code = true;
|
||||||
} else {
|
saw_rtcp_g_word = true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
i = static_cast<size_t>(end - text);
|
i = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto &action : parsed) {
|
||||||
|
if (!action.rtcp_enabled && saw_h_word) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (auto &action : parsed) {
|
for (auto &action : parsed) {
|
||||||
action.h_code = action.rtcp_enabled ? h_code : 0;
|
action.h_code = action.rtcp_enabled ? h_code : 0;
|
||||||
actions->push_back(action);
|
actions->push_back(action);
|
||||||
@@ -121,25 +269,51 @@ bool parse_rtcp_control_line(const std::string &stripped,
|
|||||||
|
|
||||||
bool parse_simulator_gcode_control_line(const std::string &line,
|
bool parse_simulator_gcode_control_line(const std::string &line,
|
||||||
std::vector<SimulatorGcodeControlAction> *actions) {
|
std::vector<SimulatorGcodeControlAction> *actions) {
|
||||||
|
return parse_simulator_gcode_control_line(line, false, actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parse_simulator_gcode_control_line(const std::string &line,
|
||||||
|
bool block_delete,
|
||||||
|
std::vector<SimulatorGcodeControlAction> *actions) {
|
||||||
actions->clear();
|
actions->clear();
|
||||||
const std::string stripped = strip_line_comment(line);
|
std::string stripped;
|
||||||
if (parse_m_control_line(stripped, actions)) {
|
if (!strip_line_comment(line, block_delete, &stripped)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::string control_line;
|
||||||
|
if (!skip_linuxcnc_leading_n_number(stripped, &control_line)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (parse_m_control_line(control_line, actions)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
actions->clear();
|
actions->clear();
|
||||||
if (parse_rtcp_control_line(stripped, actions)) {
|
if (parse_rtcp_control_line(control_line, actions)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
actions->clear();
|
actions->clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_simulator_gcode_control_action(CanonEventSink &sink,
|
bool can_emit_simulator_gcode_control_action(const CanonEventSink &sink,
|
||||||
|
const SimulatorGcodeControlAction &action) {
|
||||||
|
if (action.kind == SimulatorGcodeControlKind::KinematicsSwitch) {
|
||||||
|
return sink.can_switch_m_code_kinematics(action.m_code);
|
||||||
|
}
|
||||||
|
if (action.kind == SimulatorGcodeControlKind::RtcpState) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool emit_simulator_gcode_control_action(CanonEventSink &sink,
|
||||||
const SimulatorGcodeControlAction &action,
|
const SimulatorGcodeControlAction &action,
|
||||||
int line) {
|
int line) {
|
||||||
if (action.kind == SimulatorGcodeControlKind::KinematicsSwitch) {
|
if (action.kind == SimulatorGcodeControlKind::KinematicsSwitch) {
|
||||||
sink.switch_kinematics(action.value, action.rtcp_enabled, line);
|
return sink.switch_m_code_kinematics(action.m_code, action.value, line);
|
||||||
} else if (action.kind == SimulatorGcodeControlKind::RtcpState) {
|
} else if (action.kind == SimulatorGcodeControlKind::RtcpState) {
|
||||||
sink.set_rtcp_state(action.rtcp_enabled, action.h_code, line);
|
sink.set_rtcp_state(action.rtcp_enabled, action.h_code, line);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,18 @@ enum class SimulatorGcodeControlKind {
|
|||||||
struct SimulatorGcodeControlAction {
|
struct SimulatorGcodeControlAction {
|
||||||
SimulatorGcodeControlKind kind;
|
SimulatorGcodeControlKind kind;
|
||||||
int value;
|
int value;
|
||||||
|
int m_code;
|
||||||
bool rtcp_enabled;
|
bool rtcp_enabled;
|
||||||
int h_code;
|
int h_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool parse_simulator_gcode_control_line(const std::string &line,
|
bool parse_simulator_gcode_control_line(const std::string &line,
|
||||||
std::vector<SimulatorGcodeControlAction> *actions);
|
std::vector<SimulatorGcodeControlAction> *actions);
|
||||||
void emit_simulator_gcode_control_action(CanonEventSink &sink,
|
bool parse_simulator_gcode_control_line(const std::string &line,
|
||||||
|
bool block_delete,
|
||||||
|
std::vector<SimulatorGcodeControlAction> *actions);
|
||||||
|
bool can_emit_simulator_gcode_control_action(const CanonEventSink &sink,
|
||||||
|
const SimulatorGcodeControlAction &action);
|
||||||
|
bool emit_simulator_gcode_control_action(CanonEventSink &sink,
|
||||||
const SimulatorGcodeControlAction &action,
|
const SimulatorGcodeControlAction &action,
|
||||||
int line);
|
int line);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@
|
|||||||
#include "canon_event_sink.h"
|
#include "canon_event_sink.h"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class SmokeGcodeParser {
|
class SmokeGcodeParser {
|
||||||
@@ -12,14 +13,38 @@ public:
|
|||||||
int parse(const char *program, size_t program_len, std::string *error);
|
int parse(const char *program, size_t program_len, std::string *error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct SmokeToolTableEntry {
|
||||||
|
int pocketno = 0;
|
||||||
|
CncSimPose offset{};
|
||||||
|
double diameter = 0.0;
|
||||||
|
double frontangle = 0.0;
|
||||||
|
double backangle = 0.0;
|
||||||
|
double orientation = 0.0;
|
||||||
|
};
|
||||||
|
|
||||||
CanonEventSink &sink_;
|
CanonEventSink &sink_;
|
||||||
bool absolute_ = true;
|
bool absolute_ = true;
|
||||||
bool arc_absolute_ = false;
|
bool arc_absolute_ = false;
|
||||||
bool lathe_diameter_mode_ = false;
|
bool lathe_diameter_mode_ = false;
|
||||||
bool cutter_comp_on_ = false;
|
bool cutter_comp_on_ = false;
|
||||||
|
bool cutter_comp_exit_pending_ = false;
|
||||||
|
bool cutter_comp_has_prev_vector_ = false;
|
||||||
|
bool cutter_comp_has_prev_prev_vector_ = false;
|
||||||
|
double cutter_comp_radius_ = 0.0;
|
||||||
|
int spindle_tool_id_ = 0;
|
||||||
|
CncSimPose cutter_comp_prev_vector_{};
|
||||||
|
CncSimPose cutter_comp_prev_prev_vector_{};
|
||||||
|
int cutter_comp_mode_ = 40;
|
||||||
|
bool spindle_css_mode_ = false;
|
||||||
|
bool tool_selected_ = false;
|
||||||
|
bool nurbs_g5_collecting_ = false;
|
||||||
|
int nurbs_g5_control_points_ = 0;
|
||||||
|
int nurbs_g5_order_ = 3;
|
||||||
|
bool nurbs_g6_collecting_ = false;
|
||||||
int feed_mode_ = 0;
|
int feed_mode_ = 0;
|
||||||
int canned_cycle_ = 0;
|
int canned_cycle_ = 0;
|
||||||
bool canned_return_to_initial_ = false;
|
bool canned_return_to_initial_ = false;
|
||||||
|
bool g92_applied_ = false;
|
||||||
bool canned_has_r_ = false;
|
bool canned_has_r_ = false;
|
||||||
bool canned_has_z_ = false;
|
bool canned_has_z_ = false;
|
||||||
bool canned_has_p_ = false;
|
bool canned_has_p_ = false;
|
||||||
@@ -36,6 +61,11 @@ private:
|
|||||||
double canned_i_ = 0.0;
|
double canned_i_ = 0.0;
|
||||||
double canned_j_ = 0.0;
|
double canned_j_ = 0.0;
|
||||||
double canned_k_ = 0.0;
|
double canned_k_ = 0.0;
|
||||||
|
double m66_result_ = 0.0;
|
||||||
double oword_return_value_ = 0.0;
|
double oword_return_value_ = 0.0;
|
||||||
bool oword_value_returned_ = false;
|
bool oword_value_returned_ = false;
|
||||||
|
int selected_tool_id_ = 0;
|
||||||
|
int current_pocket_index_ = 0;
|
||||||
|
int selected_pocket_index_ = 0;
|
||||||
|
std::unordered_map<int, SmokeToolTableEntry> tool_table_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "canon_event_sink.h"
|
#include "canon_event_sink.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -25,6 +26,18 @@ bool expect(bool value, const char *message) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool near(double actual, double expected) {
|
||||||
|
return std::fabs(actual - expected) < 1e-9;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool expect_near(double actual, double expected, const char *message) {
|
||||||
|
if (!near(actual, expected)) {
|
||||||
|
std::cerr << "FAIL: " << message << " actual=" << actual << " expected=" << expected << '\n';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
@@ -32,6 +45,8 @@ int main() {
|
|||||||
std::vector<CncSimEvent> events;
|
std::vector<CncSimEvent> events;
|
||||||
CanonEventSink sink;
|
CanonEventSink sink;
|
||||||
sink.set_callback(collect_event, &events);
|
sink.set_callback(collect_event, &events);
|
||||||
|
ok &= expect(sink.kinematics_type() == 0,
|
||||||
|
"expected LinuxCNC xyzbc-trt identityfirst startup kinematics type 0");
|
||||||
|
|
||||||
CncSimPose end{};
|
CncSimPose end{};
|
||||||
end.x = 10.0;
|
end.x = 10.0;
|
||||||
@@ -49,6 +64,8 @@ int main() {
|
|||||||
|
|
||||||
int abort_count = 0;
|
int abort_count = 0;
|
||||||
sink.reset();
|
sink.reset();
|
||||||
|
ok &= expect(sink.kinematics_type() == 0,
|
||||||
|
"expected LinuxCNC xyzbc-trt identityfirst reset kinematics type 0");
|
||||||
sink.set_callback(abort_on_second_event, &abort_count);
|
sink.set_callback(abort_on_second_event, &abort_count);
|
||||||
sink.select_plane(17, 1);
|
sink.select_plane(17, 1);
|
||||||
sink.set_feed_rate(100.0, 2);
|
sink.set_feed_rate(100.0, 2);
|
||||||
@@ -56,6 +73,290 @@ int main() {
|
|||||||
ok &= expect(sink.callback_aborted(), "expected callback abort state");
|
ok &= expect(sink.callback_aborted(), "expected callback abort state");
|
||||||
ok &= expect(abort_count == 2, "expected no further callbacks after abort");
|
ok &= expect(abort_count == 2, "expected no further callbacks after abort");
|
||||||
|
|
||||||
|
events.clear();
|
||||||
|
sink.reset();
|
||||||
|
sink.set_callback(collect_event, &events);
|
||||||
|
sink.configure_rtcp(false, 250.0);
|
||||||
|
sink.switch_kinematics(2, 1);
|
||||||
|
CncSimPose five_axis_end{};
|
||||||
|
five_axis_end.x = 260.0;
|
||||||
|
five_axis_end.y = 20.0;
|
||||||
|
five_axis_end.z = 280.0;
|
||||||
|
five_axis_end.b = 90.0;
|
||||||
|
five_axis_end.c = 45.0;
|
||||||
|
five_axis_end.w = 12.0;
|
||||||
|
sink.straight_feed(2, five_axis_end);
|
||||||
|
bool saw_userk_before_g434 = false;
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_userk_before_g434 = saw_userk_before_g434 || event.type == CNC_SIM_EVENT_RTCP_PIVOT;
|
||||||
|
}
|
||||||
|
ok &= expect(!saw_userk_before_g434, "expected M430 not to enable RTCP without G43.4/G43.5");
|
||||||
|
|
||||||
|
events.clear();
|
||||||
|
sink.set_rtcp_state(true, 0, 2);
|
||||||
|
sink.straight_feed(3, five_axis_end);
|
||||||
|
bool saw_userk_pivot = false;
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_userk_pivot = saw_userk_pivot ||
|
||||||
|
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||||
|
event.line == 3 &&
|
||||||
|
event.reserved == 2 &&
|
||||||
|
near(event.dwell_seconds, 250.0) &&
|
||||||
|
near(event.end.x, 260.0) &&
|
||||||
|
near(event.end.y, 20.0) &&
|
||||||
|
near(event.end.z, 280.0) &&
|
||||||
|
near(event.end.b, 90.0) &&
|
||||||
|
near(event.end.c, 45.0) &&
|
||||||
|
near(event.end.w, 0.0));
|
||||||
|
}
|
||||||
|
ok &= expect(saw_userk_pivot, "expected M430-style RTCP pivot to use LinuxCNC userk identity inverse");
|
||||||
|
|
||||||
|
events.clear();
|
||||||
|
sink.configure_rtcp(true, 0.0);
|
||||||
|
sink.switch_kinematics(2, 3);
|
||||||
|
bool saw_userk_remap_m68 = false;
|
||||||
|
bool saw_userk_remap_m66 = false;
|
||||||
|
bool saw_userk_switch_rtcp_feed = false;
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_userk_remap_m68 = saw_userk_remap_m68 ||
|
||||||
|
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||||
|
event.line == 3 &&
|
||||||
|
event.reserved == 68 &&
|
||||||
|
event.tool == 3 &&
|
||||||
|
near(event.feed, 2.0));
|
||||||
|
saw_userk_remap_m66 = saw_userk_remap_m66 ||
|
||||||
|
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||||
|
event.line == 3 &&
|
||||||
|
event.reserved == 66 &&
|
||||||
|
event.tool == 0 &&
|
||||||
|
near(event.feed, 0.0) &&
|
||||||
|
near(event.dwell_seconds, 0.0));
|
||||||
|
saw_userk_switch_rtcp_feed = saw_userk_switch_rtcp_feed ||
|
||||||
|
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||||
|
event.line == 3 &&
|
||||||
|
event.reserved == 2 &&
|
||||||
|
near(event.feed, 1.0));
|
||||||
|
}
|
||||||
|
ok &= expect(saw_userk_remap_m68, "expected M430 remap to emit LinuxCNC M68 E3 Q2 side effect");
|
||||||
|
ok &= expect(saw_userk_remap_m66, "expected M430 remap to emit LinuxCNC M66 E0 L0 side effect");
|
||||||
|
ok &= expect(!saw_userk_switch_rtcp_feed,
|
||||||
|
"expected kinematics switch event not to carry RTCP state");
|
||||||
|
|
||||||
|
events.clear();
|
||||||
|
CncSimPose zero_tool_end{};
|
||||||
|
zero_tool_end.x = 7.0;
|
||||||
|
zero_tool_end.y = 8.0;
|
||||||
|
zero_tool_end.z = 9.0;
|
||||||
|
zero_tool_end.b = 10.0;
|
||||||
|
zero_tool_end.c = 11.0;
|
||||||
|
sink.straight_feed(4, zero_tool_end);
|
||||||
|
bool saw_zero_tool_userk_pivot = false;
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_zero_tool_userk_pivot = saw_zero_tool_userk_pivot ||
|
||||||
|
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||||
|
event.line == 4 &&
|
||||||
|
event.reserved == 2 &&
|
||||||
|
near(event.dwell_seconds, 0.0) &&
|
||||||
|
near(event.end.x, 7.0) &&
|
||||||
|
near(event.end.y, 8.0) &&
|
||||||
|
near(event.end.z, 9.0) &&
|
||||||
|
near(event.end.b, 10.0) &&
|
||||||
|
near(event.end.c, 11.0));
|
||||||
|
}
|
||||||
|
ok &= expect(saw_zero_tool_userk_pivot, "expected M430 userk inverse to run with zero tool offset");
|
||||||
|
|
||||||
|
events.clear();
|
||||||
|
sink.configure_rtcp(false, 250.0);
|
||||||
|
sink.switch_kinematics(1, 3);
|
||||||
|
CncSimPose trt_end{};
|
||||||
|
trt_end.x = 225.0;
|
||||||
|
trt_end.y = 20.0;
|
||||||
|
trt_end.z = -205.0;
|
||||||
|
trt_end.b = 90.0;
|
||||||
|
sink.straight_feed(4, trt_end);
|
||||||
|
bool saw_trt_before_g434 = false;
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_trt_before_g434 = saw_trt_before_g434 || event.type == CNC_SIM_EVENT_RTCP_PIVOT;
|
||||||
|
}
|
||||||
|
ok &= expect(!saw_trt_before_g434, "expected M428 not to enable RTCP without G43.4/G43.5");
|
||||||
|
|
||||||
|
events.clear();
|
||||||
|
sink.set_rtcp_state(true, 0, 4);
|
||||||
|
sink.straight_feed(5, trt_end);
|
||||||
|
bool saw_xyzbc_trt_pivot = false;
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_xyzbc_trt_pivot = saw_xyzbc_trt_pivot ||
|
||||||
|
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||||
|
event.line == 5 &&
|
||||||
|
event.reserved == 1 &&
|
||||||
|
near(event.dwell_seconds, 250.0) &&
|
||||||
|
near(event.end.x, 10.0) &&
|
||||||
|
near(event.end.y, 20.0) &&
|
||||||
|
near(event.end.z, 30.0) &&
|
||||||
|
near(event.end.b, 90.0));
|
||||||
|
}
|
||||||
|
ok &= expect(saw_xyzbc_trt_pivot, "expected M428-style RTCP pivot to use LinuxCNC xyzbc-trt inverse");
|
||||||
|
|
||||||
|
events.clear();
|
||||||
|
LinuxCncXyzbcTrtParameters trt_parameters = linuxcnc_xyzbc_trt_default_parameters(0.0);
|
||||||
|
trt_parameters.x_rot_point = 3.0;
|
||||||
|
trt_parameters.y_rot_point = -4.0;
|
||||||
|
trt_parameters.z_rot_point = 5.0;
|
||||||
|
trt_parameters.x_offset = 2.0;
|
||||||
|
trt_parameters.z_offset = 7.0;
|
||||||
|
trt_parameters.conventional_directions = true;
|
||||||
|
sink.configure_rtcp(false, 11.0);
|
||||||
|
sink.configure_xyzbc_trt(trt_parameters);
|
||||||
|
sink.switch_kinematics(1, 5);
|
||||||
|
sink.set_rtcp_state(true, 0, 5);
|
||||||
|
CncSimPose configured_trt_end{};
|
||||||
|
configured_trt_end.x = 30.0;
|
||||||
|
configured_trt_end.y = 40.0;
|
||||||
|
configured_trt_end.z = 50.0;
|
||||||
|
configured_trt_end.b = 20.0;
|
||||||
|
configured_trt_end.c = -30.0;
|
||||||
|
sink.straight_feed(6, configured_trt_end);
|
||||||
|
LinuxCncXyzbcTrtParameters expected_trt_parameters = trt_parameters;
|
||||||
|
expected_trt_parameters.tool_offset = 11.0;
|
||||||
|
const LinuxCncFiveAxisJoints expected_configured_trt =
|
||||||
|
linuxcnc_xyzbc_trt_inverse(configured_trt_end, expected_trt_parameters);
|
||||||
|
bool saw_configured_trt_pivot = false;
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_configured_trt_pivot = saw_configured_trt_pivot ||
|
||||||
|
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||||
|
event.line == 6 &&
|
||||||
|
event.reserved == 1 &&
|
||||||
|
near(event.dwell_seconds, 11.0) &&
|
||||||
|
near(event.end.x, expected_configured_trt.x) &&
|
||||||
|
near(event.end.y, expected_configured_trt.y) &&
|
||||||
|
near(event.end.z, expected_configured_trt.z) &&
|
||||||
|
near(event.end.b, expected_configured_trt.b) &&
|
||||||
|
near(event.end.c, expected_configured_trt.c));
|
||||||
|
}
|
||||||
|
ok &= expect(saw_configured_trt_pivot, "expected M428 xyzbc-trt inverse to use configured HAL-style pins");
|
||||||
|
|
||||||
|
events.clear();
|
||||||
|
LinuxCncXyzbcTrtParameters xyzac_parameters = linuxcnc_xyzbc_trt_default_parameters(0.0);
|
||||||
|
xyzac_parameters.y_offset = 20.0;
|
||||||
|
xyzac_parameters.z_offset = 10.0;
|
||||||
|
sink.configure_rtcp(false, 7.0);
|
||||||
|
sink.configure_xyzac_trt(xyzac_parameters);
|
||||||
|
sink.switch_kinematics(1, 6);
|
||||||
|
sink.set_rtcp_state(true, 0, 6);
|
||||||
|
CncSimPose xyzac_end{};
|
||||||
|
xyzac_end.x = 12.0;
|
||||||
|
xyzac_end.y = -8.0;
|
||||||
|
xyzac_end.z = 42.0;
|
||||||
|
xyzac_end.a = 35.0;
|
||||||
|
xyzac_end.c = -25.0;
|
||||||
|
sink.straight_feed(7, xyzac_end);
|
||||||
|
LinuxCncXyzbcTrtParameters expected_xyzac_parameters = xyzac_parameters;
|
||||||
|
expected_xyzac_parameters.tool_offset = 7.0;
|
||||||
|
const LinuxCncFiveAxisJoints expected_xyzac =
|
||||||
|
linuxcnc_xyzac_trt_inverse(xyzac_end, expected_xyzac_parameters);
|
||||||
|
bool saw_xyzac_trt_pivot = false;
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_xyzac_trt_pivot = saw_xyzac_trt_pivot ||
|
||||||
|
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||||
|
event.line == 7 &&
|
||||||
|
event.reserved == 1 &&
|
||||||
|
near(event.dwell_seconds, 7.0) &&
|
||||||
|
near(event.end.x, expected_xyzac.x) &&
|
||||||
|
near(event.end.y, expected_xyzac.y) &&
|
||||||
|
near(event.end.z, expected_xyzac.z) &&
|
||||||
|
near(event.end.a, expected_xyzac.a) &&
|
||||||
|
near(event.end.c, expected_xyzac.c));
|
||||||
|
}
|
||||||
|
ok &= expect(saw_xyzac_trt_pivot, "expected M428 xyzac-trt inverse to use LinuxCNC xyzacKinematicsInverse");
|
||||||
|
|
||||||
|
std::vector<CncSimEvent> fiveaxis_events;
|
||||||
|
CanonEventSink fiveaxis_sink;
|
||||||
|
fiveaxis_sink.set_callback(collect_event, &fiveaxis_events);
|
||||||
|
fiveaxis_sink.configure_rtcp(true, 250.0);
|
||||||
|
fiveaxis_sink.configure_fiveaxis(250.0, 0);
|
||||||
|
fiveaxis_sink.switch_m_code_kinematics(428, 1, 8);
|
||||||
|
CncSimPose bridgemill_end{};
|
||||||
|
bridgemill_end.x = 260.0;
|
||||||
|
bridgemill_end.y = 20.0;
|
||||||
|
bridgemill_end.z = 280.0;
|
||||||
|
bridgemill_end.b = 90.0;
|
||||||
|
bridgemill_end.c = 0.0;
|
||||||
|
fiveaxis_sink.straight_feed(9, bridgemill_end);
|
||||||
|
bool saw_fiveaxis_pivot = false;
|
||||||
|
for (const auto &event : fiveaxis_events) {
|
||||||
|
saw_fiveaxis_pivot = saw_fiveaxis_pivot ||
|
||||||
|
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||||
|
event.line == 9 &&
|
||||||
|
event.reserved == 0 &&
|
||||||
|
near(event.dwell_seconds, 250.0) &&
|
||||||
|
near(event.end.x, 10.0) &&
|
||||||
|
near(event.end.y, 20.0) &&
|
||||||
|
near(event.end.z, 30.0) &&
|
||||||
|
near(event.end.b, 90.0) &&
|
||||||
|
near(event.end.c, 0.0));
|
||||||
|
}
|
||||||
|
ok &= expect(saw_fiveaxis_pivot, "expected M428 bridgemill RTCP pivot to use LinuxCNC 5axiskins inverse");
|
||||||
|
|
||||||
|
std::vector<CncSimEvent> switchkins_events;
|
||||||
|
CanonEventSink switchkins_sink;
|
||||||
|
switchkins_sink.set_callback(collect_event, &switchkins_events);
|
||||||
|
switchkins_sink.configure_switchkins_remap(0, 1, 2);
|
||||||
|
switchkins_sink.switch_m_code_kinematics(428, 1, 10);
|
||||||
|
switchkins_sink.switch_m_code_kinematics(429, 0, 11);
|
||||||
|
bool saw_scara_m428 = false;
|
||||||
|
bool saw_scara_m429 = false;
|
||||||
|
for (const auto &event : switchkins_events) {
|
||||||
|
saw_scara_m428 = saw_scara_m428 ||
|
||||||
|
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||||
|
event.line == 10 &&
|
||||||
|
event.reserved == 0);
|
||||||
|
saw_scara_m429 = saw_scara_m429 ||
|
||||||
|
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||||
|
event.line == 11 &&
|
||||||
|
event.reserved == 1);
|
||||||
|
}
|
||||||
|
ok &= expect(saw_scara_m428,
|
||||||
|
"expected M428 scara/bridgemill/melfa remap to select LinuxCNC kinstype 0");
|
||||||
|
ok &= expect(saw_scara_m429,
|
||||||
|
"expected M429 scara/bridgemill/melfa remap to select LinuxCNC identity kinstype 1");
|
||||||
|
|
||||||
|
std::vector<CncSimEvent> table_dual_events;
|
||||||
|
CanonEventSink table_dual_sink;
|
||||||
|
table_dual_sink.set_callback(collect_event, &table_dual_events);
|
||||||
|
table_dual_sink.configure_switchkins_remap(1, 0, -1);
|
||||||
|
const bool table_dual_m430_handled = table_dual_sink.switch_m_code_kinematics(430, 2, 12);
|
||||||
|
bool saw_table_dual_m430 = false;
|
||||||
|
for (const auto &event : table_dual_events) {
|
||||||
|
saw_table_dual_m430 = saw_table_dual_m430 ||
|
||||||
|
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||||
|
event.line == 12);
|
||||||
|
}
|
||||||
|
ok &= expect(!table_dual_m430_handled,
|
||||||
|
"expected LinuxCNC table-dual-rotary config without 430remap.ngc to leave M430 unhandled");
|
||||||
|
ok &= expect(!saw_table_dual_m430,
|
||||||
|
"expected LinuxCNC table-dual-rotary config without 430remap.ngc to skip M430 switch");
|
||||||
|
|
||||||
|
events.clear();
|
||||||
|
sink.configure_rtcp(true, 250.0);
|
||||||
|
sink.switch_kinematics(0, 3);
|
||||||
|
five_axis_end.x = 300.0;
|
||||||
|
sink.straight_feed(4, five_axis_end);
|
||||||
|
bool saw_disabled_pivot = false;
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_disabled_pivot = saw_disabled_pivot || event.type == CNC_SIM_EVENT_RTCP_PIVOT;
|
||||||
|
}
|
||||||
|
ok &= expect(!saw_disabled_pivot, "expected M429-style kinematics switch to disable RTCP pivot events");
|
||||||
|
|
||||||
|
events.clear();
|
||||||
|
sink.configure_rtcp(true, 250.0);
|
||||||
|
sink.switch_kinematics(3, 5);
|
||||||
|
sink.straight_feed(6, five_axis_end);
|
||||||
|
bool saw_unknown_switchkins_pivot = false;
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_unknown_switchkins_pivot = saw_unknown_switchkins_pivot || event.type == CNC_SIM_EVENT_RTCP_PIVOT;
|
||||||
|
}
|
||||||
|
ok &= expect(!saw_unknown_switchkins_pivot,
|
||||||
|
"expected unsupported switchkins type to avoid generic RTCP fallback");
|
||||||
|
|
||||||
return ok ? 0 : 1;
|
return ok ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user