From 232f42f45af235bca1f694293174669c1a50fe1b Mon Sep 17 00:00:00 2001 From: wangdequan Date: Sun, 7 Jun 2026 21:12:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=89=E6=8E=A8=E8=8D=90=E5=BB=BA=E8=AE=AE?= =?UTF-8?q?=EF=BC=8C=E7=BB=A7=E7=BB=AD=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 结论:已继续补齐 LinuxCNC 源码派生的 genhexkins 与 pentakins 原生 runtime baseline,构建、vendor 同步、语义守卫和 native probe 验证均通过。 --- wasm-port/docs/drift-report.md | 5 +- wasm-port/docs/source-reuse-map.md | 8 +- .../linuxcnc_genhex_kinematics_probe.cpp | 110 ++++++++++++++++++ .../linuxcnc_pentakins_kinematics_probe.cpp | 89 ++++++++++++++ .../tests/native/verify_native_probes.sh | 25 ++++ wasm-port/tools/build_native_probes.sh | 65 +++++++++++ 6 files changed, 296 insertions(+), 6 deletions(-) create mode 100644 wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_genhex_kinematics_probe.cpp create mode 100644 wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_pentakins_kinematics_probe.cpp diff --git a/wasm-port/docs/drift-report.md b/wasm-port/docs/drift-report.md index 32f7807..1df7b23 100644 --- a/wasm-port/docs/drift-report.md +++ b/wasm-port/docs/drift-report.md @@ -31,6 +31,7 @@ semantic rewrites: | Realtime scheduler | TP probes seed deterministic status/config data instead of running LinuxCNC realtime process topology. | | Kinematics component lifecycle | Kinematics modules are initialized through LinuxCNC module entry points where native runtime probes exist, while HAL component init/ready/exit, HAL pin allocation, and RTAPI module metadata are handled by standalone shims. | | Go math C/C++ linkage | `genserkins` runtime probing compiles vendored `gomath.c` through a narrow C++ wrapper so LinuxCNC `genserfuncs.c` can link to the upstream Go math symbols without editing vendored source. | +| Switchkins iterative forward | `genhexkins` runtime probing follows LinuxCNC switchkins iterative-forward behavior, including the first-call warmup path before asserting roundtrip convergence. | | Browser storage | OPFS remains outside the native core and is not yet connected. | ## Enforced Non-Drift Rules @@ -52,8 +53,8 @@ semantic rewrites: serial, hexapod, pentapod, and related kinematics sources now have native source-probe coverage. - Full machine baselines beyond the current identity/trivial, `5axiskins`, - TRT, delta, SCARA, PUMA, serial `genserkins`, and other existing runtime - probes are not established. + TRT, delta, SCARA, PUMA, serial `genserkins`, hexapod `genhexkins`, + pentapod `pentakins`, and other existing runtime probes are not established. - Fixture expectations are currently checked against the standalone vendored source path, not by running a native LinuxCNC binary for every fixture. diff --git a/wasm-port/docs/source-reuse-map.md b/wasm-port/docs/source-reuse-map.md index 8a0285d..374ab7c 100644 --- a/wasm-port/docs/source-reuse-map.md +++ b/wasm-port/docs/source-reuse-map.md @@ -38,7 +38,7 @@ Current validation is intentionally mechanical: | Identity/trivial kinematics | `src/emc/kinematics/kinematics.h`, `cubic.h`, `kins_util.c`, `trivkins.c` | Copy unchanged | HAL component lifecycle and RTAPI module metadata are replaced by standalone shims; forward/inverse mapping behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_kinematics_probe` | | Switchable 5-axis bridge kinematics | `src/emc/kinematics/5axiskins.c`, `switchkins.c`, `switchkins.h`, `userkfuncs.c`, plus `src/rtapi/rtapi_ctype.h` | Copy unchanged | HAL pin allocation, HAL component lifecycle, and RTAPI module metadata are standalone runtime edges; switchable 5-axis forward/inverse behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_5axis_kinematics_probe` | | TRT table-rotary kinematics | `src/emc/kinematics/trtfuncs.c`, `xyzac-trt-kins.c`, `xyzbc-trt-kins.c` | Copy unchanged | HAL pin allocation and switchkins lifecycle stay runtime boundaries; XYZAC/XYZBC TRT forward/inverse behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_xyzac_trt_kinematics_probe`, `linuxcnc_xyzbc_trt_kinematics_probe` | -| Additional non-switchable kinematics | `src/emc/kinematics/corexykins.c`, `rotatekins.c`, `rosekins.c`, `maxkins.c`, `lineardeltakins.c`, `lineardeltakins-common.h`, `rotarydeltakins.c`, `rotarydeltakins-common.h`, `scorbot-kins.c`, `tripodkins.c`, `scarakins.c`, `pumakins.c`, `pumakins.h`, `genhexkins.c`, `genhexkins.h`, `genserfuncs.c`, `genserkins.c`, `genserkins.h`, `ugenserkins.c`, `pentakins.c`, `pentakins.h`, `cubic.c` | Copy unchanged | HAL pin allocation, HAL parameter allocation, HAL component lifecycle, RTAPI module metadata, Go math C/C++ linkage, and userspace test-program process entry remain standalone runtime edges; forward/inverse behavior remains LinuxCNC source where the module exposes it | Vendor byte sync, per-file source probes, `linuxcnc_corexy_kinematics_probe`, `linuxcnc_rotate_kinematics_probe`, `linuxcnc_rose_kinematics_probe`, `linuxcnc_max_kinematics_probe`, `linuxcnc_lineardelta_kinematics_probe`, `linuxcnc_rotarydelta_kinematics_probe`, `linuxcnc_scorbot_kinematics_probe`, `linuxcnc_tripod_kinematics_probe`, `linuxcnc_scara_kinematics_probe`, `linuxcnc_puma_kinematics_probe`, `linuxcnc_genser_kinematics_probe` | +| Additional non-switchable kinematics | `src/emc/kinematics/corexykins.c`, `rotatekins.c`, `rosekins.c`, `maxkins.c`, `lineardeltakins.c`, `lineardeltakins-common.h`, `rotarydeltakins.c`, `rotarydeltakins-common.h`, `scorbot-kins.c`, `tripodkins.c`, `scarakins.c`, `pumakins.c`, `pumakins.h`, `genhexkins.c`, `genhexkins.h`, `genserfuncs.c`, `genserkins.c`, `genserkins.h`, `ugenserkins.c`, `pentakins.c`, `pentakins.h`, `cubic.c` | Copy unchanged | HAL pin allocation, HAL parameter allocation, HAL component lifecycle, RTAPI module metadata, Go math C/C++ linkage, switchkins iterative-forward warmup, and userspace test-program process entry remain standalone runtime edges; forward/inverse behavior remains LinuxCNC source where the module exposes it | Vendor byte sync, per-file source probes, `linuxcnc_corexy_kinematics_probe`, `linuxcnc_rotate_kinematics_probe`, `linuxcnc_rose_kinematics_probe`, `linuxcnc_max_kinematics_probe`, `linuxcnc_lineardelta_kinematics_probe`, `linuxcnc_rotarydelta_kinematics_probe`, `linuxcnc_scorbot_kinematics_probe`, `linuxcnc_tripod_kinematics_probe`, `linuxcnc_scara_kinematics_probe`, `linuxcnc_puma_kinematics_probe`, `linuxcnc_genser_kinematics_probe`, `linuxcnc_genhex_kinematics_probe`, `linuxcnc_pentakins_kinematics_probe` | | Trajectory planner | `src/emc/tp/tp.c`, `tc.c`, `tcq.c`, `spherical_arc.c`, `blendmath.c`, `sp_scurve.c`, `ruckig_wrapper.c`, plus matching `*.h` files | Copy unchanged | Native realtime scheduling and motion process state are replaced by standalone probe setup | Vendor byte sync, per-file source probes, `linuxcnc_tp_api_probe` | | Ruckig C planner support | Selected `src/emc/tp/cruckig/*.c` and `*.h` files in the manifest | Copy unchanged | Used as LinuxCNC planner support code through vendored TP sources | Vendor byte sync, per-file source probes | | Posemath | `src/libnml/posemath/posemath.cc`, `_posemath.c`, `gomath.c`, `sincos.c`, and matching headers | Copy unchanged | `gomath.c` is compiled as C; `rtapi.h` shim is C/C++ compatible for this boundary | Vendor byte sync, per-file source probes, TP probe | @@ -63,9 +63,9 @@ Current validation is intentionally mechanical: ## Known Gaps - Additional non-trivial kinematics implementation files are now extracted at - source-probe level. Serial `genserkins` has a native runtime baseline; full - runtime machine baselines for hexapod, pentapod, and userspace genser flows - are not yet established. + source-probe level. Serial `genserkins`, hexapod `genhexkins`, and pentapod + `pentakins` have native runtime baselines; full runtime machine baselines for + userspace genser flows are not yet established. - Browser/WASM C ABI and JS SDK layers are not yet built for the full interpreter/planner core. - OPFS persistence is not yet connected to INI, tool table, parameter file, or diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_genhex_kinematics_probe.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_genhex_kinematics_probe.cpp new file mode 100644 index 0000000..61a2e74 --- /dev/null +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_genhex_kinematics_probe.cpp @@ -0,0 +1,110 @@ +#include +#include + +#include "emc/kinematics/kinematics.h" +#include "emc/motion/emcmotcfg.h" + +int rtapi_app_main(void); +void rtapi_app_exit(void); + +namespace { + +int near(double actual, double expected) +{ + return std::fabs(actual - expected) < 1e-6; +} + +int near_pose(const EmcPose &actual, const EmcPose &expected) +{ + return near(actual.tran.x, expected.tran.x) && + near(actual.tran.y, expected.tran.y) && + near(actual.tran.z, expected.tran.z) && + near(actual.a, expected.a) && + near(actual.b, expected.b) && + near(actual.c, expected.c); +} + +int near_identity_pose(const EmcPose &actual, const double *joints) +{ + return near(actual.tran.x, joints[0]) && + near(actual.tran.y, joints[1]) && + near(actual.tran.z, joints[2]) && + near(actual.a, joints[3]) && + near(actual.b, joints[4]) && + near(actual.c, joints[5]); +} + +void print_pose(const char *prefix, const EmcPose &pose) +{ + std::cout << prefix << "_xyz=" + << pose.tran.x << "," + << pose.tran.y << "," + << pose.tran.z << "\n"; + std::cout << prefix << "_abc=" + << pose.a << "," + << pose.b << "," + << pose.c << "\n"; +} + +void print_joints(const char *prefix, const double *joints) +{ + std::cout << prefix << "_struts=" + << joints[0] << "," + << joints[1] << "," + << joints[2] << "," + << joints[3] << "," + << joints[4] << "," + << joints[5] << "\n"; +} + +} // namespace + +int main() +{ + const int init_rc = rtapi_app_main(); + std::cout << "genhex_init=" << init_rc << "\n"; + std::cout << "genhex_type=" << kinematicsType() << "\n"; + std::cout << "genhex_switchable=" << kinematicsSwitchable() << "\n"; + + EmcPose pose{}; + pose.tran.x = 1.25; + pose.tran.y = -2.5; + pose.tran.z = 3.75; + pose.a = 1.0; + pose.b = -2.0; + pose.c = 3.0; + + KINEMATICS_FORWARD_FLAGS fflags = 0; + KINEMATICS_INVERSE_FLAGS iflags = 0; + double inverse_joints[EMCMOT_MAX_JOINTS]{}; + const int inverse_rc = kinematicsInverse(&pose, inverse_joints, &iflags, &fflags); + std::cout << "genhex_inverse=" << inverse_rc << "\n"; + print_joints("genhex_inverse", inverse_joints); + + EmcPose warmup_pose = pose; + const int warmup_rc = kinematicsForward(inverse_joints, &warmup_pose, &fflags, &iflags); + std::cout << "genhex_forward_warmup=" << warmup_rc << "\n"; + + EmcPose forward_pose = pose; + const int forward_rc = kinematicsForward(inverse_joints, &forward_pose, &fflags, &iflags); + std::cout << "genhex_forward=" << forward_rc << "\n"; + print_pose("genhex_forward", forward_pose); + std::cout << "genhex_roundtrip_pose=" << near_pose(forward_pose, pose) << "\n"; + + const int switch_rc = kinematicsSwitch(1); + std::cout << "genhex_switch_identity=" << switch_rc << "\n"; + double identity_joints[EMCMOT_MAX_JOINTS]{}; + for (int index = 0; index < 6; ++index) { + identity_joints[index] = inverse_joints[index]; + } + EmcPose identity_pose{}; + const int identity_forward_rc = kinematicsForward( + identity_joints, &identity_pose, &fflags, &iflags); + std::cout << "genhex_identity_forward=" << identity_forward_rc << "\n"; + print_pose("genhex_identity", identity_pose); + std::cout << "genhex_identity_near=" + << near_identity_pose(identity_pose, identity_joints) << "\n"; + + rtapi_app_exit(); + return 0; +} diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_pentakins_kinematics_probe.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_pentakins_kinematics_probe.cpp new file mode 100644 index 0000000..f47465b --- /dev/null +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_pentakins_kinematics_probe.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include "emc/kinematics/kinematics.h" +#include "emc/motion/emcmotcfg.h" + +int rtapi_app_main(void); +void rtapi_app_exit(void); + +namespace { + +int near(double actual, double expected) +{ + return std::fabs(actual - expected) < 1e-6; +} + +int near_pose(const EmcPose &actual, const EmcPose &expected) +{ + return near(actual.tran.x, expected.tran.x) && + near(actual.tran.y, expected.tran.y) && + near(actual.tran.z, expected.tran.z) && + near(actual.a, expected.a) && + near(actual.b, expected.b); +} + +int positive_struts(const double *joints) +{ + for (int index = 0; index < 5; ++index) { + if (joints[index] <= 0.0) { + return 0; + } + } + return 1; +} + +void print_pose(const char *prefix, const EmcPose &pose) +{ + std::cout << prefix << "_xyz=" + << pose.tran.x << "," + << pose.tran.y << "," + << pose.tran.z << "\n"; + std::cout << prefix << "_ab=" + << pose.a << "," + << pose.b << "\n"; +} + +void print_joints(const char *prefix, const double *joints) +{ + std::cout << prefix << "_struts=" + << joints[0] << "," + << joints[1] << "," + << joints[2] << "," + << joints[3] << "," + << joints[4] << "\n"; +} + +} // namespace + +int main() +{ + const int init_rc = rtapi_app_main(); + std::cout << "pentakins_init=" << init_rc << "\n"; + std::cout << "pentakins_type=" << kinematicsType() << "\n"; + std::cout << "pentakins_switchable=" << kinematicsSwitchable() << "\n"; + + EmcPose pose{}; + pose.tran.x = 12.5; + pose.tran.y = -8.25; + pose.tran.z = 25.0; + pose.a = 2.0; + pose.b = -1.5; + + KINEMATICS_FORWARD_FLAGS fflags = 0; + KINEMATICS_INVERSE_FLAGS iflags = 0; + double inverse_joints[EMCMOT_MAX_JOINTS]{}; + const int inverse_rc = kinematicsInverse(&pose, inverse_joints, &iflags, &fflags); + std::cout << "pentakins_inverse=" << inverse_rc << "\n"; + print_joints("pentakins_inverse", inverse_joints); + std::cout << "pentakins_positive_struts=" << positive_struts(inverse_joints) << "\n"; + + EmcPose forward_pose = pose; + const int forward_rc = kinematicsForward(inverse_joints, &forward_pose, &fflags, &iflags); + std::cout << "pentakins_forward=" << forward_rc << "\n"; + print_pose("pentakins_forward", forward_pose); + std::cout << "pentakins_roundtrip_pose=" << near_pose(forward_pose, pose) << "\n"; + + rtapi_app_exit(); + return 0; +} diff --git a/wasm-port/tests/native/verify_native_probes.sh b/wasm-port/tests/native/verify_native_probes.sh index 90a2faf..a4f946f 100755 --- a/wasm-port/tests/native/verify_native_probes.sh +++ b/wasm-port/tests/native/verify_native_probes.sh @@ -109,6 +109,10 @@ check_exitcode linuxcnc_puma_kinematics_probe check_exitcode linuxcnc_puma_kinematics_probe.run check_exitcode linuxcnc_genser_kinematics_probe check_exitcode linuxcnc_genser_kinematics_probe.run +check_exitcode linuxcnc_genhex_kinematics_probe +check_exitcode linuxcnc_genhex_kinematics_probe.run +check_exitcode linuxcnc_pentakins_kinematics_probe +check_exitcode linuxcnc_pentakins_kinematics_probe.run for name in \ linuxcnc_tp_tp_source_probe \ linuxcnc_tp_tc_source_probe \ @@ -407,6 +411,27 @@ grep -Fq "genser_switch_identity=0" "$GENSER_KINEMATICS_STDOUT" grep -Fq "genser_identity_forward=0" "$GENSER_KINEMATICS_STDOUT" grep -Fq "genser_identity_near=1" "$GENSER_KINEMATICS_STDOUT" +GENHEX_KINEMATICS_STDOUT="$BUILD_DIR/linuxcnc_genhex_kinematics_probe.run.stdout.log" +grep -Fq "genhex_init=0" "$GENHEX_KINEMATICS_STDOUT" +grep -Fq "genhex_type=4" "$GENHEX_KINEMATICS_STDOUT" +grep -Fq "genhex_switchable=1" "$GENHEX_KINEMATICS_STDOUT" +grep -Fq "genhex_inverse=0" "$GENHEX_KINEMATICS_STDOUT" +grep -Fq "genhex_forward_warmup=-1" "$GENHEX_KINEMATICS_STDOUT" +grep -Fq "genhex_forward=0" "$GENHEX_KINEMATICS_STDOUT" +grep -Fq "genhex_roundtrip_pose=1" "$GENHEX_KINEMATICS_STDOUT" +grep -Fq "genhex_switch_identity=0" "$GENHEX_KINEMATICS_STDOUT" +grep -Fq "genhex_identity_forward=0" "$GENHEX_KINEMATICS_STDOUT" +grep -Fq "genhex_identity_near=1" "$GENHEX_KINEMATICS_STDOUT" + +PENTAKINS_KINEMATICS_STDOUT="$BUILD_DIR/linuxcnc_pentakins_kinematics_probe.run.stdout.log" +grep -Fq "pentakins_init=0" "$PENTAKINS_KINEMATICS_STDOUT" +grep -Fq "pentakins_type=4" "$PENTAKINS_KINEMATICS_STDOUT" +grep -Fq "pentakins_switchable=0" "$PENTAKINS_KINEMATICS_STDOUT" +grep -Fq "pentakins_inverse=0" "$PENTAKINS_KINEMATICS_STDOUT" +grep -Fq "pentakins_positive_struts=1" "$PENTAKINS_KINEMATICS_STDOUT" +grep -Fq "pentakins_forward=0" "$PENTAKINS_KINEMATICS_STDOUT" +grep -Fq "pentakins_roundtrip_pose=1" "$PENTAKINS_KINEMATICS_STDOUT" + check_fixture_output() { local fixture="$1" local expected="$2" diff --git a/wasm-port/tools/build_native_probes.sh b/wasm-port/tools/build_native_probes.sh index 707d4b5..1d98f2d 100755 --- a/wasm-port/tools/build_native_probes.sh +++ b/wasm-port/tools/build_native_probes.sh @@ -463,6 +463,27 @@ GENSER_KINEMATICS_PROBE_SOURCES=( "$WRAP_DIR/linuxcnc_genser_kinematics_probe.cpp" ) +GENHEX_KINEMATICS_PROBE_SOURCES=( + "$VENDOR_DIR/src/emc/kinematics/kins_util.c" + "$VENDOR_DIR/src/emc/kinematics/switchkins.c" + "$VENDOR_DIR/src/emc/kinematics/userkfuncs.c" + "$VENDOR_DIR/src/emc/kinematics/genhexkins.c" + "$VENDOR_DIR/src/libnml/posemath/posemath.cc" + "$VENDOR_DIR/src/libnml/posemath/_posemath.c" + "$VENDOR_DIR/src/libnml/posemath/sincos.c" + "$WRAP_DIR/linuxcnc_hal_adapter.cpp" + "$WRAP_DIR/linuxcnc_genhex_kinematics_probe.cpp" +) + +PENTAKINS_KINEMATICS_PROBE_SOURCES=( + "$VENDOR_DIR/src/emc/kinematics/pentakins.c" + "$VENDOR_DIR/src/libnml/posemath/posemath.cc" + "$VENDOR_DIR/src/libnml/posemath/_posemath.c" + "$VENDOR_DIR/src/libnml/posemath/sincos.c" + "$WRAP_DIR/linuxcnc_hal_adapter.cpp" + "$WRAP_DIR/linuxcnc_pentakins_kinematics_probe.cpp" +) + TP_CORE_SOURCES=( "$VENDOR_DIR/src/emc/tp/tp.c" "$VENDOR_DIR/src/emc/tp/tc.c" @@ -741,6 +762,20 @@ build_binary_target \ GENSER_KINEMATICS_PROBE_SOURCES \ NO_LINK_FLAGS +build_binary_target \ + linuxcnc_genhex_kinematics_probe \ + "$BUILD_DIR/linuxcnc_genhex_kinematics_probe" \ + TP_FLAGS \ + GENHEX_KINEMATICS_PROBE_SOURCES \ + NO_LINK_FLAGS + +build_binary_target \ + linuxcnc_pentakins_kinematics_probe \ + "$BUILD_DIR/linuxcnc_pentakins_kinematics_probe" \ + TP_FLAGS \ + PENTAKINS_KINEMATICS_PROBE_SOURCES \ + NO_LINK_FLAGS + if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_kinematics_probe.exitcode")" == "0" ]]; then set +e "$BUILD_DIR/linuxcnc_kinematics_probe" \ @@ -966,6 +1001,36 @@ else "$BUILD_DIR/linuxcnc_genser_kinematics_probe.run.stderr.log" fi +if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_genhex_kinematics_probe.exitcode")" == "0" ]]; then + set +e + "$BUILD_DIR/linuxcnc_genhex_kinematics_probe" \ + >"$BUILD_DIR/linuxcnc_genhex_kinematics_probe.run.stdout.log" \ + 2>"$BUILD_DIR/linuxcnc_genhex_kinematics_probe.run.stderr.log" + GENHEX_KINEMATICS_RUN_RC=$? + set -e + echo "$GENHEX_KINEMATICS_RUN_RC" > "$BUILD_DIR/linuxcnc_genhex_kinematics_probe.run.exitcode" +else + rm -f \ + "$BUILD_DIR/linuxcnc_genhex_kinematics_probe.run.exitcode" \ + "$BUILD_DIR/linuxcnc_genhex_kinematics_probe.run.stdout.log" \ + "$BUILD_DIR/linuxcnc_genhex_kinematics_probe.run.stderr.log" +fi + +if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_pentakins_kinematics_probe.exitcode")" == "0" ]]; then + set +e + "$BUILD_DIR/linuxcnc_pentakins_kinematics_probe" \ + >"$BUILD_DIR/linuxcnc_pentakins_kinematics_probe.run.stdout.log" \ + 2>"$BUILD_DIR/linuxcnc_pentakins_kinematics_probe.run.stderr.log" + PENTAKINS_KINEMATICS_RUN_RC=$? + set -e + echo "$PENTAKINS_KINEMATICS_RUN_RC" > "$BUILD_DIR/linuxcnc_pentakins_kinematics_probe.run.exitcode" +else + rm -f \ + "$BUILD_DIR/linuxcnc_pentakins_kinematics_probe.run.exitcode" \ + "$BUILD_DIR/linuxcnc_pentakins_kinematics_probe.run.stdout.log" \ + "$BUILD_DIR/linuxcnc_pentakins_kinematics_probe.run.stderr.log" +fi + if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_tp_api_probe.exitcode")" == "0" ]]; then set +e "$BUILD_DIR/linuxcnc_tp_api_probe" \