Compare commits

..

1 Commits

Author SHA1 Message Date
cnc
f1e10045df Align LinuxCNC parser coverage 2026-05-23 17:28:41 +08:00
660 changed files with 1402 additions and 58858 deletions

View File

@@ -116,13 +116,19 @@ 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"}
``` ```
`linuxcnc-rs274` 是默认后端wasm 和 UI 默认通过 LinuxCNC RS274 源码路径解析;`smoke` 仅用于显式编译/选择的 legacy 联调路径 网页面板右上角的 `BACKEND` 下拉框会把该配置传给 wasm/core。当前默认 wasm 构建不包含 LinuxCNC 后端,选择 `LINUXCNC` 会返回明确错误native API 测试已验证该后端可用
网页面板右上角的 `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 配置
@@ -137,19 +143,11 @@ 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 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 内核是第一版头头/摆头类几何模型:编程 XYZ 视为刀尖点,刀长沿本地 `-Z`A/B/C 按 `Rz(C) * Ry(B) * Rx(A)` 旋转。后续会继续加入机型拓扑、旋转中心偏置、刀表刀长和不同五轴构型
RTCP G 码控制已开始标准化: RTCP G 码控制已开始标准化:
@@ -163,11 +161,11 @@ RTCP G 码控制已开始标准化:
core 已对原型中的运动学切换 M 码做标准化解析: core 已对原型中的运动学切换 M 码做标准化解析:
- `M429`:切换到三轴恒等运动学 `IDENTITY` - `M429`:切换到三轴恒等运动学 `IDENTITY`,关闭 RTCP
- `M428`切换到 LinuxCNC `xyzbc-trt-kins` 的 XYZBC TRT 运动学 - `M428`恢复到原始五轴运动学,开启 RTCP
- `M430`:切换到 LinuxCNC 默认 `userk` 运动学;当前对齐 `userkfuncs.c` 的 identity 正/逆解 - `M430`:切换到 `FIVEAXIS_BC`,开启 RTCP
解析后会发出 `kinematics-switch` 事件。事件中的 `reserved` 字段表示运动学类型:`0=IDENTITY``1=XYZBC_TRT``2=USERK_IDENTITY`。这些 M 码对齐 LinuxCNC `remap_subs/428remap.ngc``429remap.ngc``430remap.ngc`,只设置 `motion.switchkins-type`,不隐式开启或关闭 RTCPRTCP 状态仍由 `G43.4``G43.5``G49` 控制。同一行中的 `M428 M429 M430` 会按出现顺序产生三个切换事件。 解析后会发出 `kinematics-switch` 事件。事件中的 `reserved` 字段表示运动学类型:`0=IDENTITY``1=ORIGINAL``2=FIVEAXIS_BC``feed` 字段临时表示 RTCP 状态:`0=关闭``1=开启`。同一行中的 `M428 M429 M430` 会按出现顺序产生三个切换事件。
`linuxcnc-rs274` native API backend 会在送入 LinuxCNC 解释器前拦截只包含这些切换 M 码的行,避免 LinuxCNC 去查找外部用户 M-code 文件。 `linuxcnc-rs274` native API backend 会在送入 LinuxCNC 解释器前拦截只包含这些切换 M 码的行,避免 LinuxCNC 去查找外部用户 M-code 文件。

View File

@@ -1,214 +0,0 @@
#!/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[@]}"

View File

@@ -1,105 +0,0 @@
#!/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[@]}"

View File

@@ -1,152 +0,0 @@
#!/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"

View File

@@ -1,197 +0,0 @@
#!/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[@]}"

View File

@@ -1,211 +0,0 @@
#!/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"

View File

@@ -3,208 +3,14 @@ set -euo pipefail
cd "$(dirname "$0")" cd "$(dirname "$0")"
# LinuxCNC source basis: the wasm build preflights and compiles the if ! command -v emcmake >/dev/null 2>&1; then
# linuxcnc-rs274-wasm-source-files.txt manifest entries from echo "Emscripten is required. Install/activate emsdk so emcmake and emcc are in PATH." >&2
# 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
wasm_build_signature=build/wasm/wasm-build.signature emcmake cmake -S core -B build/wasm -DCMAKE_BUILD_TYPE=Release
wasm_build_next_signature=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_build.signature.XXXXXX") cmake --build build/wasm
{
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/cnc_sim.js cp build/wasm/cnc_sim.js web/public/
cp build/wasm/cnc_sim.wasm web/public/cnc_sim.wasm cp build/wasm/cnc_sim.wasm web/public/
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

View File

@@ -1,130 +0,0 @@
#!/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

View File

@@ -1,202 +0,0 @@
#!/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

View File

@@ -1,136 +0,0 @@
#!/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"

File diff suppressed because it is too large Load Diff

View File

@@ -1,97 +0,0 @@
#!/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

View File

@@ -1,182 +0,0 @@
#!/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

View File

@@ -1,102 +0,0 @@
#!/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

View File

@@ -1,107 +0,0 @@
#!/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

View File

@@ -1,123 +0,0 @@
#!/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"

File diff suppressed because it is too large Load Diff

View File

@@ -1,333 +0,0 @@
#!/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

View File

@@ -1,194 +0,0 @@
#!/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

View File

@@ -1,499 +0,0 @@
#!/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

View File

@@ -1,204 +0,0 @@
#!/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

View File

@@ -1,132 +0,0 @@
#!/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

View File

@@ -1,224 +1,31 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
project(cnc_sim_wasm_core LANGUAGES C CXX) project(cnc_sim_wasm_core LANGUAGES 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 ${cnc_sim_linuxcnc_rs274_backend_sources}) list(APPEND cnc_sim_core_sources
elseif(CNC_SIM_ENABLE_SMOKE_BACKEND) src/linuxcnc_canon_bridge.cpp
list(APPEND cnc_sim_core_sources ${cnc_sim_smoke_backend_sources}) src/linuxcnc_rs274_backend.cpp
endif() src/linuxcnc_tooldata_fixture.cpp
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
@@ -230,36 +37,9 @@ 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)
@@ -279,97 +59,6 @@ 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>
) )
@@ -399,13 +88,11 @@ 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
@@ -419,24 +106,17 @@ 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
@@ -476,11 +156,7 @@ 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>
) )
@@ -488,15 +164,7 @@ 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"
@@ -504,14 +172,12 @@ 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=['FS','ccall','cwrap','UTF8ToString','stringToUTF8','lengthBytesUTF8','addFunction','removeFunction']" "-sEXPORTED_RUNTIME_METHODS=['ccall','cwrap','UTF8ToString','stringToUTF8','lengthBytesUTF8','addFunction','removeFunction']"
) )
endif() endif()

View File

@@ -1,23 +1,6 @@
#include "canon_event_sink.h" #include "canon_event_sink.h"
#include <cmath> #include "rtcp_kinematics.h"
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_ = {};
@@ -31,19 +14,14 @@ 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;
// LinuxCNC xyzbc-trt-kins with sparm=identityfirst starts at switchkins-type 0. kinematics_type_ = 1;
// 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) {
@@ -60,41 +38,12 @@ 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 &parameters) {
xyzbc_trt_parameters_ = parameters;
xyzbc_trt_parameters_configured_ = true;
use_xyzac_trt_ = false;
}
void CanonEventSink::configure_xyzac_trt(const LinuxCncXyzbcTrtParameters &parameters) {
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;
@@ -113,26 +62,6 @@ 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;
@@ -147,72 +76,15 @@ void CanonEventSink::set_rtcp_state(bool enabled, int h_code, int line) {
emit(event); emit(event);
} }
void CanonEventSink::switch_kinematics(int kinematics_type, int line) { void CanonEventSink::switch_kinematics(int kinematics_type, bool rtcp_enabled, int line) {
kinematics_type_ = kinematics_type; kinematics_type_ = kinematics_type;
// Source: linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/{428,429,430}remap.ngc. rtcp_enabled_ = rtcp_enabled;
// 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;
@@ -227,48 +99,12 @@ 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;
@@ -302,13 +138,8 @@ 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) {
set_spindle_speed(0, spindle, line); spindle_ = spindle;
}
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);
@@ -318,7 +149,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 ? kConstantRpmSpindleModeEvent : kCssSpindleModeEvent; event.reserved = mode == 0.0 ? 970 : 960;
emit(event); emit(event);
} }
@@ -398,26 +229,16 @@ 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);
@@ -435,45 +256,41 @@ 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 = has_pending_motion_start_ ? pending_motion_start_ : position_; event.start = position_;
event.end = end; event.end = end;
emit(event); emit(event);
emit_rtcp_pivot(line, event.start, end); emit_rtcp_pivot(line, position_, 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 = has_pending_motion_start_ ? pending_motion_start_ : position_; event.start = position_;
event.end = end; event.end = end;
emit(event); emit(event);
emit_rtcp_pivot(line, event.start, end); emit_rtcp_pivot(line, position_, end);
has_pending_motion_start_ = false;
position_ = end; position_ = end;
} }
void CanonEventSink::arc_feed(int line, const CncSimPose &end, const CncSimPose &center, int turns) { void CanonEventSink::arc_feed(int line, const CncSimPose &end, const CncSimPose &center, int turns) {
CncSimEvent event = base_event(CNC_SIM_EVENT_ARC_FEED, line); CncSimEvent event = base_event(CNC_SIM_EVENT_ARC_FEED, line);
event.start = has_pending_motion_start_ ? pending_motion_start_ : position_; event.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, event.start, end); emit_rtcp_pivot(line, position_, 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 = has_pending_motion_start_ ? pending_motion_start_ : position_; event.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;
} }
@@ -580,10 +397,6 @@ 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;
} }
@@ -599,67 +412,16 @@ 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_ || callback_status_ != 0) { if (!rtcp_enabled_ || rtcp_tool_length_ == 0.0 || 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);
if (fiveaxis_configured_ && kinematics_type_ == fiveaxis_kinematics_type_) { event.start = rtcp_pivot_from_tool_tip(start, rtcp_tool_length_);
const LinuxCncFiveAxisJoints start_joints = event.end = rtcp_pivot_from_tool_tip(end, rtcp_tool_length_);
linuxcnc_5axis_inverse(start, fiveaxis_pivot_length_); const RtcpVector tool = rtcp_tool_vector_from_pose(end, rtcp_tool_length_);
const LinuxCncFiveAxisJoints end_joints = event.center.x = tool.x;
linuxcnc_5axis_inverse(end, fiveaxis_pivot_length_); event.center.y = tool.y;
event.start.x = start_joints.x; event.center.z = tool.z;
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);
} }

View File

@@ -1,7 +1,6 @@
#pragma once #pragma once
#include "cnc_sim_api.h" #include "cnc_sim_api.h"
#include "rtcp_kinematics.h"
#include <unordered_map> #include <unordered_map>
@@ -11,31 +10,21 @@ 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 &parameters);
void configure_xyzac_trt(const LinuxCncXyzbcTrtParameters &parameters);
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, int line); void switch_kinematics(int kinematics_type, bool rtcp_enabled, 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);
@@ -45,9 +34,7 @@ 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);
@@ -79,7 +66,6 @@ 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);
@@ -105,27 +91,13 @@ 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_{};
double xy_rotation_degrees_ = 0.0; int kinematics_type_ = 1;
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_{};
}; };

View File

@@ -4,14 +4,12 @@
#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::LinuxCncRs274; GcodeBackendKind backend = GcodeBackendKind::Smoke;
GcodeBackendOptions backend_options;
std::string last_error; std::string last_error;
CanonEventSink sink; CanonEventSink sink;
}; };
@@ -75,116 +73,6 @@ 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);
@@ -240,118 +128,6 @@ 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, &parameters.x_rot_point, "xrotpoint", "x_rot_point", "x-rot-point") ||
configured;
configured = find_number_any(compact, &parameters.y_rot_point, "yrotpoint", "y_rot_point", "y-rot-point") ||
configured;
configured = find_number_any(compact, &parameters.z_rot_point, "zrotpoint", "z_rot_point", "z-rot-point") ||
configured;
configured = find_number_any(compact, &parameters.x_offset, "xoffset", "x_offset", "x-offset") ||
configured;
configured = find_number_any(compact, &parameters.y_offset, "yoffset", "y_offset", "y-offset") ||
configured;
configured = find_number_any(compact, &parameters.z_offset, "zoffset", "z_offset", "z-offset") ||
configured;
configured = contains_bool_any(compact,
&parameters.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;
@@ -367,20 +143,6 @@ 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) ||
@@ -390,15 +152,7 @@ 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;
} }
@@ -464,12 +218,7 @@ 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, const int rc = parse_gcode_with_backend(handle->backend, handle->sink, program, program_len, &handle->last_error);
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";
} }

View File

@@ -3,9 +3,7 @@
#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) {
@@ -22,23 +20,15 @@ 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, options, error); return parse_linuxcnc_rs274_backend(sink, program, program_len, 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";

View File

@@ -10,15 +10,11 @@ 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);

View File

@@ -1,266 +0,0 @@
#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

View File

@@ -1,122 +0,0 @@
#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;
}

View File

@@ -1,10 +0,0 @@
#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);

View File

@@ -15,8 +15,6 @@
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;
@@ -28,19 +26,6 @@ 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) {
@@ -65,12 +50,6 @@ 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;
} }
@@ -94,12 +73,6 @@ 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;
@@ -111,27 +84,6 @@ const CncSimPose &current_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);
@@ -193,7 +145,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(), true); active_sink->use_length_units(units_to_scale(units), event_line());
} }
} }
@@ -211,10 +163,10 @@ void SET_FEED_RATE(double rate) {
} }
} }
void SET_SPINDLE_SPEED(int spindle, double speed) { void SET_SPINDLE_SPEED(int, double speed) {
trace_call("SET_SPINDLE_SPEED"); trace_call("SET_SPINDLE_SPEED");
if (active_sink) { if (active_sink) {
active_sink->set_spindle_speed(spindle, speed, event_line()); active_sink->set_spindle_speed(speed, event_line());
} }
} }
@@ -228,10 +180,6 @@ 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());
} }
} }
@@ -402,15 +350,6 @@ 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) {
@@ -434,21 +373,27 @@ void STOP_SPEED_FEED_SYNCH() {
} }
} }
void NURBS_G5_FEED(int lineno, const std::vector<NURBS_CONTROL_POINT> &points, unsigned int, CANON_PLANE plane) { void NURBS_G5_FEED(int lineno, const std::vector<NURBS_CONTROL_POINT> &points, unsigned int, CANON_PLANE) {
if (!active_sink) { if (!active_sink) {
return; return;
} }
for (const auto &point : points) { for (const auto &point : points) {
active_sink->straight_feed(event_line(lineno), nurbs_plane_point_to_pose(point, plane)); CncSimPose end = active_sink->position();
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 plane) { void NURBS_G6_FEED(int lineno, const std::vector<NURBS_G6_CONTROL_POINT> &points, unsigned int, double, int, CANON_PLANE) {
if (!active_sink) { if (!active_sink) {
return; return;
} }
for (const auto &point : points) { for (const auto &point : points) {
active_sink->straight_feed(event_line(lineno), nurbs_plane_point_to_pose(point, plane)); CncSimPose end = active_sink->position();
end.x = point.NURBS_X;
end.y = point.NURBS_Y;
active_sink->straight_feed(lineno, end);
} }
} }
@@ -486,21 +431,21 @@ void SET_SPINDLE_MODE(int spindle, double mode) {
void SPINDLE_RETRACT_TRAVERSE() { void SPINDLE_RETRACT_TRAVERSE() {
} }
void START_SPINDLE_CLOCKWISE(int spindle, int) { void START_SPINDLE_CLOCKWISE(int, int) {
if (active_sink) { if (active_sink) {
active_sink->start_spindle(spindle, 1, event_line()); active_sink->start_spindle(1, event_line());
} }
} }
void START_SPINDLE_COUNTERCLOCKWISE(int spindle, int) { void START_SPINDLE_COUNTERCLOCKWISE(int, int) {
if (active_sink) { if (active_sink) {
active_sink->start_spindle(spindle, -1, event_line()); active_sink->start_spindle(-1, event_line());
} }
} }
void STOP_SPINDLE_TURNING(int spindle) { void STOP_SPINDLE_TURNING(int) {
if (active_sink) { if (active_sink) {
active_sink->stop_spindle(spindle, event_line()); active_sink->stop_spindle(event_line());
} }
} }
@@ -543,14 +488,13 @@ 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 = kToolLengthOffsetEvent; event.reserved = 430;
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());
} }
@@ -782,16 +726,11 @@ int GET_EXTERNAL_FLOOD() {
} }
CANON_UNITS GET_EXTERNAL_LENGTH_UNIT_TYPE() { CANON_UNITS GET_EXTERNAL_LENGTH_UNIT_TYPE() {
// LinuxCNC src/emc/task/emccanon.cc derives this from INI machine/user return active_sink && active_sink->unit_scale() == 25.4 ? CANON_UNITS_INCHES : CANON_UNITS_MM;
// units, not from the active G20/G21 program units.
return CANON_UNITS_MM;
} }
double GET_EXTERNAL_LENGTH_UNITS() { double GET_EXTERNAL_LENGTH_UNITS() {
// LinuxCNC src/emc/task/emccanon.cc returns traj.linearUnits here: return active_sink ? active_sink->unit_scale() : 1.0;
// 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() {

View File

@@ -1,127 +0,0 @@
#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

View File

@@ -1,104 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#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);

View File

@@ -1,117 +0,0 @@
#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

View File

@@ -1,36 +0,0 @@
#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;
}

View File

@@ -1,11 +0,0 @@
#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();

View File

@@ -1,223 +0,0 @@
#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

View File

@@ -1,96 +0,0 @@
#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;
}

View File

@@ -1,8 +0,0 @@
#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);

View File

@@ -1,206 +0,0 @@
#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

View File

@@ -1,166 +0,0 @@
#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 &parameters, 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 &parameters,
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 &parameters,
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;
}

View File

@@ -1,15 +0,0 @@
#pragma once
#include "rtcp_kinematics.h"
bool linuxcnc_genserfuncs_forward(const LinuxCncAxisJoints &joints,
const LinuxCncGenserParameters &parameters,
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 &parameters,
int max_iterations,
LinuxCncAxisJoints *joints,
int *iterations);

View File

@@ -1,116 +0,0 @@
#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

View File

@@ -1,121 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#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);

View File

@@ -1,155 +0,0 @@
#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

View File

@@ -1,138 +0,0 @@
#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 &parameters,
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 &parameters,
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;
}

View File

@@ -1,11 +0,0 @@
#pragma once
#include "rtcp_kinematics.h"
bool linuxcnc_lineardeltakins_source_default_parameters(LinuxCncLinearDeltaParameters *parameters);
bool linuxcnc_lineardeltakins_source_forward(const LinuxCncAxisJoints &joints,
const LinuxCncLinearDeltaParameters &parameters,
CncSimPose *pose);
bool linuxcnc_lineardeltakins_source_inverse(const CncSimPose &pose,
const LinuxCncLinearDeltaParameters &parameters,
LinuxCncAxisJoints *joints);

View File

@@ -1,168 +0,0 @@
#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

View File

@@ -1,140 +0,0 @@
#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 &parameters,
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 &parameters,
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;
}

View File

@@ -1,11 +0,0 @@
#pragma once
#include "rtcp_kinematics.h"
bool linuxcnc_maxkins_source_default_parameters(LinuxCncMaxkinsParameters *parameters);
bool linuxcnc_maxkins_source_forward(const LinuxCncAxisJoints &joints,
const LinuxCncMaxkinsParameters &parameters,
CncSimPose *pose);
bool linuxcnc_maxkins_source_inverse(const CncSimPose &pose,
const LinuxCncMaxkinsParameters &parameters,
LinuxCncAxisJoints *joints);

View File

@@ -1,172 +0,0 @@
#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

View File

@@ -1,97 +0,0 @@
#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;
}

View File

@@ -1,9 +0,0 @@
#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);

View File

@@ -1,218 +0,0 @@
#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;
}

View File

@@ -1,156 +0,0 @@
#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 &parameters) {
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 &parameters,
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 &current_joints,
const LinuxCncPumaParameters &parameters,
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;
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include "rtcp_kinematics.h"
bool linuxcnc_pumakins_forward(const LinuxCncAxisJoints &joints,
const LinuxCncPumaParameters &parameters,
CncSimPose *pose,
int *iflags);
bool linuxcnc_pumakins_inverse(const CncSimPose &pose,
const LinuxCncAxisJoints &current_joints,
const LinuxCncPumaParameters &parameters,
int iflags,
LinuxCncAxisJoints *joints,
int *fflags);

View File

@@ -1,147 +0,0 @@
#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

View File

@@ -1,121 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#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);

View File

@@ -1,165 +0,0 @@
#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

View File

@@ -1,157 +0,0 @@
#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 &parameters,
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 &parameters,
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;
}

View File

@@ -1,11 +0,0 @@
#pragma once
#include "rtcp_kinematics.h"
bool linuxcnc_rotarydeltakins_source_default_parameters(LinuxCncRotaryDeltaParameters *parameters);
bool linuxcnc_rotarydeltakins_source_forward(const LinuxCncAxisJoints &joints,
const LinuxCncRotaryDeltaParameters &parameters,
CncSimPose *pose);
bool linuxcnc_rotarydeltakins_source_inverse(const CncSimPose &pose,
const LinuxCncRotaryDeltaParameters &parameters,
LinuxCncAxisJoints *joints);

View File

@@ -1,118 +0,0 @@
#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

View File

@@ -1,104 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#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);

View File

@@ -1,10 +1,6 @@
#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"
@@ -20,14 +16,10 @@
#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
char _parameter_file_name[LINELEN];
#ifndef CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
int _task = 0; int _task = 0;
char _parameter_file_name[LINELEN];
extern "C" PyObject *PyInit_interpreter(void); extern "C" PyObject *PyInit_interpreter(void);
extern "C" PyObject *PyInit_emccanon(void); extern "C" PyObject *PyInit_emccanon(void);
@@ -37,7 +29,6 @@ struct _inittab builtin_modules[] = {
{"emccanon", PyInit_emccanon}, {"emccanon", PyInit_emccanon},
{nullptr, nullptr}, {nullptr, nullptr},
}; };
#endif
namespace { namespace {
@@ -82,48 +73,12 @@ 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) {
const char *tmpdir = std::getenv("TMPDIR"); char tmpl[] = "/tmp/cnc_sim_api_XXXXXX.ngc";
std::string tmpl = std::string(tmpdir ? tmpdir : "/tmp") + "/cnc_sim_api_XXXXXX.ngc"; const int fd = mkstemps(tmpl, 4);
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";
@@ -145,16 +100,15 @@ bool write_temp_program(const char *program,
ok = false; ok = false;
} }
if (!ok) { if (!ok) {
unlink(tmpl_buffer.data()); unlink(tmpl);
if (error) { if (error) {
*error = "failed to write temporary ngc file"; *error = "failed to write temporary ngc file";
} }
return false; return false;
} }
*path = tmpl_buffer.data(); *path = tmpl;
return true; return true;
} }
#endif
int execute_file_mode(InterpBase *interp, int execute_file_mode(InterpBase *interp,
CanonEventSink &sink, CanonEventSink &sink,
@@ -206,7 +160,6 @@ 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) {
@@ -215,36 +168,14 @@ 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) {
@@ -254,18 +185,8 @@ 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();
@@ -281,7 +202,6 @@ 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);
@@ -292,47 +212,21 @@ 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, sink.block_delete(), &control_actions)) { if (parse_simulator_gcode_control_line(line, &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) {
if (!can_emit_simulator_gcode_control_action(sink, action)) { emit_simulator_gcode_control_action(sink, action, line_number);
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)) {
if (!all_control_actions_handled && control_actions.size() > 1) { interp->exit();
for (const auto &action : control_actions) { delete interp;
if (!can_emit_simulator_gcode_control_action(sink, action) && cnc_sim_linuxcnc_set_canon_sink(nullptr);
action.kind == SimulatorGcodeControlKind::KinematicsSwitch) { return -1;
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;
} }

View File

@@ -1,7 +1,6 @@
#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>
@@ -9,5 +8,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);

View File

@@ -1,224 +0,0 @@
#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);
}

View File

@@ -1,144 +0,0 @@
#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 &parameters) {
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 &parameters,
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 &parameters,
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;
}

View File

@@ -1,12 +0,0 @@
#pragma once
#include "rtcp_kinematics.h"
bool linuxcnc_scarakins_forward(const LinuxCncScaraJoints &joints,
const LinuxCncScaraParameters &parameters,
CncSimPose *pose,
int *iflags);
bool linuxcnc_scarakins_inverse(const CncSimPose &pose,
const LinuxCncScaraParameters &parameters,
int iflags,
LinuxCncScaraJoints *joints);

View File

@@ -1,121 +0,0 @@
#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

View File

@@ -1,110 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#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);

View File

@@ -1,180 +0,0 @@
// 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},

View File

@@ -2,8 +2,6 @@
#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) {
@@ -24,29 +22,5 @@ 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);
} }

View File

@@ -1,142 +0,0 @@
#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

View File

@@ -1,94 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#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);

View File

@@ -1,163 +0,0 @@
#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

View File

@@ -1,129 +0,0 @@
#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();
}

View File

@@ -1,7 +0,0 @@
#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();

View File

@@ -1,207 +0,0 @@
#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

View File

@@ -1,241 +0,0 @@
#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 &parameters) {
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 &parameters,
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 &parameters,
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 &parameters,
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 &parameters,
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;
}

View File

@@ -1,16 +0,0 @@
#pragma once
#include "rtcp_kinematics.h"
bool linuxcnc_trtfuncs_xyzbc_forward(const LinuxCncFiveAxisJoints &joints,
const LinuxCncXyzbcTrtParameters &parameters,
CncSimPose *pose);
bool linuxcnc_trtfuncs_xyzbc_inverse(const CncSimPose &pose,
const LinuxCncXyzbcTrtParameters &parameters,
LinuxCncFiveAxisJoints *joints);
bool linuxcnc_trtfuncs_xyzac_forward(const LinuxCncFiveAxisJoints &joints,
const LinuxCncXyzbcTrtParameters &parameters,
CncSimPose *pose);
bool linuxcnc_trtfuncs_xyzac_inverse(const CncSimPose &pose,
const LinuxCncXyzbcTrtParameters &parameters,
LinuxCncFiveAxisJoints *joints);

View File

@@ -1,154 +0,0 @@
#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

View File

@@ -1,113 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#pragma once
#include "rtcp_kinematics.h"
bool linuxcnc_userkfuncs_forward(const LinuxCncFiveAxisJoints &joints, CncSimPose *pose);
bool linuxcnc_userkfuncs_inverse(const CncSimPose &pose, LinuxCncFiveAxisJoints *joints);

View File

@@ -1,241 +0,0 @@
#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

View File

@@ -1,177 +0,0 @@
#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 &parameters) {
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 &parameters,
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 &parameters,
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;
}

View File

@@ -1,14 +0,0 @@
#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 &parameters,
int switchkins_type,
CncSimPose *pose);
bool linuxcnc_xyzab_tdr_kins_inverse(const CncSimPose &pose,
const LinuxCncXyzabTdrParameters &parameters,
int switchkins_type,
LinuxCncAxisJoints *joints);

View File

@@ -1,497 +1,72 @@
#include "rtcp_kinematics.h" #include "rtcp_kinematics.h"
#include "linuxcnc_5axiskins_adapter.h" #include <cmath>
#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"
LinuxCncAxisJoints linuxcnc_identity_default_joints() { namespace {
return {};
constexpr double kPi = 3.141592653589793238462643383279502884;
double radians(double degrees) {
return degrees * kPi / 180.0;
} }
// Source: linuxcnc/src/emc/kinematics/kins_util.c RtcpVector rotate_x(RtcpVector vector, double angle) {
// Mirrors identityKinematicsForward() with default XYZABCUVW coordinate mapping. const double c = std::cos(angle);
CncSimPose linuxcnc_identity_forward(const LinuxCncAxisJoints &joints) { const double s = std::sin(angle);
CncSimPose pose{}; return {
linuxcnc_kins_util_identity_forward(joints, &pose); vector.x,
return pose; vector.y * c - vector.z * s,
vector.y * s + vector.z * c,
};
} }
// Source: linuxcnc/src/emc/kinematics/kins_util.c RtcpVector rotate_y(RtcpVector vector, double angle) {
// Mirrors identityKinematicsInverse() with default XYZABCUVW coordinate mapping. const double c = std::cos(angle);
LinuxCncAxisJoints linuxcnc_identity_inverse(const CncSimPose &pose) { const double s = std::sin(angle);
LinuxCncAxisJoints joints{}; return {
linuxcnc_kins_util_identity_inverse(pose, &joints); vector.x * c + vector.z * s,
return joints; vector.y,
-vector.x * s + vector.z * c,
};
} }
// Source: linuxcnc/src/emc/kinematics/trivkins.c RtcpVector rotate_z(RtcpVector vector, double angle) {
// kinematicsForward()/kinematicsInverse() delegate to identityKinematics*(). const double c = std::cos(angle);
const double s = std::sin(angle);
// Source: linuxcnc/src/emc/kinematics/corexykins.c return {
// Mirrors kinematicsForward(). vector.x * c - vector.y * s,
CncSimPose linuxcnc_corexykins_forward(const LinuxCncAxisJoints &joints) { vector.x * s + vector.y * c,
CncSimPose pose{}; vector.z,
linuxcnc_corexykins_source_forward(joints, &pose); };
return pose;
} }
// Source: linuxcnc/src/emc/kinematics/corexykins.c } // namespace
// Mirrors kinematicsInverse().
LinuxCncAxisJoints linuxcnc_corexykins_inverse(const CncSimPose &pose) { RtcpVector rtcp_rotate_abc_degrees(RtcpVector vector, double a_deg, double b_deg, double c_deg) {
LinuxCncAxisJoints joints{}; vector = rotate_x(vector, radians(a_deg));
linuxcnc_corexykins_source_inverse(pose, &joints); vector = rotate_y(vector, radians(b_deg));
return joints; vector = rotate_z(vector, radians(c_deg));
return vector;
} }
// Source: linuxcnc/src/emc/kinematics/rotatekins.c RtcpVector rtcp_tool_vector_from_pose(const CncSimPose &pose, double tool_length) {
// Mirrors kinematicsForward(). return rtcp_rotate_abc_degrees({0.0, 0.0, -tool_length}, pose.a, pose.b, pose.c);
CncSimPose linuxcnc_rotatekins_forward(const LinuxCncAxisJoints &joints) {
CncSimPose pose{};
linuxcnc_rotatekins_source_forward(joints, &pose);
return pose;
} }
// Source: linuxcnc/src/emc/kinematics/rotatekins.c CncSimPose rtcp_pivot_from_tool_tip(const CncSimPose &tool_tip, double tool_length) {
// Mirrors kinematicsInverse(). const RtcpVector tool = rtcp_tool_vector_from_pose(tool_tip, tool_length);
LinuxCncAxisJoints linuxcnc_rotatekins_inverse(const CncSimPose &pose) { CncSimPose pivot = tool_tip;
LinuxCncAxisJoints joints{}; pivot.x = tool_tip.x - tool.x;
linuxcnc_rotatekins_source_inverse(pose, &joints); pivot.y = tool_tip.y - tool.y;
return joints; pivot.z = tool_tip.z - tool.z;
return pivot;
} }
// Source: linuxcnc/src/emc/kinematics/genhexkins.c CncSimPose rtcp_tool_tip_from_pivot(const CncSimPose &pivot, double tool_length) {
// Mirrors genhexKinematicsInverse(). const RtcpVector tool = rtcp_tool_vector_from_pose(pivot, tool_length);
LinuxCncGenhexJoints linuxcnc_genhex_inverse(const CncSimPose &pose) { CncSimPose tool_tip = pivot;
LinuxCncGenhexJoints joints{}; tool_tip.x = pivot.x + tool.x;
linuxcnc_genhexkins_source_inverse(pose, &joints); tool_tip.y = pivot.y + tool.y;
return joints; tool_tip.z = pivot.z + tool.z;
} 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(&parameters);
return parameters;
}
// Source: linuxcnc/src/emc/kinematics/lineardeltakins.c
// Mirrors kinematicsForward().
CncSimPose linuxcnc_lineardelta_forward(const LinuxCncAxisJoints &joints,
const LinuxCncLinearDeltaParameters &parameters) {
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 &parameters) {
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(&parameters);
return parameters;
}
// Source: linuxcnc/src/emc/kinematics/rotarydeltakins.c
// Mirrors kinematicsForward().
CncSimPose linuxcnc_rotarydelta_forward(const LinuxCncAxisJoints &joints,
const LinuxCncRotaryDeltaParameters &parameters) {
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 &parameters) {
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(&parameters);
return parameters;
}
// Source: linuxcnc/src/emc/kinematics/maxkins.c
// Mirrors kinematicsForward().
CncSimPose linuxcnc_maxkins_forward(const LinuxCncAxisJoints &joints,
const LinuxCncMaxkinsParameters &parameters) {
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 &parameters) {
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 &parameters) {
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 &parameters) {
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 &parameters) {
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 &parameters) {
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 &parameters,
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 &parameters,
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 &parameters) {
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 &parameters) {
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 &parameters,
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 &current_joints,
const LinuxCncPumaParameters &parameters,
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(&parameters, 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 &parameters) {
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 &parameters,
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 &parameters,
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;
} }

View File

@@ -8,207 +8,10 @@ struct RtcpVector {
double z; double z;
}; };
struct LinuxCncFiveAxisJoints { // Rotation order is intrinsic tool orientation A then B then C, represented as
double x; // Rz(C) * Ry(B) * Rx(A) applied to a local tool vector.
double y; RtcpVector rtcp_rotate_abc_degrees(RtcpVector vector, double a_deg, double b_deg, double c_deg);
double z;
double a;
double b;
double c;
double w;
};
struct LinuxCncAxisJoints { RtcpVector rtcp_tool_vector_from_pose(const CncSimPose &pose, double tool_length);
double x; CncSimPose rtcp_pivot_from_tool_tip(const CncSimPose &tool_tip, double tool_length);
double y; CncSimPose rtcp_tool_tip_from_pivot(const CncSimPose &pivot, double tool_length);
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 &parameters);
LinuxCncAxisJoints linuxcnc_lineardelta_inverse(const CncSimPose &pose,
const LinuxCncLinearDeltaParameters &parameters);
LinuxCncRotaryDeltaParameters linuxcnc_rotarydelta_default_parameters();
CncSimPose linuxcnc_rotarydelta_forward(const LinuxCncAxisJoints &joints,
const LinuxCncRotaryDeltaParameters &parameters);
LinuxCncAxisJoints linuxcnc_rotarydelta_inverse(const CncSimPose &pose,
const LinuxCncRotaryDeltaParameters &parameters);
LinuxCncMaxkinsParameters linuxcnc_maxkins_default_parameters();
CncSimPose linuxcnc_maxkins_forward(const LinuxCncAxisJoints &joints,
const LinuxCncMaxkinsParameters &parameters);
LinuxCncAxisJoints linuxcnc_maxkins_inverse(const CncSimPose &pose,
const LinuxCncMaxkinsParameters &parameters);
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 &parameters);
LinuxCncFiveAxisJoints linuxcnc_xyzbc_trt_inverse(const CncSimPose &pose,
const LinuxCncXyzbcTrtParameters &parameters);
CncSimPose linuxcnc_xyzac_trt_forward(const LinuxCncFiveAxisJoints &joints,
const LinuxCncXyzbcTrtParameters &parameters);
LinuxCncFiveAxisJoints linuxcnc_xyzac_trt_inverse(const CncSimPose &pose,
const LinuxCncXyzbcTrtParameters &parameters);
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 &parameters,
int *iflags);
LinuxCncScaraJoints linuxcnc_scara_inverse(const CncSimPose &pose,
const LinuxCncScaraParameters &parameters,
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 &parameters);
LinuxCncAxisJoints linuxcnc_xyzab_tdr_tcp_inverse(const CncSimPose &pose,
const LinuxCncXyzabTdrParameters &parameters);
LinuxCncPumaParameters linuxcnc_puma_default_parameters();
CncSimPose linuxcnc_puma_forward(const LinuxCncAxisJoints &joints,
const LinuxCncPumaParameters &parameters,
int *iflags);
LinuxCncAxisJoints linuxcnc_puma_inverse(const CncSimPose &pose,
const LinuxCncAxisJoints &current_joints,
const LinuxCncPumaParameters &parameters,
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 &parameters);
LinuxCncAxisJoints linuxcnc_genser_inverse(const CncSimPose &pose,
const LinuxCncAxisJoints &joint_estimate,
const LinuxCncGenserParameters &parameters,
int *iterations,
int max_iterations = 100);
bool linuxcnc_genser_inverse_checked(const CncSimPose &pose,
const LinuxCncAxisJoints &joint_estimate,
const LinuxCncGenserParameters &parameters,
LinuxCncAxisJoints *joints,
int *iterations,
int max_iterations = 100);

View File

@@ -6,155 +6,31 @@
namespace { namespace {
bool strip_line_comment(const std::string &line, bool block_delete, std::string *stripped) { std::string strip_line_comment(const std::string &line) {
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);
} }
if (in_paren) { return out;
return false;
}
*stripped = out;
return true;
} }
bool linuxcnc_integer_word_value(double value, int *integer) { bool g_code_is(double actual, double expected) {
*integer = static_cast<int>(std::floor(value)); return std::fabs(actual - expected) < 0.0001;
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,
@@ -170,13 +46,9 @@ bool parse_m_control_line(const std::string &stripped,
return false; return false;
} }
++i; ++i;
double raw_value = 0.0; char *end = nullptr;
size_t end = i; const long value = std::strtol(text + i, &end, 10);
if (!read_linuxcnc_real_number(text, i, &raw_value, &end)) { if (end == text + i) {
return false;
}
int value = 0;
if (!linuxcnc_integer_word_value(raw_value, &value) || value < 0) {
return false; return false;
} }
@@ -184,19 +56,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.m_code = 428; action.rtcp_enabled = true;
} else if (value == 429) { } else if (value == 429) {
action.value = 0; action.value = 0;
action.m_code = 429; action.rtcp_enabled = false;
} else if (value == 430) { } else if (value == 430) {
action.value = 2; action.value = 2;
action.m_code = 430; action.rtcp_enabled = true;
} else { } else {
return false; return false;
} }
actions->push_back(action); actions->push_back(action);
saw_code = true; saw_code = true;
i = end; i = static_cast<size_t>(end - text);
} }
return saw_code; return saw_code;
} }
@@ -206,9 +78,7 @@ 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]))) {
@@ -220,44 +90,26 @@ bool parse_rtcp_control_line(const std::string &stripped,
return false; return false;
} }
++i; ++i;
double value = 0.0; char *end = nullptr;
size_t end = i; const double value = std::strtod(text + i, &end);
if (!read_linuxcnc_real_number(text, i, &value, &end)) { if (end == text + i) {
return false; return false;
} }
if (letter == 'H') { if (letter == 'H') {
if (saw_h_word) { h_code = static_cast<int>(std::lround(value));
return false; } else if (g_code_is(value, 43.4) || g_code_is(value, 43.5) || g_code_is(value, 49.0)) {
}
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 = g_code; action.value = static_cast<int>(std::lround(value * 10.0));
action.rtcp_enabled = g_code == 434 || g_code == 435; action.rtcp_enabled = g_code_is(value, 43.4) || g_code_is(value, 43.5);
parsed.push_back(action); parsed.push_back(action);
saw_rtcp_code = true; saw_rtcp_code = true;
saw_rtcp_g_word = true; } else {
}
i = end;
}
for (const auto &action : parsed) {
if (!action.rtcp_enabled && saw_h_word) {
return false; return false;
} }
i = static_cast<size_t>(end - text);
} }
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);
@@ -269,51 +121,25 @@ 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();
std::string stripped; const std::string stripped = strip_line_comment(line);
if (!strip_line_comment(line, block_delete, &stripped)) { if (parse_m_control_line(stripped, actions)) {
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(control_line, actions)) { if (parse_rtcp_control_line(stripped, actions)) {
return true; return true;
} }
actions->clear(); actions->clear();
return false; return false;
} }
bool can_emit_simulator_gcode_control_action(const CanonEventSink &sink, void emit_simulator_gcode_control_action(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) {
return sink.switch_m_code_kinematics(action.m_code, action.value, line); sink.switch_kinematics(action.value, action.rtcp_enabled, 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;
} }

View File

@@ -13,18 +13,12 @@ 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);
bool parse_simulator_gcode_control_line(const std::string &line, void emit_simulator_gcode_control_action(CanonEventSink &sink,
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

View File

@@ -3,7 +3,6 @@
#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 {
@@ -13,38 +12,14 @@ 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;
@@ -61,11 +36,6 @@ 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_;
}; };

View File

@@ -1,6 +1,5 @@
#include "canon_event_sink.h" #include "canon_event_sink.h"
#include <cmath>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
@@ -26,18 +25,6 @@ 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() {
@@ -45,8 +32,6 @@ 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;
@@ -64,8 +49,6 @@ 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);
@@ -73,290 +56,6 @@ 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