From 1b2f95b3d1aaf5159455a1dbbbe8c7ea633b4045 Mon Sep 17 00:00:00 2001 From: wangdequan Date: Sun, 7 Jun 2026 19:08:40 +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 5axiskins 及 switchkins 相关源码纳入 vendored manifest、native probe 和文档验证链,完整 native 验证通过。 --- wasm-port/docs/compatibility-validation.md | 7 +- wasm-port/docs/drift-report.md | 11 +- wasm-port/docs/scope-and-baseline.md | 5 +- wasm-port/docs/source-reuse-map.md | 5 +- .../linuxcnc_5axis_kinematics_probe.cpp | 108 ++++++ .../linuxcnc_wrap/linuxcnc_hal_adapter.cpp | 154 ++++++++ wasm-port/runtime/core/shims/hal.h | 22 ++ .../tests/native/verify_native_probes.sh | 16 + wasm-port/tools/build_native_probes.sh | 49 +++ wasm-port/tools/source-manifest.txt | 5 + .../linuxcnc/src/emc/kinematics/5axiskins.c | 272 ++++++++++++++ .../linuxcnc/src/emc/kinematics/switchkins.c | 342 ++++++++++++++++++ .../linuxcnc/src/emc/kinematics/switchkins.h | 36 ++ .../linuxcnc/src/emc/kinematics/userkfuncs.c | 83 +++++ .../vendor/linuxcnc/src/rtapi/rtapi_ctype.h | 24 ++ 15 files changed, 1129 insertions(+), 10 deletions(-) create mode 100644 wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_5axis_kinematics_probe.cpp create mode 100644 wasm-port/vendor/linuxcnc/src/emc/kinematics/5axiskins.c create mode 100644 wasm-port/vendor/linuxcnc/src/emc/kinematics/switchkins.c create mode 100644 wasm-port/vendor/linuxcnc/src/emc/kinematics/switchkins.h create mode 100644 wasm-port/vendor/linuxcnc/src/emc/kinematics/userkfuncs.c create mode 100644 wasm-port/vendor/linuxcnc/src/rtapi/rtapi_ctype.h diff --git a/wasm-port/docs/compatibility-validation.md b/wasm-port/docs/compatibility-validation.md index 407355d..3d99cbf 100644 --- a/wasm-port/docs/compatibility-validation.md +++ b/wasm-port/docs/compatibility-validation.md @@ -53,6 +53,7 @@ The validation fails if: | `linuxcnc_parameter_file_harness` | Validates LinuxCNC parameter file restore/save behavior and required/read-only parameter handling. | | `linuxcnc_tp_api_probe` | Validates vendored LinuxCNC trajectory planner calls for linear, arc, and queued motion paths. | | `linuxcnc_kinematics_probe` | Validates vendored LinuxCNC `trivkins.c` plus `kins_util.c` initialize and perform identity forward/inverse mapping through the standalone HAL/RTAPI boundary. | +| `linuxcnc_5axis_kinematics_probe` | Validates vendored LinuxCNC `5axiskins.c` through `switchkins.c`, including 5-axis forward/inverse round-trip behavior and switching to identity kinematics. | ## Fixture Coverage @@ -95,5 +96,7 @@ The current fixture expectations validate standalone behavior against the vendored LinuxCNC source path. They do not yet run a side-by-side native LinuxCNC executable comparison for each fixture. -The kinematics probe currently covers LinuxCNC identity/trivial kinematics -only. Non-trivial and 5-axis kinematics still need dedicated machine baselines. +The kinematics probes currently cover LinuxCNC identity/trivial kinematics and +the switchable `5axiskins` XYZBCW bridge-mill model. TRT `xyzac`/`xyzbc`, +serial, delta, SCARA, and other machine-specific kinematics still need +dedicated baselines. diff --git a/wasm-port/docs/drift-report.md b/wasm-port/docs/drift-report.md index 6d4a743..5f4a67b 100644 --- a/wasm-port/docs/drift-report.md +++ b/wasm-port/docs/drift-report.md @@ -29,7 +29,7 @@ semantic rewrites: | Python/remap | Python/remap hooks are stubbed at the runtime edge. | | Dynamic interpreter path | `interp_base.cc` probe uses standalone `EMC2_HOME` compile-time path boundary. | | Realtime scheduler | TP probes seed deterministic status/config data instead of running LinuxCNC realtime process topology. | -| Kinematics component lifecycle | `trivkins.c` is initialized through its LinuxCNC module entry point while HAL component init/ready/exit and RTAPI module metadata are handled by standalone shims. | +| Kinematics component lifecycle | `trivkins.c` and `5axiskins.c` are initialized through LinuxCNC module entry points while HAL component init/ready/exit, HAL pin allocation, and RTAPI module metadata are handled by standalone shims. | | Browser storage | OPFS remains outside the native core and is not yet connected. | ## Enforced Non-Drift Rules @@ -47,10 +47,11 @@ semantic rewrites: - No browser/WASM parity tests yet. - No JS SDK validation yet. - No OPFS persistence validation yet. -- Identity/trivial kinematics now have native source-probe coverage; non-trivial - and 5-axis kinematics implementation files are not yet extracted. -- Full machine baselines beyond the identity/trivial kinematics probe are not - established. +- Identity/trivial kinematics and LinuxCNC `5axiskins` now have native + source-probe coverage; TRT `xyzac`/`xyzbc`, serial, delta, SCARA, and other + machine-specific kinematics are not yet extracted. +- Full machine baselines beyond the current identity/trivial and `5axiskins` + 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/scope-and-baseline.md b/wasm-port/docs/scope-and-baseline.md index cc5afb7..a5882c6 100644 --- a/wasm-port/docs/scope-and-baseline.md +++ b/wasm-port/docs/scope-and-baseline.md @@ -60,5 +60,6 @@ Negative fixture coverage includes: - missing tool length offset Machine baseline is still limited to standalone interpreter, trajectory -planner, and LinuxCNC identity/trivial kinematics probes. Non-trivial -kinematics and 5-axis machine baselines remain future work. +planner, LinuxCNC identity/trivial kinematics, and the LinuxCNC `5axiskins` +XYZBCW bridge-mill probe. Additional non-trivial kinematics and fuller machine +baselines remain future work. diff --git a/wasm-port/docs/source-reuse-map.md b/wasm-port/docs/source-reuse-map.md index 1a9c5f3..e17de1d 100644 --- a/wasm-port/docs/source-reuse-map.md +++ b/wasm-port/docs/source-reuse-map.md @@ -36,6 +36,7 @@ Current validation is intentionally mechanical: | Canon/NML-facing interpreter types | `src/emc/nml_intf/canon*.hh`, `emctool.h`, `interp_return.hh`, `motion_types.h`, `emcpose.*`, `emcpos.h`, `debugflags.h`, `src/emc/linuxcnc.h` | Copy unchanged | NML transport is not ported; wrappers provide only the status/type edges needed by standalone probes | Vendor byte sync, dependent source probes, `linuxcnc_tp_api_probe`, interpreter harnesses | | Motion state headers | `src/emc/motion/state_tag.h`, `emcmotcfg.h`, `simple_tp.h`, `motion.h`, `mot_priv.h`, `axis.h` | Copy unchanged | Realtime motion process is not ported; standalone probes seed the small motion status/config state required by TP calls | Vendor byte sync, `linuxcnc_tp_api_probe` | | 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` | | 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 | @@ -59,7 +60,9 @@ Current validation is intentionally mechanical: ## Known Gaps -- Full non-trivial and 5-axis kinematics implementation files are not yet extracted. +- Additional non-trivial kinematics implementation files, including TRT + `xyzac`/`xyzbc`, serial, delta, SCARA, and other machine-specific modules, + are not yet extracted. - 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_5axis_kinematics_probe.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_5axis_kinematics_probe.cpp new file mode 100644 index 0000000..a13fe73 --- /dev/null +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_5axis_kinematics_probe.cpp @@ -0,0 +1,108 @@ +#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-9; +} + +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.b, expected.b) && + near(actual.c, expected.c) && + near(actual.w, expected.w); +} + +int near_joints(const double *actual, const double *expected) +{ + for (int index = 0; index < 6; ++index) { + if (!near(actual[index], expected[index])) { + 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 << "_bcw=" + << pose.b << "," + << pose.c << "," + << pose.w << "\n"; +} + +void print_joints(const char *prefix, const double *joints) +{ + std::cout << prefix << "_xyzbcw=" + << 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 << "fiveaxis_init=" << init_rc << "\n"; + std::cout << "fiveaxis_type=" << kinematicsType() << "\n"; + std::cout << "fiveaxis_switchable=" << kinematicsSwitchable() << "\n"; + + double joints[EMCMOT_MAX_JOINTS]{}; + joints[0] = 10.0; + joints[1] = 20.0; + joints[2] = 30.0; + joints[3] = 45.0; + joints[4] = 30.0; + joints[5] = 5.0; + + KINEMATICS_FORWARD_FLAGS fflags = 0; + KINEMATICS_INVERSE_FLAGS iflags = 0; + EmcPose forward_pose{}; + const int forward_rc = kinematicsForward(joints, &forward_pose, &fflags, &iflags); + std::cout << "fiveaxis_forward=" << forward_rc << "\n"; + print_pose("fiveaxis_forward", forward_pose); + + double inverse_joints[EMCMOT_MAX_JOINTS]{}; + const int inverse_rc = kinematicsInverse(&forward_pose, inverse_joints, &iflags, &fflags); + std::cout << "fiveaxis_inverse=" << inverse_rc << "\n"; + print_joints("fiveaxis_inverse", inverse_joints); + std::cout << "fiveaxis_roundtrip_joints=" << near_joints(inverse_joints, joints) << "\n"; + + const int switch_rc = kinematicsSwitch(1); + std::cout << "fiveaxis_switch_identity=" << switch_rc << "\n"; + EmcPose identity_pose{}; + const int identity_forward_rc = kinematicsForward(joints, &identity_pose, &fflags, &iflags); + std::cout << "fiveaxis_identity_forward=" << identity_forward_rc << "\n"; + print_pose("fiveaxis_identity", identity_pose); + + EmcPose expected_identity{}; + expected_identity.tran.x = joints[0]; + expected_identity.tran.y = joints[1]; + expected_identity.tran.z = joints[2]; + expected_identity.b = joints[3]; + expected_identity.c = joints[4]; + expected_identity.w = joints[5]; + std::cout << "fiveaxis_identity_near=" << near_pose(identity_pose, expected_identity) << "\n"; + + rtapi_app_exit(); + return 0; +} diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_hal_adapter.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_hal_adapter.cpp index 70af334..3875bd9 100644 --- a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_hal_adapter.cpp +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_hal_adapter.cpp @@ -1,7 +1,11 @@ #include "linuxcnc_hal_adapter.hh" +#include +#include +#include #include #include +#include namespace { @@ -29,6 +33,12 @@ std::unordered_map ¶ms() return values; } +std::vector &hal_allocations() +{ + static std::vector values; + return values; +} + std::unordered_map &values_for(standalone::HalValueKind kind) { switch (kind) { @@ -96,6 +106,150 @@ int hal_exit(int) return 0; } +void *hal_malloc(long int size) +{ + if (size <= 0) { + return nullptr; + } + void *ptr = ::operator new(static_cast(size), std::nothrow); + if (ptr) { + hal_allocations().push_back(ptr); + } + return ptr; +} + +int hal_pin_bit_new(const char *, hal_pin_dir_t, hal_bit_t **data_ptr_addr, int) +{ + if (!data_ptr_addr) { + return -1; + } + *data_ptr_addr = new hal_bit_t{}; + return 0; +} + +int hal_pin_float_new(const char *, hal_pin_dir_t, hal_float_t **data_ptr_addr, int) +{ + if (!data_ptr_addr) { + return -1; + } + *data_ptr_addr = new hal_float_t{}; + return 0; +} + +int hal_pin_u32_new(const char *, hal_pin_dir_t, hal_u32_t **data_ptr_addr, int) +{ + if (!data_ptr_addr) { + return -1; + } + *data_ptr_addr = new hal_u32_t{}; + return 0; +} + +int hal_pin_s32_new(const char *, hal_pin_dir_t, hal_s32_t **data_ptr_addr, int) +{ + if (!data_ptr_addr) { + return -1; + } + *data_ptr_addr = new hal_s32_t{}; + return 0; +} + +int hal_pin_u64_new(const char *, hal_pin_dir_t, hal_u64_t **data_ptr_addr, int) +{ + if (!data_ptr_addr) { + return -1; + } + *data_ptr_addr = new hal_u64_t{}; + return 0; +} + +int hal_pin_s64_new(const char *, hal_pin_dir_t, hal_s64_t **data_ptr_addr, int) +{ + if (!data_ptr_addr) { + return -1; + } + *data_ptr_addr = new hal_s64_t{}; + return 0; +} + +template +int hal_pin_newf_impl(hal_pin_dir_t dir, T **data_ptr_addr, int comp_id, const char *fmt, + va_list ap) +{ + if (!fmt) { + return -1; + } + char name[HAL_NAME_LEN * 2]{}; + vsnprintf(name, sizeof(name), fmt, ap); + return Create(name, dir, data_ptr_addr, comp_id); +} + +int hal_pin_bit_newf(hal_pin_dir_t dir, hal_bit_t **data_ptr_addr, int comp_id, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + const int rc = hal_pin_newf_impl( + dir, data_ptr_addr, comp_id, fmt, ap); + va_end(ap); + return rc; +} + +int hal_pin_float_newf(hal_pin_dir_t dir, hal_float_t **data_ptr_addr, int comp_id, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + const int rc = hal_pin_newf_impl( + dir, data_ptr_addr, comp_id, fmt, ap); + va_end(ap); + return rc; +} + +int hal_pin_u32_newf(hal_pin_dir_t dir, hal_u32_t **data_ptr_addr, int comp_id, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + const int rc = hal_pin_newf_impl( + dir, data_ptr_addr, comp_id, fmt, ap); + va_end(ap); + return rc; +} + +int hal_pin_s32_newf(hal_pin_dir_t dir, hal_s32_t **data_ptr_addr, int comp_id, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + const int rc = hal_pin_newf_impl( + dir, data_ptr_addr, comp_id, fmt, ap); + va_end(ap); + return rc; +} + +int hal_pin_u64_newf(hal_pin_dir_t dir, hal_u64_t **data_ptr_addr, int comp_id, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + const int rc = hal_pin_newf_impl( + dir, data_ptr_addr, comp_id, fmt, ap); + va_end(ap); + return rc; +} + +int hal_pin_s64_newf(hal_pin_dir_t dir, hal_s64_t **data_ptr_addr, int comp_id, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + const int rc = hal_pin_newf_impl( + dir, data_ptr_addr, comp_id, fmt, ap); + va_end(ap); + return rc; +} + int hal_get_pin_value_by_name(const char *name, hal_type_t *type, hal_data_u **ptr, bool *connected) { diff --git a/wasm-port/runtime/core/shims/hal.h b/wasm-port/runtime/core/shims/hal.h index 110e4e2..8a62dcd 100644 --- a/wasm-port/runtime/core/shims/hal.h +++ b/wasm-port/runtime/core/shims/hal.h @@ -2,6 +2,8 @@ #include +#include "rtapi.h" + #define HAL_NAME_LEN 64 typedef enum { @@ -14,6 +16,13 @@ typedef enum { HAL_U64 } hal_type_t; +typedef enum { + HAL_DIR_UNSPECIFIED = -1, + HAL_IN = 16, + HAL_OUT = 32, + HAL_IO = (HAL_IN | HAL_OUT), +} hal_pin_dir_t; + typedef union { bool b; double f; @@ -33,6 +42,19 @@ typedef unsigned long long hal_u64_t; int hal_init(const char *); int hal_ready(int); int hal_exit(int); +void *hal_malloc(long int); +int hal_pin_bit_new(const char *, hal_pin_dir_t, hal_bit_t **, int); +int hal_pin_float_new(const char *, hal_pin_dir_t, hal_float_t **, int); +int hal_pin_u32_new(const char *, hal_pin_dir_t, hal_u32_t **, int); +int hal_pin_s32_new(const char *, hal_pin_dir_t, hal_s32_t **, int); +int hal_pin_u64_new(const char *, hal_pin_dir_t, hal_u64_t **, int); +int hal_pin_s64_new(const char *, hal_pin_dir_t, hal_s64_t **, int); +int hal_pin_bit_newf(hal_pin_dir_t, hal_bit_t **, int, const char *, ...); +int hal_pin_float_newf(hal_pin_dir_t, hal_float_t **, int, const char *, ...); +int hal_pin_u32_newf(hal_pin_dir_t, hal_u32_t **, int, const char *, ...); +int hal_pin_s32_newf(hal_pin_dir_t, hal_s32_t **, int, const char *, ...); +int hal_pin_u64_newf(hal_pin_dir_t, hal_u64_t **, int, const char *, ...); +int hal_pin_s64_newf(hal_pin_dir_t, hal_s64_t **, int, const char *, ...); int hal_get_pin_value_by_name(const char *, hal_type_t *, hal_data_u **, bool *); int hal_get_signal_value_by_name(const char *, hal_type_t *, hal_data_u **, bool *); int hal_get_param_value_by_name(const char *, hal_type_t *, hal_data_u **); diff --git a/wasm-port/tests/native/verify_native_probes.sh b/wasm-port/tests/native/verify_native_probes.sh index 9028b85..db86bfe 100755 --- a/wasm-port/tests/native/verify_native_probes.sh +++ b/wasm-port/tests/native/verify_native_probes.sh @@ -81,6 +81,8 @@ check_exitcode linuxcnc_tp_api_probe check_exitcode linuxcnc_tp_api_probe.run check_exitcode linuxcnc_kinematics_probe check_exitcode linuxcnc_kinematics_probe.run +check_exitcode linuxcnc_5axis_kinematics_probe +check_exitcode linuxcnc_5axis_kinematics_probe.run for name in \ linuxcnc_tp_tp_source_probe \ linuxcnc_tp_tc_source_probe \ @@ -123,6 +125,9 @@ check_exitcode linuxcnc_parameter_file_harness.run check_exitcode linuxcnc_rs274_compile_probe check_exitcode linuxcnc_kins_util_source_probe check_exitcode linuxcnc_trivkins_source_probe +check_exitcode linuxcnc_switchkins_source_probe +check_exitcode linuxcnc_userkfuncs_source_probe +check_exitcode linuxcnc_5axiskins_source_probe check_exitcode linuxcnc_interp_convert_source_probe check_exitcode linuxcnc_interp_read_source_probe check_exitcode linuxcnc_interp_check_source_probe @@ -218,6 +223,17 @@ grep -Fq "kinematics_inverse=0" "$KINEMATICS_STDOUT" grep -Fq "kinematics_inverse_xyz=10,20,30" "$KINEMATICS_STDOUT" grep -Fq "kinematics_inverse_abcuvw=40,50,60,70,80,90" "$KINEMATICS_STDOUT" +FIVEAXIS_KINEMATICS_STDOUT="$BUILD_DIR/linuxcnc_5axis_kinematics_probe.run.stdout.log" +grep -Fq "fiveaxis_init=0" "$FIVEAXIS_KINEMATICS_STDOUT" +grep -Fq "fiveaxis_type=4" "$FIVEAXIS_KINEMATICS_STDOUT" +grep -Fq "fiveaxis_switchable=1" "$FIVEAXIS_KINEMATICS_STDOUT" +grep -Fq "fiveaxis_forward=0" "$FIVEAXIS_KINEMATICS_STDOUT" +grep -Fq "fiveaxis_inverse=0" "$FIVEAXIS_KINEMATICS_STDOUT" +grep -Fq "fiveaxis_roundtrip_joints=1" "$FIVEAXIS_KINEMATICS_STDOUT" +grep -Fq "fiveaxis_switch_identity=0" "$FIVEAXIS_KINEMATICS_STDOUT" +grep -Fq "fiveaxis_identity_forward=0" "$FIVEAXIS_KINEMATICS_STDOUT" +grep -Fq "fiveaxis_identity_near=1" "$FIVEAXIS_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 34dc52b..0095d77 100755 --- a/wasm-port/tools/build_native_probes.sh +++ b/wasm-port/tools/build_native_probes.sh @@ -353,6 +353,15 @@ KINEMATICS_PROBE_SOURCES=( "$WRAP_DIR/linuxcnc_kinematics_probe.cpp" ) +FIVEAXIS_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/5axiskins.c" + "$WRAP_DIR/linuxcnc_hal_adapter.cpp" + "$WRAP_DIR/linuxcnc_5axis_kinematics_probe.cpp" +) + TP_CORE_SOURCES=( "$VENDOR_DIR/src/emc/tp/tp.c" "$VENDOR_DIR/src/emc/tp/tc.c" @@ -533,6 +542,13 @@ build_binary_target \ KINEMATICS_PROBE_SOURCES \ NO_LINK_FLAGS +build_binary_target \ + linuxcnc_5axis_kinematics_probe \ + "$BUILD_DIR/linuxcnc_5axis_kinematics_probe" \ + TP_FLAGS \ + FIVEAXIS_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" \ @@ -548,6 +564,21 @@ else "$BUILD_DIR/linuxcnc_kinematics_probe.run.stderr.log" fi +if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_5axis_kinematics_probe.exitcode")" == "0" ]]; then + set +e + "$BUILD_DIR/linuxcnc_5axis_kinematics_probe" \ + >"$BUILD_DIR/linuxcnc_5axis_kinematics_probe.run.stdout.log" \ + 2>"$BUILD_DIR/linuxcnc_5axis_kinematics_probe.run.stderr.log" + FIVEAXIS_KINEMATICS_RUN_RC=$? + set -e + echo "$FIVEAXIS_KINEMATICS_RUN_RC" > "$BUILD_DIR/linuxcnc_5axis_kinematics_probe.run.exitcode" +else + rm -f \ + "$BUILD_DIR/linuxcnc_5axis_kinematics_probe.run.exitcode" \ + "$BUILD_DIR/linuxcnc_5axis_kinematics_probe.run.stdout.log" \ + "$BUILD_DIR/linuxcnc_5axis_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" \ @@ -658,6 +689,24 @@ build_object_target \ "$VENDOR_DIR/src/emc/kinematics/trivkins.c" \ TP_FLAGS +build_object_target \ + linuxcnc_switchkins_source_probe \ + "$BUILD_DIR/linuxcnc_switchkins_source_probe.o" \ + "$VENDOR_DIR/src/emc/kinematics/switchkins.c" \ + TP_FLAGS + +build_object_target \ + linuxcnc_userkfuncs_source_probe \ + "$BUILD_DIR/linuxcnc_userkfuncs_source_probe.o" \ + "$VENDOR_DIR/src/emc/kinematics/userkfuncs.c" \ + TP_FLAGS + +build_object_target \ + linuxcnc_5axiskins_source_probe \ + "$BUILD_DIR/linuxcnc_5axiskins_source_probe.o" \ + "$VENDOR_DIR/src/emc/kinematics/5axiskins.c" \ + TP_FLAGS + build_object_target \ linuxcnc_interp_convert_source_probe \ "$BUILD_DIR/linuxcnc_interp_convert_source_probe.o" \ diff --git a/wasm-port/tools/source-manifest.txt b/wasm-port/tools/source-manifest.txt index 440c666..8ac993a 100644 --- a/wasm-port/tools/source-manifest.txt +++ b/wasm-port/tools/source-manifest.txt @@ -11,6 +11,7 @@ src/rtapi/rtapi_gfp.h src/rtapi/rtapi_math.h src/rtapi/rtapi_byteorder.h src/rtapi/rtapi_app.h +src/rtapi/rtapi_ctype.h src/emc/nml_intf/emcpos.h src/emc/nml_intf/emcpose.h src/emc/nml_intf/emcpose.c @@ -32,6 +33,10 @@ src/emc/kinematics/kinematics.h src/emc/kinematics/cubic.h src/emc/kinematics/kins_util.c src/emc/kinematics/trivkins.c +src/emc/kinematics/switchkins.h +src/emc/kinematics/switchkins.c +src/emc/kinematics/userkfuncs.c +src/emc/kinematics/5axiskins.c src/emc/tp/tp.h src/emc/tp/tp_types.h src/emc/tp/tc.h diff --git a/wasm-port/vendor/linuxcnc/src/emc/kinematics/5axiskins.c b/wasm-port/vendor/linuxcnc/src/emc/kinematics/5axiskins.c new file mode 100644 index 0000000..4b688f1 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/src/emc/kinematics/5axiskins.c @@ -0,0 +1,272 @@ +/******************************************************************** +* Description: 5axiskins.c +* kinematics for XYZBC 5 axis bridge mill +* +* Derived from a work by Fred Proctor & Will Shackleford +* +* Author: +* License: GPL Version 2 +* System: Linux +* +* Copyright (c) 2007 Chris Radek +* +* Notes: +* 1) pivot_length hal pin must agree with mechanical +* design (including vismach simulation) and augmented +* with current tool z offset +* (typ: mechanical_pivot_length + motion.tooloffset.z) +* 2) C axis: spherical coordinates aziumthal angle (t or theta) +* projection of radius to xy plane +* 3) B axis: spherical coordinates polar angle (p or phi) +* wrt z axis +* 4) W axis: tool motion. Negative values increase tool radial +* motion example: drilling into body at b,c angles +* 5) W axis motion is incorporated into the motion of the +* joints used for X,Y,Z positioning and no motor or +* hal pin connections are required for the joint specified +* as JW. However, a joint must be configured for W to +* support display of the W axis letter value for +* complicated reasons. (motion/control.c computes joint +* positions only for the number of configured kinematic +* joints (NO_OF_KINS_JOINTS) and the joint positions +* are needed to display axis letters via inverse +* kinematics. +* 6) If no coordinates module parameter is supplied, kins +* will use the required coordinates XYZBCW mapped +* to joints 0..5 in sequence. +* 7) Multiple joints may be assigned to an axis letter +* with the module coordinates parameter +* 8) If a coordinates module parameter is supplied, +* the kins will map coordinate letters in sequence +* to joint numbers beginning with joint 0. +* 9) Coordinates XYZBCW are required, AUV may be used +* if specified with the coordinates parameter and will +* be mapped one-to-one with the assigned joint. +* 10) The direction of the tilt axis is the opposite of the +* conventional axis direction. See +* https://linuxcnc.org/docs/html/gcode/machining-center.html +********************************************************************/ + +// non-required coordinates (A,U,V) can be set by using +// the module coordinates parameter +#define REQUIRED_COORDINATES "XYZBCW" + +#define DEFAULT_PIVOT_LENGTH 250 + +#include +#include +#include +#include +#include +#include +#include + +#include "switchkins.h" + +struct haldata { + hal_float_t *pivot_length; +} *haldata; +static int fiveaxis_max_joints; + +static PmCartesian s2r(double r, double t, double p) { + // s2r: spherical coordinates to cartesian coordinates + // r = length of vector + // p=phi = angle of vector wrt z axis + // t=theta = angle of vector projected onto xy plane + // (projection length in xy plane is r*sin(p) + PmCartesian c; + t = TO_RAD*t; p = TO_RAD*p; // degrees to radians + + c.x = r * sin(p) * cos(t); + c.y = r * sin(p) * sin(t); + c.z = r * cos(p); + + return c; +} //s2r() + +// assignments of principal joints to axis letters: +// (-1 means not defined (yet)) +static int JX = -1; +static int JY = -1; +static int JZ = -1; +static int JA = -1; +static int JB = -1; +static int JC = -1; +static int JU = -1; +static int JV = -1; +static int JW = -1; + +static int fiveaxis_KinematicsForward(const double *joints, + EmcPose * pos, + const KINEMATICS_FORWARD_FLAGS * fflags, + KINEMATICS_INVERSE_FLAGS * iflags) +{ + (void)fflags; + (void)iflags; + PmCartesian r = s2r(*(haldata->pivot_length) + joints[JW], + joints[JC], + 180.0 - joints[JB]); + + // Note: 'principal' joints are used + pos->tran.x = joints[JX] + r.x; + pos->tran.y = joints[JY] + r.y; + pos->tran.z = joints[JZ] + *(haldata->pivot_length) + r.z; + pos->b = joints[JB]; + pos->c = joints[JC]; + pos->w = joints[JW]; + + // optional letters (specify with coordinates module parameter) + pos->a = (JA != -1)? joints[JA] : 0; + pos->u = (JU != -1)? joints[JU] : 0; + pos->v = (JV != -1)? joints[JV] : 0; + + return 0; +} //fiveaxis_KinematicsForward() + +static int fiveaxis_KinematicsInverse(const EmcPose * pos, + double *joints, + const KINEMATICS_INVERSE_FLAGS * iflags, + KINEMATICS_FORWARD_FLAGS * fflags) +{ + (void)iflags; + (void)fflags; + PmCartesian r = s2r(*(haldata->pivot_length) + pos->w, + pos->c, + 180.0 - pos->b); + + EmcPose P; // computed position + P.tran.x = pos->tran.x - r.x; + P.tran.y = pos->tran.y - r.y; + P.tran.z = pos->tran.z - *(haldata->pivot_length) - r.z; + + P.b = pos->b; + P.c = pos->c; + P.w = pos->w; + + // optional letters (specify with coordinates module parameter) + P.a = (JA != -1)? pos->a : 0; + P.u = (JU != -1)? pos->u : 0; + P.v = (JV != -1)? pos->v : 0; + + // update joints with support for + // multiple-joints per-coordinate letter: + // based on computed position + position_to_mapped_joints(fiveaxis_max_joints, + &P, + joints); + return 0; +} // fiveaxis_kinematicsInverse() + +int fiveaxis_KinematicsSetup(const int comp_id, + const char* coordinates, + kparms* kp) +{ + int result=0; + int i,jno; + int axis_idx_for_jno[EMCMOT_MAX_JOINTS]; + int minjoints = strlen(kp->required_coordinates); + fiveaxis_max_joints = strlen(coordinates); // allow for dup coords + + if (fiveaxis_max_joints > kp->max_joints) { + rtapi_print_msg(RTAPI_MSG_ERR, + "ERROR %s: coordinates=%s requires %d joints, max joints=%d\n", + kp->kinsname, + coordinates, + fiveaxis_max_joints, + kp->max_joints); + goto error; + } + + if (map_coordinates_to_jnumbers(coordinates, + kp->max_joints, + kp->allow_duplicates, + axis_idx_for_jno)) { + goto error; + } + // require all chars in reqd_coordinates (order doesn't matter) + for (i=0; i < minjoints; i++) { + char reqd_char; + reqd_char = *(kp->required_coordinates + i); + if ( !strchr(coordinates,toupper(reqd_char)) + && !strchr(coordinates,tolower(reqd_char)) ) { + rtapi_print_msg(RTAPI_MSG_ERR, + "ERROR %s:\nrequired coordinates:%s\n" + "specified coordinates:%s\n", + kp->kinsname, kp->required_coordinates, coordinates); + goto error; + } + } + // assign principal joint numbers (first found in coordinates map) + // duplicates are handled by position_to_mapped_joints() + for (jno=0; jnopivot_length),comp_id, + "%s.pivot-length",kp->halprefix); + if(result < 0) goto error; + + *haldata->pivot_length = DEFAULT_PIVOT_LENGTH; + + rtapi_print("Kinematics Module %s\n",__FILE__); + rtapi_print(" module name = %s\n" + " coordinates = %s Requires: [KINS]JOINTS>=%d\n" + " sparm = %s\n", + kp->kinsname, + coordinates,fiveaxis_max_joints, + kp->sparm?kp->sparm:"NOTSPECIFIED"); + rtapi_print(" default pivot-length = %.3f\n",*haldata->pivot_length); + + return 0; + +error: + return -1; +} // fiveaxis_KinematicsSetup() + +int switchkinsSetup(kparms* kp, + KS* kset0, KS* kset1, KS* kset2, + KF* kfwd0, KF* kfwd1, KF* kfwd2, + KI* kinv0, KI* kinv1, KI* kinv2 + ) +{ + kp->kinsname = "5axiskins"; // !!! must agree with filename + kp->halprefix = "5axiskins"; // hal pin names + kp->required_coordinates = REQUIRED_COORDINATES; + kp->allow_duplicates = 1; + kp->max_joints = EMCMOT_MAX_JOINTS; + + if (kp->sparm && strstr(kp->sparm,"identityfirst")) { + rtapi_print("\n!!! switchkins-type 0 is IDENTITY\n"); + *kset0 = identityKinematicsSetup; + *kfwd0 = identityKinematicsForward; + *kinv0 = identityKinematicsInverse; + + *kset1 = fiveaxis_KinematicsSetup; + *kfwd1 = fiveaxis_KinematicsForward; + *kinv1 = fiveaxis_KinematicsInverse; + } else { + rtapi_print("\n!!! switchkins-type 0 is %s\n",kp->kinsname); + *kset0 = fiveaxis_KinematicsSetup; + *kfwd0 = fiveaxis_KinematicsForward; + *kinv0 = fiveaxis_KinematicsInverse; + + *kset1 = identityKinematicsSetup; + *kfwd1 = identityKinematicsForward; + *kinv1 = identityKinematicsInverse; + } + *kset2 = userkKinematicsSetup; + *kfwd2 = userkKinematicsForward; + *kinv2 = userkKinematicsInverse; + + return 0; +} // switchkinsSetup() diff --git a/wasm-port/vendor/linuxcnc/src/emc/kinematics/switchkins.c b/wasm-port/vendor/linuxcnc/src/emc/kinematics/switchkins.c new file mode 100644 index 0000000..9eb492e --- /dev/null +++ b/wasm-port/vendor/linuxcnc/src/emc/kinematics/switchkins.c @@ -0,0 +1,342 @@ +/* + Copyright 2019 Dewey Garrett + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* switchkins.c provide functions for switchable kins modules: +* rtapi_app() +* rtapi_exit() +* kinematicsType() +* kinematicsForward() +* kinematicsInverse() +* kinematicsSwitch() +* kinematicsSwitchable() +* Using modules must supply function: switchkinsSetup() +*/ +#include +#include +#include +#include +#include + +#include "switchkins.h" + +//********************************************************************* +// kinematic functions (default=0 for err detection): +static kparms kp; // kinematics parms (common all types) + +static KF kfwd0 = 0; // 0==switchkins_type kinematics forward +static KF kfwd1 = 0; // 1 +static KF kfwd2 = 0; // 2 + +static KI kinv0 = 0; // 0==switchkins_type kinematics inverse +static KI kinv1 = 0; // 1 +static KI kinv2 = 0; // 2 + +static hal_u32_t switchkins_type; +static struct swdata { + hal_bit_t *kinstype_is_0; + hal_bit_t *kinstype_is_1; + hal_bit_t *kinstype_is_2; + + hal_float_t *gui_x; + hal_float_t *gui_y; + hal_float_t *gui_z; + hal_float_t *gui_a; + hal_float_t *gui_b; + hal_float_t *gui_c; +} *swdata; + +// Note: parallel kinematics (like genhexkins) often +// use iterative method for Forward algorithm +// and require an initial EmcPose. +// If fwd_iterates_mask is set +// then save/use the lastpose +static int fwd_iterates[SWITCHKINS_MAX_TYPES] = {0}; +static bool use_lastpose[SWITCHKINS_MAX_TYPES] = {0}; +static EmcPose lastpose[SWITCHKINS_MAX_TYPES]; + +static void save_lastpose(int ktype, EmcPose* pos) +{ + lastpose[ktype].tran.x = pos->tran.x; + lastpose[ktype].tran.y = pos->tran.y; + lastpose[ktype].tran.z = pos->tran.z; + lastpose[ktype].a = pos->a; + lastpose[ktype].b = pos->b; + lastpose[ktype].c = pos->c; + lastpose[ktype].u = pos->u; + lastpose[ktype].v = pos->v; + lastpose[ktype].w = pos->w; +} // save_lastpose() + +static void get_lastpose(int ktype, EmcPose* pos) +{ + pos->tran.x = lastpose[ktype].tran.x; + pos->tran.y = lastpose[ktype].tran.y; + pos->tran.z = lastpose[ktype].tran.z; + pos->a = lastpose[ktype].a; + pos->b = lastpose[ktype].b; + pos->c = lastpose[ktype].c; + pos->u = lastpose[ktype].u; + pos->v = lastpose[ktype].v; + pos->w = lastpose[ktype].w; +} // get_lastpose() + +static int gui_forward_kins(const double *joints) +{ + // the hexapod vismach gui uses these hal pins to + // display platform position/orientation in both + // genhexkins and identity kinematic types + // (similar needs for many parallel kinemtic machines) + int res; + KINEMATICS_FORWARD_FLAGS fflags = 0; + KINEMATICS_INVERSE_FLAGS iflags; + switch (kp.gui_kinstype) { + case 0: res = kfwd0(joints, &lastpose[0], &fflags, &iflags);break; + case 1: res = kfwd1(joints, &lastpose[1], &fflags, &iflags);break; + case 2: res = kfwd2(joints, &lastpose[2], &fflags, &iflags);break; + default: rtapi_print_msg(RTAPI_MSG_ERR, + "gui_forward_kins BAD gui_kinstype <%d>\n", + kp.gui_kinstype); + return -1; + } + *swdata->gui_x = lastpose[kp.gui_kinstype].tran.x; + *swdata->gui_y = lastpose[kp.gui_kinstype].tran.y; + *swdata->gui_z = lastpose[kp.gui_kinstype].tran.z; + *swdata->gui_a = lastpose[kp.gui_kinstype].a; + *swdata->gui_b = lastpose[kp.gui_kinstype].b; + *swdata->gui_c = lastpose[kp.gui_kinstype].c; + return res; +} // gui_forward_kins + +//********************************************************************* +int kinematicsSwitchable() {return 1;} + +int kinematicsSwitch(int new_switchkins_type) +{ + int k; + for (k=0; k< SWITCHKINS_MAX_TYPES; k++) { use_lastpose[k] = 0;} + + switchkins_type = new_switchkins_type; + switch (switchkins_type) { + case 0: rtapi_print_msg(RTAPI_MSG_INFO, + "kinematicsSwitch:TYPE0\n"); + *swdata->kinstype_is_0 = 1; + *swdata->kinstype_is_1 = 0; + *swdata->kinstype_is_2 = 0; + break; + case 1: rtapi_print_msg(RTAPI_MSG_INFO, + "kinematicsSwitch:TYPE1\n"); + *swdata->kinstype_is_0 = 0; + *swdata->kinstype_is_1 = 1; + *swdata->kinstype_is_2 = 0; + break; + case 2: rtapi_print_msg(RTAPI_MSG_INFO, + "kinematicsSwitch:TYPE2\n"); + *swdata->kinstype_is_0 = 0; + *swdata->kinstype_is_1 = 0; + *swdata->kinstype_is_2 = 1; + break; + default: rtapi_print_msg(RTAPI_MSG_ERR, + "kinematicsSwitch:BAD VALUE <%d>\n", + switchkins_type); + *swdata->kinstype_is_1 = 0; + *swdata->kinstype_is_0 = 0; + *swdata->kinstype_is_2 = 0; + return -1; // FAIL + } + if (fwd_iterates[switchkins_type]) { + use_lastpose[switchkins_type] = 1; // restarting a kins types + } + return 0; // 0==> no error +} // kinematicsSwitch() + +int kinematicsForward(const double *joint, + EmcPose * pos, + const KINEMATICS_FORWARD_FLAGS * fflags, + KINEMATICS_INVERSE_FLAGS * iflags) +{ + int r; + + if (fwd_iterates[switchkins_type] && use_lastpose[switchkins_type]) { + // initialize iterative forward kins (ok for identity too) + get_lastpose(switchkins_type,pos); + use_lastpose[switchkins_type] = 0; + } + + switch (switchkins_type) { + case 0: r = kfwd0(joint, pos, fflags, iflags); break; + case 1: r = kfwd1(joint, pos, fflags, iflags); break; + case 2: r = kfwd2(joint, pos, fflags, iflags); break; + default: rtapi_print_msg(RTAPI_MSG_ERR, + "switchkins: Forward BAD switchkins_type \n", + switchkins_type); + return -1; + } + if (fwd_iterates[switchkins_type]) {save_lastpose(switchkins_type,pos);} + if (r) return r; + + // gui.* pins created only if gui_kinstype>=0 + // consider alternate implementations for gui_forward_kins(): + // a) always call and use -1 to select default 0 type + if (kp.gui_kinstype >=0) { + // create gui pins for a vismach gui using the + // kins type specified by kp.gui_kinstype; + // currently the skgui pins are only needed for + // the hexagui vismach program (as it needs + // world coords for switchkin-types + r = gui_forward_kins(joint); + } + + return r; +} // kinematicsForward() + +int kinematicsInverse(const EmcPose * pos, + double *joint, + const KINEMATICS_INVERSE_FLAGS * iflags, + KINEMATICS_FORWARD_FLAGS * fflags) +{ + int r; + + switch (switchkins_type) { + case 0: r = kinv0(pos, joint, iflags, fflags); break; + case 1: r = kinv1(pos, joint, iflags, fflags); break; + case 2: r = kinv2(pos, joint, iflags, fflags); break; + default: rtapi_print_msg(RTAPI_MSG_ERR, + "switchkins: Inverse BAD switchkins_type \n", + switchkins_type); + return -1; + } + return r; +} // kinematicsInverse() + +KINEMATICS_TYPE kinematicsType() +{ + return KINEMATICS_BOTH; +} + +//********************************************************************* +static char *coordinates; +RTAPI_MP_STRING(coordinates, "Axes-to-joints-ordering"); +static char *sparm; +RTAPI_MP_STRING(sparm, "switchkins module-specific parameter"); + +EXPORT_SYMBOL(kinematicsSwitchable); +EXPORT_SYMBOL(kinematicsSwitch); +EXPORT_SYMBOL(kinematicsType); +EXPORT_SYMBOL(kinematicsForward); +EXPORT_SYMBOL(kinematicsInverse); +MODULE_LICENSE("GPL"); + +static int comp_id; +//********************************************************************* +int rtapi_app_main(void) +{ + int i,res; + char* emsg="other"; + + // defaults prior to switchkinsSetup() call + kp.kinsname = NULL; + kp.halprefix = NULL; + kp.required_coordinates = ""; + kp.max_joints = 0; // Setup must supply + kp.allow_duplicates = 0; + kp.fwd_iterates_mask = 0; + kp.gui_kinstype = -1; // negative means: not used + + kp.sparm = sparm; // module parm passed to kins + + KS ksetup0 = 0; + KS ksetup1 = 0; + KS ksetup2 = 0; + + res = switchkinsSetup(&kp, + &ksetup0, &ksetup1, &ksetup2, + &kfwd0, &kfwd1, &kfwd2, + &kinv0, &kinv1, &kinv2); + if (res) {emsg="switchkinsSetp FAIL"; goto error;} + + for (i=0; i < SWITCHKINS_MAX_TYPES; i++) { + if (kp.fwd_iterates_mask & (1< EMCMOT_MAX_JOINTS) { + emsg = "bogus max_joints"; goto error; + } + if (kp.gui_kinstype >= SWITCHKINS_MAX_TYPES) { + emsg = "bogus gui_kinstype"; goto error; + } + + if (!ksetup0 || !ksetup1 || !ksetup2) { + emsg = "Missing setup function"; goto error; + } + if (!kfwd0 || !kfwd1 || !kfwd2) { + emsg = "Missing fwd functionn"; goto error; + } + if (!kinv0 || !kinv1 || !kinv2) { + emsg = "Missing inv function"; goto error; + } + + comp_id = hal_init(kp.kinsname); + if(comp_id < 0) goto error; + + swdata = hal_malloc(sizeof(struct swdata)); + if (!swdata) goto error; + + res += hal_pin_bit_new("kinstype.is-0", HAL_OUT, &(swdata->kinstype_is_0), comp_id); + res += hal_pin_bit_new("kinstype.is-1", HAL_OUT, &(swdata->kinstype_is_1), comp_id); + res += hal_pin_bit_new("kinstype.is-2", HAL_OUT, &(swdata->kinstype_is_2), comp_id); + + if (kp.gui_kinstype >=0) { + res += hal_pin_float_newf(HAL_IN, &swdata->gui_x, comp_id, "skgui.x"); + res += hal_pin_float_newf(HAL_IN, &swdata->gui_y, comp_id, "skgui.y"); + res += hal_pin_float_newf(HAL_IN, &swdata->gui_z, comp_id, "skgui.z"); + res += hal_pin_float_newf(HAL_IN, &swdata->gui_a, comp_id, "skgui.a"); + res += hal_pin_float_newf(HAL_IN, &swdata->gui_b, comp_id, "skgui.b"); + res += hal_pin_float_newf(HAL_IN, &swdata->gui_c, comp_id, "skgui.c"); + if (res) {emsg = "hal pin create fail";goto error;} + } + + switchkins_type = 0; // startup with default type + kinematicsSwitch(switchkins_type); + + if (!coordinates) {coordinates = kp.required_coordinates;} + + ksetup0(comp_id,coordinates,&kp); + ksetup1(comp_id,coordinates,&kp); + ksetup2(comp_id,coordinates,&kp); + + hal_ready(comp_id); + return 0; + +error: + rtapi_print_msg(RTAPI_MSG_ERR, + "\nSwitchkins FAIL %s:<%s>\n",kp.kinsname,emsg); + hal_exit(comp_id); + return -1; +} // rtapi_app_main() + +void rtapi_app_exit(void) { hal_exit(comp_id); } diff --git a/wasm-port/vendor/linuxcnc/src/emc/kinematics/switchkins.h b/wasm-port/vendor/linuxcnc/src/emc/kinematics/switchkins.h new file mode 100644 index 0000000..1cad41b --- /dev/null +++ b/wasm-port/vendor/linuxcnc/src/emc/kinematics/switchkins.h @@ -0,0 +1,36 @@ +/* +** License GPL Version 2 +*/ +#ifndef SWITCHKINS_H // { +#define SWITCHKINS_H + +#include + +//hardcoded number of switchkins types (KS,KF,KI): +#define SWITCHKINS_MAX_TYPES 3 + +// KinematicsFORWARD functions +typedef int (*KF)(const double *joint, + EmcPose * pos, + const KINEMATICS_FORWARD_FLAGS * fflags, + KINEMATICS_INVERSE_FLAGS * iflags); + +// KinematicsINVERSE functions +typedef int (*KI)(const struct EmcPose * world, + double *joint, + const KINEMATICS_INVERSE_FLAGS * iflags, + KINEMATICS_FORWARD_FLAGS * fflags); + +// KinematicsSETUP functions +typedef int (*KS)(const int comp_id, // halpins + const char* coordinates, // module parameter + kparms* ksetup_parms // + ); + +//********************************************************************* +extern int switchkinsSetup(kparms* ksetup_parms, + KS* kset0, KS* kset1, KS* kset2, + KF* kfwd0, KF* kfwd1, KF* kfwd2, + KI* kinv0, KI* kinv1, KI* kinv2 + ); +#endif // } diff --git a/wasm-port/vendor/linuxcnc/src/emc/kinematics/userkfuncs.c b/wasm-port/vendor/linuxcnc/src/emc/kinematics/userkfuncs.c new file mode 100644 index 0000000..d1c6b6a --- /dev/null +++ b/wasm-port/vendor/linuxcnc/src/emc/kinematics/userkfuncs.c @@ -0,0 +1,83 @@ +/* userkfuncs.c: template file for a user set of +** switchable kinematics functions. +** License GPL Version 2 +** +** Example Usage (for customizing the genser-switchkins module): +** (works with rtpreempt only rtai --> Makefile needs work) +** +** LDIR is LinuxCNC git root directory +** UDIR is user directory (not in LinuxCNC git tree) +** 1) $ cp LDIR/src/emc/kinematics/userkfuncs.c UDIR/my_userk.c +** 2) $ edit UDIR/my_userk.c as required +** 3) $ source LDIR/scripts/rip-environment +** 4) For genser-switchkins module use make command line option: +** $ cd LDIR/src +** $ userkfuncs=UDIR/my_userk.c make && sudo make setuid +*/ + +// typical includes: +//#include // if reqd +#include +#include + +// Add for kins based on genserkins: +// #include "genserkins.h" //includes gomath,hal + +//********************************************************************** +// static local variables and functions go here + +static int userk_inited = 0; +static struct udata { + hal_s32_t *fct; + hal_s32_t *ict; +} *udata; + +//********************************************************************** +int userkKinematicsSetup(const int comp_id, + const char* coordinates, + kparms* kp) +{ + int res=0; + rtapi_print("\nuserkKinematicsSetup:\n" + " %s <%s> max_joints=%d allow_duplicates=%d\n\n", + __FILE__,coordinates, + kp->max_joints,kp->allow_duplicates); + + + udata = hal_malloc(sizeof(struct udata)); + if (!udata) goto error; + + // HAL_IO used to allow resetting demo pins: + res += hal_pin_s32_new("userk.fct", HAL_IO, &(udata->fct), comp_id); + res += hal_pin_s32_new("userk.ict", HAL_IO, &(udata->ict), comp_id); + if (res) goto error; + + userk_inited = 1; + return 0; // 0 ==> OK + +error: + return -1; +} + +int userkKinematicsForward(const double *joint, + struct EmcPose * world, + const KINEMATICS_FORWARD_FLAGS * fflags, + KINEMATICS_INVERSE_FLAGS * iflags) +{ + if (!userk_inited) { + rtapi_print_msg(RTAPI_MSG_ERR, + "userkKinematics: not initialized\n"); + return -1; + } + (*udata->fct)++; + return identityKinematicsForward(joint,world,fflags,iflags); +} + +int userkKinematicsInverse(const EmcPose * pos, + double *joint, + const KINEMATICS_INVERSE_FLAGS * iflags, + KINEMATICS_FORWARD_FLAGS * fflags) +{ + (*udata->ict)++; + return identityKinematicsInverse(pos,joint,iflags,fflags); +} diff --git a/wasm-port/vendor/linuxcnc/src/rtapi/rtapi_ctype.h b/wasm-port/vendor/linuxcnc/src/rtapi/rtapi_ctype.h new file mode 100644 index 0000000..31856dc --- /dev/null +++ b/wasm-port/vendor/linuxcnc/src/rtapi/rtapi_ctype.h @@ -0,0 +1,24 @@ +#ifndef __LINUXCNC_RTAPI_CTYPE_H +#define __LINUXCNC_RTAPI_CTYPE_H +// Copyright 2006 Jeff Epler +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +#ifdef MODULE +#include +#else +#include +#endif + +#endif