接续上一轮:推进浏览器验证与M428配置收拢
结论:已完成浏览器侧真实加载验证,M428/M429/M430 的配置入口进一步从 LinuxCNC INI/HALFILE/REMAP 来源生成,native 与 source-link 验证通过。
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
project(cnc_sim_wasm_core LANGUAGES CXX)
|
||||
project(cnc_sim_wasm_core LANGUAGES C CXX)
|
||||
|
||||
option(CNC_SIM_ENABLE_LINUXCNC_BRIDGE "Build the experimental LinuxCNC canon bridge" OFF)
|
||||
option(CNC_SIM_ENABLE_LINUXCNC_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)
|
||||
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"
|
||||
@@ -15,23 +16,71 @@ set(cnc_sim_core_sources
|
||||
src/canon_event_sink.cpp
|
||||
src/cnc_sim_api.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/simulator_gcode_controls.cpp
|
||||
)
|
||||
|
||||
set(cnc_sim_smoke_backend_sources
|
||||
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_SMOKE_BACKEND)
|
||||
message(FATAL_ERROR "CNC_SIM_ENABLE_SMOKE_BACKEND cannot be combined with CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND")
|
||||
endif()
|
||||
if(EMSCRIPTEN)
|
||||
message(FATAL_ERROR "CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND is native-only; it links LinuxCNC librs274")
|
||||
endif()
|
||||
if(NOT CNC_SIM_LINUXCNC_ROOT)
|
||||
message(FATAL_ERROR "Set CNC_SIM_LINUXCNC_ROOT to the LinuxCNC source root")
|
||||
endif()
|
||||
list(APPEND cnc_sim_core_sources
|
||||
src/linuxcnc_canon_bridge.cpp
|
||||
src/linuxcnc_rs274_backend.cpp
|
||||
src/linuxcnc_tooldata_fixture.cpp
|
||||
)
|
||||
list(APPEND cnc_sim_core_sources ${cnc_sim_linuxcnc_rs274_backend_sources})
|
||||
elseif(CNC_SIM_ENABLE_SMOKE_BACKEND)
|
||||
list(APPEND cnc_sim_core_sources ${cnc_sim_smoke_backend_sources})
|
||||
endif()
|
||||
|
||||
if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||
@@ -67,7 +116,11 @@ if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||
|
||||
set(manifest_group "${CMAKE_MATCH_1}")
|
||||
set(manifest_path "${CMAKE_MATCH_2}")
|
||||
if(NOT manifest_group STREQUAL "core" AND NOT manifest_group STREQUAL "blocked")
|
||||
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()
|
||||
|
||||
@@ -81,7 +134,7 @@ if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||
|
||||
if(manifest_group STREQUAL "core")
|
||||
list(APPEND linuxcnc_wasm_safe_probe_sources "${manifest_source}")
|
||||
else()
|
||||
elseif(manifest_group STREQUAL "blocked")
|
||||
list(APPEND linuxcnc_wasm_blocked_sources "${manifest_source}")
|
||||
endif()
|
||||
endforeach()
|
||||
@@ -97,6 +150,17 @@ if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||
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")
|
||||
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
|
||||
@@ -115,7 +179,7 @@ if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||
)
|
||||
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 -include wctype.h)
|
||||
target_compile_options(linuxcnc_rs274_wasm_safe_probe_objects PRIVATE ${cnc_sim_wasm_safe_preinclude_options})
|
||||
target_include_directories(linuxcnc_rs274_wasm_safe_probe_objects
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
@@ -128,12 +192,55 @@ if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||
${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(linuxcnc_rs274_wasm_safe_probe_project_sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/canon_event_sink.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_canon_bridge.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_rs274_backend.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_tooldata_fixture.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_5axiskins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_5axiskins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_corexykins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_corexykins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_cubic_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_cubic_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_genserfuncs_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_genserfuncs_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_genhexkins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_genhexkins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_kins_util_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_kins_util_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_lineardeltakins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_lineardeltakins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_maxkins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_maxkins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_pentakins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_pentakins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_pumakins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_pumakins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_rotatekins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_rotatekins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_rosekins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_rosekins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_rotarydeltakins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_rotarydeltakins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_scarakins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_scarakins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_scorbot_kins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_scorbot_kins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_tripodkins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_tripodkins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_trtfuncs_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_trtfuncs_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_userkfuncs_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_userkfuncs_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_xyzab_tdr_kins_adapter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_xyzab_tdr_kins_adapter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/rtcp_kinematics.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/simulator_gcode_controls.cpp
|
||||
)
|
||||
|
||||
add_executable(linuxcnc_rs274_wasm_safe_probe EXCLUDE_FROM_ALL
|
||||
@@ -142,8 +249,13 @@ if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||
${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 ULAPI)
|
||||
target_compile_options(linuxcnc_rs274_wasm_safe_probe PRIVATE -include wctype.h)
|
||||
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_include_directories(linuxcnc_rs274_wasm_safe_probe
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
@@ -156,7 +268,15 @@ if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/motion
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/include
|
||||
)
|
||||
target_link_libraries(linuxcnc_rs274_wasm_safe_probe PRIVATE fmt)
|
||||
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()
|
||||
|
||||
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
|
||||
@@ -165,6 +285,10 @@ if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||
list(APPEND cnc_sim_core_sources ${cnc_sim_linuxcnc_rs274_backend_sources})
|
||||
endif()
|
||||
|
||||
add_library(cnc_sim_objects OBJECT
|
||||
${cnc_sim_core_sources}
|
||||
)
|
||||
@@ -174,9 +298,36 @@ target_include_directories(cnc_sim_objects
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../linuxcnc/include
|
||||
)
|
||||
|
||||
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)
|
||||
find_package(Python3 REQUIRED COMPONENTS Development)
|
||||
@@ -196,6 +347,64 @@ if(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
||||
)
|
||||
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(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_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
|
||||
$<TARGET_OBJECTS:cnc_sim_objects>
|
||||
)
|
||||
@@ -225,11 +434,13 @@ if(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
||||
endif()
|
||||
|
||||
if(NOT EMSCRIPTEN)
|
||||
if(CNC_SIM_ENABLE_SMOKE_BACKEND)
|
||||
add_executable(cnc_sim_api_smoke
|
||||
tests/cnc_sim_api_smoke.cpp
|
||||
)
|
||||
target_link_libraries(cnc_sim_api_smoke PRIVATE cnc_sim_core)
|
||||
target_include_directories(cnc_sim_api_smoke PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
endif()
|
||||
|
||||
add_executable(canon_event_sink_smoke
|
||||
tests/canon_event_sink_smoke.cpp
|
||||
@@ -254,11 +465,13 @@ if(NOT EMSCRIPTEN)
|
||||
target_link_libraries(simulator_gcode_controls_smoke PRIVATE cnc_sim_core)
|
||||
target_include_directories(simulator_gcode_controls_smoke PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
|
||||
if(CNC_SIM_ENABLE_SMOKE_BACKEND)
|
||||
add_executable(cnc_sim_dump
|
||||
tools/cnc_sim_dump.cpp
|
||||
)
|
||||
target_link_libraries(cnc_sim_dump PRIVATE cnc_sim_core)
|
||||
target_include_directories(cnc_sim_dump PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
endif()
|
||||
|
||||
if(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
||||
add_executable(cnc_sim_api_linuxcnc_rs274_smoke
|
||||
@@ -298,7 +511,11 @@ if(CNC_SIM_ENABLE_LINUXCNC_BRIDGE)
|
||||
endif()
|
||||
|
||||
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
|
||||
$<TARGET_OBJECTS:linuxcnc_rs274_wasm_safe_probe_objects>
|
||||
$<TARGET_OBJECTS:cnc_sim_objects>
|
||||
)
|
||||
|
||||
@@ -306,7 +523,15 @@ if(EMSCRIPTEN)
|
||||
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
|
||||
)
|
||||
target_compile_definitions(cnc_sim_wasm PRIVATE FMT_HEADER_ONLY=1)
|
||||
|
||||
set_target_properties(cnc_sim_wasm PROPERTIES
|
||||
OUTPUT_NAME "cnc_sim"
|
||||
|
||||
@@ -88,6 +88,13 @@ void CanonEventSink::configure_fiveaxis(double pivot_length, int kinematics_type
|
||||
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) {
|
||||
if (h_code <= 0) {
|
||||
default_rtcp_tool_length_ = tool_length;
|
||||
@@ -151,24 +158,59 @@ void CanonEventSink::switch_kinematics(int kinematics_type, int line) {
|
||||
emit(event);
|
||||
}
|
||||
|
||||
void CanonEventSink::switch_m_code_kinematics(int m_code, int default_kinematics_type, int line) {
|
||||
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_) {
|
||||
// Source: linuxcnc/configs/sim/axis/vismach/5axis/bridgemill/remap_subs/{428,429,430}remap.ngc
|
||||
// M428 selects 5axiskins type 0, M429 selects identity type 1, M430 selects userk type 2.
|
||||
// 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;
|
||||
return true;
|
||||
}
|
||||
if (m_code == 429) {
|
||||
switch_kinematics(1, line);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (m_code == 430) {
|
||||
switch_kinematics(2, line);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
switch_kinematics(default_kinematics_type, line);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CanonEventSink::set_g5x_offset(int index, const CncSimPose &offset, int line) {
|
||||
|
||||
@@ -16,12 +16,14 @@ public:
|
||||
void configure_xyzbc_trt(const LinuxCncXyzbcTrtParameters ¶meters);
|
||||
void configure_xyzac_trt(const LinuxCncXyzbcTrtParameters ¶meters);
|
||||
void configure_fiveaxis(double pivot_length, int kinematics_type);
|
||||
void configure_switchkins_remap(int m428_type, int m429_type, int m430_type);
|
||||
void set_tool_length(int h_code, double tool_length);
|
||||
void set_tool_length_offset(const CncSimPose &offset);
|
||||
void apply_tool_length_offset(const CncSimPose &offset);
|
||||
void set_rtcp_state(bool enabled, int h_code, int line);
|
||||
void switch_kinematics(int kinematics_type, int line);
|
||||
void switch_m_code_kinematics(int m_code, int default_kinematics_type, int line);
|
||||
bool can_switch_m_code_kinematics(int m_code) const;
|
||||
bool switch_m_code_kinematics(int m_code, int default_kinematics_type, int line);
|
||||
void set_g5x_offset(int index, const CncSimPose &offset, int line);
|
||||
void set_g92_offset(const CncSimPose &offset, int line);
|
||||
void set_xy_rotation(double angle_degrees, int line);
|
||||
@@ -108,6 +110,10 @@ private:
|
||||
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_{};
|
||||
double xy_rotation_degrees_ = 0.0;
|
||||
int kinematics_type_ = 0;
|
||||
|
||||
@@ -4,16 +4,13 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
struct CncSimHandle {
|
||||
CncSimDialect dialect = CNC_SIM_DIALECT_LINUXCNC;
|
||||
#ifdef CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
||||
GcodeBackendKind backend = GcodeBackendKind::LinuxCncRs274;
|
||||
#else
|
||||
GcodeBackendKind backend = GcodeBackendKind::Smoke;
|
||||
#endif
|
||||
std::string last_error;
|
||||
CanonEventSink sink;
|
||||
};
|
||||
@@ -77,6 +74,40 @@ bool contains_bool_value(const std::string &compact, const char *key, bool *valu
|
||||
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 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, "config", alias) ||
|
||||
contains_string_value(compact, "configpath", alias) ||
|
||||
contains_string_value(compact, "config_path", alias);
|
||||
}
|
||||
|
||||
bool find_number_value(const std::string &compact, const char *key, double *value) {
|
||||
const std::string needle = std::string("\"") + key + "\":";
|
||||
const size_t pos = compact.find(needle);
|
||||
@@ -212,6 +243,38 @@ void apply_fiveaxis_config(CanonEventSink &sink, const std::string &compact) {
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (json.empty()) {
|
||||
return 0;
|
||||
@@ -242,6 +305,7 @@ int apply_config(CncSimHandle *handle, const std::string &json) {
|
||||
handle->sink.set_block_delete(block_delete);
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
#ifdef CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
||||
#include "linuxcnc_rs274_backend.h"
|
||||
#endif
|
||||
#ifdef CNC_SIM_ENABLE_SMOKE_BACKEND
|
||||
#include "smoke_gcode_parser.h"
|
||||
#endif
|
||||
|
||||
const char *gcode_backend_name(GcodeBackendKind backend) {
|
||||
switch (backend) {
|
||||
@@ -23,8 +25,15 @@ int parse_gcode_with_backend(GcodeBackendKind backend,
|
||||
std::string *error) {
|
||||
switch (backend) {
|
||||
case GcodeBackendKind::Smoke: {
|
||||
#ifdef CNC_SIM_ENABLE_SMOKE_BACKEND
|
||||
SmokeGcodeParser parser(sink);
|
||||
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:
|
||||
#ifdef CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
||||
|
||||
266
core/src/linuxcnc_5axiskins_adapter.c
Normal file
266
core/src/linuxcnc_5axiskins_adapter.c
Normal file
@@ -0,0 +1,266 @@
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_STRING_H
|
||||
#define __LINUXCNC_RTAPI_CTYPE_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_EMCMOTCFG_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
#define SWITCHKINS_H
|
||||
|
||||
#define RTAPI_MSG_ERR 1
|
||||
#define PM_PI 3.1415926535897932384626433832795029
|
||||
#define TO_RAD (PM_PI / 180.0)
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
#define EMCMOT_MAX_AXIS 9
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef int hal_s32_t;
|
||||
typedef bool hal_bit_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
typedef int (*KF)(const double *joint,
|
||||
EmcPose *pos,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags);
|
||||
typedef int (*KI)(const struct EmcPose *world,
|
||||
double *joint,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags);
|
||||
typedef int (*KS)(const int comp_id, const char *coordinates, kparms *ksetup_parms);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static int cnc_sim_axis_idx_for_jno[EMCMOT_MAX_JOINTS];
|
||||
static int cnc_sim_max_joints;
|
||||
|
||||
void cnc_sim_5axis_rtapi_print(const char *fmt, ...) {
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void cnc_sim_5axis_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||
(void)level;
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void *cnc_sim_5axis_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_5axis_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||
hal_float_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_5axis_map_coordinates_to_jnumbers(const char *coordinates,
|
||||
const int max_joints,
|
||||
const int allow_duplicates,
|
||||
int axis_idx_for_jno[]) {
|
||||
(void)allow_duplicates;
|
||||
const char *letters = "XYZABCUVW";
|
||||
int jno = 0;
|
||||
for (int i = 0; i < EMCMOT_MAX_JOINTS; ++i) {
|
||||
axis_idx_for_jno[i] = -1;
|
||||
cnc_sim_axis_idx_for_jno[i] = -1;
|
||||
}
|
||||
while (*coordinates) {
|
||||
const char *found = strchr(letters, toupper((unsigned char)*coordinates));
|
||||
if (!found || jno >= max_joints) {
|
||||
return -1;
|
||||
}
|
||||
axis_idx_for_jno[jno++] = (int)(found - letters);
|
||||
++coordinates;
|
||||
}
|
||||
cnc_sim_max_joints = jno;
|
||||
for (int i = 0; i < EMCMOT_MAX_JOINTS; ++i) {
|
||||
cnc_sim_axis_idx_for_jno[i] = axis_idx_for_jno[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnc_sim_5axis_position_to_mapped_joints(const int max_joints, const EmcPose *pos, double *joints) {
|
||||
for (int jno = 0; jno < max_joints; ++jno) {
|
||||
switch (cnc_sim_axis_idx_for_jno[jno]) {
|
||||
case 0: joints[jno] = pos->tran.x; break;
|
||||
case 1: joints[jno] = pos->tran.y; break;
|
||||
case 2: joints[jno] = pos->tran.z; break;
|
||||
case 3: joints[jno] = pos->a; break;
|
||||
case 4: joints[jno] = pos->b; break;
|
||||
case 5: joints[jno] = pos->c; break;
|
||||
case 6: joints[jno] = pos->u; break;
|
||||
case 7: joints[jno] = pos->v; break;
|
||||
case 8: joints[jno] = pos->w; break;
|
||||
default: joints[jno] = 0.0; break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnc_sim_5axis_identityKinematicsSetup(const int comp_id, const char *coordinates, kparms *ksetup_parms) {
|
||||
(void)comp_id;
|
||||
(void)coordinates;
|
||||
(void)ksetup_parms;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnc_sim_5axis_identityKinematicsForward(const double *joint,
|
||||
EmcPose *world,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||
(void)joint;
|
||||
(void)world;
|
||||
(void)fflags;
|
||||
(void)iflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_5axis_identityKinematicsInverse(const EmcPose *world,
|
||||
double *joint,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||
(void)world;
|
||||
(void)joint;
|
||||
(void)iflags;
|
||||
(void)fflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_5axis_userkKinematicsSetup(const int comp_id, const char *coordinates, kparms *ksetup_parms) {
|
||||
(void)comp_id;
|
||||
(void)coordinates;
|
||||
(void)ksetup_parms;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_5axis_userkKinematicsForward(const double *joint,
|
||||
EmcPose *world,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||
(void)joint;
|
||||
(void)world;
|
||||
(void)fflags;
|
||||
(void)iflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_5axis_userkKinematicsInverse(const EmcPose *pos,
|
||||
double *joint,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||
(void)pos;
|
||||
(void)joint;
|
||||
(void)iflags;
|
||||
(void)fflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define rtapi_print cnc_sim_5axis_rtapi_print
|
||||
#define rtapi_print_msg cnc_sim_5axis_rtapi_print_msg
|
||||
#define hal_pin_float_newf cnc_sim_5axis_hal_pin_float_newf
|
||||
#define map_coordinates_to_jnumbers cnc_sim_5axis_map_coordinates_to_jnumbers
|
||||
#define position_to_mapped_joints cnc_sim_5axis_position_to_mapped_joints
|
||||
#define identityKinematicsSetup cnc_sim_5axis_identityKinematicsSetup
|
||||
#define identityKinematicsForward cnc_sim_5axis_identityKinematicsForward
|
||||
#define identityKinematicsInverse cnc_sim_5axis_identityKinematicsInverse
|
||||
#define userkKinematicsSetup cnc_sim_5axis_userkKinematicsSetup
|
||||
#define userkKinematicsForward cnc_sim_5axis_userkKinematicsForward
|
||||
#define userkKinematicsInverse cnc_sim_5axis_userkKinematicsInverse
|
||||
#define switchkinsSetup cnc_sim_5axis_switchkinsSetup
|
||||
#define haldata cnc_sim_5axis_haldata
|
||||
#define hal_malloc(size) ((struct haldata *)cnc_sim_5axis_hal_malloc(size))
|
||||
#include "../../../linuxcnc/src/emc/kinematics/5axiskins.c"
|
||||
#undef hal_malloc
|
||||
#undef haldata
|
||||
#undef switchkinsSetup
|
||||
#undef userkKinematicsInverse
|
||||
#undef userkKinematicsForward
|
||||
#undef userkKinematicsSetup
|
||||
#undef identityKinematicsInverse
|
||||
#undef identityKinematicsForward
|
||||
#undef identityKinematicsSetup
|
||||
#undef position_to_mapped_joints
|
||||
#undef map_coordinates_to_jnumbers
|
||||
#undef hal_pin_float_newf
|
||||
#undef rtapi_print_msg
|
||||
#undef rtapi_print
|
||||
|
||||
int cnc_sim_linuxcnc_5axiskins_setup(void) {
|
||||
kparms kp = {0};
|
||||
static char kinsname[] = "5axiskins";
|
||||
static char halprefix[] = "5axiskins";
|
||||
static char required_coordinates[] = "XYZBCW";
|
||||
kp.kinsname = kinsname;
|
||||
kp.halprefix = halprefix;
|
||||
kp.required_coordinates = required_coordinates;
|
||||
kp.max_joints = EMCMOT_MAX_JOINTS;
|
||||
kp.allow_duplicates = 1;
|
||||
return fiveaxis_KinematicsSetup(0, "XYZBCW", &kp);
|
||||
}
|
||||
|
||||
void cnc_sim_linuxcnc_5axiskins_set_pivot_length(double pivot_length) {
|
||||
*cnc_sim_5axis_haldata->pivot_length = pivot_length;
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_5axiskins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return fiveaxis_KinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_5axiskins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return fiveaxis_KinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
122
core/src/linuxcnc_5axiskins_adapter.cpp
Normal file
122
core/src/linuxcnc_5axiskins_adapter.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "linuxcnc_5axiskins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_5axiskins_setup(void);
|
||||
void cnc_sim_linuxcnc_5axiskins_set_pivot_length(double pivot_length);
|
||||
int cnc_sim_linuxcnc_5axiskins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_5axiskins_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_5axiskins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncFiveAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.b;
|
||||
out[4] = joints.c;
|
||||
out[5] = joints.w;
|
||||
}
|
||||
|
||||
LinuxCncFiveAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncFiveAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.b = joints[3];
|
||||
out.c = joints[4];
|
||||
out.w = joints[5];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_5axiskins_forward(const LinuxCncFiveAxisJoints &joints,
|
||||
double pivot_length,
|
||||
CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
cnc_sim_linuxcnc_5axiskins_set_pivot_length(pivot_length);
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_5axiskins_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_5axiskins_inverse(const CncSimPose &pose,
|
||||
double pivot_length,
|
||||
LinuxCncFiveAxisJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
cnc_sim_linuxcnc_5axiskins_set_pivot_length(pivot_length);
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
if (cnc_sim_linuxcnc_5axiskins_inverse(&in, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
10
core/src/linuxcnc_5axiskins_adapter.h
Normal file
10
core/src/linuxcnc_5axiskins_adapter.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_5axiskins_forward(const LinuxCncFiveAxisJoints &joints,
|
||||
double pivot_length,
|
||||
CncSimPose *pose);
|
||||
bool linuxcnc_5axiskins_inverse(const CncSimPose &pose,
|
||||
double pivot_length,
|
||||
LinuxCncFiveAxisJoints *joints);
|
||||
127
core/src/linuxcnc_corexykins_adapter.c
Normal file
127
core/src/linuxcnc_corexykins_adapter.c
Normal file
@@ -0,0 +1,127 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_APP_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_STRING_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_EMCMOTCFG_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
|
||||
#define MODULE_LICENSE(...)
|
||||
#define EXPORT_SYMBOL(symbol)
|
||||
#define RTAPI_MSG_ERR 1
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
typedef int hal_s32_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#define KINS_NOT_SWITCHABLE \
|
||||
extern int kinematicsSwitchable() { return 0; } \
|
||||
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int cnc_sim_corexykins_hal_init(const char *name) {
|
||||
(void)name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *cnc_sim_corexykins_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_corexykins_hal_ready(int comp_id) {
|
||||
(void)comp_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnc_sim_corexykins_hal_exit(int comp_id) {
|
||||
(void)comp_id;
|
||||
}
|
||||
|
||||
#define hal_init cnc_sim_corexykins_hal_init
|
||||
#define hal_malloc(size) ((struct data *)cnc_sim_corexykins_hal_malloc(size))
|
||||
#define hal_ready cnc_sim_corexykins_hal_ready
|
||||
#define hal_exit cnc_sim_corexykins_hal_exit
|
||||
#define kinematicsType cnc_sim_corexykins_kinematicsType
|
||||
#define kinematicsForward cnc_sim_corexykins_kinematicsForward
|
||||
#define kinematicsInverse cnc_sim_corexykins_kinematicsInverse
|
||||
#define kinematicsHome cnc_sim_corexykins_kinematicsHome
|
||||
#define kinematicsSwitchable cnc_sim_corexykins_kinematicsSwitchable
|
||||
#define kinematicsSwitch cnc_sim_corexykins_kinematicsSwitch
|
||||
#define rtapi_app_main cnc_sim_corexykins_rtapi_app_main
|
||||
#define rtapi_app_exit cnc_sim_corexykins_rtapi_app_exit
|
||||
#define comp_id cnc_sim_corexykins_comp_id
|
||||
#define data cnc_sim_corexykins_data
|
||||
#include "../../../linuxcnc/src/emc/kinematics/corexykins.c"
|
||||
#undef data
|
||||
#undef comp_id
|
||||
#undef rtapi_app_exit
|
||||
#undef rtapi_app_main
|
||||
#undef kinematicsSwitch
|
||||
#undef kinematicsSwitchable
|
||||
#undef kinematicsHome
|
||||
#undef kinematicsInverse
|
||||
#undef kinematicsForward
|
||||
#undef kinematicsType
|
||||
#undef hal_exit
|
||||
#undef hal_ready
|
||||
#undef hal_malloc
|
||||
#undef hal_init
|
||||
|
||||
int cnc_sim_linuxcnc_corexykins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_corexykins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_corexykins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_corexykins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
104
core/src/linuxcnc_corexykins_adapter.cpp
Normal file
104
core/src/linuxcnc_corexykins_adapter.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
#include "linuxcnc_corexykins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_corexykins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_corexykins_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.a;
|
||||
out[4] = joints.b;
|
||||
out[5] = joints.c;
|
||||
out[6] = joints.u;
|
||||
out[7] = joints.v;
|
||||
out[8] = joints.w;
|
||||
}
|
||||
|
||||
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.a = joints[3];
|
||||
out.b = joints[4];
|
||||
out.c = joints[5];
|
||||
out.u = joints[6];
|
||||
out.v = joints[7];
|
||||
out.w = joints[8];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_corexykins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose) {
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_corexykins_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_corexykins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints) {
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
if (cnc_sim_linuxcnc_corexykins_inverse(&in, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
6
core/src/linuxcnc_corexykins_adapter.h
Normal file
6
core/src/linuxcnc_corexykins_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_corexykins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose);
|
||||
bool linuxcnc_corexykins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints);
|
||||
117
core/src/linuxcnc_cubic_adapter.c
Normal file
117
core/src/linuxcnc_cubic_adapter.c
Normal file
@@ -0,0 +1,117 @@
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
|
||||
typedef struct {
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double d;
|
||||
} CUBIC_COEFF;
|
||||
|
||||
typedef struct {
|
||||
int configured;
|
||||
double segmentTime;
|
||||
int interpolationRate;
|
||||
double interpolationTime;
|
||||
double interpolationIncrement;
|
||||
double x0, x1, x2, x3;
|
||||
double wp0, wp1;
|
||||
double velp0, velp1;
|
||||
int filled;
|
||||
int needNextPoint;
|
||||
CUBIC_COEFF coeff;
|
||||
} CUBIC_STRUCT;
|
||||
|
||||
#define CUBIC_H
|
||||
#define cubicInit cnc_sim_cubic_cubicInit
|
||||
#define cubicSetSegmentTime cnc_sim_cubic_cubicSetSegmentTime
|
||||
#define cubicGetSegmentTime cnc_sim_cubic_cubicGetSegmentTime
|
||||
#define cubicSetInterpolationRate cnc_sim_cubic_cubicSetInterpolationRate
|
||||
#define cubicGetInterpolationRate cnc_sim_cubic_cubicGetInterpolationRate
|
||||
#define cubicAddPoint cnc_sim_cubic_cubicAddPoint
|
||||
#define cubicOffset cnc_sim_cubic_cubicOffset
|
||||
#define cubicGetInterpolationIncrement cnc_sim_cubic_cubicGetInterpolationIncrement
|
||||
#define cubicGetCubicCoeff cnc_sim_cubic_cubicGetCubicCoeff
|
||||
#define cubicFilled cnc_sim_cubic_cubicFilled
|
||||
#define cubicInterpolate cnc_sim_cubic_cubicInterpolate
|
||||
#define cubicNeedNextPoint cnc_sim_cubic_cubicNeedNextPoint
|
||||
#define cubicDrain cnc_sim_cubic_cubicDrain
|
||||
int cubicInit(CUBIC_STRUCT *ci);
|
||||
int cubicSetSegmentTime(CUBIC_STRUCT *ci, double time);
|
||||
double cubicGetSegmentTime(CUBIC_STRUCT *ci);
|
||||
int cubicSetInterpolationRate(CUBIC_STRUCT *ci, int rate);
|
||||
int cubicGetInterpolationRate(CUBIC_STRUCT *ci);
|
||||
int cubicAddPoint(CUBIC_STRUCT *ci, double point);
|
||||
int cubicOffset(CUBIC_STRUCT *ci, double offset);
|
||||
double cubicGetInterpolationIncrement(CUBIC_STRUCT *ci);
|
||||
CUBIC_COEFF cubicGetCubicCoeff(CUBIC_STRUCT *ci);
|
||||
int cubicFilled(CUBIC_STRUCT *ci);
|
||||
double cubicInterpolate(CUBIC_STRUCT *ci, double *x, double *v, double *a, double *j);
|
||||
int cubicNeedNextPoint(CUBIC_STRUCT *ci);
|
||||
int cubicDrain(CUBIC_STRUCT *ci);
|
||||
#include "../../../linuxcnc/src/emc/kinematics/cubic.c"
|
||||
#undef cubicDrain
|
||||
#undef cubicNeedNextPoint
|
||||
#undef cubicInterpolate
|
||||
#undef cubicFilled
|
||||
#undef cubicGetCubicCoeff
|
||||
#undef cubicGetInterpolationIncrement
|
||||
#undef cubicOffset
|
||||
#undef cubicAddPoint
|
||||
#undef cubicGetInterpolationRate
|
||||
#undef cubicSetInterpolationRate
|
||||
#undef cubicGetSegmentTime
|
||||
#undef cubicSetSegmentTime
|
||||
#undef cubicInit
|
||||
#undef CUBIC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int cnc_sim_linuxcnc_cubic_second_segment_samples(double *x,
|
||||
double *v,
|
||||
double *a,
|
||||
double *j,
|
||||
int sample_count) {
|
||||
if (!x || !v || !a || !j || sample_count != 4) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
CUBIC_STRUCT cubic;
|
||||
if (cnc_sim_cubic_cubicInit(&cubic) != 0 ||
|
||||
cnc_sim_cubic_cubicSetSegmentTime(&cubic, 1.0) != 0 ||
|
||||
cnc_sim_cubic_cubicSetInterpolationRate(&cubic, 4) != 0 ||
|
||||
cnc_sim_cubic_cubicAddPoint(&cubic, 0.0) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
cnc_sim_cubic_cubicInterpolate(&cubic, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
if (!cnc_sim_cubic_cubicNeedNextPoint(&cubic) ||
|
||||
cnc_sim_cubic_cubicAddPoint(&cubic, 10.0) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sample_count; ++i) {
|
||||
x[i] = cnc_sim_cubic_cubicInterpolate(&cubic, &x[i], &v[i], &a[i], &j[i]);
|
||||
}
|
||||
|
||||
return cnc_sim_cubic_cubicNeedNextPoint(&cubic) ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_cubic_rejects_invalid_configuration(void) {
|
||||
CUBIC_STRUCT cubic;
|
||||
return cnc_sim_cubic_cubicInit(&cubic) == 0 &&
|
||||
cnc_sim_cubic_cubicSetSegmentTime(&cubic, 0.0) != 0 &&
|
||||
cnc_sim_cubic_cubicSetInterpolationRate(&cubic, 0) != 0 &&
|
||||
cnc_sim_cubic_cubicAddPoint(&cubic, 1.0) != 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
36
core/src/linuxcnc_cubic_adapter.cpp
Normal file
36
core/src/linuxcnc_cubic_adapter.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "linuxcnc_cubic_adapter.h"
|
||||
|
||||
extern "C" {
|
||||
int cnc_sim_linuxcnc_cubic_second_segment_samples(double *x,
|
||||
double *v,
|
||||
double *a,
|
||||
double *j,
|
||||
int sample_count);
|
||||
int cnc_sim_linuxcnc_cubic_rejects_invalid_configuration(void);
|
||||
}
|
||||
|
||||
bool linuxcnc_cubic_source_second_segment_samples(LinuxCncCubicSample *samples, int sample_count) {
|
||||
if (!samples || sample_count != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double x[4] = {};
|
||||
double v[4] = {};
|
||||
double a[4] = {};
|
||||
double j[4] = {};
|
||||
if (cnc_sim_linuxcnc_cubic_second_segment_samples(x, v, a, j, sample_count) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sample_count; ++i) {
|
||||
samples[i].x = x[i];
|
||||
samples[i].v = v[i];
|
||||
samples[i].a = a[i];
|
||||
samples[i].j = j[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_cubic_source_rejects_invalid_configuration() {
|
||||
return cnc_sim_linuxcnc_cubic_rejects_invalid_configuration() != 0;
|
||||
}
|
||||
11
core/src/linuxcnc_cubic_adapter.h
Normal file
11
core/src/linuxcnc_cubic_adapter.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
struct LinuxCncCubicSample {
|
||||
double x;
|
||||
double v;
|
||||
double a;
|
||||
double j;
|
||||
};
|
||||
|
||||
bool linuxcnc_cubic_source_second_segment_samples(LinuxCncCubicSample *samples, int sample_count);
|
||||
bool linuxcnc_cubic_source_rejects_invalid_configuration();
|
||||
223
core/src/linuxcnc_genhexkins_adapter.c
Normal file
223
core/src/linuxcnc_genhexkins_adapter.c
Normal file
@@ -0,0 +1,223 @@
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_STRING_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_EMCMOTCFG_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
#define SWITCHKINS_H
|
||||
|
||||
#define RTAPI_MSG_ERR 1
|
||||
#define RTAPI_MSG_INFO 2
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef int hal_bit_t;
|
||||
typedef uint32_t hal_u32_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
#include "../../../linuxcnc/src/libnml/posemath/posemath.h"
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
typedef int (*KF)(const double *joint,
|
||||
EmcPose *pos,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags);
|
||||
typedef int (*KI)(const EmcPose *world,
|
||||
double *joint,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags);
|
||||
typedef int (*KS)(const int comp_id, const char *coordinates, kparms *ksetup_parms);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cnc_sim_genhex_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||
(void)level;
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void *cnc_sim_genhex_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_genhex_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||
hal_float_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_genhex_hal_pin_u32_newf(hal_pin_dir_t dir,
|
||||
hal_u32_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_u32_t *)calloc(1, sizeof(hal_u32_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_genhex_hal_pin_bit_newf(hal_pin_dir_t dir,
|
||||
hal_bit_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_bit_t *)calloc(1, sizeof(hal_bit_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_genhex_identityKinematicsSetup(const int comp_id, const char *coordinates, kparms *ksetup_parms) {
|
||||
(void)comp_id;
|
||||
(void)coordinates;
|
||||
(void)ksetup_parms;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnc_sim_genhex_identityKinematicsForward(const double *joint,
|
||||
EmcPose *world,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||
(void)joint;
|
||||
(void)world;
|
||||
(void)fflags;
|
||||
(void)iflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_genhex_identityKinematicsInverse(const EmcPose *world,
|
||||
double *joint,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||
(void)world;
|
||||
(void)joint;
|
||||
(void)iflags;
|
||||
(void)fflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_genhex_userkKinematicsSetup(const int comp_id, const char *coordinates, kparms *ksetup_parms) {
|
||||
(void)comp_id;
|
||||
(void)coordinates;
|
||||
(void)ksetup_parms;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_genhex_userkKinematicsForward(const double *joint,
|
||||
EmcPose *world,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||
(void)joint;
|
||||
(void)world;
|
||||
(void)fflags;
|
||||
(void)iflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_genhex_userkKinematicsInverse(const EmcPose *world,
|
||||
double *joint,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||
(void)world;
|
||||
(void)joint;
|
||||
(void)iflags;
|
||||
(void)fflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define rtapi_print_msg cnc_sim_genhex_rtapi_print_msg
|
||||
#define hal_pin_float_newf cnc_sim_genhex_hal_pin_float_newf
|
||||
#define hal_pin_u32_newf cnc_sim_genhex_hal_pin_u32_newf
|
||||
#define hal_pin_bit_newf cnc_sim_genhex_hal_pin_bit_newf
|
||||
#define identityKinematicsSetup cnc_sim_genhex_identityKinematicsSetup
|
||||
#define identityKinematicsForward cnc_sim_genhex_identityKinematicsForward
|
||||
#define identityKinematicsInverse cnc_sim_genhex_identityKinematicsInverse
|
||||
#define userkKinematicsSetup cnc_sim_genhex_userkKinematicsSetup
|
||||
#define userkKinematicsForward cnc_sim_genhex_userkKinematicsForward
|
||||
#define userkKinematicsInverse cnc_sim_genhex_userkKinematicsInverse
|
||||
#define switchkinsSetup cnc_sim_genhex_switchkinsSetup
|
||||
#define haldata cnc_sim_genhex_haldata
|
||||
#define hal_malloc(size) ((struct haldata *)cnc_sim_genhex_hal_malloc(size))
|
||||
#include "../../../linuxcnc/src/emc/kinematics/genhexkins.c"
|
||||
#undef hal_malloc
|
||||
#undef haldata
|
||||
#undef switchkinsSetup
|
||||
#undef userkKinematicsInverse
|
||||
#undef userkKinematicsForward
|
||||
#undef userkKinematicsSetup
|
||||
#undef identityKinematicsInverse
|
||||
#undef identityKinematicsForward
|
||||
#undef identityKinematicsSetup
|
||||
#undef hal_pin_bit_newf
|
||||
#undef hal_pin_u32_newf
|
||||
#undef hal_pin_float_newf
|
||||
#undef rtapi_print_msg
|
||||
|
||||
int cnc_sim_linuxcnc_genhexkins_setup(void) {
|
||||
kparms kp;
|
||||
memset(&kp, 0, sizeof(kp));
|
||||
static char kinsname[] = "genhexkins";
|
||||
static char halprefix[] = "genhexkins";
|
||||
kp.kinsname = kinsname;
|
||||
kp.halprefix = halprefix;
|
||||
kp.max_joints = NUM_STRUTS;
|
||||
return genhexKinematicsSetup(0, "XYZABC", &kp);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_genhexkins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return genhexKinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_genhexkins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return genhexKinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
96
core/src/linuxcnc_genhexkins_adapter.cpp
Normal file
96
core/src/linuxcnc_genhexkins_adapter.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#include "linuxcnc_genhexkins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_genhexkins_setup(void);
|
||||
int cnc_sim_linuxcnc_genhexkins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_genhexkins_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_genhexkins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_genhexkins_source_forward(const LinuxCncGenhexJoints &joints,
|
||||
const CncSimPose &initial_pose,
|
||||
CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
double raw_joints[6];
|
||||
std::memcpy(raw_joints, joints.strut, sizeof(raw_joints));
|
||||
EmcPose emc_pose = to_emc_pose(initial_pose);
|
||||
if (cnc_sim_linuxcnc_genhexkins_forward(raw_joints, &emc_pose) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(emc_pose);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_genhexkins_source_inverse(const CncSimPose &pose, LinuxCncGenhexJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
const EmcPose emc_pose = to_emc_pose(pose);
|
||||
double raw_joints[6] = {};
|
||||
if (cnc_sim_linuxcnc_genhexkins_inverse(&emc_pose, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
std::memcpy(joints->strut, raw_joints, sizeof(raw_joints));
|
||||
return true;
|
||||
}
|
||||
8
core/src/linuxcnc_genhexkins_adapter.h
Normal file
8
core/src/linuxcnc_genhexkins_adapter.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_genhexkins_source_forward(const LinuxCncGenhexJoints &joints,
|
||||
const CncSimPose &initial_pose,
|
||||
CncSimPose *pose);
|
||||
bool linuxcnc_genhexkins_source_inverse(const CncSimPose &pose, LinuxCncGenhexJoints *joints);
|
||||
206
core/src/linuxcnc_genserfuncs_adapter.c
Normal file
206
core/src/linuxcnc_genserfuncs_adapter.c
Normal file
@@ -0,0 +1,206 @@
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_STRING_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
|
||||
#define RTAPI_MSG_ERR 1
|
||||
#define PM_PI 3.1415926535897932384626433832795029
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef unsigned int hal_u32_t;
|
||||
typedef int hal_s32_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cnc_sim_genser_rtapi_print(const char *fmt, ...) {
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void cnc_sim_genser_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||
(void)level;
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void *cnc_sim_genser_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_genser_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||
hal_float_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_genser_hal_pin_u32_newf(hal_pin_dir_t dir,
|
||||
hal_u32_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_u32_t *)calloc(1, sizeof(hal_u32_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_genser_hal_pin_s32_newf(hal_pin_dir_t dir,
|
||||
hal_s32_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_s32_t *)calloc(1, sizeof(hal_s32_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
#define rtapi_print cnc_sim_genser_rtapi_print
|
||||
#define rtapi_print_msg cnc_sim_genser_rtapi_print_msg
|
||||
#define hal_pin_float_newf cnc_sim_genser_hal_pin_float_newf
|
||||
#define hal_pin_u32_newf cnc_sim_genser_hal_pin_u32_newf
|
||||
#define hal_pin_s32_newf cnc_sim_genser_hal_pin_s32_newf
|
||||
#define pm_sincos cnc_sim_genser_pm_sincos
|
||||
#include "../../../linuxcnc/src/libnml/posemath/sincos.c"
|
||||
#include "../../../linuxcnc/src/libnml/posemath/gomath.c"
|
||||
#define hal_malloc(size) cnc_sim_genser_hal_malloc(size)
|
||||
#include "../../../linuxcnc/src/emc/kinematics/genserfuncs.c"
|
||||
#undef hal_malloc
|
||||
#undef pm_sincos
|
||||
#undef hal_pin_s32_newf
|
||||
#undef hal_pin_u32_newf
|
||||
#undef hal_pin_float_newf
|
||||
#undef rtapi_print_msg
|
||||
#undef rtapi_print
|
||||
|
||||
int cnc_sim_linuxcnc_genserfuncs_setup(void) {
|
||||
kparms kp = {0};
|
||||
static char kinsname[] = "genserkins";
|
||||
static char halprefix[] = "genserkins";
|
||||
kp.kinsname = kinsname;
|
||||
kp.halprefix = halprefix;
|
||||
kp.max_joints = 6;
|
||||
return genserKinematicsSetup(0, "XYZABC", &kp);
|
||||
}
|
||||
|
||||
void cnc_sim_linuxcnc_genserfuncs_set_parameters(const double *a,
|
||||
const double *alpha,
|
||||
const double *d,
|
||||
const int *unrotate,
|
||||
int max_iterations) {
|
||||
for (int i = 0; i < GENSER_MAX_JOINTS; ++i) {
|
||||
*haldata->a[i] = a[i];
|
||||
*haldata->alpha[i] = alpha[i];
|
||||
*haldata->d[i] = d[i];
|
||||
*haldata->unrotate[i] = unrotate[i];
|
||||
}
|
||||
*haldata->max_iterations = (hal_u32_t)max_iterations;
|
||||
}
|
||||
|
||||
void cnc_sim_linuxcnc_genserfuncs_default_parameters(double *a,
|
||||
double *alpha,
|
||||
double *d,
|
||||
int *unrotate,
|
||||
int *max_iterations) {
|
||||
const double default_a[GENSER_MAX_JOINTS] = {
|
||||
DEFAULT_A1,
|
||||
DEFAULT_A2,
|
||||
DEFAULT_A3,
|
||||
DEFAULT_A4,
|
||||
DEFAULT_A5,
|
||||
DEFAULT_A6,
|
||||
};
|
||||
const double default_alpha[GENSER_MAX_JOINTS] = {
|
||||
DEFAULT_ALPHA1,
|
||||
DEFAULT_ALPHA2,
|
||||
DEFAULT_ALPHA3,
|
||||
DEFAULT_ALPHA4,
|
||||
DEFAULT_ALPHA5,
|
||||
DEFAULT_ALPHA6,
|
||||
};
|
||||
const double default_d[GENSER_MAX_JOINTS] = {
|
||||
DEFAULT_D1,
|
||||
DEFAULT_D2,
|
||||
DEFAULT_D3,
|
||||
DEFAULT_D4,
|
||||
DEFAULT_D5,
|
||||
DEFAULT_D6,
|
||||
};
|
||||
|
||||
for (int i = 0; i < GENSER_MAX_JOINTS; ++i) {
|
||||
a[i] = default_a[i];
|
||||
alpha[i] = default_alpha[i];
|
||||
d[i] = default_d[i];
|
||||
unrotate[i] = 0;
|
||||
}
|
||||
*max_iterations = GENSER_DEFAULT_MAX_ITERATIONS;
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_genserfuncs_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return genserKinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_genserfuncs_inverse(const EmcPose *pos, double *joints, int *iterations) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
const int result = genserKinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
if (iterations) {
|
||||
*iterations = genser_kin_inv_iterations(KINS_PTR);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
166
core/src/linuxcnc_genserfuncs_adapter.cpp
Normal file
166
core/src/linuxcnc_genserfuncs_adapter.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "linuxcnc_genserfuncs_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_genserfuncs_setup(void);
|
||||
void cnc_sim_linuxcnc_genserfuncs_set_parameters(const double *a,
|
||||
const double *alpha,
|
||||
const double *d,
|
||||
const int *unrotate,
|
||||
int max_iterations);
|
||||
void cnc_sim_linuxcnc_genserfuncs_default_parameters(double *a,
|
||||
double *alpha,
|
||||
double *d,
|
||||
int *unrotate,
|
||||
int *max_iterations);
|
||||
int cnc_sim_linuxcnc_genserfuncs_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_genserfuncs_inverse(const EmcPose *pos, double *joints, int *iterations);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_genserfuncs_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void apply_parameters(const LinuxCncGenserParameters ¶meters, int max_iterations) {
|
||||
cnc_sim_linuxcnc_genserfuncs_set_parameters(parameters.a,
|
||||
parameters.alpha,
|
||||
parameters.d,
|
||||
parameters.unrotate,
|
||||
max_iterations);
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.a;
|
||||
out[4] = joints.b;
|
||||
out[5] = joints.c;
|
||||
out[6] = joints.u;
|
||||
out[7] = joints.v;
|
||||
out[8] = joints.w;
|
||||
}
|
||||
|
||||
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.a = joints[3];
|
||||
out.b = joints[4];
|
||||
out.c = joints[5];
|
||||
out.u = joints[6];
|
||||
out.v = joints[7];
|
||||
out.w = joints[8];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_genserfuncs_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncGenserParameters ¶meters,
|
||||
CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
apply_parameters(parameters, 100);
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_genserfuncs_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_genserfuncs_source_default_parameters(LinuxCncGenserParameters *parameters,
|
||||
int *max_iterations) {
|
||||
if (!parameters) {
|
||||
return false;
|
||||
}
|
||||
int raw_max_iterations = 0;
|
||||
cnc_sim_linuxcnc_genserfuncs_default_parameters(parameters->a,
|
||||
parameters->alpha,
|
||||
parameters->d,
|
||||
parameters->unrotate,
|
||||
&raw_max_iterations);
|
||||
if (max_iterations) {
|
||||
*max_iterations = raw_max_iterations;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_genserfuncs_inverse(const CncSimPose &pose,
|
||||
const LinuxCncAxisJoints &joint_estimate,
|
||||
const LinuxCncGenserParameters ¶meters,
|
||||
int max_iterations,
|
||||
LinuxCncAxisJoints *joints,
|
||||
int *iterations) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
apply_parameters(parameters, max_iterations);
|
||||
double raw_joints[16];
|
||||
to_joints(joint_estimate, raw_joints);
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
if (cnc_sim_linuxcnc_genserfuncs_inverse(&in, raw_joints, iterations) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
15
core/src/linuxcnc_genserfuncs_adapter.h
Normal file
15
core/src/linuxcnc_genserfuncs_adapter.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_genserfuncs_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncGenserParameters ¶meters,
|
||||
CncSimPose *pose);
|
||||
bool linuxcnc_genserfuncs_source_default_parameters(LinuxCncGenserParameters *parameters,
|
||||
int *max_iterations);
|
||||
bool linuxcnc_genserfuncs_inverse(const CncSimPose &pose,
|
||||
const LinuxCncAxisJoints &joint_estimate,
|
||||
const LinuxCncGenserParameters ¶meters,
|
||||
int max_iterations,
|
||||
LinuxCncAxisJoints *joints,
|
||||
int *iterations);
|
||||
116
core/src/linuxcnc_kins_util_adapter.c
Normal file
116
core/src/linuxcnc_kins_util_adapter.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_STRING_H
|
||||
#define __LINUXCNC_EMCMOTCFG_H
|
||||
#define __LINUXCNC_EMCPOS_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
|
||||
#define RTAPI_MSG_ERR 1
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
#define EMCMOT_MAX_AXIS 9
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cnc_sim_kins_util_rtapi_print(const char *fmt, ...) {
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void cnc_sim_kins_util_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||
(void)level;
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
KINEMATICS_TYPE kinematicsType(void) {
|
||||
return KINEMATICS_BOTH;
|
||||
}
|
||||
|
||||
#define rtapi_print cnc_sim_kins_util_rtapi_print
|
||||
#define rtapi_print_msg cnc_sim_kins_util_rtapi_print_msg
|
||||
#define map_coordinates_to_jnumbers cnc_sim_kins_util_map_coordinates_to_jnumbers
|
||||
#define mapped_joints_to_position cnc_sim_kins_util_mapped_joints_to_position
|
||||
#define position_to_mapped_joints cnc_sim_kins_util_position_to_mapped_joints
|
||||
#define identityKinematicsSetup cnc_sim_kins_util_identityKinematicsSetup
|
||||
#define identityKinematicsForward cnc_sim_kins_util_identityKinematicsForward
|
||||
#define identityKinematicsInverse cnc_sim_kins_util_identityKinematicsInverse
|
||||
#include "../../../linuxcnc/src/emc/kinematics/kins_util.c"
|
||||
#undef identityKinematicsInverse
|
||||
#undef identityKinematicsForward
|
||||
#undef identityKinematicsSetup
|
||||
#undef position_to_mapped_joints
|
||||
#undef mapped_joints_to_position
|
||||
#undef map_coordinates_to_jnumbers
|
||||
#undef rtapi_print_msg
|
||||
#undef rtapi_print
|
||||
|
||||
int cnc_sim_linuxcnc_kins_util_setup(void) {
|
||||
kparms kp = {0};
|
||||
static char kinsname[] = "kins_util_identity";
|
||||
static char halprefix[] = "identity";
|
||||
kp.kinsname = kinsname;
|
||||
kp.halprefix = halprefix;
|
||||
kp.max_joints = EMCMOT_MAX_JOINTS;
|
||||
kp.allow_duplicates = 0;
|
||||
return cnc_sim_kins_util_identityKinematicsSetup(0, "XYZABCUVW", &kp);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_kins_util_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_kins_util_identityKinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_kins_util_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_kins_util_identityKinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
121
core/src/linuxcnc_kins_util_adapter.cpp
Normal file
121
core/src/linuxcnc_kins_util_adapter.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
#include "linuxcnc_kins_util_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_kins_util_setup(void);
|
||||
int cnc_sim_linuxcnc_kins_util_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_kins_util_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_kins_util_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.a;
|
||||
out[4] = joints.b;
|
||||
out[5] = joints.c;
|
||||
out[6] = joints.u;
|
||||
out[7] = joints.v;
|
||||
out[8] = joints.w;
|
||||
}
|
||||
|
||||
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.a = joints[3];
|
||||
out.b = joints[4];
|
||||
out.c = joints[5];
|
||||
out.u = joints[6];
|
||||
out.v = joints[7];
|
||||
out.w = joints[8];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_kins_util_identity_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_kins_util_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_kins_util_identity_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
if (cnc_sim_linuxcnc_kins_util_inverse(&in, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
6
core/src/linuxcnc_kins_util_adapter.h
Normal file
6
core/src/linuxcnc_kins_util_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_kins_util_identity_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose);
|
||||
bool linuxcnc_kins_util_identity_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints);
|
||||
155
core/src/linuxcnc_lineardeltakins_adapter.c
Normal file
155
core/src/linuxcnc_lineardeltakins_adapter.c
Normal file
@@ -0,0 +1,155 @@
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_APP_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
#define __LINUXCNC_EMCPOS_H
|
||||
|
||||
#define MODULE_LICENSE(...)
|
||||
#define EXPORT_SYMBOL(symbol)
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#define KINS_NOT_SWITCHABLE \
|
||||
extern int kinematicsSwitchable() { return 0; } \
|
||||
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int cnc_sim_lineardelta_hal_init(const char *name) {
|
||||
(void)name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *cnc_sim_lineardelta_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_lineardelta_hal_ready(int comp_id) {
|
||||
(void)comp_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnc_sim_lineardelta_hal_exit(int comp_id) {
|
||||
(void)comp_id;
|
||||
}
|
||||
|
||||
int cnc_sim_lineardelta_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||
hal_float_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
#define hal_init cnc_sim_lineardelta_hal_init
|
||||
#define hal_malloc(size) ((struct haldata *)cnc_sim_lineardelta_hal_malloc(size))
|
||||
#define hal_pin_float_newf cnc_sim_lineardelta_hal_pin_float_newf
|
||||
#define hal_ready cnc_sim_lineardelta_hal_ready
|
||||
#define hal_exit cnc_sim_lineardelta_hal_exit
|
||||
#define kinematicsType cnc_sim_lineardelta_kinematicsType
|
||||
#define kinematicsForward cnc_sim_lineardelta_kinematicsForward
|
||||
#define kinematicsInverse cnc_sim_lineardelta_kinematicsInverse
|
||||
#define kinematicsSwitchable cnc_sim_lineardelta_kinematicsSwitchable
|
||||
#define kinematicsSwitch cnc_sim_lineardelta_kinematicsSwitch
|
||||
#define rtapi_app_main cnc_sim_lineardelta_rtapi_app_main
|
||||
#define rtapi_app_exit cnc_sim_lineardelta_rtapi_app_exit
|
||||
#define comp_id cnc_sim_lineardelta_comp_id
|
||||
#define haldata cnc_sim_lineardelta_haldata
|
||||
#include "../../../linuxcnc/src/emc/kinematics/lineardeltakins.c"
|
||||
#undef haldata
|
||||
#undef comp_id
|
||||
#undef rtapi_app_exit
|
||||
#undef rtapi_app_main
|
||||
#undef kinematicsSwitch
|
||||
#undef kinematicsSwitchable
|
||||
#undef kinematicsInverse
|
||||
#undef kinematicsForward
|
||||
#undef kinematicsType
|
||||
#undef hal_exit
|
||||
#undef hal_ready
|
||||
#undef hal_pin_float_newf
|
||||
#undef hal_malloc
|
||||
#undef hal_init
|
||||
|
||||
int cnc_sim_linuxcnc_lineardeltakins_setup(void) {
|
||||
return cnc_sim_lineardelta_rtapi_app_main();
|
||||
}
|
||||
|
||||
void cnc_sim_linuxcnc_lineardeltakins_default_parameters(double *r, double *l) {
|
||||
*r = DELTA_RADIUS;
|
||||
*l = DELTA_DIAGONAL_ROD;
|
||||
}
|
||||
|
||||
void cnc_sim_linuxcnc_lineardeltakins_set_parameters(double r, double l) {
|
||||
*cnc_sim_lineardelta_haldata->r = r;
|
||||
*cnc_sim_lineardelta_haldata->l = l;
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_lineardeltakins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_lineardelta_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_lineardeltakins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_lineardelta_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
138
core/src/linuxcnc_lineardeltakins_adapter.cpp
Normal file
138
core/src/linuxcnc_lineardeltakins_adapter.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#include "linuxcnc_lineardeltakins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_lineardeltakins_setup(void);
|
||||
void cnc_sim_linuxcnc_lineardeltakins_default_parameters(double *r, double *l);
|
||||
void cnc_sim_linuxcnc_lineardeltakins_set_parameters(double r, double l);
|
||||
int cnc_sim_linuxcnc_lineardeltakins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_lineardeltakins_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_lineardeltakins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.a;
|
||||
out[4] = joints.b;
|
||||
out[5] = joints.c;
|
||||
out[6] = joints.u;
|
||||
out[7] = joints.v;
|
||||
out[8] = joints.w;
|
||||
}
|
||||
|
||||
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.a = joints[3];
|
||||
out.b = joints[4];
|
||||
out.c = joints[5];
|
||||
out.u = joints[6];
|
||||
out.v = joints[7];
|
||||
out.w = joints[8];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_lineardeltakins_source_default_parameters(LinuxCncLinearDeltaParameters *parameters) {
|
||||
double r = 0.0;
|
||||
double l = 0.0;
|
||||
cnc_sim_linuxcnc_lineardeltakins_default_parameters(&r, &l);
|
||||
parameters->r = r;
|
||||
parameters->l = l;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_lineardeltakins_source_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncLinearDeltaParameters ¶meters,
|
||||
CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
cnc_sim_linuxcnc_lineardeltakins_set_parameters(parameters.r, parameters.l);
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_lineardeltakins_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_lineardeltakins_source_inverse(const CncSimPose &pose,
|
||||
const LinuxCncLinearDeltaParameters ¶meters,
|
||||
LinuxCncAxisJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
cnc_sim_linuxcnc_lineardeltakins_set_parameters(parameters.r, parameters.l);
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
if (cnc_sim_linuxcnc_lineardeltakins_inverse(&in, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
11
core/src/linuxcnc_lineardeltakins_adapter.h
Normal file
11
core/src/linuxcnc_lineardeltakins_adapter.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_lineardeltakins_source_default_parameters(LinuxCncLinearDeltaParameters *parameters);
|
||||
bool linuxcnc_lineardeltakins_source_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncLinearDeltaParameters ¶meters,
|
||||
CncSimPose *pose);
|
||||
bool linuxcnc_lineardeltakins_source_inverse(const CncSimPose &pose,
|
||||
const LinuxCncLinearDeltaParameters ¶meters,
|
||||
LinuxCncAxisJoints *joints);
|
||||
168
core/src/linuxcnc_maxkins_adapter.c
Normal file
168
core/src/linuxcnc_maxkins_adapter.c
Normal file
@@ -0,0 +1,168 @@
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_APP_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
#define __LINUXCNC_EMCPOS_H
|
||||
|
||||
#define MODULE_LICENSE(...)
|
||||
#define EXPORT_SYMBOL(symbol)
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
#define PM_PI 3.1415926535897932384626433832795029
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef bool hal_bit_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#define KINS_NOT_SWITCHABLE \
|
||||
extern int kinematicsSwitchable() { return 0; } \
|
||||
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int cnc_sim_maxkins_hal_init(const char *name) {
|
||||
(void)name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *cnc_sim_maxkins_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_maxkins_hal_ready(int comp_id) {
|
||||
(void)comp_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnc_sim_maxkins_hal_exit(int comp_id) {
|
||||
(void)comp_id;
|
||||
}
|
||||
|
||||
int cnc_sim_maxkins_hal_pin_float_new(const char *name,
|
||||
hal_pin_dir_t dir,
|
||||
hal_float_t **data_ptr_addr,
|
||||
int comp_id) {
|
||||
(void)name;
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_maxkins_hal_pin_bit_new(const char *name,
|
||||
hal_pin_dir_t dir,
|
||||
hal_bit_t **data_ptr_addr,
|
||||
int comp_id) {
|
||||
(void)name;
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
*data_ptr_addr = (hal_bit_t *)calloc(1, sizeof(hal_bit_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
#define hal_init cnc_sim_maxkins_hal_init
|
||||
#define hal_malloc(size) ((struct haldata *)cnc_sim_maxkins_hal_malloc(size))
|
||||
#define hal_pin_float_new cnc_sim_maxkins_hal_pin_float_new
|
||||
#define hal_pin_bit_new cnc_sim_maxkins_hal_pin_bit_new
|
||||
#define hal_ready cnc_sim_maxkins_hal_ready
|
||||
#define hal_exit cnc_sim_maxkins_hal_exit
|
||||
#define kinematicsType cnc_sim_maxkins_kinematicsType
|
||||
#define kinematicsForward cnc_sim_maxkins_kinematicsForward
|
||||
#define kinematicsInverse cnc_sim_maxkins_kinematicsInverse
|
||||
#define kinematicsSwitchable cnc_sim_maxkins_kinematicsSwitchable
|
||||
#define kinematicsSwitch cnc_sim_maxkins_kinematicsSwitch
|
||||
#define rtapi_app_main cnc_sim_maxkins_rtapi_app_main
|
||||
#define rtapi_app_exit cnc_sim_maxkins_rtapi_app_exit
|
||||
#define comp_id cnc_sim_maxkins_comp_id
|
||||
#define haldata cnc_sim_maxkins_haldata
|
||||
#include "../../../linuxcnc/src/emc/kinematics/maxkins.c"
|
||||
#undef haldata
|
||||
#undef comp_id
|
||||
#undef rtapi_app_exit
|
||||
#undef rtapi_app_main
|
||||
#undef kinematicsSwitch
|
||||
#undef kinematicsSwitchable
|
||||
#undef kinematicsInverse
|
||||
#undef kinematicsForward
|
||||
#undef kinematicsType
|
||||
#undef hal_exit
|
||||
#undef hal_ready
|
||||
#undef hal_pin_bit_new
|
||||
#undef hal_pin_float_new
|
||||
#undef hal_malloc
|
||||
#undef hal_init
|
||||
|
||||
int cnc_sim_linuxcnc_maxkins_setup(void) {
|
||||
return cnc_sim_maxkins_rtapi_app_main();
|
||||
}
|
||||
|
||||
void cnc_sim_linuxcnc_maxkins_default_parameters(double *pivot_length, int *conventional_directions) {
|
||||
*pivot_length = 0.666;
|
||||
*conventional_directions = 0;
|
||||
}
|
||||
|
||||
void cnc_sim_linuxcnc_maxkins_set_parameters(double pivot_length, int conventional_directions) {
|
||||
*cnc_sim_maxkins_haldata->pivot_length = pivot_length;
|
||||
*cnc_sim_maxkins_haldata->conventional_directions = conventional_directions != 0;
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_maxkins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_maxkins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_maxkins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_maxkins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
140
core/src/linuxcnc_maxkins_adapter.cpp
Normal file
140
core/src/linuxcnc_maxkins_adapter.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
#include "linuxcnc_maxkins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_maxkins_setup(void);
|
||||
void cnc_sim_linuxcnc_maxkins_default_parameters(double *pivot_length, int *conventional_directions);
|
||||
void cnc_sim_linuxcnc_maxkins_set_parameters(double pivot_length, int conventional_directions);
|
||||
int cnc_sim_linuxcnc_maxkins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_maxkins_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_maxkins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.a;
|
||||
out[4] = joints.b;
|
||||
out[5] = joints.c;
|
||||
out[6] = joints.u;
|
||||
out[7] = joints.v;
|
||||
out[8] = joints.w;
|
||||
}
|
||||
|
||||
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.a = joints[3];
|
||||
out.b = joints[4];
|
||||
out.c = joints[5];
|
||||
out.u = joints[6];
|
||||
out.v = joints[7];
|
||||
out.w = joints[8];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_maxkins_source_default_parameters(LinuxCncMaxkinsParameters *parameters) {
|
||||
double pivot_length = 0.0;
|
||||
int conventional_directions = 0;
|
||||
cnc_sim_linuxcnc_maxkins_default_parameters(&pivot_length, &conventional_directions);
|
||||
parameters->pivot_length = pivot_length;
|
||||
parameters->conventional_directions = conventional_directions != 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_maxkins_source_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncMaxkinsParameters ¶meters,
|
||||
CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
cnc_sim_linuxcnc_maxkins_set_parameters(parameters.pivot_length,
|
||||
parameters.conventional_directions ? 1 : 0);
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_maxkins_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_maxkins_source_inverse(const CncSimPose &pose,
|
||||
const LinuxCncMaxkinsParameters ¶meters,
|
||||
LinuxCncAxisJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
cnc_sim_linuxcnc_maxkins_set_parameters(parameters.pivot_length,
|
||||
parameters.conventional_directions ? 1 : 0);
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
if (cnc_sim_linuxcnc_maxkins_inverse(&in, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
11
core/src/linuxcnc_maxkins_adapter.h
Normal file
11
core/src/linuxcnc_maxkins_adapter.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_maxkins_source_default_parameters(LinuxCncMaxkinsParameters *parameters);
|
||||
bool linuxcnc_maxkins_source_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncMaxkinsParameters ¶meters,
|
||||
CncSimPose *pose);
|
||||
bool linuxcnc_maxkins_source_inverse(const CncSimPose &pose,
|
||||
const LinuxCncMaxkinsParameters ¶meters,
|
||||
LinuxCncAxisJoints *joints);
|
||||
172
core/src/linuxcnc_pentakins_adapter.c
Normal file
172
core/src/linuxcnc_pentakins_adapter.c
Normal file
@@ -0,0 +1,172 @@
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_APP_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
#define __LINUXCNC_EMCPOS_H
|
||||
|
||||
#define MODULE_LICENSE(...)
|
||||
#define EXPORT_SYMBOL(symbol)
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef uint32_t hal_u32_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
typedef enum { HAL_RO = 64, HAL_RW = (HAL_RO | 128) } hal_param_dir_t;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
#include "../../../linuxcnc/src/libnml/posemath/posemath.h"
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#define KINS_NOT_SWITCHABLE \
|
||||
extern int kinematicsSwitchable() { return 0; } \
|
||||
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int cnc_sim_pentakins_hal_init(const char *name) {
|
||||
(void)name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *cnc_sim_pentakins_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_pentakins_hal_ready(int comp_id) {
|
||||
(void)comp_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnc_sim_pentakins_hal_exit(int comp_id) {
|
||||
(void)comp_id;
|
||||
}
|
||||
|
||||
int cnc_sim_pentakins_hal_param_float_newf(hal_param_dir_t dir,
|
||||
hal_float_t *data_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)data_addr;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnc_sim_pentakins_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||
hal_float_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_pentakins_hal_pin_u32_newf(hal_pin_dir_t dir,
|
||||
hal_u32_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_u32_t *)calloc(1, sizeof(hal_u32_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
#define hal_init cnc_sim_pentakins_hal_init
|
||||
#define hal_malloc(size) ((struct haldata *)cnc_sim_pentakins_hal_malloc(size))
|
||||
#define hal_param_float_newf cnc_sim_pentakins_hal_param_float_newf
|
||||
#define hal_pin_float_newf cnc_sim_pentakins_hal_pin_float_newf
|
||||
#define hal_pin_u32_newf cnc_sim_pentakins_hal_pin_u32_newf
|
||||
#define hal_ready cnc_sim_pentakins_hal_ready
|
||||
#define hal_exit cnc_sim_pentakins_hal_exit
|
||||
#define kinematicsType cnc_sim_pentakins_kinematicsType
|
||||
#define kinematicsForward cnc_sim_pentakins_kinematicsForward
|
||||
#define kinematicsInverse cnc_sim_pentakins_kinematicsInverse
|
||||
#define kinematicsSwitchable cnc_sim_pentakins_kinematicsSwitchable
|
||||
#define kinematicsSwitch cnc_sim_pentakins_kinematicsSwitch
|
||||
#define rtapi_app_main cnc_sim_pentakins_rtapi_app_main
|
||||
#define rtapi_app_exit cnc_sim_pentakins_rtapi_app_exit
|
||||
#define comp_id cnc_sim_pentakins_comp_id
|
||||
#define haldata cnc_sim_pentakins_haldata
|
||||
#include "../../../linuxcnc/src/emc/kinematics/pentakins.c"
|
||||
#undef haldata
|
||||
#undef comp_id
|
||||
#undef rtapi_app_exit
|
||||
#undef rtapi_app_main
|
||||
#undef kinematicsSwitch
|
||||
#undef kinematicsSwitchable
|
||||
#undef kinematicsInverse
|
||||
#undef kinematicsForward
|
||||
#undef kinematicsType
|
||||
#undef hal_exit
|
||||
#undef hal_ready
|
||||
#undef hal_pin_u32_newf
|
||||
#undef hal_pin_float_newf
|
||||
#undef hal_param_float_newf
|
||||
#undef hal_malloc
|
||||
#undef hal_init
|
||||
|
||||
int cnc_sim_linuxcnc_pentakins_setup(void) {
|
||||
return cnc_sim_pentakins_rtapi_app_main();
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_pentakins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_pentakins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_pentakins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_pentakins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
97
core/src/linuxcnc_pentakins_adapter.cpp
Normal file
97
core/src/linuxcnc_pentakins_adapter.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "linuxcnc_pentakins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_pentakins_setup(void);
|
||||
int cnc_sim_linuxcnc_pentakins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_pentakins_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_pentakins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_pentakins_source_forward(const LinuxCncPentakinsJoints &joints,
|
||||
const CncSimPose &initial_pose,
|
||||
CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
double raw_joints[5];
|
||||
std::memcpy(raw_joints, joints.strut, sizeof(raw_joints));
|
||||
EmcPose emc_pose = to_emc_pose(initial_pose);
|
||||
if (cnc_sim_linuxcnc_pentakins_forward(raw_joints, &emc_pose) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(emc_pose);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_pentakins_source_inverse(const CncSimPose &pose,
|
||||
LinuxCncPentakinsJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
const EmcPose emc_pose = to_emc_pose(pose);
|
||||
double raw_joints[5] = {};
|
||||
if (cnc_sim_linuxcnc_pentakins_inverse(&emc_pose, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
std::memcpy(joints->strut, raw_joints, sizeof(raw_joints));
|
||||
return true;
|
||||
}
|
||||
9
core/src/linuxcnc_pentakins_adapter.h
Normal file
9
core/src/linuxcnc_pentakins_adapter.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_pentakins_source_forward(const LinuxCncPentakinsJoints &joints,
|
||||
const CncSimPose &initial_pose,
|
||||
CncSimPose *pose);
|
||||
bool linuxcnc_pentakins_source_inverse(const CncSimPose &pose,
|
||||
LinuxCncPentakinsJoints *joints);
|
||||
218
core/src/linuxcnc_pumakins_adapter.c
Normal file
218
core/src/linuxcnc_pumakins_adapter.c
Normal file
@@ -0,0 +1,218 @@
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_STRING_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
#define SWITCHKINS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define CNC_SIM_EXTERN_C extern "C"
|
||||
#else
|
||||
#define CNC_SIM_EXTERN_C
|
||||
#endif
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef int hal_s32_t;
|
||||
typedef bool hal_bit_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
#include "../../../linuxcnc/src/libnml/posemath/sincos.c"
|
||||
#include "../../../linuxcnc/src/libnml/posemath/_posemath.c"
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
typedef int (*KF)(const double *joint,
|
||||
EmcPose *pos,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags);
|
||||
typedef int (*KI)(const EmcPose *world,
|
||||
double *joint,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags);
|
||||
typedef int (*KS)(const int comp_id, const char *coordinates, kparms *ksetup_parms);
|
||||
|
||||
void cnc_sim_puma_rtapi_print(const char *fmt, ...) {
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void cnc_sim_puma_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||
(void)level;
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void *cnc_sim_puma_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_puma_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||
hal_float_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_puma_identityKinematicsSetup(const int comp_id, const char *coordinates, kparms *ksetup_parms) {
|
||||
(void)comp_id;
|
||||
(void)coordinates;
|
||||
(void)ksetup_parms;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnc_sim_puma_identityKinematicsForward(const double *joint,
|
||||
EmcPose *world,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||
(void)joint;
|
||||
(void)world;
|
||||
(void)fflags;
|
||||
(void)iflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_puma_identityKinematicsInverse(const EmcPose *world,
|
||||
double *joint,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||
(void)world;
|
||||
(void)joint;
|
||||
(void)iflags;
|
||||
(void)fflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_puma_userkKinematicsSetup(const int comp_id, const char *coordinates, kparms *ksetup_parms) {
|
||||
(void)comp_id;
|
||||
(void)coordinates;
|
||||
(void)ksetup_parms;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_puma_userkKinematicsForward(const double *joint,
|
||||
EmcPose *world,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||
(void)joint;
|
||||
(void)world;
|
||||
(void)fflags;
|
||||
(void)iflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_puma_userkKinematicsInverse(const EmcPose *world,
|
||||
double *joint,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||
(void)world;
|
||||
(void)joint;
|
||||
(void)iflags;
|
||||
(void)fflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define rtapi_print cnc_sim_puma_rtapi_print
|
||||
#define rtapi_print_msg cnc_sim_puma_rtapi_print_msg
|
||||
#define hal_pin_float_newf cnc_sim_puma_hal_pin_float_newf
|
||||
#define identityKinematicsSetup cnc_sim_puma_identityKinematicsSetup
|
||||
#define identityKinematicsForward cnc_sim_puma_identityKinematicsForward
|
||||
#define identityKinematicsInverse cnc_sim_puma_identityKinematicsInverse
|
||||
#define userkKinematicsSetup cnc_sim_puma_userkKinematicsSetup
|
||||
#define userkKinematicsForward cnc_sim_puma_userkKinematicsForward
|
||||
#define userkKinematicsInverse cnc_sim_puma_userkKinematicsInverse
|
||||
#define switchkinsSetup cnc_sim_puma_switchkinsSetup
|
||||
#define haldata cnc_sim_puma_haldata
|
||||
#define hal_malloc(size) ((struct haldata *)cnc_sim_puma_hal_malloc(size))
|
||||
#include "../../../linuxcnc/src/emc/kinematics/pumakins.c"
|
||||
#undef hal_malloc
|
||||
#undef haldata
|
||||
#undef switchkinsSetup
|
||||
#undef userkKinematicsInverse
|
||||
#undef userkKinematicsForward
|
||||
#undef userkKinematicsSetup
|
||||
#undef identityKinematicsInverse
|
||||
#undef identityKinematicsForward
|
||||
#undef identityKinematicsSetup
|
||||
#undef hal_pin_float_newf
|
||||
#undef rtapi_print_msg
|
||||
#undef rtapi_print
|
||||
|
||||
CNC_SIM_EXTERN_C int cnc_sim_linuxcnc_pumakins_setup(void) {
|
||||
kparms kp = {0};
|
||||
static char kinsname[] = "pumakins";
|
||||
static char halprefix[] = "pumakins";
|
||||
kp.kinsname = kinsname;
|
||||
kp.halprefix = halprefix;
|
||||
return pumaKinematicsSetup(0, "XYZABC", &kp);
|
||||
}
|
||||
|
||||
CNC_SIM_EXTERN_C void cnc_sim_linuxcnc_pumakins_set_parameters(double a2,
|
||||
double a3,
|
||||
double d3,
|
||||
double d4,
|
||||
double d6) {
|
||||
*cnc_sim_puma_haldata->a2 = a2;
|
||||
*cnc_sim_puma_haldata->a3 = a3;
|
||||
*cnc_sim_puma_haldata->d3 = d3;
|
||||
*cnc_sim_puma_haldata->d4 = d4;
|
||||
*cnc_sim_puma_haldata->d6 = d6;
|
||||
}
|
||||
|
||||
CNC_SIM_EXTERN_C int cnc_sim_linuxcnc_pumakins_forward(const double *joints,
|
||||
struct EmcPose *pos,
|
||||
int *iflags) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS raw_iflags = 0;
|
||||
const int result = pumaKinematicsForward(joints, pos, &fflags, &raw_iflags);
|
||||
if (iflags) {
|
||||
*iflags = (int)raw_iflags;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CNC_SIM_EXTERN_C int cnc_sim_linuxcnc_pumakins_inverse(const struct EmcPose *pos,
|
||||
double *joints,
|
||||
int iflags,
|
||||
int *fflags) {
|
||||
KINEMATICS_INVERSE_FLAGS raw_iflags = (KINEMATICS_INVERSE_FLAGS)iflags;
|
||||
KINEMATICS_FORWARD_FLAGS raw_fflags = 0;
|
||||
const int result = pumaKinematicsInverse(pos, joints, &raw_iflags, &raw_fflags);
|
||||
if (fflags) {
|
||||
*fflags = (int)raw_fflags;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
156
core/src/linuxcnc_pumakins_adapter.cpp
Normal file
156
core/src/linuxcnc_pumakins_adapter.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "linuxcnc_pumakins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_pumakins_setup(void);
|
||||
void cnc_sim_linuxcnc_pumakins_set_parameters(double a2,
|
||||
double a3,
|
||||
double d3,
|
||||
double d4,
|
||||
double d6);
|
||||
int cnc_sim_linuxcnc_pumakins_forward(const double *joints, EmcPose *pos, int *iflags);
|
||||
int cnc_sim_linuxcnc_pumakins_inverse(const EmcPose *pos,
|
||||
double *joints,
|
||||
int iflags,
|
||||
int *fflags);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_pumakins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void apply_parameters(const LinuxCncPumaParameters ¶meters) {
|
||||
cnc_sim_linuxcnc_pumakins_set_parameters(parameters.a2,
|
||||
parameters.a3,
|
||||
parameters.d3,
|
||||
parameters.d4,
|
||||
parameters.d6);
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.a;
|
||||
out[4] = joints.b;
|
||||
out[5] = joints.c;
|
||||
out[6] = joints.u;
|
||||
out[7] = joints.v;
|
||||
out[8] = joints.w;
|
||||
}
|
||||
|
||||
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.a = joints[3];
|
||||
out.b = joints[4];
|
||||
out.c = joints[5];
|
||||
out.u = joints[6];
|
||||
out.v = joints[7];
|
||||
out.w = joints[8];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_pumakins_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncPumaParameters ¶meters,
|
||||
CncSimPose *pose,
|
||||
int *iflags) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
apply_parameters(parameters);
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
int raw_iflags = 0;
|
||||
if (cnc_sim_linuxcnc_pumakins_forward(raw_joints, &out, &raw_iflags) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (iflags) {
|
||||
*iflags = raw_iflags;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_pumakins_inverse(const CncSimPose &pose,
|
||||
const LinuxCncAxisJoints ¤t_joints,
|
||||
const LinuxCncPumaParameters ¶meters,
|
||||
int iflags,
|
||||
LinuxCncAxisJoints *joints,
|
||||
int *fflags) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
apply_parameters(parameters);
|
||||
double raw_joints[16];
|
||||
to_joints(current_joints, raw_joints);
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
int raw_fflags = 0;
|
||||
if (cnc_sim_linuxcnc_pumakins_inverse(&in, raw_joints, iflags, &raw_fflags) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (fflags) {
|
||||
*fflags = raw_fflags;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
14
core/src/linuxcnc_pumakins_adapter.h
Normal file
14
core/src/linuxcnc_pumakins_adapter.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_pumakins_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncPumaParameters ¶meters,
|
||||
CncSimPose *pose,
|
||||
int *iflags);
|
||||
bool linuxcnc_pumakins_inverse(const CncSimPose &pose,
|
||||
const LinuxCncAxisJoints ¤t_joints,
|
||||
const LinuxCncPumaParameters ¶meters,
|
||||
int iflags,
|
||||
LinuxCncAxisJoints *joints,
|
||||
int *fflags);
|
||||
147
core/src/linuxcnc_rosekins_adapter.c
Normal file
147
core/src/linuxcnc_rosekins_adapter.c
Normal file
@@ -0,0 +1,147 @@
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_APP_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
#define __LINUXCNC_EMCPOS_H
|
||||
|
||||
#define MODULE_LICENSE(...)
|
||||
#define EXPORT_SYMBOL(symbol)
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
#define PM_PI 3.1415926535897932384626433832795029
|
||||
#define PM_2_PI (2.0 * PM_PI)
|
||||
#define TO_RAD (PM_PI / 180.0)
|
||||
#define TO_DEG (180.0 / PM_PI)
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#define KINS_NOT_SWITCHABLE \
|
||||
extern int kinematicsSwitchable() { return 0; } \
|
||||
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int cnc_sim_rosekins_hal_init(const char *name) {
|
||||
(void)name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *cnc_sim_rosekins_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_rosekins_hal_ready(int comp_id) {
|
||||
(void)comp_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnc_sim_rosekins_hal_exit(int comp_id) {
|
||||
(void)comp_id;
|
||||
}
|
||||
|
||||
int cnc_sim_rosekins_hal_pin_float_new(const char *name,
|
||||
hal_pin_dir_t dir,
|
||||
hal_float_t **data_ptr_addr,
|
||||
int comp_id) {
|
||||
(void)name;
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
#define hal_init cnc_sim_rosekins_hal_init
|
||||
#define hal_malloc(size) ((struct haldata *)cnc_sim_rosekins_hal_malloc(size))
|
||||
#define hal_pin_float_new cnc_sim_rosekins_hal_pin_float_new
|
||||
#define hal_ready cnc_sim_rosekins_hal_ready
|
||||
#define hal_exit cnc_sim_rosekins_hal_exit
|
||||
#define kinematicsType cnc_sim_rosekins_kinematicsType
|
||||
#define kinematicsForward cnc_sim_rosekins_kinematicsForward
|
||||
#define kinematicsInverse cnc_sim_rosekins_kinematicsInverse
|
||||
#define kinematicsSwitchable cnc_sim_rosekins_kinematicsSwitchable
|
||||
#define kinematicsSwitch cnc_sim_rosekins_kinematicsSwitch
|
||||
#define rtapi_app_main cnc_sim_rosekins_rtapi_app_main
|
||||
#define rtapi_app_exit cnc_sim_rosekins_rtapi_app_exit
|
||||
#define comp_id cnc_sim_rosekins_comp_id
|
||||
#define haldata cnc_sim_rosekins_haldata
|
||||
#include "../../../linuxcnc/src/emc/kinematics/rosekins.c"
|
||||
#undef haldata
|
||||
#undef comp_id
|
||||
#undef rtapi_app_exit
|
||||
#undef rtapi_app_main
|
||||
#undef kinematicsSwitch
|
||||
#undef kinematicsSwitchable
|
||||
#undef kinematicsInverse
|
||||
#undef kinematicsForward
|
||||
#undef kinematicsType
|
||||
#undef hal_exit
|
||||
#undef hal_ready
|
||||
#undef hal_pin_float_new
|
||||
#undef hal_malloc
|
||||
#undef hal_init
|
||||
|
||||
int cnc_sim_linuxcnc_rosekins_setup(void) {
|
||||
return cnc_sim_rosekins_rtapi_app_main();
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_rosekins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_rosekins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_rosekins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_rosekins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
121
core/src/linuxcnc_rosekins_adapter.cpp
Normal file
121
core/src/linuxcnc_rosekins_adapter.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
#include "linuxcnc_rosekins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_rosekins_setup(void);
|
||||
int cnc_sim_linuxcnc_rosekins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_rosekins_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_rosekins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.a;
|
||||
out[4] = joints.b;
|
||||
out[5] = joints.c;
|
||||
out[6] = joints.u;
|
||||
out[7] = joints.v;
|
||||
out[8] = joints.w;
|
||||
}
|
||||
|
||||
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.a = joints[3];
|
||||
out.b = joints[4];
|
||||
out.c = joints[5];
|
||||
out.u = joints[6];
|
||||
out.v = joints[7];
|
||||
out.w = joints[8];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_rosekins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_rosekins_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_rosekins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
if (cnc_sim_linuxcnc_rosekins_inverse(&in, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
6
core/src/linuxcnc_rosekins_adapter.h
Normal file
6
core/src/linuxcnc_rosekins_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_rosekins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose);
|
||||
bool linuxcnc_rosekins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints);
|
||||
165
core/src/linuxcnc_rotarydeltakins_adapter.c
Normal file
165
core/src/linuxcnc_rotarydeltakins_adapter.c
Normal file
@@ -0,0 +1,165 @@
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_APP_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
#define __LINUXCNC_EMCPOS_H
|
||||
|
||||
#define MODULE_LICENSE(...)
|
||||
#define EXPORT_SYMBOL(symbol)
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#define KINS_NOT_SWITCHABLE \
|
||||
extern int kinematicsSwitchable() { return 0; } \
|
||||
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int cnc_sim_rotarydelta_hal_init(const char *name) {
|
||||
(void)name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *cnc_sim_rotarydelta_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_rotarydelta_hal_ready(int comp_id) {
|
||||
(void)comp_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnc_sim_rotarydelta_hal_exit(int comp_id) {
|
||||
(void)comp_id;
|
||||
}
|
||||
|
||||
int cnc_sim_rotarydelta_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||
hal_float_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
#define hal_init cnc_sim_rotarydelta_hal_init
|
||||
#define hal_malloc(size) ((struct haldata *)cnc_sim_rotarydelta_hal_malloc(size))
|
||||
#define hal_pin_float_newf cnc_sim_rotarydelta_hal_pin_float_newf
|
||||
#define hal_ready cnc_sim_rotarydelta_hal_ready
|
||||
#define hal_exit cnc_sim_rotarydelta_hal_exit
|
||||
#define kinematicsType cnc_sim_rotarydelta_kinematicsType
|
||||
#define kinematicsForward cnc_sim_rotarydelta_kinematicsForward
|
||||
#define kinematicsInverse cnc_sim_rotarydelta_kinematicsInverse
|
||||
#define kinematicsSwitchable cnc_sim_rotarydelta_kinematicsSwitchable
|
||||
#define kinematicsSwitch cnc_sim_rotarydelta_kinematicsSwitch
|
||||
#define rtapi_app_main cnc_sim_rotarydelta_rtapi_app_main
|
||||
#define rtapi_app_exit cnc_sim_rotarydelta_rtapi_app_exit
|
||||
#define comp_id cnc_sim_rotarydelta_comp_id
|
||||
#define haldata cnc_sim_rotarydelta_haldata
|
||||
#include "../../../linuxcnc/src/emc/kinematics/rotarydeltakins.c"
|
||||
#undef haldata
|
||||
#undef comp_id
|
||||
#undef rtapi_app_exit
|
||||
#undef rtapi_app_main
|
||||
#undef kinematicsSwitch
|
||||
#undef kinematicsSwitchable
|
||||
#undef kinematicsInverse
|
||||
#undef kinematicsForward
|
||||
#undef kinematicsType
|
||||
#undef hal_exit
|
||||
#undef hal_ready
|
||||
#undef hal_pin_float_newf
|
||||
#undef hal_malloc
|
||||
#undef hal_init
|
||||
|
||||
int cnc_sim_linuxcnc_rotarydeltakins_setup(void) {
|
||||
return cnc_sim_rotarydelta_rtapi_app_main();
|
||||
}
|
||||
|
||||
void cnc_sim_linuxcnc_rotarydeltakins_default_parameters(double *platformradius,
|
||||
double *thighlength,
|
||||
double *shinlength,
|
||||
double *footradius) {
|
||||
*platformradius = RDELTA_PFR;
|
||||
*thighlength = RDELTA_TL;
|
||||
*shinlength = RDELTA_SL;
|
||||
*footradius = RDELTA_FR;
|
||||
}
|
||||
|
||||
void cnc_sim_linuxcnc_rotarydeltakins_set_parameters(double platformradius,
|
||||
double thighlength,
|
||||
double shinlength,
|
||||
double footradius) {
|
||||
*cnc_sim_rotarydelta_haldata->pfr = platformradius;
|
||||
*cnc_sim_rotarydelta_haldata->tl = thighlength;
|
||||
*cnc_sim_rotarydelta_haldata->sl = shinlength;
|
||||
*cnc_sim_rotarydelta_haldata->fr = footradius;
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_rotarydeltakins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_rotarydelta_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_rotarydeltakins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_rotarydelta_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
157
core/src/linuxcnc_rotarydeltakins_adapter.cpp
Normal file
157
core/src/linuxcnc_rotarydeltakins_adapter.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
#include "linuxcnc_rotarydeltakins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_rotarydeltakins_setup(void);
|
||||
void cnc_sim_linuxcnc_rotarydeltakins_default_parameters(double *platformradius,
|
||||
double *thighlength,
|
||||
double *shinlength,
|
||||
double *footradius);
|
||||
void cnc_sim_linuxcnc_rotarydeltakins_set_parameters(double platformradius,
|
||||
double thighlength,
|
||||
double shinlength,
|
||||
double footradius);
|
||||
int cnc_sim_linuxcnc_rotarydeltakins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_rotarydeltakins_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_rotarydeltakins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.a;
|
||||
out[4] = joints.b;
|
||||
out[5] = joints.c;
|
||||
out[6] = joints.u;
|
||||
out[7] = joints.v;
|
||||
out[8] = joints.w;
|
||||
}
|
||||
|
||||
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.a = joints[3];
|
||||
out.b = joints[4];
|
||||
out.c = joints[5];
|
||||
out.u = joints[6];
|
||||
out.v = joints[7];
|
||||
out.w = joints[8];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_rotarydeltakins_source_default_parameters(LinuxCncRotaryDeltaParameters *parameters) {
|
||||
double platformradius = 0.0;
|
||||
double thighlength = 0.0;
|
||||
double shinlength = 0.0;
|
||||
double footradius = 0.0;
|
||||
cnc_sim_linuxcnc_rotarydeltakins_default_parameters(&platformradius,
|
||||
&thighlength,
|
||||
&shinlength,
|
||||
&footradius);
|
||||
parameters->platformradius = platformradius;
|
||||
parameters->thighlength = thighlength;
|
||||
parameters->shinlength = shinlength;
|
||||
parameters->footradius = footradius;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_rotarydeltakins_source_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncRotaryDeltaParameters ¶meters,
|
||||
CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
cnc_sim_linuxcnc_rotarydeltakins_set_parameters(parameters.platformradius,
|
||||
parameters.thighlength,
|
||||
parameters.shinlength,
|
||||
parameters.footradius);
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_rotarydeltakins_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_rotarydeltakins_source_inverse(const CncSimPose &pose,
|
||||
const LinuxCncRotaryDeltaParameters ¶meters,
|
||||
LinuxCncAxisJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
cnc_sim_linuxcnc_rotarydeltakins_set_parameters(parameters.platformradius,
|
||||
parameters.thighlength,
|
||||
parameters.shinlength,
|
||||
parameters.footradius);
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
if (cnc_sim_linuxcnc_rotarydeltakins_inverse(&in, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
11
core/src/linuxcnc_rotarydeltakins_adapter.h
Normal file
11
core/src/linuxcnc_rotarydeltakins_adapter.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_rotarydeltakins_source_default_parameters(LinuxCncRotaryDeltaParameters *parameters);
|
||||
bool linuxcnc_rotarydeltakins_source_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncRotaryDeltaParameters ¶meters,
|
||||
CncSimPose *pose);
|
||||
bool linuxcnc_rotarydeltakins_source_inverse(const CncSimPose &pose,
|
||||
const LinuxCncRotaryDeltaParameters ¶meters,
|
||||
LinuxCncAxisJoints *joints);
|
||||
118
core/src/linuxcnc_rotatekins_adapter.c
Normal file
118
core/src/linuxcnc_rotatekins_adapter.c
Normal file
@@ -0,0 +1,118 @@
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_APP_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
|
||||
#define MODULE_LICENSE(...)
|
||||
#define EXPORT_SYMBOL(symbol)
|
||||
#define RTAPI_MSG_ERR 1
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#define KINS_NOT_SWITCHABLE \
|
||||
extern int kinematicsSwitchable() { return 0; } \
|
||||
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int cnc_sim_rotatekins_hal_init(const char *name) {
|
||||
(void)name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cnc_sim_rotatekins_hal_ready(int comp_id) {
|
||||
(void)comp_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnc_sim_rotatekins_hal_exit(int comp_id) {
|
||||
(void)comp_id;
|
||||
}
|
||||
|
||||
#define hal_init cnc_sim_rotatekins_hal_init
|
||||
#define hal_ready cnc_sim_rotatekins_hal_ready
|
||||
#define hal_exit cnc_sim_rotatekins_hal_exit
|
||||
#define kinematicsType cnc_sim_rotatekins_kinematicsType
|
||||
#define kinematicsForward cnc_sim_rotatekins_kinematicsForward
|
||||
#define kinematicsInverse cnc_sim_rotatekins_kinematicsInverse
|
||||
#define kinematicsHome cnc_sim_rotatekins_kinematicsHome
|
||||
#define kinematicsSwitchable cnc_sim_rotatekins_kinematicsSwitchable
|
||||
#define kinematicsSwitch cnc_sim_rotatekins_kinematicsSwitch
|
||||
#define rtapi_app_main cnc_sim_rotatekins_rtapi_app_main
|
||||
#define rtapi_app_exit cnc_sim_rotatekins_rtapi_app_exit
|
||||
#define comp_id cnc_sim_rotatekins_comp_id
|
||||
#include "../../../linuxcnc/src/emc/kinematics/rotatekins.c"
|
||||
#undef comp_id
|
||||
#undef rtapi_app_exit
|
||||
#undef rtapi_app_main
|
||||
#undef kinematicsSwitch
|
||||
#undef kinematicsSwitchable
|
||||
#undef kinematicsHome
|
||||
#undef kinematicsInverse
|
||||
#undef kinematicsForward
|
||||
#undef kinematicsType
|
||||
#undef hal_exit
|
||||
#undef hal_ready
|
||||
#undef hal_init
|
||||
|
||||
int cnc_sim_linuxcnc_rotatekins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_rotatekins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_rotatekins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_rotatekins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
104
core/src/linuxcnc_rotatekins_adapter.cpp
Normal file
104
core/src/linuxcnc_rotatekins_adapter.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
#include "linuxcnc_rotatekins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_rotatekins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_rotatekins_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.a;
|
||||
out[4] = joints.b;
|
||||
out[5] = joints.c;
|
||||
out[6] = joints.u;
|
||||
out[7] = joints.v;
|
||||
out[8] = joints.w;
|
||||
}
|
||||
|
||||
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.a = joints[3];
|
||||
out.b = joints[4];
|
||||
out.c = joints[5];
|
||||
out.u = joints[6];
|
||||
out.v = joints[7];
|
||||
out.w = joints[8];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_rotatekins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose) {
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_rotatekins_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_rotatekins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints) {
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
if (cnc_sim_linuxcnc_rotatekins_inverse(&in, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
6
core/src/linuxcnc_rotatekins_adapter.h
Normal file
6
core/src/linuxcnc_rotatekins_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_rotatekins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose);
|
||||
bool linuxcnc_rotatekins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints);
|
||||
@@ -1,6 +1,10 @@
|
||||
#include "linuxcnc_rs274_backend.h"
|
||||
|
||||
#ifdef CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
|
||||
#include "boost/python/object.hpp"
|
||||
#else
|
||||
#include <Python.h>
|
||||
#endif
|
||||
|
||||
#include "linuxcnc_canon_bridge.h"
|
||||
#include "linuxcnc_tooldata_fixture.h"
|
||||
@@ -16,11 +20,15 @@
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#ifndef CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
int _task = 0;
|
||||
char _parameter_file_name[LINELEN];
|
||||
|
||||
#ifndef CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
|
||||
int _task = 0;
|
||||
|
||||
extern "C" PyObject *PyInit_interpreter(void);
|
||||
extern "C" PyObject *PyInit_emccanon(void);
|
||||
extern "C" struct _inittab builtin_modules[];
|
||||
@@ -29,6 +37,7 @@ struct _inittab builtin_modules[] = {
|
||||
{"emccanon", PyInit_emccanon},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -73,6 +82,7 @@ bool file_mode_enabled() {
|
||||
return std::getenv("CNC_SIM_RS274_FILE_MODE") != nullptr;
|
||||
}
|
||||
|
||||
#ifndef CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
|
||||
bool write_temp_program(const char *program,
|
||||
size_t program_len,
|
||||
std::string *path,
|
||||
@@ -113,6 +123,7 @@ bool write_temp_program(const char *program,
|
||||
*path = tmpl_buffer.data();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
int execute_file_mode(InterpBase *interp,
|
||||
CanonEventSink &sink,
|
||||
@@ -192,6 +203,15 @@ int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
||||
SET_BLOCK_DELETE(sink.block_delete());
|
||||
|
||||
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;
|
||||
if (!write_temp_program(program, program_len, &temp_path, error)) {
|
||||
interp->exit();
|
||||
@@ -207,6 +227,7 @@ int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
||||
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
std::string source(program, program + program_len);
|
||||
std::istringstream input(source);
|
||||
@@ -219,19 +240,45 @@ int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
||||
std::vector<SimulatorGcodeControlAction> control_actions;
|
||||
if (parse_simulator_gcode_control_line(line, sink.block_delete(), &control_actions)) {
|
||||
bool simulator_only_line = true;
|
||||
bool all_control_actions_handled = true;
|
||||
for (const auto &action : control_actions) {
|
||||
emit_simulator_gcode_control_action(sink, action, line_number);
|
||||
if (!can_emit_simulator_gcode_control_action(sink, action)) {
|
||||
all_control_actions_handled = false;
|
||||
simulator_only_line = false;
|
||||
}
|
||||
if (action.kind == SimulatorGcodeControlKind::RtcpState &&
|
||||
!action.rtcp_enabled) {
|
||||
simulator_only_line = false;
|
||||
}
|
||||
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 && control_actions.size() > 1) {
|
||||
for (const auto &action : control_actions) {
|
||||
if (!can_emit_simulator_gcode_control_action(sink, action) &&
|
||||
action.kind == SimulatorGcodeControlKind::KinematicsSwitch) {
|
||||
if (error) {
|
||||
*error = "M-code greater than 199: M" + std::to_string(action.m_code);
|
||||
}
|
||||
interp->exit();
|
||||
delete interp;
|
||||
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (all_control_actions_handled) {
|
||||
for (const auto &action : control_actions) {
|
||||
emit_simulator_gcode_control_action(sink, action, line_number);
|
||||
if (stop_if_callback_aborted(sink, error)) {
|
||||
interp->exit();
|
||||
delete interp;
|
||||
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!all_control_actions_handled) {
|
||||
simulator_only_line = false;
|
||||
}
|
||||
if (simulator_only_line) {
|
||||
continue;
|
||||
}
|
||||
|
||||
224
core/src/linuxcnc_scarakins_adapter.c
Normal file
224
core/src/linuxcnc_scarakins_adapter.c
Normal file
@@ -0,0 +1,224 @@
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_STRING_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
#define SWITCHKINS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define CNC_SIM_EXTERN_C extern "C"
|
||||
#else
|
||||
#define CNC_SIM_EXTERN_C
|
||||
#endif
|
||||
|
||||
#define PM_PI 3.1415926535897932384626433832795029
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef int hal_s32_t;
|
||||
typedef bool hal_bit_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
typedef int (*KF)(const double *joint,
|
||||
EmcPose *pos,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags);
|
||||
typedef int (*KI)(const struct EmcPose *world,
|
||||
double *joint,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags);
|
||||
typedef int (*KS)(const int comp_id, const char *coordinates, kparms *ksetup_parms);
|
||||
|
||||
void cnc_sim_scara_rtapi_print(const char *fmt, ...) {
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void cnc_sim_scara_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||
(void)level;
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void *cnc_sim_scara_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_scara_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||
hal_float_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_scara_identityKinematicsSetup(const int comp_id,
|
||||
const char *coordinates,
|
||||
kparms *ksetup_parms) {
|
||||
(void)comp_id;
|
||||
(void)coordinates;
|
||||
(void)ksetup_parms;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnc_sim_scara_identityKinematicsForward(const double *joint,
|
||||
struct EmcPose *world,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||
(void)joint;
|
||||
(void)world;
|
||||
(void)fflags;
|
||||
(void)iflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_scara_identityKinematicsInverse(const struct EmcPose *world,
|
||||
double *joint,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||
(void)world;
|
||||
(void)joint;
|
||||
(void)iflags;
|
||||
(void)fflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_scara_userkKinematicsSetup(const int comp_id,
|
||||
const char *coordinates,
|
||||
kparms *ksetup_parms) {
|
||||
(void)comp_id;
|
||||
(void)coordinates;
|
||||
(void)ksetup_parms;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_scara_userkKinematicsForward(const double *joint,
|
||||
struct EmcPose *world,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags) {
|
||||
(void)joint;
|
||||
(void)world;
|
||||
(void)fflags;
|
||||
(void)iflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnc_sim_scara_userkKinematicsInverse(const struct EmcPose *world,
|
||||
double *joint,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags) {
|
||||
(void)world;
|
||||
(void)joint;
|
||||
(void)iflags;
|
||||
(void)fflags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define rtapi_print cnc_sim_scara_rtapi_print
|
||||
#define rtapi_print_msg cnc_sim_scara_rtapi_print_msg
|
||||
#define hal_pin_float_newf cnc_sim_scara_hal_pin_float_newf
|
||||
#define identityKinematicsSetup cnc_sim_scara_identityKinematicsSetup
|
||||
#define identityKinematicsForward cnc_sim_scara_identityKinematicsForward
|
||||
#define identityKinematicsInverse cnc_sim_scara_identityKinematicsInverse
|
||||
#define userkKinematicsSetup cnc_sim_scara_userkKinematicsSetup
|
||||
#define userkKinematicsForward cnc_sim_scara_userkKinematicsForward
|
||||
#define userkKinematicsInverse cnc_sim_scara_userkKinematicsInverse
|
||||
#define switchkinsSetup cnc_sim_scara_switchkinsSetup
|
||||
#define haldata cnc_sim_scara_haldata
|
||||
#define hal_malloc(size) ((struct scara_data *)cnc_sim_scara_hal_malloc(size))
|
||||
#include "../../../linuxcnc/src/emc/kinematics/scarakins.c"
|
||||
#undef hal_malloc
|
||||
#undef haldata
|
||||
#undef switchkinsSetup
|
||||
#undef userkKinematicsInverse
|
||||
#undef userkKinematicsForward
|
||||
#undef userkKinematicsSetup
|
||||
#undef identityKinematicsInverse
|
||||
#undef identityKinematicsForward
|
||||
#undef identityKinematicsSetup
|
||||
#undef hal_pin_float_newf
|
||||
#undef rtapi_print_msg
|
||||
#undef rtapi_print
|
||||
|
||||
CNC_SIM_EXTERN_C int cnc_sim_linuxcnc_scarakins_setup(void) {
|
||||
kparms kp = {0};
|
||||
static char kinsname[] = "scarakins";
|
||||
static char halprefix[] = "scarakins";
|
||||
kp.kinsname = kinsname;
|
||||
kp.halprefix = halprefix;
|
||||
return scaraKinematicsSetup(0, "XYZABC", &kp);
|
||||
}
|
||||
|
||||
CNC_SIM_EXTERN_C void cnc_sim_linuxcnc_scarakins_set_parameters(double d1,
|
||||
double d2,
|
||||
double d3,
|
||||
double d4,
|
||||
double d5,
|
||||
double d6) {
|
||||
*cnc_sim_scara_haldata->d1 = d1;
|
||||
*cnc_sim_scara_haldata->d2 = d2;
|
||||
*cnc_sim_scara_haldata->d3 = d3;
|
||||
*cnc_sim_scara_haldata->d4 = d4;
|
||||
*cnc_sim_scara_haldata->d5 = d5;
|
||||
*cnc_sim_scara_haldata->d6 = d6;
|
||||
}
|
||||
|
||||
CNC_SIM_EXTERN_C int cnc_sim_linuxcnc_scarakins_forward(const double *joints,
|
||||
struct EmcPose *pos,
|
||||
int *iflags) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS raw_iflags = 0;
|
||||
const int result = scaraKinematicsForward(joints, pos, &fflags, &raw_iflags);
|
||||
if (iflags) {
|
||||
*iflags = (int)raw_iflags;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CNC_SIM_EXTERN_C int cnc_sim_linuxcnc_scarakins_inverse(const struct EmcPose *pos,
|
||||
double *joints,
|
||||
int iflags) {
|
||||
KINEMATICS_INVERSE_FLAGS raw_iflags = (KINEMATICS_INVERSE_FLAGS)iflags;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return scaraKinematicsInverse(pos, joints, &raw_iflags, &fflags);
|
||||
}
|
||||
144
core/src/linuxcnc_scarakins_adapter.cpp
Normal file
144
core/src/linuxcnc_scarakins_adapter.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
#include "linuxcnc_scarakins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_scarakins_setup(void);
|
||||
void cnc_sim_linuxcnc_scarakins_set_parameters(double d1,
|
||||
double d2,
|
||||
double d3,
|
||||
double d4,
|
||||
double d5,
|
||||
double d6);
|
||||
int cnc_sim_linuxcnc_scarakins_forward(const double *joints, EmcPose *pos, int *iflags);
|
||||
int cnc_sim_linuxcnc_scarakins_inverse(const EmcPose *pos,
|
||||
double *joints,
|
||||
int iflags);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_scarakins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void apply_parameters(const LinuxCncScaraParameters ¶meters) {
|
||||
cnc_sim_linuxcnc_scarakins_set_parameters(parameters.d1,
|
||||
parameters.d2,
|
||||
parameters.d3,
|
||||
parameters.d4,
|
||||
parameters.d5,
|
||||
parameters.d6);
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncScaraJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.j0;
|
||||
out[1] = joints.j1;
|
||||
out[2] = joints.j2;
|
||||
out[3] = joints.j3;
|
||||
out[4] = joints.j4;
|
||||
out[5] = joints.j5;
|
||||
}
|
||||
|
||||
LinuxCncScaraJoints from_joints(const double joints[16]) {
|
||||
LinuxCncScaraJoints out{};
|
||||
out.j0 = joints[0];
|
||||
out.j1 = joints[1];
|
||||
out.j2 = joints[2];
|
||||
out.j3 = joints[3];
|
||||
out.j4 = joints[4];
|
||||
out.j5 = joints[5];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_scarakins_forward(const LinuxCncScaraJoints &joints,
|
||||
const LinuxCncScaraParameters ¶meters,
|
||||
CncSimPose *pose,
|
||||
int *iflags) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
apply_parameters(parameters);
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
int raw_iflags = 0;
|
||||
if (cnc_sim_linuxcnc_scarakins_forward(raw_joints, &out, &raw_iflags) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (iflags) {
|
||||
*iflags = raw_iflags;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_scarakins_inverse(const CncSimPose &pose,
|
||||
const LinuxCncScaraParameters ¶meters,
|
||||
int iflags,
|
||||
LinuxCncScaraJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
apply_parameters(parameters);
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
if (cnc_sim_linuxcnc_scarakins_inverse(&in, raw_joints, iflags) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
12
core/src/linuxcnc_scarakins_adapter.h
Normal file
12
core/src/linuxcnc_scarakins_adapter.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_scarakins_forward(const LinuxCncScaraJoints &joints,
|
||||
const LinuxCncScaraParameters ¶meters,
|
||||
CncSimPose *pose,
|
||||
int *iflags);
|
||||
bool linuxcnc_scarakins_inverse(const CncSimPose &pose,
|
||||
const LinuxCncScaraParameters ¶meters,
|
||||
int iflags,
|
||||
LinuxCncScaraJoints *joints);
|
||||
121
core/src/linuxcnc_scorbot_kins_adapter.c
Normal file
121
core/src/linuxcnc_scorbot_kins_adapter.c
Normal file
@@ -0,0 +1,121 @@
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_APP_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_GO_TYPES_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
#define __LINUXCNC_EMCPOS_H
|
||||
|
||||
#define MODULE_LICENSE(...)
|
||||
#define EXPORT_SYMBOL(symbol)
|
||||
|
||||
#define PM_PI 3.1415926535897932384626433832795029
|
||||
#define TO_RAD (PM_PI / 180.0)
|
||||
#define TO_DEG (180.0 / PM_PI)
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#define KINS_NOT_SWITCHABLE \
|
||||
extern int kinematicsSwitchable() { return 0; } \
|
||||
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int cnc_sim_scorbot_kins_hal_init(const char *name) {
|
||||
(void)name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cnc_sim_scorbot_kins_hal_ready(int comp_id) {
|
||||
(void)comp_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnc_sim_scorbot_kins_hal_exit(int comp_id) {
|
||||
(void)comp_id;
|
||||
}
|
||||
|
||||
#define hal_init cnc_sim_scorbot_kins_hal_init
|
||||
#define hal_ready cnc_sim_scorbot_kins_hal_ready
|
||||
#define hal_exit cnc_sim_scorbot_kins_hal_exit
|
||||
#define kinematicsType cnc_sim_scorbot_kins_kinematicsType
|
||||
#define kinematicsForward cnc_sim_scorbot_kins_kinematicsForward
|
||||
#define kinematicsInverse cnc_sim_scorbot_kins_kinematicsInverse
|
||||
#define kinematicsSwitchable cnc_sim_scorbot_kins_kinematicsSwitchable
|
||||
#define kinematicsSwitch cnc_sim_scorbot_kins_kinematicsSwitch
|
||||
#define rtapi_app_main cnc_sim_scorbot_kins_rtapi_app_main
|
||||
#define rtapi_app_exit cnc_sim_scorbot_kins_rtapi_app_exit
|
||||
#define comp_id cnc_sim_scorbot_kins_comp_id
|
||||
#include "../../../linuxcnc/src/emc/kinematics/scorbot-kins.c"
|
||||
#undef comp_id
|
||||
#undef rtapi_app_exit
|
||||
#undef rtapi_app_main
|
||||
#undef kinematicsSwitch
|
||||
#undef kinematicsSwitchable
|
||||
#undef kinematicsInverse
|
||||
#undef kinematicsForward
|
||||
#undef kinematicsType
|
||||
#undef hal_exit
|
||||
#undef hal_ready
|
||||
#undef hal_init
|
||||
|
||||
int cnc_sim_linuxcnc_scorbot_kins_setup(void) {
|
||||
return cnc_sim_scorbot_kins_rtapi_app_main();
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_scorbot_kins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_scorbot_kins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_scorbot_kins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_scorbot_kins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
110
core/src/linuxcnc_scorbot_kins_adapter.cpp
Normal file
110
core/src/linuxcnc_scorbot_kins_adapter.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "linuxcnc_scorbot_kins_adapter.h"
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_scorbot_kins_setup(void);
|
||||
int cnc_sim_linuxcnc_scorbot_kins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_scorbot_kins_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_scorbot_kins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncScorbotJoints &joints, double out[5]) {
|
||||
out[0] = joints.j0;
|
||||
out[1] = joints.j1;
|
||||
out[2] = joints.j2;
|
||||
out[3] = joints.j3;
|
||||
out[4] = joints.j4;
|
||||
}
|
||||
|
||||
LinuxCncScorbotJoints from_joints(const double joints[5]) {
|
||||
LinuxCncScorbotJoints out{};
|
||||
out.j0 = joints[0];
|
||||
out.j1 = joints[1];
|
||||
out.j2 = joints[2];
|
||||
out.j3 = joints[3];
|
||||
out.j4 = joints[4];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_scorbot_kins_source_forward(const LinuxCncScorbotJoints &joints, CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
double raw_joints[5] = {};
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_scorbot_kins_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_scorbot_kins_source_inverse(const CncSimPose &pose, LinuxCncScorbotJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[5] = {};
|
||||
if (cnc_sim_linuxcnc_scorbot_kins_inverse(&in, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
6
core/src/linuxcnc_scorbot_kins_adapter.h
Normal file
6
core/src/linuxcnc_scorbot_kins_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_scorbot_kins_source_forward(const LinuxCncScorbotJoints &joints, CncSimPose *pose);
|
||||
bool linuxcnc_scorbot_kins_source_inverse(const CncSimPose &pose, LinuxCncScorbotJoints *joints);
|
||||
110
core/src/linuxcnc_switchkins_remap_table.inc
Normal file
110
core/src/linuxcnc_switchkins_remap_table.inc
Normal file
@@ -0,0 +1,110 @@
|
||||
// Generated by ./generate-linuxcnc-switchkins-remap-table.sh.
|
||||
// Source: LinuxCNC INI MACHINE/KINEMATICS/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},
|
||||
{"5axisgui.hal", 0, 1, 2},
|
||||
{"5axisgui", 0, 1, 2},
|
||||
{"configs/sim/axis/vismach/5axis/bridgemill/remap_subs", 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/remap_subs", 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/remap_subs", 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/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/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/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},
|
||||
{"kinematics.hal", 0, 1, 2},
|
||||
{"kinematics", 0, 1, 2},
|
||||
{"configs/sim/axis/vismach/hexapod-sim/remap_subs", 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},
|
||||
{"melfa_dh.hal", 0, 1, 2},
|
||||
{"melfa_dh", 0, 1, 2},
|
||||
{"configs/sim/axis/vismach/melfa-sim/remap_subs", 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},
|
||||
{"millturn.hal", 0, 1, -1},
|
||||
{"configs/sim/axis/vismach/millturn/remap_subs", 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},
|
||||
{"puma_dh.hal", 0, 1, 2},
|
||||
{"puma_dh", 0, 1, 2},
|
||||
{"configs/sim/axis/vismach/puma/remap_subs", 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},
|
||||
{"puma560_dh.hal", 0, 1, 2},
|
||||
{"puma560_dh", 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/remap_subs", 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", 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", 0, 1, 2},
|
||||
142
core/src/linuxcnc_tripodkins_adapter.c
Normal file
142
core/src/linuxcnc_tripodkins_adapter.c
Normal file
@@ -0,0 +1,142 @@
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_APP_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
#define __LINUXCNC_EMCPOS_H
|
||||
|
||||
#define MODULE_LICENSE(...)
|
||||
#define EXPORT_SYMBOL(symbol)
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#define KINS_NOT_SWITCHABLE \
|
||||
extern int kinematicsSwitchable() { return 0; } \
|
||||
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int cnc_sim_tripodkins_hal_init(const char *name) {
|
||||
(void)name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *cnc_sim_tripodkins_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_tripodkins_hal_ready(int comp_id) {
|
||||
(void)comp_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnc_sim_tripodkins_hal_exit(int comp_id) {
|
||||
(void)comp_id;
|
||||
}
|
||||
|
||||
int cnc_sim_tripodkins_hal_pin_float_new(const char *name,
|
||||
hal_pin_dir_t dir,
|
||||
hal_float_t **data_ptr_addr,
|
||||
int comp_id) {
|
||||
(void)name;
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
#define hal_init cnc_sim_tripodkins_hal_init
|
||||
#define hal_malloc(size) ((struct haldata *)cnc_sim_tripodkins_hal_malloc(size))
|
||||
#define hal_pin_float_new cnc_sim_tripodkins_hal_pin_float_new
|
||||
#define hal_ready cnc_sim_tripodkins_hal_ready
|
||||
#define hal_exit cnc_sim_tripodkins_hal_exit
|
||||
#define kinematicsType cnc_sim_tripodkins_kinematicsType
|
||||
#define kinematicsForward cnc_sim_tripodkins_kinematicsForward
|
||||
#define kinematicsInverse cnc_sim_tripodkins_kinematicsInverse
|
||||
#define kinematicsSwitchable cnc_sim_tripodkins_kinematicsSwitchable
|
||||
#define kinematicsSwitch cnc_sim_tripodkins_kinematicsSwitch
|
||||
#define rtapi_app_main cnc_sim_tripodkins_rtapi_app_main
|
||||
#define rtapi_app_exit cnc_sim_tripodkins_rtapi_app_exit
|
||||
#define comp_id cnc_sim_tripodkins_comp_id
|
||||
#define haldata cnc_sim_tripodkins_haldata
|
||||
#include "../../../linuxcnc/src/emc/kinematics/tripodkins.c"
|
||||
#undef haldata
|
||||
#undef comp_id
|
||||
#undef rtapi_app_exit
|
||||
#undef rtapi_app_main
|
||||
#undef kinematicsSwitch
|
||||
#undef kinematicsSwitchable
|
||||
#undef kinematicsInverse
|
||||
#undef kinematicsForward
|
||||
#undef kinematicsType
|
||||
#undef hal_exit
|
||||
#undef hal_ready
|
||||
#undef hal_pin_float_new
|
||||
#undef hal_malloc
|
||||
#undef hal_init
|
||||
|
||||
int cnc_sim_linuxcnc_tripodkins_setup(void) {
|
||||
return cnc_sim_tripodkins_rtapi_app_main();
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_tripodkins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_tripodkins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_tripodkins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_tripodkins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
94
core/src/linuxcnc_tripodkins_adapter.cpp
Normal file
94
core/src/linuxcnc_tripodkins_adapter.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "linuxcnc_tripodkins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_tripodkins_setup(void);
|
||||
int cnc_sim_linuxcnc_tripodkins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_tripodkins_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_tripodkins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_tripodkins_source_forward(const LinuxCncTripodJoints &joints, CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
double raw_joints[3];
|
||||
std::memcpy(raw_joints, joints.strut, sizeof(raw_joints));
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_tripodkins_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_tripodkins_source_inverse(const CncSimPose &pose, LinuxCncTripodJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
const EmcPose emc_pose = to_emc_pose(pose);
|
||||
double raw_joints[3] = {};
|
||||
if (cnc_sim_linuxcnc_tripodkins_inverse(&emc_pose, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
std::memcpy(joints->strut, raw_joints, sizeof(raw_joints));
|
||||
return true;
|
||||
}
|
||||
6
core/src/linuxcnc_tripodkins_adapter.h
Normal file
6
core/src/linuxcnc_tripodkins_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_tripodkins_source_forward(const LinuxCncTripodJoints &joints, CncSimPose *pose);
|
||||
bool linuxcnc_tripodkins_source_inverse(const CncSimPose &pose, LinuxCncTripodJoints *joints);
|
||||
163
core/src/linuxcnc_trivkins_adapter.c
Normal file
163
core/src/linuxcnc_trivkins_adapter.c
Normal file
@@ -0,0 +1,163 @@
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_APP_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_STRING_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_EMCMOTCFG_H
|
||||
#define __LINUXCNC_EMCPOS_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
|
||||
#define MODULE_LICENSE(...)
|
||||
#define EXPORT_SYMBOL(symbol)
|
||||
#define RTAPI_MP_STRING(name, desc)
|
||||
#define RTAPI_MSG_ERR 1
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
#define EMCMOT_MAX_AXIS 9
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#define KINS_NOT_SWITCHABLE \
|
||||
extern int kinematicsSwitchable() { return 0; } \
|
||||
extern int kinematicsSwitch(int switchkins_type) { (void)switchkins_type; return 0; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cnc_sim_trivkins_rtapi_print(const char *fmt, ...) {
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void cnc_sim_trivkins_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||
(void)level;
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
int cnc_sim_trivkins_hal_init(const char *name) {
|
||||
(void)name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cnc_sim_trivkins_hal_ready(int comp_id) {
|
||||
(void)comp_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnc_sim_trivkins_hal_exit(int comp_id) {
|
||||
(void)comp_id;
|
||||
}
|
||||
|
||||
#define rtapi_print cnc_sim_trivkins_rtapi_print
|
||||
#define rtapi_print_msg cnc_sim_trivkins_rtapi_print_msg
|
||||
#define kinematicsType cnc_sim_trivkins_kinematicsType
|
||||
KINEMATICS_TYPE kinematicsType(void);
|
||||
#define map_coordinates_to_jnumbers cnc_sim_trivkins_map_coordinates_to_jnumbers
|
||||
#define mapped_joints_to_position cnc_sim_trivkins_mapped_joints_to_position
|
||||
#define position_to_mapped_joints cnc_sim_trivkins_position_to_mapped_joints
|
||||
#define identityKinematicsSetup cnc_sim_trivkins_identityKinematicsSetup
|
||||
#define identityKinematicsForward cnc_sim_trivkins_identityKinematicsForward
|
||||
#define identityKinematicsInverse cnc_sim_trivkins_identityKinematicsInverse
|
||||
#include "../../../linuxcnc/src/emc/kinematics/kins_util.c"
|
||||
|
||||
#define hal_init cnc_sim_trivkins_hal_init
|
||||
#define hal_ready cnc_sim_trivkins_hal_ready
|
||||
#define hal_exit cnc_sim_trivkins_hal_exit
|
||||
#define kinematicsForward cnc_sim_trivkins_kinematicsForward
|
||||
#define kinematicsInverse cnc_sim_trivkins_kinematicsInverse
|
||||
#define kinematicsSwitchable cnc_sim_trivkins_kinematicsSwitchable
|
||||
#define kinematicsSwitch cnc_sim_trivkins_kinematicsSwitch
|
||||
#define rtapi_app_main cnc_sim_trivkins_rtapi_app_main
|
||||
#define rtapi_app_exit cnc_sim_trivkins_rtapi_app_exit
|
||||
#define comp_id cnc_sim_trivkins_comp_id
|
||||
#define coordinates cnc_sim_trivkins_coordinates
|
||||
#define kinstype cnc_sim_trivkins_kinstype
|
||||
#include "../../../linuxcnc/src/emc/kinematics/trivkins.c"
|
||||
#undef kinstype
|
||||
#undef coordinates
|
||||
#undef comp_id
|
||||
#undef rtapi_app_exit
|
||||
#undef rtapi_app_main
|
||||
#undef kinematicsSwitch
|
||||
#undef kinematicsSwitchable
|
||||
#undef kinematicsInverse
|
||||
#undef kinematicsForward
|
||||
#undef hal_exit
|
||||
#undef hal_ready
|
||||
#undef hal_init
|
||||
#undef identityKinematicsInverse
|
||||
#undef identityKinematicsForward
|
||||
#undef identityKinematicsSetup
|
||||
#undef position_to_mapped_joints
|
||||
#undef mapped_joints_to_position
|
||||
#undef map_coordinates_to_jnumbers
|
||||
#undef kinematicsType
|
||||
#undef rtapi_print_msg
|
||||
#undef rtapi_print
|
||||
|
||||
int cnc_sim_linuxcnc_trivkins_setup(void) {
|
||||
return cnc_sim_trivkins_rtapi_app_main();
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_trivkins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_trivkins_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_trivkins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_trivkins_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_trivkins_type(void) {
|
||||
return (int)cnc_sim_trivkins_kinematicsType();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
129
core/src/linuxcnc_trivkins_adapter.cpp
Normal file
129
core/src/linuxcnc_trivkins_adapter.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
#include "linuxcnc_trivkins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_trivkins_setup(void);
|
||||
int cnc_sim_linuxcnc_trivkins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_trivkins_inverse(const EmcPose *pos, double *joints);
|
||||
int cnc_sim_linuxcnc_trivkins_type(void);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_trivkins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.a;
|
||||
out[4] = joints.b;
|
||||
out[5] = joints.c;
|
||||
out[6] = joints.u;
|
||||
out[7] = joints.v;
|
||||
out[8] = joints.w;
|
||||
}
|
||||
|
||||
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.a = joints[3];
|
||||
out.b = joints[4];
|
||||
out.c = joints[5];
|
||||
out.u = joints[6];
|
||||
out.v = joints[7];
|
||||
out.w = joints[8];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_trivkins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_trivkins_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_trivkins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
if (cnc_sim_linuxcnc_trivkins_inverse(&in, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
|
||||
int linuxcnc_trivkins_source_kinematics_type() {
|
||||
if (!ensure_initialized()) {
|
||||
return 0;
|
||||
}
|
||||
return cnc_sim_linuxcnc_trivkins_type();
|
||||
}
|
||||
7
core/src/linuxcnc_trivkins_adapter.h
Normal file
7
core/src/linuxcnc_trivkins_adapter.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_trivkins_source_forward(const LinuxCncAxisJoints &joints, CncSimPose *pose);
|
||||
bool linuxcnc_trivkins_source_inverse(const CncSimPose &pose, LinuxCncAxisJoints *joints);
|
||||
int linuxcnc_trivkins_source_kinematics_type();
|
||||
207
core/src/linuxcnc_trtfuncs_adapter.c
Normal file
207
core/src/linuxcnc_trtfuncs_adapter.c
Normal file
@@ -0,0 +1,207 @@
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_STRING_H
|
||||
#define __LINUXCNC_RTAPI_CTYPE_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_EMCMOTCFG_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
|
||||
#define RTAPI_MSG_ERR 1
|
||||
#define PM_PI 3.1415926535897932384626433832795029
|
||||
#define TO_RAD (PM_PI / 180.0)
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
#define EMCMOT_MAX_AXIS 9
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef bool hal_bit_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
static int cnc_sim_axis_idx_for_jno[EMCMOT_MAX_JOINTS];
|
||||
static int cnc_sim_max_joints;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void rtapi_print(const char *fmt, ...) {
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void rtapi_print_msg(int level, const char *fmt, ...) {
|
||||
(void)level;
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void *cnc_sim_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int hal_pin_float_newf(hal_pin_dir_t dir, hal_float_t **data_ptr_addr, int comp_id, const char *fmt, ...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int hal_pin_bit_newf(hal_pin_dir_t dir, hal_bit_t **data_ptr_addr, int comp_id, const char *fmt, ...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_bit_t *)calloc(1, sizeof(hal_bit_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int map_coordinates_to_jnumbers(const char *coordinates,
|
||||
const int max_joints,
|
||||
const int allow_duplicates,
|
||||
int axis_idx_for_jno[]) {
|
||||
(void)allow_duplicates;
|
||||
const char *letters = "XYZABCUVW";
|
||||
int jno = 0;
|
||||
for (int i = 0; i < EMCMOT_MAX_JOINTS; ++i) {
|
||||
axis_idx_for_jno[i] = -1;
|
||||
cnc_sim_axis_idx_for_jno[i] = -1;
|
||||
}
|
||||
while (*coordinates) {
|
||||
const char *found = strchr(letters, toupper((unsigned char)*coordinates));
|
||||
if (!found || jno >= max_joints) {
|
||||
return -1;
|
||||
}
|
||||
axis_idx_for_jno[jno++] = (int)(found - letters);
|
||||
++coordinates;
|
||||
}
|
||||
cnc_sim_max_joints = jno;
|
||||
for (int i = 0; i < EMCMOT_MAX_JOINTS; ++i) {
|
||||
cnc_sim_axis_idx_for_jno[i] = axis_idx_for_jno[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int position_to_mapped_joints(const int max_joints, const EmcPose *pos, double *joints) {
|
||||
for (int jno = 0; jno < max_joints; ++jno) {
|
||||
switch (cnc_sim_axis_idx_for_jno[jno]) {
|
||||
case 0: joints[jno] = pos->tran.x; break;
|
||||
case 1: joints[jno] = pos->tran.y; break;
|
||||
case 2: joints[jno] = pos->tran.z; break;
|
||||
case 3: joints[jno] = pos->a; break;
|
||||
case 4: joints[jno] = pos->b; break;
|
||||
case 5: joints[jno] = pos->c; break;
|
||||
case 6: joints[jno] = pos->u; break;
|
||||
case 7: joints[jno] = pos->v; break;
|
||||
case 8: joints[jno] = pos->w; break;
|
||||
default: joints[jno] = 0.0; break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define hal_malloc(size) ((struct haldata *)cnc_sim_hal_malloc(size))
|
||||
#include "../../../linuxcnc/src/emc/kinematics/trtfuncs.c"
|
||||
#undef hal_malloc
|
||||
|
||||
void cnc_sim_linuxcnc_trtfuncs_reset_setup_state(void) {
|
||||
trtfuncs_max_joints = 0;
|
||||
JX = -1;
|
||||
JY = -1;
|
||||
JZ = -1;
|
||||
JA = -1;
|
||||
JB = -1;
|
||||
JC = -1;
|
||||
JU = -1;
|
||||
JV = -1;
|
||||
JW = -1;
|
||||
haldata = NULL;
|
||||
cnc_sim_max_joints = 0;
|
||||
for (int i = 0; i < EMCMOT_MAX_JOINTS; ++i) {
|
||||
cnc_sim_axis_idx_for_jno[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_trtfuncs_setup_xyzbc(void) {
|
||||
kparms kp = {0};
|
||||
static char kinsname[] = "xyzbc-trt-kins";
|
||||
static char halprefix[] = "xyzbc-trt-kins";
|
||||
static char required_coordinates[] = "XYZBC";
|
||||
kp.kinsname = kinsname;
|
||||
kp.halprefix = halprefix;
|
||||
kp.required_coordinates = required_coordinates;
|
||||
kp.max_joints = EMCMOT_MAX_JOINTS;
|
||||
kp.allow_duplicates = 1;
|
||||
return trtKinematicsSetup(0, "XYZBC", &kp);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_trtfuncs_setup_xyzac(void) {
|
||||
kparms kp = {0};
|
||||
static char kinsname[] = "xyzac-trt-kins";
|
||||
static char halprefix[] = "xyzac-trt-kins";
|
||||
static char required_coordinates[] = "XYZAC";
|
||||
kp.kinsname = kinsname;
|
||||
kp.halprefix = halprefix;
|
||||
kp.required_coordinates = required_coordinates;
|
||||
kp.max_joints = EMCMOT_MAX_JOINTS;
|
||||
kp.allow_duplicates = 1;
|
||||
return trtKinematicsSetup(0, "XYZAC", &kp);
|
||||
}
|
||||
|
||||
void cnc_sim_linuxcnc_trtfuncs_set_pins(double x_rot_point,
|
||||
double y_rot_point,
|
||||
double z_rot_point,
|
||||
double x_offset,
|
||||
double y_offset,
|
||||
double z_offset,
|
||||
double tool_offset,
|
||||
bool conventional_directions) {
|
||||
*haldata->x_rot_point = x_rot_point;
|
||||
*haldata->y_rot_point = y_rot_point;
|
||||
*haldata->z_rot_point = z_rot_point;
|
||||
*haldata->x_offset = x_offset;
|
||||
*haldata->y_offset = y_offset;
|
||||
*haldata->z_offset = z_offset;
|
||||
*haldata->tool_offset = tool_offset;
|
||||
*haldata->conventional_directions = conventional_directions;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
241
core/src/linuxcnc_trtfuncs_adapter.cpp
Normal file
241
core/src/linuxcnc_trtfuncs_adapter.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
#include "linuxcnc_trtfuncs_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
int cnc_sim_linuxcnc_trtfuncs_setup_xyzbc(void);
|
||||
int cnc_sim_linuxcnc_trtfuncs_setup_xyzac(void);
|
||||
void cnc_sim_linuxcnc_trtfuncs_set_pins(double x_rot_point,
|
||||
double y_rot_point,
|
||||
double z_rot_point,
|
||||
double x_offset,
|
||||
double y_offset,
|
||||
double z_offset,
|
||||
double tool_offset,
|
||||
bool conventional_directions);
|
||||
void cnc_sim_linuxcnc_trtfuncs_reset_setup_state(void);
|
||||
int xyzbcKinematicsForward(const double *joints,
|
||||
EmcPose *pos,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags);
|
||||
int xyzbcKinematicsInverse(const EmcPose *pos,
|
||||
double *joints,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags);
|
||||
int xyzacKinematicsForward(const double *joints,
|
||||
EmcPose *pos,
|
||||
const KINEMATICS_FORWARD_FLAGS *fflags,
|
||||
KINEMATICS_INVERSE_FLAGS *iflags);
|
||||
int xyzacKinematicsInverse(const EmcPose *pos,
|
||||
double *joints,
|
||||
const KINEMATICS_INVERSE_FLAGS *iflags,
|
||||
KINEMATICS_FORWARD_FLAGS *fflags);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
enum class TrtSetup {
|
||||
None,
|
||||
Xyzbc,
|
||||
Xyzac,
|
||||
};
|
||||
|
||||
TrtSetup current_setup = TrtSetup::None;
|
||||
|
||||
bool ensure_xyzbc() {
|
||||
if (current_setup == TrtSetup::Xyzbc) {
|
||||
return true;
|
||||
}
|
||||
cnc_sim_linuxcnc_trtfuncs_reset_setup_state();
|
||||
if (cnc_sim_linuxcnc_trtfuncs_setup_xyzbc() != 0) {
|
||||
current_setup = TrtSetup::None;
|
||||
return false;
|
||||
}
|
||||
current_setup = TrtSetup::Xyzbc;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ensure_xyzac() {
|
||||
if (current_setup == TrtSetup::Xyzac) {
|
||||
return true;
|
||||
}
|
||||
cnc_sim_linuxcnc_trtfuncs_reset_setup_state();
|
||||
if (cnc_sim_linuxcnc_trtfuncs_setup_xyzac() != 0) {
|
||||
current_setup = TrtSetup::None;
|
||||
return false;
|
||||
}
|
||||
current_setup = TrtSetup::Xyzac;
|
||||
return true;
|
||||
}
|
||||
|
||||
void apply_parameters(const LinuxCncXyzbcTrtParameters ¶meters) {
|
||||
cnc_sim_linuxcnc_trtfuncs_set_pins(parameters.x_rot_point,
|
||||
parameters.y_rot_point,
|
||||
parameters.z_rot_point,
|
||||
parameters.x_offset,
|
||||
parameters.y_offset,
|
||||
parameters.z_offset,
|
||||
parameters.tool_offset,
|
||||
parameters.conventional_directions);
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
void to_xyzbc_joints(const LinuxCncFiveAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.b;
|
||||
out[4] = joints.c;
|
||||
}
|
||||
|
||||
void to_xyzac_joints(const LinuxCncFiveAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.a;
|
||||
out[4] = joints.c;
|
||||
}
|
||||
|
||||
LinuxCncFiveAxisJoints from_xyzbc_joints(const double joints[16]) {
|
||||
LinuxCncFiveAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.b = joints[3];
|
||||
out.c = joints[4];
|
||||
return out;
|
||||
}
|
||||
|
||||
LinuxCncFiveAxisJoints from_xyzac_joints(const double joints[16]) {
|
||||
LinuxCncFiveAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.a = joints[3];
|
||||
out.c = joints[4];
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_trtfuncs_xyzbc_forward(const LinuxCncFiveAxisJoints &joints,
|
||||
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||
CncSimPose *pose) {
|
||||
if (!ensure_xyzbc()) {
|
||||
return false;
|
||||
}
|
||||
apply_parameters(parameters);
|
||||
double raw_joints[16];
|
||||
to_xyzbc_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
if (xyzbcKinematicsForward(raw_joints, &out, &fflags, &iflags) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_trtfuncs_xyzbc_inverse(const CncSimPose &pose,
|
||||
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||
LinuxCncFiveAxisJoints *joints) {
|
||||
if (!ensure_xyzbc()) {
|
||||
return false;
|
||||
}
|
||||
apply_parameters(parameters);
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
if (xyzbcKinematicsInverse(&in, raw_joints, &iflags, &fflags) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_xyzbc_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_trtfuncs_xyzac_forward(const LinuxCncFiveAxisJoints &joints,
|
||||
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||
CncSimPose *pose) {
|
||||
if (!ensure_xyzac()) {
|
||||
return false;
|
||||
}
|
||||
apply_parameters(parameters);
|
||||
double raw_joints[16];
|
||||
to_xyzac_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
if (xyzacKinematicsForward(raw_joints, &out, &fflags, &iflags) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_trtfuncs_xyzac_inverse(const CncSimPose &pose,
|
||||
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||
LinuxCncFiveAxisJoints *joints) {
|
||||
if (!ensure_xyzac()) {
|
||||
return false;
|
||||
}
|
||||
apply_parameters(parameters);
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
if (xyzacKinematicsInverse(&in, raw_joints, &iflags, &fflags) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_xyzac_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
16
core/src/linuxcnc_trtfuncs_adapter.h
Normal file
16
core/src/linuxcnc_trtfuncs_adapter.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_trtfuncs_xyzbc_forward(const LinuxCncFiveAxisJoints &joints,
|
||||
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||
CncSimPose *pose);
|
||||
bool linuxcnc_trtfuncs_xyzbc_inverse(const CncSimPose &pose,
|
||||
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||
LinuxCncFiveAxisJoints *joints);
|
||||
bool linuxcnc_trtfuncs_xyzac_forward(const LinuxCncFiveAxisJoints &joints,
|
||||
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||
CncSimPose *pose);
|
||||
bool linuxcnc_trtfuncs_xyzac_inverse(const CncSimPose &pose,
|
||||
const LinuxCncXyzbcTrtParameters ¶meters,
|
||||
LinuxCncFiveAxisJoints *joints);
|
||||
154
core/src/linuxcnc_userkfuncs_adapter.c
Normal file
154
core/src/linuxcnc_userkfuncs_adapter.c
Normal file
@@ -0,0 +1,154 @@
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_STRING_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_EMCMOTCFG_H
|
||||
#define __LINUXCNC_EMCPOS_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
|
||||
#define RTAPI_MSG_ERR 1
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
#define EMCMOT_MAX_AXIS 9
|
||||
|
||||
typedef double hal_float_t;
|
||||
typedef int hal_s32_t;
|
||||
typedef bool hal_bit_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cnc_sim_userk_rtapi_print(const char *fmt, ...) {
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void cnc_sim_userk_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||
(void)level;
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void *cnc_sim_userk_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_userk_hal_pin_s32_new(const char *name,
|
||||
hal_pin_dir_t dir,
|
||||
hal_s32_t **data_ptr_addr,
|
||||
int comp_id) {
|
||||
(void)name;
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
*data_ptr_addr = (hal_s32_t *)calloc(1, sizeof(hal_s32_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
KINEMATICS_TYPE cnc_sim_userk_kinematicsType(void) {
|
||||
return KINEMATICS_BOTH;
|
||||
}
|
||||
|
||||
#define rtapi_print cnc_sim_userk_rtapi_print
|
||||
#define rtapi_print_msg cnc_sim_userk_rtapi_print_msg
|
||||
#define kinematicsType cnc_sim_userk_kinematicsType
|
||||
#define hal_pin_s32_new cnc_sim_userk_hal_pin_s32_new
|
||||
#define map_coordinates_to_jnumbers cnc_sim_userk_map_coordinates_to_jnumbers
|
||||
#define mapped_joints_to_position cnc_sim_userk_mapped_joints_to_position
|
||||
#define position_to_mapped_joints cnc_sim_userk_position_to_mapped_joints
|
||||
#define identityKinematicsSetup cnc_sim_userk_identityKinematicsSetup
|
||||
#define identityKinematicsForward cnc_sim_userk_identityKinematicsForward
|
||||
#define identityKinematicsInverse cnc_sim_userk_identityKinematicsInverse
|
||||
#define userkKinematicsSetup cnc_sim_userk_userkKinematicsSetup
|
||||
#define userkKinematicsForward cnc_sim_userk_userkKinematicsForward
|
||||
#define userkKinematicsInverse cnc_sim_userk_userkKinematicsInverse
|
||||
#include "../../../linuxcnc/src/emc/kinematics/kins_util.c"
|
||||
#define hal_malloc(size) ((struct udata *)cnc_sim_userk_hal_malloc(size))
|
||||
#include "../../../linuxcnc/src/emc/kinematics/userkfuncs.c"
|
||||
#undef hal_malloc
|
||||
#undef userkKinematicsInverse
|
||||
#undef userkKinematicsForward
|
||||
#undef userkKinematicsSetup
|
||||
#undef identityKinematicsInverse
|
||||
#undef identityKinematicsForward
|
||||
#undef identityKinematicsSetup
|
||||
#undef position_to_mapped_joints
|
||||
#undef mapped_joints_to_position
|
||||
#undef map_coordinates_to_jnumbers
|
||||
#undef hal_pin_s32_new
|
||||
#undef kinematicsType
|
||||
#undef rtapi_print_msg
|
||||
#undef rtapi_print
|
||||
|
||||
int cnc_sim_linuxcnc_userkfuncs_setup(void) {
|
||||
kparms kp = {0};
|
||||
static char kinsname[] = "userkfuncs";
|
||||
static char halprefix[] = "userk";
|
||||
kp.kinsname = kinsname;
|
||||
kp.halprefix = halprefix;
|
||||
kp.max_joints = EMCMOT_MAX_JOINTS;
|
||||
kp.allow_duplicates = 1;
|
||||
if (cnc_sim_userk_identityKinematicsSetup(0, "XYZBC", &kp) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return cnc_sim_userk_userkKinematicsSetup(0, "XYZBC", &kp);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_userkfuncs_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_userk_userkKinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_userkfuncs_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_userk_userkKinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
113
core/src/linuxcnc_userkfuncs_adapter.cpp
Normal file
113
core/src/linuxcnc_userkfuncs_adapter.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
#include "linuxcnc_userkfuncs_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_userkfuncs_setup(void);
|
||||
int cnc_sim_linuxcnc_userkfuncs_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_userkfuncs_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_userkfuncs_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncFiveAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.b;
|
||||
out[4] = joints.c;
|
||||
}
|
||||
|
||||
LinuxCncFiveAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncFiveAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.b = joints[3];
|
||||
out.c = joints[4];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_userkfuncs_forward(const LinuxCncFiveAxisJoints &joints, CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_userkfuncs_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_userkfuncs_inverse(const CncSimPose &pose, LinuxCncFiveAxisJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
if (cnc_sim_linuxcnc_userkfuncs_inverse(&in, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
6
core/src/linuxcnc_userkfuncs_adapter.h
Normal file
6
core/src/linuxcnc_userkfuncs_adapter.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_userkfuncs_forward(const LinuxCncFiveAxisJoints &joints, CncSimPose *pose);
|
||||
bool linuxcnc_userkfuncs_inverse(const CncSimPose &pose, LinuxCncFiveAxisJoints *joints);
|
||||
241
core/src/linuxcnc_xyzab_tdr_kins_adapter.c
Normal file
241
core/src/linuxcnc_xyzab_tdr_kins_adapter.c
Normal file
@@ -0,0 +1,241 @@
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define __LINUXCNC_RTAPI_H
|
||||
#define __LINUXCNC_RTAPI_APP_H
|
||||
#define __LINUXCNC_RTAPI_STRING_H
|
||||
#define __LINUXCNC_RTAPI_ERRNO_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_MATH64_H
|
||||
#define __LINUXCNC_HAL_H
|
||||
#define __LINUXCNC_KINEMATICS_H
|
||||
|
||||
#define MODULE_INFO(...)
|
||||
#define MODULE_LICENSE(...)
|
||||
#define EXPORT_SYMBOL(symbol)
|
||||
#define RTAPI_MP_INT(name, description)
|
||||
#define RTAPI_MP_STRING(name, description)
|
||||
|
||||
#define RTAPI_MSG_ERR 1
|
||||
#define RTAPI_MSG_INFO 2
|
||||
#define HAL_NAME_LEN 47
|
||||
#define EINVAL 22
|
||||
#define PM_PI 3.1415926535897932384626433832795029
|
||||
#define TO_RAD (PM_PI / 180.0)
|
||||
|
||||
typedef double real_t;
|
||||
typedef double hal_float_t;
|
||||
typedef int hal_s32_t;
|
||||
typedef unsigned int hal_u32_t;
|
||||
typedef bool hal_bit_t;
|
||||
typedef enum { HAL_IN = 16, HAL_OUT = 32, HAL_IO = (HAL_IN | HAL_OUT) } hal_pin_dir_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} PmCartesian;
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
} EmcPose;
|
||||
|
||||
typedef enum {
|
||||
KINEMATICS_IDENTITY = 1,
|
||||
KINEMATICS_FORWARD_ONLY,
|
||||
KINEMATICS_INVERSE_ONLY,
|
||||
KINEMATICS_BOTH
|
||||
} KINEMATICS_TYPE;
|
||||
|
||||
typedef unsigned long int KINEMATICS_FORWARD_FLAGS;
|
||||
typedef unsigned long int KINEMATICS_INVERSE_FLAGS;
|
||||
|
||||
typedef struct kinematics_parms {
|
||||
char *sparm;
|
||||
char *kinsname;
|
||||
char *halprefix;
|
||||
char *required_coordinates;
|
||||
int max_joints;
|
||||
int allow_duplicates;
|
||||
int fwd_iterates_mask;
|
||||
int gui_kinstype;
|
||||
} kparms;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int __attribute__((weak)) rtapi_snprintf(char *str, unsigned long int size, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
const int result = vsnprintf(str, (size_t)size, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
void cnc_sim_xyzab_tdr_rtapi_print(const char *fmt, ...) {
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void cnc_sim_xyzab_tdr_rtapi_print_msg(int level, const char *fmt, ...) {
|
||||
(void)level;
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
void *cnc_sim_xyzab_tdr_hal_malloc(long int size) {
|
||||
return calloc(1, (size_t)size);
|
||||
}
|
||||
|
||||
int cnc_sim_xyzab_tdr_hal_init(const char *name) {
|
||||
(void)name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cnc_sim_xyzab_tdr_hal_exit(int comp_id) {
|
||||
(void)comp_id;
|
||||
}
|
||||
|
||||
int cnc_sim_xyzab_tdr_hal_ready(int comp_id) {
|
||||
(void)comp_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnc_sim_xyzab_tdr_hal_set_unready(int comp_id) {
|
||||
(void)comp_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnc_sim_xyzab_tdr_hal_pin_s32_newf(hal_pin_dir_t dir,
|
||||
hal_s32_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_s32_t *)calloc(1, sizeof(hal_s32_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_xyzab_tdr_hal_pin_float_newf(hal_pin_dir_t dir,
|
||||
hal_float_t **data_ptr_addr,
|
||||
int comp_id,
|
||||
const char *fmt,
|
||||
...) {
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
(void)fmt;
|
||||
*data_ptr_addr = (hal_float_t *)calloc(1, sizeof(hal_float_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
int cnc_sim_xyzab_tdr_hal_pin_bit_new(const char *name,
|
||||
hal_pin_dir_t dir,
|
||||
hal_bit_t **data_ptr_addr,
|
||||
int comp_id) {
|
||||
(void)name;
|
||||
(void)dir;
|
||||
(void)comp_id;
|
||||
*data_ptr_addr = (hal_bit_t *)calloc(1, sizeof(hal_bit_t));
|
||||
return *data_ptr_addr ? 0 : -1;
|
||||
}
|
||||
|
||||
#define rtapi_print cnc_sim_xyzab_tdr_rtapi_print
|
||||
#define rtapi_print_msg cnc_sim_xyzab_tdr_rtapi_print_msg
|
||||
#define hal_malloc(size) cnc_sim_xyzab_tdr_hal_malloc(size)
|
||||
#define hal_init cnc_sim_xyzab_tdr_hal_init
|
||||
#define hal_exit cnc_sim_xyzab_tdr_hal_exit
|
||||
#define hal_ready cnc_sim_xyzab_tdr_hal_ready
|
||||
#define hal_set_unready cnc_sim_xyzab_tdr_hal_set_unready
|
||||
#define hal_pin_s32_newf cnc_sim_xyzab_tdr_hal_pin_s32_newf
|
||||
#define hal_pin_float_newf cnc_sim_xyzab_tdr_hal_pin_float_newf
|
||||
#define hal_pin_bit_new cnc_sim_xyzab_tdr_hal_pin_bit_new
|
||||
#define kinematicsType cnc_sim_xyzab_tdr_kinematicsType
|
||||
#define kinematicsSwitchable cnc_sim_xyzab_tdr_kinematicsSwitchable
|
||||
#define kinematicsSwitch cnc_sim_xyzab_tdr_kinematicsSwitch
|
||||
#define kinematicsForward cnc_sim_xyzab_tdr_kinematicsForward
|
||||
#define kinematicsInverse cnc_sim_xyzab_tdr_kinematicsInverse
|
||||
#define rtapi_app_main cnc_sim_xyzab_tdr_rtapi_app_main
|
||||
#define rtapi_app_exit cnc_sim_xyzab_tdr_rtapi_app_exit
|
||||
#define export cnc_sim_xyzab_tdr_export
|
||||
#include "../../../linuxcnc/src/objects/hal/components/xyzab_tdr_kins.c"
|
||||
#undef export
|
||||
#undef rtapi_app_exit
|
||||
#undef rtapi_app_main
|
||||
#undef kinematicsInverse
|
||||
#undef kinematicsForward
|
||||
#undef kinematicsSwitch
|
||||
#undef kinematicsSwitchable
|
||||
#undef kinematicsType
|
||||
#undef hal_pin_bit_new
|
||||
#undef hal_pin_float_newf
|
||||
#undef hal_pin_s32_newf
|
||||
#undef hal_set_unready
|
||||
#undef hal_ready
|
||||
#undef hal_exit
|
||||
#undef hal_init
|
||||
#undef hal_malloc
|
||||
#undef rtapi_print_msg
|
||||
#undef rtapi_print
|
||||
|
||||
int cnc_sim_linuxcnc_xyzab_tdr_kins_setup(void) {
|
||||
return cnc_sim_xyzab_tdr_kinematicsType() == KINEMATICS_BOTH ? 0 : -1;
|
||||
}
|
||||
|
||||
void cnc_sim_linuxcnc_xyzab_tdr_kins_set_parameters(double tool_offset_z,
|
||||
double x_offset,
|
||||
double z_offset,
|
||||
double x_rot_point,
|
||||
double y_rot_point,
|
||||
double z_rot_point) {
|
||||
*haldata->tool_offset_z = tool_offset_z;
|
||||
*haldata->x_offset = x_offset;
|
||||
*haldata->z_offset = z_offset;
|
||||
*haldata->x_rot_point = x_rot_point;
|
||||
*haldata->y_rot_point = y_rot_point;
|
||||
*haldata->z_rot_point = z_rot_point;
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_xyzab_tdr_kins_switch(int switchkins_type) {
|
||||
return cnc_sim_xyzab_tdr_kinematicsSwitch(switchkins_type);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_xyzab_tdr_kins_switch_state(int *kinstype_is_0, int *kinstype_is_1) {
|
||||
if (!haldata || !haldata->kinstype_is_0 || !haldata->kinstype_is_1) {
|
||||
return -1;
|
||||
}
|
||||
if (kinstype_is_0) {
|
||||
*kinstype_is_0 = *haldata->kinstype_is_0 ? 1 : 0;
|
||||
}
|
||||
if (kinstype_is_1) {
|
||||
*kinstype_is_1 = *haldata->kinstype_is_1 ? 1 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_xyzab_tdr_kins_forward(const double *joints, EmcPose *pos) {
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
return cnc_sim_xyzab_tdr_kinematicsForward(joints, pos, &fflags, &iflags);
|
||||
}
|
||||
|
||||
int cnc_sim_linuxcnc_xyzab_tdr_kins_inverse(const EmcPose *pos, double *joints) {
|
||||
KINEMATICS_INVERSE_FLAGS iflags = 0;
|
||||
KINEMATICS_FORWARD_FLAGS fflags = 0;
|
||||
return cnc_sim_xyzab_tdr_kinematicsInverse(pos, joints, &iflags, &fflags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
177
core/src/linuxcnc_xyzab_tdr_kins_adapter.cpp
Normal file
177
core/src/linuxcnc_xyzab_tdr_kins_adapter.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
#include "linuxcnc_xyzab_tdr_kins_adapter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
struct PmCartesian {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
int cnc_sim_linuxcnc_xyzab_tdr_kins_setup(void);
|
||||
void cnc_sim_linuxcnc_xyzab_tdr_kins_set_parameters(double tool_offset_z,
|
||||
double x_offset,
|
||||
double z_offset,
|
||||
double x_rot_point,
|
||||
double y_rot_point,
|
||||
double z_rot_point);
|
||||
int cnc_sim_linuxcnc_xyzab_tdr_kins_switch(int switchkins_type);
|
||||
int cnc_sim_linuxcnc_xyzab_tdr_kins_switch_state(int *kinstype_is_0, int *kinstype_is_1);
|
||||
int cnc_sim_linuxcnc_xyzab_tdr_kins_forward(const double *joints, EmcPose *pos);
|
||||
int cnc_sim_linuxcnc_xyzab_tdr_kins_inverse(const EmcPose *pos, double *joints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ensure_initialized() {
|
||||
if (initialized) {
|
||||
return true;
|
||||
}
|
||||
initialized = cnc_sim_linuxcnc_xyzab_tdr_kins_setup() == 0;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void apply_parameters(const LinuxCncXyzabTdrParameters ¶meters) {
|
||||
cnc_sim_linuxcnc_xyzab_tdr_kins_set_parameters(parameters.tool_offset_z,
|
||||
parameters.x_offset,
|
||||
parameters.z_offset,
|
||||
parameters.x_rot_point,
|
||||
parameters.y_rot_point,
|
||||
parameters.z_rot_point);
|
||||
}
|
||||
|
||||
void to_joints(const LinuxCncAxisJoints &joints, double out[16]) {
|
||||
std::memset(out, 0, sizeof(double) * 16);
|
||||
out[0] = joints.x;
|
||||
out[1] = joints.y;
|
||||
out[2] = joints.z;
|
||||
out[3] = joints.a;
|
||||
out[4] = joints.b;
|
||||
out[5] = joints.c;
|
||||
out[6] = joints.u;
|
||||
out[7] = joints.v;
|
||||
out[8] = joints.w;
|
||||
}
|
||||
|
||||
LinuxCncAxisJoints from_joints(const double joints[16]) {
|
||||
LinuxCncAxisJoints out{};
|
||||
out.x = joints[0];
|
||||
out.y = joints[1];
|
||||
out.z = joints[2];
|
||||
out.a = joints[3];
|
||||
out.b = joints[4];
|
||||
out.c = joints[5];
|
||||
out.u = joints[6];
|
||||
out.v = joints[7];
|
||||
out.w = joints[8];
|
||||
return out;
|
||||
}
|
||||
|
||||
EmcPose to_emc_pose(const CncSimPose &pose) {
|
||||
EmcPose emc{};
|
||||
emc.tran.x = pose.x;
|
||||
emc.tran.y = pose.y;
|
||||
emc.tran.z = pose.z;
|
||||
emc.a = pose.a;
|
||||
emc.b = pose.b;
|
||||
emc.c = pose.c;
|
||||
emc.u = pose.u;
|
||||
emc.v = pose.v;
|
||||
emc.w = pose.w;
|
||||
return emc;
|
||||
}
|
||||
|
||||
CncSimPose from_emc_pose(const EmcPose &emc) {
|
||||
CncSimPose pose{};
|
||||
pose.x = emc.tran.x;
|
||||
pose.y = emc.tran.y;
|
||||
pose.z = emc.tran.z;
|
||||
pose.a = emc.a;
|
||||
pose.b = emc.b;
|
||||
pose.c = emc.c;
|
||||
pose.u = emc.u;
|
||||
pose.v = emc.v;
|
||||
pose.w = emc.w;
|
||||
return pose;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool linuxcnc_xyzab_tdr_kins_switch(int switchkins_type) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
return cnc_sim_linuxcnc_xyzab_tdr_kins_switch(switchkins_type) == 0;
|
||||
}
|
||||
|
||||
bool linuxcnc_xyzab_tdr_kins_switch_state(bool *kinstype_is_0, bool *kinstype_is_1) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
int raw_kinstype_is_0 = 0;
|
||||
int raw_kinstype_is_1 = 0;
|
||||
if (cnc_sim_linuxcnc_xyzab_tdr_kins_switch_state(&raw_kinstype_is_0, &raw_kinstype_is_1) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (kinstype_is_0) {
|
||||
*kinstype_is_0 = raw_kinstype_is_0 != 0;
|
||||
}
|
||||
if (kinstype_is_1) {
|
||||
*kinstype_is_1 = raw_kinstype_is_1 != 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_xyzab_tdr_kins_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncXyzabTdrParameters ¶meters,
|
||||
int switchkins_type,
|
||||
CncSimPose *pose) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
apply_parameters(parameters);
|
||||
if (!linuxcnc_xyzab_tdr_kins_switch(switchkins_type)) {
|
||||
return false;
|
||||
}
|
||||
double raw_joints[16];
|
||||
to_joints(joints, raw_joints);
|
||||
EmcPose out{};
|
||||
if (cnc_sim_linuxcnc_xyzab_tdr_kins_forward(raw_joints, &out) != 0) {
|
||||
return false;
|
||||
}
|
||||
*pose = from_emc_pose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool linuxcnc_xyzab_tdr_kins_inverse(const CncSimPose &pose,
|
||||
const LinuxCncXyzabTdrParameters ¶meters,
|
||||
int switchkins_type,
|
||||
LinuxCncAxisJoints *joints) {
|
||||
if (!ensure_initialized()) {
|
||||
return false;
|
||||
}
|
||||
apply_parameters(parameters);
|
||||
if (!linuxcnc_xyzab_tdr_kins_switch(switchkins_type)) {
|
||||
return false;
|
||||
}
|
||||
const EmcPose in = to_emc_pose(pose);
|
||||
double raw_joints[16] = {};
|
||||
if (cnc_sim_linuxcnc_xyzab_tdr_kins_inverse(&in, raw_joints) != 0) {
|
||||
return false;
|
||||
}
|
||||
*joints = from_joints(raw_joints);
|
||||
return true;
|
||||
}
|
||||
14
core/src/linuxcnc_xyzab_tdr_kins_adapter.h
Normal file
14
core/src/linuxcnc_xyzab_tdr_kins_adapter.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
bool linuxcnc_xyzab_tdr_kins_switch(int switchkins_type);
|
||||
bool linuxcnc_xyzab_tdr_kins_switch_state(bool *kinstype_is_0, bool *kinstype_is_1);
|
||||
bool linuxcnc_xyzab_tdr_kins_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncXyzabTdrParameters ¶meters,
|
||||
int switchkins_type,
|
||||
CncSimPose *pose);
|
||||
bool linuxcnc_xyzab_tdr_kins_inverse(const CncSimPose &pose,
|
||||
const LinuxCncXyzabTdrParameters ¶meters,
|
||||
int switchkins_type,
|
||||
LinuxCncAxisJoints *joints);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -83,12 +83,78 @@ struct LinuxCncScaraJoints {
|
||||
double j5;
|
||||
};
|
||||
|
||||
struct LinuxCncGenhexJoints {
|
||||
double strut[6];
|
||||
};
|
||||
|
||||
struct LinuxCncPentakinsJoints {
|
||||
double strut[5];
|
||||
};
|
||||
|
||||
struct LinuxCncTripodJoints {
|
||||
double strut[3];
|
||||
};
|
||||
|
||||
struct LinuxCncScorbotJoints {
|
||||
double j0;
|
||||
double j1;
|
||||
double j2;
|
||||
double j3;
|
||||
double j4;
|
||||
};
|
||||
|
||||
struct LinuxCncLinearDeltaParameters {
|
||||
double r;
|
||||
double l;
|
||||
};
|
||||
|
||||
struct LinuxCncRotaryDeltaParameters {
|
||||
double platformradius;
|
||||
double thighlength;
|
||||
double shinlength;
|
||||
double footradius;
|
||||
};
|
||||
|
||||
struct LinuxCncMaxkinsParameters {
|
||||
double pivot_length;
|
||||
bool conventional_directions;
|
||||
};
|
||||
|
||||
LinuxCncAxisJoints linuxcnc_identity_default_joints();
|
||||
CncSimPose linuxcnc_identity_forward(const LinuxCncAxisJoints &joints);
|
||||
LinuxCncAxisJoints linuxcnc_identity_inverse(const CncSimPose &pose);
|
||||
|
||||
CncSimPose linuxcnc_corexykins_forward(const LinuxCncAxisJoints &joints);
|
||||
LinuxCncAxisJoints linuxcnc_corexykins_inverse(const CncSimPose &pose);
|
||||
|
||||
CncSimPose linuxcnc_rotatekins_forward(const LinuxCncAxisJoints &joints);
|
||||
LinuxCncAxisJoints linuxcnc_rotatekins_inverse(const CncSimPose &pose);
|
||||
LinuxCncGenhexJoints linuxcnc_genhex_inverse(const CncSimPose &pose);
|
||||
CncSimPose linuxcnc_genhex_forward(const LinuxCncGenhexJoints &joints, const CncSimPose &initial_pose);
|
||||
LinuxCncPentakinsJoints linuxcnc_pentakins_inverse(const CncSimPose &pose);
|
||||
CncSimPose linuxcnc_pentakins_forward(const LinuxCncPentakinsJoints &joints,
|
||||
const CncSimPose &initial_pose);
|
||||
LinuxCncTripodJoints linuxcnc_tripodkins_inverse(const CncSimPose &pose);
|
||||
CncSimPose linuxcnc_tripodkins_forward(const LinuxCncTripodJoints &joints);
|
||||
LinuxCncScorbotJoints linuxcnc_scorbot_kins_inverse(const CncSimPose &pose);
|
||||
CncSimPose linuxcnc_scorbot_kins_forward(const LinuxCncScorbotJoints &joints);
|
||||
LinuxCncLinearDeltaParameters linuxcnc_lineardelta_default_parameters();
|
||||
CncSimPose linuxcnc_lineardelta_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncLinearDeltaParameters ¶meters);
|
||||
LinuxCncAxisJoints linuxcnc_lineardelta_inverse(const CncSimPose &pose,
|
||||
const LinuxCncLinearDeltaParameters ¶meters);
|
||||
LinuxCncRotaryDeltaParameters linuxcnc_rotarydelta_default_parameters();
|
||||
CncSimPose linuxcnc_rotarydelta_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncRotaryDeltaParameters ¶meters);
|
||||
LinuxCncAxisJoints linuxcnc_rotarydelta_inverse(const CncSimPose &pose,
|
||||
const LinuxCncRotaryDeltaParameters ¶meters);
|
||||
LinuxCncMaxkinsParameters linuxcnc_maxkins_default_parameters();
|
||||
CncSimPose linuxcnc_maxkins_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncMaxkinsParameters ¶meters);
|
||||
LinuxCncAxisJoints linuxcnc_maxkins_inverse(const CncSimPose &pose,
|
||||
const LinuxCncMaxkinsParameters ¶meters);
|
||||
CncSimPose linuxcnc_rosekins_forward(const LinuxCncAxisJoints &joints);
|
||||
LinuxCncAxisJoints linuxcnc_rosekins_inverse(const CncSimPose &pose);
|
||||
|
||||
CncSimPose linuxcnc_5axis_forward(const LinuxCncFiveAxisJoints &joints, double pivot_length);
|
||||
LinuxCncFiveAxisJoints linuxcnc_5axis_inverse(const CncSimPose &pose, double pivot_length);
|
||||
@@ -132,6 +198,7 @@ LinuxCncAxisJoints linuxcnc_puma_inverse(const CncSimPose &pose,
|
||||
int *fflags);
|
||||
|
||||
LinuxCncGenserParameters linuxcnc_genser_puma560_parameters();
|
||||
LinuxCncGenserParameters linuxcnc_genser_default_parameters(int *max_iterations = nullptr);
|
||||
CncSimPose linuxcnc_genser_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncGenserParameters ¶meters);
|
||||
LinuxCncAxisJoints linuxcnc_genser_inverse(const CncSimPose &pose,
|
||||
@@ -139,3 +206,9 @@ LinuxCncAxisJoints linuxcnc_genser_inverse(const CncSimPose &pose,
|
||||
const LinuxCncGenserParameters ¶meters,
|
||||
int *iterations,
|
||||
int max_iterations = 100);
|
||||
bool linuxcnc_genser_inverse_checked(const CncSimPose &pose,
|
||||
const LinuxCncAxisJoints &joint_estimate,
|
||||
const LinuxCncGenserParameters ¶meters,
|
||||
LinuxCncAxisJoints *joints,
|
||||
int *iterations,
|
||||
int max_iterations = 100);
|
||||
|
||||
@@ -295,12 +295,25 @@ bool parse_simulator_gcode_control_line(const std::string &line,
|
||||
return false;
|
||||
}
|
||||
|
||||
void emit_simulator_gcode_control_action(CanonEventSink &sink,
|
||||
bool can_emit_simulator_gcode_control_action(const CanonEventSink &sink,
|
||||
const SimulatorGcodeControlAction &action) {
|
||||
if (action.kind == SimulatorGcodeControlKind::KinematicsSwitch) {
|
||||
return sink.can_switch_m_code_kinematics(action.m_code);
|
||||
}
|
||||
if (action.kind == SimulatorGcodeControlKind::RtcpState) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emit_simulator_gcode_control_action(CanonEventSink &sink,
|
||||
const SimulatorGcodeControlAction &action,
|
||||
int line) {
|
||||
if (action.kind == SimulatorGcodeControlKind::KinematicsSwitch) {
|
||||
sink.switch_m_code_kinematics(action.m_code, action.value, line);
|
||||
return sink.switch_m_code_kinematics(action.m_code, action.value, line);
|
||||
} else if (action.kind == SimulatorGcodeControlKind::RtcpState) {
|
||||
sink.set_rtcp_state(action.rtcp_enabled, action.h_code, line);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ bool parse_simulator_gcode_control_line(const std::string &line,
|
||||
bool parse_simulator_gcode_control_line(const std::string &line,
|
||||
bool block_delete,
|
||||
std::vector<SimulatorGcodeControlAction> *actions);
|
||||
void emit_simulator_gcode_control_action(CanonEventSink &sink,
|
||||
bool can_emit_simulator_gcode_control_action(const CanonEventSink &sink,
|
||||
const SimulatorGcodeControlAction &action);
|
||||
bool emit_simulator_gcode_control_action(CanonEventSink &sink,
|
||||
const SimulatorGcodeControlAction &action,
|
||||
int line);
|
||||
|
||||
@@ -180,6 +180,7 @@ size_t leading_special_word_start(const std::string &line);
|
||||
bool is_numeric_m98_subprogram_header(const std::string &line);
|
||||
OwordKind oword_kind(const std::string &line);
|
||||
bool integer_word_value(const std::unordered_map<char, double> &words, char letter, int *value);
|
||||
bool smoke_ini_raw_value(const std::string §ion, const std::string &key, std::string *value);
|
||||
bool evaluate_expression(const std::string &text,
|
||||
const std::vector<CallFrame> &call_stack,
|
||||
const std::unordered_map<int, double> ¶meters,
|
||||
@@ -444,6 +445,20 @@ bool parse_smoke_hal_named_parameter(const std::string &name, std::string *pin)
|
||||
}
|
||||
|
||||
bool smoke_ini_value(const std::string §ion, const std::string &key, double *value) {
|
||||
std::string raw_value;
|
||||
if (!smoke_ini_raw_value(section, key, &raw_value)) {
|
||||
return false;
|
||||
}
|
||||
char *end = nullptr;
|
||||
const double parsed = std::strtod(raw_value.c_str(), &end);
|
||||
if (end == raw_value.c_str()) {
|
||||
return false;
|
||||
}
|
||||
*value = parsed;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool smoke_ini_raw_value(const std::string §ion, const std::string &key, std::string *value) {
|
||||
const char *path = std::getenv("INI_FILE_NAME");
|
||||
if (!path || !*path) {
|
||||
return false;
|
||||
@@ -474,18 +489,20 @@ bool smoke_ini_value(const std::string §ion, const std::string &key, double
|
||||
if (ini_lookup_key(text.substr(0, equals)) != key) {
|
||||
continue;
|
||||
}
|
||||
char *end = nullptr;
|
||||
const std::string raw_value = trim(text.substr(equals + 1));
|
||||
const double parsed = std::strtod(raw_value.c_str(), &end);
|
||||
if (end == raw_value.c_str()) {
|
||||
return false;
|
||||
}
|
||||
*value = parsed;
|
||||
*value = trim(text.substr(equals + 1));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
double smoke_metric_machine_value() {
|
||||
std::string linear_units;
|
||||
if (!smoke_ini_raw_value("TRAJ", "LINEAR_UNITS", &linear_units)) {
|
||||
return -1.0;
|
||||
}
|
||||
return linear_units == "inch" ? 0.0 : 1.0;
|
||||
}
|
||||
|
||||
bool smoke_hal_value(const std::string &pin, double *value) {
|
||||
const char *path = std::getenv("HAL_PIN_FILE");
|
||||
if (path && *path) {
|
||||
@@ -1735,6 +1752,18 @@ bool smoke_tool_number_exists(int tool_number) {
|
||||
return tool_number == 0 || tool_number == 1 || tool_number == 4;
|
||||
}
|
||||
|
||||
template <typename ToolTable>
|
||||
double smoke_pocket_named_parameter_value(const ToolTable &tool_table, int pocket_index, bool selected_pocket) {
|
||||
const auto it = tool_table.find(pocket_index);
|
||||
if (it == tool_table.end()) {
|
||||
return -1.0;
|
||||
}
|
||||
if (selected_pocket && it->second.pocketno == 0) {
|
||||
return -1.0;
|
||||
}
|
||||
return static_cast<double>(it->second.pocketno);
|
||||
}
|
||||
|
||||
int supported_linuxcnc_g_modal_group(double value) {
|
||||
const int code = linuxcnc_g_code_number(value);
|
||||
if (code < 0 || code >= kLinuxCncGCodeTableSize) {
|
||||
@@ -2333,13 +2362,7 @@ bool is_smoke_readonly_named_parameter(const std::string &name) {
|
||||
name == "_ABS_B" ||
|
||||
name == "_abs_b" ||
|
||||
name == "_ABS_C" ||
|
||||
name == "_abs_c" ||
|
||||
name == "_ABS_U" ||
|
||||
name == "_abs_u" ||
|
||||
name == "_ABS_V" ||
|
||||
name == "_abs_v" ||
|
||||
name == "_ABS_W" ||
|
||||
name == "_abs_w";
|
||||
name == "_abs_c";
|
||||
}
|
||||
|
||||
bool is_smoke_readonly_numbered_parameter(int index) {
|
||||
@@ -5408,6 +5431,8 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
spindle_css_mode_ = false;
|
||||
spindle_tool_id_ = 0;
|
||||
selected_tool_id_ = 0;
|
||||
current_pocket_index_ = 0;
|
||||
selected_pocket_index_ = 0;
|
||||
feed_mode_ = 0;
|
||||
canned_cycle_ = 0;
|
||||
canned_return_to_initial_ = false;
|
||||
@@ -5433,13 +5458,16 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
oword_value_returned_ = false;
|
||||
tool_table_.clear();
|
||||
tool_table_[0] = {};
|
||||
tool_table_[0].pocketno = 0;
|
||||
tool_table_[1] = {};
|
||||
tool_table_[1].pocketno = 1;
|
||||
tool_table_[1].offset.z = 12.5;
|
||||
tool_table_[1].diameter = 6.0;
|
||||
tool_table_[1].frontangle = 12.0;
|
||||
tool_table_[1].backangle = 34.0;
|
||||
tool_table_[1].orientation = 5.0;
|
||||
tool_table_[4] = {};
|
||||
tool_table_[4].pocketno = 4;
|
||||
tool_table_[4].offset.z = 0.7;
|
||||
tool_table_[4].diameter = 1.0;
|
||||
|
||||
@@ -5685,9 +5713,13 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
named_parameters["_CURRENT_TOOL"] = named_parameters["_current_tool"];
|
||||
named_parameters["_selected_tool"] = static_cast<double>(selected_tool_id_);
|
||||
named_parameters["_SELECTED_TOOL"] = named_parameters["_selected_tool"];
|
||||
named_parameters["_current_pocket"] = static_cast<double>(spindle_tool_id_);
|
||||
named_parameters["_current_pocket"] = smoke_pocket_named_parameter_value(tool_table_,
|
||||
current_pocket_index_,
|
||||
false);
|
||||
named_parameters["_CURRENT_POCKET"] = named_parameters["_current_pocket"];
|
||||
named_parameters["_selected_pocket"] = static_cast<double>(selected_tool_id_);
|
||||
named_parameters["_selected_pocket"] = smoke_pocket_named_parameter_value(tool_table_,
|
||||
selected_pocket_index_,
|
||||
true);
|
||||
named_parameters["_SELECTED_POCKET"] = named_parameters["_selected_pocket"];
|
||||
named_parameters["_spindle_rpm_mode"] = spindle_css_mode_ ? 0.0 : 1.0;
|
||||
named_parameters["_SPINDLE_RPM_MODE"] = named_parameters["_spindle_rpm_mode"];
|
||||
@@ -5707,8 +5739,8 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
named_parameters["_VMAJOR"] = 2.10;
|
||||
named_parameters["_vminor"] = 0.0;
|
||||
named_parameters["_VMINOR"] = 0.0;
|
||||
named_parameters["_metric_machine"] = -1.0;
|
||||
named_parameters["_METRIC_MACHINE"] = -1.0;
|
||||
named_parameters["_metric_machine"] = smoke_metric_machine_value();
|
||||
named_parameters["_METRIC_MACHINE"] = named_parameters["_metric_machine"];
|
||||
named_parameters["_task"] = 0.0;
|
||||
named_parameters["_TASK"] = 0.0;
|
||||
const bool has_tool_offset = tool_length_offset.x != 0.0 ||
|
||||
@@ -5747,18 +5779,12 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
named_parameters["_abs_a"] = position.a;
|
||||
named_parameters["_abs_b"] = position.b;
|
||||
named_parameters["_abs_c"] = position.c;
|
||||
named_parameters["_abs_u"] = position.u;
|
||||
named_parameters["_abs_v"] = position.v;
|
||||
named_parameters["_abs_w"] = position.w;
|
||||
named_parameters["_ABS_X"] = position.x;
|
||||
named_parameters["_ABS_Y"] = position.y;
|
||||
named_parameters["_ABS_Z"] = position.z;
|
||||
named_parameters["_ABS_A"] = position.a;
|
||||
named_parameters["_ABS_B"] = position.b;
|
||||
named_parameters["_ABS_C"] = position.c;
|
||||
named_parameters["_ABS_U"] = position.u;
|
||||
named_parameters["_ABS_V"] = position.v;
|
||||
named_parameters["_ABS_W"] = position.w;
|
||||
|
||||
const CncSimPose &probe_position = sink_.probe_position();
|
||||
parameters[5061] = probe_position.x;
|
||||
@@ -5956,14 +5982,34 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
if (!has_keyword_oword &&
|
||||
parse_simulator_gcode_control_line(line, sink_.block_delete(), &simulator_control_actions)) {
|
||||
bool simulator_only_line = true;
|
||||
bool all_control_actions_handled = true;
|
||||
for (const auto &action : simulator_control_actions) {
|
||||
emit_simulator_gcode_control_action(sink_, action, line_number);
|
||||
if (!can_emit_simulator_gcode_control_action(sink_, action)) {
|
||||
all_control_actions_handled = false;
|
||||
simulator_only_line = false;
|
||||
}
|
||||
if (action.kind == SimulatorGcodeControlKind::RtcpState &&
|
||||
!action.rtcp_enabled) {
|
||||
simulator_only_line = false;
|
||||
}
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
return -1;
|
||||
}
|
||||
if (!all_control_actions_handled && simulator_control_actions.size() > 1) {
|
||||
for (const auto &action : simulator_control_actions) {
|
||||
if (!can_emit_simulator_gcode_control_action(sink_, action) &&
|
||||
action.kind == SimulatorGcodeControlKind::KinematicsSwitch) {
|
||||
if (error) {
|
||||
*error = "M-code greater than 199: M" + std::to_string(action.m_code);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (all_control_actions_handled) {
|
||||
for (const auto &action : simulator_control_actions) {
|
||||
emit_simulator_gcode_control_action(sink_, action, line_number);
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (simulator_only_line) {
|
||||
@@ -7704,6 +7750,15 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
for (int m : m_codes) {
|
||||
if ((m == 428 || m == 429 || m == 430) &&
|
||||
!sink_.can_switch_m_code_kinematics(m)) {
|
||||
if (error) {
|
||||
*error = "M-code greater than 199: M" + std::to_string(m);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (modal_motion_is_threading(modal_motion) && words.count('F')) {
|
||||
if (error) {
|
||||
@@ -7764,6 +7819,7 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
}
|
||||
sink_.select_tool(tool_id);
|
||||
selected_tool_id_ = tool_id;
|
||||
selected_pocket_index_ = tool_id;
|
||||
tool_selected_ = true;
|
||||
}
|
||||
|
||||
@@ -7910,6 +7966,10 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
return -1;
|
||||
}
|
||||
if (selected_tool_id_ == 0) {
|
||||
spindle_tool_id_ = 0;
|
||||
}
|
||||
current_pocket_index_ = selected_pocket_index_;
|
||||
} else if (m == 7) {
|
||||
sink_.set_mist_on(true);
|
||||
emit_comment_state(sink_, line_number, 11);
|
||||
@@ -8058,6 +8118,10 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
}
|
||||
sink_.select_tool(tool_number);
|
||||
sink_.change_tool(line_number);
|
||||
if (tool_number == 0) {
|
||||
spindle_tool_id_ = 0;
|
||||
}
|
||||
current_pocket_index_ = tool_number;
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -8192,17 +8256,32 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
return -1;
|
||||
}
|
||||
} else if (m == 428) {
|
||||
sink_.switch_kinematics(1, line_number);
|
||||
if (!sink_.switch_m_code_kinematics(428, 1, line_number)) {
|
||||
if (error) {
|
||||
*error = "M-code greater than 199: M428";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
return -1;
|
||||
}
|
||||
} else if (m == 429) {
|
||||
sink_.switch_kinematics(0, line_number);
|
||||
if (!sink_.switch_m_code_kinematics(429, 0, line_number)) {
|
||||
if (error) {
|
||||
*error = "M-code greater than 199: M429";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
return -1;
|
||||
}
|
||||
} else if (m == 430) {
|
||||
sink_.switch_kinematics(2, line_number);
|
||||
if (!sink_.switch_m_code_kinematics(430, 2, line_number)) {
|
||||
if (error) {
|
||||
*error = "M-code greater than 199: M430";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ public:
|
||||
|
||||
private:
|
||||
struct SmokeToolTableEntry {
|
||||
int pocketno = 0;
|
||||
CncSimPose offset{};
|
||||
double diameter = 0.0;
|
||||
double frontangle = 0.0;
|
||||
@@ -64,5 +65,7 @@ private:
|
||||
double oword_return_value_ = 0.0;
|
||||
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_;
|
||||
};
|
||||
|
||||
@@ -297,6 +297,45 @@ int main() {
|
||||
}
|
||||
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);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
@@ -55,6 +56,16 @@ bool saw_comment_state(const std::vector<CncSimEvent> &events,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool saw_any_kinematics_switch(const std::vector<CncSimEvent> &events, int line) {
|
||||
for (const auto &event : events) {
|
||||
if (event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == line) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
@@ -521,6 +532,109 @@ int main() {
|
||||
ok &= expect(saw_g49_tool_offset_parameter_before && saw_g49_tool_offset_parameter_after,
|
||||
"expected LinuxCNC G49 to clear the applied tool offset parameter before the next motion");
|
||||
|
||||
const char tool_pocket_named_parameter_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"T1\n"
|
||||
"O10 if [[#<_selected_tool> EQ 1] AND [#<_current_tool> EQ 0] AND [#<_selected_pocket> EQ 1] AND [#<_current_pocket> EQ 0]]\n"
|
||||
"G1 X1 F100\n"
|
||||
"O10 endif\n"
|
||||
"M6\n"
|
||||
"O20 if [[#<_selected_tool> EQ 1] AND [#<_current_tool> EQ 0] AND [#<_selected_pocket> EQ 1] AND [#<_current_pocket> EQ 1]]\n"
|
||||
"G1 Y1 F100\n"
|
||||
"O20 endif\n"
|
||||
"M30\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
tool_pocket_named_parameter_program,
|
||||
sizeof(tool_pocket_named_parameter_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_tool_pocket_before_change = false;
|
||||
bool saw_tool_pocket_after_change = false;
|
||||
for (const auto &event : events) {
|
||||
saw_tool_pocket_before_change = saw_tool_pocket_before_change ||
|
||||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||
event.line == 4 &&
|
||||
near(event.end.x, 1.0));
|
||||
saw_tool_pocket_after_change = saw_tool_pocket_after_change ||
|
||||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||
event.line == 8 &&
|
||||
near(event.end.y, 1.0));
|
||||
}
|
||||
ok &= expect(saw_tool_pocket_before_change && saw_tool_pocket_after_change,
|
||||
"expected LinuxCNC tool pocket named parameters to follow selected/current pocket indexes");
|
||||
|
||||
const char m61_tool_pocket_named_parameter_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"M61 Q1\n"
|
||||
"O10 if [[#<_selected_tool> EQ 0] AND [#<_current_tool> EQ 0] AND [#<_selected_pocket> EQ -1] AND [#<_current_pocket> EQ 1]]\n"
|
||||
"G1 X1 F100\n"
|
||||
"O10 endif\n"
|
||||
"M30\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
m61_tool_pocket_named_parameter_program,
|
||||
sizeof(m61_tool_pocket_named_parameter_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_m61_tool_pocket_named_parameter = false;
|
||||
for (const auto &event : events) {
|
||||
saw_m61_tool_pocket_named_parameter = saw_m61_tool_pocket_named_parameter ||
|
||||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||
event.line == 4 &&
|
||||
near(event.end.x, 1.0));
|
||||
}
|
||||
ok &= expect(saw_m61_tool_pocket_named_parameter,
|
||||
"expected LinuxCNC M61 to publish the current pocket without changing selected/current tool named parameters");
|
||||
|
||||
{
|
||||
ScopedEnv spindle_tool_env("CNC_SIM_TOOL_IN_SPINDLE", "1");
|
||||
const char m61_unload_spindle_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"M61 Q0\n"
|
||||
"O10 if [#5400 EQ 0]\n"
|
||||
"G1 X1 F100\n"
|
||||
"O10 endif\n"
|
||||
"M30\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
m61_unload_spindle_program,
|
||||
sizeof(m61_unload_spindle_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_m61_unload_spindle = false;
|
||||
for (const auto &event : events) {
|
||||
saw_m61_unload_spindle = saw_m61_unload_spindle ||
|
||||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||
event.line == 4 &&
|
||||
near(event.end.x, 1.0));
|
||||
}
|
||||
ok &= expect(saw_m61_unload_spindle,
|
||||
"expected LinuxCNC M61 Q0 to unload the spindle current tool number");
|
||||
}
|
||||
|
||||
{
|
||||
ScopedEnv spindle_tool_env("CNC_SIM_TOOL_IN_SPINDLE", "1");
|
||||
const char t0_m6_unload_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"T0 M6\n"
|
||||
"O10 if [#5400 EQ 0]\n"
|
||||
"G1 X1 F100\n"
|
||||
"O10 endif\n"
|
||||
"M30\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
t0_m6_unload_program,
|
||||
sizeof(t0_m6_unload_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_t0_m6_unload = false;
|
||||
for (const auto &event : events) {
|
||||
saw_t0_m6_unload = saw_t0_m6_unload ||
|
||||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||
event.line == 4 &&
|
||||
near(event.end.x, 1.0));
|
||||
}
|
||||
ok &= expect(saw_t0_m6_unload,
|
||||
"expected LinuxCNC T0 M6 to unload the spindle current tool number");
|
||||
}
|
||||
|
||||
const char spindle_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"S1200 M3\n"
|
||||
@@ -1443,6 +1557,26 @@ int main() {
|
||||
ok &= expect(saw_bracket_m428, "expected LinuxCNC source M[428] to execute as M428");
|
||||
ok &= expect(saw_bracket_g434, "expected LinuxCNC source G[43.4] H[7] to execute as G43.4 H7");
|
||||
|
||||
const char table_dual_config[] =
|
||||
"{\"backend\":\"linuxcnc-rs274\","
|
||||
"\"config\":\"configs/sim/axis/vismach/5axis/table-dual-rotary/xyzab-tdr.ini\"}";
|
||||
ok &= expect(cnc_sim_load_config_json(sim, table_dual_config, sizeof(table_dual_config) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
const char mixed_unremapped_m430_program[] =
|
||||
"G21 G90\n"
|
||||
"M428 M430\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
mixed_unremapped_m430_program,
|
||||
sizeof(mixed_unremapped_m430_program) - 1) != 0,
|
||||
"expected LinuxCNC source-backed config without 430remap.ngc to reject mixed M428/M430");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "M-code greater than 199: M430",
|
||||
"expected LinuxCNC source-backed mixed M428/M430 error to name unremapped M430");
|
||||
ok &= expect(!saw_any_kinematics_switch(events, 2),
|
||||
"expected LinuxCNC source-backed mixed M428/M430 error to emit no partial switch");
|
||||
ok &= expect(cnc_sim_load_config_json(sim, config, sizeof(config) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
|
||||
const char exponent_m428_control_program[] =
|
||||
"G21 G90\n"
|
||||
"M4.28e2\n";
|
||||
|
||||
@@ -109,11 +109,92 @@ bool saw_comment_state(const std::vector<CncSimEvent> &events,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool saw_kinematics_switch(const std::vector<CncSimEvent> &events, int line, int kinstype) {
|
||||
for (const auto &event : events) {
|
||||
if (event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == line &&
|
||||
event.reserved == kinstype) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool saw_any_kinematics_switch(const std::vector<CncSimEvent> &events, int line) {
|
||||
for (const auto &event : events) {
|
||||
if (event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == line) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool expect_switchkins_remap_config(const std::string &json,
|
||||
int m428_type,
|
||||
int m429_type,
|
||||
int m430_type,
|
||||
const char *message) {
|
||||
std::vector<CncSimEvent> events;
|
||||
CncSimHandle *sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(sim, collect_event, &events);
|
||||
const char supported_program[] =
|
||||
"M428\n"
|
||||
"M429\n";
|
||||
const char full_program[] =
|
||||
"M428\n"
|
||||
"M429\n"
|
||||
"M430\n";
|
||||
const char *program = m430_type >= 0 ? full_program : supported_program;
|
||||
const size_t program_len = m430_type >= 0 ? sizeof(full_program) - 1 : sizeof(supported_program) - 1;
|
||||
bool ok = true;
|
||||
ok &= expect(cnc_sim_load_config_json(sim, json.c_str(), json.size()) == 0, cnc_sim_last_error(sim));
|
||||
ok &= expect(cnc_sim_parse_program(sim, program, program_len) == 0, cnc_sim_last_error(sim));
|
||||
ok &= expect(saw_kinematics_switch(events, 1, m428_type), message);
|
||||
ok &= expect(saw_kinematics_switch(events, 2, m429_type), message);
|
||||
if (m430_type >= 0) {
|
||||
ok &= expect(saw_kinematics_switch(events, 3, m430_type), message);
|
||||
} else {
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim, "M430\n", 5) != 0, message);
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "M-code greater than 199: M430", message);
|
||||
ok &= expect(!saw_kinematics_switch(events, 1, 2), message);
|
||||
|
||||
std::vector<CncSimEvent> mixed_events;
|
||||
CncSimHandle *mixed_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(mixed_sim, collect_event, &mixed_events);
|
||||
ok &= expect(cnc_sim_load_config_json(mixed_sim, json.c_str(), json.size()) == 0,
|
||||
cnc_sim_last_error(mixed_sim));
|
||||
ok &= expect(cnc_sim_parse_program(mixed_sim, "M428 M430\n", 9) != 0, message);
|
||||
ok &= expect(std::string(cnc_sim_last_error(mixed_sim)) == "M-code greater than 199: M430", message);
|
||||
ok &= expect(!saw_any_kinematics_switch(mixed_events, 1), message);
|
||||
cnc_sim_destroy(mixed_sim);
|
||||
}
|
||||
cnc_sim_destroy(sim);
|
||||
return ok;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
ScopedTempDir temp_dir("cnc_sim_api_smoke");
|
||||
|
||||
#ifndef CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
||||
{
|
||||
CncSimHandle *default_sim = cnc_sim_create();
|
||||
const char default_program[] = "G21\nM30\n";
|
||||
const int default_rc = cnc_sim_parse_program(default_sim,
|
||||
default_program,
|
||||
sizeof(default_program) - 1);
|
||||
const bool default_ok = expect(default_rc != 0,
|
||||
"default LinuxCNC backend must not fall back to smoke parser");
|
||||
cnc_sim_destroy(default_sim);
|
||||
if (!default_ok) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const char program[] =
|
||||
"G21 G90 G17\n"
|
||||
"T1 M6\n"
|
||||
@@ -1311,11 +1392,11 @@ int main() {
|
||||
const char selected_current_tool_named_param_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"T1\n"
|
||||
"O10 if [[#<_selected_tool> EQ 1] AND [#<_current_tool> EQ 0]]\n"
|
||||
"O10 if [[#<_selected_tool> EQ 1] AND [#<_current_tool> EQ 0] AND [#<_selected_pocket> EQ 1] AND [#<_current_pocket> EQ 0]]\n"
|
||||
"G1 X1 F100\n"
|
||||
"O10 endif\n"
|
||||
"M6\n"
|
||||
"O20 if [[#<_selected_tool> EQ 1] AND [#<_current_tool> EQ 0]]\n"
|
||||
"O20 if [[#<_selected_tool> EQ 1] AND [#<_current_tool> EQ 0] AND [#<_selected_pocket> EQ 1] AND [#<_current_pocket> EQ 1]]\n"
|
||||
"G1 Y1\n"
|
||||
"O20 endif\n";
|
||||
events.clear();
|
||||
@@ -1336,14 +1417,14 @@ int main() {
|
||||
near(event.end.y, 1.0));
|
||||
}
|
||||
ok &= expect(saw_selected_tool_before_change,
|
||||
"expected LinuxCNC T word to update selected tool before current tool");
|
||||
"expected LinuxCNC T word to update selected tool/pocket before current tool/pocket");
|
||||
ok &= expect(saw_current_tool_after_change,
|
||||
"expected LinuxCNC M6 to keep current tool tied to #5400 in the nonrandom fixture");
|
||||
"expected LinuxCNC M6 to keep current tool tied to #5400 while updating current pocket in the nonrandom fixture");
|
||||
|
||||
const char m61_tool_named_param_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"M61 Q1\n"
|
||||
"O10 if [[#<_selected_tool> EQ 0] AND [#<_current_tool> EQ 0]]\n"
|
||||
"O10 if [[#<_selected_tool> EQ 0] AND [#<_current_tool> EQ 0] AND [#<_selected_pocket> EQ -1] AND [#<_current_pocket> EQ 1]]\n"
|
||||
"G1 X1 F100\n"
|
||||
"O10 endif\n";
|
||||
events.clear();
|
||||
@@ -1359,7 +1440,7 @@ int main() {
|
||||
near(event.end.x, 1.0));
|
||||
}
|
||||
ok &= expect(saw_m61_tool_named_params,
|
||||
"expected LinuxCNC M61 to leave selected/current tool named parameters unchanged in nonrandom fixture");
|
||||
"expected LinuxCNC M61 to update current pocket while leaving selected/current tool named parameters unchanged in nonrandom fixture");
|
||||
|
||||
const char dynamic_tool_length_program[] =
|
||||
"G21 G90 G17\n"
|
||||
@@ -5404,7 +5485,7 @@ int main() {
|
||||
const char spindle_tool_info_parameter_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"F100\n"
|
||||
"O10 if [[#5400 EQ 1] AND [#5410 EQ 6] AND [#5411 EQ 12] AND [#5412 EQ 34] AND [#5413 EQ 5]]\n"
|
||||
"O10 if [[#5400 EQ 1] AND [#5410 EQ 6] AND [#5411 EQ 12] AND [#5412 EQ 34] AND [#5413 EQ 5] AND [#<_current_pocket> EQ 0] AND [#<_selected_pocket> EQ -1]]\n"
|
||||
"G1 X1\n"
|
||||
"O10 endif\n";
|
||||
events.clear();
|
||||
@@ -5420,7 +5501,57 @@ int main() {
|
||||
near(event.end.x, 1.0));
|
||||
}
|
||||
ok &= expect(saw_spindle_tool_info_parameter,
|
||||
"expected LinuxCNC numbered tool info parameters for preloaded spindle tool");
|
||||
"expected LinuxCNC numbered tool info parameters and pocket named parameters for preloaded spindle tool");
|
||||
}
|
||||
|
||||
{
|
||||
ScopedEnv spindle_tool_env("CNC_SIM_TOOL_IN_SPINDLE", "1");
|
||||
const char m61_unload_spindle_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"M61 Q0\n"
|
||||
"O10 if [#5400 EQ 0]\n"
|
||||
"G1 X1 F100\n"
|
||||
"O10 endif\n"
|
||||
"M30\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
m61_unload_spindle_program,
|
||||
sizeof(m61_unload_spindle_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_m61_unload_spindle = false;
|
||||
for (const auto &event : events) {
|
||||
saw_m61_unload_spindle = saw_m61_unload_spindle ||
|
||||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||
event.line == 4 &&
|
||||
near(event.end.x, 1.0));
|
||||
}
|
||||
ok &= expect(saw_m61_unload_spindle,
|
||||
"expected LinuxCNC M61 Q0 to unload the spindle current tool number");
|
||||
}
|
||||
|
||||
{
|
||||
ScopedEnv spindle_tool_env("CNC_SIM_TOOL_IN_SPINDLE", "1");
|
||||
const char t0_m6_unload_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"T0 M6\n"
|
||||
"O10 if [#5400 EQ 0]\n"
|
||||
"G1 X1 F100\n"
|
||||
"O10 endif\n"
|
||||
"M30\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
t0_m6_unload_program,
|
||||
sizeof(t0_m6_unload_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_t0_m6_unload = false;
|
||||
for (const auto &event : events) {
|
||||
saw_t0_m6_unload = saw_t0_m6_unload ||
|
||||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||
event.line == 4 &&
|
||||
near(event.end.x, 1.0));
|
||||
}
|
||||
ok &= expect(saw_t0_m6_unload,
|
||||
"expected LinuxCNC T0 M6 to unload the spindle current tool number");
|
||||
}
|
||||
|
||||
const char g28_g30_numbered_parameter_program[] =
|
||||
@@ -6210,7 +6341,8 @@ int main() {
|
||||
const std::string ini_path = temp_dir.file("named_ini.ini");
|
||||
{
|
||||
std::ofstream ini(ini_path);
|
||||
ini << "[SETUP]\nXPOS = 3.25\n";
|
||||
ini << "[TRAJ]\nLINEAR_UNITS = inch\n"
|
||||
<< "[SETUP]\nXPOS = 3.25\n";
|
||||
}
|
||||
{
|
||||
ScopedEnv ini_env("INI_FILE_NAME", ini_path.c_str());
|
||||
@@ -6236,6 +6368,25 @@ int main() {
|
||||
event.line == 5 &&
|
||||
event.end.y == 1.0);
|
||||
}
|
||||
|
||||
const char metric_machine_named_parameter_program[] =
|
||||
"G21 G90\n"
|
||||
"F100\n"
|
||||
"G1 X[2 + #<_metric_machine>]\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
metric_machine_named_parameter_program,
|
||||
sizeof(metric_machine_named_parameter_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_inch_metric_machine_named_parameter = false;
|
||||
for (const auto &event : events) {
|
||||
saw_inch_metric_machine_named_parameter = saw_inch_metric_machine_named_parameter ||
|
||||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||
event.line == 3 &&
|
||||
near(event.end.x, 2.0));
|
||||
}
|
||||
ok &= expect(saw_inch_metric_machine_named_parameter,
|
||||
"expected #<_metric_machine> to reflect inch INI LINEAR_UNITS");
|
||||
}
|
||||
ok &= expect(saw_ini_named_parameter_motion, "expected #<_ini[section]key> named parameter lookup");
|
||||
ok &= expect(saw_ini_named_parameter_exists_motion, "expected EXISTS for #<_ini[section]key>");
|
||||
@@ -9881,6 +10032,16 @@ int main() {
|
||||
sizeof(missing_named_parameter_program) - 1) != 0,
|
||||
"expected undefined named parameter read to fail");
|
||||
|
||||
const char missing_abs_uvw_named_parameter_program[] =
|
||||
"G21 G90\n"
|
||||
"F100\n"
|
||||
"G1 X#<_abs_u>\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
missing_abs_uvw_named_parameter_program,
|
||||
sizeof(missing_abs_uvw_named_parameter_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject undefined _abs_u named parameter");
|
||||
|
||||
const char indexed_parameter_program[] =
|
||||
"#2 = 3\n"
|
||||
"#3 = 11\n"
|
||||
@@ -10832,6 +10993,407 @@ int main() {
|
||||
ok &= expect(config_rc == 0, cnc_sim_last_error(sim));
|
||||
ok &= expect(rc != 0, "expected uncompiled linuxcnc-rs274 backend to fail clearly");
|
||||
|
||||
{
|
||||
std::vector<CncSimEvent> scara_events;
|
||||
CncSimHandle *scara_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(scara_sim, collect_event, &scara_events);
|
||||
const char scara_config[] = "{\"backend\":\"smoke\",\"switchkins\":\"scara\"}";
|
||||
const char scara_program[] =
|
||||
"M428\n"
|
||||
"M429\n"
|
||||
"M430\n";
|
||||
ok &= expect(cnc_sim_load_config_json(scara_sim, scara_config, sizeof(scara_config) - 1) == 0,
|
||||
cnc_sim_last_error(scara_sim));
|
||||
ok &= expect(cnc_sim_parse_program(scara_sim, scara_program, sizeof(scara_program) - 1) == 0,
|
||||
cnc_sim_last_error(scara_sim));
|
||||
bool saw_scara_m428 = false;
|
||||
bool saw_scara_m429 = false;
|
||||
bool saw_scara_m430 = false;
|
||||
for (const auto &event : scara_events) {
|
||||
saw_scara_m428 = saw_scara_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 1 &&
|
||||
event.reserved == 0);
|
||||
saw_scara_m429 = saw_scara_m429 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_scara_m430 = saw_scara_m430 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 2);
|
||||
}
|
||||
ok &= expect(saw_scara_m428, "expected scara M428 remap to select kinstype 0");
|
||||
ok &= expect(saw_scara_m429, "expected scara M429 remap to select kinstype 1");
|
||||
ok &= expect(saw_scara_m430, "expected scara M430 remap to select kinstype 2");
|
||||
cnc_sim_destroy(scara_sim);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<CncSimEvent> table_dual_events;
|
||||
CncSimHandle *table_dual_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(table_dual_sim, collect_event, &table_dual_events);
|
||||
const char table_dual_config[] = "{\"backend\":\"smoke\",\"switchkins\":\"table-dual-rotary\"}";
|
||||
const char table_dual_program[] =
|
||||
"M428\n"
|
||||
"M429\n";
|
||||
ok &= expect(cnc_sim_load_config_json(table_dual_sim,
|
||||
table_dual_config,
|
||||
sizeof(table_dual_config) - 1) == 0,
|
||||
cnc_sim_last_error(table_dual_sim));
|
||||
ok &= expect(cnc_sim_parse_program(table_dual_sim,
|
||||
table_dual_program,
|
||||
sizeof(table_dual_program) - 1) == 0,
|
||||
cnc_sim_last_error(table_dual_sim));
|
||||
bool saw_table_dual_m428 = false;
|
||||
bool saw_table_dual_m429 = false;
|
||||
for (const auto &event : table_dual_events) {
|
||||
saw_table_dual_m428 = saw_table_dual_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 1 &&
|
||||
event.reserved == 1);
|
||||
saw_table_dual_m429 = saw_table_dual_m429 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 0);
|
||||
}
|
||||
ok &= expect(saw_table_dual_m428, "expected table-dual-rotary M428 remap to select kinstype 1");
|
||||
ok &= expect(saw_table_dual_m429, "expected table-dual-rotary M429 remap to select kinstype 0");
|
||||
cnc_sim_destroy(table_dual_sim);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<CncSimEvent> xyzab_tdr_events;
|
||||
CncSimHandle *xyzab_tdr_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(xyzab_tdr_sim, collect_event, &xyzab_tdr_events);
|
||||
const char xyzab_tdr_config[] = "{\"backend\":\"smoke\",\"switchkins\":\"sim-xyzab-tdr-kins\"}";
|
||||
const char xyzab_tdr_program[] =
|
||||
"M428\n"
|
||||
"M429\n";
|
||||
ok &= expect(cnc_sim_load_config_json(xyzab_tdr_sim,
|
||||
xyzab_tdr_config,
|
||||
sizeof(xyzab_tdr_config) - 1) == 0,
|
||||
cnc_sim_last_error(xyzab_tdr_sim));
|
||||
ok &= expect(cnc_sim_parse_program(xyzab_tdr_sim,
|
||||
xyzab_tdr_program,
|
||||
sizeof(xyzab_tdr_program) - 1) == 0,
|
||||
cnc_sim_last_error(xyzab_tdr_sim));
|
||||
bool saw_xyzab_tdr_m428 = false;
|
||||
bool saw_xyzab_tdr_m429 = false;
|
||||
for (const auto &event : xyzab_tdr_events) {
|
||||
saw_xyzab_tdr_m428 = saw_xyzab_tdr_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 1 &&
|
||||
event.reserved == 1);
|
||||
saw_xyzab_tdr_m429 = saw_xyzab_tdr_m429 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 0);
|
||||
}
|
||||
ok &= expect(saw_xyzab_tdr_m428, "expected sim-xyzab-tdr-kins M428 remap to select kinstype 1");
|
||||
ok &= expect(saw_xyzab_tdr_m429, "expected sim-xyzab-tdr-kins M429 remap to select kinstype 0");
|
||||
cnc_sim_destroy(xyzab_tdr_sim);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<CncSimEvent> puma_events;
|
||||
CncSimHandle *puma_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(puma_sim, collect_event, &puma_events);
|
||||
const char puma_config[] = "{\"backend\":\"smoke\",\"switchkins\":\"puma\"}";
|
||||
const char puma_program[] =
|
||||
"M428\n"
|
||||
"M429\n"
|
||||
"M430\n";
|
||||
ok &= expect(cnc_sim_load_config_json(puma_sim, puma_config, sizeof(puma_config) - 1) == 0,
|
||||
cnc_sim_last_error(puma_sim));
|
||||
ok &= expect(cnc_sim_parse_program(puma_sim, puma_program, sizeof(puma_program) - 1) == 0,
|
||||
cnc_sim_last_error(puma_sim));
|
||||
bool saw_puma_m428 = false;
|
||||
bool saw_puma_m429 = false;
|
||||
bool saw_puma_m430 = false;
|
||||
for (const auto &event : puma_events) {
|
||||
saw_puma_m428 = saw_puma_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 1 &&
|
||||
event.reserved == 0);
|
||||
saw_puma_m429 = saw_puma_m429 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_puma_m430 = saw_puma_m430 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 2);
|
||||
}
|
||||
ok &= expect(saw_puma_m428, "expected puma M428 remap to select kinstype 0");
|
||||
ok &= expect(saw_puma_m429, "expected puma M429 remap to select kinstype 1");
|
||||
ok &= expect(saw_puma_m430, "expected puma M430 remap to select kinstype 2");
|
||||
cnc_sim_destroy(puma_sim);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<CncSimEvent> melfa_events;
|
||||
CncSimHandle *melfa_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(melfa_sim, collect_event, &melfa_events);
|
||||
const char melfa_config[] = "{\"backend\":\"smoke\",\"switchkins\":\"melfa-sim\"}";
|
||||
const char melfa_program[] =
|
||||
"M428\n"
|
||||
"M429\n"
|
||||
"M430\n";
|
||||
ok &= expect(cnc_sim_load_config_json(melfa_sim, melfa_config, sizeof(melfa_config) - 1) == 0,
|
||||
cnc_sim_last_error(melfa_sim));
|
||||
ok &= expect(cnc_sim_parse_program(melfa_sim, melfa_program, sizeof(melfa_program) - 1) == 0,
|
||||
cnc_sim_last_error(melfa_sim));
|
||||
bool saw_melfa_m428 = false;
|
||||
bool saw_melfa_m429 = false;
|
||||
bool saw_melfa_m430 = false;
|
||||
for (const auto &event : melfa_events) {
|
||||
saw_melfa_m428 = saw_melfa_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 1 &&
|
||||
event.reserved == 0);
|
||||
saw_melfa_m429 = saw_melfa_m429 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_melfa_m430 = saw_melfa_m430 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 2);
|
||||
}
|
||||
ok &= expect(saw_melfa_m428, "expected melfa-sim M428 remap to select kinstype 0");
|
||||
ok &= expect(saw_melfa_m429, "expected melfa-sim M429 remap to select kinstype 1");
|
||||
ok &= expect(saw_melfa_m430, "expected melfa-sim M430 remap to select kinstype 2");
|
||||
cnc_sim_destroy(melfa_sim);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<CncSimEvent> hexapod_events;
|
||||
CncSimHandle *hexapod_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(hexapod_sim, collect_event, &hexapod_events);
|
||||
const char hexapod_config[] = "{\"backend\":\"smoke\",\"remap\":\"hexapod-sim\"}";
|
||||
const char hexapod_program[] =
|
||||
"M428\n"
|
||||
"M429\n"
|
||||
"M430\n";
|
||||
ok &= expect(cnc_sim_load_config_json(hexapod_sim, hexapod_config, sizeof(hexapod_config) - 1) == 0,
|
||||
cnc_sim_last_error(hexapod_sim));
|
||||
ok &= expect(cnc_sim_parse_program(hexapod_sim, hexapod_program, sizeof(hexapod_program) - 1) == 0,
|
||||
cnc_sim_last_error(hexapod_sim));
|
||||
bool saw_hexapod_m428 = false;
|
||||
bool saw_hexapod_m429 = false;
|
||||
bool saw_hexapod_m430 = false;
|
||||
for (const auto &event : hexapod_events) {
|
||||
saw_hexapod_m428 = saw_hexapod_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 1 &&
|
||||
event.reserved == 0);
|
||||
saw_hexapod_m429 = saw_hexapod_m429 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_hexapod_m430 = saw_hexapod_m430 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 2);
|
||||
}
|
||||
ok &= expect(saw_hexapod_m428, "expected hexapod-sim M428 remap to select kinstype 0");
|
||||
ok &= expect(saw_hexapod_m429, "expected hexapod-sim M429 remap to select kinstype 1");
|
||||
ok &= expect(saw_hexapod_m430, "expected hexapod-sim M430 remap to select kinstype 2");
|
||||
cnc_sim_destroy(hexapod_sim);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<CncSimEvent> trsrn_events;
|
||||
CncSimHandle *trsrn_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(trsrn_sim, collect_event, &trsrn_events);
|
||||
const char trsrn_config[] = "{\"backend\":\"smoke\",\"switchkins\":\"xyzacb-trsrn\"}";
|
||||
const char trsrn_program[] =
|
||||
"M428\n"
|
||||
"M429\n"
|
||||
"M430\n";
|
||||
ok &= expect(cnc_sim_load_config_json(trsrn_sim, trsrn_config, sizeof(trsrn_config) - 1) == 0,
|
||||
cnc_sim_last_error(trsrn_sim));
|
||||
ok &= expect(cnc_sim_parse_program(trsrn_sim, trsrn_program, sizeof(trsrn_program) - 1) == 0,
|
||||
cnc_sim_last_error(trsrn_sim));
|
||||
bool saw_trsrn_m428 = false;
|
||||
bool saw_trsrn_m429 = false;
|
||||
bool saw_trsrn_m430 = false;
|
||||
for (const auto &event : trsrn_events) {
|
||||
saw_trsrn_m428 = saw_trsrn_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 1 &&
|
||||
event.reserved == 0);
|
||||
saw_trsrn_m429 = saw_trsrn_m429 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_trsrn_m430 = saw_trsrn_m430 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 2);
|
||||
}
|
||||
ok &= expect(saw_trsrn_m428, "expected xyzacb-trsrn M428 remap to select kinstype 0");
|
||||
ok &= expect(saw_trsrn_m429, "expected xyzacb-trsrn M429 remap to select kinstype 1");
|
||||
ok &= expect(saw_trsrn_m430, "expected xyzacb-trsrn M430 remap to select kinstype 2");
|
||||
cnc_sim_destroy(trsrn_sim);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<CncSimEvent> machine_events;
|
||||
CncSimHandle *machine_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(machine_sim, collect_event, &machine_events);
|
||||
const char machine_config[] = "{\"backend\":\"smoke\",\"machine\":\"sim-xyzac-trt-kins (switchkins)\"}";
|
||||
const char machine_program[] =
|
||||
"M428\n"
|
||||
"M429\n"
|
||||
"M430\n";
|
||||
ok &= expect(cnc_sim_load_config_json(machine_sim, machine_config, sizeof(machine_config) - 1) == 0,
|
||||
cnc_sim_last_error(machine_sim));
|
||||
ok &= expect(cnc_sim_parse_program(machine_sim, machine_program, sizeof(machine_program) - 1) == 0,
|
||||
cnc_sim_last_error(machine_sim));
|
||||
ok &= expect(saw_kinematics_switch(machine_events, 1, 1),
|
||||
"expected LinuxCNC xyzac-trt MACHINE config M428 remap to select kinstype 1");
|
||||
ok &= expect(saw_kinematics_switch(machine_events, 2, 0),
|
||||
"expected LinuxCNC xyzac-trt MACHINE config M429 remap to select kinstype 0");
|
||||
ok &= expect(saw_kinematics_switch(machine_events, 3, 2),
|
||||
"expected LinuxCNC xyzac-trt MACHINE config M430 remap to select kinstype 2");
|
||||
cnc_sim_destroy(machine_sim);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<CncSimEvent> kinematics_events;
|
||||
CncSimHandle *kinematics_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(kinematics_sim, collect_event, &kinematics_events);
|
||||
const char kinematics_config[] = "{\"backend\":\"smoke\",\"kinematics\":\"genhexkins\"}";
|
||||
const char kinematics_program[] =
|
||||
"M428\n"
|
||||
"M429\n"
|
||||
"M430\n";
|
||||
ok &= expect(cnc_sim_load_config_json(kinematics_sim,
|
||||
kinematics_config,
|
||||
sizeof(kinematics_config) - 1) == 0,
|
||||
cnc_sim_last_error(kinematics_sim));
|
||||
ok &= expect(cnc_sim_parse_program(kinematics_sim,
|
||||
kinematics_program,
|
||||
sizeof(kinematics_program) - 1) == 0,
|
||||
cnc_sim_last_error(kinematics_sim));
|
||||
ok &= expect(saw_kinematics_switch(kinematics_events, 1, 0),
|
||||
"expected LinuxCNC genhexkins KINEMATICS config M428 remap to select kinstype 0");
|
||||
ok &= expect(saw_kinematics_switch(kinematics_events, 2, 1),
|
||||
"expected LinuxCNC genhexkins KINEMATICS config M429 remap to select kinstype 1");
|
||||
ok &= expect(saw_kinematics_switch(kinematics_events, 3, 2),
|
||||
"expected LinuxCNC genhexkins KINEMATICS config M430 remap to select kinstype 2");
|
||||
cnc_sim_destroy(kinematics_sim);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<CncSimEvent> config_path_events;
|
||||
CncSimHandle *config_path_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(config_path_sim, collect_event, &config_path_events);
|
||||
const char config_path_config[] =
|
||||
"{\"backend\":\"smoke\","
|
||||
"\"config\":\"configs/sim/axis/vismach/5axis/table-dual-rotary/xyzab-tdr.ini\"}";
|
||||
const char config_path_program[] =
|
||||
"M428\n"
|
||||
"M429\n";
|
||||
ok &= expect(cnc_sim_load_config_json(config_path_sim,
|
||||
config_path_config,
|
||||
sizeof(config_path_config) - 1) == 0,
|
||||
cnc_sim_last_error(config_path_sim));
|
||||
ok &= expect(cnc_sim_parse_program(config_path_sim,
|
||||
config_path_program,
|
||||
sizeof(config_path_program) - 1) == 0,
|
||||
cnc_sim_last_error(config_path_sim));
|
||||
ok &= expect(saw_kinematics_switch(config_path_events, 1, 1),
|
||||
"expected LinuxCNC xyzab-tdr config path M428 remap to select kinstype 1");
|
||||
ok &= expect(saw_kinematics_switch(config_path_events, 2, 0),
|
||||
"expected LinuxCNC xyzab-tdr config path M429 remap to select kinstype 0");
|
||||
cnc_sim_destroy(config_path_sim);
|
||||
}
|
||||
|
||||
{
|
||||
struct SourceBackedConfigCase {
|
||||
const char *field;
|
||||
const char *value;
|
||||
int m428_type;
|
||||
int m429_type;
|
||||
int m430_type;
|
||||
};
|
||||
const SourceBackedConfigCase source_cases[] = {
|
||||
{"config", "configs/sim/axis/vismach/5axis/bridgemill/5axis.ini", 0, 1, 2},
|
||||
{"config", "configs/sim/axis/vismach/5axis/table-dual-rotary/xyzab-tdr.ini", 1, 0, -1},
|
||||
{"config", "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini", 1, 0, 2},
|
||||
{"config", "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini", 1, 0, 2},
|
||||
{"config",
|
||||
"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzacb-trsrn_twp/xyzacb-trsrn.ini",
|
||||
0,
|
||||
1,
|
||||
2},
|
||||
{"config",
|
||||
"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzbca-trsrn_twp/xyzbca-trsrn.ini",
|
||||
0,
|
||||
1,
|
||||
2},
|
||||
{"config", "configs/sim/axis/vismach/hexapod-sim/hexapod.ini", 0, 1, 2},
|
||||
{"config", "configs/sim/axis/vismach/melfa-sim/melfa.ini", 0, 1, 2},
|
||||
{"config", "configs/sim/axis/vismach/millturn/millturn.ini", 0, 1, -1},
|
||||
{"config", "configs/sim/axis/vismach/puma/puma.ini", 0, 1, 2},
|
||||
{"config", "configs/sim/axis/vismach/puma/puma_cube.ini", 0, 1, 2},
|
||||
{"config", "configs/sim/axis/vismach/puma/puma560.ini", 0, 1, 2},
|
||||
{"config", "configs/sim/axis/vismach/puma/puma560_uvw.ini", 0, 1, 2},
|
||||
{"config", "configs/sim/axis/vismach/scara/scara.ini", 0, 1, 2},
|
||||
{"config", "configs/sim/qtaxis/non-trivial/scara/scara.ini", 0, 1, 2},
|
||||
{"config", "configs/sim/qtvcp_screens/non-trivial/scara/scara.ini", 0, 1, 2},
|
||||
{"machine", "Sim-5Axis Bridge Mill (xyzbcw)", 0, 1, 2},
|
||||
{"machine", "sim-xyzab-tdr-kins (switchkins)", 1, 0, -1},
|
||||
{"machine", "sim-xyzac-trt-kins (switchkins)", 1, 0, 2},
|
||||
{"machine", "sim-xyzbc-trt-kins (switchkins)", 1, 0, 2},
|
||||
{"machine", "xyzacb-trsrn (switchkins)", 0, 1, 2},
|
||||
{"machine", "xyzbca-trsrn (switchkins)", 0, 1, 2},
|
||||
{"machine", "hexapod (switchkins)", 0, 1, 2},
|
||||
{"machine", "melfa (mm)", 0, 1, 2},
|
||||
{"machine", "millturn (mm)", 0, 1, -1},
|
||||
{"machine", "PUMA (pumakins,switchkins)", 0, 1, 2},
|
||||
{"machine", "puma_cube.ini (pumakins)", 0, 1, 2},
|
||||
{"machine", "puma560 (switchkins) (inch)", 0, 1, 2},
|
||||
{"machine", "SCARA (genserkins,switchkins)", 0, 1, 2},
|
||||
{"kinematics", "5axiskins", 0, 1, 2},
|
||||
{"kinematics", "xyzab_tdr_kins", 1, 0, -1},
|
||||
{"kinematics", "xyzac-trt-kins sparm=identityfirst", 1, 0, 2},
|
||||
{"kinematics", "xyzbc-trt-kins sparm=identityfirst", 1, 0, 2},
|
||||
{"kinematics", "xyzacb_trsrn", 0, 1, 2},
|
||||
{"kinematics", "xyzbca_trsrn", 0, 1, 2},
|
||||
{"kinematics", "genhexkins", 0, 1, 2},
|
||||
{"kinematics", "genserkins", 0, 1, 2},
|
||||
{"kinematics", "millturn", 0, 1, -1},
|
||||
{"kinematics", "pumakins", 0, 1, 2},
|
||||
{"kinematics", "scarakins coordinates=xyzcab", 0, 1, 2},
|
||||
{"halfile", "5axisgui.hal", 0, 1, 2},
|
||||
{"halfile", "5axisgui", 0, 1, 2},
|
||||
{"halfile", "kinematics.hal", 0, 1, 2},
|
||||
{"hal_file", "melfa_dh.hal", 0, 1, 2},
|
||||
{"hal_file", "melfa_dh", 0, 1, 2},
|
||||
{"hal_file", "millturn.hal", 0, 1, -1},
|
||||
{"halfile", "puma_dh.hal", 0, 1, 2},
|
||||
{"halfile", "puma_dh", 0, 1, 2},
|
||||
{"halfile", "puma560_dh.hal", 0, 1, 2},
|
||||
{"halfile", "puma560_dh", 0, 1, 2},
|
||||
};
|
||||
for (const SourceBackedConfigCase &source_case : source_cases) {
|
||||
const std::string json = std::string("{\"backend\":\"smoke\",\"") +
|
||||
source_case.field +
|
||||
"\":\"" +
|
||||
source_case.value +
|
||||
"\"}";
|
||||
ok &= expect_switchkins_remap_config(json,
|
||||
source_case.m428_type,
|
||||
source_case.m429_type,
|
||||
source_case.m430_type,
|
||||
"expected LinuxCNC source-backed switchkins remap config");
|
||||
}
|
||||
}
|
||||
|
||||
cnc_sim_destroy(sim);
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
#include "linuxcnc_cubic_adapter.h"
|
||||
#include "linuxcnc_xyzab_tdr_kins_adapter.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
@@ -63,6 +66,48 @@ bool expect_axis_joints_near(const LinuxCncAxisJoints &actual,
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool expect_genhex_joints_near(const LinuxCncGenhexJoints &actual,
|
||||
const LinuxCncGenhexJoints &expected,
|
||||
const char *message) {
|
||||
bool ok = true;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
ok &= expect_near_eps(actual.strut[i], expected.strut[i], 1e-6, message);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool expect_pentakins_joints_near(const LinuxCncPentakinsJoints &actual,
|
||||
const LinuxCncPentakinsJoints &expected,
|
||||
const char *message) {
|
||||
bool ok = true;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
ok &= expect_near_eps(actual.strut[i], expected.strut[i], 1e-6, message);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool expect_tripod_joints_near(const LinuxCncTripodJoints &actual,
|
||||
const LinuxCncTripodJoints &expected,
|
||||
const char *message) {
|
||||
bool ok = true;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
ok &= expect_near_eps(actual.strut[i], expected.strut[i], 1e-9, message);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool expect_scorbot_joints_near(const LinuxCncScorbotJoints &actual,
|
||||
const LinuxCncScorbotJoints &expected,
|
||||
const char *message) {
|
||||
bool ok = true;
|
||||
ok &= expect_near_eps(actual.j0, expected.j0, 1e-9, message);
|
||||
ok &= expect_near_eps(actual.j1, expected.j1, 1e-9, message);
|
||||
ok &= expect_near_eps(actual.j2, expected.j2, 1e-9, message);
|
||||
ok &= expect_near_eps(actual.j3, expected.j3, 1e-9, message);
|
||||
ok &= expect_near_eps(actual.j4, expected.j4, 1e-9, message);
|
||||
return ok;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
@@ -86,6 +131,46 @@ int main() {
|
||||
axis_joints,
|
||||
"identity/trivkins forward/inverse roundtrip");
|
||||
|
||||
LinuxCncCubicSample cubic_samples[4]{};
|
||||
ok &= expect(linuxcnc_cubic_source_second_segment_samples(cubic_samples, 4),
|
||||
"expected LinuxCNC cubic.c second segment sample generation");
|
||||
ok &= expect_near(cubic_samples[0].x, 0.0, "cubic second segment sample0 x");
|
||||
ok &= expect_near(cubic_samples[0].v, 0.0, "cubic second segment sample0 v");
|
||||
ok &= expect_near(cubic_samples[0].a, 0.0, "cubic second segment sample0 a");
|
||||
ok &= expect_near(cubic_samples[0].j, 10.0, "cubic second segment sample0 j");
|
||||
ok &= expect_near_eps(cubic_samples[1].x, 0.026041666666666668, 1e-12, "cubic second segment sample1 x");
|
||||
ok &= expect_near(cubic_samples[1].v, 0.3125, "cubic second segment sample1 v");
|
||||
ok &= expect_near(cubic_samples[1].a, 2.5, "cubic second segment sample1 a");
|
||||
ok &= expect_near(cubic_samples[1].j, 10.0, "cubic second segment sample1 j");
|
||||
ok &= expect_near_eps(cubic_samples[2].x, 0.20833333333333334, 1e-12, "cubic second segment sample2 x");
|
||||
ok &= expect_near(cubic_samples[2].v, 1.25, "cubic second segment sample2 v");
|
||||
ok &= expect_near(cubic_samples[2].a, 5.0, "cubic second segment sample2 a");
|
||||
ok &= expect_near_eps(cubic_samples[3].x, 0.703125, 1e-12, "cubic second segment sample3 x");
|
||||
ok &= expect_near(cubic_samples[3].v, 2.8125, "cubic second segment sample3 v");
|
||||
ok &= expect_near(cubic_samples[3].a, 7.5, "cubic second segment sample3 a");
|
||||
ok &= expect(linuxcnc_cubic_source_rejects_invalid_configuration(),
|
||||
"expected LinuxCNC cubic.c to reject invalid configuration");
|
||||
|
||||
axis_joints = {};
|
||||
axis_joints.x = 12.0;
|
||||
axis_joints.y = 4.0;
|
||||
axis_joints.z = 3.0;
|
||||
axis_joints.a = 10.0;
|
||||
axis_joints.b = 20.0;
|
||||
axis_joints.c = 30.0;
|
||||
axis_joints.u = 7.0;
|
||||
axis_joints.v = 8.0;
|
||||
axis_joints.w = 9.0;
|
||||
CncSimPose corexy_pose = linuxcnc_corexykins_forward(axis_joints);
|
||||
ok &= expect_near(corexy_pose.x, 8.0, "corexykins forward x");
|
||||
ok &= expect_near(corexy_pose.y, 4.0, "corexykins forward y");
|
||||
ok &= expect_near(corexy_pose.z, 3.0, "corexykins forward z");
|
||||
ok &= expect_near(corexy_pose.a, 10.0, "corexykins forward a");
|
||||
ok &= expect_near(corexy_pose.w, 9.0, "corexykins forward w");
|
||||
ok &= expect_axis_joints_near(linuxcnc_corexykins_inverse(corexy_pose),
|
||||
axis_joints,
|
||||
"corexykins forward/inverse roundtrip");
|
||||
|
||||
axis_joints = {};
|
||||
axis_joints.x = 10.0;
|
||||
axis_joints.y = 0.0;
|
||||
@@ -104,6 +189,173 @@ int main() {
|
||||
axis_joints,
|
||||
"rotatekins forward/inverse roundtrip");
|
||||
|
||||
CncSimPose genhex_pose{};
|
||||
genhex_pose.x = 1.25;
|
||||
genhex_pose.y = -2.5;
|
||||
genhex_pose.z = 3.75;
|
||||
genhex_pose.a = 4.0;
|
||||
genhex_pose.b = -5.0;
|
||||
genhex_pose.c = 6.0;
|
||||
const LinuxCncGenhexJoints genhex_joints = linuxcnc_genhex_inverse(genhex_pose);
|
||||
CncSimPose genhex_roundtrip_pose = linuxcnc_genhex_forward(genhex_joints, genhex_pose);
|
||||
ok &= expect_near_eps(genhex_roundtrip_pose.x, genhex_pose.x, 1e-6, "genhexkins forward/inverse roundtrip x");
|
||||
ok &= expect_near_eps(genhex_roundtrip_pose.y, genhex_pose.y, 1e-6, "genhexkins forward/inverse roundtrip y");
|
||||
ok &= expect_near_eps(genhex_roundtrip_pose.z, genhex_pose.z, 1e-6, "genhexkins forward/inverse roundtrip z");
|
||||
ok &= expect_near_eps(genhex_roundtrip_pose.a, genhex_pose.a, 1e-6, "genhexkins forward/inverse roundtrip a");
|
||||
ok &= expect_near_eps(genhex_roundtrip_pose.b, genhex_pose.b, 1e-6, "genhexkins forward/inverse roundtrip b");
|
||||
ok &= expect_near_eps(genhex_roundtrip_pose.c, genhex_pose.c, 1e-6, "genhexkins forward/inverse roundtrip c");
|
||||
ok &= expect_genhex_joints_near(linuxcnc_genhex_inverse(genhex_roundtrip_pose),
|
||||
genhex_joints,
|
||||
"genhexkins inverse deterministic strut lengths");
|
||||
|
||||
CncSimPose penta_pose{};
|
||||
penta_pose.x = 1.25;
|
||||
penta_pose.y = -2.5;
|
||||
penta_pose.z = 3.75;
|
||||
penta_pose.a = 4.0;
|
||||
penta_pose.b = -5.0;
|
||||
const LinuxCncPentakinsJoints penta_joints = linuxcnc_pentakins_inverse(penta_pose);
|
||||
CncSimPose penta_roundtrip_pose = linuxcnc_pentakins_forward(penta_joints, penta_pose);
|
||||
ok &= expect_near_eps(penta_roundtrip_pose.x, penta_pose.x, 1e-6, "pentakins forward/inverse roundtrip x");
|
||||
ok &= expect_near_eps(penta_roundtrip_pose.y, penta_pose.y, 1e-6, "pentakins forward/inverse roundtrip y");
|
||||
ok &= expect_near_eps(penta_roundtrip_pose.z, penta_pose.z, 1e-6, "pentakins forward/inverse roundtrip z");
|
||||
ok &= expect_near_eps(penta_roundtrip_pose.a, penta_pose.a, 1e-6, "pentakins forward/inverse roundtrip a");
|
||||
ok &= expect_near_eps(penta_roundtrip_pose.b, penta_pose.b, 1e-6, "pentakins forward/inverse roundtrip b");
|
||||
ok &= expect_pentakins_joints_near(linuxcnc_pentakins_inverse(penta_roundtrip_pose),
|
||||
penta_joints,
|
||||
"pentakins inverse deterministic strut lengths");
|
||||
|
||||
CncSimPose tripod_pose{};
|
||||
tripod_pose.x = 0.2;
|
||||
tripod_pose.y = 0.3;
|
||||
tripod_pose.z = 0.4;
|
||||
const LinuxCncTripodJoints tripod_joints = linuxcnc_tripodkins_inverse(tripod_pose);
|
||||
const CncSimPose tripod_roundtrip_pose = linuxcnc_tripodkins_forward(tripod_joints);
|
||||
ok &= expect_near_eps(tripod_roundtrip_pose.x, tripod_pose.x, 1e-12, "tripodkins forward/inverse roundtrip x");
|
||||
ok &= expect_near_eps(tripod_roundtrip_pose.y, tripod_pose.y, 1e-12, "tripodkins forward/inverse roundtrip y");
|
||||
ok &= expect_near_eps(tripod_roundtrip_pose.z, tripod_pose.z, 1e-12, "tripodkins forward/inverse roundtrip z");
|
||||
ok &= expect_near(tripod_roundtrip_pose.a, 0.0, "tripodkins forward clears a");
|
||||
ok &= expect_tripod_joints_near(linuxcnc_tripodkins_inverse(tripod_roundtrip_pose),
|
||||
tripod_joints,
|
||||
"tripodkins inverse deterministic strut lengths");
|
||||
|
||||
LinuxCncScorbotJoints scorbot_joints{};
|
||||
scorbot_joints.j0 = 30.0;
|
||||
scorbot_joints.j1 = 20.0;
|
||||
scorbot_joints.j2 = -10.0;
|
||||
scorbot_joints.j3 = 7.0;
|
||||
scorbot_joints.j4 = -8.0;
|
||||
const CncSimPose scorbot_pose = linuxcnc_scorbot_kins_forward(scorbot_joints);
|
||||
ok &= expect_near_eps(scorbot_pose.x, 382.1896396002526, 1e-9, "scorbot-kins forward x");
|
||||
ok &= expect_near_eps(scorbot_pose.y, 220.65729130469182, 1e-9, "scorbot-kins forward y");
|
||||
ok &= expect_near_eps(scorbot_pose.z, 177.2102044105812, 1e-9, "scorbot-kins forward z");
|
||||
ok &= expect_near(scorbot_pose.a, scorbot_joints.j3, "scorbot-kins forward wrist roll");
|
||||
ok &= expect_near(scorbot_pose.b, scorbot_joints.j4, "scorbot-kins forward wrist pitch");
|
||||
ok &= expect_scorbot_joints_near(linuxcnc_scorbot_kins_inverse(scorbot_pose),
|
||||
scorbot_joints,
|
||||
"scorbot-kins forward/inverse roundtrip");
|
||||
|
||||
const LinuxCncLinearDeltaParameters lineardelta_parameters = linuxcnc_lineardelta_default_parameters();
|
||||
ok &= expect_near(lineardelta_parameters.r, 130.25, "lineardeltakins default R");
|
||||
ok &= expect_near(lineardelta_parameters.l, 269.0, "lineardeltakins default L");
|
||||
CncSimPose lineardelta_pose{};
|
||||
lineardelta_pose.x = 1.25;
|
||||
lineardelta_pose.y = -2.5;
|
||||
lineardelta_pose.z = -20.0;
|
||||
lineardelta_pose.a = 4.0;
|
||||
lineardelta_pose.b = 5.0;
|
||||
lineardelta_pose.c = 6.0;
|
||||
lineardelta_pose.u = 7.0;
|
||||
lineardelta_pose.v = 8.0;
|
||||
lineardelta_pose.w = 9.0;
|
||||
const LinuxCncAxisJoints lineardelta_joints =
|
||||
linuxcnc_lineardelta_inverse(lineardelta_pose, lineardelta_parameters);
|
||||
const CncSimPose lineardelta_roundtrip_pose =
|
||||
linuxcnc_lineardelta_forward(lineardelta_joints, lineardelta_parameters);
|
||||
ok &= expect_near_eps(lineardelta_roundtrip_pose.x,
|
||||
lineardelta_pose.x,
|
||||
1e-6,
|
||||
"lineardeltakins forward/inverse roundtrip x");
|
||||
ok &= expect_near_eps(lineardelta_roundtrip_pose.y,
|
||||
lineardelta_pose.y,
|
||||
1e-6,
|
||||
"lineardeltakins forward/inverse roundtrip y");
|
||||
ok &= expect_near_eps(lineardelta_roundtrip_pose.z,
|
||||
lineardelta_pose.z,
|
||||
1e-6,
|
||||
"lineardeltakins forward/inverse roundtrip z");
|
||||
ok &= expect_near(lineardelta_roundtrip_pose.a, lineardelta_pose.a, "lineardeltakins pass-through a");
|
||||
ok &= expect_near(lineardelta_roundtrip_pose.w, lineardelta_pose.w, "lineardeltakins pass-through w");
|
||||
|
||||
const LinuxCncRotaryDeltaParameters rotarydelta_parameters = linuxcnc_rotarydelta_default_parameters();
|
||||
ok &= expect_near(rotarydelta_parameters.platformradius, 10.0, "rotarydeltakins default platformradius");
|
||||
ok &= expect_near(rotarydelta_parameters.thighlength, 10.0, "rotarydeltakins default thighlength");
|
||||
ok &= expect_near(rotarydelta_parameters.shinlength, 14.0, "rotarydeltakins default shinlength");
|
||||
ok &= expect_near(rotarydelta_parameters.footradius, 6.0, "rotarydeltakins default footradius");
|
||||
LinuxCncAxisJoints rotarydelta_joints{};
|
||||
rotarydelta_joints.x = 20.0;
|
||||
rotarydelta_joints.y = 25.0;
|
||||
rotarydelta_joints.z = 30.0;
|
||||
rotarydelta_joints.a = 4.0;
|
||||
rotarydelta_joints.b = 5.0;
|
||||
rotarydelta_joints.c = 6.0;
|
||||
rotarydelta_joints.u = 7.0;
|
||||
rotarydelta_joints.v = 8.0;
|
||||
rotarydelta_joints.w = 9.0;
|
||||
const CncSimPose rotarydelta_pose =
|
||||
linuxcnc_rotarydelta_forward(rotarydelta_joints, rotarydelta_parameters);
|
||||
const LinuxCncAxisJoints rotarydelta_roundtrip_joints =
|
||||
linuxcnc_rotarydelta_inverse(rotarydelta_pose, rotarydelta_parameters);
|
||||
const CncSimPose rotarydelta_roundtrip_pose =
|
||||
linuxcnc_rotarydelta_forward(rotarydelta_roundtrip_joints, rotarydelta_parameters);
|
||||
ok &= expect_near_eps(rotarydelta_roundtrip_pose.x,
|
||||
rotarydelta_pose.x,
|
||||
1e-6,
|
||||
"rotarydeltakins forward/inverse roundtrip x");
|
||||
ok &= expect_near_eps(rotarydelta_roundtrip_pose.y,
|
||||
rotarydelta_pose.y,
|
||||
1e-6,
|
||||
"rotarydeltakins forward/inverse roundtrip y");
|
||||
ok &= expect_near_eps(rotarydelta_roundtrip_pose.z,
|
||||
rotarydelta_pose.z,
|
||||
1e-6,
|
||||
"rotarydeltakins forward/inverse roundtrip z");
|
||||
ok &= expect_near(rotarydelta_roundtrip_pose.a, rotarydelta_pose.a, "rotarydeltakins pass-through a");
|
||||
ok &= expect_near(rotarydelta_roundtrip_pose.w, rotarydelta_pose.w, "rotarydeltakins pass-through w");
|
||||
|
||||
const LinuxCncMaxkinsParameters maxkins_parameters = linuxcnc_maxkins_default_parameters();
|
||||
ok &= expect_near(maxkins_parameters.pivot_length, 0.666, "maxkins default pivot-length");
|
||||
ok &= expect(!maxkins_parameters.conventional_directions, "maxkins default unconventional directions");
|
||||
LinuxCncAxisJoints maxkins_joints{};
|
||||
maxkins_joints.x = 10.0;
|
||||
maxkins_joints.y = 4.0;
|
||||
maxkins_joints.z = 3.0;
|
||||
maxkins_joints.a = 1.0;
|
||||
maxkins_joints.b = 0.0;
|
||||
maxkins_joints.c = 30.0;
|
||||
maxkins_joints.u = 0.0;
|
||||
maxkins_joints.v = 0.0;
|
||||
maxkins_joints.w = 0.0;
|
||||
const CncSimPose maxkins_pose = linuxcnc_maxkins_forward(maxkins_joints, maxkins_parameters);
|
||||
const LinuxCncAxisJoints maxkins_roundtrip_joints =
|
||||
linuxcnc_maxkins_inverse(maxkins_pose, maxkins_parameters);
|
||||
ok &= expect_axis_joints_near(maxkins_roundtrip_joints,
|
||||
maxkins_joints,
|
||||
"maxkins forward/inverse roundtrip");
|
||||
|
||||
LinuxCncAxisJoints rosekins_joints{};
|
||||
rosekins_joints.x = 5.0;
|
||||
rosekins_joints.y = 2.0;
|
||||
rosekins_joints.z = 45.0;
|
||||
const CncSimPose rosekins_pose = linuxcnc_rosekins_forward(rosekins_joints);
|
||||
ok &= expect_near_eps(rosekins_pose.x, 3.53553390593274, 1e-12, "rosekins forward x");
|
||||
ok &= expect_near_eps(rosekins_pose.y, 3.53553390593274, 1e-12, "rosekins forward y");
|
||||
ok &= expect_near(rosekins_pose.z, 2.0, "rosekins forward z");
|
||||
const LinuxCncAxisJoints rosekins_roundtrip_joints = linuxcnc_rosekins_inverse(rosekins_pose);
|
||||
ok &= expect_near_eps(rosekins_roundtrip_joints.x, rosekins_joints.x, 1e-9, "rosekins inverse radius");
|
||||
ok &= expect_near(rosekins_roundtrip_joints.y, rosekins_joints.y, "rosekins inverse z joint");
|
||||
ok &= expect_near_eps(rosekins_roundtrip_joints.z, rosekins_joints.z, 1e-9, "rosekins inverse theta");
|
||||
|
||||
LinuxCncFiveAxisJoints joints{};
|
||||
joints.x = 10.0;
|
||||
joints.y = 20.0;
|
||||
@@ -257,6 +509,24 @@ int main() {
|
||||
ok &= expect_near(xyzac_roundtrip_joints.b, 0.0, "xyzac-trt inverse drops unconfigured B");
|
||||
ok &= expect_near(xyzac_roundtrip_joints.w, 0.0, "xyzac-trt inverse drops unconfigured W");
|
||||
|
||||
xyzac_pose = linuxcnc_xyzac_trt_forward(joints, trt_parameters);
|
||||
ok &= expect_near(xyzac_pose.a, joints.a, "xyzac-trt forward keeps configured A after xyzbc setup");
|
||||
ok &= expect_near(xyzac_pose.b, 0.0, "xyzac-trt forward drops unconfigured B after xyzbc setup");
|
||||
|
||||
trt_parameters = linuxcnc_xyzbc_trt_default_parameters(250.0);
|
||||
joints = {};
|
||||
joints.x = 10.0;
|
||||
joints.y = 20.0;
|
||||
joints.z = 30.0;
|
||||
joints.b = 90.0;
|
||||
joints.c = 0.0;
|
||||
pose = linuxcnc_xyzbc_trt_forward(joints, trt_parameters);
|
||||
ok &= expect_near(pose.x, 185.0, "xyzbc-trt B90 C0 forward x after xyzac setup");
|
||||
ok &= expect_near(pose.y, 20.0, "xyzbc-trt B90 C0 forward y after xyzac setup");
|
||||
ok &= expect_near(pose.z, 265.0, "xyzbc-trt B90 C0 forward z after xyzac setup");
|
||||
ok &= expect_near(pose.a, 0.0, "xyzbc-trt forward drops unconfigured A after xyzac setup");
|
||||
ok &= expect_near(pose.b, 90.0, "xyzbc-trt forward keeps configured B after xyzac setup");
|
||||
|
||||
LinuxCncScaraParameters scara_parameters = linuxcnc_scara_default_parameters();
|
||||
LinuxCncScaraJoints scara_joints{};
|
||||
scara_joints.j0 = 0.0;
|
||||
@@ -355,6 +625,32 @@ int main() {
|
||||
ok &= expect_near(xyzab_tcp_roundtrip.z, axis_joints.z, "xyzab-tdr type1 roundtrip z");
|
||||
ok &= expect_near(xyzab_tcp_roundtrip.a, axis_joints.a, "xyzab-tdr type1 roundtrip a");
|
||||
ok &= expect_near(xyzab_tcp_roundtrip.b, axis_joints.b, "xyzab-tdr type1 roundtrip b");
|
||||
ok &= expect(!linuxcnc_xyzab_tdr_kins_switch(2),
|
||||
"xyzab-tdr LinuxCNC kinematicsSwitch rejects invalid switchkins type");
|
||||
bool xyzab_kinstype_is_0 = true;
|
||||
bool xyzab_kinstype_is_1 = true;
|
||||
ok &= expect(linuxcnc_xyzab_tdr_kins_switch_state(&xyzab_kinstype_is_0, &xyzab_kinstype_is_1),
|
||||
"xyzab-tdr LinuxCNC switch state is readable after invalid switchkins type");
|
||||
ok &= expect(!xyzab_kinstype_is_0,
|
||||
"xyzab-tdr LinuxCNC invalid switch clears kinstype.is-0");
|
||||
ok &= expect(!xyzab_kinstype_is_1,
|
||||
"xyzab-tdr LinuxCNC invalid switch clears kinstype.is-1");
|
||||
ok &= expect(linuxcnc_xyzab_tdr_kins_switch(1),
|
||||
"xyzab-tdr LinuxCNC kinematicsSwitch restores valid switchkins type");
|
||||
ok &= expect(linuxcnc_xyzab_tdr_kins_switch_state(&xyzab_kinstype_is_0, &xyzab_kinstype_is_1),
|
||||
"xyzab-tdr LinuxCNC switch state is readable after type1 switch");
|
||||
ok &= expect(!xyzab_kinstype_is_0,
|
||||
"xyzab-tdr LinuxCNC type1 switch clears kinstype.is-0");
|
||||
ok &= expect(xyzab_kinstype_is_1,
|
||||
"xyzab-tdr LinuxCNC type1 switch sets kinstype.is-1");
|
||||
ok &= expect(linuxcnc_xyzab_tdr_kins_switch(0),
|
||||
"xyzab-tdr LinuxCNC kinematicsSwitch accepts type0 switch");
|
||||
ok &= expect(linuxcnc_xyzab_tdr_kins_switch_state(&xyzab_kinstype_is_0, &xyzab_kinstype_is_1),
|
||||
"xyzab-tdr LinuxCNC switch state is readable after type0 switch");
|
||||
ok &= expect(xyzab_kinstype_is_0,
|
||||
"xyzab-tdr LinuxCNC type0 switch sets kinstype.is-0");
|
||||
ok &= expect(!xyzab_kinstype_is_1,
|
||||
"xyzab-tdr LinuxCNC type0 switch clears kinstype.is-1");
|
||||
|
||||
LinuxCncPumaParameters puma_parameters = linuxcnc_puma_default_parameters();
|
||||
LinuxCncAxisJoints puma_joints{};
|
||||
@@ -377,6 +673,31 @@ int main() {
|
||||
ok &= expect_near(puma_roundtrip.c, puma_joints.c, "pumakins roundtrip j5");
|
||||
ok &= expect_near(puma_fflags, 0, "pumakins non-singular inverse flags");
|
||||
|
||||
int genser_default_iterations = 0;
|
||||
LinuxCncGenserParameters genser_default_parameters =
|
||||
linuxcnc_genser_default_parameters(&genser_default_iterations);
|
||||
ok &= expect_near(genser_default_iterations, 100, "genserkins LinuxCNC default max iterations");
|
||||
ok &= expect_near(genser_default_parameters.a[2], 300.0, "genserkins LinuxCNC default A3");
|
||||
ok &= expect_near(genser_default_parameters.a[3], 50.0, "genserkins LinuxCNC default A4");
|
||||
ok &= expect_near_eps(genser_default_parameters.alpha[1],
|
||||
-1.5707963267948966,
|
||||
1e-12,
|
||||
"genserkins LinuxCNC default ALPHA2");
|
||||
ok &= expect_near_eps(genser_default_parameters.alpha[3],
|
||||
-1.5707963267948966,
|
||||
1e-12,
|
||||
"genserkins LinuxCNC default ALPHA4");
|
||||
ok &= expect_near_eps(genser_default_parameters.alpha[4],
|
||||
1.5707963267948966,
|
||||
1e-12,
|
||||
"genserkins LinuxCNC default ALPHA5");
|
||||
ok &= expect_near_eps(genser_default_parameters.alpha[5],
|
||||
-1.5707963267948966,
|
||||
1e-12,
|
||||
"genserkins LinuxCNC default ALPHA6");
|
||||
ok &= expect_near(genser_default_parameters.d[2], 70.0, "genserkins LinuxCNC default D3");
|
||||
ok &= expect_near(genser_default_parameters.d[3], 400.0, "genserkins LinuxCNC default D4");
|
||||
|
||||
LinuxCncGenserParameters genser_parameters = linuxcnc_genser_puma560_parameters();
|
||||
LinuxCncAxisJoints genser_joints{};
|
||||
CncSimPose genser_pose = linuxcnc_genser_forward(genser_joints, genser_parameters);
|
||||
@@ -441,5 +762,16 @@ int main() {
|
||||
"genserkins puma560 iterative inverse c");
|
||||
ok &= expect(genser_iterations > 0, "genserkins puma560 inverse should iterate from perturbed estimate");
|
||||
|
||||
LinuxCncAxisJoints limited_genser_inverse{};
|
||||
genser_iterations = -1;
|
||||
const bool limited_genser_ok = linuxcnc_genser_inverse_checked(genser_pose,
|
||||
genser_estimate,
|
||||
genser_parameters,
|
||||
&limited_genser_inverse,
|
||||
&genser_iterations,
|
||||
1);
|
||||
ok &= expect(!limited_genser_ok, "genserkins puma560 inverse fails when max_iterations is too low");
|
||||
ok &= expect_near(genser_iterations, 1, "genserkins failed inverse reports LinuxCNC iteration count");
|
||||
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -107,6 +107,8 @@ int main(int argc, char **argv) {
|
||||
CncSimHandle *sim = cnc_sim_create();
|
||||
bool first = true;
|
||||
cnc_sim_set_event_callback(sim, print_event, &first);
|
||||
const char smoke_config[] = "{\"backend\":\"smoke\"}";
|
||||
cnc_sim_load_config_json(sim, smoke_config, sizeof(smoke_config) - 1);
|
||||
|
||||
std::cout << "[\n";
|
||||
const int rc = cnc_sim_parse_program(sim, program.c_str(), program.size());
|
||||
|
||||
@@ -143,7 +143,10 @@ bool execute_line(InterpBase *interp,
|
||||
if (parse_simulator_gcode_control_line(line, &control_actions)) {
|
||||
bool simulator_only_line = true;
|
||||
for (const auto &action : control_actions) {
|
||||
emit_simulator_gcode_control_action(sink, action, line_number);
|
||||
const bool handled = emit_simulator_gcode_control_action(sink, action, line_number);
|
||||
if (!handled) {
|
||||
simulator_only_line = false;
|
||||
}
|
||||
if (action.kind == SimulatorGcodeControlKind::RtcpState &&
|
||||
!action.rtcp_enabled) {
|
||||
simulator_only_line = false;
|
||||
|
||||
3
core/wasm_shims/Python.h
Normal file
3
core/wasm_shims/Python.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
18
core/wasm_shims/boost/noncopyable.hpp
Normal file
18
core/wasm_shims/boost/noncopyable.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef CNC_SIM_WASM_SHIMS_BOOST_NONCOPYABLE_HPP
|
||||
#define CNC_SIM_WASM_SHIMS_BOOST_NONCOPYABLE_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
class noncopyable {
|
||||
protected:
|
||||
noncopyable() = default;
|
||||
~noncopyable() = default;
|
||||
|
||||
private:
|
||||
noncopyable(const noncopyable &) = delete;
|
||||
noncopyable &operator=(const noncopyable &) = delete;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // CNC_SIM_WASM_SHIMS_BOOST_NONCOPYABLE_HPP
|
||||
10
core/wasm_shims/boost/python/class.hpp
Normal file
10
core/wasm_shims/boost/python/class.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/call_traits.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifndef BOOST_DEDUCED_TYPENAME
|
||||
#define BOOST_DEDUCED_TYPENAME typename
|
||||
#endif
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
3
core/wasm_shims/boost/python/converter/registry.hpp
Normal file
3
core/wasm_shims/boost/python/converter/registry.hpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
13
core/wasm_shims/boost/python/def.hpp
Normal file
13
core/wasm_shims/boost/python/def.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
template <typename... Args>
|
||||
void def(Args &&...) {
|
||||
}
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
3
core/wasm_shims/boost/python/detail/caller.hpp
Normal file
3
core/wasm_shims/boost/python/detail/caller.hpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
25
core/wasm_shims/boost/python/enum.hpp
Normal file
25
core/wasm_shims/boost/python/enum.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
template <typename T>
|
||||
class enum_ {
|
||||
public:
|
||||
explicit enum_(const char *) {
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
enum_ &value(const char *, Value) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
enum_ &export_values() {
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
13
core/wasm_shims/boost/python/exception_translator.hpp
Normal file
13
core/wasm_shims/boost/python/exception_translator.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
template <typename Exception, typename Translator>
|
||||
void register_exception_translator(Translator) {
|
||||
}
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
5
core/wasm_shims/boost/python/module.hpp
Normal file
5
core/wasm_shims/boost/python/module.hpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
#define BOOST_PYTHON_MODULE(name) extern "C" void init_##name()
|
||||
@@ -1,24 +1,126 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdarg>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include "boost/noncopyable.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
using Py_ssize_t = std::ptrdiff_t;
|
||||
struct _object;
|
||||
using PyObject = _object;
|
||||
|
||||
struct _typeobject {
|
||||
const char *tp_name;
|
||||
std::size_t tp_basicsize;
|
||||
std::size_t tp_itemsize;
|
||||
void *tp_dealloc;
|
||||
void *tp_print;
|
||||
void *tp_getattr;
|
||||
void *tp_setattr;
|
||||
void *tp_compare;
|
||||
void *tp_repr;
|
||||
void *tp_as_number;
|
||||
void *tp_as_sequence;
|
||||
void *tp_as_mapping;
|
||||
void *tp_hash;
|
||||
void *tp_call;
|
||||
void *tp_str;
|
||||
void *tp_getattro;
|
||||
void *tp_setattro;
|
||||
void *tp_as_buffer;
|
||||
unsigned long tp_flags;
|
||||
const char *tp_doc;
|
||||
void *tp_traverse;
|
||||
void *tp_clear;
|
||||
void *tp_richcompare;
|
||||
Py_ssize_t tp_weaklistoffset;
|
||||
void *tp_iter;
|
||||
void *tp_iternext;
|
||||
void *tp_methods;
|
||||
void *tp_members;
|
||||
void *tp_getset;
|
||||
struct _typeobject *tp_base;
|
||||
void *tp_dict;
|
||||
void *tp_descr_get;
|
||||
void *tp_descr_set;
|
||||
Py_ssize_t tp_dictoffset;
|
||||
void *tp_init;
|
||||
void *tp_alloc;
|
||||
PyObject *(*tp_new)(struct _typeobject *, PyObject *, PyObject *);
|
||||
void *tp_free;
|
||||
void *tp_is_gc;
|
||||
void *tp_bases;
|
||||
void *tp_mro;
|
||||
void *tp_cache;
|
||||
void *tp_subclasses;
|
||||
void *tp_weaklink;
|
||||
void *tp_del;
|
||||
unsigned int tp_version_tag;
|
||||
void *tp_finalize;
|
||||
#if PY_VERSION_HEX >= 0x030800f0
|
||||
void *tp_vectorcall;
|
||||
#if PY_VERSION_HEX >= 0x030c00f0
|
||||
void *tp_watched;
|
||||
#if PY_VERSION_HEX >= 0x030d00f0
|
||||
void *tp_versions_used;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
using PyTypeObject = _typeobject;
|
||||
|
||||
struct _object {
|
||||
PyTypeObject *ob_type;
|
||||
};
|
||||
using PyObject = _object;
|
||||
|
||||
struct _inittab {
|
||||
const char *name;
|
||||
PyObject *(*initfunc)(void);
|
||||
};
|
||||
|
||||
using PyCFunction = PyObject *(*)(PyObject *, PyObject *);
|
||||
using getter = PyObject *(*)(PyObject *, void *);
|
||||
using setter = int (*)(PyObject *, PyObject *, void *);
|
||||
|
||||
struct PyGetSetDef {
|
||||
char *name;
|
||||
getter get;
|
||||
setter set;
|
||||
char *doc;
|
||||
void *closure;
|
||||
};
|
||||
|
||||
struct PyMemberDef {
|
||||
char *name;
|
||||
int type;
|
||||
Py_ssize_t offset;
|
||||
int flags;
|
||||
char *doc;
|
||||
};
|
||||
|
||||
struct PyMethodDef {
|
||||
const char *ml_name;
|
||||
PyCFunction ml_meth;
|
||||
int ml_flags;
|
||||
const char *ml_doc;
|
||||
};
|
||||
|
||||
struct PyModuleDef {
|
||||
void *m_base;
|
||||
const char *m_name;
|
||||
const char *m_doc;
|
||||
Py_ssize_t m_size;
|
||||
PyMethodDef *m_methods;
|
||||
void *m_slots;
|
||||
void *m_traverse;
|
||||
void *m_clear;
|
||||
void *m_free;
|
||||
};
|
||||
|
||||
int Py_IsInitialized(void);
|
||||
PyObject *PyErr_Occurred(void);
|
||||
void PyErr_Clear(void);
|
||||
@@ -31,21 +133,66 @@ int PyUnicode_Check(PyObject *);
|
||||
int PyLong_Check(PyObject *);
|
||||
int PyFloat_Check(PyObject *);
|
||||
int PyGen_Check(PyObject *);
|
||||
int PyObject_IsInstance(PyObject *, PyObject *);
|
||||
PyObject *PyObject_Str(PyObject *);
|
||||
const char *PyUnicode_AsUTF8(PyObject *);
|
||||
PyObject *PyUnicode_FromString(const char *);
|
||||
void PyErr_SetObject(PyObject *, PyObject *);
|
||||
PyObject *PyErr_Format(PyObject *, const char *, ...);
|
||||
void Py_DecRef(PyObject *);
|
||||
int PyArg_ParseTuple(PyObject *, const char *, ...);
|
||||
int PyArg_VaParse(PyObject *, const char *, va_list);
|
||||
PyObject *PyObject_CallMethod(PyObject *, char *, char *, ...);
|
||||
PyObject *PyObject_GetAttrString(PyObject *, const char *);
|
||||
int PyObject_SetAttrString(PyObject *, const char *, PyObject *);
|
||||
int PyObject_IsTrue(PyObject *);
|
||||
PyObject *PyLong_FromLong(long);
|
||||
long PyLong_AsLong(PyObject *);
|
||||
double PyFloat_AsDouble(PyObject *);
|
||||
PyObject *PyTuple_New(Py_ssize_t);
|
||||
PyObject *PyTuple_GetItem(PyObject *, Py_ssize_t);
|
||||
Py_ssize_t PyTuple_Size(PyObject *);
|
||||
int PyTuple_SetItem(PyObject *, Py_ssize_t, PyObject *);
|
||||
PyObject *PyList_New(Py_ssize_t);
|
||||
PyObject *PyList_GetItem(PyObject *, Py_ssize_t);
|
||||
Py_ssize_t PyList_Size(PyObject *);
|
||||
int PyList_SetItem(PyObject *, Py_ssize_t, PyObject *);
|
||||
PyObject *PySequence_GetItem(PyObject *, Py_ssize_t);
|
||||
Py_ssize_t PySequence_Length(PyObject *);
|
||||
PyObject *Py_BuildValue(const char *, ...);
|
||||
PyObject *PyModule_Create(PyModuleDef *);
|
||||
int PyModule_AddObject(PyObject *, const char *, PyObject *);
|
||||
int PyType_Ready(PyTypeObject *);
|
||||
PyObject *PyType_GenericNew(PyTypeObject *, PyObject *, PyObject *);
|
||||
void *PyObject_NewShim(std::size_t, PyTypeObject *);
|
||||
extern PyObject *PyExc_KeyError;
|
||||
extern PyObject *PyExc_KeyboardInterrupt;
|
||||
extern PyObject *PyExc_RuntimeError;
|
||||
extern PyObject *PyExc_StopIteration;
|
||||
extern PyObject *PyExc_TypeError;
|
||||
extern PyObject *_Py_NoneStructPtr;
|
||||
extern PyTypeObject PyString_Type;
|
||||
extern PyTypeObject PyInt_Type;
|
||||
extern PyTypeObject PyList_Type;
|
||||
|
||||
#define PyObject_HEAD PyObject ob_base;
|
||||
#define PyVarObject_HEAD_INIT(type, size)
|
||||
#define PyModuleDef_HEAD_INIT nullptr
|
||||
#define Py_TPFLAGS_DEFAULT 0
|
||||
#define PyMODINIT_FUNC extern "C" PyObject *
|
||||
#define METH_VARARGS 0x0001
|
||||
#define Py_None (_Py_NoneStructPtr)
|
||||
#define Py_TYPE(ob) ((ob)->ob_type)
|
||||
#define Py_DECREF(ob) Py_DecRef(reinterpret_cast<PyObject *>(ob))
|
||||
#define Py_XDECREF(ob) \
|
||||
do { \
|
||||
if (ob) { \
|
||||
Py_DecRef(ob); \
|
||||
Py_DecRef(reinterpret_cast<PyObject *>(ob)); \
|
||||
} \
|
||||
} while (0)
|
||||
#define PyTuple_SET_ITEM(op, i, v) PyTuple_SetItem((op), (i), (v))
|
||||
#define PyList_SET_ITEM(op, i, v) PyList_SetItem((op), (i), (v))
|
||||
#define PyObject_New(type, typeobj) reinterpret_cast<type *>(PyObject_NewShim(sizeof(type), (typeobj)))
|
||||
|
||||
}
|
||||
|
||||
@@ -106,6 +253,93 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct no_init_t {};
|
||||
inline constexpr no_init_t no_init{};
|
||||
|
||||
struct default_call_policies {};
|
||||
struct reference_existing_object {};
|
||||
|
||||
template <typename T>
|
||||
struct return_value_policy {
|
||||
};
|
||||
|
||||
template <int, int>
|
||||
struct with_custodian_and_ward_postcall {
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
struct init {
|
||||
};
|
||||
|
||||
class arg {
|
||||
public:
|
||||
explicit arg(const char *) {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T = void>
|
||||
struct type_info {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
type_info<T> type_id() {
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
object make_getter(Args &&...) {
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
object make_setter(Args &&...) {
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
object make_function(Args &&...) {
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename T, typename Bases = void>
|
||||
class class_ {
|
||||
public:
|
||||
explicit class_(const char *) {
|
||||
}
|
||||
|
||||
class_(const char *, no_init_t) {
|
||||
}
|
||||
|
||||
class_(const char *, const char *) {
|
||||
}
|
||||
|
||||
class_(const char *, const char *, no_init_t) {
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
class_(const char *, Arg) {
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
class_ &def(Args &&...) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
class_ &def_readwrite(Args &&...) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
class_ &add_property(Args &&...) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
PyObject *ptr() const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
inline object getattr(const object &, const char *) {
|
||||
return {};
|
||||
}
|
||||
@@ -115,6 +349,10 @@ public:
|
||||
template <typename T>
|
||||
void append(const T &) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void extend(const T &) {
|
||||
}
|
||||
};
|
||||
|
||||
class dict : public object {
|
||||
@@ -131,8 +369,35 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
tuple make_tuple(Args &&...) {
|
||||
return {};
|
||||
}
|
||||
|
||||
inline object operator%(const char *, const tuple &) {
|
||||
return {};
|
||||
}
|
||||
|
||||
inline object operator%(const object &, const tuple &) {
|
||||
return {};
|
||||
}
|
||||
|
||||
inline object operator+(const object &, const object &) {
|
||||
return {};
|
||||
}
|
||||
|
||||
inline object operator+(const object &, const char *) {
|
||||
return {};
|
||||
}
|
||||
|
||||
inline object operator+(const char *, const object &) {
|
||||
return {};
|
||||
}
|
||||
|
||||
class scope {
|
||||
public:
|
||||
scope() = default;
|
||||
|
||||
explicit scope(const object &) {
|
||||
}
|
||||
|
||||
@@ -187,6 +452,8 @@ allow_null_result<T> allow_null(T *value) {
|
||||
template <typename T = void>
|
||||
class handle {
|
||||
public:
|
||||
handle() = default;
|
||||
|
||||
template <typename U>
|
||||
explicit handle(const U &) {
|
||||
}
|
||||
@@ -194,6 +461,10 @@ public:
|
||||
explicit operator bool() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *get() const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class str : public object {
|
||||
|
||||
16
core/wasm_shims/boost/python/object/class_detail.hpp
Normal file
16
core/wasm_shims/boost/python/object/class_detail.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
namespace objects {
|
||||
|
||||
template <typename T>
|
||||
void *registered_class_object(T) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace objects
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
13
core/wasm_shims/boost/python/return_internal_reference.hpp
Normal file
13
core/wasm_shims/boost/python/return_internal_reference.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
template <int Owner = 1, typename BasePolicy = default_call_policies>
|
||||
struct return_internal_reference : BasePolicy {
|
||||
};
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
template <typename Map>
|
||||
class map_indexing_suite {
|
||||
};
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
99
core/wasm_shims/cnc_sim_wasm_runtime_probe_main.cc
Normal file
99
core/wasm_shims/cnc_sim_wasm_runtime_probe_main.cc
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "cnc_sim_api.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <wordexp.h>
|
||||
|
||||
namespace {
|
||||
|
||||
int collect_event(const CncSimEvent *event, void *user_data) {
|
||||
auto *events = static_cast<std::vector<CncSimEvent> *>(user_data);
|
||||
events->push_back(*event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool near(double lhs, double rhs) {
|
||||
return std::fabs(lhs - rhs) < 0.000001;
|
||||
}
|
||||
|
||||
bool wordexp_expands_home() {
|
||||
const char *home = std::getenv("HOME");
|
||||
if (!home || !home[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
wordexp_t expanded{};
|
||||
if (wordexp("~/cnc_sim_wordexp_probe", &expanded, 0) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string expected = std::string(home) + "/cnc_sim_wordexp_probe";
|
||||
const bool ok = expanded.we_wordc == 1 &&
|
||||
expanded.we_wordv &&
|
||||
expanded.we_wordv[0] &&
|
||||
std::strcmp(expanded.we_wordv[0], expected.c_str()) == 0;
|
||||
wordfree(&expanded);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool wordexp_expands_environment_variables() {
|
||||
setenv("CNC_SIM_WORDEXP_PROBE", "linuxcnc-wordexp", 1);
|
||||
|
||||
wordexp_t expanded{};
|
||||
if (wordexp("$CNC_SIM_WORDEXP_PROBE/path", &expanded, 0) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool ok = expanded.we_wordc == 1 &&
|
||||
expanded.we_wordv &&
|
||||
expanded.we_wordv[0] &&
|
||||
std::strcmp(expanded.we_wordv[0], "linuxcnc-wordexp/path") == 0;
|
||||
wordfree(&expanded);
|
||||
return ok;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
if (!wordexp_expands_home()) {
|
||||
return 5;
|
||||
}
|
||||
if (!wordexp_expands_environment_variables()) {
|
||||
return 6;
|
||||
}
|
||||
|
||||
std::vector<CncSimEvent> events;
|
||||
CncSimHandle *sim = cnc_sim_create();
|
||||
if (!sim) {
|
||||
return 1;
|
||||
}
|
||||
if (cnc_sim_set_event_callback(sim, collect_event, &events) != 0) {
|
||||
cnc_sim_destroy(sim);
|
||||
return 2;
|
||||
}
|
||||
|
||||
const char program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G0 X1\n"
|
||||
"M30\n";
|
||||
if (cnc_sim_parse_program(sim, program, sizeof(program) - 1) != 0) {
|
||||
cnc_sim_destroy(sim);
|
||||
return 3;
|
||||
}
|
||||
|
||||
bool saw_linuxcnc_rapid = false;
|
||||
bool saw_program_end = false;
|
||||
for (const auto &event : events) {
|
||||
saw_linuxcnc_rapid = saw_linuxcnc_rapid ||
|
||||
(event.type == CNC_SIM_EVENT_RAPID &&
|
||||
event.line == 2 &&
|
||||
near(event.end.x, 1.0));
|
||||
saw_program_end = saw_program_end || event.type == CNC_SIM_EVENT_PROGRAM_END;
|
||||
}
|
||||
|
||||
cnc_sim_destroy(sim);
|
||||
return saw_linuxcnc_rapid && saw_program_end ? 0 : 4;
|
||||
}
|
||||
20
core/wasm_shims/libgen.h
Normal file
20
core/wasm_shims/libgen.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef CNC_SIM_WASM_SHIMS_LIBGEN_H
|
||||
#define CNC_SIM_WASM_SHIMS_LIBGEN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *dirname(char *);
|
||||
char *basename(char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
inline char *basename(const char *path)
|
||||
{
|
||||
return basename(const_cast<char *>(path));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CNC_SIM_WASM_SHIMS_LIBGEN_H
|
||||
@@ -1,6 +1,12 @@
|
||||
#include "boost/python/object.hpp"
|
||||
#include "hal.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <wordexp.h>
|
||||
|
||||
int _task = 0;
|
||||
|
||||
extern "C" PyObject *PyInit_interpreter(void) {
|
||||
@@ -11,6 +17,10 @@ extern "C" PyObject *PyInit_emccanon(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" PyObject *PyInit_gcode(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
struct _inittab builtin_modules[] = {
|
||||
{"interpreter", PyInit_interpreter},
|
||||
@@ -70,3 +80,119 @@ extern "C" int hal_get_param_value_by_name(const char *,
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
std::string expand_home_directory(const char *words) {
|
||||
std::string expanded(words);
|
||||
if (expanded.empty() || expanded[0] != '~') {
|
||||
return expanded;
|
||||
}
|
||||
if (expanded.size() > 1 && expanded[1] != '/') {
|
||||
return expanded;
|
||||
}
|
||||
|
||||
const char *home = std::getenv("HOME");
|
||||
if (!home || !home[0]) {
|
||||
return expanded;
|
||||
}
|
||||
expanded.replace(0, 1, home);
|
||||
return expanded;
|
||||
}
|
||||
|
||||
bool variable_start(char value) {
|
||||
const unsigned char ch = static_cast<unsigned char>(value);
|
||||
return std::isalpha(ch) || value == '_';
|
||||
}
|
||||
|
||||
bool variable_char(char value) {
|
||||
const unsigned char ch = static_cast<unsigned char>(value);
|
||||
return std::isalnum(ch) || value == '_';
|
||||
}
|
||||
|
||||
std::string expand_environment_variables(const std::string &words) {
|
||||
std::string expanded;
|
||||
expanded.reserve(words.size());
|
||||
|
||||
for (size_t index = 0; index < words.size();) {
|
||||
if (words[index] != '$' || index + 1 >= words.size()) {
|
||||
expanded.push_back(words[index++]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (words[index + 1] == '{') {
|
||||
const size_t end = words.find('}', index + 2);
|
||||
if (end == std::string::npos || end == index + 2) {
|
||||
expanded.push_back(words[index++]);
|
||||
continue;
|
||||
}
|
||||
const std::string name = words.substr(index + 2, end - index - 2);
|
||||
if (const char *value = std::getenv(name.c_str())) {
|
||||
expanded += value;
|
||||
}
|
||||
index = end + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!variable_start(words[index + 1])) {
|
||||
expanded.push_back(words[index++]);
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t end = index + 2;
|
||||
while (end < words.size() && variable_char(words[end])) {
|
||||
++end;
|
||||
}
|
||||
const std::string name = words.substr(index + 1, end - index - 1);
|
||||
if (const char *value = std::getenv(name.c_str())) {
|
||||
expanded += value;
|
||||
}
|
||||
index = end;
|
||||
}
|
||||
|
||||
return expanded;
|
||||
}
|
||||
|
||||
std::string expand_path_word(const char *words) {
|
||||
return expand_environment_variables(expand_home_directory(words));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" int wordexp(const char *words, wordexp_t *pwordexp, int) {
|
||||
if (!words || !pwordexp) {
|
||||
return WRDE_BADVAL;
|
||||
}
|
||||
|
||||
const std::string expanded = expand_path_word(words);
|
||||
char **wordv = static_cast<char **>(std::calloc(2, sizeof(char *)));
|
||||
if (!wordv) {
|
||||
return WRDE_NOSPACE;
|
||||
}
|
||||
|
||||
wordv[0] = static_cast<char *>(std::malloc(expanded.size() + 1));
|
||||
if (!wordv[0]) {
|
||||
std::free(wordv);
|
||||
return WRDE_NOSPACE;
|
||||
}
|
||||
|
||||
std::strcpy(wordv[0], expanded.c_str());
|
||||
pwordexp->we_wordc = 1;
|
||||
pwordexp->we_wordv = wordv;
|
||||
pwordexp->we_offs = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void wordfree(wordexp_t *pwordexp) {
|
||||
if (!pwordexp || !pwordexp->we_wordv) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < pwordexp->we_wordc; ++index) {
|
||||
std::free(pwordexp->we_wordv[index]);
|
||||
}
|
||||
std::free(pwordexp->we_wordv);
|
||||
pwordexp->we_wordc = 0;
|
||||
pwordexp->we_wordv = nullptr;
|
||||
pwordexp->we_offs = 0;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
extern "C" {
|
||||
|
||||
static PyTypeObject none_type = {"NoneType"};
|
||||
static PyObject none_object = {&none_type};
|
||||
|
||||
PyObject *PyExc_KeyError = reinterpret_cast<PyObject *>(1);
|
||||
PyObject *PyExc_StopIteration = reinterpret_cast<PyObject *>(2);
|
||||
PyObject *PyExc_KeyboardInterrupt = reinterpret_cast<PyObject *>(2);
|
||||
PyObject *PyExc_RuntimeError = reinterpret_cast<PyObject *>(3);
|
||||
PyObject *PyExc_StopIteration = reinterpret_cast<PyObject *>(4);
|
||||
PyObject *PyExc_TypeError = reinterpret_cast<PyObject *>(5);
|
||||
PyObject *_Py_NoneStructPtr = &none_object;
|
||||
PyTypeObject PyString_Type = {"str"};
|
||||
PyTypeObject PyInt_Type = {"int"};
|
||||
PyTypeObject PyList_Type = {"list"};
|
||||
|
||||
int Py_IsInitialized(void) {
|
||||
return 1;
|
||||
@@ -62,6 +70,10 @@ int PyGen_Check(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyObject_IsInstance(PyObject *, PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyObject_Str(PyObject *) {
|
||||
return &none_object;
|
||||
}
|
||||
@@ -70,7 +82,122 @@ const char *PyUnicode_AsUTF8(PyObject *) {
|
||||
return "";
|
||||
}
|
||||
|
||||
PyObject *PyUnicode_FromString(const char *) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
void PyErr_SetObject(PyObject *, PyObject *) {
|
||||
}
|
||||
|
||||
PyObject *PyErr_Format(PyObject *, const char *, ...) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Py_DecRef(PyObject *) {
|
||||
}
|
||||
|
||||
int PyArg_ParseTuple(PyObject *, const char *, ...) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyArg_VaParse(PyObject *, const char *, va_list) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyObject_CallMethod(PyObject *, char *, char *, ...) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
PyObject *PyObject_GetAttrString(PyObject *, const char *) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
int PyObject_SetAttrString(PyObject *, const char *, PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyObject_IsTrue(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyLong_FromLong(long) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
long PyLong_AsLong(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
double PyFloat_AsDouble(PyObject *) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
PyObject *PyTuple_New(Py_ssize_t) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
PyObject *PyTuple_GetItem(PyObject *, Py_ssize_t) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
Py_ssize_t PyTuple_Size(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyTuple_SetItem(PyObject *, Py_ssize_t, PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyList_New(Py_ssize_t) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
PyObject *PyList_GetItem(PyObject *, Py_ssize_t) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
Py_ssize_t PyList_Size(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyList_SetItem(PyObject *, Py_ssize_t, PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PySequence_GetItem(PyObject *, Py_ssize_t) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
Py_ssize_t PySequence_Length(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *Py_BuildValue(const char *, ...) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
PyObject *PyModule_Create(PyModuleDef *) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
int PyModule_AddObject(PyObject *, const char *, PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyType_Ready(PyTypeObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyType_GenericNew(PyTypeObject *, PyObject *, PyObject *) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
void *PyObject_NewShim(std::size_t size, PyTypeObject *type) {
|
||||
auto *object = static_cast<PyObject *>(std::calloc(1, size));
|
||||
if (object) {
|
||||
object->ob_type = type;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "pythonplugin/python_plugin.hh"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
__attribute__((weak)) std::string handle_pyerror() {
|
||||
return "python disabled in wasm-safe probe";
|
||||
}
|
||||
@@ -13,7 +16,30 @@ PythonPlugin *PythonPlugin::instantiate(struct _inittab *) {
|
||||
return python_plugin;
|
||||
}
|
||||
|
||||
int PythonPlugin::configure(const char *, const char *) {
|
||||
int PythonPlugin::configure(const char *iniFilename, const char *section) {
|
||||
if (!section) {
|
||||
error_msg = "no section";
|
||||
status = PLUGIN_NO_SECTION;
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!iniFilename) {
|
||||
iniFilename = std::getenv("INI_FILE_NAME");
|
||||
if (!iniFilename) {
|
||||
error_msg = "no inifile";
|
||||
status = PLUGIN_NO_INIFILE;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *file = std::fopen(iniFilename, "r");
|
||||
if (!file) {
|
||||
error_msg = "bad inifile";
|
||||
status = PLUGIN_BAD_INIFILE;
|
||||
return status;
|
||||
}
|
||||
std::fclose(file);
|
||||
|
||||
status = PLUGIN_OK;
|
||||
return status;
|
||||
}
|
||||
@@ -23,12 +49,17 @@ bool PythonPlugin::is_callable(const char *, const char *) {
|
||||
}
|
||||
|
||||
int PythonPlugin::call(const char *,
|
||||
const char *,
|
||||
const char *callable,
|
||||
boost::python::object,
|
||||
boost::python::object,
|
||||
boost::python::object &retval) {
|
||||
if (!callable) {
|
||||
return PLUGIN_NO_CALLABLE;
|
||||
}
|
||||
|
||||
retval = boost::python::object();
|
||||
status = PLUGIN_NO_CALLABLE;
|
||||
exception_msg = handle_pyerror();
|
||||
status = PLUGIN_EXCEPTION;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,34 @@ int main() {
|
||||
if (!plugin->usable()) {
|
||||
return 2;
|
||||
}
|
||||
if (plugin->configure(nullptr, nullptr) != PLUGIN_NO_SECTION) {
|
||||
return 6;
|
||||
}
|
||||
if (plugin->configure("/tmp/cnc_sim_missing_python_plugin_probe.ini", "PYTHON") != PLUGIN_BAD_INIFILE) {
|
||||
return 7;
|
||||
}
|
||||
boost::python::object retval;
|
||||
if (plugin->run_string("noop", retval, false) != PLUGIN_OK) {
|
||||
return 3;
|
||||
}
|
||||
if (plugin->call(nullptr, nullptr, boost::python::object(), boost::python::object(), retval) != PLUGIN_NO_CALLABLE) {
|
||||
return 8;
|
||||
}
|
||||
if (plugin->plugin_status() != PLUGIN_OK) {
|
||||
return 9;
|
||||
}
|
||||
if (plugin->call(nullptr, "noop", boost::python::object(), boost::python::object(), retval) != PLUGIN_EXCEPTION) {
|
||||
return 10;
|
||||
}
|
||||
if (plugin->plugin_status() != PLUGIN_EXCEPTION) {
|
||||
return 11;
|
||||
}
|
||||
if (plugin->last_exception().empty()) {
|
||||
return 12;
|
||||
}
|
||||
if (plugin->run_string("noop", retval, false) != PLUGIN_OK) {
|
||||
return 13;
|
||||
}
|
||||
if (plugin->is_callable(nullptr, "noop")) {
|
||||
return 4;
|
||||
}
|
||||
@@ -20,4 +44,3 @@ int main() {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
7
core/wasm_shims/structmember.h
Normal file
7
core/wasm_shims/structmember.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
#define T_INT 1
|
||||
#define T_DOUBLE 2
|
||||
#define READONLY 1
|
||||
@@ -19,6 +19,7 @@ extern "C" {
|
||||
|
||||
toolidx_t tooldata_put(CANON_TOOL_TABLE tdata, int idx) {
|
||||
if (!mmap_created) {
|
||||
std::fprintf(stderr, "%5d tooldata_put() no tool_mmap_base\n", getpid());
|
||||
return IDX_FAIL;
|
||||
}
|
||||
if (idx < 0 || idx >= CANON_POCKETS_MAX) {
|
||||
@@ -110,7 +111,11 @@ int tool_mmap_creator(EMC_TOOL_STAT const *ptr, int random_toolchanger) {
|
||||
}
|
||||
|
||||
int tool_mmap_user(void) {
|
||||
return mmap_created ? 0 : -1;
|
||||
if (!mmap_created) {
|
||||
std::fprintf(stderr, "tool_mmap_user(): tool mmap not available\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tool_mmap_close(void) {
|
||||
|
||||
Reference in New Issue
Block a user