diff --git a/.clang-format b/.clang-format deleted file mode 100644 index d645254..0000000 --- a/.clang-format +++ /dev/null @@ -1,94 +0,0 @@ ---- -Language: Cpp -BasedOnStyle: LLVM -IndentWidth: 4 -TabWidth: 4 -UseTab: Never -ColumnLimit: 100 -AccessModifierOffset: -4 -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -AlignEscapedNewlines: Right -AlignOperands: true -AlignTrailingComments: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -AllowShortFunctionsOnASingleLine: Empty -AllowShortBlocksOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: false -BinPackArguments: true -BinPackParameters: true -BraceWrapping: - AfterClass: false - AfterControlStatement: false - AfterEnum: false - AfterFunction: false - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false - BeforeCatch: true - BeforeElse: true - IndentBraces: false -BreakBeforeBinaryOperators: None -BreakBeforeBraces: Attach -BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: false -BreakAfterJavaFieldAnnotations: false -BreakStringLiterals: true -CommentPragmas: '^ IWYU pragma:' -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -DisableFormat: false -ExperimentalAutoDetectBinPacking: false -ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] -IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 3 - - Regex: '.*' - Priority: 1 -IncludeIsMainRegex: '([-_](test|unittest))?$' -IndentCaseLabels: true -IndentWrappedFunctionNames: false -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: true -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBlockIndentWidth: 2 -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: false -PenaltyBreakBeforeFirstCallParameter: 1 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyBreakAssignment: 2 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 200 -PointerAlignment: Right -ReflowComments: true -SortIncludes: true -SpaceAfterCStyleCast: false -SpaceAfterTemplateKeyword: true -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: C++17 diff --git a/.clang-tidy b/.clang-tidy deleted file mode 100644 index b02d4a2..0000000 --- a/.clang-tidy +++ /dev/null @@ -1,59 +0,0 @@ ---- -Checks: > - -*, - bugprone-*, - cert-*, - cppcoreguidelines-*, - -cppcoreguidelines-avoid-magic-numbers, - -cppcoreguidelines-pro-bounds-array-to-pointer-decay, - -cppcoreguidelines-pro-type-union-access, - -cppcoreguidelines-pro-bounds-constant-array-index, - -cppcoreguidelines-avoid-non-const-global-variables, - misc-*, - -misc-non-private-member-variables-in-classes, - performance-*, - -performance-avoid-endl, - readability-*, - -readability-magic-numbers, - -readability-identifier-length, - -readability-function-cognitive-complexity, - modernize-*, - -modernize-use-trailing-return-type, - -modernize-avoid-c-arrays - -WarningsAsErrors: '' -HeaderFilterRegex: '.*' -AnalyzeTemporaryDtors: false -FormatStyle: 'file' -User: '' -CheckOptions: - - key: readability-identifier-naming.NamespaceCase - value: lower_case - - key: readability-identifier-naming.ClassCase - value: CamelCase - - key: readability-identifier-naming.StructCase - value: CamelCase - - key: readability-identifier-naming.FunctionCase - value: camelBack - - key: readability-identifier-naming.VariableCase - value: camelBack - - key: readability-identifier-naming.ParameterCase - value: camelBack - - key: readability-identifier-naming.MemberCase - value: camelBack - - key: readability-identifier-naming.PrivateMemberPrefix - value: m_ - - key: readability-identifier-naming.ProtectedMemberPrefix - value: m_ - - key: readability-identifier-naming.EnumCase - value: CamelCase - - key: readability-identifier-naming.EnumConstantCase - value: UPPER_CASE - - key: readability-identifier-naming.ConstantCase - value: UPPER_CASE - - key: readability-identifier-naming.MacroDefinitionCase - value: UPPER_CASE - - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor - value: true - - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions - value: true diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 65c2709..0000000 --- a/.gitattributes +++ /dev/null @@ -1,33 +0,0 @@ -# 自动检测文本文件并规范化行尾 -* text=auto - -# 明确指定文本文件使用 LF 换行符 -*.cpp text eol=lf -*.h text eol=lf -*.hpp text eol=lf -*.c text eol=lf -*.cmake text eol=lf -CMakeLists.txt text eol=lf -*.txt text eol=lf -*.md text eol=lf -*.sh text eol=lf -*.yml text eol=lf -*.yaml text eol=lf -*.json text eol=lf - -# 二进制文件 -*.so binary -*.dll binary -*.dylib binary -*.a binary -*.lib binary -*.exe binary -*.png binary -*.jpg binary -*.jpeg binary -*.gif binary -*.ico binary -*.pdf binary - -# 第三方库目录保持原样 -third_party/** -text diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ae6e96..af6438c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -179,26 +179,26 @@ jobs: cmake --build . \ --config Release \ --parallel $(nproc) \ - --target toolset_example action_group_show_l10 + --target test test_o6_can_0 - name: 验证示例程序 working-directory: build run: | echo "=== 验证构建产物 ===" - if [ -f toolset_example ]; then - echo "✓ toolset_example 构建成功" - file toolset_example - ls -lh toolset_example + if [ -f bin/test ]; then + echo "✓ test 构建成功" + file bin/test + ls -lh bin/test else - echo "✗ toolset_example 未找到" + echo "✗ test 未找到" exit 1 fi - if [ -f action_group_show_l10 ]; then - echo "✓ action_group_show_l10 构建成功" - file action_group_show_l10 - ls -lh action_group_show_l10 + if [ -f bin/test_o6_can_0 ]; then + echo "✓ test_o6_can_0 构建成功" + file bin/test_o6_can_0 + ls -lh bin/test_o6_can_0 else - echo "✗ action_group_show_l10 未找到" + echo "✗ test_o6_can_0 未找到" exit 1 fi diff --git a/.gitignore b/.gitignore index e3380a2..f5669a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,2 @@ build .vscode/ -linker_hand/build -TODO.md -PROJECT_ANALYSIS.md diff --git a/CMakeLists.txt b/CMakeLists.txt index ef21a2a..d4b3969 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,123 +1,81 @@ -cmake_minimum_required(VERSION 3.15) -project(LinkerHand-CPP-SDK - VERSION 1.1.7 - LANGUAGES CXX - DESCRIPTION "LinkerHand C++ SDK for robotic hand control" -) - -if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") - set(LIB_SUBDIR "x86_64") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64") - set(LIB_SUBDIR "aarch64") -else() - message(WARNING "Unknown architecture, defaulting to x86_64") - set(LIB_SUBDIR "x86_64") -endif() +cmake_minimum_required(VERSION 3.10) +project(LinkerHandSDKExamples LANGUAGES CXX) -#----------------------------------------------------------------------------- -# LINKER_HAND_CPP_SDK -#----------------------------------------------------------------------------- -find_library(LINKER_HAND_LIB - NAMES linkerhand_cpp_sdk linkerhand_cpp - PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib/${LIB_SUBDIR} - /usr/local/lib/linkerhand-cpp-sdk/${LIB_SUBDIR} - /usr/lib/linkerhand-cpp-sdk/${LIB_SUBDIR} - ${CMAKE_INSTALL_PREFIX}/lib/linkerhand-cpp-sdk/${LIB_SUBDIR} - NO_DEFAULT_PATH -) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) -set(LINKER_HAND_INCLUDE_DIR - ${CMAKE_CURRENT_SOURCE_DIR}/include - /usr/local/include/linkerhand-cpp-sdk - /usr/include/linkerhand-cpp-sdk - ${CMAKE_INSTALL_PREFIX}/include/linkerhand-cpp-sdk -) +option(BUILD_EXAMPLES "Build example applications" ON) +option(BUILD_HAND_TEACH_PENDANT "Build hand teach pendant application" OFF) -if(NOT LINKER_HAND_LIB) - message(FATAL_ERROR "linkerhand_cpp_sdk library not found!") +if(BUILD_EXAMPLES) + add_subdirectory(examples) endif() -if(NOT LINKER_HAND_INCLUDE_DIR) - message(FATAL_ERROR "LinkerHand headers not found!") +if(BUILD_HAND_TEACH_PENDANT) + add_subdirectory(hand_teach_pendant) endif() -message(STATUS "Found linkerhand_cpp_sdk library: ${LINKER_HAND_LIB}") -message(STATUS "Found LinkerHand headers: ${LINKER_HAND_INCLUDE_DIR}") - -#----------------------------------------------------------------------------- -# INCLUDE_DIRECTORIES -#----------------------------------------------------------------------------- -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${LINKER_HAND_INCLUDE_DIR} -) - -#----------------------------------------------------------------------------- -# EXECUTABLE -#----------------------------------------------------------------------------- -add_executable(my_project src/main.cpp) -target_link_libraries(my_project ${LINKER_HAND_LIB} pthread) - -add_executable(toolset_example examples/toolset_example.cpp) -target_link_libraries(toolset_example ${LINKER_HAND_LIB} pthread) - -add_executable(action_group_show_l10 examples/action_group_show_l10.cpp) -target_link_libraries(action_group_show_l10 ${LINKER_HAND_LIB} pthread) - -#----------------------------------------------------------------------------- -# INSTALL TARGETS -#----------------------------------------------------------------------------- -# 安装头文件 -install(DIRECTORY include/ - DESTINATION include/linkerhand-cpp-sdk - FILES_MATCHING PATTERN "*.h" -) - -# 安装库文件 -if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/lib/${LIB_SUBDIR}) - install(DIRECTORY lib/${LIB_SUBDIR}/ - DESTINATION lib/linkerhand-cpp-sdk/${LIB_SUBDIR} - FILES_MATCHING PATTERN "*.so*" - ) +message(STATUS "=== LinkerHand C++ SDK Examples ===") +message(STATUS "Version: 2.0.0") +message(STATUS "Build Examples: ${BUILD_EXAMPLES}") +message(STATUS "Build Hand Teach Pendant: ${BUILD_HAND_TEACH_PENDANT}") +message(STATUS "=====================================") + +# --------------------------------------------------------------------------- +# 安装规则(发布包模式) +# 本目录是 pack.sh 产出的发布包:SDK 已是预编译产物,源码不在此处。 +# cmake --install 时把 include/ 头与对应平台的 lib 铺到 prefix,与 build.sh +# 期望的目录布局保持一致: +# $PREFIX/include/linkerhand-cpp-sdk/{api,core,communication}/*.h +# $PREFIX/lib/linkerhand-cpp-sdk/lib/<预编译库> +# build.sh 随后在 $PREFIX/lib/ 建符号链接 + ldconfig。 +# --------------------------------------------------------------------------- + +set(LH_INSTALL_INCLUDE_DIR "include/linkerhand-cpp-sdk") +set(LH_INSTALL_LIB_ROOT "lib/linkerhand-cpp-sdk") + +# 头:按子目录白名单发布 +install(DIRECTORY include/api/ DESTINATION "${LH_INSTALL_INCLUDE_DIR}/api" FILES_MATCHING PATTERN "*.h") +install(DIRECTORY include/core/ DESTINATION "${LH_INSTALL_INCLUDE_DIR}/core" FILES_MATCHING PATTERN "*.h") +install(DIRECTORY include/communication/ DESTINATION "${LH_INSTALL_INCLUDE_DIR}/communication" FILES_MATCHING PATTERN "*.h") + +# 平台/架构选库:与 lib/ 实际目录布局一致 +set(LH_LIB_SRC_DIR "") +if(WIN32) + if(MSVC) + set(LH_LIB_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib/win64/msvc") + else() + set(LH_LIB_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib/win64/mingw") + endif() +elseif(UNIX AND NOT APPLE) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64|AMD64)$") + set(LH_LIB_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib/linux/x86_64") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)$") + set(LH_LIB_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib/linux/arm64") + endif() endif() -#----------------------------------------------------------------------------- -# PACKAGE CONFIGURATION -#----------------------------------------------------------------------------- -include(CMakePackageConfigHelpers) - -# 创建包配置文件 -write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/LinkerHandCPPSDKConfigVersion.cmake" - VERSION ${PROJECT_VERSION} - COMPATIBILITY AnyNewerVersion -) - -# 设置包配置变量(用于 configure_file) -set(PACKAGE_INCLUDE_INSTALL_DIR "include/linkerhand-cpp-sdk") -set(PACKAGE_LIB_INSTALL_DIR "lib/linkerhand-cpp-sdk/${LIB_SUBDIR}") - -# 创建包配置文件模板 -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/LinkerHandCPPSDKConfig.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/LinkerHandCPPSDKConfig.cmake" - @ONLY -) +if(LH_LIB_SRC_DIR AND EXISTS "${LH_LIB_SRC_DIR}") + # 用 install(DIRECTORY) 而非 install(FILES):保留 .so → .so.2 → .so.2.0.0 的软链 + install(DIRECTORY "${LH_LIB_SRC_DIR}/" DESTINATION "${LH_INSTALL_LIB_ROOT}/lib" USE_SOURCE_PERMISSIONS) + message(STATUS "Install lib source: ${LH_LIB_SRC_DIR}") +else() + message(WARNING "No prebuilt lib matched (system=${CMAKE_SYSTEM_NAME} arch=${CMAKE_SYSTEM_PROCESSOR}); install will skip libs.") +endif() -# 安装包配置文件 +# CMake config 包:让下游用 find_package(linkerhand-cpp-sdk CONFIG REQUIRED) +# 配置文件相对路径自定位(见 cmake/linkerhand-cpp-sdk-config.cmake), +# prefix 改了无需重新生成。 install(FILES - "${CMAKE_CURRENT_BINARY_DIR}/LinkerHandCPPSDKConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/LinkerHandCPPSDKConfigVersion.cmake" - DESTINATION lib/cmake/LinkerHandCPPSDK + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/linkerhand-cpp-sdk-config.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/linkerhand-cpp-sdk-config-version.cmake" + DESTINATION "lib/cmake/linkerhand-cpp-sdk" ) -#----------------------------------------------------------------------------- -# TESTING -#----------------------------------------------------------------------------- -# 添加选项以启用/禁用测试 -option(BUILD_TESTING "Build the testing tree" ON) - -# 如果启用测试,包含测试子目录 -if(BUILD_TESTING) - add_subdirectory(tests) +# third_party 头:CanFD.h / PCANBus.h / CanFrame.h 公共头泄漏了 Hcanbus.h / PCANBasic.h, +# 任何 include 它们的下游都得有这条路径,所以随包发布。 +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/third_party") + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/third_party/" + DESTINATION "${LH_INSTALL_LIB_ROOT}/third_party") endif() diff --git a/README.md b/README.md index 748ba0f..58a9b62 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,63 @@ # LinkerHand-CPP-SDK [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -[![Platform](https://img.shields.io/badge/Platform-Linux-blue.svg)](https://www.linux.org/) +[![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20Windows-blue.svg)]() [![Architecture](https://img.shields.io/badge/Arch-x86__64%20%7C%20aarch64-lightgrey.svg)]() [![CI/CD](https://github.com/linker-bot/linkerhand-cpp-sdk/workflows/CI/CD/badge.svg)](https://github.com/linker-bot/linkerhand-cpp-sdk/actions) -> 用于灵心巧手系列灵巧手的 C++ 软件开发工具包 +> 灵心巧手系列灵巧手的官方 C++ 软件开发工具包 -LinkerHand-CPP-SDK 是由灵心巧手(北京)科技有限公司开发的官方 C++ SDK,提供完整的 API 接口用于控制 O6、L6、L7、L10、L20、L21、L25 等型号的灵巧手设备。 +LinkerHand-CPP-SDK 由灵心巧手(北京)科技有限公司开发,提供完整的 C++ API,用于控制 L6、L7、L10、L20、L21、L25、O6、O20、G20等型号的灵巧手设备,支持 CAN / CAN-FD / Modbus 多种总线。 + +--- ## 📋 目录 - [特性](#-特性) - [系统要求](#-系统要求) - [快速开始](#-快速开始) -- [安装](#-安装) -- [使用示例](#-使用示例) - [API 文档](#-api-文档) - [通信协议](#-通信协议) +- [支持的型号](#-支持的型号) - [项目结构](#-项目结构) -- [构建项目](#-构建项目) +- [示例程序列表](#-示例程序列表) +- [关节映射表](#-关节映射表) - [故障排查](#-故障排查) - [常见问题](#-常见问题) - [贡献](#-贡献) +- [更新日志](#-更新日志) - [许可证](#-许可证) - [联系我们](#-联系我们) +--- + ## ✨ 特性 -- 🎯 **多型号支持** - 支持 O6、L6、L7、L10、L20、L21、L25 等多种型号 -- 🚀 **简单易用** - 提供简洁的 C++ API 接口 -- 🔌 **通信协议** - 支持 CAN 通信 -- 📊 **传感器数据** - 实时获取压力、温度、电流等传感器数据 -- 🎮 **精确控制** - 支持关节位置、速度、扭矩的精确控制 -- 🔄 **实时反馈** - 获取关节状态、电机故障码等实时信息 -- 🛠️ **跨平台** - 支持 Linux (x86_64, aarch64) -- 📚 **完整文档** - 提供详细的 API 文档和使用示例 +- 🎯 **多型号支持** — L6 / L7 / L10 / L20 / L21 / L25 / O6 / O20 / G20 +- 🔌 **多总线** — CAN、CAN-FD、Modbus +- 🚀 **易用** — 简洁的 C++ API,回调注入式通信层,便于嵌入到自有应用 +- 📊 **传感数据** — 实时获取压力、温度、电流等传感器读数 +- 🎮 **精确控制** — 支持关节位置(原始值 / 弧度)、速度、扭矩控制 +- 🔄 **实时反馈** — 关节状态、电机故障码等实时上报 +- 🛠️ **跨平台** — Linux (x86_64 / aarch64)、Windows (MinGW) +- 📚 **完整文档** — 附 API 参考、FAQ 与排障文档 ## 💻 系统要求 -- **操作系统**: Linux (Ubuntu 18.04+ 推荐) -- **架构**: x86_64 或 aarch64 -- **编译器**: GCC 7.0+ 或 Clang 5.0+ -- **CMake**: 3.15+ -- **依赖**: pthread +**Linux** +- 操作系统:Ubuntu 18.04 及以上 +- 架构:x86_64 或 aarch64 +- 编译器:GCC 7.0+ 或 Clang 6.0+(C++17) +- CMake:3.15+ +- 依赖:pthread + +**Windows** +- 操作系统:Windows 10 / 11 (x64) +- 编译器:MinGW-w64 GCC 13+,线程模型需为 `win32`(`g++ -v` 查看 `Thread model`),或 MSVC(VS2017 / VS2019 / VS2022 任一,已实测 VS2017 消费 CI artifact 通过) +- CMake:建议 4.0+(已实测 4.0.3) +- 依赖:`PCAN-Basic` 与 mingw 运行时 DLL 已随发布包附带 + +> CAN-FD 在 ARM + Ubuntu ≤ 18 上自动禁用;O20(CAN-FD)目前仅在 Linux x86_64 上支持。 ## 🚀 快速开始 @@ -54,351 +68,293 @@ git clone https://github.com/linker-bot/linkerhand-cpp-sdk.git cd linkerhand-cpp-sdk ``` -### 2. 使用安装脚本(推荐) - -```bash -./script.sh -``` - -选择选项 `[2]: Install SDK` 进行构建和安装。 - -### 3. 基本使用示例 - -创建 `main.cpp` 文件: +### 2. 使用脚本构建 -```cpp -#include "LinkerHandApi.h" -#include -#include -#include - -int main() { - // 初始化 L10 型号右手 - LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); - - // 获取版本信息 - std::cout << "SDK Version: " << hand.getVersion() << std::endl; +发布包内附 `build.sh`(Linux)与 `build.bat`(Windows)。 - // 握拳动作 - std::vector fist_pose = {101, 60, 0, 0, 0, 0, 255, 255, 255, 51}; - hand.fingerMove(fist_pose); - std::this_thread::sleep_for(std::chrono::seconds(1)); +| 选项 | 说明 | +|------|------| +| `-h`, `--help` | 显示帮助信息 | +| `-b`, `--build` | 构建示例程序 | +| `-i`, `--install` | 安装 SDK 到系统(需 sudo) | +| `-u`, `--uninstall` | 从系统卸载 SDK(需 sudo) | +| `-c`, `--clean` | 清理 `build/` 目录 | +| `--prefix PATH` | 指定安装前缀(默认 `/usr/local`) | - // 张开动作 - std::vector open_pose = {255, 104, 255, 255, 255, 255, 255, 255, 255, 71}; - hand.fingerMove(open_pose); - std::this_thread::sleep_for(std::chrono::seconds(1)); +```bash +# Linux +./build.sh -b # 编译 +sudo ./build.sh -i # 编译并安装到 /usr/local +sudo ./build.sh -u # 卸载 - return 0; -} +# Windows(cmd / PowerShell) +build.bat # 编译 ``` -### 4. 编译和运行 +> 发布包是预编译产物,`build.sh` 仅负责装配示例与触发安装;SDK 共享库取自 `lib/` 下对应平台目录,无须从源码编译。 -创建 `CMakeLists.txt`: - -```cmake -cmake_minimum_required(VERSION 3.15) -project(LinkerHand-CPP-SDK) - -# 检测系统架构 -if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") - set(LIB_SUBDIR "x86_64") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64") - set(LIB_SUBDIR "aarch64") -else() - message(WARNING "Unknown architecture, defaulting to x86_64") - set(LIB_SUBDIR "x86_64") -endif() - -# 查找库文件 -find_library(LINKER_HAND_LIB - NAMES linkerhand_cpp_sdk - PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib/${LIB_SUBDIR} - /usr/local/lib/linkerhand-cpp-sdk/${LIB_SUBDIR} - /usr/lib/linkerhand-cpp-sdk/${LIB_SUBDIR} - NO_DEFAULT_PATH -) - -# 查找头文件 -set(LINKER_HAND_INCLUDE_DIR - ${CMAKE_CURRENT_SOURCE_DIR}/include - /usr/local/include/linkerhand-cpp-sdk - /usr/include/linkerhand-cpp-sdk -) - -if(NOT LINKER_HAND_LIB) - message(FATAL_ERROR "linkerhand_cpp_sdk library not found!") -endif() - -# 包含头文件 -include_directories(${LINKER_HAND_INCLUDE_DIR}) - -# 创建可执行文件 -add_executable(my_project main.cpp) -target_link_libraries(my_project ${LINKER_HAND_LIB} pthread) -``` - -编译和运行: +### 3. 启动CAN设备 +打开终端执行 ```bash -mkdir build && cd build -cmake .. -make -./my_project +请手动启动CAN接口(需要sudo): + sudo ip link set canX up type can bitrate 1000000 + +或使用批量启动脚本: + for i in 0 1 2 3 4; do sudo ip link set can$i up type can bitrate 1000000; sudo ip link set can$i txqueuelen 1024; done ``` -## 📦 安装 +### 4. 运行示例程序 -### 方法一:使用安装脚本(推荐) +构建完成后,可执行文件位于 `build/bin/`: ```bash -./script.sh +# Linux +cd build/bin +./linker_hand_example # CLI 工具 +./test_o6_can_0 +./test_l10_can_0 +./test_o20_canfd_0 # 仅 Linux x86_64 + +# Windows +build\bin\linker_hand_example.exe +build\bin\test_l10_can_0.exe ``` -脚本提供以下功能: -- `[1]`: 构建 SDK -- `[2]`: 构建并安装 SDK -- `[3]`: 卸载 SDK -- `[6]`: 运行示例程序 +更多示例见 [`examples/`](examples/) 目录。 -### 方法二:手动安装 +### 5. 快速集成 -```bash -# 构建项目 -mkdir build && cd build -cmake .. -make +新建工程目录: -# 安装(需要 root 权限) -sudo make install +```bash +mkdir demo && cd demo +touch main.cpp CMakeLists.txt ``` -安装后,库文件将安装到: -- 头文件: `/usr/local/include/linkerhand-cpp-sdk/` -- 库文件: `/usr/local/lib/linkerhand-cpp-sdk/{arch}/` +两种集成方式的目录布局: -## 💡 使用示例 +``` +# 解压即用(未安装 SDK,把发布包整个拷到工程内) +demo/ +├── CMakeLists.txt +├── linkerhand-cpp-sdk/ # 即本发布包 +└── main.cpp + +# 已安装 SDK(系统级,find_package 即可找到) +demo/ +├── CMakeLists.txt +└── main.cpp +``` -### 基本控制 +`demo/main.cpp`: ```cpp -#include "LinkerHandApi.h" +#include +#include +#include #include -#include -#include -int main() { - // 创建 API 实例 - LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); - - // 设置速度 - std::vector speed = {200, 200, 200, 200, 200}; - hand.setSpeed(speed); - - // 设置扭矩 - std::vector torque = {255, 255, 255, 255, 255}; - hand.setTorque(torque); - - // 控制手指运动 - std::vector pose = {128, 128, 128, 128, 128, 128, 128, 128, 128, 128}; - hand.fingerMove(pose); +#include "LinkerHandApi.h" +#include "CommFactory.h" +int main() { + constexpr LINKER_HAND model = LINKER_HAND::O6; + constexpr HAND_TYPE side = HAND_TYPE::LEFT; + + auto hand = std::make_shared(model, side, COMM_TYPE::CAN); + auto bus = std::shared_ptr(Communication::CommFactory::createCanBus(side)); + + hand->setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t len) -> int32_t { + std::vector buf(data, data + len); + bus->send(buf, can_id); + return 0; + }); + + hand->setCanRxCallback([bus](uint32_t *id_out, uint8_t *data_out, uint8_t *len_out) -> int32_t { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) return -1; + *id_out = frame.can_id; + *len_out = frame.can_dlc; + std::memcpy(data_out, frame.data, frame.can_dlc); + return 0; + }); + + std::cout << "-----------------------------------" << std::endl; + std::cout << "version: " << hand->getVersion() << '\n'; + std::cout << "-----------------------------------" << std::endl; return 0; } ``` -### 获取传感器数据 - -```cpp -// 获取压力数据 -auto force_data = hand.getForce(); +`demo/CMakeLists.txt`: -// 获取关节状态 -auto joint_state = hand.getState(); +```cmake +cmake_minimum_required(VERSION 3.10) +project(my_app LANGUAGES CXX) -// 获取电机温度 -auto temperature = hand.getTemperature(); +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) -// 获取故障码 -auto fault_code = hand.getFaultCode(); -``` +# 解压即用:把发布包目录加进 CMake 搜索路径,无需安装。 +# 等价命令行:cmake -S . -B build -DCMAKE_PREFIX_PATH=${CMAKE_SOURCE_DIR}/linkerhand-cpp-sdk +list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/linkerhand-cpp-sdk") -### 使用弧度制控制(L10/L20/L21/L25) +find_package(linkerhand-cpp-sdk 2.0 CONFIG REQUIRED) -```cpp -// 使用弧度制控制关节 -std::vector pose_arc = {0.5, 0.3, 0.2, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; -hand.fingerMoveArc(pose_arc); +add_executable(demo main.cpp) +target_link_libraries(demo PRIVATE LinkerHand::linkerhand_cpp_sdk) -// 获取弧度制关节状态 -auto state_arc = hand.getStateArc(); +# 运行时定位 .so:把 SDK lib 目录写进 RPATH,免去 LD_LIBRARY_PATH。 +# linkerhand-cpp-sdk_LIBRARY_DIR 由 cmake/linkerhand-cpp-sdk-config.cmake 设置。 +set_target_properties(demo PROPERTIES + BUILD_RPATH "${linkerhand-cpp-sdk_LIBRARY_DIR}" + INSTALL_RPATH "${linkerhand-cpp-sdk_LIBRARY_DIR}" +) ``` -更多示例请参考 `examples/` 目录。详细说明请查看 [示例代码文档](examples/README.md)。 - -## 📚 API 文档 - -详细的 API 文档请参考:[API 参考文档](docs/API-Reference.md) - -文档包含: -- 完整的 API 函数说明 -- 参数和返回值详解 -- 使用示例和注意事项 -- 版本兼容性说明 - -### 命名规范 - -项目已进行命名规范改进,详细信息请参考:[命名规范改进文档](docs/NAMING_IMPROVEMENTS.md) - -主要改进包括: -- 统一命名空间结构(所有型号实现类迁移到 `linkerhand::hand` 命名空间) -- 类名改进(不同型号使用不同类名,如 `L10Hand`, `L20Hand` 等) -- 参数命名修正(`handJoint` → `handModel`) -- 完全向后兼容(旧命名仍可使用) - -## 🧪 测试 - -### 运行测试 +编译运行: ```bash -# 构建并运行测试 mkdir build && cd build -cmake .. -DBUILD_TESTING=ON -make -ctest --output-on-failure +cmake .. +cmake --build . -j +./demo ``` -### 测试文档 - -- **测试指南**: [测试文档](docs/TESTING.md)(待创建) - 详细的测试框架安装、编写和运行指南 -- **测试说明**: [测试目录 README](tests/README.md) - 测试结构和快速参考 -- **CI/CD 文档**: [CI/CD 文档](docs/CI-CD.md) - 持续集成和持续部署配置说明 - -测试文档包含: -- 测试框架安装和配置(Google Test) -- 如何编写和运行测试 -- 测试覆盖率配置 -- 测试最佳实践 -- CI/CD 集成指南 +## 📚 API 文档 -### 当前测试覆盖 +完整的 API 参考见 [`docs/API-Reference.md`](docs/API-Reference.md),内容涵盖: -项目已包含以下单元测试: -- ✅ `test_Common.cpp` - Common.h 枚举和类型测试 -- ✅ `test_RangeToArc.cpp` - 范围到弧度转换函数测试 -- ✅ `test_IHand_Utils.cpp` - IHand 工具函数测试 -- ✅ `test_CanFrame.cpp` - CAN 帧结构测试 +- 完整的 API 函数说明 +- 参数与返回值详解 +- 使用示例与注意事项 +- 版本兼容性说明 ### 主要 API 接口 -#### 控制接口 -- `fingerMove()` - 设置关节位置(0-255) -- `fingerMoveArc()` - 设置关节位置(弧度制) -- `setSpeed()` - 设置运动速度 -- `setTorque()` - 设置扭矩限制 +**控制接口** +- `fingerMove()` — 设置关节位置(原始值 0–255) +- `fingerMoveArc()` — 设置关节位置(弧度) +- `setSpeed()` — 设置运动速度 +- `setTorque()` — 设置扭矩限制 -#### 状态查询接口 -- `getState()` - 获取关节状态 -- `getStateArc()` - 获取关节状态(弧度制) -- `getSpeed()` - 获取当前速度设置 -- `getTorque()` - 获取当前扭矩设置 +**状态查询** +- `getState()` / `getStateArc()` — 获取关节状态(原始值 / 弧度) +- `getSpeed()` / `getTorque()` — 获取当前速度 / 扭矩设置 -#### 传感器接口 -- `getForce()` - 获取压力数据(法向、切向、方向、接近感应) -- `getTemperature()` - 获取电机温度 -- `getFaultCode()` - 获取电机故障码 -- `getCurrent()` - 获取电机电流 +**传感器** +- `getForce()` — 压力数据(法向 / 切向 / 方向 / 接近感应) +- `getTemperature()` — 电机温度 +- `getFaultCode()` — 电机故障码 ## 🔌 通信协议 -SDK 支持以下通信协议: - -- **CAN** (`COMM_CAN_0`, `COMM_CAN_1`) - CAN 总线通信 -- **ModBus** (`COMM_MODBUS`) - ModBus 通信协议 -- **EtherCAT** (`COMM_ETHERCAT`) - EtherCAT 工业以太网通信 - -默认使用 `COMM_CAN_0`。 +| 协议 | 枚举值 | 适用范围 | +|------|--------|---------| +| CAN | `COMM_TYPE::CAN` | 全系列 | +| CAN-FD | `COMM_TYPE::CAN`(搭配 `CanFD` 实现) | O20(仅 Linux x86_64) | +| Modbus | `COMM_TYPE::MODBUS` | L7 / L10 / O6 | -```cpp -// 使用 CAN0 通信(默认) -LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); -// 使用 CAN1 通信 -LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT, COMM_CAN_1); +通信层通过 `Communication::CommFactory` 构造(旧名 `CanBusFactory` 保留为兼容别名),调用方通过 `LinkerHandApi::setCanTxCallback` / `setCanRxCallback`(或 Modbus 等价回调)注入收发逻辑,SDK 本身不持有任何 socket。 -// 使用 ModBus 通信 -LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT, COMM_MODBUS); +## 🤖 支持的型号 -// 使用 EtherCAT 通信 -LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT, COMM_ETHERCAT); -``` +| 型号 | 通信方式 | 备注 | +|------|----------|------| +| LinkerHand G20 | CAN | G20 series robotic hand | +| LinkerHand L6 | CAN | L6 series robotic hand | +| LinkerHand L7 | CAN / Modbus | L7 series robotic hand | +| LinkerHand L10 | CAN / Modbus | L10 series robotic hand | +| LinkerHand L20 | CAN | L20 series robotic hand | +| LinkerHand L21 | CAN | L21 series robotic hand | +| LinkerHand L25 | CAN | L25 series robotic hand | +| LinkerHand O6 | CAN / Modbus | O6 series robotic hand | +| LinkerHand O20 | CAN-FD | O20 series robotic hand(仅 Linux x86_64) | ## 📁 项目结构 ``` linkerhand-cpp-sdk/ -├── include/ # 头文件 -│ ├── LinkerHandApi.h # 主 API 接口 -│ ├── Common.h # 通用定义 -│ └── ... -├── lib/ # 预编译库文件 -│ ├── x86_64/ # x86_64 架构库 -│ └── aarch64/ # aarch64 架构库 -├── examples/ # 示例代码 -│ ├── toolset_example.cpp -│ └── action_group_show_l10.cpp -├── docs/ # 文档 -│ ├── API-Reference.md # API 参考文档 -│ ├── TROUBLESHOOTING.md # 故障排查指南 -│ └── FAQ.md # 常见问题解答 -├── src/ # 源代码 -├── third_party/ # 第三方依赖 -├── CMakeLists.txt # CMake 配置 -├── script.sh # 安装脚本 -└── README.md # 本文档 -``` - -## 🔨 构建项目 - -### 使用 CMake - -```bash -mkdir build -cd build -cmake .. -make +├── include/ # 公共头文件 +│ ├── api/ +│ │ └── LinkerHandApi.h # 唯一公共入口 +│ ├── core/ +│ │ ├── Common.h # 枚举:LINKER_HAND / HAND_TYPE / COMM_TYPE +│ │ ├── ErrorCode.h +│ │ └── LinkerHandExport.h # 跨平台符号导出宏 +│ └── communication/ +│ ├── CommFactory.h # 通信层工厂(推荐) +│ ├── CanBusFactory.h # 兼容别名(旧名,将逐步废弃) +│ ├── CommunicationCallbacks.h # 回调签名 +│ ├── CanBus.h / CanFD.h / Modbus.h / PCANBus.h +│ ├── CanFrame.h +│ └── ICanBus.h / ICanFD.h / ICommunication.h / IModbus.h +├── lib/ +│ ├── linux/ +│ │ ├── x86_64/ # Linux x86_64 共享库(.so) +│ │ └── arm64/ # Linux aarch64 共享库(.so) +│ └── win64/ +│ └── mingw/ # Windows MinGW(.dll / .dll.a) +├── examples/ # 示例源码(CAN / CAN-FD / Modbus) +├── docs/ # API-Reference / FAQ / TROUBLESHOOTING +├── cmake/ # find_package 用的 *-config.cmake +├── third_party/ +│ ├── libcanbus/ # CAN / CAN-FD 驱动 +│ └── PCAN_Basic/ # Windows PCAN 驱动 +├── build.sh # 构建脚本(Linux) +├── build.bat # 构建脚本(Windows) +└── CMakeLists.txt # 顶层 CMake:聚合 examples + 安装规则 ``` -### 运行示例 - -```bash -cd build -./toolset_example -./action_group_show_l10 -``` +> 发布包以预编译共享库为核心,`include/` 与 `lib/` 是对外契约;`examples/` 与 `cmake/` 是配套消费样例与集成胶水。 + +## 📜 示例程序列表 + +| 示例文件 | 说明 | +|----------|------| +| `linker_hand_example.cpp` | 多型号 / 多协议巡检 | +| `test_g20_can_0.cpp` | G20 CAN 基础示例 | +| `test_g20_can_1.cpp` | G20 CAN 进阶示例(直连具体类) | +| `test_l7_can_0.cpp` | L7 CAN 基础示例 | +| `test_l7_can_1.cpp` | L7 CAN 进阶示例 | +| `test_l7_modbus_0.cpp` | L7 Modbus 基础示例 | +| `test_l7_modbus_1.cpp` | L7 Modbus 进阶示例 | +| `test_l10_can_0.cpp` | L10 CAN 基础示例 | +| `test_l10_can_1.cpp` | L10 CAN 进阶示例 | +| `test_l10_modbus.cpp` | L10 Modbus 示例 | +| `test_l20_can_0.cpp` | L20 CAN 示例 | +| `test_l21_can_0.cpp` | L21 CAN 示例 | +| `test_o6_can_0.cpp` | O6 CAN 基础示例 | +| `test_o6_can_1.cpp` | O6 CAN 进阶示例 | +| `test_o6_can_3.cpp` | O6 CAN 高级示例 | +| `test_o6_modbus_0.cpp` | O6 Modbus 基础示例 | +| `test_o6_modbus_1.cpp` | O6 Modbus 进阶示例 | +| `test_o6_modbus_2.cpp` | O6 Modbus 高级示例 | +| `test_o20_canfd_0.cpp` | O20 CAN-FD 基础示例(仅 Linux x86_64) | +| `test_o20_canfd_1.cpp` | O20 CAN-FD 进阶示例(仅 Linux x86_64) | +| `L10/action_group_show.cpp` | L10 动作组演示 | ## 📖 关节映射表 -不同型号的关节映射关系: - -### L6/O6 +- L6 / O6 ``` ["大拇指弯曲", "大拇指横摆", "食指弯曲", "中指弯曲", "无名指弯曲", "小拇指弯曲"] ``` -### L7 +- L7 ``` ["大拇指弯曲", "大拇指横摆", "食指弯曲", "中指弯曲", "无名指弯曲", "小拇指弯曲", "拇指旋转"] ``` -### L10 +- L10 ``` -["拇指根部", "拇指侧摆", "食指根部", "中指根部", "无名指根部", "小指根部", +["拇指根部", "拇指侧摆", "食指根部", "中指根部", "无名指根部", "小指根部", "食指侧摆", "无名指侧摆", "小指侧摆", "拇指旋转"] ``` -### L20 +- L20 ``` ["拇指根部", "食指根部", "中指根部", "无名指根部", "小指根部", "拇指侧摆", "食指侧摆", "中指侧摆", "无名指侧摆", "小指侧摆", @@ -406,54 +362,44 @@ cd build "拇指尖部", "食指末端", "中指末端", "无名指末端", "小指末端"] ``` -### L21/L25 -详细映射请参考 [API 文档](docs/API-Reference.md)。 +- L21 / L25 +详细映射见 [`docs/API-Reference.md`](docs/API-Reference.md)。 ## 🔧 故障排查 -如果遇到问题,请参考以下文档: +- [故障排查指南](docs/TROUBLESHOOTING.md) — 编译 / 运行时 / 通信 / API 使用 / 性能 +- [常见问题解答](docs/FAQ.md) — 安装、使用、API、兼容性、性能 -- **[故障排查指南](docs/TROUBLESHOOTING.md)** - 常见问题的排查和解决方案 - - 编译问题 - - 运行时问题 - - 通信问题 - - API 使用问题 - - 性能问题 - -- **[常见问题解答](docs/FAQ.md)** - 常见问题的快速解答 - - 安装相关问题 - - 使用相关问题 - - API 相关问题 - - 兼容性问题 - - 性能相关问题 - -如果文档无法解决您的问题,请: -1. 查看 [GitHub Issues](https://github.com/linker-bot/linkerhand-cpp-sdk/issues) 查看是否有类似问题 -2. 提交新的 Issue,并提供详细的错误信息和复现步骤 -3. 联系技术支持:[https://linkerbot.cn/aboutUs](https://linkerbot.cn/aboutUs) +如文档无法解决: +1. 在 [GitHub Issues](https://github.com/linker-bot/linkerhand-cpp-sdk/issues) 搜索同类问题 +2. 提交新 Issue,附错误信息与复现步骤 +3. 联系技术支持: ## ❓ 常见问题 -快速查找常见问题的答案,请参考 [常见问题解答 (FAQ)](docs/FAQ.md)。 +快速答案见 [FAQ](docs/FAQ.md),覆盖: -常见问题包括: -- 如何安装和配置 SDK? -- 如何选择通信接口? -- 不同型号的关节数量是多少? -- 如何提高性能? -- 如何获取技术支持? +- 如何安装与配置 SDK +- 如何选择通信接口 +- 各型号关节数量 +- 如何提升性能 +- 如何获取技术支持 ## 🤝 贡献 -我们欢迎社区贡献!请参考以下步骤: +欢迎社区贡献: 1. Fork 本仓库 -2. 创建特性分支 (`git checkout -b feature/AmazingFeature`) -3. 提交更改 (`git commit -m 'Add some AmazingFeature'`) -4. 推送到分支 (`git push origin feature/AmazingFeature`) +2. 创建特性分支:`git checkout -b feature/AmazingFeature` +3. 提交更改:`git commit -m 'feat: 新增 AmazingFeature'` +4. 推送:`git push origin feature/AmazingFeature` 5. 开启 Pull Request -更多贡献指南请参考 [CONTRIBUTING.md](CONTRIBUTING.md)(待创建)。 +更多贡献指南见 `CONTRIBUTING.md`(待创建)。 + +## 📝 更新日志 + +详细版本记录见 `CHANGELOG.md`(待创建)。 ## 📄 许可证 @@ -463,14 +409,10 @@ Copyright (c) 2026 灵心巧手(北京)科技有限公司 ## 📞 联系我们 -- **官方网站**: [https://linkerbot.cn](https://linkerbot.cn) -- **关于我们**: [https://linkerbot.cn/aboutUs](https://linkerbot.cn/aboutUs) -- **GitHub**: [https://github.com/linker-bot/linkerhand-cpp-sdk](https://github.com/linker-bot/linkerhand-cpp-sdk) - -## 📝 更新日志 - -详细的版本更新记录请参考 [CHANGELOG.md](CHANGELOG.md)(待创建)。 +- 官方网站: +- 关于我们: +- GitHub: --- -**注意**: 使用前请确保设备已正确连接并配置好通信接口。 +**注意**:使用前请确保设备已正确连接并配置好通信接口。 diff --git a/build.bat b/build.bat new file mode 100755 index 0000000..f5f56bb --- /dev/null +++ b/build.bat @@ -0,0 +1,190 @@ +@echo off +setlocal enabledelayedexpansion + +set BUILD_ONLY=0 +set INSTALL=0 +set CLEAN=0 +set SKIP_TESTS=0 +set USE_LIB=0 +set INSTALL_PREFIX=C:\Program Files\LinkerHandSDK +set COMPILER=mingw + +if "%~1"=="-h" goto help +if "%~1"=="--help" goto help +if "%~1"=="-b" set BUILD_ONLY=1 +if "%~1"=="-i" set INSTALL=1 +if "%~1"=="-c" set CLEAN=1 +if "%~1"=="--skip-tests" set SKIP_TESTS=1 +if "%~1"=="--prefix" set INSTALL_PREFIX=%~2 +if "%~1"=="--use-lib" set USE_LIB=1 +if "%~1"=="--compiler" ( + set COMPILER=%~2 + if /i not "!COMPILER!"=="mingw" if /i not "!COMPILER!"=="msvc" ( + echo [ERROR] Invalid compiler: !COMPILER! + echo Valid options: mingw, msvc + exit /b 1 + ) +) + +if "%CLEAN%"=="1" ( + echo [INFO] Cleaning build directory... + if exist build rmdir /s /q build + if exist build_msvc rmdir /s /q build_msvc + if exist build_msvc_bin rmdir /s /q build_msvc_bin + echo [INFO] Done + exit /b 0 +) + +echo [INFO] Checking build tools... +where cmake >nul 2>&1 +if errorlevel 1 ( + echo [ERROR] CMake not found + exit /b 1 +) + +if /i "%COMPILER%"=="mingw" ( + echo [INFO] Using MinGW compiler + where mingw32-make >nul 2>&1 + if errorlevel 1 ( + echo [ERROR] MinGW not found + exit /b 1 + ) + set BUILD_DIR=build + set CMAKE_GENERATOR="MinGW Makefiles" + set CMAKE_MAKE_PROGRAM=mingw32-make + if "%USE_LIB%"=="1" ( + echo [WARNING] --use-lib option is not supported for MinGW, using source build mode + set USE_LIB=0 + ) +) else if /i "%COMPILER%"=="msvc" ( + echo [INFO] Using MSVC compiler + set BUILD_DIR=build_msvc + if "%USE_LIB%"=="1" set BUILD_DIR=build_msvc_bin + set CMAKE_GENERATOR="NMake Makefiles" + set CMAKE_MAKE_PROGRAM=nmake + + set "VCVARS_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat" + if not exist "!VCVARS_PATH!" ( + set "VCVARS_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" + ) + if not exist "!VCVARS_PATH!" ( + set "VCVARS_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat" + ) + if not exist "!VCVARS_PATH!" ( + set "VCVARS_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" + ) + if not exist "!VCVARS_PATH!" ( + set "VCVARS_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat" + ) + if not exist "!VCVARS_PATH!" ( + set "VCVARS_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + ) + + if not exist "!VCVARS_PATH!" ( + echo [ERROR] MSVC not found. Please install Visual Studio. + exit /b 1 + ) + + echo [INFO] Setting up MSVC environment... + call "!VCVARS_PATH!" + if errorlevel 1 ( + echo [ERROR] Failed to setup MSVC environment + exit /b 1 + ) +) + +if "%USE_LIB%"=="1" ( + echo [INFO] Using pre-built library mode + if /i "%COMPILER%"=="msvc" ( + set LIB_PATH=lib\win64\msvc\linkerhand_cpp_sdk.dll + ) else ( + set LIB_PATH=lib\win64\mingw\linkerhand_cpp_sdk.dll + ) + if not exist "!LIB_PATH!" ( + echo [ERROR] Pre-built library not found: !LIB_PATH! + echo [ERROR] Please build the library first using: build.bat --compiler !COMPILER! + exit /b 1 + ) +) + +echo [INFO] Creating build directory... +if exist "!BUILD_DIR!" rmdir /s /q "!BUILD_DIR!" +mkdir "!BUILD_DIR!" +cd "!BUILD_DIR!" + +echo [INFO] Configuring CMake... +set CMAKE_ARGS=-G !CMAKE_GENERATOR! -DCMAKE_BUILD_TYPE=Release +if defined CMAKE_MAKE_PROGRAM set CMAKE_ARGS=!CMAKE_ARGS! -DCMAKE_MAKE_PROGRAM=!CMAKE_MAKE_PROGRAM! +if "%SKIP_TESTS%"=="1" set CMAKE_ARGS=!CMAKE_ARGS! -DBUILD_TESTS=OFF +if "%USE_LIB%"=="1" ( + set CMAKE_ARGS=!CMAKE_ARGS! -DBUILD_SO=OFF +) else ( + set CMAKE_ARGS=!CMAKE_ARGS! -DBUILD_SO=ON +) + +cmake !CMAKE_ARGS! .. +if errorlevel 1 ( + echo [ERROR] CMake failed + cd .. + exit /b 1 +) + +echo [INFO] Building... +if /i "%COMPILER%"=="mingw" ( + mingw32-make +) else if /i "%COMPILER%"=="msvc" ( + nmake +) +if errorlevel 1 ( + echo [ERROR] Build failed + cd .. + exit /b 1 +) + +echo [INFO] Build successful! +echo [INFO] Executables: %CD%\bin\ + +if "%BUILD_ONLY%"=="1" ( + echo Usage: Run programs from bin\ directory + cd .. + exit /b 0 +) + +if "%INSTALL%"=="1" ( + echo [INFO] Installing to %INSTALL_PREFIX%... + net session >nul 2>&1 + if errorlevel 1 ( + echo [ERROR] Need admin rights + cd .. + exit /b 1 + ) + if not exist "%INSTALL_PREFIX%" mkdir "%INSTALL_PREFIX%" + if exist "%INSTALL_PREFIX%\include" rmdir /s /q "%INSTALL_PREFIX%\include" + if exist "%INSTALL_PREFIX%\lib" rmdir /s /q "%INSTALL_PREFIX%\lib" + xcopy /E /I /Y ..\include "%INSTALL_PREFIX%\include" + xcopy /E /I /Y ..\lib "%INSTALL_PREFIX%\lib" + setx LINKERHAND_SDK_ROOT "%INSTALL_PREFIX%" /M >nul 2>&1 + setx PATH "%PATH%;%INSTALL_PREFIX%\lib\win64" /M >nul 2>&1 + echo [INFO] Installation complete! + echo Restart terminal to use environment variables + cd .. + exit /b 0 +) + +echo Usage: Run programs from bin\ directory +echo Use 'build.bat -i' to install to system +cd .. +exit /b 0 + +:help +echo Usage: build.bat [options] +echo Options: +echo -h, --help Show help +echo -b Build only +echo -i Build and install +echo -c Clean build +echo --skip-tests Skip tests +echo --prefix PATH Install directory +echo --compiler TYPE Compiler type: mingw (default) or msvc +echo --use-lib Use pre-built library (MSVC only) +exit /b 0 diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..eb4ea04 --- /dev/null +++ b/build.sh @@ -0,0 +1,308 @@ +#!/bin/bash + +# LinkerHand C++ SDK 构建和安装脚本 +# 支持 Linux 和 macOS + +set -e + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# 打印带颜色的消息 +print_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +print_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# 检查命令是否存在 +check_command() { + if ! command -v $1 &> /dev/null; then + print_error "$1 未安装,请先安装 $1" + exit 1 + fi +} + +# 删除 $INSTALL_PREFIX 下所有已安装产物(含历史版本的目录式布局)。 +# install 前的清理与 -u/--uninstall 共用此函数,确保"装什么"与"卸什么"始终一致: +# - lib/linkerhand-cpp-sdk/ 当前布局:lib/ + third_party/(旧版还有 x86_64/ 等架构子目录) +# - lib/cmake/LinkerHand 当前 cmake 配置包;LinkerHandCPPSDK 为旧包名 +# - lib/{lib,}linkerhand_cpp_sdk.* 标准库目录下的软链(旧版或为实体文件) +# - include/linkerhand-cpp-sdk 公共头 +# 参数 $1 为 sudo 前缀(无权限时为 "sudo",root 下为空)。 +purge_install_artifacts() { + local sudo_cmd="$1" + $sudo_cmd rm -rf $INSTALL_PREFIX/lib/liblinkerhand_cpp_sdk.* \ + $INSTALL_PREFIX/lib/linkerhand_cpp_sdk.* \ + $INSTALL_PREFIX/lib/linkerhand-cpp-sdk \ + $INSTALL_PREFIX/lib/cmake/linkerhand-cpp-sdk \ + $INSTALL_PREFIX/lib/cmake/LinkerHand \ + $INSTALL_PREFIX/lib/cmake/LinkerHandCPPSDK \ + $INSTALL_PREFIX/include/linkerhand-cpp-sdk +} + +# 显示帮助信息 +show_help() { + cat << EOF +用法: $0 [选项] + +选项: + -h, --help 显示此帮助信息 + -b, --build 仅构建项目 + -i, --install 构建并安装到系统 + -u, --uninstall 从系统卸载(删除所有已安装产物) + -c, --clean 清理构建目录 + -t, --test 构建并运行测试 + --prefix PATH 指定安装前缀 (默认: /usr/local) + --skip-tests 跳过测试程序编译 + +示例: + $0 构建项目 + $0 -i 构建并安装到系统 + $0 -u 从系统卸载 + $0 -c 清理构建目录 + $0 --prefix /opt 构建并安装到 /opt + $0 -u --prefix /opt 从 /opt 卸载 + +EOF +} + +# 默认参数 +BUILD_ONLY=false +INSTALL=false +UNINSTALL=false +CLEAN=false +RUN_TESTS=false +SKIP_TESTS=false +INSTALL_PREFIX="/usr/local" + +# 解析命令行参数 +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + -b|--build) + BUILD_ONLY=true + shift + ;; + -i|--install) + INSTALL=true + shift + ;; + -u|--uninstall) + UNINSTALL=true + shift + ;; + -c|--clean) + CLEAN=true + shift + ;; + -t|--test) + RUN_TESTS=true + shift + ;; + --prefix) + INSTALL_PREFIX="$2" + shift 2 + ;; + --skip-tests) + SKIP_TESTS=true + shift + ;; + *) + print_error "未知选项: $1" + show_help + exit 1 + ;; + esac +done + +# 检测系统信息 +OS=$(uname -s) +ARCH=$(uname -m) +print_info "检测到操作系统: $OS" +print_info "检测到系统架构: $ARCH" + +# 验证系统支持 +if [[ "$OS" != "Linux" && "$OS" != "Darwin" ]]; then + print_error "不支持的操作系统: $OS" + print_error "此脚本仅支持 Linux 和 macOS" + exit 1 +fi + +# 清理构建目录 +if [ "$CLEAN" = true ]; then + print_info "清理构建目录..." + if [ -d "build" ]; then + rm -rf build + print_info "构建目录已清理" + else + print_warn "构建目录不存在" + fi + exit 0 +fi + +# 卸载:删除 $INSTALL_PREFIX 下的全部已安装产物,无需先构建 +if [ "$UNINSTALL" = true ]; then + print_info "从 $INSTALL_PREFIX 卸载 LinkerHand C++ SDK..." + + if [ "$EUID" -ne 0 ]; then + print_warn "需要 sudo 权限来卸载系统目录" + SUDO="sudo" + else + SUDO="" + fi + + purge_install_artifacts "$SUDO" + + if [ "$OS" = "Linux" ]; then + print_info "更新动态链接库缓存..." + $SUDO ldconfig + fi + + # 自检:确认没有残留 + LEFTOVER=$(find "$INSTALL_PREFIX/lib" "$INSTALL_PREFIX/include" \ + -iname '*linkerhand*' 2>/dev/null | sort) + if [ -n "$LEFTOVER" ]; then + print_warn "仍检测到以下残留(可能来自其他安装方式,请手动确认):" + echo "$LEFTOVER" | sed 's/^/ /' + else + print_info "卸载完成,未检测到残留。" + fi + exit 0 +fi + +# 检查必要的工具 +print_info "检查必要的构建工具..." +check_command cmake +check_command make + +# 创建构建目录 +print_info "创建构建目录..." +mkdir -p build +cd build + +# 配置 CMake +print_info "配置 CMake..." +CMAKE_ARGS=("-DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX") +if [ "$SKIP_TESTS" = true ]; then + CMAKE_ARGS+=("-DBUILD_TESTS=OFF") +fi +cmake .. "${CMAKE_ARGS[@]}" + +# 构建 +print_info "开始构建项目..." +make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4) + +# 检查构建结果 +if [ $? -eq 0 ]; then + print_info "构建成功!" +else + print_error "构建失败!" + exit 1 +fi + +# 运行测试 +if [ "$RUN_TESTS" = true ]; then + print_info "运行测试..." + if [ -f "bin/main" ]; then + ./bin/main + else + print_warn "未找到测试程序" + fi +fi + +# 如果只构建,则退出 +if [ "$BUILD_ONLY" = true ]; then + print_info "构建完成!可执行文件位于: $(pwd)/bin/" + exit 0 +fi + +# 安装 +if [ "$INSTALL" = true ]; then + print_info "开始安装到 $INSTALL_PREFIX..." + + # 检查是否有 sudo 权限 + if [ "$EUID" -ne 0 ]; then + print_warn "需要 sudo 权限来安装到系统" + SUDO="sudo" + else + SUDO="" + fi + + # 清理旧的安装。必须连历史版本的目录式布局一起删,否则会出现新旧 .so 叠层: + # - 旧版把 .so 装在 lib/linkerhand-cpp-sdk//(如 x86_64/),符号是无命名空间的旧 ABI + # - 旧版 cmake 包名曾是 LinkerHandCPPSDK + # 残留会让示例的 find_library 兜底分支(搜索顺序 .../linkerhand-cpp-sdk/ 在 /usr/local/lib 之前) + # 链到旧 .so → undefined reference。整目录删掉,由本次 install 重新铺。 + print_info "清理旧的安装..." + purge_install_artifacts "$SUDO" + + # 通过 CMake 的 install 规则安装。对外公共头白名单、库文件、third_party 运行时 + # 依赖、cmake config target 等都由 linkerhand/CMakeLists.txt 统一控制, + # 不要在这里再手动 cp 头文件——会绕过白名单把全部内部头释放出去。 + print_info "执行 cmake --install (受白名单约束)..." + $SUDO cmake --install . --prefix "$INSTALL_PREFIX" + + # 在标准库目录建符号链接,方便 -llinkerhand_cpp_sdk 直接找到 + if [ "$OS" = "Linux" ]; then + SDK_LIB_DIR="$INSTALL_PREFIX/lib/linkerhand-cpp-sdk/lib" + if [ -d "$SDK_LIB_DIR" ]; then + for lib_file in $SDK_LIB_DIR/*.so*; do + [ -f "$lib_file" ] || continue + lib_name=$(basename $lib_file) + $SUDO ln -sf "$SDK_LIB_DIR/$lib_name" "$INSTALL_PREFIX/lib/$lib_name" + done + fi + print_info "更新动态链接库缓存..." + $SUDO ldconfig + elif [ "$OS" = "Darwin" ]; then + SDK_LIB_DIR="$INSTALL_PREFIX/lib/linkerhand-cpp-sdk/lib" + if [ -d "$SDK_LIB_DIR" ]; then + for lib_file in $SDK_LIB_DIR/*.dylib*; do + [ -f "$lib_file" ] || continue + lib_name=$(basename $lib_file) + $SUDO ln -sf "$SDK_LIB_DIR/$lib_name" "$INSTALL_PREFIX/lib/$lib_name" + done + fi + fi + + # 列出最终对外暴露的公共头,便于打包前肉眼确认白名单未被破坏 + # 头按 api/core/communication 子目录发布,故递归列出(去掉 -maxdepth 1) + print_info "对外公共头清单:" + find "$INSTALL_PREFIX/include/linkerhand-cpp-sdk" -name "*.h" | sort | sed "s|$INSTALL_PREFIX/include/linkerhand-cpp-sdk/| |" + + print_info "安装完成!" + echo "" + echo "使用示例(推荐 find_package):" + echo " find_package(linkerhand-cpp-sdk CONFIG REQUIRED)" + echo " target_link_libraries( PRIVATE LinkerHand::linkerhand_cpp_sdk)" + echo " 参考工程: linkerhand/examples/standalone/" + echo "" + INC="$INSTALL_PREFIX/include/linkerhand-cpp-sdk" + echo "或手动指定(头按子目录发布):" + echo " g++ -std=c++17 -o test test.cpp -llinkerhand_cpp_sdk \\" + echo " -I$INC -I$INC/api -I$INC/core -I$INC/communication" + if [ "$OS" = "Linux" ]; then + echo " 运行: LD_LIBRARY_PATH=$INSTALL_PREFIX/lib ./test" + else + echo " 运行: DYLD_LIBRARY_PATH=$INSTALL_PREFIX/lib ./test" + fi + exit 0 +fi + +# 默认只构建 +print_info "构建完成!可执行文件位于: $(pwd)/bin/" +print_info "使用 '$0 -i' 来安装到系统" +print_info "使用 '$0 -h' 查看更多选项" \ No newline at end of file diff --git a/cmake/LinkerHandCPPSDKConfig.cmake.in b/cmake/LinkerHandCPPSDKConfig.cmake.in deleted file mode 100644 index 684b172..0000000 --- a/cmake/LinkerHandCPPSDKConfig.cmake.in +++ /dev/null @@ -1,45 +0,0 @@ -@PACKAGE_INIT@ - -# 确定系统架构 -if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") - set(LIB_SUBDIR "x86_64") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64") - set(LIB_SUBDIR "aarch64") -else() - set(LIB_SUBDIR "x86_64") -endif() - -# 设置包含目录和库目录(相对于安装前缀) -set(LinkerHandCPPSDK_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../@PACKAGE_INCLUDE_INSTALL_DIR@") -set(LinkerHandCPPSDK_LIB_DIR "${CMAKE_CURRENT_LIST_DIR}/../../@PACKAGE_LIB_INSTALL_DIR@") - -# 也支持从构建目录查找(用于开发时) -list(APPEND LinkerHandCPPSDK_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../include/linkerhand-cpp-sdk") -list(APPEND LinkerHandCPPSDK_LIB_DIR "${CMAKE_CURRENT_LIST_DIR}/../../lib/linkerhand-cpp-sdk/${LIB_SUBDIR}") - -# 查找库文件 -find_library(LinkerHandCPPSDK_LIBRARY - NAMES linkerhand_cpp_sdk - PATHS ${LinkerHandCPPSDK_LIB_DIR} - NO_DEFAULT_PATH -) - -# 检查库文件是否存在 -if(NOT LinkerHandCPPSDK_LIBRARY) - message(FATAL_ERROR "LinkerHandCPPSDK library not found in ${LinkerHandCPPSDK_LIB_DIR}") -endif() - -# 设置变量供外部使用 -set(LinkerHandCPPSDK_FOUND TRUE) -set(LinkerHandCPPSDK_VERSION @PROJECT_VERSION@) - -# 创建导入目标 -if(NOT TARGET LinkerHandCPPSDK::LinkerHandCPPSDK) - add_library(LinkerHandCPPSDK::LinkerHandCPPSDK SHARED IMPORTED) - set_target_properties(LinkerHandCPPSDK::LinkerHandCPPSDK PROPERTIES - IMPORTED_LOCATION "${LinkerHandCPPSDK_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${LinkerHandCPPSDK_INCLUDE_DIR}" - ) -endif() - -check_required_components(LinkerHandCPPSDK) diff --git a/cmake/linkerhand-cpp-sdk-config-version.cmake b/cmake/linkerhand-cpp-sdk-config-version.cmake new file mode 100644 index 0000000..f8e0817 --- /dev/null +++ b/cmake/linkerhand-cpp-sdk-config-version.cmake @@ -0,0 +1,26 @@ +# linkerhand-cpp-sdk-config-version.cmake +# CMake find_package 版本兼容性检查。语义:同主版本号兼容(SOVERSION=2)。 + +set(PACKAGE_VERSION "2.0.0") + +if(PACKAGE_FIND_VERSION_RANGE) + # 区间形式 find_package(... 2.0...3.0):交给 CMake 自己判断 + if(PACKAGE_FIND_VERSION_MIN_MAJOR EQUAL 2) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() +elseif(PACKAGE_FIND_VERSION) + if(PACKAGE_FIND_VERSION_MAJOR EQUAL 2 AND + NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() +else() + # 未指定版本:默认兼容 + set(PACKAGE_VERSION_COMPATIBLE TRUE) +endif() diff --git a/cmake/linkerhand-cpp-sdk-config.cmake b/cmake/linkerhand-cpp-sdk-config.cmake new file mode 100644 index 0000000..792cecf --- /dev/null +++ b/cmake/linkerhand-cpp-sdk-config.cmake @@ -0,0 +1,158 @@ +# linkerhand-cpp-sdk-config.cmake +# 同时支持两种使用方式: +# +# A) 安装后 find_package — 配置文件位于 /lib/cmake/linkerhand-cpp-sdk/ +# 头:/include/linkerhand-cpp-sdk/{api,core,communication}/ +# 库:/lib/linkerhand-cpp-sdk/lib/<预编译库> +# +# B) 解压即用 find_package — 配置文件位于 /cmake/ +# 头:/include/{api,core,communication}/ +# 库:/lib///<预编译库> +# +# 下游通用写法: +# find_package(linkerhand-cpp-sdk CONFIG REQUIRED) +# target_link_libraries( PRIVATE LinkerHand::linkerhand_cpp_sdk) +# +# 解压即用时,让 CMake 找到本文件的方式(任选其一): +# list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/linkerhand-cpp-sdk") +# # 或命令行:cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/linkerhand-cpp-sdk +# # 或命令行:cmake -S . -B build -Dlinkerhand-cpp-sdk_DIR=/path/to/linkerhand-cpp-sdk/cmake + +get_filename_component(_lh_self_dir "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) + +# --- 布局识别 --- +# 解压布局:/cmake/,向上 1 级 = ,含 include/api/... +get_filename_component(_lh_extract_root "${_lh_self_dir}/.." ABSOLUTE) +# 安装布局:/lib/cmake/linkerhand-cpp-sdk/,向上 3 级 = +get_filename_component(_lh_install_prefix "${_lh_self_dir}/../../.." ABSOLUTE) + +set(_lh_inc "") +set(_lh_lib_search "") +set(_lh_thirdparty_root "") + +if(EXISTS "${_lh_extract_root}/include/api/LinkerHandApi.h") + # 解压即用:lib 按平台/架构子目录布局 + set(_lh_inc "${_lh_extract_root}/include") + if(EXISTS "${_lh_extract_root}/third_party") + set(_lh_thirdparty_root "${_lh_extract_root}/third_party") + endif() + if(WIN32) + if(MSVC OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")) + list(APPEND _lh_lib_search "${_lh_extract_root}/lib/win64/msvc") + else() + list(APPEND _lh_lib_search "${_lh_extract_root}/lib/win64/mingw") + endif() + elseif(UNIX AND NOT APPLE) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64|AMD64)$") + list(APPEND _lh_lib_search "${_lh_extract_root}/lib/linux/x86_64") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)$") + list(APPEND _lh_lib_search "${_lh_extract_root}/lib/linux/arm64") + endif() + endif() +elseif(EXISTS "${_lh_install_prefix}/include/linkerhand-cpp-sdk/api/LinkerHandApi.h") + # 已安装:lib 平铺在 /lib/linkerhand-cpp-sdk/lib/,third_party 平级 + set(_lh_inc "${_lh_install_prefix}/include/linkerhand-cpp-sdk") + list(APPEND _lh_lib_search "${_lh_install_prefix}/lib/linkerhand-cpp-sdk/lib") + if(EXISTS "${_lh_install_prefix}/lib/linkerhand-cpp-sdk/third_party") + set(_lh_thirdparty_root "${_lh_install_prefix}/lib/linkerhand-cpp-sdk/third_party") + endif() +endif() + +if(NOT _lh_inc) + set(linkerhand-cpp-sdk_FOUND FALSE) + set(linkerhand-cpp-sdk_NOT_FOUND_MESSAGE + "linkerhand-cpp-sdk: 既不在解压布局 ${_lh_extract_root} 也不在安装布局 ${_lh_install_prefix} 下找到 include/") + return() +endif() + +include(CMakeFindDependencyMacro) +find_dependency(Threads) + +# --- 选库:Linux .so / Windows .dll(+import lib) --- +set(_lh_imported_loc "") +set(_lh_imported_implib "") +set(_lh_lib_dir "") + +foreach(_dir IN LISTS _lh_lib_search) + if(NOT _lh_imported_loc AND IS_DIRECTORY "${_dir}") + if(WIN32) + if(EXISTS "${_dir}/linkerhand_cpp_sdk.dll") + set(_lh_imported_loc "${_dir}/linkerhand_cpp_sdk.dll") + set(_lh_lib_dir "${_dir}") + endif() + elseif(UNIX) + if(EXISTS "${_dir}/linkerhand_cpp_sdk.so") + set(_lh_imported_loc "${_dir}/linkerhand_cpp_sdk.so") + set(_lh_lib_dir "${_dir}") + endif() + endif() + endif() +endforeach() + +if(WIN32 AND _lh_lib_dir) + if(MSVC OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")) + if(EXISTS "${_lh_lib_dir}/linkerhand_cpp_sdk.lib") + set(_lh_imported_implib "${_lh_lib_dir}/linkerhand_cpp_sdk.lib") + endif() + else() + if(EXISTS "${_lh_lib_dir}/linkerhand_cpp_sdk.a") + set(_lh_imported_implib "${_lh_lib_dir}/linkerhand_cpp_sdk.a") + elseif(EXISTS "${_lh_lib_dir}/linkerhand_cpp_sdk.dll") + set(_lh_imported_implib "${_lh_lib_dir}/linkerhand_cpp_sdk.dll") + endif() + endif() +endif() + +if(NOT _lh_imported_loc) + set(linkerhand-cpp-sdk_FOUND FALSE) + set(linkerhand-cpp-sdk_NOT_FOUND_MESSAGE + "linkerhand-cpp-sdk: 候选 lib 目录均无匹配文件: ${_lh_lib_search}") + return() +endif() + +if(NOT TARGET LinkerHand::linkerhand_cpp_sdk) + add_library(LinkerHand::linkerhand_cpp_sdk SHARED IMPORTED) + set_target_properties(LinkerHand::linkerhand_cpp_sdk PROPERTIES + IMPORTED_LOCATION "${_lh_imported_loc}" + # 顶层 + 三个子目录都暴露,下游既能写 #include "api/LinkerHandApi.h" + # 也能写扁平的 #include "LinkerHandApi.h" + INTERFACE_INCLUDE_DIRECTORIES "${_lh_inc};${_lh_inc}/api;${_lh_inc}/core;${_lh_inc}/communication" + INTERFACE_LINK_LIBRARIES "Threads::Threads" + ) + if(_lh_imported_implib) + set_target_properties(LinkerHand::linkerhand_cpp_sdk PROPERTIES + IMPORTED_IMPLIB "${_lh_imported_implib}") + endif() + # 公共头 CanFD.h / PCANBus.h / CanFrame.h 引用了 third_party 头(Hcanbus.h / + # PCANBasic.h)。把对应 include 目录补到 imported target,下游 link 后无需手动配。 + if(_lh_thirdparty_root) + if(WIN32) + if(EXISTS "${_lh_thirdparty_root}/libcanbus/include/windows") + set_property(TARGET LinkerHand::linkerhand_cpp_sdk APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${_lh_thirdparty_root}/libcanbus/include/windows") + endif() + if(EXISTS "${_lh_thirdparty_root}/PCAN_Basic/Include") + set_property(TARGET LinkerHand::linkerhand_cpp_sdk APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${_lh_thirdparty_root}/PCAN_Basic/Include") + endif() + elseif(UNIX AND EXISTS "${_lh_thirdparty_root}/libcanbus/include/linux") + set_property(TARGET LinkerHand::linkerhand_cpp_sdk APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${_lh_thirdparty_root}/libcanbus/include/linux") + endif() + endif() +endif() + +set(linkerhand-cpp-sdk_INCLUDE_DIRS "${_lh_inc}") +set(linkerhand-cpp-sdk_LIBRARIES LinkerHand::linkerhand_cpp_sdk) +set(linkerhand-cpp-sdk_LIBRARY_DIR "${_lh_lib_dir}") +set(linkerhand-cpp-sdk_FOUND TRUE) + +unset(_lh_self_dir) +unset(_lh_extract_root) +unset(_lh_install_prefix) +unset(_lh_inc) +unset(_lh_lib_dir) +unset(_lh_lib_search) +unset(_lh_thirdparty_root) +unset(_lh_imported_loc) +unset(_lh_imported_implib) diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt new file mode 100644 index 0000000..0b87289 --- /dev/null +++ b/demo/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.10) +project(my_app LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# 解压即用:把发布包目录加进 CMake 搜索路径,无需安装。 +# 等价命令行:cmake -S . -B build -DCMAKE_PREFIX_PATH=${CMAKE_SOURCE_DIR}/linkerhand-cpp-sdk +list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/linkerhand-cpp-sdk") + +find_package(linkerhand-cpp-sdk 2.0 CONFIG REQUIRED) + +add_executable(demo main.cpp) +target_link_libraries(demo PRIVATE LinkerHand::linkerhand_cpp_sdk) + +# 运行时定位 .so:把 SDK lib 目录写进 RPATH,免去 LD_LIBRARY_PATH。 +# linkerhand-cpp-sdk_LIBRARY_DIR 由 cmake/linkerhand-cpp-sdk-config.cmake 设置。 +set_target_properties(demo PROPERTIES + BUILD_RPATH "${linkerhand-cpp-sdk_LIBRARY_DIR}" + INSTALL_RPATH "${linkerhand-cpp-sdk_LIBRARY_DIR}" +) diff --git a/demo/main.cpp b/demo/main.cpp new file mode 100644 index 0000000..17d2836 --- /dev/null +++ b/demo/main.cpp @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +#include "LinkerHandApi.h" +#include "CommFactory.h" + +int main() { + constexpr LINKER_HAND model = LINKER_HAND::O6; + constexpr HAND_TYPE side = HAND_TYPE::LEFT; + + auto hand = std::make_shared(model, side, COMM_TYPE::CAN); + auto bus = std::shared_ptr(Communication::CommFactory::createCanBus(side)); + + hand->setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t len) -> int32_t { + std::vector buf(data, data + len); + bus->send(buf, can_id); + return 0; + }); + + hand->setCanRxCallback([bus](uint32_t *id_out, uint8_t *data_out, uint8_t *len_out) -> int32_t { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) return -1; + *id_out = frame.can_id; + *len_out = frame.can_dlc; + std::memcpy(data_out, frame.data, frame.can_dlc); + return 0; + }); + + std::cout << "-----------------------------------" << std::endl; + std::cout << "version: " << hand->getVersion() << '\n'; + std::cout << "-----------------------------------" << std::endl; + return 0; +} diff --git a/docs/API-Reference.md b/docs/API-Reference.md index f20a0e6..c1bbd9a 100644 --- a/docs/API-Reference.md +++ b/docs/API-Reference.md @@ -1,941 +1,300 @@ -# LinkerHand C++ API 参考文档 - -## 目录 - -- [API 概述](#api-概述) -- [快速索引](#快速索引) -- [构造函数](#构造函数) -- [控制接口](#控制接口) -- [状态查询接口](#状态查询接口) -- [传感器接口](#传感器接口) -- [电机管理接口](#电机管理接口) -- [使用示例](#使用示例) -- [注意事项](#注意事项) -- [版本兼容性](#版本兼容性) --- -## API 概述 +# Linker Hand C++ API Documentation -LinkerHand C++ API 提供了完整的接口用于控制灵心巧手系列灵巧手设备。支持 O6、L6、L7、L10、L20、L21、L25 等多种型号,支持 CAN、ModBus、EtherCAT 等多种通信协议。 +## API Overview ---- - -## 快速索引 - -### 控制接口 -- [`fingerMove()`](#fingermove) - 设置关节位置(0-255) -- [`fingerMoveArc()`](#fingermovearc) - 设置关节位置(弧度制) -- [`setSpeed()`](#setspeed) - 设置运动速度 -- [`setTorque()`](#settorque) - 设置扭矩限制 - -### 状态查询接口 -- [`getState()`](#getstate) - 获取关节状态 -- [`getStateArc()`](#getstatearc) - 获取关节状态(弧度制) -- [`getSpeed()`](#getspeed) - 获取当前速度设置 -- [`getTorque()`](#gettorque) - 获取当前扭矩设置 -- [`getVersion()`](#getversion) - 获取版本信息 - -### 传感器接口 -- [`getForce()`](#getforce) - 获取压力数据(法向、切向、方向、接近感应) -- [`getTemperature()`](#gettemperature) - 获取电机温度 -- [`getFaultCode()`](#getfaultcode) - 获取电机故障码 -- [`getCurrent()`](#getcurrent) - 获取电机电流 - -### 电机管理接口 -- [`setCurrent()`](#setcurrent) - 设置电流(仅 L20) -- [`setEnable()`](#setenable) - 使能电机(仅 L25) -- [`setDisable()`](#setdisable) - 禁用电机(仅 L25) -- [`clearFaultCode()`](#clearfaultcode) - 清除故障码(仅 L20) - ---- +This document provides a detailed overview of the C++ API for the Linker Hand, including functions for controlling the hand's movements, retrieving sensor data, and setting operational parameters. ## 构造函数 - -### LinkerHandApi - -```cpp -LinkerHandApi(const LINKER_HAND &handModel, const HAND_TYPE &handType, const COMM_TYPE commType = COMM_CAN_0); -``` - -**功能描述** -创建并初始化 LinkerHand API 实例。 - -**参数说明** -- `handModel` (LINKER_HAND): 机械手型号 - - 可选值: `LINKER_HAND::O6`, `LINKER_HAND::L6`, `LINKER_HAND::L7`, `LINKER_HAND::L10`, `LINKER_HAND::L20`, `LINKER_HAND::L21`, `LINKER_HAND::L25` -- `handType` (HAND_TYPE): 机械手类型 - - `HAND_TYPE::LEFT` - 左手 - - `HAND_TYPE::RIGHT` - 右手 -- `commType` (COMM_TYPE): 通信类型(可选,默认 `COMM_CAN_0`) - - `COMM_CAN_0` - CAN 总线 0 - - `COMM_CAN_1` - CAN 总线 1 - - `COMM_MODBUS` - ModBus 通信协议 - - `COMM_ETHERCAT` - EtherCAT 工业以太网通信 - -**返回值** -无 - ```cpp -LinkerHandApi(const LINKER_HAND &handModel, const HAND_TYPE &handType, - const std::string canChannel, const int baudrate); +LinkerHandApi(const LINKER_HAND &handJoint, const HAND_TYPE &handType, const COMM_TYPE commType = COMM_TYPE::CAN); ``` +描述 +LinkerHandApi 类的构造函数,用于初始化 Linker 机械手 API。 -**功能描述** -创建并初始化 LinkerHand API 实例。 +参数 +- handJoint: 机械手型号,可选值 `LINKER_HAND::{L6, L7, L10, L20, L21, L25, O6, G20, O20}`。 +- handType: 左手或右手(`HAND_TYPE::LEFT` 或 `HAND_TYPE::RIGHT`)。 +- commType: 通信协议类型,可选值 `COMM_TYPE::{CAN, MODBUS, ETHERCAT}`,默认为 `CAN`。CAN-FD 走 `COMM_TYPE::CAN`,由 `Communication::CommFactory` 在底层选择 `CanFD` 实现。 -**参数说明** -- `handModel` (LINKER_HAND): 机械手型号 - - 可选值: `LINKER_HAND::O6`, `LINKER_HAND::L6`, `LINKER_HAND::L7`, `LINKER_HAND::L10`, `LINKER_HAND::L20`, `LINKER_HAND::L21`, `LINKER_HAND::L25` -- `handType` (HAND_TYPE): 机械手类型 - - `HAND_TYPE::LEFT` - 左手 - - `HAND_TYPE::RIGHT` - 右手 -- `canChannel` (std::string): can 通道名称 -- `baudrate` (int): can 波特率 - -**返回值** -无 - -**使用示例** -```cpp -#include "LinkerHandApi.h" - -int main() { - // 创建 L10 型号右手实例,使用默认 CAN0 通信 - LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); - - // 创建 L20 型号左手实例,使用 CAN1 通信 - LinkerHandApi hand(LINKER_HAND::L20, HAND_TYPE::LEFT, COMM_CAN_1); - - return 0; -} -``` - -```cpp -#include "LinkerHandApi.h" - -int main() { - - // 调用API接口 - LinkerHandApi hand(LINKER_HAND::O6, HAND_TYPE::LEFT, "can0", 115200); - - // 获取版本信息 - std::cout << hand.getVersion() << std::endl; - - // 四指握拳 - std::vector fist_pose = {255, 255, 0, 0, 0, 0}; - hand.fingerMove(fist_pose); - std::this_thread::sleep_for(std::chrono::seconds(1)); +--- - // 四指张开 - std::vector open_pose = {255, 255, 255, 255, 255, 255}; - hand.fingerMove(open_pose); - std::this_thread::sleep_for(std::chrono::seconds(1)); +## 通信回调设置 - return 0; -} -``` +为了适配不同的底层驱动(如不同的 CAN 卡或 Modbus 库),API 提供了回调机制。 -**注意事项** -- 构造函数会自动初始化通信接口 -- 确保在创建实例前,通信接口已正确配置(如 CAN 总线已启动、ModBus 端口已配置、EtherCAT 网络已初始化) -- 不同型号支持的通信协议可能不同,请参考设备手册 -- 使用 CAN 总线前,确保总线已正确配置和启动 -- 使用 ModBus 前,确保串口或网络连接已建立 -- 使用 EtherCAT 前,确保 EtherCAT 主站已正确配置 +| 函数 | 参数类型 | 描述 | +| --- | --- | --- | +| `setCanTxCallback` | `CanTxCallback` | 设置 CAN 发送回调函数 | +| `setCanRxCallback` | `CanRxCallback` | 设置 CAN 接收回调函数 | +| `setModbusTxCallback` | `ModbusTxCallback` | 设置 Modbus 发送回调函数 | +| `setModbusRxCallback` | `ModbusRxCallback` | 设置 Modbus 接收回调函数 | +| `freeCanCallback` | 无 | 释放/重置 CAN 相关回调 | +| `freeModbusCallback` | 无 | 释放/重置 Modbus 相关回调 | --- -## 控制接口 - -### fingerMove +## 成员函数 +### 设置关节位置 ```cpp void fingerMove(const std::vector &pose); ``` - -**功能描述** -设置关节的目标位置,用于控制手指的运动。使用 0-255 的数值范围。 - -**参数说明** -- `pose` (std::vector): 关节位置数组 - - **L6/O6**: 长度为 6 - - **L7**: 长度为 7 - - **L10**: 长度为 10 - - **L20**: 长度为 20 - - **L21**: 长度为 25 - - **L25**: 长度为 25 - - 取值范围: 0-255(0 表示完全弯曲,255 表示完全伸直) - -**返回值** -无 - -**关节映射关系** - -**L6/O6** (6 个关节): -``` -[0] 大拇指弯曲 -[1] 大拇指横摆 -[2] 食指弯曲 -[3] 中指弯曲 -[4] 无名指弯曲 -[5] 小拇指弯曲 -``` - -**L7** (7 个关节): -``` -[0] 大拇指弯曲 -[1] 大拇指横摆 -[2] 食指弯曲 -[3] 中指弯曲 -[4] 无名指弯曲 -[5] 小拇指弯曲 -[6] 拇指旋转 +**Description**: +设置关节的目标位置,用于控制手指的运动。 +**Parameters**: +- `pose`: 一个包含目标位置数据长度为(O6/L6=6、L7=7、L10=10、L20=20、G20=16、L21=21、L25=25) +的 `std::vector`数组,范围是0~255。 ``` + O6/L6: ["拇指根部", "拇指侧摆", "食指根部", "中指根部", "无名指根部", "小指根部"] + + L7: ["大拇指弯曲", "大拇指横摆","食指弯曲", "中指弯曲", "无名指弯曲","小拇指弯曲","拇指旋转"] -**L10** (10 个关节): -``` -[0] 拇指根部 -[1] 拇指侧摆 -[2] 食指根部 -[3] 中指根部 -[4] 无名指根部 -[5] 小指根部 -[6] 食指侧摆 -[7] 无名指侧摆 -[8] 小指侧摆 -[9] 拇指旋转 -``` + L10: ["拇指根部", "拇指侧摆","食指根部", "中指根部", "无名指根部","小指根部","食指侧摆","无名指侧摆","小指侧摆","拇指旋转"] -**L20** (20 个关节): -``` -[0-4] 拇指根部、食指根部、中指根部、无名指根部、小指根部 -[5-9] 拇指侧摆、食指侧摆、中指侧摆、无名指侧摆、小指侧摆 -[10] 拇指横摆 -[11-14] 预留 -[15-19] 拇指尖部、食指末端、中指末端、无名指末端、小指末端 -``` + L20: ["拇指根部", "食指根部", "中指根部", "无名指根部","小指根部","拇指侧摆","食指侧摆","中指侧摆","无名指侧摆","小指侧摆","拇指横摆","预留","预留","预留","预留","拇指尖部","食指末端","中指末端","无名指末端","小指末端"] + + L21: ["大拇指根部", "食指根部", "中指根部","无名指根部","小拇指根部","大拇指侧摆","食指侧摆","中指侧摆","无名指侧摆","小拇指侧摆","大拇指横滚","预留","预留","预留","预留","大拇指中部","预留","预留","预留","预留","大拇指指尖","食指指尖","中指指尖","无名指指尖","小拇指指尖"] -**L21** (25 个关节): -``` -[0-4] 大拇指根部、食指根部、中指根部、无名指根部、小拇指根部 -[5-9] 大拇指侧摆、食指侧摆、中指侧摆、无名指侧摆、小拇指侧摆 -[10] 大拇指横滚 -[11-14] 预留 -[15] 大拇指中部 -[16-19] 预留 -[20-24] 大拇指指尖、食指指尖、中指指尖、无名指指尖、小拇指指尖 -``` + G20: ["大拇指根部", "食指根部", "中指根部","无名指根部","小拇指根部","大拇指侧摆","食指侧摆","中指侧摆","无名指侧摆","小拇指侧摆","大拇指横滚","大拇指指尖","食指指尖","中指指尖","无名指指尖","小拇指指尖"] -**L25** (25 个关节): -``` -[0-4] 大拇指根部、食指根部、中指根部、无名指根部、小拇指根部 -[5-9] 大拇指侧摆、食指侧摆、中指侧摆、无名指侧摆、小拇指侧摆 -[10] 大拇指横滚 -[11-14] 预留 -[15-19] 大拇指中部、食指中部、中指中部、无名指中部、小拇指中部 -[20-24] 大拇指指尖、食指指尖、中指指尖、无名指指尖、小拇指指尖 + L25: ["大拇指根部", "食指根部", "中指根部","无名指根部","小拇指根部","大拇指侧摆","食指侧摆","中指侧摆","无名指侧摆","小拇指侧摆","大拇指横滚","预留","预留","预留","预留","大拇指中部","食指中部","中指中部","无名指中部","小拇指中部","大拇指指尖","食指指尖","中指指尖","无名指指尖","小拇指指尖"] ``` - -**使用示例** -```cpp -// L10 握拳 -std::vector fist_pose = {101, 60, 0, 0, 0, 0, 255, 255, 255, 51}; -hand.fingerMove(fist_pose); - -// L10 张开 -std::vector open_pose = {255, 104, 255, 255, 255, 255, 255, 255, 255, 71}; -hand.fingerMove(open_pose); -``` - -**注意事项** -- 数组长度必须与型号匹配,否则可能导致未定义行为 -- 建议在调用前先设置速度和扭矩 -- 动作执行需要时间,建议在调用后添加适当的延时 - --- -### fingerMoveArc - +### 设置关节位置 ```cpp void fingerMoveArc(const std::vector &pose); ``` - -**功能描述** -设置关节的目标位置,使用弧度制。适用于需要精确角度控制的场景。 - -**参数说明** -- `pose` (std::vector): 关节位置数组(弧度制) - - **L10**: 长度为 10 - - **L20**: 长度为 20 - - **L21**: 长度为 25 - - **L25**: 长度为 25 - - 取值范围: 根据 URDF 限位定义 - -**返回值** -无 - -**使用示例** -```cpp -// L10 使用弧度制控制 -std::vector pose_arc = {0.5, 0.3, 0.2, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; -hand.fingerMoveArc(pose_arc); -``` - -**注意事项** -- 仅支持 L10、L20、L21、L25 型号 -- 弧度值必须在 URDF 定义的限位范围内 -- 建议参考设备的 URDF 文件了解各关节的限位范围 +**Description**: +设置关节的目标位置,用于控制手指的运动。 +**Parameters**: +- `pose`: 一个包含目标位置数据长度为(O6/L6=6、L7=7、L10=10、L20=20、G20=16、L21=21、L25=25) +的 `std::vector`数组,范围为urdf限位。 --- -### setSpeed - +### 设置速度 ```cpp void setSpeed(const std::vector &speed); ``` - -**功能描述** -设置手部的运动速度。速度值影响关节运动的快慢。 - -**参数说明** -- `speed` (std::vector): 速度数组 - - 长度: 5 个元素(对应 5 根手指) - - 取值范围: 0-255 - - 值越大,运动速度越快 - -**返回值** -无 - -**使用示例** -```cpp -// 设置中等速度 -std::vector speed = {200, 200, 200, 200, 200}; -hand.setSpeed(speed); - -// 设置不同手指的不同速度 -std::vector speed_custom = {255, 200, 200, 200, 150}; -hand.setSpeed(speed_custom); -``` - -**注意事项** -- 速度设置会影响所有后续的 `fingerMove()` 调用 -- 建议在初始化时设置速度 -- 过高的速度可能导致运动不稳定 +**Description**: +设置手部的运动速度。 +**Parameters**: +- `speed`: 一个包含速度数据的 `std::vector`,长度为5个元素对应每手指的速度值。 --- -### setTorque - +### 设置扭矩 ```cpp void setTorque(const std::vector &torque); ``` - -**功能描述** -设置手部的扭矩限制。扭矩值影响手指的抓握力度。 - -**参数说明** -- `torque` (std::vector): 扭矩数组 - - 长度: 5 个元素(对应 5 根手指) - - 取值范围: 0-255 - - 值越大,允许的最大扭矩越大 - -**返回值** -无 - -**使用示例** -```cpp -// 设置最大扭矩 -std::vector torque = {255, 255, 255, 255, 255}; -hand.setTorque(torque); - -// 设置较小的扭矩(轻柔抓握) -std::vector torque_light = {128, 128, 128, 128, 128}; -hand.setTorque(torque_light); -``` - -**注意事项** -- 扭矩设置会影响所有后续的 `fingerMove()` 调用 -- 建议在初始化时设置扭矩 -- 过高的扭矩可能导致设备损坏,请谨慎设置 - ---- - -## 状态查询接口 - -### getState - -```cpp -std::vector getState(); -``` - -**功能描述** -获取当前关节的状态信息,返回值为 0-255 的数值。 - -**参数说明** -无 - -**返回值** -- `std::vector`: 当前关节状态数组 - - 长度: 根据型号不同(L10=10, L20=20, L21=25, L25=25) - - 取值范围: 0-255 - -**使用示例** -```cpp -auto state = hand.getState(); -for (size_t i = 0; i < state.size(); i++) { - std::cout << "关节 " << i << ": " << static_cast(state[i]) << std::endl; -} -``` - -**注意事项** -- 返回值反映的是当前关节的实际位置 -- 如果关节正在运动,返回值会持续变化 +**Description**: +设置手部的扭矩。 +**Parameters**: +- `torque`: 一个包含扭矩数据的 `std::vector`,长度为5个元素对应手指的扭矩值。 --- -### getStateArc - +### 获取法向压力、切向压力、切向方向、接近感应 ```cpp -std::vector getStateArc(); -``` - -**功能描述** -获取当前关节的状态信息,返回值为弧度制。 - -**参数说明** -无 - -**返回值** -- `std::vector`: 当前关节状态数组(弧度制) - - 长度: 根据型号不同(L10=10, L20=20, L21=25, L25=25) - -**使用示例** -```cpp -auto state_arc = hand.getStateArc(); -for (size_t i = 0; i < state_arc.size(); i++) { - std::cout << "关节 " << i << ": " << state_arc[i] << " 弧度" << std::endl; -} +std::vector>> getForce(); ``` - -**注意事项** -- 仅支持 L10、L20、L21、L25 型号 -- 返回值反映的是当前关节的实际位置(弧度制) +**Description**: +获取手部传感器的综合数据,包括法向压力、切向压力、切向方向和接近感应。 +**Returns**: +- 返回一个三维向量:第一维为传感器类型,第二维为手指,第三维为该手指对应的数据。 --- -### getSpeed - +### 获取速度 ```cpp std::vector getSpeed(); ``` - -**功能描述** -获取当前设置的速度值。 - -**参数说明** -无 - -**返回值** -- `std::vector`: 当前速度设置数组 - - 长度: 5 个元素 - -**使用示例** -```cpp -auto speed = hand.getSpeed(); -std::cout << "当前速度设置: "; -for (auto s : speed) { - std::cout << static_cast(s) << " "; -} -std::cout << std::endl; -``` +**Description**: +获取当前设置的速度值。 +**Returns**: +- 返回一个 `std::vector`,包含当前的速度设置值。 --- -### getTorque - +### 获取当前关节状态 ```cpp -std::vector getTorque(); -``` - -**功能描述** -获取当前设置的最大扭矩值。 - -**参数说明** -无 - -**返回值** -- `std::vector`: 当前扭矩设置数组 - - 长度: 5 个元素 - -**使用示例** -```cpp -auto torque = hand.getTorque(); -std::cout << "当前扭矩设置: "; -for (auto t : torque) { - std::cout << static_cast(t) << " "; -} -std::cout << std::endl; +std::vector getState(); ``` +**Description**: +获取当前关节的状态信息。 +**Returns**: +- 返回一个 `std::vector`,包含当前关节的状态数据。 --- -### getVersion - +### 获取当前关节状态 ```cpp -std::string getVersion(); -``` - -**功能描述** -获取当前软件或硬件的版本号。 - -**参数说明** -无 - -**返回值** -- `std::string`: 版本号字符串 - -**使用示例** -```cpp -std::string version = hand.getVersion(); -std::cout << "版本号: " << version << std::endl; +std::vector getStateArc(); ``` +**Description**: +获取当前关节的状态信息。 +**Returns**: +- 返回一个 `std::vector`,包含当前关节的状态数据。 --- -## 传感器接口 +### 获取大拇指、食指、中指、无名指、小指的所有压力数据 -### getForce +压感数据统一通过 `getForce()` 获取,返回三维向量 `[传感器类型][手指][数据]`,传感器类型依次为法向压力、切向压力、切向方向、接近感应。`LinkerHandApi` 不再提供 `getPressure()` 接口。 -```cpp -std::vector>> getForce(); -``` - -**功能描述** -获取手部传感器的综合数据,包括法向压力、切向压力、切向方向和接近感应。 - -**参数说明** -无 - -**返回值** -- `std::vector>>`: 三维向量 - - 第一维: 手指索引(0-4,对应拇指、食指、中指、无名指、小指) - - 第二维: 传感器类型(法向压力、切向压力、切向方向、接近感应) - - 第三维: 传感器数据矩阵 +--- -**使用示例** +### 获取版本号 ```cpp -auto force_data = hand.getForce(); - -// 遍历每根手指 -for (size_t finger = 0; finger < force_data.size(); finger++) { - std::cout << "手指 " << finger << ":" << std::endl; - - // 遍历传感器类型 - for (size_t sensor_type = 0; sensor_type < force_data[finger].size(); sensor_type++) { - std::cout << " 传感器类型 " << sensor_type << ": "; - - // 遍历传感器数据 - for (auto value : force_data[finger][sensor_type]) { - std::cout << static_cast(value) << " "; - } - std::cout << std::endl; - } -} +std::string getVersion(); ``` - -**注意事项** -- 返回值结构复杂,建议参考示例代码理解数据结构 -- 不同型号的传感器配置可能不同 +**Description**: +获取当前软件或硬件的版本号。 +**Returns**: +- 返回一个字符串,表示当前的版本号。 --- -### getTemperature - +### 获取电机温度 ```cpp std::vector getTemperature(); ``` - -**功能描述** -获取电机的温度数据。 - -**参数说明** -无 - -**返回值** -- `std::vector`: 电机温度数组 - - 长度: 根据型号不同 - - 单位: 摄氏度(具体换算方式请参考设备手册) - -**使用示例** -```cpp -auto temperature = hand.getTemperature(); -for (size_t i = 0; i < temperature.size(); i++) { - std::cout << "电机 " << i << " 温度: " << static_cast(temperature[i]) << std::endl; -} -``` - -**注意事项** -- 温度值可能需要根据设备手册进行换算 -- 建议定期检查温度,避免过热 +**Description**: +获取电机的温度数据。 +**Returns**: +- 返回一个 `std::vector`,包含电机的温度数据。 --- -### getFaultCode - +### 获取电机故障码 ```cpp std::vector getFaultCode(); ``` - -**功能描述** -获取电机的故障码。用于诊断设备故障。 - -**参数说明** -无 - -**返回值** -- `std::vector`: 故障码数组 - - 长度: 根据型号不同 - - 0 表示正常,非 0 表示存在故障 - -**使用示例** -```cpp -auto fault_code = hand.getFaultCode(); -for (size_t i = 0; i < fault_code.size(); i++) { - if (fault_code[i] != 0) { - std::cout << "警告: 电机 " << i << " 故障码: " - << static_cast(fault_code[i]) << std::endl; - } -} -``` - -**注意事项** -- 故障码的具体含义请参考设备手册 -- 出现故障码时,建议停止操作并检查设备 - ---- - -### getCurrent - -```cpp -std::vector getCurrent(); -``` - -**功能描述** -获取电机的当前电流值。 - -**参数说明** -无 - -**返回值** -- `std::vector`: 电流数组 - - 长度: 根据型号不同 - - 单位: 安培(具体换算方式请参考设备手册) - -**使用示例** -```cpp -auto current = hand.getCurrent(); -for (size_t i = 0; i < current.size(); i++) { - std::cout << "电机 " << i << " 电流: " << static_cast(current[i]) << std::endl; -} -``` - -**注意事项** -- 电流值可能需要根据设备手册进行换算 -- 异常高的电流可能表示负载过大或故障 +**Description**: +获取电机的故障码。 +**Returns**: +- 返回一个 `std::vector`,包含电机的故障码。 --- -## 电机管理接口 - -### setCurrent - +### 获取当前最大扭矩 ```cpp -void setCurrent(const std::vector ¤t); -``` - -**功能描述** -设置电机的电流值。**目前仅支持 L20 型号。** - -**参数说明** -- `current` (std::vector): 电流数组 - - 长度: 根据电机数量 - - 取值范围: 请参考设备手册 - -**返回值** -无 - -**使用示例** -```cpp -// 仅 L20 支持 -if (hand.handModel_ == LINKER_HAND::L20) { - std::vector current = {100, 100, 100, 100, 100}; - hand.setCurrent(current); -} +std::vector getTorque(); ``` - -**注意事项** -- 仅支持 L20 型号 -- 电流设置需要谨慎,过高的电流可能损坏设备 +**Description**: +获取电机的当前最大扭矩值。 +**Returns**: +- 返回一个 `std::vector`,包含电机的当前最大扭矩值。 --- -### setEnable - -```cpp -void setEnable(const std::vector &enable = std::vector(5, 0)); -``` - -**功能描述** -使能电机。**目前仅支持 L25 型号。** - -**参数说明** -- `enable` (std::vector): 使能数组(可选,默认全 0) - - 长度: 5 个元素 - - 0 表示禁用,非 0 表示使能 - -**返回值** -无 - -**使用示例** +### 设置电机使能(目前仅支持 L25) ```cpp -// 仅 L25 支持 -if (hand.handModel_ == LINKER_HAND::L25) { - std::vector enable = {1, 1, 1, 1, 1}; // 使能所有手指 - hand.setEnable(enable); -} +void setEnable(const std::vector &enable); ``` - -**注意事项** -- 仅支持 L25 型号 -- 默认参数为全 0(禁用状态) +**Description**: +使能电机。 +**Parameters**: +- `enable`: 一个包含使能数据的 `std::vector`,每个元素对应一个电机的使能状态。 --- -### setDisable - +### 设置电机禁用(目前仅支持 L25) ```cpp -void setDisable(const std::vector &disable = std::vector(5, 1)); +void setDisable(const std::vector &disable); ``` - -**功能描述** -禁用电机。**目前仅支持 L25 型号。** - -**参数说明** -- `disable` (std::vector): 禁用数组(可选,默认全 1) - - 长度: 5 个元素 - - 0 表示使能,非 0 表示禁用 - -**返回值** -无 - -**使用示例** -```cpp -// 仅 L25 支持 -if (hand.handModel_ == LINKER_HAND::L25) { - std::vector disable = {1, 1, 1, 1, 1}; // 禁用所有手指 - hand.setDisable(disable); -} -``` - -**注意事项** -- 仅支持 L25 型号 -- 默认参数为全 1(禁用状态) +**Description**: +禁用电机。 +**Parameters**: +- `disable`: 一个包含禁用数据的 `std::vector`,每个元素对应一个电机的禁用状态。 --- -### clearFaultCode - -```cpp -void clearFaultCode(const std::vector &torque = std::vector(5, 1)); -``` - -**功能描述** -清除电机的故障码。**目前仅支持 L20 型号。** - -**参数说明** -- `torque` (std::vector): 扭矩数组(可选,默认全 1) - - 长度: 5 个元素 - -**返回值** -无 - -**使用示例** +### 清除电机故障码(目前仅支持 L20) ```cpp -// 仅 L20 支持 -if (hand.handModel_ == LINKER_HAND::L20) { - hand.clearFaultCode(); -} +void clearFaultCode(); ``` - -**注意事项** -- 仅支持 L20 型号 -- 清除故障码前,请确保故障原因已解决 +**Description**: +清除电机的故障码。 --- -## 使用示例 +## Example Usage -### 完整示例:基本控制流程 +以下是一个完整的示例代码,展示如何使用上述 API: ```cpp #include "LinkerHandApi.h" -#include -#include -#include int main() { - // 1. 初始化 API - LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); - // 2. 获取版本信息 - std::cout << "SDK Version: " << hand.getVersion() << std::endl; + // 初始化灵巧手 + LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::LEFT, COMM_TYPE::CAN); + + // 初始化CAN设备/自动搜索CAN设备(CommFactory 旧名 CanBusFactory 兼容保留) + std::shared_ptr bus = Communication::CommFactory::createCanBus("can0", 1000000); + // std::shared_ptr bus = Communication::CommFactory::createCanBus(HAND_TYPE::LEFT); + + // 设置CAN发送回调函数 + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + // 设置CAN接收回调函数 + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + try { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; + } + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + return 0; + } catch (const std::exception& e) { + std::cerr << "CAN接收错误: " << e.what() << std::endl; + return -1; + } + }); + std::cout << "-------------------------------------------" << std::endl; - // 3. 设置速度和扭矩 - std::vector speed = {200, 200, 200, 200, 200}; - std::vector torque = {255, 255, 255, 255, 255}; - hand.setSpeed(speed); - hand.setTorque(torque); + std::cout << "获取版本信息:" << std::endl; + std::cout << hand.getVersion() << std::endl; + std::cout << "-------------------------------------------" << std::endl; - // 4. 握拳动作 - std::vector fist_pose = {101, 60, 0, 0, 0, 0, 255, 255, 255, 51}; + std::cout << "执行动作:握拳" << std::endl; + std::vector fist_pose = {120, 60, 0, 0, 0, 0, 255, 255, 255, 51}; hand.fingerMove(fist_pose); std::this_thread::sleep_for(std::chrono::seconds(1)); + std::cout << "-------------------------------------------" << std::endl; - // 5. 张开动作 + std::cout << "执行动作:张开" << std::endl; std::vector open_pose = {255, 104, 255, 255, 255, 255, 255, 255, 255, 71}; hand.fingerMove(open_pose); std::this_thread::sleep_for(std::chrono::seconds(1)); - - // 6. 获取状态信息 - auto state = hand.getState(); - std::cout << "当前关节状态: "; - for (auto s : state) { - std::cout << static_cast(s) << " "; - } - std::cout << std::endl; - - return 0; -} -``` - -### 示例:使用弧度制控制(L10/L20/L21/L25) - -```cpp -#include "LinkerHandApi.h" - -int main() { - LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); - - // 使用弧度制控制关节 - std::vector pose_arc = {0.5, 0.3, 0.2, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; - hand.fingerMoveArc(pose_arc); - - // 获取弧度制关节状态 - auto state_arc = hand.getStateArc(); - for (size_t i = 0; i < state_arc.size(); i++) { - std::cout << "关节 " << i << ": " << state_arc[i] << " 弧度" << std::endl; - } - + std::cout << "-------------------------------------------" << std::endl; + + std::cout << "程序结束!" << std::endl; return 0; } -``` - -### 示例:读取传感器数据 - -```cpp -#include "LinkerHandApi.h" -#include - -int main() { - LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); - - // 获取压力数据 - auto force_data = hand.getForce(); - - // 获取电机温度 - auto temperature = hand.getTemperature(); - // 获取故障码 - auto fault_code = hand.getFaultCode(); - - // 获取电流 - auto current = hand.getCurrent(); - - // 处理数据... - - return 0; -} ``` --- -## 注意事项 - -1. **初始化顺序** - - 建议在使用 API 前先设置速度和扭矩 - - 确保通信接口已正确配置 - -2. **参数范围** - - `fingerMove()` 的参数范围是 0-255 - - `fingerMoveArc()` 的参数范围由 URDF 限位定义 - - 速度和扭矩的范围是 0-255 - -3. **型号差异** - - 不同型号支持的关节数量不同 - - 部分功能仅特定型号支持(如 `setCurrent()` 仅 L20 支持) - - 请根据实际使用的型号调整代码 - -4. **通信协议** - - 默认使用 CAN0,可通过构造函数参数修改 - - 使用 CAN 总线前,确保总线已正确配置和启动 - - 使用 ModBus 前,确保串口或网络连接已建立 - - 使用 EtherCAT 前,确保 EtherCAT 主站已正确配置 - -5. **错误处理** - - 建议定期检查故障码 - - 出现故障时及时停止操作 - - 温度过高时应暂停使用 - -6. **性能考虑** - - 动作执行需要时间,建议添加适当的延时 - - 频繁调用 API 可能影响性能 - - 建议在循环中适当添加延时 +## Notes +- 在使用 API 之前,请确保手部设备已正确连接并初始化。 +- 参数值(如速度、扭矩等)的具体范围和含义请参考设备的技术手册。 --- -## 版本兼容性 - -### 支持的型号 -- ✅ O6 -- ✅ L6 -- ✅ L7 -- ✅ L10 -- ✅ L20 -- ✅ L21 -- ✅ L25 - -### 功能支持矩阵 - -| 功能 | O6 | L6 | L7 | L10 | L20 | L21 | L25 | -|------|----|----|----|-----|-----|-----|-----| -| `fingerMove()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| `fingerMoveArc()` | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | -| `setCurrent()` | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | -| `setEnable()` / `setDisable()` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | -| `clearFaultCode()` | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | - -### 通信协议支持 -- ✅ CAN (CAN0, CAN1) -- ✅ ModBus -- ✅ EtherCAT +## Contact +- 如果有任何问题或需要进一步支持,请联系 [https://linkerbot.cn/aboutUs](https://linkerbot.cn/aboutUs)。 --- - -## 获取帮助 - -- **官方网站**: [https://linkerbot.cn](https://linkerbot.cn) -- **技术支持**: [https://linkerbot.cn/aboutUs](https://linkerbot.cn/aboutUs) -- **GitHub**: [https://github.com/linker-bot/linkerhand-cpp-sdk](https://github.com/linker-bot/linkerhand-cpp-sdk) -- **故障排查**: 请参考 [故障排查指南](TROUBLESHOOTING.md) -- **常见问题**: 请参考 [常见问题解答](FAQ.md) diff --git a/docs/CI-CD.md b/docs/CI-CD.md deleted file mode 100644 index 6cbf2da..0000000 --- a/docs/CI-CD.md +++ /dev/null @@ -1,316 +0,0 @@ -# CI/CD 文档 - -本文档介绍项目的持续集成和持续部署(CI/CD)配置。 - -## 📋 目录 - -- [概述](#概述) -- [工作流配置](#工作流配置) -- [触发条件](#触发条件) -- [构建矩阵](#构建矩阵) -- [作业说明](#作业说明) -- [状态徽章](#状态徽章) -- [故障排查](#故障排查) -- [本地测试](#本地测试) - -## 概述 - -项目使用 GitHub Actions 进行持续集成,自动执行以下任务: - -- ✅ 多平台构建(Linux x86_64) -- ✅ 自动运行单元测试 -- ✅ 构建示例程序 -- ✅ 代码质量检查 -- ✅ 构建状态报告 - -## 工作流配置 - -CI/CD 工作流配置文件位于:`.github/workflows/ci.yml` - -### 主要特性 - -- **多构建配置**: 支持 Release 和 Debug 构建 -- **并行测试**: 使用多核并行运行测试以加快速度 -- **缓存优化**: 缓存 CMake 构建文件以提高效率 -- **详细日志**: 提供详细的构建和测试输出 - -## 触发条件 - -工作流在以下情况下自动触发: - -1. **推送代码** - 推送到 `main`、`master` 或 `develop` 分支 -2. **Pull Request** - 创建或更新 PR 到 `main`、`master` 或 `develop` 分支 -3. **手动触发** - 通过 GitHub Actions 界面手动运行(`workflow_dispatch`) - -## 构建矩阵 - -当前支持的构建配置: - -| 操作系统 | 架构 | 构建类型 | 说明 | -|---------|------|---------|------| -| Ubuntu Latest | x86_64 | Release | 主要构建配置 | -| Ubuntu Latest | x86_64 | Debug | 调试构建配置 | -| Ubuntu Latest | aarch64 | Release | ARM64 架构构建(使用 QEMU 模拟) | - -### 架构支持说明 - -- **x86_64**: 原生支持,使用系统默认工具链 -- **aarch64**: 使用交叉编译工具链(`aarch64-linux-gnu-gcc`)和 QEMU 用户模式模拟运行测试 - - 构建速度较慢(由于 QEMU 模拟) - - 测试并行度降低(使用 2 个并行任务) - - 确保库文件在 `lib/aarch64/` 目录下可用 - - -## 作业说明 - -### 1. build-and-test - -**目的**: 构建项目并运行所有单元测试 - -**步骤**: -1. 检出代码 -2. 设置 QEMU(仅 aarch64 架构) -3. 缓存 CMake 构建文件 -4. 安装构建依赖(CMake、GCC、Git 等,aarch64 需要交叉编译工具链) -5. 验证工具链版本 -6. 配置 CMake(启用测试,aarch64 使用交叉编译配置) -7. 构建项目 -8. 运行测试(使用 CTest,aarch64 通过 QEMU 运行) -9. 显示测试结果和构建产物 - -**架构特定说明**: -- **x86_64**: 使用系统原生工具链,并行运行所有测试 -- **aarch64**: 使用 `aarch64-linux-gnu-gcc` 交叉编译,通过 QEMU 用户模式运行测试(并行度降低为 2) - -**输出**: 测试结果、构建的可执行文件信息 - -### 2. build-examples - -**目的**: 验证示例程序可以成功构建 - -**步骤**: -1. 检出代码 -2. 安装构建依赖 -3. 配置 CMake(禁用测试) -4. 构建示例程序(`toolset_example`、`action_group_show_l10`) -5. 验证构建产物 - -**依赖**: 等待 `build-and-test` 作业完成 - -**输出**: 示例程序构建状态 - -### 3. code-quality - -**目的**: 执行代码质量检查 - -**检查项**: -- 文件编码和换行符(确保使用 LF) -- CMake 语法验证 -- 头文件包含检查 - -**输出**: 代码质量报告 - -### 4. summary - -**目的**: 生成 CI/CD 摘要报告 - -**功能**: 汇总所有作业的状态,生成易于阅读的摘要 - -## 状态徽章 - -将以下 Markdown 代码添加到 README.md 以显示构建状态: - -```markdown -![CI/CD](https://github.com/你的用户名/linkerhand-cpp-sdk/workflows/CI/CD/badge.svg) -``` - -或者使用 shields.io 样式: - -```markdown -![CI/CD Status](https://img.shields.io/github/workflow/status/你的用户名/linkerhand-cpp-sdk/CI/CD?label=CI%2FCD) -``` - -## 故障排查 - -### 常见问题 - -#### 1. 测试失败 - -**症状**: `build-and-test` 作业失败 - -**可能原因**: -- 代码更改导致测试失败 -- 测试超时 -- 依赖库未找到 - -**解决方法**: -1. 查看作业日志中的详细错误信息 -2. 在本地运行测试:`cd build && ctest --output-on-failure` -3. 检查 CMake 配置是否正确 - -#### 2. 构建失败 - -**症状**: CMake 配置或构建步骤失败 - -**可能原因**: -- CMakeLists.txt 语法错误 -- 缺少依赖库 -- 编译器版本不兼容 - -**解决方法**: -1. 检查 CMake 输出日志 -2. 验证本地构建是否成功 -3. 检查依赖库路径配置 - -#### 3. 缓存问题 - -**症状**: 构建使用过期的缓存 - -**解决方法**: -1. 在 GitHub Actions 界面清除缓存 -2. 修改工作流中的缓存 key -3. 手动触发工作流 - -#### 4. aarch64 构建问题 - -**症状**: aarch64 架构构建或测试失败 - -**可能原因**: -- QEMU 未正确设置 -- 交叉编译工具链未安装 -- 库文件路径不正确 -- QEMU 模拟运行失败 - -**解决方法**: -1. 检查 QEMU 设置步骤是否成功 -2. 验证交叉编译工具链是否安装:`aarch64-linux-gnu-gcc --version` -3. 确认 `lib/aarch64/` 目录下存在库文件 -4. 检查测试可执行文件架构:`file build/test_*` -5. 查看 QEMU 相关日志和错误信息 -6. 如果 QEMU 模拟失败,可以尝试减少并行任务数量 - -### 查看日志 - -1. 进入 GitHub 仓库 -2. 点击 "Actions" 标签 -3. 选择失败的工作流运行 -4. 查看具体作业的日志 - -## 本地测试 - -在提交代码前,建议在本地运行 CI/CD 流程: - -### 1. 安装依赖 - -```bash -sudo apt-get update -sudo apt-get install -y \ - build-essential \ - cmake \ - git \ - libpthread-stubs0-dev -``` - -### 2. 运行完整构建和测试 - -#### x86_64 架构 - -```bash -# 创建构建目录 -mkdir -p build -cd build - -# 配置 CMake(启用测试,CMake 最低版本要求 3.15) -cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON - -# 构建项目 -cmake --build . --config Release --parallel $(nproc) - -# 运行测试 -ctest --output-on-failure --parallel $(nproc) -``` - -#### aarch64 架构(交叉编译) - -```bash -# 安装交叉编译工具链和 QEMU -sudo apt-get update -sudo apt-get install -y \ - gcc-aarch64-linux-gnu \ - g++-aarch64-linux-gnu \ - qemu-user-static \ - binfmt-support - -# 创建构建目录 -mkdir -p build -cd build - -# 配置 CMake(交叉编译,CMake 最低版本要求 3.15) -cmake .. \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_TESTING=ON \ - -DCMAKE_SYSTEM_NAME=Linux \ - -DCMAKE_SYSTEM_PROCESSOR=aarch64 \ - -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \ - -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \ - -DCMAKE_FIND_ROOT_PATH=/usr/aarch64-linux-gnu - -# 构建项目 -cmake --build . --config Release --parallel $(nproc) - -# 运行测试(通过 QEMU) -export QEMU_LD_PREFIX=/usr/aarch64-linux-gnu -ctest --output-on-failure --parallel 2 -``` - -### 3. 构建示例程序 - -```bash -cd build -cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -cmake --build . --target toolset_example action_group_show_l10 -``` - -### 4. 代码质量检查 - -```bash -# 检查文件编码 -find . -type f \( -name "*.cpp" -o -name "*.h" \) \ - -exec file {} \; | grep -q "CRLF" && echo "发现 CRLF" || echo "✓ 使用 LF" - -# 验证 CMake 语法 -cmake --version -mkdir -p /tmp/cmake-check -cd /tmp/cmake-check -cmake /path/to/project -Wno-dev -``` - -## 最佳实践 - -1. **提交前测试**: 在本地运行测试确保通过 -2. **小步提交**: 频繁提交小改动,便于定位问题 -3. **查看日志**: 失败时仔细查看详细日志 -4. **更新文档**: 修改 CI/CD 配置时更新本文档 -5. **监控状态**: 定期检查构建状态,及时修复问题 - -## 相关文档 - -- [测试文档](tests/README.md) - 测试框架和运行指南 -- [构建文档](../README.md#构建项目) - 项目构建说明 -- [故障排查](TROUBLESHOOTING.md) - 常见问题解决方案 - -## 贡献 - -如果您想改进 CI/CD 配置: - -1. Fork 仓库 -2. 创建特性分支 -3. 修改 `.github/workflows/ci.yml` -4. 测试您的更改 -5. 提交 Pull Request - ---- - -**最后更新**: 2026-01-XX - -**注意**: 本文档描述了项目的 CI/CD 配置。如果您的项目尚未配置 CI/CD,可以参考本文档进行配置。实际的工作流配置文件位于 `.github/workflows/ci.yml`。 diff --git a/docs/FAQ.md b/docs/FAQ.md index f8784e9..897e17c 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -1,539 +1,106 @@ -# 常见问题解答 (FAQ) +# 常见问题解答 -本文档回答 LinkerHand-CPP-SDK 的常见问题。 +本文档面向 `pack.sh` 生成的 `linkerhand-cpp-sdk/` 发布包,以及从 `linkerhand/` 源码构建安装 SDK 的开发者。 -## 目录 +## 安装与发布包 -- [安装相关问题](#安装相关问题) -- [使用相关问题](#使用相关问题) -- [API 相关问题](#api-相关问题) -- [兼容性问题](#兼容性问题) -- [性能相关问题](#性能相关问题) -- [其他问题](#其他问题) +### Q1: 发布包和源码仓库是什么关系? ---- +`linkerhand/` 是唯一主开发工作区,`./pack.sh pack` 会基于它生成可直接发布的 `linkerhand-cpp-sdk/`。发布包内包含预编译库、示例、示教器、文档和必要的第三方依赖。 -## 安装相关问题 +### Q2: 发布包解压后怎么快速验证? -### Q1: 如何安装 SDK? +Linux/macOS: -**A**: 有两种安装方式: - -**方法一:使用安装脚本(推荐)** -```bash -./script.sh -# 选择选项 [2]: Install SDK -``` - -**方法二:手动安装** ```bash +cd linkerhand-cpp-sdk mkdir build && cd build cmake .. -make -sudo make install +cmake --build . -j$(nproc) +./bin/test_l10_can_0 ``` -详细说明请参考 [README.md](../README.md#安装)。 +Windows MinGW: ---- +```cmd +cd linkerhand-cpp-sdk +mkdir build +cd build +cmake -G "MinGW Makefiles" -DCMAKE_MAKE_PROGRAM=mingw32-make .. +mingw32-make -j +build\bin\test_l10_can_0.exe +``` -### Q2: 安装后找不到库文件怎么办? +### Q3: 发布包里的头文件为什么比最小 API 入口多? -**A**: 检查以下几点: +发布包不仅面向统一 API,也要支持 `examples/`、`hand_teach_pendant/` 和部分需要直连通信层的客户工程,所以会一起发布 `include/communication/` 下的通信相关头。新项目优先从 `LinkerHandApi.h` 开始接入。 -1. **确认安装路径**: - ```bash - ls /usr/local/lib/linkerhand-cpp-sdk/ - ``` +### Q4: 安装后 `find_package` 应该怎么接? -2. **检查架构匹配**: - ```bash - uname -m # 查看系统架构 - ls lib/x86_64/ # 或 lib/aarch64/ - ``` +从源码执行 `cmake --install` 或 `./build.sh -i` 后,可直接在下游工程里写: -3. **设置库路径**: - ```bash - export LD_LIBRARY_PATH=/usr/local/lib/linkerhand-cpp-sdk/x86_64:$LD_LIBRARY_PATH - ``` +```cmake +find_package(linkerhand-cpp-sdk CONFIG REQUIRED) +target_link_libraries(my_app PRIVATE LinkerHand::linkerhand_cpp_sdk) +``` -4. **更新动态链接库缓存**: - ```bash - sudo ldconfig - ``` +这条路径适合系统安装后的二次开发;如果只是消费发布包,直接用发布包根目录的 `CMakeLists.txt` 构建 examples 或参考 `README.md` 手动链接即可。 ---- +## 构建与运行 -### Q3: 支持哪些操作系统和架构? +### Q5: 发布包里的 `build.sh` / `build.bat` 能做什么? -**A**: -- **操作系统**: Linux (Ubuntu 18.04+ 推荐) -- **架构**: x86_64、aarch64 -- **编译器**: GCC 7.0+ 或 Clang 5.0+ -- **CMake**: 3.11+ ---- +它们主要服务于持有源码工程的开发者,用于重建、安装或卸载 SDK。客户从发布包消费预编译库时,通常不需要执行 `-b` / `-i`,直接用 `cmake ..` 构建 examples 即可。 -### Q4: 如何卸载 SDK? +### Q6: `--skip-tests` 为什么没有关闭 examples? -**A**: 使用安装脚本: -```bash -./script.sh -# 选择选项 [3]: Uninstall SDK -``` +当前 `build.sh` 透传的是 `-DBUILD_TESTS=OFF`,这是 examples 子目录内部开关,不影响顶层 `BUILD_EXAMPLES` / `BUILD_PENDANT`。如果只想构建 SDK,请直接使用: -或手动删除: ```bash -sudo rm -rf /usr/local/include/linkerhand-cpp-sdk -sudo rm -rf /usr/local/lib/linkerhand-cpp-sdk +cmake -S linkerhand -B linkerhand/build -DBUILD_EXAMPLES=OFF -DBUILD_PENDANT=OFF +cmake --build linkerhand/build -j ``` ---- - -## 使用相关问题 - -### Q5: 如何快速开始使用 SDK? - -**A**: 参考以下步骤: - -1. **创建项目文件**: - ```cpp - // main.cpp - #include "LinkerHandApi.h" - #include - - int main() { - LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); - std::cout << "Version: " << hand.getVersion() << std::endl; - return 0; - } - ``` - -2. **创建 CMakeLists.txt**: - ```cmake - cmake_minimum_required(VERSION 3.5) - project(MyProject) - - # 查找库和头文件 - find_library(LINKER_HAND_LIB linkerhand_cpp_sdk - PATHS /usr/local/lib/linkerhand-cpp-sdk/x86_64) - include_directories(/usr/local/include/linkerhand-cpp-sdk) - - add_executable(my_project main.cpp) - target_link_libraries(my_project ${LINKER_HAND_LIB} pthread) - ``` - -3. **编译和运行**: - ```bash - mkdir build && cd build - cmake .. - make - ./my_project - ``` - -详细说明请参考 [README.md](../README.md#快速开始)。 - ---- - -### Q6: 如何选择正确的通信接口? - -**A**: 根据您的硬件配置选择: - -- **CAN 总线**: 默认使用 `COMM_CAN_0`,如果有多个 CAN 接口可使用 `COMM_CAN_1` -- **ModBus**: 使用 `COMM_MODBUS` 进行 ModBus 通信 -- **EtherCAT**: 使用 `COMM_ETHERCAT` 进行 EtherCAT 工业以太网通信 - -```cpp -// CAN0(默认) -LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); - -// CAN1 -LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT, COMM_CAN_1); - -// ModBus -LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT, COMM_MODBUS); - -// EtherCAT -LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT, COMM_ETHERCAT); -``` +### Q7: 哪些平台是当前主要验证目标? ---- +- Linux `x86_64` +- Linux `aarch64` +- Windows `x64`(MinGW / MSVC 导入库) -### Q7: 如何配置通信接口? +其中 O20 的 CAN-FD 示例目前主要面向 Linux `x86_64`。 -**A**: 根据不同的通信协议进行配置: +## 通信与接口 -#### CAN 总线配置 +### Q8: CAN、Modbus、EtherCAT 怎么选? -在 Linux 系统中配置 CAN 总线: +- 统一 API 层通过 `COMM_TYPE::CAN`、`COMM_TYPE::MODBUS`、`COMM_TYPE::ETHERCAT` 选择通信方式。 +- 不同手型支持范围不同,具体以 `README.md` 型号表和现有 examples 为准。 +- 需要自己管理底层总线时,优先参考 `examples/test_*` 和 `hand_teach_pendant/src/HandController.cpp` 的实际用法。 + +### Q9: Linux 下 CAN 默认怎么配? ```bash -# 加载 CAN 模块 sudo modprobe can sudo modprobe can_raw -sudo modprobe vcan # 虚拟 CAN(用于测试) - -# 配置 CAN 接口 sudo ip link set can0 type can bitrate 1000000 sudo ip link set can0 up - -# 查看 CAN 接口状态 ip link show can0 - -# 测试 CAN 通信 -cansend can0 123#DEADBEEF -candump can0 -``` - -#### ModBus 配置 - -ModBus 配置取决于使用的接口类型(串口或网络): - -- **串口 ModBus**: 确保串口设备权限正确,通常需要将用户添加到 `dialout` 组 -- **网络 ModBus**: 确保网络连接正常,ModBus TCP/IP 端口已开放 - -#### EtherCAT 配置 - -EtherCAT 需要配置 EtherCAT 主站: - -- 确保 EtherCAT 主站软件已安装和配置 -- 检查 EtherCAT 网络拓扑 -- 验证 EtherCAT 从站设备已正确连接 - ---- - -### Q8: 如何控制手指运动? - -**A**: 使用 `fingerMove()` 函数: - -```cpp -// 1. 设置速度和扭矩 -std::vector speed = {200, 200, 200, 200, 200}; -std::vector torque = {255, 255, 255, 255, 255}; -hand.setSpeed(speed); -hand.setTorque(torque); - -// 2. 设置关节位置(L10 示例) -std::vector pose = {128, 128, 128, 128, 128, 128, 128, 128, 128, 128}; -hand.fingerMove(pose); - -// 3. 等待动作完成 -std::this_thread::sleep_for(std::chrono::seconds(1)); -``` - ---- - -### Q9: 如何读取传感器数据? - -**A**: 使用相应的获取函数: - -```cpp -// 获取压力数据 -auto force = hand.getForce(); - -// 获取温度 -auto temperature = hand.getTemperature(); - -// 获取故障码 -auto fault_code = hand.getFaultCode(); - -// 获取电流 -auto current = hand.getCurrent(); - -// 获取关节状态 -auto state = hand.getState(); -``` - ---- - -## API 相关问题 - -### Q10: 不同型号的关节数量是多少? - -**A**: -- **L6/O6**: 6 个关节 -- **L7**: 7 个关节 -- **L10**: 10 个关节 -- **L20**: 20 个关节 -- **L21**: 25 个关节 -- **L25**: 25 个关节 - -详细映射关系请参考 [README.md](../README.md#关节映射表) 或 [API 参考文档](API-Reference.md)。 - ---- - -### Q11: `fingerMove()` 和 `fingerMoveArc()` 有什么区别? - -**A**: -- **`fingerMove()`**: 使用 0-255 的数值范围,适用于快速控制 -- **`fingerMoveArc()`**: 使用弧度制,适用于精确角度控制 - -```cpp -// 使用 0-255 范围(L10) -std::vector pose = {128, 128, 128, 128, 128, 128, 128, 128, 128, 128}; -hand.fingerMove(pose); - -// 使用弧度制(L10) -std::vector pose_arc = {0.5, 0.3, 0.2, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; -hand.fingerMoveArc(pose_arc); -``` - -**注意**: `fingerMoveArc()` 仅支持 L10、L20、L21、L25 型号。 - ---- - -### Q12: 速度和扭矩的取值范围是多少? - -**A**: -- **范围**: 0-255 -- **速度**: 值越大,运动速度越快 -- **扭矩**: 值越大,允许的最大扭矩越大 - -```cpp -// 中等速度 -std::vector speed = {200, 200, 200, 200, 200}; - -// 最大扭矩 -std::vector torque = {255, 255, 255, 255, 255}; -``` - ---- - -### Q13: `getForce()` 返回的数据结构是什么? - -**A**: `getForce()` 返回三维向量: - -```cpp -std::vector>> force = hand.getForce(); - -// force[finger][sensor_type][data] -// finger: 0-4 (拇指、食指、中指、无名指、小指) -// sensor_type: 0-3 (法向压力、切向压力、切向方向、接近感应) -// data: 传感器数据矩阵 -``` - -示例: -```cpp -auto force = hand.getForce(); -for (size_t finger = 0; finger < force.size(); finger++) { - for (size_t sensor_type = 0; sensor_type < force[finger].size(); sensor_type++) { - // 处理数据... - } -} -``` - ---- - -### Q14: 哪些功能仅特定型号支持? - -**A**: -- **`setCurrent()`**: 仅 L20 支持 -- **`setEnable()` / `setDisable()`**: 仅 L25 支持 -- **`clearFaultCode()`**: 仅 L20 支持 -- **`fingerMoveArc()`**: 仅 L10、L20、L21、L25 支持 - -详细支持矩阵请参考 [API 参考文档](API-Reference.md#版本兼容性)。 - ---- - -## 兼容性问题 - -### Q15: SDK 版本和设备固件版本需要匹配吗? - -**A**: 建议使用匹配的版本。如果遇到兼容性问题: - -1. 检查 SDK 版本: - ```cpp - std::string version = hand.getVersion(); - std::cout << "SDK Version: " << version << std::endl; - ``` - -2. 查看 [更新日志](../CHANGELOG.md)(如果存在)了解版本变更 - -3. 联系技术支持获取兼容性信息 - ---- - -### Q16: 可以在 Windows 上使用吗? - -**A**: 当前版本主要支持 Linux 系统。Windows 支持情况: - -- **当前状态**: 主要支持 Linux -- **Windows**: 可能需要额外的配置和编译 -- **建议**: 使用 Linux 系统(Ubuntu 18.04+ 推荐) - -如有 Windows 支持需求,请联系技术支持。 - ---- - -### Q17: 支持哪些编译器? - -**A**: -- **GCC**: 7.0 或更高版本 -- **Clang**: 5.0 或更高版本 - -建议使用较新的编译器版本以获得更好的兼容性。 - ---- - -## 性能相关问题 - -### Q18: API 调用的响应时间是多少? - -**A**: 响应时间取决于多个因素: - -- **系统负载**: 系统负载高时响应会变慢 -- **网络延迟**: EtherCAT 网络延迟 - -**建议**: -- 在动作后添加适当的延时:`std::this_thread::sleep_for(std::chrono::milliseconds(100))` -- 避免过于频繁的 API 调用 -- 使用多线程处理传感器数据 - ---- - -### Q19: 如何提高性能? - -**A**: 以下建议可以提高性能: - -1. **降低轮询频率**: - ```cpp - // 从 10ms 改为 100ms - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - ``` - -2. **使用多线程**: - ```cpp - std::thread sensor_thread([&hand]() { - while (running) { - auto force = hand.getForce(); - // 处理数据... - } - }); - ``` - -3. **批量处理操作**: - - 减少不必要的 API 调用 - - 缓存不需要实时更新的数据 - -4. **优化通信**: - - 优化通信参数 - ---- - -### Q20: CPU 占用过高怎么办? - -**A**: 可能的原因和解决方案: - -1. **轮询频率过高**: - ```cpp - // 增加延时 - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - ``` - -2. **阻塞操作**: - - 使用异步操作 - - 避免在循环中进行阻塞调用 - -3. **资源泄漏**: - - 检查资源是否正确释放 - - 使用 RAII 原则管理资源 - ---- - -## 其他问题 - -### Q21: 如何获取技术支持? - -**A**: 可以通过以下方式获取支持: - -1. **文档**: - - [API 参考文档](API-Reference.md) - - [故障排查指南](TROUBLESHOOTING.md) - - [README](../README.md) - -2. **在线资源**: - - **官方网站**: [https://linkerbot.cn](https://linkerbot.cn) - - **技术支持**: [https://linkerbot.cn/aboutUs](https://linkerbot.cn/aboutUs) - - **GitHub**: [https://github.com/linker-bot/linkerhand-cpp-sdk](https://github.com/linker-bot/linkerhand-cpp-sdk) - -3. **GitHub Issues**: - - 提交问题报告 - - 查看已有问题和解决方案 - ---- - -### Q22: 如何贡献代码? - -**A**: 欢迎贡献!请参考以下步骤: - -1. Fork 本仓库 -2. 创建特性分支 (`git checkout -b feature/AmazingFeature`) -3. 提交更改 (`git commit -m 'Add some AmazingFeature'`) -4. 推送到分支 (`git push origin feature/AmazingFeature`) -5. 开启 Pull Request - -详细说明请参考 [README.md](../README.md#贡献)。 - ---- - -### Q23: 如何报告 Bug? - -**A**: 在 GitHub Issues 中报告 Bug 时,请提供: - -1. **错误信息**: 完整的错误信息或日志 -2. **系统信息**: - - 操作系统和版本 - - 系统架构(x86_64/aarch64) - - SDK 版本 -3. **设备信息**: - - 设备型号(L6/L7/L10/L20/L21/L25) - - 固件版本(如果知道) -4. **复现步骤**: 详细的步骤说明 -5. **相关代码**: 能够复现问题的代码片段 - ---- - -### Q24: 有示例代码吗? - -**A**: 是的,项目提供了示例代码: - -- **位置**: `examples/` 目录 -- **示例**: - - `toolset_example.cpp` - 工具集示例 - - `action_group_show_l10.cpp` - L10 动作组示例 - -运行示例: -```bash -cd build -./toolset_example -./action_group_show_l10 ``` -详细说明请参考 [示例代码文档](../examples/README.md)。 +如果示例使用了 `can1` 或其他设备名,请按现场总线名替换。 ---- +### Q10: Windows 下还需要额外 DLL 吗? -### Q25: 如何更新 SDK? +需要。发布包已经带上 `third_party/PCAN_Basic/` 和对应导入库;客户工程除了 SDK 自身 DLL 外,还要确保 `PCANBasic.dll` 与可执行文件同目录,或能被系统搜索路径找到。 -**A**: 更新步骤: +## 文档与支持 -1. **拉取最新代码**: - ```bash - git pull origin main - ``` +### Q11: 先看哪个文档最合适? -2. **重新编译和安装**: - ```bash - ./script.sh - # 选择选项 [2]: Install SDK - ``` +- 想了解总体接入方式:看 `README.md` +- 想确认接口签名:看 `docs/API-Reference.md` +- 遇到构建或运行问题:看 `docs/TROUBLESHOOTING.md` -3. **或手动更新**: - ```bash - cd build - cmake .. - make - sudo make install - ``` +### Q12: 旧版参考目录还能直接当文档源吗? -如有其他问题,请参考 [故障排查指南](TROUBLESHOOTING.md) 或联系技术支持。 +不能。旧版目录只适合做历史对照,内容可能与当前命名空间、打包布局、构建开关不一致。对外发布请以 `linkerhand/` 和 `pack.sh` 产物为准。 diff --git a/docs/NAMING_IMPROVEMENTS.md b/docs/NAMING_IMPROVEMENTS.md deleted file mode 100644 index 745db8d..0000000 --- a/docs/NAMING_IMPROVEMENTS.md +++ /dev/null @@ -1,187 +0,0 @@ -# LinkerHand C++ SDK 命名规范改进指南 - -## 概述 - -本文档描述了 LinkerHand C++ SDK 的命名规范改进,这些改进旨在提高代码一致性、可维护性和可读性。 - -## 改进内容 - -### 1. 统一命名空间结构 - -所有手型号实现类已迁移到统一的 `linkerhand::hand` 命名空间: - -**改进前:** -```cpp -namespace LinkerHandL10 { - class LinkerHand : public linkerhand::hand::IHand { ... }; -} -``` - -**改进后:** -```cpp -namespace linkerhand { -namespace hand { - class L10Hand : public IHand { ... }; -} // namespace hand -} // namespace linkerhand -``` - -### 2. 类名改进 - -不同型号的手现在使用不同的类名,便于区分: - -| 型号 | 旧类名 | 新类名 | 命名空间 | -|------|--------|--------|---------| -| L6/O6 | `LinkerHandL6::LinkerHand` | `linkerhand::hand::L6Hand` | `linkerhand::hand` | -| L7 | `LinkerHandL7::LinkerHand` | `linkerhand::hand::L7Hand` | `linkerhand::hand` | -| L10 | `LinkerHandL10::LinkerHand` | `linkerhand::hand::L10Hand` | `linkerhand::hand` | -| L20 | `LinkerHandL20::LinkerHand` | `linkerhand::hand::L20Hand` | `linkerhand::hand` | -| L25/L21 | `LinkerHandL25::LinkerHand` | `linkerhand::hand::L25Hand` | `linkerhand::hand` | -| Modbus L10 | `ModbusLinkerHandL10::LinkerHand` | `linkerhand::hand::ModbusL10Hand` | `linkerhand::hand` | - -### 3. 帧属性枚举重命名和改进 - -各型号的帧属性枚举已重命名,使用更清晰的命名,并改为使用 `enum class` 以避免命名冲突: - -| 型号 | 旧枚举名 | 新枚举名 | -|------|---------|---------| -| L6/O6 | `LinkerHandL6::FRAME_PROPERTY` | `linkerhand::hand::L6FrameProperty` | -| L7 | `LinkerHandL7::FRAME_PROPERTY` | `linkerhand::hand::L7FrameProperty` | -| L10 | `LinkerHandL10::FRAME_PROPERTY` | `linkerhand::hand::L10FrameProperty` | -| L20 | `LinkerHandL20::FRAME_PROPERTY` | `linkerhand::hand::L20FrameProperty` | -| L25/L21 | `LinkerHandL25::FRAME_PROPERTY` | `linkerhand::hand::L25FrameProperty` | - -**重要改进**: -- 枚举类型从 `typedef enum` 改为 `enum class`(C++11 强类型枚举) -- 解决了多个枚举类型之间的命名冲突问题 -- 枚举值现在需要使用作用域限定符访问(如 `L6FrameProperty::JOINT_POSITION`) - -**使用示例**: -```cpp -// 旧方式(已废弃,但仍可通过向后兼容别名使用) -LinkerHandL6::FRAME_PROPERTY prop = LinkerHandL6::FRAME_PROPERTY::JOINT_POSITION; - -// 新方式(推荐) -linkerhand::hand::L6FrameProperty prop = linkerhand::hand::L6FrameProperty::JOINT_POSITION; - -// 转换为整数(用于 CAN 帧) -uint8_t frameProperty = static_cast(linkerhand::hand::L6FrameProperty::JOINT_POSITION); -``` - -### 4. 参数命名修正 - -修正了错误的参数命名: - -**改进前(错误)**: -```cpp -LinkerHandApi(const LINKER_HAND &handJoint, ...); -LINKER_HAND handJoint_; // 这是手型号,不是关节 -``` - -**改进后(正确)**: -```cpp -LinkerHandApi(const LINKER_HAND &handModel, ...); -LINKER_HAND handModel_; // 手型号(L6, L7, L10, L20, L21, L25 等) -``` - -**说明**: -- `handJoint` 命名不准确,因为这是手型号(Model),不是关节(Joint) -- 已统一修正为 `handModel`,更准确地表示手型号 - -## 向后兼容性 - -为了保持向后兼容,所有旧的命名空间和类名都通过 `using` 别名保留: - -```cpp -// 向后兼容:在旧命名空间中提供别名 -namespace LinkerHandL10 { - using FRAME_PROPERTY = linkerhand::hand::L10FrameProperty; - using LinkerHand = linkerhand::hand::L10Hand; -} // namespace LinkerHandL10 -``` - -这意味着现有代码可以继续使用旧的命名,无需立即修改。 - -## 使用示例 - -### 使用新命名(推荐) - -```cpp -#include "LinkerHandL10.h" -#include "HandFactory.h" - -// 使用新的命名空间和类名 -using namespace linkerhand; - -auto hand = factory::HandFactory::createHand( - LINKER_HAND::L10, - HAND_TYPE::RIGHT, - COMM_CAN_0 -); -// hand 的类型是 std::unique_ptr -// 实际类型是 hand::L10Hand -``` - -### 使用旧命名(向后兼容) - -```cpp -#include "LinkerHandL10.h" -#include "HandFactory.h" - -// 仍然可以使用旧的命名空间 -LinkerHandL10::LinkerHand hand(0x27, "can0", 1000000); -``` - -## 迁移建议 - -### 阶段一:保持兼容(当前) - -- ✅ 所有新命名已实现 -- ✅ 向后兼容别名已添加 -- ✅ 现有代码无需修改即可继续工作 - -### 阶段二:逐步迁移(推荐) - -1. **新代码使用新命名**:所有新编写的代码应使用新的命名空间和类名 -2. **更新文档和示例**:逐步更新文档和示例代码使用新命名 -3. **代码审查**:在代码审查中鼓励使用新命名 - -### 阶段三:完全迁移(未来) - -在未来版本中,可以考虑: -- 移除向后兼容别名(需要主版本号升级) -- 更新所有内部代码使用新命名 -- 更新所有文档和示例 - -## 优势 - -1. **一致性**:所有型号使用统一的命名空间结构 -2. **可读性**:类名直接反映型号(`L10Hand` vs `LinkerHand`) -3. **可维护性**:统一的命名空间便于管理和查找 -4. **扩展性**:新型号可以轻松添加到同一命名空间 - -## 注意事项 - -1. **工厂类**:`HandFactory` 已更新为使用新类名,但返回类型仍然是 `IHand` 接口 -2. **头文件**:头文件名暂时保持不变,未来可以考虑重命名 -3. **枚举**: - - 帧属性枚举已重命名,枚举值保持不变 - - 枚举类型已改为 `enum class`,需要使用作用域限定符访问枚举值 - - 这解决了多个枚举类型之间的命名冲突问题(如 `JOINT_POSITION`、`TORQUE_LIMIT` 等) - - 如果需要将枚举值转换为整数,使用 `static_cast()` - -## 相关文件 - -- `include/LinkerHandL6.h` - L6/O6 型号实现 -- `include/LinkerHandL7.h` - L7 型号实现 -- `include/LinkerHandL10.h` - L10 型号实现 -- `include/LinkerHandL20.h` - L20 型号实现 -- `include/LinkerHandL25.h` - L25/L21 型号实现 -- `include/ModbusLinkerHandL10.h` - Modbus L10 型号实现 -- `include/HandFactory.h` - 工厂类 - -## 版本信息 - -- **改进版本**:1.1.7+ -- **兼容性**:完全向后兼容 - diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 2578d46..b453d63 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -1,610 +1,132 @@ # 故障排查指南 -本文档提供 LinkerHand-CPP-SDK 常见问题的排查和解决方案。 +本文档覆盖发布包消费、源码构建、运行示例和通信联调中的常见问题。 -## 目录 +## 编译与配置 -- [编译问题](#编译问题) -- [运行时问题](#运行时问题) -- [通信问题](#通信问题) -- [API 使用问题](#api-使用问题) -- [性能问题](#性能问题) -- [获取帮助](#获取帮助) +### 1. `cmake ..` 失败或提示缺少依赖 ---- +先确认基础工具链和依赖: -## 编译问题 +```bash +cmake --version +g++ --version +pkg-config --modversion libusb-1.0 +``` -### 问题:找不到库文件 +如果构建网页示教器,还要确认 `Boost::system` 可用。只想先验证 SDK 本体时,可显式关闭示例和示教器: -**错误信息**: -``` -linkerhand_cpp_sdk library not found! +```bash +cmake -S linkerhand -B linkerhand/build -DBUILD_EXAMPLES=OFF -DBUILD_PENDANT=OFF +cmake --build linkerhand/build -j ``` -**可能原因**: -1. 库文件未正确安装 -2. 架构不匹配(x86_64 vs aarch64) -3. CMake 查找路径不正确 - -**解决方案**: -1. 检查库文件是否存在: - ```bash - ls -la lib/x86_64/ # 或 lib/aarch64/ - ``` +### 2. 找不到 `LinkerHandApi.h` 或 `CommFactory.h`(旧名 `CanBusFactory.h`) -2. 确认系统架构: - ```bash - uname -m - ``` +发布包消费和 install 消费的 include 路径不同: -3. 使用安装脚本重新安装: - ```bash - ./script.sh - # 选择选项 [2]: Install SDK - ``` +- 发布包:直接加 `include/`、`include/api`、`include/core`、`include/communication` +- install 后:加 `/include/linkerhand-cpp-sdk` 及其三个子目录 -4. 手动指定库路径(在 CMakeLists.txt 中): - ```cmake - set(LINKER_HAND_LIB ${CMAKE_CURRENT_SOURCE_DIR}/lib/x86_64/liblinkerhand_cpp_sdk.so) - ``` +若直接用发布包根目录 `CMakeLists.txt` 构建 examples,无需手动补这些路径。 ---- +### 3. 链接时报 `undefined reference` -### 问题:找不到头文件 +优先检查三件事: -**错误信息**: -``` -fatal error: LinkerHandApi.h: No such file or directory +```bash +ldd lib/linux/x86_64/linkerhand_cpp_sdk.so +file lib/linux/x86_64/linkerhand_cpp_sdk.so +uname -m ``` -**可能原因**: -1. 头文件路径未正确配置 -2. 头文件未安装 +- 架构必须匹配 +- Linux 侧还需要 `pthread` +- 如果手动链接,确认没有把 MinGW、MSVC、Linux 三种产物混用 + +### 4. Windows 下找不到 `PCANBasic.dll` -**解决方案**: -1. 检查头文件是否存在: - ```bash - ls -la include/LinkerHandApi.h - ``` +确认以下文件在运行时可被找到: -2. 在 CMakeLists.txt 中添加包含目录: - ```cmake - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) - ``` +- `linkerhand_cpp_sdk.dll` +- `PCANBasic.dll` -3. 如果已安装,检查安装路径: - ```bash - ls /usr/local/include/linkerhand-cpp-sdk/ - ``` +最稳妥的方式是把它们复制到最终 `.exe` 同目录。 ---- +## 运行与设备联调 -### 问题:链接错误 +### 5. 示例程序启动后无响应 -**错误信息**: +优先排查环境而不是盲改代码: + +```bash +ip link show can0 ``` -undefined reference to `LinkerHandApi::...` + +确认: + +- 机械手已上电 +- 设备名与示例中的总线名一致,例如 `can0` +- 波特率与现场配置一致,常见为 `1000000` + +若需要重新配置 CAN: + +```bash +sudo ip link set can0 down +sudo ip link set can0 type can bitrate 1000000 +sudo ip link set can0 up ``` -**可能原因**: -1. 未链接库文件 -2. 库文件版本不匹配 -3. 缺少依赖库(如 pthread) +### 6. CAN-FD 相关构建或运行异常 -**解决方案**: -1. 确保在 CMakeLists.txt 中链接库: - ```cmake - target_link_libraries(your_target ${LINKER_HAND_LIB} pthread) - ``` +O20 的 CAN-FD 主要面向 Linux `x86_64`。在 ARM + Ubuntu 18 及以下环境,顶层 CMake 会自动禁用 CAN-FD。先看配置日志里是否出现 `CANFD is disabled` 提示,再决定是换平台还是调整目标。 -2. 检查库文件完整性: - ```bash - ldd lib/x86_64/liblinkerhand_cpp_sdk.so - ``` +### 7. Modbus 无法通信 -3. 重新编译和安装 SDK +先确认不是代码问题: ---- +- 串口设备名是否正确,例如 `/dev/ttyUSB0` +- 当前用户是否有串口权限 +- 从站地址、波特率、校验位是否与设备一致 -### 问题:枚举命名冲突编译错误 +发布包中的 Modbus 示例可作为最小回归入口,先让示例通,再接自己的业务程序。 -**错误信息**: -``` -error: 'JOINT_POSITION' conflicts with a previous declaration -error: 'TORQUE_LIMIT' conflicts with a previous declaration -error: 'TOUCH_SENSOR_TYPE' conflicts with a previous declaration +### 8. EtherCAT 相关构建失败 + +`USE_ETHERCAT` 默认关闭。只有在现场确实需要时再打开: + +```bash +cmake -S linkerhand -B linkerhand/build -DUSE_ETHERCAT=ON ``` -**可能原因**: -在旧版本中,多个枚举类型(`L6FrameProperty`、`L7FrameProperty`、`L10FrameProperty` 等)使用 `typedef enum`,导致枚举值泄漏到外层命名空间,当多个头文件同时被包含时会发生命名冲突。 +打开后仍失败,先检查系统是否已安装 `libethercat` 和对应 `pkg-config` 信息,而不是直接修改源码。 -**解决方案**: -此问题已在最新版本中修复。所有枚举类型已改为使用 `enum class`(C++11 强类型枚举),每个枚举值都在自己的作用域内,不会发生命名冲突。 +## 打包与发布 -**如果使用旧版本**: -1. 升级到最新版本的 SDK -2. 如果必须使用旧版本,可以: - - 避免同时包含多个型号的头文件 - - 使用前向声明和单独编译单元 - - 使用命名空间别名隔离不同的枚举类型 +### 9. `./pack.sh pack` 后发布目录缺文件 -**新版本使用方式**: -```cpp -// 使用作用域限定符访问枚举值 -linkerhand::hand::L6FrameProperty prop = linkerhand::hand::L6FrameProperty::JOINT_POSITION; +先检查脚本自检输出。当前打包会显式校验: -// 转换为整数(用于 CAN 帧) -uint8_t frameProperty = static_cast(linkerhand::hand::L6FrameProperty::JOINT_POSITION); -``` +- `README.md` +- `docs/API-Reference.md` +- `docs/FAQ.md` +- `docs/TROUBLESHOOTING.md` +- `examples/CMakeLists.txt` +- `hand_teach_pendant/CMakeLists.txt` +- 各平台 `lib/` 目录是否生成库文件 ---- +如果缺的是某个平台库,先看对应 Docker 编译日志,而不是手动往发布目录补文件。 -### 问题:CMake 版本过低 +### 10. 发布包能直接代表 install 结果吗? -**错误信息**: -``` -CMake 3.5 or higher is required -``` +不能完全等同。发布包面向“解压即用”,会同时携带示例、示教器和通信层头文件;install 更偏系统集成与 `find_package` 消费。两者都来自同一主工作区,但用途不同。 + +### 11. 为什么不再从旧版参考目录复制文档? + +旧版目录长期手工维护,很多内容与当前仓库状态不再一致。现在的发布文档都应从 `linkerhand/docs/` 输出,由 `pack.sh` 直接复制,避免一边改代码、一边忘记同步旧目录。 + +## 排查原则 -**解决方案**: -1. 升级 CMake: - ```bash - # Ubuntu/Debian - sudo apt-get update - sudo apt-get install cmake - - # 或从源码编译最新版本 - ``` - -2. 检查 CMake 版本: - ```bash - cmake --version - ``` - ---- - -## 运行时问题 - -### 问题:程序崩溃或段错误 - -**可能原因**: -1. 通信接口未正确初始化 -2. 设备未连接 -3. 参数数组长度不匹配 -4. 内存访问错误 - -**解决方案**: -1. 检查设备连接: - ```bash - # CAN 总线 - ip link show can0 - cansend can0 123#DEADBEEF # 测试 CAN 通信 - ``` - -2. 检查参数数组长度: - ```cpp - // L10 需要 10 个元素 - if (pose.size() != 10) { - std::cerr << "错误: pose 数组长度应为 10" << std::endl; - return; - } - hand.fingerMove(pose); - ``` - -3. 使用调试工具: - ```bash - gdb ./your_program - # 或 - valgrind --leak-check=full ./your_program - ``` - -4. 添加错误检查: - ```cpp - try { - LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); - // ... - } catch (const std::exception& e) { - std::cerr << "错误: " << e.what() << std::endl; - } - ``` - ---- - -### 问题:设备无响应 - -**可能原因**: -1. 通信接口配置错误 -2. 设备未上电 -3. 通信协议不匹配 -4. 设备地址错误 - -**解决方案**: -1. 检查设备电源和连接 - -2. 验证通信接口: - ```cpp - // 尝试不同的通信接口 - LinkerHandApi hand1(LINKER_HAND::L10, HAND_TYPE::RIGHT, COMM_CAN_0); - LinkerHandApi hand2(LINKER_HAND::L10, HAND_TYPE::RIGHT, COMM_CAN_1); - LinkerHandApi hand3(LINKER_HAND::L10, HAND_TYPE::RIGHT, COMM_MODBUS); - LinkerHandApi hand4(LINKER_HAND::L10, HAND_TYPE::RIGHT, COMM_ETHERCAT); - ``` - -3. 检查通信接口状态: - - **CAN 总线**: - ```bash - # 查看 CAN 接口 - ip link show can0 - - # 启动 CAN 接口(如果未启动) - sudo ip link set can0 up type can bitrate 500000 - - # 监听 CAN 消息 - candump can0 - ``` - - **ModBus**: - - 检查串口设备或网络连接 - - 验证 ModBus 配置参数 - - **EtherCAT**: - - 使用 EtherCAT 主站工具检查网络状态 - - 验证从站配置和连接 - -4. 检查设备 ID 和地址设置 - ---- - -### 问题:关节不运动或运动异常 - -**可能原因**: -1. 速度和扭矩设置不当 -2. 参数值超出范围 -3. 电机故障 -4. 机械卡阻 - -**解决方案**: -1. 检查速度和扭矩设置: - ```cpp - // 设置合适的速度和扭矩 - std::vector speed = {200, 200, 200, 200, 200}; - std::vector torque = {255, 255, 255, 255, 255}; - hand.setSpeed(speed); - hand.setTorque(torque); - ``` - -2. 检查参数范围: - ```cpp - // 确保所有值在 0-255 范围内 - for (auto& val : pose) { - if (val > 255) val = 255; - if (val < 0) val = 0; - } - ``` - -3. 检查故障码: - ```cpp - auto fault_code = hand.getFaultCode(); - for (size_t i = 0; i < fault_code.size(); i++) { - if (fault_code[i] != 0) { - std::cout << "警告: 电机 " << i << " 故障码: " - << static_cast(fault_code[i]) << std::endl; - } - } - ``` - -4. 检查温度: - ```cpp - auto temperature = hand.getTemperature(); - for (size_t i = 0; i < temperature.size(); i++) { - if (temperature[i] > 80) { // 假设阈值 - std::cout << "警告: 电机 " << i << " 温度过高: " - << static_cast(temperature[i]) << std::endl; - } - } - ``` - ---- - -## 通信问题 - -### 问题:通信接口连接失败 - -**错误现象**: -- 设备无响应 -- 数据读取失败 -- 通信超时 - -**可能原因**: -- 通信接口未正确配置 -- 设备未连接或未上电 -- 通信协议不匹配 -- 权限问题 - -**解决方案**: -根据使用的通信协议,参考以下配置: - -### CAN 总线通信问题 - -**错误现象**: -- 设备无响应 -- 数据读取失败 -- 通信超时 - -**解决方案**: -1. **检查 CAN 接口配置**: - ```bash - # 查看 CAN 接口状态 - ip link show can0 - - # 配置 CAN 接口 - sudo ip link set can0 type can bitrate 500000 - sudo ip link set can0 up - ``` - -2. **检查 CAN 总线连接**: - ```bash - # 测试 CAN 通信 - cansend can0 123#DEADBEEF - candump can0 - ``` - -3. **检查权限**: - ```bash - # 可能需要 root 权限或添加用户到 dialout 组 - sudo usermod -a -G dialout $USER - # 重新登录后生效 - ``` - -4. **检查终端电阻**: - - CAN 总线两端需要 120Ω 终端电阻 - - 检查硬件连接 - -### ModBus 通信问题 - -**错误现象**: -- ModBus 连接失败 -- 数据读取超时 -- 串口权限错误 - -**解决方案**: -1. **检查串口权限**: - ```bash - # 添加用户到 dialout 组 - sudo usermod -a -G dialout $USER - # 重新登录后生效 - - # 检查串口设备 - ls -l /dev/ttyUSB* # USB 转串口 - ls -l /dev/ttyS* # 串口 - ``` - -2. **检查串口配置**: - - 确认串口设备路径正确 - - 检查波特率、数据位、停止位、校验位设置 - - 验证 ModBus 从站地址 - -3. **测试 ModBus 通信**: - - 使用 ModBus 测试工具验证连接 - - 检查网络连接(ModBus TCP/IP) - -### EtherCAT 通信问题 - -**错误现象**: -- EtherCAT 主站无法识别从站 -- 网络拓扑错误 -- 同步失败 - -**解决方案**: -1. **检查 EtherCAT 主站配置**: - - 确保 EtherCAT 主站软件已正确安装 - - 验证主站配置与硬件匹配 - -2. **检查网络拓扑**: - - 验证 EtherCAT 从站设备已正确连接 - - 检查网络线缆和连接器 - - 确认网络拓扑正确(环形或线性) - -3. **检查从站状态**: - - 使用 EtherCAT 主站工具检查从站状态 - - 验证从站配置和地址 - -4. **检查同步**: - - 确保 EtherCAT 网络同步正常 - - 检查分布式时钟(DC)配置(如适用) - ---- - -## API 使用问题 - -### 问题:参数数组长度错误 - -**错误现象**: -- 程序崩溃 -- 关节运动异常 -- 未定义行为 - -**解决方案**: -1. **根据型号使用正确的数组长度**: - ```cpp - std::vector pose; - - switch (hand.handModel_) { - case LINKER_HAND::L6: - case LINKER_HAND::O6: - pose.resize(6); - break; - case LINKER_HAND::L7: - pose.resize(7); - break; - case LINKER_HAND::L10: - pose.resize(10); - break; - case LINKER_HAND::L20: - pose.resize(20); - break; - case LINKER_HAND::L21: - case LINKER_HAND::L25: - pose.resize(25); - break; - } - ``` - -2. **添加参数验证**: - ```cpp - void safeFingerMove(LinkerHandApi& hand, const std::vector& pose) { - int expected_size = 0; - switch (hand.handModel_) { - case LINKER_HAND::L10: expected_size = 10; break; - case LINKER_HAND::L20: expected_size = 20; break; - // ... - } - - if (pose.size() != expected_size) { - std::cerr << "错误: 数组长度应为 " << expected_size - << ",实际为 " << pose.size() << std::endl; - return; - } - - hand.fingerMove(pose); - } - ``` - ---- - -### 问题:功能不支持 - -**错误现象**: -- 调用特定型号不支持的功能 -- 无响应或错误 - -**解决方案**: -1. **检查型号支持**: - ```cpp - // 仅 L20 支持 setCurrent - if (hand.handModel_ == LINKER_HAND::L20) { - hand.setCurrent(current); - } else { - std::cerr << "警告: setCurrent 仅支持 L20" << std::endl; - } - ``` - -2. **参考功能支持矩阵**: - - 查看 [API 参考文档](API-Reference.md#版本兼容性) - - 了解各型号支持的功能 - ---- - -### 问题:返回值理解错误 - -**错误现象**: -- 数据解析错误 -- 单位换算错误 - -**解决方案**: -1. **理解返回值格式**: - ```cpp - // getForce() 返回三维向量 - auto force = hand.getForce(); - // force[finger][sensor_type][data] - - // getTemperature() 返回温度值(可能需要换算) - auto temp = hand.getTemperature(); - // 具体换算方式请参考设备手册 - ``` - -2. **参考 API 文档**: - - 查看 [API 参考文档](API-Reference.md) 了解返回值格式 - - 参考设备手册了解数据含义 - ---- - -## 性能问题 - -### 问题:响应延迟 - -**可能原因**: -1. 通信延迟 -2. 处理速度慢 -3. 系统负载高 - -**解决方案**: -1. **优化通信频率**: - ```cpp - // 避免过于频繁的 API 调用 - // 添加适当的延时 - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - ``` - -2. **使用多线程**: - ```cpp - // 在单独线程中处理传感器数据 - std::thread sensor_thread([&hand]() { - while (running) { - auto force = hand.getForce(); - // 处理数据... - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } - }); - ``` - -3. **减少不必要的调用**: - - 缓存不需要实时更新的数据 - - 批量处理操作 - ---- - -### 问题:CPU 占用过高 - -**可能原因**: -1. 轮询频率过高 -2. 阻塞操作 -3. 资源泄漏 - -**解决方案**: -1. **降低轮询频率**: - ```cpp - // 从 10ms 改为 100ms - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - ``` - -2. **使用事件驱动**: - - 避免轮询,使用回调或事件 - - 仅在需要时读取数据 - -3. **检查资源管理**: - ```cpp - // 确保正确释放资源 - // 使用 RAII 原则 - ``` - ---- - -## 获取帮助 - -如果以上解决方案无法解决您的问题,请尝试以下方式获取帮助: - -1. **查看文档**: - - [API 参考文档](API-Reference.md) - - [常见问题解答](FAQ.md) - - [README](README.md) - -2. **检查示例代码**: - - 查看 `examples/` 目录下的示例 - - 参考示例代码的使用方式 - -3. **联系技术支持**: - - **官方网站**: [https://linkerbot.cn](https://linkerbot.cn) - - **技术支持**: [https://linkerbot.cn/aboutUs](https://linkerbot.cn/aboutUs) - - **GitHub Issues**: [https://github.com/linker-bot/linkerhand-cpp-sdk/issues](https://github.com/linker-bot/linkerhand-cpp-sdk/issues) - -4. **提供问题信息**: - 在寻求帮助时,请提供以下信息: - - 错误信息或日志 - - 系统信息(操作系统、架构) - - SDK 版本 - - 设备型号 - - 复现步骤 - - 相关代码片段 +- 连续编译或运行失败两次以上,先回看日志和环境,不继续盲试。 +- 先检查平台、依赖、设备名、库路径,再怀疑源码逻辑。 +- 对外发布只以 `linkerhand/` 当前内容和 `pack.sh` 生成物为准。 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..b1d9777 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,262 @@ +cmake_minimum_required(VERSION 3.10) +project(LinkerHandSDKExamples LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +if(MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /utf-8") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4275") + set(CMAKE_MSVC_SHOW_INCLUDES FALSE) +endif() + +option(BUILD_TESTS "Build test applications" ON) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +if(WIN32) + set(LIB_SUBDIR "win64") + set(LIB_EXTENSION ".dll") + + if(MSVC) + set(LIB_COMPILER_SUBDIR "msvc") + message(STATUS "Detected MSVC compiler") + elseif(MINGW) + set(LIB_COMPILER_SUBDIR "mingw") + message(STATUS "Detected MinGW compiler") + else() + message(WARNING "Unknown compiler on Windows, defaulting to msvc") + set(LIB_COMPILER_SUBDIR "msvc") + endif() +elseif(UNIX AND NOT APPLE) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") + set(LIB_SUBDIR "arm64") + else() + set(LIB_SUBDIR "x86_64") + endif() + set(LIB_EXTENSION ".so") +elseif(APPLE) + set(LIB_SUBDIR "x86_64") + set(LIB_EXTENSION ".dylib") +else() + message(WARNING "Unknown architecture, defaulting to x86_64") + set(LIB_SUBDIR "x86_64") + set(LIB_EXTENSION ".so") +endif() + +set(LINKERHAND_LIB_NAME "linkerhand_cpp_sdk") +set(LINKERHAND_DLL_NAME "${LINKERHAND_LIB_NAME}${LIB_EXTENSION}") + +# 嵌套模式:被主 CMake add_subdirectory 引入时,直接复用 SDK target,跳过 .so 路径搜索 +if(TARGET linkerhand_cpp_sdk) + set(LINKERHAND_AS_SUBPROJECT TRUE) + set(LINKERHAND_LIB linkerhand_cpp_sdk) + set(LINKERHAND_LIB_DIR "") + set(LINKERHAND_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../include") + set(LINKERHAND_DLL "$") + message(STATUS "examples: nested under main SDK build, link target linkerhand_cpp_sdk") +endif() + +if(NOT LINKERHAND_AS_SUBPROJECT) + +# 独立模式:通过 find_package 解析 SDK。 +# - 解压即用:examples/ 与 cmake/ 同处 release 顶层,把 release 根加进 PREFIX_PATH +# - 已安装(/usr/local 或自定义 prefix):CMake 自动搜系统 lib/cmake/ +# 也兼容用户用 -DCMAKE_PREFIX_PATH=... 或 -Dlinkerhand-cpp-sdk_DIR=... 指定。 +list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/..") +find_package(linkerhand-cpp-sdk 2.0 CONFIG REQUIRED) + +set(LINKERHAND_LIB LinkerHand::linkerhand_cpp_sdk) +set(LINKERHAND_INCLUDE_DIR "${linkerhand-cpp-sdk_INCLUDE_DIRS}") +set(LINKERHAND_LIB_DIR "${linkerhand-cpp-sdk_LIBRARY_DIR}") + +if(LINKERHAND_LIB_DIR) + if(WIN32 AND EXISTS "${LINKERHAND_LIB_DIR}/${LINKERHAND_DLL_NAME}") + set(LINKERHAND_DLL "${LINKERHAND_LIB_DIR}/${LINKERHAND_DLL_NAME}") + elseif(UNIX AND EXISTS "${LINKERHAND_LIB_DIR}/${LINKERHAND_DLL_NAME}") + set(LINKERHAND_DLL "${LINKERHAND_LIB_DIR}/${LINKERHAND_DLL_NAME}") + endif() +endif() + +endif() # NOT LINKERHAND_AS_SUBPROJECT + +message(STATUS "Found linkerhand_cpp_sdk library: ${LINKERHAND_LIB}") +message(STATUS "Found LinkerHand headers: ${LINKERHAND_INCLUDE_DIR}") + +include_directories( + ${LINKERHAND_INCLUDE_DIR} + ${LINKERHAND_INCLUDE_DIR}/api + ${LINKERHAND_INCLUDE_DIR}/hand + ${LINKERHAND_INCLUDE_DIR}/factory + ${LINKERHAND_INCLUDE_DIR}/communication + ${LINKERHAND_INCLUDE_DIR}/util + ${LINKERHAND_INCLUDE_DIR}/core +) + +if(WIN32) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../third_party/PCAN_Basic/Include) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../third_party/libcanbus/include/windows) +else() + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../third_party/libcanbus/include/linux) + + # Linux: 设置 libcanbus 库路径 + set(LIBCANBUS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/libcanbus/linux") + if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") + set(LIBCANBUS_DIR "${LIBCANBUS_DIR}/arm64") + else() + set(LIBCANBUS_DIR "${LIBCANBUS_DIR}/ubuntu22") + endif() + + # 添加库搜索路径 + link_directories(${LIBCANBUS_DIR}) + + # 设置运行时库路径,确保运行时能找到 libcanbus.so 与 SDK .so + set(CMAKE_INSTALL_RPATH "${LIBCANBUS_DIR}") + if(LINKERHAND_LIB_DIR) + list(APPEND CMAKE_INSTALL_RPATH "${LINKERHAND_LIB_DIR}") + endif() + set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) + + message(STATUS "libcanbus directory: ${LIBCANBUS_DIR}") +endif() + +# 兜底(独立消费已安装 SDK,且示例被拷出源码树):源码树 ../third_party 不存在时, +# 改从安装位置 /lib/linkerhand-cpp-sdk/third_party 找 CanFD/PCAN 的 third_party 头。 +# CanFD.h 暴露了 ::Dev_Info(来自 Hcanbus.h),任何 include 它的下游都得有这条路径。 +if(NOT LINKERHAND_AS_SUBPROJECT AND LINKERHAND_INCLUDE_DIR) + # 安装布局 LINKERHAND_INCLUDE_DIR = /include/linkerhand-cpp-sdk → 上溯两级得 + get_filename_component(_LH_PREFIX "${LINKERHAND_INCLUDE_DIR}" DIRECTORY) + get_filename_component(_LH_PREFIX "${_LH_PREFIX}" DIRECTORY) + set(_LH_INSTALLED_TP "${_LH_PREFIX}/lib/linkerhand-cpp-sdk/third_party") + if(WIN32) + if(EXISTS "${_LH_INSTALLED_TP}/PCAN_Basic/Include") + include_directories("${_LH_INSTALLED_TP}/PCAN_Basic/Include") + endif() + if(EXISTS "${_LH_INSTALLED_TP}/libcanbus/include/windows") + include_directories("${_LH_INSTALLED_TP}/libcanbus/include/windows") + endif() + elseif(EXISTS "${_LH_INSTALLED_TP}/libcanbus/include/linux") + include_directories("${_LH_INSTALLED_TP}/libcanbus/include/linux") + endif() +endif() + +function(copy_dependencies target) + if(LINKERHAND_AS_SUBPROJECT) + # 嵌套模式:用 generator expression 取主项目 SDK target 的产物 + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "$" + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + COMMENT "Copying linkerhand_cpp_sdk runtime to output directory" + ) + elseif(LINKERHAND_DLL AND EXISTS "${LINKERHAND_DLL}") + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${LINKERHAND_DLL}" + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + COMMENT "Copying ${LINKERHAND_DLL_NAME} to output directory" + ) + endif() + + if(WIN32) + set(PCAN_DLL "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/PCAN_Basic/x64/PCANBasic.dll") + if(EXISTS "${PCAN_DLL}") + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${PCAN_DLL}" + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + COMMENT "Copying PCANBasic.dll to output directory" + ) + endif() + + set(CANFD_DLL "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/libcanbus/windows/x64/HCanbus.dll") + if(EXISTS "${CANFD_DLL}") + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CANFD_DLL}" + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + COMMENT "Copying HCanbus.dll (CANFD) to output directory" + ) + endif() + + # 拷贝 mingw runtime DLL:SDK DLL 与 exe 必须共享同一份 libstdc++, + # 否则跨 DLL 边界传 std::string / std::vector 会因 allocator 不一致引发 + # heap corruption;exe 启动若找不到 runtime 也会被 Windows 静默终止。 + # win32 线程模型下 std::mutex / std::thread 用 Windows 原生 API, + # 不依赖 libwinpthread-1.dll,所以不在拷贝列表中。 + # 仅当 lib/win64/mingw/ 下存在这些 DLL 时拷贝(pack.sh 出品的 release 包带这些)。 + foreach(_RT_DLL libstdc++-6.dll libgcc_s_seh-1.dll) + set(_RT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../lib/win64/mingw/${_RT_DLL}") + if(EXISTS "${_RT_PATH}") + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${_RT_PATH}" + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + COMMENT "Copying ${_RT_DLL} (mingw runtime) to output directory" + ) + endif() + endforeach() + elseif(UNIX AND NOT APPLE) + # Linux: 复制 libcanbus.so 到输出目录 + set(CANBUS_SO "${LIBCANBUS_DIR}/libcanbus.so") + if(EXISTS "${CANBUS_SO}") + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CANBUS_SO}" + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + COMMENT "Copying libcanbus.so to output directory" + ) + endif() + + # Linux: 复制 libusb-1.0.so 到输出目录(libcanbus 的依赖) + set(LIBUSB_SO "${LIBCANBUS_DIR}/libusb-1.0.so") + if(EXISTS "${LIBUSB_SO}") + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${LIBUSB_SO}" + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + COMMENT "Copying libusb-1.0.so to output directory" + ) + endif() + endif() +endfunction() + +set(COMMON_LIBS ${LINKERHAND_LIB}) + +if(UNIX AND NOT APPLE) + find_package(Threads REQUIRED) + list(APPEND COMMON_LIBS Threads::Threads) +endif() + +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/main_demo.cpp") + add_executable(main_demo main_demo.cpp) + target_link_libraries(main_demo PRIVATE ${COMMON_LIBS}) + copy_dependencies(main_demo) +endif() + +if(BUILD_TESTS) + include(${CMAKE_CURRENT_SOURCE_DIR}/sources.cmake) + + set(EXAMPLE_STEMS ${LINKERHAND_EXAMPLES}) + if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") + list(APPEND EXAMPLE_STEMS ${LINKERHAND_EXAMPLES_CANFD}) + endif() + + foreach(stem ${EXAMPLE_STEMS}) + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${stem}.cpp") + get_filename_component(target "${stem}" NAME) + string(REPLACE ".cpp" "" target "${target}") + add_executable(${target} "${stem}.cpp") + target_link_libraries(${target} PRIVATE ${COMMON_LIBS}) + copy_dependencies(${target}) + endif() + endforeach() +endif() + +message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") +message(STATUS "Target platform: ${CMAKE_SYSTEM_NAME} ${LIB_SUBDIR}") +message(STATUS "Output directory: ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") diff --git a/examples/action_group_show_l10.cpp b/examples/L10/action_group_show.cpp similarity index 97% rename from examples/action_group_show_l10.cpp rename to examples/L10/action_group_show.cpp index 3298c38..f4843ff 100644 --- a/examples/action_group_show_l10.cpp +++ b/examples/L10/action_group_show.cpp @@ -1,6 +1,11 @@ -// 本demo为适配球形拇指根部关节版本L10灵巧手,默认支持右手,如需左手,请将 HAND_TYPE::RIGHT 改为 HAND_TYPE::LEFT +// L10 / CAN / 右手 —— 动作组状态机演示(球形拇指根部关节版本) +// 如需左手,请将 HAND_TYPE::RIGHT 改为 HAND_TYPE::LEFT #include +#include +#include +#include +#include #include "LinkerHandApi.h" using namespace std; @@ -417,7 +422,7 @@ vector showLeft() { int main() { // 调用API接口 - LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::LEFT); + LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); hand.setSpeed({100, 100, 100, 100, 100}); hand.setTorque({200, 200, 200, 200, 200}); @@ -428,4 +433,4 @@ int main() { } return 0; -} +} \ No newline at end of file diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index d325c9a..0000000 --- a/examples/README.md +++ /dev/null @@ -1,367 +0,0 @@ -# 示例代码说明 - -本文档介绍 LinkerHand-CPP-SDK 提供的示例代码及其使用方法。 - -## 目录 - -- [示例列表](#示例列表) -- [如何运行示例](#如何运行示例) -- [示例详细说明](#示例详细说明) -- [学习路径](#学习路径) -- [常见问题](#常见问题) - ---- - -## 示例列表 - -| 示例文件 | 功能描述 | 适用型号 | 难度 | -|---------|---------|---------|------| -| `toolset_example.cpp` | 交互式工具集,演示所有 API 功能 | 所有型号 | 中级 | -| `action_group_show_l10.cpp` | L10 型号的动作组演示 | L10 | 初级 | - ---- - -## 如何运行示例 - -### 方法一:使用安装脚本(推荐) - -```bash -./script.sh -# 选择选项 [6]: Run examples -``` - -### 方法二:手动编译和运行 - -```bash -# 1. 构建项目 -mkdir build && cd build -cmake .. -make - -# 2. 运行示例 -./toolset_example -./action_group_show_l10 -``` - -### 方法三:直接编译示例 - -```bash -# 编译 toolset_example -g++ -std=c++11 examples/toolset_example.cpp -I./include \ - -L./lib/x86_64 -llinkerhand_cpp_sdk -lpthread -o toolset_example - -# 运行 -./toolset_example -``` - ---- - -## 示例详细说明 - -### toolset_example.cpp - -**功能描述** -交互式工具集,提供菜单界面,可以测试所有 API 功能。适合学习和调试。 - -**主要功能**: -1. 获取版本信息 -2. 获取温度数据 -3. 获取故障码 -4. 获取电流数据 -5. 获取扭矩数据 -6. 获取速度数据 -7. 获取压力传感信息 -8. 循环获取关节状态 -9. 执行预设动作 -10. 清除故障码 - -**使用步骤**: -1. 运行程序 -2. 选择机械手型号(L6/O6、L7、L10、L20、L21、L25) -3. 选择手部方向(左手/右手) -4. 选择通信接口(CAN0、CAN1、ModBus、EtherCAT) -5. 进入交互菜单,选择要测试的功能 - -**代码结构**: -```cpp -// 1. 选择型号 -// 2. 选择手部方向 -// 3. 选择通信接口 -// 4. 创建 API 实例 -LinkerHandApi hand(linkerhand, handType, channel); - -// 5. 进入交互模式 -interactiveMode(hand); -``` - -**预设动作**: -- **L6**: 单指循环弯曲 -- **L7**: 握拳和张开 -- **L10**: - - 手指循环弯曲 - - 拇指与其他手指循环对指 - - 手指侧摆 - - 握拳和张开 -- **L20**: 握拳和张开 -- **L21/L25**: 握拳和张开 - -**使用示例**: -```bash -$ ./toolset_example - -========================= - Example -========================= - -Run Choose LinkerHand: -------------------------- -[1]: L6/O6 -------------------------- -[2]: L7 -------------------------- -[3]: L10 -------------------------- -... -``` - ---- - -### action_group_show_l10.cpp - -**功能描述** -专门为 L10 型号设计的动作组演示程序。展示如何实现连续的动作序列。 - -**主要功能**: -- 演示 L10 型号的各种动作组合 -- 展示动作序列的编程方式 -- 适合学习动作控制的基本方法 - -**适用型号**: L10(适配球形拇指根部关节版本) - -**代码特点**: -- 使用关节映射表管理关节状态 -- 实现动作序列的循环执行 -- 支持左右手(默认右手,修改 `HAND_TYPE::RIGHT` 为 `HAND_TYPE::LEFT` 可切换为左手) - -**关节映射**: -```cpp -// L10 关节顺序 -vector joint_order = { - "joint1", // 拇指根部弯曲 - "joint2", // 拇指侧摆 - "joint3", // 食指根部弯曲 - "joint4", // 中指根部弯曲 - "joint5", // 无名指根部弯曲 - "joint6", // 小指根部弯曲 - "joint7", // 食指侧摆 - "joint8", // 中指侧摆 - "joint9", // 无名指侧摆 - "joint10" // 拇指旋转 -}; -``` - -**使用示例**: -```bash -$ ./action_group_show_l10 -# 程序会自动执行预设的动作序列 -``` - -**注意事项**: -- 本示例仅支持 L10 型号 -- 默认使用右手,如需左手请修改代码中的 `HAND_TYPE::RIGHT` 为 `HAND_TYPE::LEFT` -- 确保设备已正确连接 -- 确保通信接口已正确配置(CAN 总线、ModBus 或 EtherCAT) - ---- - -## 学习路径 - -### 初学者 - -1. **第一步**: 阅读 [README.md](../README.md) 了解基本概念 -2. **第二步**: 运行 `action_group_show_l10.cpp` 查看基本动作 -3. **第三步**: 阅读代码,理解关节控制的基本方法 -4. **第四步**: 尝试修改代码,实现自己的动作 - -### 中级用户 - -1. **第一步**: 运行 `toolset_example.cpp` 熟悉所有 API -2. **第二步**: 阅读 [API 参考文档](../docs/API-Reference.md) 了解详细接口 -3. **第三步**: 参考示例代码实现自己的应用 -4. **第四步**: 学习传感器数据读取和处理 - -### 高级用户 - -1. **第一步**: 深入研究示例代码的实现细节 -2. **第二步**: 优化代码性能 -3. **第三步**: 实现复杂的动作序列 -4. **第四步**: 集成到自己的项目中 - ---- - -## 代码学习要点 - -### 1. 初始化 API - -```cpp -// 创建 API 实例 -LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); -``` - -### 2. 设置速度和扭矩 - -```cpp -// 设置速度(5 个元素对应 5 根手指) -std::vector speed = {200, 200, 200, 200, 200}; -hand.setSpeed(speed); - -// 设置扭矩 -std::vector torque = {255, 255, 255, 255, 255}; -hand.setTorque(torque); -``` - -### 3. 控制关节运动 - -```cpp -// L10 需要 10 个关节值 -std::vector pose = {128, 128, 128, 128, 128, 128, 128, 128, 128, 128}; -hand.fingerMove(pose); - -// 等待动作完成 -std::this_thread::sleep_for(std::chrono::seconds(1)); -``` - -### 4. 读取传感器数据 - -```cpp -// 获取压力数据 -auto force = hand.getForce(); - -// 获取关节状态 -auto state = hand.getState(); - -// 获取温度 -auto temperature = hand.getTemperature(); -``` - -### 5. 错误处理 - -```cpp -// 检查故障码 -auto fault_code = hand.getFaultCode(); -for (size_t i = 0; i < fault_code.size(); i++) { - if (fault_code[i] != 0) { - std::cout << "警告: 电机 " << i << " 故障码: " - << static_cast(fault_code[i]) << std::endl; - } -} -``` - ---- - -## 常见问题 - -### Q1: 示例程序无法运行? - -**A**: 检查以下几点: -1. 确保已正确编译 -2. 检查库文件路径是否正确 -3. 确保设备已连接 -4. 检查通信接口配置(CAN 总线等) - -详细排查请参考 [故障排查指南](../docs/TROUBLESHOOTING.md)。 - ---- - -### Q2: 如何修改示例代码适配其他型号? - -**A**: -1. 修改型号参数: - ```cpp - // 从 L10 改为 L20 - LinkerHandApi hand(LINKER_HAND::L20, HAND_TYPE::RIGHT); - ``` - -2. 修改关节数组长度: - ```cpp - // L20 需要 20 个关节值 - std::vector pose(20, 128); - ``` - -3. 参考 [关节映射表](../README.md#关节映射表) 了解不同型号的关节配置 - ---- - -### Q3: 如何实现自己的动作序列? - -**A**: -1. 定义动作数组: - ```cpp - std::vector> actions = { - {255, 104, 255, 255, 255, 255, 255, 255, 255, 71}, // 动作1 - {101, 60, 0, 0, 0, 0, 255, 255, 255, 51}, // 动作2 - // ... - }; - ``` - -2. 循环执行: - ```cpp - for (const auto& pose : actions) { - hand.fingerMove(pose); - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - ``` - ---- - -### Q4: 如何读取和处理传感器数据? - -**A**: 参考 `toolset_example.cpp` 中的示例: - -```cpp -// 获取压力数据 -auto force_data = hand.getForce(); - -// 遍历每根手指 -for (size_t finger = 0; finger < force_data.size(); finger++) { - // 处理数据... -} -``` - -详细说明请参考 [API 参考文档](../docs/API-Reference.md#getforce)。 - ---- - -### Q5: 示例代码中的延时时间如何设置? - -**A**: 延时时间取决于: -- 动作的复杂度 -- 设置的速度 -- 设备的响应时间 - -**建议**: -- 简单动作: 0.5-1 秒 -- 复杂动作: 1-2 秒 -- 连续动作: 根据实际效果调整 - -```cpp -// 快速动作 -std::this_thread::sleep_for(std::chrono::milliseconds(500)); - -// 标准动作 -std::this_thread::sleep_for(std::chrono::seconds(1)); - -// 慢速动作 -std::this_thread::sleep_for(std::chrono::seconds(2)); -``` - ---- - -## 下一步 - -- 阅读 [API 参考文档](../docs/API-Reference.md) 了解完整的 API -- 查看 [故障排查指南](../docs/TROUBLESHOOTING.md) 解决遇到的问题 -- 参考 [常见问题解答](../docs/FAQ.md) 获取更多帮助 -- 贡献您的示例代码到项目 - -如有问题,请参考 [故障排查指南](../docs/TROUBLESHOOTING.md) 或联系技术支持。 diff --git a/examples/_win_console_utf8.h b/examples/_win_console_utf8.h new file mode 100644 index 0000000..f04948e --- /dev/null +++ b/examples/_win_console_utf8.h @@ -0,0 +1,17 @@ +// 共享头:Windows 上把控制台输入/输出码页切到 UTF-8。 +// 源码里的中文字符串是 UTF-8(mingw/clang 默认;MSVC 由 /utf-8 保证), +// 控制台默认 GBK 会把 cout/cerr 的中文输出按错误码页解读 → 乱码,连带 +// 让 catch 块里的中文报错肉眼无法识别。 +// 通过匿名 namespace 静态对象在 main() 进入前完成初始化,example 只需 include 即可。 +#pragma once +#ifdef _WIN32 +#include +namespace { +struct _LhConsoleUtf8Init { + _LhConsoleUtf8Init() { + SetConsoleOutputCP(CP_UTF8); + SetConsoleCP(CP_UTF8); + } +} _lh_console_utf8_init; +} +#endif diff --git a/examples/toolset_example.cpp b/examples/linker_hand_example.cpp similarity index 66% rename from examples/toolset_example.cpp rename to examples/linker_hand_example.cpp index 96eb13e..2f5ef27 100644 --- a/examples/toolset_example.cpp +++ b/examples/linker_hand_example.cpp @@ -1,12 +1,23 @@ +// 全型号 / CAN·CAN-FD·Modbus —— 交互式功能巡检示例(菜单选择型号/手别/总线) #include #include #include #include #include #include +#include +#include +#include #include "LinkerHandApi.h" +#include "Modbus.h" -#include +#ifdef _WIN32 +#include "PCANBus.h" +#include "CanFD.h" +#else +#include "CanBus.h" +#include "CanFD.h" +#endif // 定义ANSI转义序列常量 const std::string RESET = "\033[0m"; @@ -70,12 +81,6 @@ void exit() { std::cout << "Exit the program ..." << std::endl; running = false; - std::string can_channel; - - if (channel == COMM_CAN_0) can_channel = "can0"; - if (channel == COMM_CAN_1) can_channel = "can1"; - - // system(std::string("sudo /usr/sbin/ip link set " + can_channel + " down").c_str()); exit(0); } @@ -187,6 +192,14 @@ std::vector L10_POSE_OPEN = {255, 104, 255, 255, 255, 255, 255, 255, 25 // L10 - 执行动作 - 握拳 std::vector L10_POSE_CLOSE = {101, 60, 0, 0, 0, 0, 255, 255, 255, 51}; +// O20 - 执行动作 - 张开/握拳 +std::vector O20_POSE_OPEN = { + 255, 255, 127, 255, 127, 255, 255, 127, 255, 255, 127, 255, 255, 127, 255, 255, 0 +}; +std::vector O20_POSE_CLOSE = { + 0, 0, 127, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0, 0 +}; + void interactiveMode(LinkerHandApi &hand) { int choice; @@ -198,24 +211,22 @@ void interactiveMode(LinkerHandApi &hand) std::cout << BLUE << " 1. Obtain version information\n" << RESET; std::cout << BLUE << " 2. Obtain temperature\n" << RESET; std::cout << BLUE << " 3. Obtain fault codes\n" << RESET; - std::cout << BLUE << " 4. Obtain current\n" << RESET; - std::cout << BLUE << " 5. Obtain torque\n" << RESET; - std::cout << BLUE << " 6. Obtain speed\n" << RESET; - std::cout << BLUE << " 7. Obtain pressure sensing information 1\n" << RESET; - std::cout << BLUE << " 8. Obtain pressure sensing information 2\n" << RESET; - std::cout << BLUE << " 9. Clear fault codes\n" << RESET; - std::cout << BLUE << "10. Loop to obtain the current finger joint status 10 times\n" << RESET; - std::cout << BLUE << "11. Execute preset actions\n" << RESET; - std::cout << RED << "0. Exit\n" << RESET; + std::cout << BLUE << " 4. Obtain torque\n" << RESET; + std::cout << BLUE << " 5. Obtain speed\n" << RESET; + std::cout << BLUE << " 6. Obtain pressure sensing information\n" << RESET; + std::cout << BLUE << " 7. Clear fault codes\n" << RESET; + std::cout << BLUE << " 8. Loop to obtain the current finger joint status 10 times\n" << RESET; + std::cout << BLUE << " 9. Execute preset actions\n" << RESET; + std::cout << RED << " 0. Exit\n" << RESET; printColorLine2(); std::cout << GREEN << "Please enter options: " << RESET; std::cin >> choice; + if (choice != 1) printNoColorLine(); std::string pose_str; - int arr[7]; std::vector pose; switch (choice) @@ -230,21 +241,18 @@ void interactiveMode(LinkerHandApi &hand) std::cout << "Obtain fault codes: " << bytesToHex(hand.getFaultCode()) << std::endl; break; case 4: - std::cout << "Obtain current: " << bytesToHex(hand.getCurrent()) << std::endl; - break; - case 5: std::cout << "Obtain torque: " << std::endl; - for (size_t i = 0; i < 10; i++) + for (size_t i = 0; i < 10; i++) { std::cout << bytesToHex(hand.getTorque()) << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } break; - case 6: + case 5: std::cout << "Obtain speed: " << bytesToHex(hand.getSpeed()) << std::endl; break; - case 7: - for (size_t i = 0; i < 30; i++) + case 6: + for (size_t i = 0; i < 30; i++) { std::vector>> touch_mats = hand.getForce(); // 手指名称表,顺序对应 touch_mats[0..4] @@ -266,24 +274,20 @@ void interactiveMode(LinkerHandApi &hand) std::this_thread::sleep_for(std::chrono::milliseconds(100)); } break; - case 8: - std::cout << "NULL \n" << std::endl; - break; - case 9: + case 7: std::cout << "Clear fault codes\n" << std::endl; hand.clearFaultCode(); break; - case 10: - for (size_t i = 0; i < 10; i++) + case 8: + for (size_t i = 0; i < 10; i++) { std::cout << bytesToHex(hand.getState()) << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } break; - case 11: - if (hand.handModel_ == LINKER_HAND::L6) { + case 9: + if (hand.handJoint_ == LINKER_HAND::L6) { std::cout << "L6 - Execute action" << std::endl; - for (size_t i = 0; i < 10; i++) { for (const auto &pose : L6_POSE_1) { hand.fingerMove(pose); @@ -291,9 +295,13 @@ void interactiveMode(LinkerHandApi &hand) } std::this_thread::sleep_for(std::chrono::milliseconds(150)); } - - - } else if (hand.handModel_ == LINKER_HAND::L7) { + } else if (hand.handJoint_ == LINKER_HAND::O6) { + std::cout << "O6 - Execute action" << std::endl; + for (const auto &pose : L6_POSE_1) { + hand.fingerMove(pose); + std::this_thread::sleep_for(std::chrono::milliseconds(1200)); + } + } else if (hand.handJoint_ == LINKER_HAND::L7) { hand.setSpeed(std::vector(7, HAND_SPEED)); // L7 need 7 speed hand.setTorque(std::vector(7, HAND_TORQUE)); // L7 need 7 torque //--------------------------------------------------------- @@ -309,10 +317,10 @@ void interactiveMode(LinkerHandApi &hand) std::this_thread::sleep_for(std::chrono::seconds(1)); //--------------------------------------------------------- } - else if (hand.handModel_ == LINKER_HAND::L10) + else if (hand.handJoint_ == LINKER_HAND::L10) { - hand.setSpeed(std::vector(5, HAND_SPEED)); // L10 need 5 speed - hand.setTorque(std::vector(5, HAND_TORQUE)); // L10 need 5 torque + hand.setSpeed(std::vector(10, HAND_SPEED)); // L10 need 10 speed + hand.setTorque(std::vector(10, HAND_TORQUE)); // L10 need 10 torque //--------------------------------------------------------- std::cout << "L10 - Execute action - Finger cycle bending" << std::endl; for (const auto &pose : L10_POSE_1) @@ -344,7 +352,7 @@ void interactiveMode(LinkerHandApi &hand) std::this_thread::sleep_for(std::chrono::seconds(1)); //--------------------------------------------------------- } - else if (hand.handModel_ == LINKER_HAND::L20) + else if (hand.handJoint_ == LINKER_HAND::L20) { hand.setSpeed(std::vector(5, HAND_SPEED)); // L20 need 5 speed //--------------------------------------------------------- @@ -358,7 +366,7 @@ void interactiveMode(LinkerHandApi &hand) hand.fingerMove(L20_POSE_OPEN); std::this_thread::sleep_for(std::chrono::seconds(1)); } - else if (hand.handModel_ == LINKER_HAND::L25 || hand.handModel_ == LINKER_HAND::L21) + else if (hand.handJoint_ == LINKER_HAND::L25 || hand.handJoint_ == LINKER_HAND::L21) { hand.setSpeed(std::vector(25, HAND_SPEED)); hand.setTorque(std::vector(25, HAND_TORQUE)); @@ -368,7 +376,7 @@ void interactiveMode(LinkerHandApi &hand) std::vector pos1_1 = {230, 0, 0, 15, 5, 250, 55, 80, 210, 202, 85, 0, 0, 0, 0, 250, 0, 40, 35, 5, 250, 0, 5, 0, 0}; std::vector pos1_2 = {80, 255, 255, 255, 255, 180, 51, 51, 72, 202, 202, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; std::vector pos1_3 = {75, 255, 255, 255, 255, 176, 51, 80, 210, 202, 202, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; - + // Make a fist std::vector pos2_1 = {230, 0, 0, 15, 5, 250, 55, 80, 210, 202, 85, 0, 0, 0, 0, 80, 0, 40, 35, 5, 250, 0, 5, 0, 0}; std::vector pos2_2 = {230, 0, 0, 15, 5, 42, 55, 80, 210, 202, 85, 0, 0, 0, 0, 90, 0, 40, 35, 5, 120, 0, 5, 0, 0}; @@ -388,20 +396,27 @@ void interactiveMode(LinkerHandApi &hand) hand.fingerMove(pos1_3); std::this_thread::sleep_for(std::chrono::seconds(1)); } - break; - case 12: - hand.setSpeed(std::vector(7, HAND_SPEED)); // L7 need 7 speed - hand.setTorque(std::vector(7, HAND_TORQUE)); // L7 need 7 torque - //--------------------------------------------------------- - - std::cout << "请输入" << 7 << "个整数:" << std::endl; - for (int i = 0; i < 7; ++i) { - std::cin >> arr[i]; - pose.push_back(arr[i]); + else if (hand.handJoint_ == LINKER_HAND::G20) + { + hand.setSpeed(std::vector(5, HAND_SPEED)); // L20 need 5 speed + //--------------------------------------------------------- + std::cout << "G20 - Execute action - Make a fist" << std::endl; + std::vector G20_POSE_CLOSE_1 = {255, 0, 0, 0, 0,255,255,178,84,0,255,255,0,0,0,0}; + hand.fingerMove(G20_POSE_CLOSE_1); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + std::vector G20_POSE_CLOSE_2 = {117, 0, 0, 0, 0,47,255,178,84,0,115,104,0,0,0,0}; + hand.fingerMove(G20_POSE_CLOSE_2); + std::this_thread::sleep_for(std::chrono::seconds(1)); + //--------------------------------------------------------- + std::cout << "G20 - Execute action - Open hand" << std::endl; + std::vector G20_POSE_OPEN = {255, 255, 255, 255, 255, 255, 255, 172, 74, 0, 255, 255, 255, 255, 255, 255}; + hand.fingerMove(G20_POSE_OPEN); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + else if (hand.handJoint_ == LINKER_HAND::O20) + { + std::cout << "暂无动作!" << std::endl; } - - hand.fingerMove(pose); - std::this_thread::sleep_for(std::chrono::seconds(1)); break; case 0: exit(); @@ -414,19 +429,24 @@ void interactiveMode(LinkerHandApi &hand) } } -int main() +int main(int argc, char *argv[]) { +#ifdef _WIN32 + // 设置控制台输出编码为 UTF-8,解决中文乱码问题 + SetConsoleOutputCP(CP_UTF8); +#endif + std::cout << YELLOW << "=========================\n" << RESET; std::cout << YELLOW << " Example\n" << RESET; std::cout << YELLOW << "=========================\n" << RESET; - + int choice; LINKER_HAND linkerhand; while (true) { std::cout << GREEN << "\nRun Choose LinkerHand:\n" << RESET; printColorLine1(); - std::cout << BLUE << "[1]: L6/O6\n" << RESET; + std::cout << BLUE << "[1]: L6\n" << RESET; printColorLine1(); std::cout << BLUE << "[2]: L7\n" << RESET; printColorLine1(); @@ -438,11 +458,17 @@ int main() printColorLine1(); std::cout << BLUE << "[6]: L25\n" << RESET; printColorLine1(); + std::cout << BLUE << "[7]: O6\n" << RESET; + printColorLine1(); + std::cout << BLUE << "[8]: G20\n" << RESET; + printColorLine1(); + std::cout << BLUE << "[9]: O20\n" << RESET; + printColorLine1(); std::cout << RED << "[0]: Exit\n" << RESET; printColorLine1(); std::cout << GREEN << "Please enter options: " << RESET; std::cin >> choice; - + switch (choice) { case 1: @@ -463,6 +489,15 @@ int main() case 6: linkerhand = LINKER_HAND::L25; break; + case 7: + linkerhand = LINKER_HAND::O6; + break; + case 8: + linkerhand = LINKER_HAND::G20; + break; + case 9: + linkerhand = LINKER_HAND::O20; + break; case 0: exit(); break; @@ -505,48 +540,157 @@ int main() } break; } - - while (true) - { - printColorLine2(); - std::cout << GREEN << "Run Choose CANBus:\n" << RESET; - printColorLine1(); - std::cout << BLUE << "[1]: CAN0\n" << RESET; - printColorLine1(); - std::cout << BLUE << "[2]: CAN1\n" << RESET; - printColorLine1(); - std::cout << BLUE << "[3]: EtherCAT\n" << RESET; - printColorLine1(); - std::cout << RED << "[0]: Exit\n" << RESET; - printColorLine1(); - std::cout << GREEN << "Please enter options: " << RESET; - std::cin >> choice; - switch (choice) + if (linkerhand == LINKER_HAND::O20) { + channel = COMM_TYPE::CAN; + std::cout << "O20 uses CANFD transport, skip bus selection." << std::endl; + } else { + while (true) { - case 1: - channel = COMM_CAN_0; - break; - case 2: - channel = COMM_CAN_1; - break; - case 3: - channel = COMM_ETHERCAT; - break; - case 0: - exit(); + printColorLine2(); + std::cout << GREEN << "Run Choose CANBus:\n" << RESET; + printColorLine1(); + std::cout << BLUE << "[1]: CAN\n" << RESET; + printColorLine1(); + std::cout << BLUE << "[2]: Modbus\n" << RESET; + printColorLine1(); + std::cout << BLUE << "[3]: EtherCAT\n" << RESET; + printColorLine1(); + std::cout << RED << "[0]: Exit\n" << RESET; + printColorLine1(); + std::cout << GREEN << "Please enter options: " << RESET; + std::cin >> choice; + + switch (choice) + { + case 1: + channel = COMM_TYPE::CAN; + break; + case 2: + channel = COMM_TYPE::MODBUS; + break; + case 3: + channel = COMM_TYPE::ETHERCAT; + break; + case 0: + exit(); + break; + default: + std::cout << "Invalid option, please re-enter!\n"; + continue; + } break; - default: - std::cout << "Invalid option, please re-enter!\n"; - continue; } - break; } // 调用API接口 LinkerHandApi hand(linkerhand, handType, channel); - // LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::RIGHT); +#ifdef _WIN32 + std::shared_ptr bus = nullptr; + std::shared_ptr canfd = nullptr; +#else + std::shared_ptr bus = nullptr; + std::shared_ptr canfd = nullptr; +#endif + std::shared_ptr modbus = nullptr; + + std::string channel_name; + + if (channel == COMM_TYPE::CAN) { + (argc > 1) ? channel_name = argv[1] : channel_name = "can0"; +#ifdef _WIN32 + TPCANHandle pcan_channel = PCAN_USBBUS1; + if (channel_name == "can1") pcan_channel = PCAN_USBBUS2; + else if (channel_name.find("PCAN_USBBUS") != std::string::npos) { + pcan_channel = static_cast(std::stoi(channel_name.substr(12)) + 0x20); + } + if (linkerhand == LINKER_HAND::O20) { + canfd = std::make_shared(0, 0); + if (!canfd->init()) { + std::cerr << "Failed to initialize CANFD" << std::endl; + return 1; + } + } else { + bus = std::make_shared(handType); + } +#else + if (linkerhand == LINKER_HAND::O20) { + canfd = std::make_shared(0, 0); + if (!canfd->init()) { + std::cerr << "Failed to initialize CANFD" << std::endl; + return 1; + } + } else { + bus = std::make_shared(handType); + } +#endif + + if (linkerhand == LINKER_HAND::O20) { + hand.setCanTxCallback([canfd](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + std::vector data_vec(data, data + data_len); + canfd->send(data_vec, can_id, true); + return 0; + }); + + hand.setCanRxCallback([canfd](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + try { + auto frame = canfd->recv(10); + if (!frame.valid) { + return -1; + } + *can_id_out = frame.can_id; + *len_out = Communication::CanFD::dlcToLen(frame.can_dlc); + memcpy(data_out, frame.data, *len_out); + return 0; + } catch (const std::exception& e) { + std::cerr << "CANFD接收错误: " << e.what() << std::endl; + return -1; + } + }); + } else { + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + try { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; + } + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + return 0; + } catch (const std::exception& e) { + std::cerr << "CAN接收错误: " << e.what() << std::endl; + return -1; + } + }); + } + } else if (channel == COMM_TYPE::MODBUS) { + (argc > 1) ? channel_name = argv[1] : channel_name = "/dev/ttyUSB0"; + modbus = std::make_shared(handType); + + hand.setModbusTxCallback([modbus](uint8_t sid, uint16_t addr, const uint8_t* data, uintptr_t len) -> int32_t { + if (!modbus) return -1; + return modbus->sendRawFrame(data, len) ? 0 : -1; + }); + + hand.setModbusRxCallback([modbus](uint8_t sid, uint16_t* addr_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + if (!modbus) return -1; + int len = modbus->receiveCompleteFrame(data_out, 256, 500); + if (len <= 0 || data_out[0] != sid) return -1; + *len_out = static_cast(len); + if (addr_out) *addr_out = 0; + return 0; + }); + } else if (channel == COMM_TYPE::ETHERCAT) { + std::cout << "EtherCAT 暂不支持 !" << std::endl; + } printNoColorLine(); // 启动交互模式 interactiveMode(hand); diff --git a/examples/sources.cmake b/examples/sources.cmake new file mode 100644 index 0000000..4145933 --- /dev/null +++ b/examples/sources.cmake @@ -0,0 +1,36 @@ +# 客户级示例源清单(相对 examples/ 根,不含 .cpp 扩展名)。 +# 嵌入构建(examples/CMakeLists.txt)与独立 CONFIG 构建(examples/standalone/)共用, +# 避免两处维护两份列表。新增示例只需在此登记一次。 + +# 平台无关示例(所有平台都构建) +set(LINKERHAND_EXAMPLES + test + test_0 + test_l10 + test_l10_can_0 + test_l10_can_1 + test_l10_modbus + test_l7_can_0 + test_l7_can_1 + test_l7_modbus_0 + test_l7_modbus_1 + test_l20_can_0 + test_l21_can_0 + test_g20_can_0 + test_g20_can_1 + test_o6_can_0 + test_o6_can_1 + test_o6_can_3 + test_o6_modbus_0 + test_o6_modbus_1 + test_o6_modbus_2 + L10/action_group_show + range_to_arc/range_to_arc +) + +# 需要 CanFD 支持的示例:仅在非 aarch64 的 Linux 上构建(与顶层 ENABLE_CANFD 逻辑一致) +set(LINKERHAND_EXAMPLES_CANFD + test_o20_canfd_0 + test_o20_canfd_1 + linker_hand_example +) diff --git a/examples/test.cpp b/examples/test.cpp new file mode 100644 index 0000000..33a9ecf --- /dev/null +++ b/examples/test.cpp @@ -0,0 +1,123 @@ +// L10 / CAN / 左手 —— 读取版本、力矩、速度、状态与触觉(带 TX/RX 日志) +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommFactory.h" + +// 格式化当前时间,用于 TX/RX 日志 +std::string getCurrentTime() { + auto now = std::chrono::system_clock::now(); + auto now_time = std::chrono::system_clock::to_time_t(now); + auto now_ms = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + + std::tm* tm = std::localtime(&now_time); + char buffer[80]; + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm); + + std::ostringstream oss; + oss << buffer << "." << std::setfill('0') << std::setw(3) << now_ms.count(); + return oss.str(); +} + +int main() { + try { + // 初始化灵巧手 + LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::LEFT); + + // 创建 CAN 总线对象 + std::shared_ptr bus = Communication::CommFactory::createCanBus("can0", 1000000); + + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + static int tx_count = 0; + tx_count++; + std::cout << "\033[32m[TX #" << tx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << can_id + << std::dec << " (" << can_id << ")" + << " | Len: " << data_len + << " | Data: "; + for (uintptr_t i = 0; i < data_len; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)data[i] << " "; + } + std::cout << std::dec << std::endl; + + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; + } + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + + static int rx_count = 0; + rx_count++; + std::cout << "\033[34m[RX #" << rx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << frame.can_id + << std::dec << " (" << frame.can_id << ")" + << " | DLC: " << (int)frame.can_dlc + << " | Data: "; + for (int i = 0; i < frame.can_dlc; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)frame.data[i] << " "; + } + std::cout << std::dec << std::endl; + return 0; + }); + + for (size_t i = 0; i < 3; ++i) { + std::cout << hand.getVersion() << std::endl; + + hand.setTorque({200,200,200,200,200,200,200,200,200,200}); + hand.setSpeed({200,200,200,200,200,200,200,200,200,200}); + + std::vector torque = hand.getTorque(); + std::cout << "torque size:" << torque.size() << std::endl; + for (size_t j = 0; j < torque.size(); j++) { + std::cout << (int)torque[j] << " "; + } + std::cout << std::endl; + + std::vector speed = hand.getSpeed(); + std::cout << "speed size:" << speed.size() << std::endl; + for (size_t j = 0; j < speed.size(); j++) { + std::cout << (int)speed[j] << " "; + } + std::cout << std::endl; + + std::vector state = hand.getState(); + std::cout << "state size:" << state.size() << std::endl; + for (size_t j = 0; j < state.size(); j++) { + std::cout << (int)state[j] << " "; + } + std::cout << std::endl; + + std::vector>> touch_mats = hand.getForce(); + // 手指名称表,顺序对应 touch_mats[0..4] + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + } + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_0.cpp b/examples/test_0.cpp new file mode 100644 index 0000000..47c2b2a --- /dev/null +++ b/examples/test_0.cpp @@ -0,0 +1,56 @@ +// L10 / CAN / 左手 —— 握拳与张开最小冒烟示例 +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommFactory.h" + +int main() { + try { + // 初始化灵巧手 + LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::LEFT, COMM_TYPE::CAN); + + // 创建 CAN 总线对象 + std::shared_ptr bus = Communication::CommFactory::createCanBus("can0", 1000000); + + // 设置 CAN 发送回调 + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + // 设置 CAN 接收回调 + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; + } + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + return 0; + }); + std::cout << "-------------------------------------------" << std::endl; + + std::cout << "获取版本信息:" << std::endl; + std::cout << hand.getVersion() << std::endl; + std::cout << "-------------------------------------------" << std::endl; + + std::cout << "执行动作:握拳" << std::endl; + std::vector fist_pose = {120, 60, 0, 0, 0, 0, 255, 255, 255, 51}; + hand.fingerMove(fist_pose); + std::this_thread::sleep_for(std::chrono::seconds(1)); + std::cout << "-------------------------------------------" << std::endl; + + std::cout << "执行动作:张开" << std::endl; + std::vector open_pose = {255, 104, 255, 255, 255, 255, 255, 255, 255, 71}; + hand.fingerMove(open_pose); + std::this_thread::sleep_for(std::chrono::seconds(1)); + std::cout << "-------------------------------------------" << std::endl; + + std::cout << "程序结束!" << std::endl; + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_g20_can_0.cpp b/examples/test_g20_can_0.cpp new file mode 100644 index 0000000..a736a4c --- /dev/null +++ b/examples/test_g20_can_0.cpp @@ -0,0 +1,94 @@ +// G20 / CAN / 左手 —— 握拳/张开动作循环 +#include +#include +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommFactory.h" + +#define HAND_SPEED 200 + +int main(int argc, char *argv[]) { + try { + std::cout << "=========================\n"; + std::cout << " G20 CAN Test\n"; + std::cout << "=========================\n"; + + std::string channel_name = "can0"; + if (argc > 1) { + channel_name = argv[1]; + } + + // 创建 CAN 总线对象(工厂按平台分流 SocketCAN / PCAN) + std::shared_ptr bus = Communication::CommFactory::createCanBus(channel_name, 1000000); + + // 创建 G20 手对象 + LinkerHandApi hand(LINKER_HAND::G20, HAND_TYPE::LEFT, COMM_TYPE::CAN); + + // 设置 CAN 发送回调 + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + // 设置 CAN 接收回调 + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; + } + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + return 0; + }); + + // 设置速度 + hand.setSpeed(std::vector(5, HAND_SPEED)); + + // 获取版本信息 + std::cout << "Version: " << hand.getVersion() << std::endl; + + // G20 握拳动作 + std::cout << "G20 - Execute action - Make a fist" << std::endl; + std::vector G20_POSE_CLOSE_1 = {255, 0, 0, 0, 0, 255, 255, 178, 84, 0, 255, 255, 0, 0, 0, 0}; + hand.fingerMove(G20_POSE_CLOSE_1); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + + std::vector G20_POSE_CLOSE_2 = {117, 0, 0, 0, 0, 47, 255, 178, 84, 0, 115, 104, 0, 0, 0, 0}; + hand.fingerMove(G20_POSE_CLOSE_2); + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // G20 张开动作 + std::cout << "G20 - Execute action - Open hand" << std::endl; + std::vector G20_POSE_OPEN = {255, 255, 255, 255, 255, 255, 255, 172, 74, 0, 255, 255, 255, 255, 255, 255}; + hand.fingerMove(G20_POSE_OPEN); + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // 循环测试 + for (int i = 0; i < 3; ++i) { + std::cout << "\nLoop " << i + 1 << ":\n"; + + // 握拳 + std::cout << "Make a fist..." << std::endl; + hand.fingerMove(G20_POSE_CLOSE_1); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + hand.fingerMove(G20_POSE_CLOSE_2); + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // 张开 + std::cout << "Open hand..." << std::endl; + hand.fingerMove(G20_POSE_OPEN); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + + std::cout << "\nTest completed!" << std::endl; + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_g20_can_1.cpp b/examples/test_g20_can_1.cpp new file mode 100644 index 0000000..d752a5e --- /dev/null +++ b/examples/test_g20_can_1.cpp @@ -0,0 +1,331 @@ +// G20 / CAN / 左手 —— 多线程并发测试(直连具体总线类的进阶示例) +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" + +#ifdef _WIN32 +#include "PCANBus.h" +#else +#include "CanBus.h" +#endif + +// 格式化当前时间,用于日志 +std::string getCurrentTime() { + auto now = std::chrono::system_clock::now(); + auto now_time = std::chrono::system_clock::to_time_t(now); + auto now_ms = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + + #if defined(_WIN32) || defined(_WIN64) + std::tm tm_info = {}; + localtime_s(&tm_info, &now_time); + std::tm* tm = &tm_info; + #else + std::tm* tm = std::localtime(&now_time); + #endif + char buffer[80]; + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm); + + std::ostringstream oss; + oss << buffer << "." << std::setfill('0') << std::setw(3) << now_ms.count(); + return oss.str(); +} + +// 全局互斥锁,用于控制输出顺序 +std::mutex cout_mutex; + +void printWithLock(const std::string& message) { + std::lock_guard lock(cout_mutex); + std::cout << message << std::endl; +} + +// 线程1:获取版本信息 +void threadGetVersion(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + std::string version = hand.getVersion(); + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread1-Iter" << iteration << "] 版本获取完成 (" << duration.count() << "ms): " << version; + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread1-Iter" << iteration << "] 版本获取失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程2:设置扭矩和速度 +void threadSetParameters(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + // G20 需要 5 个速度/扭矩值 + std::vector torque_values = {200, 200, 200, 200, 200}; + std::vector speed_values = {200, 200, 200, 200, 200}; + + hand.setTorque(torque_values); + hand.setSpeed(speed_values); + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread2-Iter" << iteration << "] 参数设置完成 (" << duration.count() << "ms)"; + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread2-Iter" << iteration << "] 参数设置失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程3:获取扭矩、速度、状态 +void threadGetParameters(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + std::vector torque; + std::vector speed; + std::vector state; + + // 并行获取三个参数 + auto future_torque = std::async(std::launch::async, [&hand]() { + return hand.getTorque(); + }); + + auto future_speed = std::async(std::launch::async, [&hand]() { + return hand.getSpeed(); + }); + + auto future_state = std::async(std::launch::async, [&hand]() { + return hand.getState(); + }); + + // 等待所有结果 + torque = future_torque.get(); + speed = future_speed.get(); + state = future_state.get(); + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread3-Iter" << iteration << "] 参数获取完成 (" << duration.count() << "ms)\n"; + ss << " 扭矩大小: " << torque.size() << " 数据: "; + for (size_t i = 0; i < torque.size() && i < 5; ++i) { + ss << (int)torque[i] << " "; + } + if (torque.size() > 5) ss << "..."; + + ss << "\n 速度大小: " << speed.size() << " 数据: "; + for (size_t i = 0; i < speed.size() && i < 5; ++i) { + ss << (int)speed[i] << " "; + } + if (speed.size() > 5) ss << "..."; + + ss << "\n 状态大小: " << state.size() << " 数据: "; + for (size_t i = 0; i < state.size() && i < 5; ++i) { + ss << (int)state[i] << " "; + } + if (state.size() > 5) ss << "..."; + + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread3-Iter" << iteration << "] 参数获取失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程4:获取压感数据 +void threadGetTouchData(LinkerHandApi& hand, int iteration) { + + for (int i = 0; i < 10; ++i) { + try { + auto start = std::chrono::steady_clock::now(); + + std::vector>> touch_mats = hand.getForce(); + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread4-Iter" << iteration << "] 压感数据获取完成 (" << duration.count() << "ms)"; + printWithLock(ss.str()); + + // 打印压感数据摘要 + for (size_t n = 0; n < touch_mats.size(); ++n) { + if (!touch_mats[n].empty()) { + std::stringstream ss2; + ss2 << " " << finger_name[n] << " 矩阵 " + << touch_mats[n].size() << "x" + << (touch_mats[n].empty() ? 0 : touch_mats[n][0].size()) + << " 第一个值: " << (int)touch_mats[n][0][0]; + printWithLock(ss2.str()); + } + } + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread4-Iter" << iteration << "] 压感获取失败: " << e.what(); + printWithLock(ss.str()); + } +} +} + +// 线程5:G20运动控制(握拳和张开) +void threadMotionControl(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + // G20 握拳动作(两步) + std::vector G20_POSE_CLOSE_1 = {255, 0, 0, 0, 0, 255, 255, 178, 84, 0, 255, 255, 0, 0, 0, 0}; + hand.fingerMove(G20_POSE_CLOSE_1); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + + std::vector G20_POSE_CLOSE_2 = {117, 0, 0, 0, 0, 47, 255, 178, 84, 0, 115, 104, 0, 0, 0, 0}; + hand.fingerMove(G20_POSE_CLOSE_2); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + // G20 张开动作 + std::vector G20_POSE_OPEN = {255, 255, 255, 255, 255, 255, 255, 172, 74, 0, 255, 255, 255, 255, 255, 255}; + hand.fingerMove(G20_POSE_OPEN); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread5-Iter" << iteration << "] G20运动控制完成 (" << duration.count() << "ms)"; + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread5-Iter" << iteration << "] 运动控制失败: " << e.what(); + printWithLock(ss.str()); + } +} + +int main() { + try { + std::cout << "=========================\n"; + std::cout << " G20 CAN 多线程测试\n"; + std::cout << "=========================\n"; + + // 创建 CAN 总线对象 +#ifdef _WIN32 + std::shared_ptr bus = std::make_shared(PCAN_USBBUS1, PCAN_BAUD_1M); +#else + std::shared_ptr bus = std::make_shared("can0", 1000000); +#endif + + // 创建 G20 手对象 + LinkerHandApi hand(LINKER_HAND::G20, HAND_TYPE::LEFT, COMM_TYPE::CAN); + + // 设置 CAN 发送回调 + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + // 设置 CAN 接收回调 + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + try { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; + } + + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + + return 0; + } catch (const std::exception& e) { + std::cerr << "CAN接收错误: " << e.what() << std::endl; + return -1; + } + }); + + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + std::cout << "=== 开始多线程并发测试 ===\n"; + auto total_start = std::chrono::steady_clock::now(); + + for (size_t iter = 0; iter < 3; ++iter) { + printWithLock("\n=== 迭代 " + std::to_string(iter + 1) + " ==="); + auto iter_start = std::chrono::steady_clock::now(); + + // 创建并启动所有线程 + std::vector threads; + + // 线程1:获取版本 + threads.emplace_back(threadGetVersion, std::ref(hand), iter + 1); + + // 线程2:设置参数 + threads.emplace_back(threadSetParameters, std::ref(hand), iter + 1); + + // 线程3:获取参数 + threads.emplace_back(threadGetParameters, std::ref(hand), iter + 1); + + // 线程4:获取压感 + threads.emplace_back(threadGetTouchData, std::ref(hand), iter + 1); + + // 线程5:运动控制 + threads.emplace_back(threadMotionControl, std::ref(hand), iter + 1); + + // 等待所有线程完成 + for (auto& t : threads) { + if (t.joinable()) { + t.join(); + } + } + + auto iter_end = std::chrono::steady_clock::now(); + auto iter_duration = std::chrono::duration_cast(iter_end - iter_start); + + std::stringstream ss; + ss << "迭代 " << iter + 1 << " 完成,耗时: " << iter_duration.count() << "ms"; + printWithLock(ss.str()); + + // 迭代之间等待100ms + if (iter < 2) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + } + + auto total_end = std::chrono::steady_clock::now(); + auto total_duration = std::chrono::duration_cast(total_end - total_start); + + std::cout << "\n=== 测试完成 ===\n"; + std::cout << "总耗时: " << total_duration.count() << "ms\n"; + std::cout << "平均每迭代: " << total_duration.count() / 3.0 << "ms\n"; + + // 等待一段时间确保所有回调完成 + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_l10.cpp b/examples/test_l10.cpp new file mode 100644 index 0000000..8b2715a --- /dev/null +++ b/examples/test_l10.cpp @@ -0,0 +1,53 @@ +// L10 / CAN / 左手 —— 入门最小示例(版本、单次动作、状态) +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommFactory.h" + +int main() { + try { + // 初始化灵巧手 + LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::LEFT, COMM_TYPE::CAN); + + // 创建 CAN 总线对象 + std::shared_ptr bus = Communication::CommFactory::createCanBus("can0", 1000000); + + // 设置 CAN 发送回调 + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + // 设置 CAN 接收回调 + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; + } + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + return 0; + }); + + // 打印版本信息 + std::cout << "版本: " << hand.getVersion() << std::endl; + + // 执行一次握拳动作 + std::vector fist_pose = {101, 60, 0, 0, 0, 0, 255, 255, 255, 51}; + hand.fingerMove(fist_pose); + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // 读取并打印当前状态 + std::vector state = hand.getState(); + std::cout << "state size: " << state.size() << std::endl; + for (size_t i = 0; i < state.size(); ++i) { + std::cout << (int)state[i] << " "; + } + std::cout << std::endl; + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_l10_can_0.cpp b/examples/test_l10_can_0.cpp new file mode 100644 index 0000000..d6d40c8 --- /dev/null +++ b/examples/test_l10_can_0.cpp @@ -0,0 +1,129 @@ +// L10 / CAN / 左手 —— 读取版本、力矩、速度、状态与触觉(带 TX/RX 日志) +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommFactory.h" + +// 格式化当前时间,用于 TX/RX 日志 +std::string getCurrentTime() { + auto now = std::chrono::system_clock::now(); + auto now_time = std::chrono::system_clock::to_time_t(now); + auto now_ms = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + + #if defined(_WIN32) || defined(_WIN64) + std::tm tm_info = {}; + localtime_s(&tm_info, &now_time); + std::tm* tm = &tm_info; + #else + std::tm* tm = std::localtime(&now_time); + #endif + char buffer[80]; + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm); + + std::ostringstream oss; + oss << buffer << "." << std::setfill('0') << std::setw(3) << now_ms.count(); + return oss.str(); +} + +int main() { + try { + // 初始化灵巧手 + LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::LEFT); + + // 创建 CAN 总线对象 + std::shared_ptr bus = Communication::CommFactory::createCanBus("can0", 1000000); + + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + static int tx_count = 0; + tx_count++; + std::cout << "\033[32m[TX #" << tx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << can_id + << std::dec << " (" << can_id << ")" + << " | Len: " << data_len + << " | Data: "; + for (uintptr_t i = 0; i < data_len; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)data[i] << " "; + } + std::cout << std::dec << std::endl; + + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; + } + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + + static int rx_count = 0; + rx_count++; + std::cout << "\033[34m[RX #" << rx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << frame.can_id + << std::dec << " (" << frame.can_id << ")" + << " | DLC: " << (int)frame.can_dlc + << " | Data: "; + for (int i = 0; i < frame.can_dlc; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)frame.data[i] << " "; + } + std::cout << std::dec << std::endl; + return 0; + }); + + for (size_t i = 0; i < 3; ++i) { + std::cout << hand.getVersion() << std::endl; + + hand.setTorque({200,200,200,200,200,200,200,200,200,200}); + hand.setSpeed({200,200,200,200,200,200,200,200,200,200}); + + std::vector torque = hand.getTorque(); + std::cout << "torque size:" << torque.size() << std::endl; + for (size_t j = 0; j < torque.size(); j++) { + std::cout << (int)torque[j] << " "; + } + std::cout << std::endl; + + std::vector speed = hand.getSpeed(); + std::cout << "speed size:" << speed.size() << std::endl; + for (size_t j = 0; j < speed.size(); j++) { + std::cout << (int)speed[j] << " "; + } + std::cout << std::endl; + + std::vector state = hand.getState(); + std::cout << "state size:" << state.size() << std::endl; + for (size_t j = 0; j < state.size(); j++) { + std::cout << (int)state[j] << " "; + } + std::cout << std::endl; + + std::vector>> touch_mats = hand.getForce(); + // 手指名称表,顺序对应 touch_mats[0..4] + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + } + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_l10_can_1.cpp b/examples/test_l10_can_1.cpp new file mode 100644 index 0000000..1f52501 --- /dev/null +++ b/examples/test_l10_can_1.cpp @@ -0,0 +1,374 @@ +// L10 / CAN / 左手 —— 多线程并发测试(版本/参数/触觉/运动并行) +#include +#include +#include +#include +#include +#include +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommFactory.h" + +// 格式化当前时间,用于 TX/RX 日志 +std::string getCurrentTime() { + auto now = std::chrono::system_clock::now(); + auto now_time = std::chrono::system_clock::to_time_t(now); + auto now_ms = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + + #if defined(_WIN32) || defined(_WIN64) + std::tm tm_info = {}; + localtime_s(&tm_info, &now_time); + std::tm* tm = &tm_info; + #else + std::tm* tm = std::localtime(&now_time); + #endif + char buffer[80]; + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm); + + std::ostringstream oss; + oss << buffer << "." << std::setfill('0') << std::setw(3) << now_ms.count(); + return oss.str(); +} + +// 全局互斥锁,用于控制输出顺序 +std::mutex cout_mutex; + +void printWithLock(const std::string& message) { + std::lock_guard lock(cout_mutex); + std::cout << message << std::endl; +} + +// 线程1:获取版本信息(独立运行,不依赖其他数据) +void threadGetVersion(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + std::string version = hand.getVersion(); + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread1-Iter" << iteration << "] 版本获取完成 (" << duration.count() << "ms): " << version; + printWithLock(ss.str()); + + // 版本获取后等待3ms + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread1-Iter" << iteration << "] 版本获取失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程2:设置扭矩和速度(这两个可以并行) +void threadSetParameters(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + // 同时设置扭矩和速度 + std::vector torque_values = {200,200,200,200,200,200,200,200,200,200}; + std::vector speed_values = {200,200,200,200,200,200,200,200,200,200}; + + hand.setTorque(torque_values); + // 设置扭矩后等待3ms + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); + + hand.setSpeed(speed_values); + // 设置速度后等待3ms + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread2-Iter" << iteration << "] 参数设置完成 (" << duration.count() << "ms)"; + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread2-Iter" << iteration << "] 参数设置失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程3:获取扭矩、速度、状态(这些可以并行获取) +void threadGetParameters(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + std::vector torque; + std::vector speed; + std::vector state; + + // 并行获取三个参数 + auto future_torque = std::async(std::launch::async, [&hand]() { + return hand.getTorque(); + }); + + auto future_speed = std::async(std::launch::async, [&hand]() { + return hand.getSpeed(); + }); + + auto future_state = std::async(std::launch::async, [&hand]() { + return hand.getState(); + }); + + // 等待所有结果 + torque = future_torque.get(); + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); // 获取扭矩后等待3ms + + speed = future_speed.get(); + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); // 获取速度后等待3ms + + state = future_state.get(); + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); // 获取状态后等待3ms + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread3-Iter" << iteration << "] 参数获取完成 (" << duration.count() << "ms)\n"; + ss << " 扭矩大小: " << torque.size() << " 数据: "; + for (size_t i = 0; i < torque.size() && i < 5; ++i) { + ss << (int)torque[i] << " "; + } + if (torque.size() > 5) ss << "..."; + + ss << "\n 速度大小: " << speed.size() << " 数据: "; + for (size_t i = 0; i < speed.size() && i < 5; ++i) { + ss << (int)speed[i] << " "; + } + if (speed.size() > 5) ss << "..."; + + ss << "\n 状态大小: " << state.size() << " 数据: "; + for (size_t i = 0; i < state.size() && i < 5; ++i) { + ss << (int)state[i] << " "; + } + if (state.size() > 5) ss << "..."; + + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread3-Iter" << iteration << "] 参数获取失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程4:获取压感数据(5个手指可以并行获取) +void threadGetTouchData(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + std::vector>> touch_mats = hand.getForce(); + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) + { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread4-Iter" << iteration << "] 压感数据获取完成 (" << duration.count() << "ms)"; + printWithLock(ss.str()); + + // 打印压感数据 + for (size_t n = 0; n < touch_mats.size(); ++n) { + if (!touch_mats[n].empty()) { + std::stringstream ss2; + ss2 << " " << finger_name[n] << " 矩阵 " + << touch_mats[n].size() << "x" + << (touch_mats[n].empty() ? 0 : touch_mats[n][0].size()) + << " 第一个值: " << (int)touch_mats[n][0][0]; + printWithLock(ss2.str()); + } + } + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread4-Iter" << iteration << "] 压感获取失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程5:运动控制(握拳和张开) +void threadMotionControl(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + // 握拳 + std::vector fist_pose = {101, 60, 0, 0, 0, 0, 255, 255, 255, 51}; + hand.fingerMove(fist_pose); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + // 张开 + std::vector open_pose = {255, 104, 255, 255, 255, 255, 255, 255, 255, 71}; + hand.fingerMove(open_pose); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread5-Iter" << iteration << "] 运动控制完成 (" << duration.count() << "ms)"; + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread5-Iter" << iteration << "] 运动控制失败: " << e.what(); + printWithLock(ss.str()); + } +} + +int main() { + try { + + // 调用API接口 + LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::LEFT); + + // 创建CAN总线对象用于通信 + std::shared_ptr bus = Communication::CommFactory::createCanBus("can0", 1000000); + + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + + // 打印发送信息 + std::cout << "\033[32m[TX #" << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << can_id + << std::dec << " (" << can_id << ")" + << " | Len: " << data_len + << " | Data: "; + + // 打印数据 + for (uintptr_t i = 0; i < data_len; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') + << (int)data[i] << " "; + } + std::cout << std::dec << std::endl; + + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + try { + auto frame = bus->recv(); + // 检查是否为空帧 + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; // 忽略空帧 + } + + // 填充输出参数 + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + // 添加安全检查以避免缓冲区溢出 + if (frame.can_dlc <= 8) { // CAN帧的最大数据长度为8字节 + memcpy(data_out, frame.data, frame.can_dlc); + } else { + return -1; // 数据长度超出范围 + } + + + static int rx_count = 0; + rx_count++; + + // 打印接收信息 + std::cout << "\033[34m[RX #" << rx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << frame.can_id + << std::dec << " (" << frame.can_id << ")" + << " | DLC: " << (int)frame.can_dlc + << " | Data: "; + + // 打印数据 + for (int i = 0; i < frame.can_dlc; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') + << (int)frame.data[i] << " "; + } + std::cout << std::dec << std::endl; + + + return 0; // 成功 + } catch (const std::exception& e) { + std::cerr << "CAN接收错误: " << e.what() << std::endl; + return -1; // 失败 + } + }); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + std::cout << "=== 开始多线程并发测试 ===\n"; + auto total_start = std::chrono::steady_clock::now(); + + for (size_t iter = 0; iter < 1; ++iter) { + printWithLock("\n=== 迭代 " + std::to_string(iter + 1) + " ==="); + auto iter_start = std::chrono::steady_clock::now(); + + // 创建并启动所有线程 + std::vector threads; + + // 线程1:获取版本 + threads.emplace_back(threadGetVersion, std::ref(hand), iter + 1); + + // 线程2:设置参数 + threads.emplace_back(threadSetParameters, std::ref(hand), iter + 1); + + // 线程3:获取参数 + threads.emplace_back(threadGetParameters, std::ref(hand), iter + 1); + + // 线程4:获取压感 + threads.emplace_back(threadGetTouchData, std::ref(hand), iter + 1); + + // 线程5:运动控制 + threads.emplace_back(threadMotionControl, std::ref(hand), iter + 1); + + // 等待所有线程完成 + for (auto& t : threads) { + if (t.joinable()) { + t.join(); + } + } + + auto iter_end = std::chrono::steady_clock::now(); + auto iter_duration = std::chrono::duration_cast(iter_end - iter_start); + + std::stringstream ss; + ss << "迭代 " << iter + 1 << " 完成,耗时: " << iter_duration.count() << "ms"; + printWithLock(ss.str()); + + // 迭代之间等待100ms + if (iter < 2) { // 修改循环次数判断 + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + } + + auto total_end = std::chrono::steady_clock::now(); + auto total_duration = std::chrono::duration_cast(total_end - total_start); + + std::cout << "\n=== 测试完成 ===\n"; + std::cout << "总耗时: " << total_duration.count() << "ms\n"; + std::cout << "平均每迭代: " << total_duration.count() / 3.0 << "ms\n"; // 修改平均计算 + + // 等待一段时间确保所有回调完成 + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} \ No newline at end of file diff --git a/examples/test_l10_modbus.cpp b/examples/test_l10_modbus.cpp new file mode 100644 index 0000000..ac992a9 --- /dev/null +++ b/examples/test_l10_modbus.cpp @@ -0,0 +1,227 @@ +// L10 / Modbus / 左手 —— 速度/扭矩/动作序列与各类状态读取 +#include +#include +#include +#include +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "Modbus.h" + +// 全局 Modbus 设备实例 +static std::unique_ptr g_modbus = nullptr; + +// 辅助函数:打印向量数据 +void printVector(const std::string& label, const std::vector& vec) { + std::cout << label << ": ["; + for (size_t i = 0; i < vec.size(); ++i) { + std::cout << static_cast(vec[i]); + if (i < vec.size() - 1) std::cout << ", "; + } + std::cout << "]" << std::endl; +} + +// 辅助函数:打印版本信息 +void printVersion(const std::string& version) { + std::cout << "版本信息:" << std::endl; + std::cout << version << std::endl; +} + +// 核心:设置回调函数 +void setupHandCallbacks(LinkerHandApi& hand) { + hand.setModbusTxCallback([](uint8_t sid, uint16_t addr, const uint8_t* data, uintptr_t len) -> int32_t { + if (!g_modbus) return -1; + return g_modbus->sendRawFrame(data, len) ? 0 : -1; + }); + + hand.setModbusRxCallback([](uint8_t sid, uint16_t* addr_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + if (!g_modbus) return -1; + int len = g_modbus->receiveCompleteFrame(data_out, 256, 500); + if (len <= 0 || data_out[0] != sid) return -1; + *len_out = static_cast(len); + if (addr_out) *addr_out = 0; + return 0; + }); +} + +int main(int argc, char* argv[]) { + const char* port = (argc > 1) ? argv[1] : "/dev/ttyUSB0"; + + // 1. 初始化 Modbus 设备 + g_modbus = std::make_unique(port, 115200); + if (!g_modbus->isOpen()) { + std::cerr << "串口打开失败,退出。" << std::endl; + return -1; + } + + // 2. 初始化手部 API + try { + LinkerHandApi hand(LINKER_HAND::L10, HAND_TYPE::LEFT, COMM_TYPE::MODBUS); + + // 3. 设置回调函数 + setupHandCallbacks(hand); + + std::cout << "初始化完成!" << std::endl; + std::cout << std::endl; + + // 测试 1: 设置速度 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 1: 设置速度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector speed(10, 128); // 10个关节,速度值 128 (L10有10个关节) + hand.setSpeed(speed); + printVector("设置速度", speed); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << std::endl; + + // 测试 2: 设置扭矩 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 2: 设置扭矩" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector torque(10, 200); // 10个关节,扭矩值 200 + hand.setTorque(torque); + printVector("设置扭矩", torque); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << std::endl; + + // 测试 3: 手指动作序列 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 3: 手指动作序列" << std::endl; + std::cout << "----------------------------------------" << std::endl; + + // L10 有 10 个关节: 大拇指弯曲、大拇指偏航、食指弯曲、中指弯曲、无名指弯曲、小拇指弯曲、食指偏航、无名指偏航、小拇指偏航、大拇指翻转 + std::vector> poses = { + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, // 完全张开 + {0, 255, 255, 255, 255, 255, 255, 255, 255, 255}, // 大拇指弯曲 + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255}, // 大拇指偏航 + {255, 255, 0, 255, 255, 255, 255, 255, 255, 255}, // 食指弯曲 + {255, 255, 255, 0, 255, 255, 255, 255, 255, 255}, // 中指弯曲 + {255, 255, 255, 255, 0, 255, 255, 255, 255, 255}, // 无名指弯曲 + {255, 255, 255, 255, 255, 0, 255, 255, 255, 255}, // 小拇指弯曲 + {255, 255, 255, 255, 255, 255, 0, 255, 255, 255}, // 食指偏航 + {255, 255, 255, 255, 255, 255, 255, 0, 255, 255}, // 无名指偏航 + {255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, // 小拇指偏航 + {255, 255, 255, 255, 255, 255, 255, 255, 255, 0}, // 大拇指翻转 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 握拳 + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255} // 完全张开 + }; + + for (size_t i = 0; i < poses.size(); ++i) { + std::cout << "动作 " << (i + 1) << "/" << poses.size() << ": "; + printVector("位置", poses[i]); + hand.fingerMove(poses[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + std::cout << std::endl; + + // 测试 4: 读取当前状态 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 4: 读取当前状态" << std::endl; + std::cout << "----------------------------------------" << std::endl; + for (int i = 0; i < 5; ++i) { + std::vector state = hand.getState(); + if (!state.empty()) { + printVector("当前关节位置", state); + } else { + std::cout << "读取状态失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + std::cout << std::endl; + + // 测试 5: 读取速度 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 5: 读取速度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector current_speed = hand.getSpeed(); + if (!current_speed.empty()) { + printVector("当前速度", current_speed); + } else { + std::cout << "读取速度失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 6: 读取扭矩 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 6: 读取扭矩" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector current_torque = hand.getTorque(); + if (!current_torque.empty()) { + printVector("当前扭矩", current_torque); + } else { + std::cout << "读取扭矩失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 7: 读取温度 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 7: 读取温度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector temperature = hand.getTemperature(); + if (!temperature.empty()) { + printVector("电机温度", temperature); + } else { + std::cout << "读取温度失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 8: 读取故障码 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 8: 读取故障码" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector fault_code = hand.getFaultCode(); + if (!fault_code.empty()) { + printVector("故障码", fault_code); + } else { + std::cout << "读取故障码失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 9: 读取版本信息 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 9: 读取版本信息" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::string version = hand.getVersion(); + if (!version.empty()) { + printVersion(version); + } else { + std::cout << "读取版本信息失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 10: 读取压感数据 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 10: 读取压感数据" << std::endl; + std::cout << "----------------------------------------" << std::endl; + for (int i = 0; i < 3; ++i) { + std::vector>> touch_mats = hand.getForce(); + // 手指名称表,顺序对应 touch_mats[0..4] + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) + { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + std::cout << "========================================" << std::endl; + std::cout << "L10 测试完成!" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << std::endl; + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} \ No newline at end of file diff --git a/examples/test_l20_can_0.cpp b/examples/test_l20_can_0.cpp new file mode 100644 index 0000000..e2a170f --- /dev/null +++ b/examples/test_l20_can_0.cpp @@ -0,0 +1,136 @@ +// L20 / CAN / 左手 —— 读取状态/触觉并执行握拳与张开(带 TX/RX 日志) +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommFactory.h" + +// 格式化当前时间,用于 TX/RX 日志 +std::string getCurrentTime() { + auto now = std::chrono::system_clock::now(); + auto now_time = std::chrono::system_clock::to_time_t(now); + auto now_ms = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + + #if defined(_WIN32) || defined(_WIN64) + std::tm tm_info = {}; + localtime_s(&tm_info, &now_time); + std::tm* tm = &tm_info; + #else + std::tm* tm = std::localtime(&now_time); + #endif + char buffer[80]; + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm); + + std::ostringstream oss; + oss << buffer << "." << std::setfill('0') << std::setw(3) << now_ms.count(); + return oss.str(); +} + +int main() { + try { + // 初始化灵巧手 + LinkerHandApi hand(LINKER_HAND::L20, HAND_TYPE::LEFT); + + // 创建 CAN 总线对象 + std::shared_ptr bus = Communication::CommFactory::createCanBus("can0", 1000000); + + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + static int tx_count = 0; + tx_count++; + std::cout << "\033[32m[TX #" << tx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << can_id + << std::dec << " (" << can_id << ")" + << " | Len: " << data_len + << " | Data: "; + for (uintptr_t i = 0; i < data_len; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)data[i] << " "; + } + std::cout << std::dec << std::endl; + + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; + } + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + + static int rx_count = 0; + rx_count++; + std::cout << "\033[34m[RX #" << rx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << frame.can_id + << std::dec << " (" << frame.can_id << ")" + << " | DLC: " << (int)frame.can_dlc + << " | Data: "; + for (int i = 0; i < frame.can_dlc; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)frame.data[i] << " "; + } + std::cout << std::dec << std::endl; + return 0; + }); + + for (size_t i = 0; i < 1; ++i) { + std::cout << hand.getVersion() << std::endl; + + std::vector torque = hand.getTorque(); + std::cout << "torque size:" << torque.size() << std::endl; + for (size_t j = 0; j < torque.size(); j++) { + std::cout << (int)torque[j] << " "; + } + std::cout << std::endl; + + std::vector speed = hand.getSpeed(); + std::cout << "speed size:" << speed.size() << std::endl; + for (size_t j = 0; j < speed.size(); j++) { + std::cout << (int)speed[j] << " "; + } + std::cout << std::endl; + + std::vector state = hand.getState(); + std::cout << "state size:" << state.size() << std::endl; + for (size_t j = 0; j < state.size(); j++) { + std::cout << (int)state[j] << " "; + } + std::cout << std::endl; + + std::vector>> touch_mats = hand.getForce(); + // 手指名称表,顺序对应 touch_mats[0..4] + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + + // 握拳 + std::vector fist_pose = {74, 0, 0, 0, 0, 176, 52, 120, 150, 201, 198, 0, 0, 0, 0, 254, 0, 0, 0, 0, 100, 0, 0, 0, 0}; + hand.fingerMove(fist_pose); + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // 张开 + std::vector open_pose = {74, 254, 254, 254, 253, 176, 52, 120, 150, 201, 198, 0, 0, 0, 0, 254, 0, 0, 0, 0, 254, 255, 255, 255, 250}; + hand.fingerMove(open_pose); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_l21_can_0.cpp b/examples/test_l21_can_0.cpp new file mode 100644 index 0000000..8b3bc9a --- /dev/null +++ b/examples/test_l21_can_0.cpp @@ -0,0 +1,136 @@ +// L21 / CAN / 左手 —— 读取状态/触觉并执行握拳与张开(带 TX/RX 日志) +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommFactory.h" + +// 格式化当前时间,用于 TX/RX 日志 +std::string getCurrentTime() { + auto now = std::chrono::system_clock::now(); + auto now_time = std::chrono::system_clock::to_time_t(now); + auto now_ms = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + + #if defined(_WIN32) || defined(_WIN64) + std::tm tm_info = {}; + localtime_s(&tm_info, &now_time); + std::tm* tm = &tm_info; + #else + std::tm* tm = std::localtime(&now_time); + #endif + char buffer[80]; + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm); + + std::ostringstream oss; + oss << buffer << "." << std::setfill('0') << std::setw(3) << now_ms.count(); + return oss.str(); +} + +int main() { + try { + // 初始化灵巧手 + LinkerHandApi hand(LINKER_HAND::L21, HAND_TYPE::LEFT); + + // 创建 CAN 总线对象 + std::shared_ptr bus = Communication::CommFactory::createCanBus("can0", 1000000); + + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + static int tx_count = 0; + tx_count++; + std::cout << "\033[32m[TX #" << tx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << can_id + << std::dec << " (" << can_id << ")" + << " | Len: " << data_len + << " | Data: "; + for (uintptr_t i = 0; i < data_len; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)data[i] << " "; + } + std::cout << std::dec << std::endl; + + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; + } + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + + static int rx_count = 0; + rx_count++; + std::cout << "\033[34m[RX #" << rx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << frame.can_id + << std::dec << " (" << frame.can_id << ")" + << " | DLC: " << (int)frame.can_dlc + << " | Data: "; + for (int i = 0; i < frame.can_dlc; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)frame.data[i] << " "; + } + std::cout << std::dec << std::endl; + return 0; + }); + + for (size_t i = 0; i < 1; ++i) { + std::cout << hand.getVersion() << std::endl; + + std::vector torque = hand.getTorque(); + std::cout << "torque size:" << torque.size() << std::endl; + for (size_t j = 0; j < torque.size(); j++) { + std::cout << (int)torque[j] << " "; + } + std::cout << std::endl; + + std::vector speed = hand.getSpeed(); + std::cout << "speed size:" << speed.size() << std::endl; + for (size_t j = 0; j < speed.size(); j++) { + std::cout << (int)speed[j] << " "; + } + std::cout << std::endl; + + std::vector state = hand.getState(); + std::cout << "state size:" << state.size() << std::endl; + for (size_t j = 0; j < state.size(); j++) { + std::cout << (int)state[j] << " "; + } + std::cout << std::endl; + + std::vector>> touch_mats = hand.getForce(); + // 手指名称表,顺序对应 touch_mats[0..4] + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + + // 握拳 + std::vector fist_pose = {74, 0, 0, 0, 0, 176, 52, 120, 150, 201, 198, 0, 0, 0, 0, 254, 0, 0, 0, 0, 100, 0, 0, 0, 0}; + hand.fingerMove(fist_pose); + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // 张开 + std::vector open_pose = {74, 254, 254, 254, 253, 176, 52, 120, 150, 201, 198, 0, 0, 0, 0, 254, 0, 0, 0, 0, 254, 255, 255, 255, 250}; + hand.fingerMove(open_pose); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_l7_can_0.cpp b/examples/test_l7_can_0.cpp new file mode 100644 index 0000000..8e9aad4 --- /dev/null +++ b/examples/test_l7_can_0.cpp @@ -0,0 +1,128 @@ +// L7 / CAN / 右手 —— 读取版本/状态/速度/扭矩/温度/故障码/触觉 +#include +#include +#include +#include +#include +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommFactory.h" + +int main() { + try { + // 创建 CAN 总线对象 + std::shared_ptr canBus = Communication::CommFactory::createCanBus("can0", 1000000); + + LinkerHandApi hand(LINKER_HAND::L7, HAND_TYPE::RIGHT); + std::cout << "LinkerHandL7 Real CAN Test Program" << std::endl; + + // 设置 CAN 发送回调 + hand.setCanTxCallback([canBus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + std::vector dataVec(data, data + data_len); + canBus->send(dataVec, can_id); + return 0; + }); + + // 设置 CAN 接收回调 + hand.setCanRxCallback([canBus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* data_len_out) -> int32_t { + auto frame = canBus->recv(); + if (frame.can_dlc > 0) { + *can_id_out = frame.can_id; + *data_len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + std::cout << "Received frame: can_id=" << frame.can_id << ", data="; + for (int i = 0; i < frame.can_dlc; ++i) { + std::cout << std::hex << (int)frame.data[i] << " "; + } + std::cout << std::dec << std::endl; + return 0; + } + return -1; + }); + + // 等待连接建立 + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // 获取版本信息 + std::cout << "Version Info:" << std::endl; + std::cout << hand.getVersion() << std::endl; + + // 获取当前状态 + std::cout << "Getting current status..." << std::endl; + auto currentStatus = hand.getState(); + std::cout << "Current status: "; + for (auto pos : currentStatus) { + std::cout << (int)pos << " "; + } + std::cout << std::endl; + + // 设置速度(7 个关节) + std::vector speeds = {255, 255, 255, 255, 255, 255, 255}; + std::cout << "Setting joint speeds..." << std::endl; + hand.setSpeed(speeds); + + std::cout << "Getting current speeds..." << std::endl; + auto currentSpeeds = hand.getSpeed(); + std::cout << "Current speeds: "; + for (auto speed : currentSpeeds) { + std::cout << (int)speed << " "; + } + std::cout << std::endl; + + // 设置扭矩(7 个关节) + std::vector torques = {255, 255, 255, 255, 255, 255, 255}; + std::cout << "Setting torques..." << std::endl; + hand.setTorque(torques); + + std::cout << "Getting current torques..." << std::endl; + auto currentTorques = hand.getTorque(); + std::cout << "Current torques: "; + for (auto torque : currentTorques) { + std::cout << (int)torque << " "; + } + std::cout << std::endl; + + // 获取温度信息 + std::cout << "Getting temperature..." << std::endl; + auto temperatures = hand.getTemperature(); + std::cout << "Temperatures: "; + for (auto temp : temperatures) { + std::cout << (int)temp << " "; + } + std::cout << std::endl; + + // 获取故障码 + std::cout << "Getting fault codes..." << std::endl; + auto faultCodes = hand.getFaultCode(); + std::cout << "Fault codes: "; + for (auto code : faultCodes) { + std::cout << (int)code << " "; + } + std::cout << std::endl; + + // 获取压力数据 + std::cout << "Getting force data..." << std::endl; + std::vector>> touch_mats = hand.getForce(); + // 手指名称表,顺序对应 touch_mats[0..4] + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH"}; + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) { + for (uint8_t val : row) + std::cout << std::setw(3) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + + std::cout << "Test completed successfully!" << std::endl; + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_l7_can_1.cpp b/examples/test_l7_can_1.cpp new file mode 100644 index 0000000..6cd5b81 --- /dev/null +++ b/examples/test_l7_can_1.cpp @@ -0,0 +1,377 @@ +// L7 / CAN / 右手 —— 多线程并发测试(版本/参数/触觉/运动并行) +#include +#include +#include +#include +#include +#include +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommFactory.h" + +// 格式化当前时间,用于 TX/RX 日志 +std::string getCurrentTime() { + auto now = std::chrono::system_clock::now(); + auto now_time = std::chrono::system_clock::to_time_t(now); + auto now_ms = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + + #if defined(_WIN32) || defined(_WIN64) + std::tm tm_info = {}; + localtime_s(&tm_info, &now_time); + std::tm* tm = &tm_info; + #else + std::tm* tm = std::localtime(&now_time); + #endif + char buffer[80]; + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm); + + std::ostringstream oss; + oss << buffer << "." << std::setfill('0') << std::setw(3) << now_ms.count(); + return oss.str(); +} + +// 全局互斥锁,用于控制输出顺序 +std::mutex cout_mutex; + +void printWithLock(const std::string& message) { + std::lock_guard lock(cout_mutex); + std::cout << message << std::endl; +} + +// 线程1:获取版本信息(独立运行,不依赖其他数据) +void threadGetVersion(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + std::string version = hand.getVersion(); + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread1-Iter" << iteration << "] 版本获取完成 (" << duration.count() << "ms): " << version; + printWithLock(ss.str()); + + // 版本获取后等待3ms + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread1-Iter" << iteration << "] 版本获取失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程2:设置扭矩和速度(这两个可以并行) +void threadSetParameters(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + // 同时设置扭矩和速度 + std::vector torque_values = {200,200,200,200,200,200,200,}; + std::vector speed_values = {200,200,200,200,200,200,200}; + + hand.setTorque(torque_values); + // 设置扭矩后等待3ms + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); + + hand.setSpeed(speed_values); + // 设置速度后等待3ms + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread2-Iter" << iteration << "] 参数设置完成 (" << duration.count() << "ms)"; + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread2-Iter" << iteration << "] 参数设置失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程3:获取扭矩、速度、状态(这些可以并行获取) +void threadGetParameters(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + std::vector torque; + std::vector speed; + std::vector state; + + // 并行获取三个参数 + auto future_torque = std::async(std::launch::async, [&hand]() { + return hand.getTorque(); + }); + + auto future_speed = std::async(std::launch::async, [&hand]() { + return hand.getSpeed(); + }); + + auto future_state = std::async(std::launch::async, [&hand]() { + return hand.getState(); + }); + + // 等待所有结果 + torque = future_torque.get(); + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); // 获取扭矩后等待3ms + + speed = future_speed.get(); + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); // 获取速度后等待3ms + + state = future_state.get(); + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); // 获取状态后等待3ms + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread3-Iter" << iteration << "] 参数获取完成 (" << duration.count() << "ms)\n"; + ss << " 扭矩大小: " << torque.size() << " 数据: "; + for (size_t i = 0; i < torque.size() && i < 5; ++i) { + ss << (int)torque[i] << " "; + } + if (torque.size() > 5) ss << "..."; + + ss << "\n 速度大小: " << speed.size() << " 数据: "; + for (size_t i = 0; i < speed.size() && i < 5; ++i) { + ss << (int)speed[i] << " "; + } + if (speed.size() > 5) ss << "..."; + + ss << "\n 状态大小: " << state.size() << " 数据: "; + for (size_t i = 0; i < state.size() && i < 5; ++i) { + ss << (int)state[i] << " "; + } + if (state.size() > 5) ss << "..."; + + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread3-Iter" << iteration << "] 参数获取失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程4:获取压感数据(5个手指可以并行获取) +void threadGetTouchData(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + std::vector>> touch_mats = hand.getForce(); + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) + { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread4-Iter" << iteration << "] 压感数据获取完成 (" << duration.count() << "ms)"; + printWithLock(ss.str()); + + // 打印压感数据 + for (size_t n = 0; n < touch_mats.size(); ++n) { + if (!touch_mats[n].empty()) { + std::stringstream ss2; + ss2 << " " << finger_name[n] << " 矩阵 " + << touch_mats[n].size() << "x" + << (touch_mats[n].empty() ? 0 : touch_mats[n][0].size()) + << " 第一个值: " << (int)touch_mats[n][0][0]; + printWithLock(ss2.str()); + } + } + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread4-Iter" << iteration << "] 压感获取失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程5:运动控制(握拳和张开) +void threadMotionControl(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + // 握拳 + std::vector fist_pose = {255, 255, 0, 0, 0, 0, 255}; + hand.fingerMove(fist_pose); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + // 张开 + std::vector open_pose = {255, 255, 255, 255, 255, 255, 255}; + hand.fingerMove(open_pose); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread5-Iter" << iteration << "] 运动控制完成 (" << duration.count() << "ms)"; + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread5-Iter" << iteration << "] 运动控制失败: " << e.what(); + printWithLock(ss.str()); + } +} + +int main() { + try { + + // 调用API接口 + LinkerHandApi hand(LINKER_HAND::L7, HAND_TYPE::RIGHT); + + // 创建CAN总线对象用于通信 + std::shared_ptr bus = Communication::CommFactory::createCanBus("can0", 1000000); + + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + + // 打印发送信息 + std::cout << "\033[32m[TX #" << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << can_id + << std::dec << " (" << can_id << ")" + << " | Len: " << data_len + << " | Data: "; + + // 打印数据 + for (uintptr_t i = 0; i < data_len; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') + << (int)data[i] << " "; + } + std::cout << std::dec << std::endl; + + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + try { + + // 接收CAN帧 + auto frame = bus->recv(); + + // 检查是否为空帧 + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; // 忽略空帧 + } + + // 填充输出参数 + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + // 添加安全检查以避免缓冲区溢出 + if (frame.can_dlc <= 8) { // CAN帧的最大数据长度为8字节 + memcpy(data_out, frame.data, frame.can_dlc); + } else { + return -1; // 数据长度超出范围 + } + + + static int rx_count = 0; + rx_count++; + + // 打印接收信息 + std::cout << "\033[34m[RX #" << rx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << frame.can_id + << std::dec << " (" << frame.can_id << ")" + << " | DLC: " << (int)frame.can_dlc + << " | Data: "; + + // 打印数据 + for (int i = 0; i < frame.can_dlc; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') + << (int)frame.data[i] << " "; + } + std::cout << std::dec << std::endl; + + + return 0; // 成功 + } catch (const std::exception& e) { + std::cerr << "CAN接收错误: " << e.what() << std::endl; + return -1; // 失败 + } + }); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + std::cout << "=== 开始多线程并发测试 ===\n"; + auto total_start = std::chrono::steady_clock::now(); + + for (size_t iter = 0; iter < 1; ++iter) { + printWithLock("\n=== 迭代 " + std::to_string(iter + 1) + " ==="); + auto iter_start = std::chrono::steady_clock::now(); + + // 创建并启动所有线程 + std::vector threads; + + // 线程1:获取版本 + threads.emplace_back(threadGetVersion, std::ref(hand), iter + 1); + + // 线程2:设置参数 + threads.emplace_back(threadSetParameters, std::ref(hand), iter + 1); + + // 线程3:获取参数 + threads.emplace_back(threadGetParameters, std::ref(hand), iter + 1); + + // 线程4:获取压感 + threads.emplace_back(threadGetTouchData, std::ref(hand), iter + 1); + + // 线程5:运动控制 + threads.emplace_back(threadMotionControl, std::ref(hand), iter + 1); + + // 等待所有线程完成 + for (auto& t : threads) { + if (t.joinable()) { + t.join(); + } + } + + auto iter_end = std::chrono::steady_clock::now(); + auto iter_duration = std::chrono::duration_cast(iter_end - iter_start); + + std::stringstream ss; + ss << "迭代 " << iter + 1 << " 完成,耗时: " << iter_duration.count() << "ms"; + printWithLock(ss.str()); + + // 迭代之间等待100ms + if (iter < 2) { // 修改循环次数判断 + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + } + + auto total_end = std::chrono::steady_clock::now(); + auto total_duration = std::chrono::duration_cast(total_end - total_start); + + std::cout << "\n=== 测试完成 ===\n"; + std::cout << "总耗时: " << total_duration.count() << "ms\n"; + std::cout << "平均每迭代: " << total_duration.count() / 3.0 << "ms\n"; // 修改平均计算 + + // 等待一段时间确保所有回调完成 + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} \ No newline at end of file diff --git a/examples/test_l7_modbus_0.cpp b/examples/test_l7_modbus_0.cpp new file mode 100644 index 0000000..c3ed341 --- /dev/null +++ b/examples/test_l7_modbus_0.cpp @@ -0,0 +1,217 @@ +// L7 / Modbus / 右手 —— 速度/扭矩/动作序列与各类状态读取 +#include +#include +#include +#include +#include +#include +#include + +#include "LinkerHandApi.h" +#include "CommunicationCallbacks.h" +#include "Modbus.h" + +// 全局 Modbus 设备实例 +static std::unique_ptr g_modbus = nullptr; + +// 辅助函数:打印向量数据 +void printVector(const std::string& label, const std::vector& vec) { + std::cout << label << ": ["; + for (size_t i = 0; i < vec.size(); ++i) { + std::cout << static_cast(vec[i]); + if (i < vec.size() - 1) std::cout << ", "; + } + std::cout << "]" << std::endl; +} + +int main(int argc, char* argv[]) { + #ifdef _WIN32 + SetConsoleOutputCP(CP_UTF8); + #endif + + std::cout << "========================================" << std::endl; + std::cout << " L7 Modbus 测试示例 (RS485 Modbus Device 封装版)" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << std::endl; + + // 1. 初始化 Modbus 设备 + g_modbus = std::make_unique("/dev/ttyUSB0", 115200); + if (!g_modbus->isOpen()) { + std::cerr << "串口打开失败,退出。" << std::endl; + return -1; + } + + // 2. 初始化手部 API + try { + LinkerHandApi hand(LINKER_HAND::L7, HAND_TYPE::RIGHT, COMM_TYPE::MODBUS); + + // 3. 设置 Modbus 回调函数 + hand.setModbusTxCallback([](uint8_t sid, uint16_t addr, const uint8_t* data, uintptr_t len) -> int32_t { + if (!g_modbus) return -1; + return g_modbus->sendRawFrame(data, len) ? 0 : -1; + }); + + hand.setModbusRxCallback([](uint8_t sid, uint16_t* addr_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + if (!g_modbus) return -1; + int len = g_modbus->receiveCompleteFrame(data_out, 256, 500); + if (len <= 0 || data_out[0] != sid) return -1; + *len_out = static_cast(len); + if (addr_out) *addr_out = 0; + return 0; + }); + + std::cout << "初始化完成!" << std::endl; + std::cout << std::endl; + + // 测试 1: 设置速度 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 1: 设置速度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector speed(7, 128); // 7个关节,速度值 128 (L7 有7个关节) + hand.setSpeed(speed); + printVector("设置速度", speed); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << std::endl; + + // 测试 2: 设置扭矩 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 2: 设置扭矩" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector torque(7, 200); // 10个关节,扭矩值 200 + hand.setTorque(torque); + printVector("设置扭矩", torque); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << std::endl; + + // 测试 3: 手指动作序列 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 3: 手指动作序列" << std::endl; + std::cout << "----------------------------------------" << std::endl; + + // L7 有 7 个关节: 大拇指弯曲、大拇指偏航、食指弯曲、中指弯曲、无名指弯曲、小拇指弯曲、大拇指翻转 + std::vector> poses = { + {255, 255, 255, 255, 255, 255, 255}, // 完全张开 + {0, 255, 255, 255, 255, 255, 255}, // 大拇指弯曲 + {255, 0, 255, 255, 255, 255, 255}, // 大拇指偏航 + {255, 255, 0, 255, 255, 255, 255}, // 食指弯曲 + {255, 255, 255, 0, 255, 255, 255}, // 中指弯曲 + {255, 255, 255, 255, 0, 255, 255}, // 无名指弯曲 + {255, 255, 255, 255, 255, 0, 255}, // 小拇指弯曲 + {255, 255, 255, 255, 255, 255, 0}, // 大拇指翻转 + {255, 255, 0, 0, 0, 0, 255}, // 握拳 + {255, 255, 255, 255, 255, 255, 255} // 完全张开 + }; + + for (size_t i = 0; i < poses.size(); ++i) { + std::cout << "动作 " << (i + 1) << "/" << poses.size() << ": "; + printVector("位置", poses[i]); + hand.fingerMove(poses[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + std::cout << std::endl; + + // 测试 4: 读取当前状态 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 4: 读取当前状态" << std::endl; + std::cout << "----------------------------------------" << std::endl; + for (int i = 0; i < 5; ++i) { + std::vector state = hand.getState(); + if (!state.empty()) { + printVector("当前关节位置", state); + } else { + std::cout << "读取状态失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + std::cout << std::endl; + + // 测试 5: 读取速度 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 5: 读取速度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector current_speed = hand.getSpeed(); + if (!current_speed.empty()) { + printVector("当前速度", current_speed); + } else { + std::cout << "读取速度失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 6: 读取扭矩 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 6: 读取扭矩" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector current_torque = hand.getTorque(); + if (!current_torque.empty()) { + printVector("当前扭矩", current_torque); + } else { + std::cout << "读取扭矩失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 7: 读取温度 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 7: 读取温度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector temperature = hand.getTemperature(); + if (!temperature.empty()) { + printVector("电机温度", temperature); + } else { + std::cout << "读取温度失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 8: 读取故障码 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 8: 读取故障码" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector fault_code = hand.getFaultCode(); + if (!fault_code.empty()) { + printVector("故障码", fault_code); + } else { + std::cout << "读取故障码失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 9: 读取版本信息 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 9: 读取版本信息" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::string version = hand.getVersion(); + std::cout << version << std::endl; + + // 测试 10: 读取压感数据 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 10: 读取压感数据" << std::endl; + std::cout << "----------------------------------------" << std::endl; + for (int i = 0; i < 3; ++i) { + std::vector>> touch_mats = hand.getForce(); + // 手指名称表,顺序对应 touch_mats[0..4] + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) + { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + std::cout << "========================================" << std::endl; + std::cout << "L7 测试完成!" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << std::endl; + + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} \ No newline at end of file diff --git a/examples/test_l7_modbus_1.cpp b/examples/test_l7_modbus_1.cpp new file mode 100644 index 0000000..f014482 --- /dev/null +++ b/examples/test_l7_modbus_1.cpp @@ -0,0 +1,446 @@ +// L7 / Modbus / 右手 —— 多线程并发:手势 + 状态监控 + 压力 + 故障检测 +#define _USE_MATH_DEFINES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "LinkerHandApi.h" +#include "CommunicationCallbacks.h" +#include "Modbus.h" + +// 全局变量 +static std::unique_ptr g_modbus = nullptr; +static std::atomic g_running{true}; +static std::mutex g_console_mutex; +static std::mutex g_hand_mutex; // 手部操作互斥锁 + +// 线程安全日志输出 +void safePrint(const std::string& message) { + std::lock_guard lock(g_console_mutex); + std::cout << message << std::endl; +} + +void threadSafePrintVector(const std::string& label, const std::vector& vec) { + std::lock_guard lock(g_console_mutex); + std::cout << label << ": ["; + for (size_t i = 0; i < vec.size(); ++i) { + std::cout << static_cast(vec[i]); + if (i < vec.size() - 1) std::cout << ", "; + } + std::cout << "]" << std::endl; +} + +// 手部状态监控线程 +void handStateMonitorThread(LinkerHandApi& hand) { + safePrint("[状态监控线程] 启动"); + + int iteration = 0; + while (g_running) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 10Hz更新 + + std::lock_guard hand_lock(g_hand_mutex); + + try { + // 读取关节位置 + std::vector state = hand.getState(); + if (!state.empty()) { + std::lock_guard console_lock(g_console_mutex); + std::cout << "\033[1;36m[状态监控 " << std::setw(4) << iteration << "] "; + std::cout << "关节位置: ["; + for (size_t i = 0; i < state.size(); ++i) { + std::cout << std::setw(3) << static_cast(state[i]); + if (i < state.size() - 1) std::cout << " "; + } + std::cout << "]\033[0m" << std::endl; + } + + // 每10次读取一次温度 + if (iteration % 10 == 0) { + std::vector temperature = hand.getTemperature(); + if (!temperature.empty()) { + std::lock_guard console_lock(g_console_mutex); + std::cout << "\033[1;33m[温度监控] "; + std::cout << "电机温度: ["; + for (size_t i = 0; i < temperature.size(); ++i) { + std::cout << std::setw(3) << static_cast(temperature[i]); + if (i < temperature.size() - 1) std::cout << " "; + } + std::cout << "]\033[0m" << std::endl; + } + } + + iteration++; + + } catch (const std::exception& e) { + safePrint("[状态监控线程] 异常: " + std::string(e.what())); + } + } + + safePrint("[状态监控线程] 停止"); +} + +// 压力传感器数据采集线程 +void pressureSensorThread(LinkerHandApi& hand) { + safePrint("[压力传感器线程] 启动"); + + int finger_index = 0; + const std::array finger_names = { + "拇指", "食指", "中指", "无名指", "小指" + }; + + while (g_running) { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 2Hz更新 + + std::lock_guard hand_lock(g_hand_mutex); + + try { + // 读取所有手指的压力数据 + std::vector>> touch_mats = hand.getForce(); + + if (!touch_mats.empty() && !touch_mats[0].empty()) { + std::lock_guard console_lock(g_console_mutex); + + // 选择当前手指显示详细数据 + if (finger_index < touch_mats.size() && !touch_mats[finger_index].empty()) { + std::cout << "\033[1;32m[压力传感器 " << finger_names[finger_index] << "] "; + std::cout << "矩阵 " << touch_mats[finger_index].size() + << "x" << touch_mats[finger_index][0].size() << "\033[0m" << std::endl; + + // 只显示前几行以避免控制台混乱 + int rows_to_show = (4 < static_cast(touch_mats[finger_index].size())) ? 4 : static_cast(touch_mats[finger_index].size()); + for (int r = 0; r < rows_to_show; ++r) { + std::cout << " "; + for (size_t c = 0; c < touch_mats[finger_index][r].size(); ++c) { + int val = static_cast(touch_mats[finger_index][r][c]); + // 根据压力值使用不同颜色 + if (val > 200) std::cout << "\033[1;31m"; + else if (val > 100) std::cout << "\033[1;33m"; + else std::cout << "\033[1;37m"; + + std::cout << std::setw(3) << val << "\033[0m "; + } + std::cout << std::endl; + } + } + + // 计算并显示最大压力值 + int max_pressure = 0; + int finger_with_max = 0; + for (size_t f = 0; f < touch_mats.size(); ++f) { + for (const auto& row : touch_mats[f]) { + for (uint8_t val : row) { + if (val > max_pressure) { + max_pressure = val; + finger_with_max = static_cast(f); + } + } + } + } + + std::cout << "\033[1;35m[最大压力] " << finger_names[finger_with_max] + << ": " << max_pressure << "\033[0m" << std::endl; + } + + // 轮询下一个手指 + finger_index = (finger_index + 1) % 5; + + } catch (const std::exception& e) { + safePrint("[压力传感器线程] 异常: " + std::string(e.what())); + } + } + + safePrint("[压力传感器线程] 停止"); +} + +// 手势控制线程 +void gestureControlThread(LinkerHandApi& hand) { + safePrint("[手势控制线程] 启动"); + + // L7手势序列(7个关节) + std::vector> gestures = { + {255, 255, 255, 255, 255, 255, 255}, // 完全张开 + {0, 255, 255, 255, 255, 255, 255}, // 大拇指弯曲 + {255, 0, 255, 255, 255, 255, 255}, // 大拇指偏航 + {255, 255, 0, 255, 255, 255, 255}, // 食指弯曲 + {255, 255, 255, 0, 255, 255, 255}, // 中指弯曲 + {255, 255, 255, 255, 0, 255, 255}, // 无名指弯曲 + {255, 255, 255, 255, 255, 0, 255}, // 小拇指弯曲 + {255, 255, 255, 255, 255, 255, 0}, // 大拇指翻转 + {255, 255, 0, 0, 0, 0, 255}, // 握拳 + {255, 255, 255, 255, 255, 255, 255} // 完全张开 + }; + + const std::vector gesture_names = { + "张开", "握拳", "捏取", "三指捏", "拇指向上", "胜利", "OK" + }; + + int gesture_index = 0; + + while (g_running) { + // 每个手势保持2秒 + std::this_thread::sleep_for(std::chrono::seconds(2)); + + std::lock_guard hand_lock(g_hand_mutex); + + try { + // 执行当前手势 + std::vector pose = gestures[gesture_index]; + + { + std::lock_guard console_lock(g_console_mutex); + std::cout << "\033[1;34m[手势控制] 执行手势: " << "\033[0m" << std::endl; + } + + hand.fingerMove(pose); + + // 下一个手势 + gesture_index = (gesture_index + 1) % gestures.size(); + + } catch (const std::exception& e) { + safePrint("[手势控制线程] 异常: " + std::string(e.what())); + } + } + + safePrint("[手势控制线程] 停止"); +} + +// 故障检测线程 +void faultDetectionThread(LinkerHandApi& hand) { + safePrint("[故障检测线程] 启动"); + + int check_count = 0; + bool last_fault_state = false; + + while (g_running) { + std::this_thread::sleep_for(std::chrono::seconds(1)); // 1Hz检测 + + std::lock_guard hand_lock(g_hand_mutex); + + try { + std::vector fault_codes = hand.getFaultCode(); + + // 检查是否有故障 + bool has_fault = false; + for (uint8_t code : fault_codes) { + if (code != 0) { + has_fault = true; + break; + } + } + + if (has_fault) { + std::lock_guard console_lock(g_console_mutex); + std::cout << "\033[1;41m[故障检测 " << std::setw(4) << check_count << "] "; + std::cout << "检测到故障! 故障码: ["; + for (size_t i = 0; i < fault_codes.size(); ++i) { + std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') + << static_cast(fault_codes[i]) << std::dec; + if (i < fault_codes.size() - 1) std::cout << ", "; + } + std::cout << "]\033[0m" << std::endl; + + last_fault_state = true; + + // 尝试自动恢复 - 发送张开手势 + if (last_fault_state) { + std::cout << "\033[1;33m[故障恢复] 尝试恢复: 发送张开手势\033[0m" << std::endl; + std::vector recovery_pose = {255, 255, 255, 255, 255, 255, 255}; + hand.fingerMove(recovery_pose); + } + + } else if (last_fault_state) { + // 故障已清除 + std::lock_guard console_lock(g_console_mutex); + std::cout << "\033[1;42m[故障恢复] 故障已清除!\033[0m" << std::endl; + last_fault_state = false; + } + + check_count++; + + } catch (const std::exception& e) { + safePrint("[故障检测线程] 异常: " + std::string(e.what())); + } + } + + safePrint("[故障检测线程] 停止"); +} + +// 性能测试线程(高频率位置控制) +void performanceTestThread(LinkerHandApi& hand) { + safePrint("[性能测试线程] 启动"); + + // 测试不同的控制频率 + const std::vector test_durations = {5000, 5000, 5000}; // 5秒每个测试 + const std::vector test_frequencies = {10, 20, 50}; // 10Hz, 20Hz, 50Hz + const std::vector test_names = {"10Hz", "20Hz", "50Hz"}; + + int test_phase = 0; + auto test_start_time = std::chrono::steady_clock::now(); + + while (g_running && test_phase < test_durations.size()) { + auto current_time = std::chrono::steady_clock::now(); + auto elapsed = std::chrono::duration_cast( + current_time - test_start_time).count(); + + if (elapsed >= test_durations[test_phase]) { + // 切换到下一个测试阶段 + test_phase++; + test_start_time = std::chrono::steady_clock::now(); + + if (test_phase < test_durations.size()) { + std::lock_guard console_lock(g_console_mutex); + std::cout << "\033[1;36m[性能测试] 切换到 " << test_names[test_phase] + << " 控制频率\033[0m" << std::endl; + } + continue; + } + + if (test_phase < test_frequencies.size()) { + int frequency = test_frequencies[test_phase]; + int period_ms = 1000 / frequency; + + // 生成正弦波位置控制信号 + double time_sec = elapsed / 1000.0; + double angle = 127.5 + 127.5 * sin(2.0 * M_PI * 0.5 * time_sec); // 0.5Hz正弦波 + + std::vector position(7, static_cast(angle)); + + { + std::lock_guard hand_lock(g_hand_mutex); + hand.fingerMove(position); + } + + // 控制频率 + std::this_thread::sleep_for(std::chrono::milliseconds(period_ms)); + } + } + + safePrint("[性能测试线程] 测试完成"); +} + +// 主测试线程(执行一次性测试) +void mainTestThread(LinkerHandApi& hand) { + safePrint("[主测试线程] 启动"); + + // 等待其他线程启动 + std::this_thread::sleep_for(std::chrono::seconds(2)); + + // 设置初始速度和扭矩 + { + std::lock_guard hand_lock(g_hand_mutex); + std::vector speed(7, 100); + std::vector torque(7, 150); + hand.setSpeed(speed); + hand.setTorque(torque); + + std::lock_guard console_lock(g_console_mutex); + std::cout << "\033[1;32m[主测试] 设置速度: 100, 扭矩: 150\033[0m" << std::endl; + } + + // 读取版本信息 + std::this_thread::sleep_for(std::chrono::seconds(1)); + { + std::lock_guard hand_lock(g_hand_mutex); + std::string version = hand.getVersion(); + + std::lock_guard console_lock(g_console_mutex); + std::cout << "\033[1;32m[主测试] 版本信息:\033[0m" << std::endl; + std::cout << version << std::endl; + } + + // 运行30秒后停止 + std::this_thread::sleep_for(std::chrono::seconds(30)); + + safePrint("[主测试线程] 测试完成,准备停止所有线程"); + g_running = false; +} + +int main(int argc, char* argv[]) { + #ifdef _WIN32 + SetConsoleOutputCP(CP_UTF8); + #endif + + std::cout << "===============================================" << std::endl; + std::cout << " L7 Modbus 多线程并发测试" << std::endl; + std::cout << " 模拟真实控制场景:手势 + 状态监控 + 压力检测" << std::endl; + std::cout << "===============================================" << std::endl; + std::cout << std::endl; + + try { + + // 2. 初始化手部 API + LinkerHandApi hand(LINKER_HAND::L7, HAND_TYPE::RIGHT, COMM_TYPE::MODBUS); + + // 1. 初始化 Modbus 设备 + g_modbus = std::make_unique("/dev/ttyUSB0", 115200); + if (!g_modbus->isOpen()) { + std::cerr << "错误: 串口打开失败,退出。" << std::endl; + return -1; + } + + safePrint("串口初始化成功: /dev/ttyUSB0 @ 115200 baud"); + + // 3. 设置 Modbus 回调函数 + hand.setModbusTxCallback([](uint8_t sid, uint16_t addr, const uint8_t* data, uintptr_t len) -> int32_t { + if (!g_modbus) return -1; + return g_modbus->sendRawFrame(data, len) ? 0 : -1; + }); + + hand.setModbusRxCallback([](uint8_t sid, uint16_t* addr_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + if (!g_modbus) return -1; + int len = g_modbus->receiveCompleteFrame(data_out, 256, 500); + if (len <= 0 || data_out[0] != sid) return -1; + *len_out = static_cast(len); + if (addr_out) *addr_out = 0; + return 0; + }); + + safePrint("手部API初始化完成"); + safePrint("开始多线程测试..."); + std::cout << std::endl; + + // 4. 启动所有工作线程 + std::vector threads; + + threads.emplace_back(handStateMonitorThread, std::ref(hand)); + threads.emplace_back(pressureSensorThread, std::ref(hand)); + threads.emplace_back(gestureControlThread, std::ref(hand)); + threads.emplace_back(faultDetectionThread, std::ref(hand)); + // threads.emplace_back(performanceTestThread, std::ref(hand)); // 可选:性能测试 + threads.emplace_back(mainTestThread, std::ref(hand)); + + // 5. 等待所有线程完成 + for (auto& t : threads) { + if (t.joinable()) { + t.join(); + } + } + + // 6. 发送停止手势(张开) + { + std::lock_guard hand_lock(g_hand_mutex); + std::vector stop_pose = {255, 255, 255, 255, 255, 255, 255}; + hand.fingerMove(stop_pose); + safePrint("发送停止手势"); + } + + hand.freeModbusCallback(); + + std::cout << std::endl; + std::cout << "===============================================" << std::endl; + std::cout << " 多线程测试完成" << std::endl; + std::cout << "===============================================" << std::endl; + + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} \ No newline at end of file diff --git a/examples/test_o20_canfd_0.cpp b/examples/test_o20_canfd_0.cpp new file mode 100644 index 0000000..4407ed3 --- /dev/null +++ b/examples/test_o20_canfd_0.cpp @@ -0,0 +1,80 @@ +// O20 / CAN-FD / 右手 —— 版本/动作/速度最小示例 +#include +#include +#include +#include +#include +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommunicationCallbacks.h" +#include "CanFD.h" + +int main() { + std::cout << "O20 CANFD Test" << std::endl; + + // 初始化 CANFD 设备 + Communication::CanFD canfd(0, 0); + if (!canfd.init()) { + std::cerr << "Failed to initialize CANFD" << std::endl; + return 1; + } + std::cout << "CANFD initialized successfully" << std::endl; + + try { + LinkerHandApi api(LINKER_HAND::O20, HAND_TYPE::RIGHT, COMM_TYPE::CAN); + + std::cout << "LinkerHandApi created" << std::endl; + + auto can_tx_callback = [&](uint32_t can_id, const uint8_t* data, uintptr_t data_len) -> int32_t { + std::vector data_vec(data, data + data_len); + canfd.send(data_vec, can_id, true); + return 0; + }; + + auto can_rx_callback = [&](uint32_t* can_id_out, uint8_t* data_out, uint8_t* data_len_out) -> int32_t { + Communication::CanFDFrame frame = canfd.recv(10); + if (frame.valid) { + *can_id_out = frame.can_id; + *data_len_out = Communication::CanFD::dlcToLen(frame.can_dlc); + memcpy(data_out, frame.data, *data_len_out); + return 0; + } + return -1; + }; + + std::cout << "RX callback set" << std::endl; + + api.setCanTxCallback(can_tx_callback); + api.setCanRxCallback(can_rx_callback); + + std::cout << "Callbacks registered, sleeping 1 second..." << std::endl; + std::this_thread::sleep_for(std::chrono::seconds(1)); + + std::cout << "Calling getVersion()..." << std::endl; + std::string version = api.getVersion(); + std::cout << "Version: " << version << std::endl; + + std::vector pos(34, 0); + std::cout << "Calling fingerMove()..." << std::endl; + api.fingerMove(pos); + + std::cout << "Calling getSpeed()..." << std::endl; + std::vector speed = api.getSpeed(); + + for (size_t i = 0; i < speed.size(); i++) { + std::cout << (int)speed[i] << std::dec << " "; + } + std::cout << std::dec << std::endl; + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + canfd.close(); + return 1; + } + + canfd.close(); + std::cout << "Test completed" << std::endl; + return 0; +} \ No newline at end of file diff --git a/examples/test_o20_canfd_1.cpp b/examples/test_o20_canfd_1.cpp new file mode 100644 index 0000000..d2fb11d --- /dev/null +++ b/examples/test_o20_canfd_1.cpp @@ -0,0 +1,113 @@ +// O20 / CAN-FD / 右手 —— 版本/速度/动作序列/触觉(带 TX/RX 日志) +#include +#include +#include +#include +#include +#include +#include +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommunicationCallbacks.h" +#include "CanFD.h" + +int main() { + std::cout << "========================================" << std::endl; + std::cout << " O20 CANFD Test Program (Example 1)" << std::endl; + std::cout << "========================================" << std::endl; + + Communication::CanFD canfd(0, 0); + if (!canfd.init()) { + std::cerr << "Failed to initialize CANFD" << std::endl; + return 1; + } + std::cout << "CANFD initialized successfully" << std::endl; + + try { + LinkerHandApi api(LINKER_HAND::O20, HAND_TYPE::RIGHT, COMM_TYPE::CAN); + + std::cout << "LinkerHandApi created for O20 (RIGHT)" << std::endl; + + auto can_tx_callback = [&](uint32_t can_id, const uint8_t* data, uintptr_t data_len) -> int32_t { + std::vector data_vec(data, data + data_len); + canfd.send(data_vec, can_id, true); + std::cout << "\033[32m[TX] ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << can_id + << std::dec << " | Len: " << (int)data_len << " | Data: "; + for (uintptr_t i = 0; i < data_len; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)data[i] << " "; + } + std::cout << std::dec << std::endl; + return 0; + }; + + auto can_rx_callback = [&](uint32_t* can_id_out, uint8_t* data_out, uint8_t* data_len_out) -> int32_t { + Communication::CanFDFrame frame = canfd.recv(10); + if (frame.valid) { + *can_id_out = frame.can_id; + *data_len_out = Communication::CanFD::dlcToLen(frame.can_dlc); + memcpy(data_out, frame.data, *data_len_out); + std::cout << "\033[34m[RX] ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << *can_id_out + << std::dec << " | Len: " << (int)*data_len_out << std::endl; + return 0; + } + return -1; + }; + + api.setCanTxCallback(can_tx_callback); + api.setCanRxCallback(can_rx_callback); + + std::cout << "Callbacks registered, connecting..." << std::endl; + std::this_thread::sleep_for(std::chrono::seconds(1)); + + std::cout << std::endl << "--- Test 1: Get Version ---" << std::endl; + std::string version = api.getVersion(); + std::cout << "Version: " << version << std::endl; + + std::cout << std::endl << "--- Test 2: Set Speed ---" << std::endl; + std::vector speed(34, 128); + api.setSpeed(speed); + std::cout << "Speed set to 128 for all 34 joints" << std::endl; + + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + + std::cout << std::endl << "--- Test 3: Get Speed ---" << std::endl; + std::vector current_speed = api.getSpeed(); + std::cout << "Current speed size: " << current_speed.size() << std::endl; + + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + + std::cout << std::endl << "--- Test 4: Finger Movement Sequence ---" << std::endl; + std::vector poses_seq(17, 0); + for (size_t i = 0; i < 17; ++i) { + std::vector poses_temp = poses_seq; + poses_temp[i] = 255; + api.fingerMove(poses_temp); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + + std::cout << std::endl << "--- Test 5: Get Force Data ---" << std::endl; + std::vector>> touch_mats = api.getForce(); + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + + for (size_t n = 0; n < touch_mats.size() && n < 5; ++n) { + std::cout << finger_name[n] << ": "; + size_t total_rows = touch_mats[n].size(); + std::cout << total_rows << " rows" << std::endl; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + } catch (const std::exception& e) { + std::cerr << "\033[31mError: " << e.what() << "\033[0m" << std::endl; + canfd.close(); + return 1; + } + + canfd.close(); + std::cout << std::endl << "========================================" << std::endl; + std::cout << "O20 CANFD Test completed successfully!" << std::endl; + std::cout << "========================================" << std::endl; + return 0; +} \ No newline at end of file diff --git a/examples/test_o6_can_0.cpp b/examples/test_o6_can_0.cpp new file mode 100644 index 0000000..4de7989 --- /dev/null +++ b/examples/test_o6_can_0.cpp @@ -0,0 +1,156 @@ +// O6 / CAN / 左手 —— 读取版本/力矩/速度/状态/触觉并执行握拳与张开(带 TX/RX 日志) +#include +#include +#include +#include +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommFactory.h" + +// 格式化当前时间,用于 TX/RX 日志 +std::string getCurrentTime() { + auto now = std::chrono::system_clock::now(); + auto now_time = std::chrono::system_clock::to_time_t(now); + auto now_ms = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + + #if defined(_WIN32) || defined(_WIN64) + std::tm tm_info = {}; + localtime_s(&tm_info, &now_time); + std::tm* tm = &tm_info; + #else + std::tm* tm = std::localtime(&now_time); + #endif + char buffer[80]; + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm); + + std::ostringstream oss; + oss << buffer << "." << std::setfill('0') << std::setw(3) << now_ms.count(); + return oss.str(); +} + +int main() { + try { + // 初始化灵巧手 + std::shared_ptr hand = std::make_shared(LINKER_HAND::O6, HAND_TYPE::LEFT); + + // 按手别创建 CAN 总线对象 + std::shared_ptr bus = Communication::CommFactory::createCanBus(HAND_TYPE::LEFT); + + hand->setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + static int tx_count = 0; + tx_count++; + std::cout << "\033[32m[TX #" << tx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << can_id + << std::dec << " (" << can_id << ")" + << " | Len: " << data_len + << " | Data: "; + for (uintptr_t i = 0; i < data_len; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)data[i] << " "; + } + std::cout << std::dec << std::endl; + + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + hand->setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; + } + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + + static int rx_count = 0; + rx_count++; + std::cout << "\033[34m[RX #" << rx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << frame.can_id + << std::dec << " (" << frame.can_id << ")" + << " | DLC: " << (int)frame.can_dlc + << " | Data: "; + for (int i = 0; i < frame.can_dlc; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)frame.data[i] << " "; + } + std::cout << std::dec << std::endl; + return 0; + }); + + std::cout << "----------------------------------------" << std::endl; + + for (size_t i = 0; i < 1; ++i) { + std::cout << hand->getVersion() << std::endl; + + std::cout << "setTorque----------------------------------------" << std::endl; + hand->setTorque({200,200,200,200,200,200}); + std::cout << "setSpeed----------------------------------------" << std::endl; + hand->setSpeed({200,200,200,200,200,200}); + + // 握拳 + std::vector fist_pose = {255, 255, 0, 0, 0, 0}; + hand->fingerMove(fist_pose); + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // 张开 + std::vector open_pose = {255, 104, 255, 255, 255, 255}; + hand->fingerMove(open_pose); + std::this_thread::sleep_for(std::chrono::seconds(1)); + + for (size_t k = 0; k < 3; k++) { + std::cout << "getTorque----------------------------------------" << std::endl; + std::vector torque = hand->getTorque(); + std::cout << "torque size:" << torque.size() << std::endl; + for (size_t j = 0; j < torque.size(); j++) { + std::cout << (int)torque[j] << " "; + } + std::cout << std::endl; + + std::cout << "getSpeed----------------------------------------" << std::endl; + std::vector speed = hand->getSpeed(); + std::cout << "speed size:" << speed.size() << std::endl; + for (size_t j = 0; j < speed.size(); j++) { + std::cout << (int)speed[j] << " "; + } + std::cout << std::endl; + + std::cout << "getState----------------------------------------" << std::endl; + std::vector state = hand->getState(); + std::cout << "state size:" << state.size() << std::endl; + for (size_t j = 0; j < state.size(); j++) { + std::cout << (int)state[j] << " "; + } + std::cout << std::endl; + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + std::vector>> touch_mats = hand->getForce(); + // 手指名称表,顺序对应 touch_mats[0..4] + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + } + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_o6_can_1.cpp b/examples/test_o6_can_1.cpp new file mode 100644 index 0000000..d1843c8 --- /dev/null +++ b/examples/test_o6_can_1.cpp @@ -0,0 +1,374 @@ +// O6 / CAN / 左手 —— 多线程并发测试(版本/参数/触觉并行) +#include +#include +#include +#include +#include +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommFactory.h" + +// 格式化当前时间,用于 TX/RX 日志 +std::string getCurrentTime() { + auto now = std::chrono::system_clock::now(); + auto now_time = std::chrono::system_clock::to_time_t(now); + auto now_ms = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + + #if defined(_WIN32) || defined(_WIN64) + std::tm tm_info = {}; + localtime_s(&tm_info, &now_time); + std::tm* tm = &tm_info; + #else + std::tm* tm = std::localtime(&now_time); + #endif + char buffer[80]; + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm); + + std::ostringstream oss; + oss << buffer << "." << std::setfill('0') << std::setw(3) << now_ms.count(); + return oss.str(); +} + +// 全局互斥锁,用于控制输出顺序 +std::mutex cout_mutex; + +void printWithLock(const std::string& message) { + std::lock_guard lock(cout_mutex); + std::cout << message << std::endl; +} + +// 线程1:获取版本信息(独立运行,不依赖其他数据) +void threadGetVersion(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + std::string version = hand.getVersion(); + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread1-Iter" << iteration << "] 版本获取完成 (" << duration.count() << "ms): " << version; + printWithLock(ss.str()); + + // 版本获取后等待3ms + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread1-Iter" << iteration << "] 版本获取失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程2:设置扭矩和速度(这两个可以并行) +void threadSetParameters(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + // 同时设置扭矩和速度 + std::vector torque_values = {200,200,200,200,200,200}; + std::vector speed_values = {200,200,200,200,200,200}; + + hand.setTorque(torque_values); + // 设置扭矩后等待3ms + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); + + hand.setSpeed(speed_values); + // 设置速度后等待3ms + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread2-Iter" << iteration << "] 参数设置完成 (" << duration.count() << "ms)"; + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread2-Iter" << iteration << "] 参数设置失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程3:获取扭矩、速度、状态(这些可以并行获取) +void threadGetParameters(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + std::vector torque; + std::vector speed; + std::vector state; + + // 并行获取三个参数 + auto future_torque = std::async(std::launch::async, [&hand]() { + return hand.getTorque(); + }); + + auto future_speed = std::async(std::launch::async, [&hand]() { + return hand.getSpeed(); + }); + + auto future_state = std::async(std::launch::async, [&hand]() { + return hand.getState(); + }); + + // 等待所有结果 + torque = future_torque.get(); + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); // 获取扭矩后等待3ms + + speed = future_speed.get(); + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); // 获取速度后等待3ms + + state = future_state.get(); + //std::this_thread::sleep_for(std::chrono::milliseconds(3)); // 获取状态后等待3ms + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread3-Iter" << iteration << "] 参数获取完成 (" << duration.count() << "ms)\n"; + ss << " 扭矩大小: " << torque.size() << " 数据: "; + for (size_t i = 0; i < torque.size() && i < 5; ++i) { + ss << (int)torque[i] << " "; + } + if (torque.size() > 5) ss << "..."; + + ss << "\n 速度大小: " << speed.size() << " 数据: "; + for (size_t i = 0; i < speed.size() && i < 5; ++i) { + ss << (int)speed[i] << " "; + } + if (speed.size() > 5) ss << "..."; + + ss << "\n 状态大小: " << state.size() << " 数据: "; + for (size_t i = 0; i < state.size() && i < 5; ++i) { + ss << (int)state[i] << " "; + } + if (state.size() > 5) ss << "..."; + + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread3-Iter" << iteration << "] 参数获取失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程4:获取压感数据(5个手指可以并行获取) +void threadGetTouchData(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + std::vector>> touch_mats = hand.getForce(); + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) + { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread4-Iter" << iteration << "] 压感数据获取完成 (" << duration.count() << "ms)"; + printWithLock(ss.str()); + + // 打印压感数据 + for (size_t n = 0; n < touch_mats.size(); ++n) { + if (!touch_mats[n].empty()) { + std::stringstream ss2; + ss2 << " " << finger_name[n] << " 矩阵 " + << touch_mats[n].size() << "x" + << (touch_mats[n].empty() ? 0 : touch_mats[n][0].size()) + << " 第一个值: " << (int)touch_mats[n][0][0]; + printWithLock(ss2.str()); + } + } + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread4-Iter" << iteration << "] 压感获取失败: " << e.what(); + printWithLock(ss.str()); + } +} + +// 线程5:运动控制(握拳和张开) +void threadMotionControl(LinkerHandApi& hand, int iteration) { + try { + auto start = std::chrono::steady_clock::now(); + + // 握拳 + std::vector fist_pose = {101, 60, 0, 0, 0, 0}; + hand.fingerMove(fist_pose); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + // 张开 + std::vector open_pose = {255, 104, 255, 255, 255, 255}; + hand.fingerMove(open_pose); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::stringstream ss; + ss << "[Thread5-Iter" << iteration << "] 运动控制完成 (" << duration.count() << "ms)"; + printWithLock(ss.str()); + + } catch (const std::exception& e) { + std::stringstream ss; + ss << "[Thread5-Iter" << iteration << "] 运动控制失败: " << e.what(); + printWithLock(ss.str()); + } +} + +int main() { + try { + + // 调用API接口 + LinkerHandApi hand(LINKER_HAND::O6, HAND_TYPE::LEFT); + + // 创建CAN总线对象用于通信 + std::shared_ptr bus = Communication::CommFactory::createCanBus("can0", 1000000); + + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + static int tx_count = 0; + tx_count++; + + // 打印发送信息 + std::cout << "\033[32m[TX #" << tx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << can_id + << std::dec << " (" << can_id << ")" + << " | Len: " << data_len + << " | Data: "; + + // 打印数据 + for (uintptr_t i = 0; i < data_len; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') + << (int)data[i] << " "; + } + std::cout << std::dec << std::endl; + + + std::vector data_vec(data, data + data_len); + try { + bus->send(data_vec, can_id); + } catch (const std::exception& e) { + std::cerr << "CAN发送错误: " << e.what() << std::endl; + return -1; + } + return 0; + }); + + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + try { + auto frame = bus->recv(); + // 检查是否为空帧 + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; // 忽略空帧 + } + + // 填充输出参数 + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + + + static int rx_count = 0; + rx_count++; + + // 打印接收信息 + std::cout << "\033[34m[RX #" << rx_count << "]\033[0m " + << getCurrentTime() + << " | CAN_ID: 0x" << std::hex << std::setw(8) << std::setfill('0') << frame.can_id + << std::dec << " (" << frame.can_id << ")" + << " | DLC: " << (int)frame.can_dlc + << " | Data: "; + + // 打印数据 + for (int i = 0; i < frame.can_dlc; i++) { + std::cout << std::hex << std::setw(2) << std::setfill('0') + << (int)frame.data[i] << " "; + } + std::cout << std::dec << std::endl; + + + return 0; // 成功 + } catch (const std::exception& e) { + std::cerr << "CAN接收错误: " << e.what() << std::endl; + return -1; // 失败 + } + }); + + + std::cout << "=== 开始多线程并发测试 ===\n"; + auto total_start = std::chrono::steady_clock::now(); + + for (size_t iter = 0; iter < 1; ++iter) { + printWithLock("\n=== 迭代 " + std::to_string(iter + 1) + " ==="); + auto iter_start = std::chrono::steady_clock::now(); + + // 创建并启动所有线程 + std::vector threads; + + // 线程1:获取版本 + threads.emplace_back(threadGetVersion, std::ref(hand), iter + 1); + + // 线程2:设置参数 + threads.emplace_back(threadSetParameters, std::ref(hand), iter + 1); + + // 线程3:获取参数 + threads.emplace_back(threadGetParameters, std::ref(hand), iter + 1); + + // 线程4:获取压感 + threads.emplace_back(threadGetTouchData, std::ref(hand), iter + 1); + + // 线程5:运动控制 + // threads.emplace_back(threadMotionControl, std::ref(hand), iter + 1); + + // 等待所有线程完成 + for (auto& t : threads) { + if (t.joinable()) { + t.join(); + } + } + + auto iter_end = std::chrono::steady_clock::now(); + auto iter_duration = std::chrono::duration_cast(iter_end - iter_start); + + std::stringstream ss; + ss << "迭代 " << iter + 1 << " 完成,耗时: " << iter_duration.count() << "ms"; + printWithLock(ss.str()); + + // 迭代之间等待100ms + if (iter < 9) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + } + + auto total_end = std::chrono::steady_clock::now(); + auto total_duration = std::chrono::duration_cast(total_end - total_start); + + std::cout << "\n=== 测试完成 ===\n"; + std::cout << "总耗时: " << total_duration.count() << "ms\n"; + std::cout << "平均每迭代: " << total_duration.count() / 10.0 << "ms\n"; + + hand.freeCanCallback(); + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_o6_can_3.cpp b/examples/test_o6_can_3.cpp new file mode 100644 index 0000000..90a5391 --- /dev/null +++ b/examples/test_o6_can_3.cpp @@ -0,0 +1,148 @@ +// O6 / CAN / 左手 —— 双线程并发:一线程读触觉,一线程设速度/扭矩/动作 +#include +#include +#include +#include +#include +#include + +#include "_win_console_utf8.h" +#include "LinkerHandApi.h" +#include "CommunicationCallbacks.h" +#include "CommFactory.h" + +// 辅助函数:打印向量数据 +void printVector(const std::string& label, const std::vector& vec) { + std::cout << label << ": ["; + for (size_t i = 0; i < vec.size(); ++i) { + std::cout << static_cast(vec[i]); + if (i < vec.size() - 1) std::cout << ", "; + } + std::cout << "]" << std::endl; +} + +int main(int argc, char* argv[]) { + try { + std::cout << "========================================" << std::endl; + std::cout << " O6 CAN 测试示例 (多线程并发测试)" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << std::endl; + + std::string channel_name = "can0"; + if (argc > 1) { + channel_name = argv[1]; + } + + // 创建 CAN 总线对象(工厂按平台分流 SocketCAN / PCAN) + std::shared_ptr bus = Communication::CommFactory::createCanBus(channel_name, 1000000); + + // 1. 初始化手部 API + LinkerHandApi hand(LINKER_HAND::O6, HAND_TYPE::LEFT, COMM_TYPE::CAN); + + // 设置 CAN 发送回调 + hand.setCanTxCallback([bus](uint32_t can_id, const uint8_t *data, uintptr_t data_len) -> int32_t { + std::vector data_vec(data, data + data_len); + bus->send(data_vec, can_id); + return 0; + }); + + // 设置 CAN 接收回调 + hand.setCanRxCallback([bus](uint32_t* can_id_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + auto frame = bus->recv(); + if (frame.can_id == 0 && frame.can_dlc == 0) { + return -1; + } + *can_id_out = frame.can_id; + *len_out = frame.can_dlc; + memcpy(data_out, frame.data, frame.can_dlc); + return 0; + }); + + std::cout << "初始化完成!" << std::endl; + std::cout << std::endl; + + // 线程:循环读取压感数据 + std::thread get_thread([&hand]() { + std::cout << "----------------------------------------" << std::endl; + std::cout << "读取压感数据" << std::endl; + std::cout << "----------------------------------------" << std::endl; + for (int i = 0; i < 100; ++i) { + std::vector>> touch_mats = hand.getForce(); + // 手指名称表,顺序对应 touch_mats[0..4] + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + }); + + // 线程:设置速度/扭矩并执行手指动作序列 + std::thread set_thread([&hand]() { + for (int i = 0; i < 3; ++i) { + std::cout << "----------------------------------------" << std::endl; + std::cout << "设置速度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector speed(6, 128); // 6个关节,速度值 128 + hand.setSpeed(speed); + printVector("设置速度", speed); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << std::endl; + + std::cout << "----------------------------------------" << std::endl; + std::cout << "设置扭矩" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector torque(6, 200); // 6个关节,扭矩值 200 + hand.setTorque(torque); + printVector("设置扭矩", torque); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << std::endl; + + std::cout << "----------------------------------------" << std::endl; + std::cout << "手指动作序列" << std::endl; + std::cout << "----------------------------------------" << std::endl; + + // O6 有 6 个关节:大拇指弯曲、大拇指横摆、食指、中指、无名指、小拇指 + std::vector> poses = { + {255, 255, 255, 255, 255, 255}, // 完全张开 + {0, 255, 255, 255, 255, 255}, // 大拇指弯曲 + {255, 0, 255, 255, 255, 255}, // 大拇指横摆 + {255, 255, 0, 255, 255, 255}, // 食指弯曲 + {255, 255, 255, 0, 255, 255}, // 中指弯曲 + {255, 255, 255, 255, 0, 255}, // 无名指弯曲 + {255, 255, 255, 255, 255, 0}, // 小拇指弯曲 + {0, 0, 0, 0, 0, 0}, // 握拳 + {255, 255, 255, 255, 255, 255} // 完全张开 + }; + for (size_t j = 0; j < poses.size(); ++j) { + std::cout << "动作 " << (j + 1) << "/" << poses.size() << ": "; + printVector("位置", poses[j]); + hand.fingerMove(poses[j]); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + std::cout << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } + }); + + get_thread.join(); + set_thread.join(); + + std::cout << "========================================" << std::endl; + std::cout << "测试完成!" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << std::endl; + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_o6_modbus_0.cpp b/examples/test_o6_modbus_0.cpp new file mode 100644 index 0000000..c671273 --- /dev/null +++ b/examples/test_o6_modbus_0.cpp @@ -0,0 +1,235 @@ +// O6 / Modbus / 左手 —— 速度/扭矩/动作序列与各类状态读取 +#include +#include +#include +#include +#include +#include +#include + +#include "LinkerHandApi.h" +#include "CommunicationCallbacks.h" +#include "Modbus.h" + +// 全局 Modbus 设备实例 +static std::unique_ptr g_modbus = nullptr; + + +// 辅助函数:打印向量数据 +void printVector(const std::string& label, const std::vector& vec) { + std::cout << label << ": ["; + for (size_t i = 0; i < vec.size(); ++i) { + std::cout << static_cast(vec[i]); + if (i < vec.size() - 1) std::cout << ", "; + } + std::cout << "]" << std::endl; +} + +// 辅助函数:打印版本信息 +void printVersion(const std::string& version) { + std::cout << "版本信息:" << std::endl; + std::cout << version << std::endl; +} + +int main(int argc, char* argv[]) { + #ifdef _WIN32 + SetConsoleOutputCP(CP_UTF8); + #endif + + std::cout << "========================================" << std::endl; + std::cout << " O6 Modbus 测试示例 (RS485 Modbus Device 封装版)" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << std::endl; + + // 解析命令行参数(可选:指定串口设备) + const char* port = "/dev/ttyUSB0"; + if (argc > 1) { + port = argv[1]; + } + + // 1. 初始化 Modbus 设备 + g_modbus = std::make_unique(port, 115200); + if (!g_modbus->isOpen()) { + std::cerr << "串口打开失败,退出。" << std::endl; + return -1; + } + + // 2. 初始化手部 API + try { + LinkerHandApi hand(LINKER_HAND::O6, HAND_TYPE::LEFT, COMM_TYPE::MODBUS); + + // 3. 设置 Modbus 回调函数 + hand.setModbusTxCallback([](uint8_t sid, uint16_t addr, const uint8_t* data, uintptr_t len) -> int32_t { + if (!g_modbus) return -1; + return g_modbus->sendRawFrame(data, len) ? 0 : -1; + }); + + hand.setModbusRxCallback([](uint8_t sid, uint16_t* addr_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + if (!g_modbus) return -1; + int len = g_modbus->receiveCompleteFrame(data_out, 256, 500); + if (len <= 0 || data_out[0] != sid) return -1; + *len_out = static_cast(len); + if (addr_out) *addr_out = 0; + return 0; + }); + + std::cout << "初始化完成!" << std::endl; + std::cout << std::endl; + + // 测试 1: 设置速度 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 1: 设置速度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector speed(6, 128); // 6个关节,速度值 128 + hand.setSpeed(speed); + printVector("设置速度", speed); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << std::endl; + + // 测试 2: 设置扭矩 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 2: 设置扭矩" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector torque(6, 200); // 6个关节,扭矩值 200 + hand.setTorque(torque); + printVector("设置扭矩", torque); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << std::endl; + + // 测试 3: 手指动作序列 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 3: 手指动作序列" << std::endl; + std::cout << "----------------------------------------" << std::endl; + + // O6 有 6 个关节:大拇指弯曲、大拇指横摆、食指、中指、无名指、小拇指 + std::vector> poses = { + {255, 255, 255, 255, 255, 255}, // 完全张开 + {0, 255, 255, 255, 255, 255}, // 大拇指弯曲 + {255, 0, 255, 255, 255, 255}, // 大拇指横摆 + {255, 255, 0, 255, 255, 255}, // 食指弯曲 + {255, 255, 255, 0, 255, 255}, // 中指弯曲 + {255, 255, 255, 255, 0, 255}, // 无名指弯曲 + {255, 255, 255, 255, 255, 0}, // 小拇指弯曲 + {0, 0, 0, 0, 0, 0}, // 握拳 + {255, 255, 255, 255, 255, 255} // 完全张开 + }; + + for (size_t i = 0; i < poses.size(); ++i) { + std::cout << "动作 " << (i + 1) << "/" << poses.size() << ": "; + printVector("位置", poses[i]); + hand.fingerMove(poses[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + std::cout << std::endl; + + // 测试 4: 读取当前状态 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 4: 读取当前状态" << std::endl; + std::cout << "----------------------------------------" << std::endl; + for (int i = 0; i < 5; ++i) { + std::vector state = hand.getState(); + if (!state.empty()) { + printVector("当前关节位置", state); + } else { + std::cout << "读取状态失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + std::cout << std::endl; + + // 测试 5: 读取速度 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 5: 读取速度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector current_speed = hand.getSpeed(); + if (!current_speed.empty()) { + printVector("当前速度", current_speed); + } else { + std::cout << "读取速度失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 6: 读取扭矩 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 6: 读取扭矩" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector current_torque = hand.getTorque(); + if (!current_torque.empty()) { + printVector("当前扭矩", current_torque); + } else { + std::cout << "读取扭矩失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 7: 读取温度 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 7: 读取温度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector temperature = hand.getTemperature(); + if (!temperature.empty()) { + printVector("电机温度", temperature); + } else { + std::cout << "读取温度失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 8: 读取故障码 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 8: 读取故障码" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector fault_code = hand.getFaultCode(); + if (!fault_code.empty()) { + printVector("故障码", fault_code); + } else { + std::cout << "读取故障码失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 9: 读取版本信息 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 9: 读取版本信息" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::string version = hand.getVersion(); + if (!version.empty()) { + printVersion(version); + } else { + std::cout << "读取版本信息失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 10: 读取压感数据 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 10: 读取压感数据" << std::endl; + std::cout << "----------------------------------------" << std::endl; + for (int i = 0; i < 3; ++i) { + std::vector>> touch_mats = hand.getForce(); + // 手指名称表,顺序对应 touch_mats[0..4] + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) + { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + std::cout << "========================================" << std::endl; + std::cout << "测试完成!" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << std::endl; + + // RS485 Modbus 设备会在智能指针离开作用域时自动关闭 + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_o6_modbus_1.cpp b/examples/test_o6_modbus_1.cpp new file mode 100644 index 0000000..1ef87b4 --- /dev/null +++ b/examples/test_o6_modbus_1.cpp @@ -0,0 +1,270 @@ +// O6 / Modbus / 左手 —— 速度/扭矩/动作序列与各类状态读取(封装 init/close) +#include +#include +#include +#include +#include +#include +#include +#include + +#include "LinkerHandApi.h" +#include "CommunicationCallbacks.h" +#include "Modbus.h" + +// 全局 RS485 Modbus 设备实例 +static std::unique_ptr modbus_device = nullptr; +static std::mutex modbus_mutex; +static const char* serial_port = "/dev/ttyUSB0"; // 默认串口设备,可根据实际情况修改 +static const int baudrate = 115200; // O6 Modbus 默认波特率 + +// 初始化串口 +bool init_modbus_device(const char* port, int baud) { + std::lock_guard lock(modbus_mutex); + + modbus_device = std::make_unique(std::string(port), baud, 'N'); + modbus_device->setDebugMode(false); // 关闭调试输出,避免干扰 + + if (!modbus_device->initialize()) { + std::cerr << "错误: RS485 Modbus 设备初始化失败!" << std::endl; + modbus_device.reset(); + return false; + } + return true; +} + +// 辅助函数:打印向量数据 +void printVector(const std::string& label, const std::vector& vec) { + std::cout << label << ": ["; + for (size_t i = 0; i < vec.size(); ++i) { + std::cout << static_cast(vec[i]); + if (i < vec.size() - 1) std::cout << ", "; + } + std::cout << "]" << std::endl; +} + +// 辅助函数:打印版本信息 +void printVersion(const std::string& version) { + std::cout << "版本信息:" << std::endl; + std::cout << version << std::endl; +} + +int main(int argc, char* argv[]) { + #ifdef _WIN32 + SetConsoleOutputCP(CP_UTF8); + #endif + + std::cout << "========================================" << std::endl; + std::cout << " O6 Modbus 测试示例 (RS485 Modbus Device 封装版)" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << std::endl; + + // 解析命令行参数(可选:指定串口设备) + const char* port = serial_port; + if (argc > 1) { + port = argv[1]; + } + + // 初始化 RS485 Modbus 设备 + std::cout << "正在初始化 RS485 Modbus 设备..." << std::endl; + std::cout << "串口设备: " << port << std::endl; + std::cout << "波特率: " << baudrate << std::endl; + + if (!init_modbus_device(port, baudrate)) { + std::cerr << "错误: RS485 Modbus 设备初始化失败!" << std::endl; + std::cerr << "请检查:" << std::endl; + std::cerr << " 1. 串口设备是否存在: " << port << std::endl; + std::cerr << " 2. 是否有权限访问串口(可能需要 sudo 或添加用户到 dialout 组)" << std::endl; + std::cerr << " 3. 串口是否被其他程序占用" << std::endl; + return -1; + } + + // 创建 O6 Modbus 手对象 + std::cout << "正在初始化 O6 Modbus 手..." << std::endl; + try { + LinkerHandApi hand(LINKER_HAND::O6, HAND_TYPE::LEFT, COMM_TYPE::MODBUS); + + // 设置 Modbus 回调函数 + std::cout << "设置 Modbus 回调函数..." << std::endl; + + hand.setModbusTxCallback([](uint8_t slave_id, uint16_t reg_addr, const uint8_t* data, uintptr_t data_len) -> int32_t { + if (!modbus_device) return -1; + // 直接发送 API 构造好的完整 Modbus 帧 + return modbus_device->sendRawFrame(data, data_len) ? 0 : -1; + }); + + hand.setModbusRxCallback([](uint8_t slave_id, uint16_t* reg_addr_out, uint8_t* data_out, uint8_t* data_len_out) -> int32_t { + if (!modbus_device || !data_out) return -1; + + int len = modbus_device->receiveCompleteFrame(data_out, 256, 500); + + if (len <= 0) return -1; + + if (data_out[0] != slave_id) return -1; + + *data_len_out = static_cast(len); + if (reg_addr_out) *reg_addr_out = 0; + + return 0; + }); + + std::cout << "初始化完成!" << std::endl; + std::cout << std::endl; + + // 测试 1: 设置速度 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 1: 设置速度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector speed(6, 128); // 6个关节,速度值 128 + hand.setSpeed(speed); + printVector("设置速度", speed); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << std::endl; + + // 测试 2: 设置扭矩 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 2: 设置扭矩" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector torque(6, 200); // 6个关节,扭矩值 200 + hand.setTorque(torque); + printVector("设置扭矩", torque); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << std::endl; + + // 测试 3: 手指动作序列 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 3: 手指动作序列" << std::endl; + std::cout << "----------------------------------------" << std::endl; + + // O6 有 6 个关节:大拇指弯曲、大拇指横摆、食指、中指、无名指、小拇指 + std::vector> poses = { + {255, 255, 255, 255, 255, 255}, // 完全张开 + {0, 255, 255, 255, 255, 255}, // 大拇指弯曲 + {255, 0, 255, 255, 255, 255}, // 大拇指横摆 + {255, 255, 0, 255, 255, 255}, // 食指弯曲 + {255, 255, 255, 0, 255, 255}, // 中指弯曲 + {255, 255, 255, 255, 0, 255}, // 无名指弯曲 + {255, 255, 255, 255, 255, 0}, // 小拇指弯曲 + {0, 0, 0, 0, 0, 0}, // 握拳 + {255, 255, 255, 255, 255, 255} // 完全张开 + }; + + for (size_t i = 0; i < poses.size(); ++i) { + std::cout << "动作 " << (i + 1) << "/" << poses.size() << ": "; + printVector("位置", poses[i]); + hand.fingerMove(poses[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + std::cout << std::endl; + + // 测试 4: 读取当前状态 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 4: 读取当前状态" << std::endl; + std::cout << "----------------------------------------" << std::endl; + for (int i = 0; i < 5; ++i) { + std::vector state = hand.getState(); + if (!state.empty()) { + printVector("当前关节位置", state); + } else { + std::cout << "读取状态失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + std::cout << std::endl; + + // 测试 5: 读取速度 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 5: 读取速度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector current_speed = hand.getSpeed(); + if (!current_speed.empty()) { + printVector("当前速度", current_speed); + } else { + std::cout << "读取速度失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 6: 读取扭矩 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 6: 读取扭矩" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector current_torque = hand.getTorque(); + if (!current_torque.empty()) { + printVector("当前扭矩", current_torque); + } else { + std::cout << "读取扭矩失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 7: 读取温度 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 7: 读取温度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector temperature = hand.getTemperature(); + if (!temperature.empty()) { + printVector("电机温度", temperature); + } else { + std::cout << "读取温度失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 8: 读取故障码 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 8: 读取故障码" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector fault_code = hand.getFaultCode(); + if (!fault_code.empty()) { + printVector("故障码", fault_code); + } else { + std::cout << "读取故障码失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 9: 读取版本信息 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 9: 读取版本信息" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::string version = hand.getVersion(); + if (!version.empty()) { + printVersion(version); + } else { + std::cout << "读取版本信息失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + // 测试 10: 读取压感数据 + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 10: 读取压感数据" << std::endl; + std::cout << "----------------------------------------" << std::endl; + for (int i = 0; i < 3; ++i) { + std::vector>> touch_mats = hand.getForce(); + // 手指名称表,顺序对应 touch_mats[0..4] + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) + { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + std::cout << "========================================" << std::endl; + std::cout << "测试完成!" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << std::endl; + + // RS485 Modbus 设备会在智能指针离开作用域时自动关闭 + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/examples/test_o6_modbus_2.cpp b/examples/test_o6_modbus_2.cpp new file mode 100644 index 0000000..da4000d --- /dev/null +++ b/examples/test_o6_modbus_2.cpp @@ -0,0 +1,241 @@ +// O6 / Modbus / 左手 —— 双线程并发:一线程读状态/参数,一线程设速度/扭矩/动作 +#include +#include +#include +#include +#include +#include +#include + +#include "LinkerHandApi.h" +#include "CommunicationCallbacks.h" +#include "Modbus.h" + +// 全局 Modbus 设备实例 +static std::unique_ptr g_modbus = nullptr; + + +// 辅助函数:打印向量数据 +void printVector(const std::string& label, const std::vector& vec) { + std::cout << label << ": ["; + for (size_t i = 0; i < vec.size(); ++i) { + std::cout << static_cast(vec[i]); + if (i < vec.size() - 1) std::cout << ", "; + } + std::cout << "]" << std::endl; +} + +// 辅助函数:打印版本信息 +void printVersion(const std::string& version) { + std::cout << "版本信息:" << std::endl; + std::cout << version << std::endl; +} + +int main(int argc, char* argv[]) { + #ifdef _WIN32 + SetConsoleOutputCP(CP_UTF8); + #endif + + std::cout << "========================================" << std::endl; + std::cout << " O6 Modbus 测试示例 (RS485 Modbus Device 封装版)" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << std::endl; + + // 1. 初始化 Modbus 设备 + g_modbus = std::make_unique("/dev/ttyUSB0", 115200); + if (!g_modbus->isOpen()) { + std::cerr << "串口打开失败,退出。" << std::endl; + return -1; + } + + // 2. 初始化手部 API + try { + LinkerHandApi hand(LINKER_HAND::O6, HAND_TYPE::LEFT, COMM_TYPE::MODBUS); + + // 3. 设置 Modbus 回调函数(事务由 LinkerHandO6Modbus::transact 保护) + hand.setModbusTxCallback([](uint8_t sid, uint16_t addr, const uint8_t* data, uintptr_t len) -> int32_t { + if (!g_modbus) return -1; + return g_modbus->sendRawFrame(data, len) ? 0 : -1; + }); + + hand.setModbusRxCallback([](uint8_t sid, uint16_t* addr_out, uint8_t* data_out, uint8_t* len_out) -> int32_t { + if (!g_modbus) return -1; + int len = g_modbus->receiveCompleteFrame(data_out, 256, 500); + if (len <= 0 || data_out[0] != sid) return -1; + *len_out = static_cast(len); + if (addr_out) *addr_out = 0; + return 0; + }); + + std::cout << "初始化完成!" << std::endl; + std::cout << std::endl; + + // 创建两个线程,同时测试获取函数和设置函数 + + std::thread get_thread([&hand]() { + for (int i = 0; i < 3; ++i) { + std::cout << "----------------------------------------" << std::endl; + std::cout << "获取函数测试" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 4: 读取当前状态" << std::endl; + std::cout << "----------------------------------------" << std::endl; + for (int i = 0; i < 5; ++i) { + std::vector state = hand.getState(); + if (!state.empty()) { + printVector("当前关节位置", state); + } else { + std::cout << "读取状态失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + std::cout << std::endl; + + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 5: 读取速度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector current_speed = hand.getSpeed(); + if (!current_speed.empty()) { + printVector("当前速度", current_speed); + } else { + std::cout << "读取速度失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 6: 读取扭矩" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector current_torque = hand.getTorque(); + if (!current_torque.empty()) { + printVector("当前扭矩", current_torque); + } else { + std::cout << "读取扭矩失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 7: 读取温度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector temperature = hand.getTemperature(); + if (!temperature.empty()) { + printVector("电机温度", temperature); + } else { + std::cout << "读取温度失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 8: 读取故障码" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector fault_code = hand.getFaultCode(); + if (!fault_code.empty()) { + printVector("故障码", fault_code); + } else { + std::cout << "读取故障码失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 9: 读取版本信息" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::string version = hand.getVersion(); + if (!version.empty()) { + printVersion(version); + } else { + std::cout << "读取版本信息失败(可能是回调未实现真实硬件通信)" << std::endl; + } + std::cout << std::endl; + + + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 10: 读取压感数据" << std::endl; + std::cout << "----------------------------------------" << std::endl; + for (int i = 0; i < 3; ++i) { + std::vector>> touch_mats = hand.getForce(); + // 手指名称表,顺序对应 touch_mats[0..4] + const std::array finger_name = { + "THUMB_TOUCH", "INDEX_TOUCH", "MIDDLE_TOUCH", "RING_TOUCH", "LITTLE_TOUCH" + }; + + for (size_t n = 0; n < touch_mats.size(); ++n) { + std::cout << finger_name[n] << ":\n"; + for (const auto &row : touch_mats[n]) + { + for (uint8_t val : row) + std::cout << std::setw(2) << static_cast(val) << ' '; + std::cout << '\n'; + } + std::cout << '\n'; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } + }); + + std::thread set_thread([&hand]() { + + for (int i = 0; i < 3; ++i) { + std::cout << "----------------------------------------" << std::endl; + std::cout << "设置函数测试" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 1: 设置速度" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector speed(6, 128); // 6个关节,速度值 128 + hand.setSpeed(speed); + printVector("设置速度", speed); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << std::endl; + + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 2: 设置扭矩" << std::endl; + std::cout << "----------------------------------------" << std::endl; + std::vector torque(6, 200); // 6个关节,扭矩值 200 + hand.setTorque(torque); + printVector("设置扭矩", torque); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << std::endl; + + + std::cout << "----------------------------------------" << std::endl; + std::cout << "测试 3: 手指动作序列" << std::endl; + std::cout << "----------------------------------------" << std::endl; + + // O6 有 6 个关节:大拇指弯曲、大拇指横摆、食指、中指、无名指、小拇指 + std::vector> poses = { + {255, 255, 255, 255, 255, 255}, // 完全张开 + {0, 255, 255, 255, 255, 255}, // 大拇指弯曲 + {255, 0, 255, 255, 255, 255}, // 大拇指横摆 + {255, 255, 0, 255, 255, 255}, // 食指弯曲 + {255, 255, 255, 0, 255, 255}, // 中指弯曲 + {255, 255, 255, 255, 0, 255}, // 无名指弯曲 + {255, 255, 255, 255, 255, 0}, // 小拇指弯曲 + {0, 0, 0, 0, 0, 0}, // 握拳 + {255, 255, 255, 255, 255, 255} // 完全张开 + }; + + for (size_t i = 0; i < poses.size(); ++i) { + std::cout << "动作 " << (i + 1) << "/" << poses.size() << ": "; + printVector("位置", poses[i]); + hand.fingerMove(poses[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + std::cout << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } + }); + + get_thread.join(); + set_thread.join(); + + std::cout << "========================================" << std::endl; + std::cout << "测试完成!" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << std::endl; + + // RS485 Modbus 设备会在智能指针离开作用域时自动关闭 + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } + return 0; +} diff --git a/img/example.png b/img/example.png deleted file mode 100644 index 64d54f6..0000000 Binary files a/img/example.png and /dev/null differ diff --git a/img/script.png b/img/script.png deleted file mode 100644 index 644c6e3..0000000 Binary files a/img/script.png and /dev/null differ diff --git a/include/CanBus.h b/include/CanBus.h deleted file mode 100644 index e8291f6..0000000 --- a/include/CanBus.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifdef __linux__ -#ifndef LINKERHAND_CAN_BUS_H -#define LINKERHAND_CAN_BUS_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Common.h" - -#include -#include -#include -#include // 包含 ifreq 和 IFNAMSIZ -#include // 包含 ioctl - -#include "ICanBus.h" - -namespace linkerhand { -namespace communication { - -/** - * @brief Linux CAN 总线实现 - */ -class CanBus : public linkerhand::communication::ICanBus - { - public: - CanBus(const std::string& interface, int bitrate, const LINKER_HAND linkerhand); - ~CanBus(); - - void send(const std::vector& data, uint32_t can_id, const bool wait = false) override; - CANFrame recv(uint32_t& id) override; - - void setReceiveTimeout(int seconds, int microseconds); - void updateSendRate(); - void updateReceiveRate(); - std::string printMillisecondTime(); - - private: - int socket_fd; - std::string interface; - int bitrate; - struct sockaddr_can addr; - struct ifreq ifr; // 确保 ifreq 是完整的类型 - std::mutex mutex_send; // 互斥锁 - std::mutex mutex_send2; // 互斥锁 - std::mutex mutex_receive; // 互斥锁 - - std::mutex send_mutex; // 用于保护发送计数器和时间 - std::atomic send_count; // 发送计数器 - std::chrono::steady_clock::time_point last_time; // 上一次记录时间 - - std::mutex receive_mutex; // 用于保护发送计数器和时间 - std::atomic receive_count; // 发送计数器 - std::chrono::steady_clock::time_point receive_last_time; // 上一次记录时间 - std::queue send_queue; // 发送队列 - - LINKER_HAND linker_hand; - }; -} // namespace communication -} // namespace linkerhand - -// 向后兼容:在全局命名空间中提供别名 -namespace Communication = linkerhand::communication; - -#endif -#endif // LINKERHAND_CAN_BUS_H - diff --git a/include/CanBusFactory.h b/include/CanBusFactory.h deleted file mode 100644 index d511616..0000000 --- a/include/CanBusFactory.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * @Author: liangshaoteng liangshaoteng2012@163.com - * @Date: 2026-01-29 17:01:44 - * @LastEditors: liangshaoteng liangshaoteng2012@163.com - * @LastEditTime: 2026-03-09 13:19:16 - * @FilePath: /linkerhand/include/CanBusFactory.h - * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE - */ -#ifndef LINKERHAND_CAN_BUS_FACTORY_H -#define LINKERHAND_CAN_BUS_FACTORY_H - -#include "ICanBus.h" -#include "CanBus.h" -#include "PCANBus.h" -#if USE_ETHERCAT -#include "EtherCAT.h" -#endif - -#include - -namespace linkerhand { -namespace communication { - class CanBusFactory - { - public: - static std::unique_ptr createCanBus( - uint32_t handId, - const std::string& interfaceOrChannel, - int bitrate, - const LINKER_HAND linkerHand - ) - { - (void)handId; // 标记为未使用,避免警告 - - #ifdef _WIN32 - // Windows 平台 - TPCANHandle channel = PCAN_USBBUS1; - TPCANBaudrate baudrate = PCAN_BAUD_1M; - if (interfaceOrChannel == "can1") { - channel = PCAN_USBBUS2; - } - return std::make_unique(channel, baudrate, linkerHand); - - #else - return std::make_unique(interfaceOrChannel, bitrate, linkerHand); - - #if USE_ETHERCAT - else if (interfaceOrChannel == "ethercat") { - return std::make_unique(handId); - } - #endif - - // 默认情况:抛出异常或返回 nullptr - throw std::runtime_error("Unsupported CAN interface: " + interfaceOrChannel); - // 或者返回 nullptr: - // return nullptr; - - #endif - } - }; -} // namespace communication -} // namespace linkerhand - -// 向后兼容:在全局命名空间中提供别名 -namespace Communication = linkerhand::communication; - -#endif // LINKERHAND_CAN_BUS_FACTORY_H diff --git a/include/CanFrame.h b/include/CanFrame.h deleted file mode 100644 index c0c3b6d..0000000 --- a/include/CanFrame.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef LINKERHAND_CAN_FRAME_H -#define LINKERHAND_CAN_FRAME_H - -#include -#include -#include - -#ifdef _WIN32 -#include "PCANBasic.h" -using CanFrame = TPCANMsg; -#elif defined(__linux__) -#include -#include -using CanFrame = struct can_frame; -#elif defined(__APPLE__) && defined(__MACH__) -std::cout << "This is macOS!" << std::endl; -#else -#error "Unsupported platform" -#endif - -// 公共的 CAN 帧结构体 -struct CANFrame -{ - uint32_t can_id; // CAN 帧 ID - uint8_t can_dlc; // 数据长度 - uint8_t data[8]; // 数据 -}; - - -#endif // LINKERHAND_CAN_FRAME_H \ No newline at end of file diff --git a/include/Common.h b/include/Common.h deleted file mode 100644 index fa6b9dc..0000000 --- a/include/Common.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef LINKERHAND_COMMON_H -#define LINKERHAND_COMMON_H - -// 为了与预编译库兼容,保持旧的枚举定义(非枚举类) -enum LINKER_HAND { - O6, - L6, - L7, - L10, - L20, - L21, - L25 -}; - -enum HAND_TYPE { - LEFT = 0x28, - RIGHT = 0x27 -}; - -enum COMM_TYPE { - COMM_CAN_0, - COMM_CAN_1, - COMM_MODBUS, - COMM_ETHERCAT -}; - -namespace linkerhand { - -/** - * @brief 通用配置和版本信息 - */ -namespace Common { - inline float current_hand_version = 1.0; -} - -/** - * @brief 新的枚举类(用于未来版本,当前保持向后兼容) - * - * 注意:当前库使用旧的枚举类型,这些枚举类用于未来版本 - */ -enum class HandModel { - O6, - L6, - L7, - L10, - L20, - L21, - L25 -}; - -enum class HandType { - LEFT = 0x28, - RIGHT = 0x27 -}; - -enum class CommType { - CAN_0, - CAN_1, - MODBUS, - ETHERCAT -}; - -} // namespace linkerhand - -#define SEND_DEBUG 0 -#define RECV_DEBUG 0 - -#endif // LINKERHAND_COMMON_H diff --git a/include/ErrorCode.h b/include/ErrorCode.h deleted file mode 100644 index cc4f1e7..0000000 --- a/include/ErrorCode.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef LINKERHAND_ERROR_CODE_H -#define LINKERHAND_ERROR_CODE_H - -#include -#include - -namespace linkerhand { - -/** - * @brief 错误码枚举 - * - * 定义 LinkerHand SDK 的所有错误类型 - */ -enum class HandError { - Success = 0, ///< 成功 - UnsupportedFeature, ///< 不支持的功能 - CommunicationError, ///< 通信错误 - InvalidParameter, ///< 无效参数 - DeviceNotFound, ///< 设备未找到 - Timeout, ///< 超时 - InvalidState, ///< 无效状态 - OperationFailed, ///< 操作失败 - NotInitialized, ///< 未初始化 - AlreadyInitialized, ///< 已初始化 - OutOfRange, ///< 超出范围 - UnknownError ///< 未知错误 -}; - -/** - * @brief 错误类别 - * - * 实现 std::error_category 接口,用于错误码分类 - */ -class HandErrorCategory : public std::error_category { -public: - const char* name() const noexcept override { - return "LinkerHand"; - } - - std::string message(int ev) const override { - switch (static_cast(ev)) { - case HandError::Success: - return "Success"; - case HandError::UnsupportedFeature: - return "Unsupported feature"; - case HandError::CommunicationError: - return "Communication error"; - case HandError::InvalidParameter: - return "Invalid parameter"; - case HandError::DeviceNotFound: - return "Device not found"; - case HandError::Timeout: - return "Timeout"; - case HandError::InvalidState: - return "Invalid state"; - case HandError::OperationFailed: - return "Operation failed"; - case HandError::NotInitialized: - return "Not initialized"; - case HandError::AlreadyInitialized: - return "Already initialized"; - case HandError::OutOfRange: - return "Out of range"; - case HandError::UnknownError: - default: - return "Unknown error"; - } - } -}; - -/** - * @brief 获取错误类别实例 - */ -inline const HandErrorCategory& hand_error_category() { - static HandErrorCategory instance; - return instance; -} - -/** - * @brief 将 HandError 转换为 std::error_code - */ -inline std::error_code make_error_code(HandError e) { - return std::error_code(static_cast(e), hand_error_category()); -} - -/** - * @brief 异常类:LinkerHand 异常基类 - */ -class HandException : public std::runtime_error { -public: - HandException(HandError error, const std::string& message) - : std::runtime_error(message), error_code_(error) {} - - HandError error_code() const noexcept { - return error_code_; - } - -private: - HandError error_code_; -}; - -/** - * @brief 异常类:不支持的功能 - */ -class UnsupportedFeatureException : public HandException { -public: - explicit UnsupportedFeatureException(const std::string& feature_name) - : HandException(HandError::UnsupportedFeature, - "Unsupported feature: " + feature_name), - feature_name_(feature_name) {} - - const std::string& feature_name() const noexcept { - return feature_name_; - } - -private: - std::string feature_name_; -}; - -/** - * @brief 异常类:通信错误 - */ -class CommunicationException : public HandException { -public: - explicit CommunicationException(const std::string& message) - : HandException(HandError::CommunicationError, message) {} -}; - -/** - * @brief 异常类:无效参数 - */ -class InvalidParameterException : public HandException { -public: - explicit InvalidParameterException(const std::string& message) - : HandException(HandError::InvalidParameter, message) {} -}; - -} // namespace linkerhand - -// 注册错误码到标准库 -namespace std { - template<> - struct is_error_code_enum : true_type {}; -} - -#endif // LINKERHAND_ERROR_CODE_H diff --git a/include/HandFactory.h b/include/HandFactory.h deleted file mode 100644 index d60238a..0000000 --- a/include/HandFactory.h +++ /dev/null @@ -1,182 +0,0 @@ -#ifndef LINKERHAND_HAND_FACTORY_H -#define LINKERHAND_HAND_FACTORY_H - -#include -#include -#include -#include - -#include "IHand.h" -#include "LinkerHandL6.h" -#include "LinkerHandL7.h" -#include "LinkerHandL10.h" -#include "LinkerHandL20.h" -#include "LinkerHandL25.h" -#include "ModbusLinkerHandL10.h" -#include "Common.h" - - - -namespace linkerhand { -namespace factory { - -/** - * @brief 手型号工厂类 - * - * 根据手型号、手类型和通信类型创建对应的手实例 - */ -class HandFactory { -public: - /** - * @brief 创建手实例 - * @param type 手型号 - * @param handId 手ID(左手/右手) - * @param commType 通信类型 - * @return 手实例的智能指针 - * @throws std::invalid_argument 如果参数无效 - */ - static std::unique_ptr createHand(LINKER_HAND type, uint32_t handId, COMM_TYPE commType) { - - if (handId != static_cast(LEFT) && - handId != static_cast(RIGHT)) - { - throw std::invalid_argument("Unsupported hand type"); - } - - std::string canChannel; - int baudrate = 1000000; - - switch (commType) - { - case COMM_CAN_0: - canChannel = "can0"; - break; - case COMM_CAN_1: - canChannel = "can1"; - break; - case COMM_MODBUS: - canChannel = "modbus"; - break; - case COMM_ETHERCAT: - canChannel = "ethercat"; - break; - default: - throw std::invalid_argument("Unknown comm type"); - break; - } - - if (canChannel == "can0" || canChannel == "can1" || canChannel == "ethercat") { - switch (type) { - case O6: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate)); - break; - case L6: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate)); - break; - case L7: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate)); - break; - case L10: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate)); - break; - case L20: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate)); - break; - case L21: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate, 1)); - break; - case L25: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate, 0)); - break; - default: - throw std::invalid_argument("Unknown hand type"); - } - } else if (canChannel == "modbus") { - #if USE_RMAN - switch (type) { - case L10: - return std::unique_ptr(std::make_unique(handId)); - default: - throw std::invalid_argument("Unknown hand type"); - break; - } - #else - throw std::runtime_error("ModBus support is disabled (USE_RMAN=0)"); - #endif - } - - return nullptr; - } - - - static std::unique_ptr createHand(LINKER_HAND type, uint32_t handId, const std::string canChannel, const int baudrate) { - - if (handId != static_cast(LEFT) && - handId != static_cast(RIGHT)) - { - throw std::invalid_argument("Unsupported hand type"); - } - - if (containsIgnoreCase(canChannel, "can")) { - switch (type) { - case O6: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate)); - break; - case L6: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate)); - break; - case L7: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate)); - break; - case L10: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate)); - break; - case L20: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate)); - break; - case L21: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate, 1)); - break; - case L25: - return std::unique_ptr(std::make_unique(handId, canChannel, baudrate, 0)); - break; - default: - throw std::invalid_argument("Unknown hand type"); - } - } else if (canChannel == "modbus") { - #if USE_RMAN - switch (type) { - case L10: - return std::unique_ptr(std::make_unique(handId)); - default: - throw std::invalid_argument("Unknown hand type"); - break; - } - #else - throw std::runtime_error("ModBus support is disabled (USE_RMAN=0)"); - #endif - } - - return nullptr; - } - -private: - - static std::string toLower(const std::string& str) { - std::string result = str; - std::transform(result.begin(), result.end(), result.begin(), ::tolower); - return result; - } - - static bool containsIgnoreCase(const std::string& str, const std::string& target) { - return toLower(str).find(toLower(target)) != std::string::npos; - } -}; - -} // namespace factory -} // namespace linkerhand - -// 向后兼容:在全局命名空间中提供别名 -using HandFactory = linkerhand::factory::HandFactory; - -#endif // LINKERHAND_HAND_FACTORY_H diff --git a/include/ICanBus.h b/include/ICanBus.h deleted file mode 100644 index 305ad03..0000000 --- a/include/ICanBus.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef LINKERHAND_ICANBUS_H -#define LINKERHAND_ICANBUS_H - -#include -#include -#include -#include "Common.h" -#include "CanFrame.h" - -namespace linkerhand { -namespace communication { - -/** - * @brief CAN 总线接口 - * - * 定义 CAN 总线通信的标准接口 - */ -class ICanBus { -public: - virtual ~ICanBus() = default; - - /** - * @brief 发送 CAN 帧 - * @param data 要发送的数据 - * @param can_id CAN 帧 ID - * @param wait 是否等待发送完成(默认 false) - */ - virtual void send(const std::vector& data, uint32_t can_id, - const bool wait = false) = 0; - - /** - * @brief 接收 CAN 帧 - * @param id CAN 帧 ID(输出参数) - * @return 接收到的 CAN 帧 - */ - virtual CANFrame recv(uint32_t& id) = 0; -}; - -} // namespace communication -} // namespace linkerhand - -// 向后兼容的别名 -namespace Communication = linkerhand::communication; - -#endif // LINKERHAND_ICANBUS_H diff --git a/include/ICommunication.h b/include/ICommunication.h deleted file mode 100644 index df6d6ab..0000000 --- a/include/ICommunication.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef LINKERHAND_ICOMMUNICATION_H -#define LINKERHAND_ICOMMUNICATION_H - -#include -#include - -namespace linkerhand { -namespace communication { - -/** - * @brief 通信接口基类 - * - * 定义通用的通信接口,支持 ModBus 等协议 - */ -class ICommunication { -public: - virtual ~ICommunication() = default; - - /** - * @brief 发送数据 - * @param data 要发送的数据 - * @param id 设备ID(输入输出参数) - * @param start_address 起始地址(默认0) - * @param num 数量(默认0) - */ - virtual void send(const std::vector& data, uint32_t &id, - const int &start_address = 0, const int &num = 0) = 0; - - /** - * @brief 接收数据 - * @param id 设备ID(输入输出参数) - * @param start_address 起始地址(默认0) - * @param num 数量(默认0) - * @return 接收到的数据 - */ - virtual std::vector recv(uint32_t& id, - const int &start_address = 0, - const int &num = 0) = 0; -}; - -} // namespace communication -} // namespace linkerhand - -#endif // LINKERHAND_ICOMMUNICATION_H \ No newline at end of file diff --git a/include/IHand.h b/include/IHand.h deleted file mode 100644 index 27e4faa..0000000 --- a/include/IHand.h +++ /dev/null @@ -1,230 +0,0 @@ -#ifndef LINKERHAND_IHAND_H -#define LINKERHAND_IHAND_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "RangeToArc.h" -#include "Common.h" -#include "ErrorCode.h" - -namespace linkerhand { -namespace hand { - -/** - * @brief 灵巧手接口基类 - * - * 定义所有手型号必须实现的基础接口 - * 注意:不支持的方法会抛出异常而不是返回空值 - */ -class IHand -{ -public: - virtual ~IHand() = default; - // 设置关节位置 - virtual void setJointPositions(const std::vector &jointAngles) = 0; - virtual void setJointPositionArc(const std::vector &jointAngles) - { - (void) jointAngles; - throw UnsupportedFeatureException("setJointPositionArc"); - } - // 获取速度数据 - virtual std::vector getSpeed() - { - throw UnsupportedFeatureException("getSpeed"); - } - // 设置关节速度 - virtual void setSpeed(const std::vector &speed) - { - (void) speed; - throw UnsupportedFeatureException("setSpeed"); - } - // 获取当前关节位置 - virtual std::vector getCurrentStatus() - { - throw UnsupportedFeatureException("getCurrentStatus"); - } - - virtual std::vector getCurrentStatusArc() - { - throw UnsupportedFeatureException("getCurrentStatusArc"); - } - // 获取电机故障码 - virtual std::vector getFaultCode() - { - throw UnsupportedFeatureException("getFaultCode"); - } - // 获取电机电流 - virtual std::vector getCurrent() - { - throw UnsupportedFeatureException("getCurrent"); - } - // ------------------------------------------------------ - // 获取压感数据 - virtual std::vector> getForce(const int type) - { - (void)type; - throw UnsupportedFeatureException("getForce"); - } - virtual std::vector>> getForce() - { - throw UnsupportedFeatureException("getForce"); - } - // 获取大拇指压感数据 - virtual std::vector getThumbForce() - { - throw UnsupportedFeatureException("getThumbForce"); - } - // 获取食指压感数据 - virtual std::vector getIndexForce() - { - throw UnsupportedFeatureException("getIndexForce"); - } - // 获取中指压感数据 - virtual std::vector getMiddleForce() - { - throw UnsupportedFeatureException("getMiddleForce"); - } - // 获取无名指压感数据 - virtual std::vector getRingForce() - { - throw UnsupportedFeatureException("getRingForce"); - } - // 获取小拇指压感数据 - virtual std::vector getLittleForce() - { - throw UnsupportedFeatureException("getLittleForce"); - } - // ------------------------------------------------------ - // 获取五指法向力 - virtual std::vector getNormalForce() - { - throw UnsupportedFeatureException("getNormalForce"); - } - // 获取五指切向力 - virtual std::vector getTangentialForce() - { - throw UnsupportedFeatureException("getTangentialForce"); - } - // 获取五指法向力方向 - virtual std::vector getTangentialForceDir() - { - throw UnsupportedFeatureException("getTangentialForceDir"); - } - // 获取五指接近感应 - virtual std::vector getApproachInc() - { - throw UnsupportedFeatureException("getApproachInc"); - } - // ------------------------------------------------------ - // 设置扭矩 L20暂不支持 - virtual void setTorque(const std::vector &torque) - { - (void)torque; - throw UnsupportedFeatureException("setTorque"); - } - // 获取电机扭矩 L20暂不支持 - virtual std::vector getTorque() - { - throw UnsupportedFeatureException("getTorque"); - } - // 获取电机温度 L20暂不支持 - virtual std::vector getTemperature() - { - throw UnsupportedFeatureException("getTemperature"); - } - // 获取版本号 目前仅支持L10 - virtual std::string getVersion() - { - throw UnsupportedFeatureException("getVersion"); - } - // 获取设备ID L20协议 - virtual std::vector getUID() - { - throw UnsupportedFeatureException("getUID"); - } - // 手指堵转或过流判断计数阀值 L20协议 - virtual std::vector getRotorLockCount() - { - throw UnsupportedFeatureException("getRotorLockCount"); - } - // 清除电机故障码 目前仅支持L20 - virtual void clearFaultCode(const std::vector &code) - { - (void)code; - throw UnsupportedFeatureException("clearFaultCode"); - } - // 设置电流 目前仅支持L20 - virtual void setCurrent(const std::vector ¤t) - { - (void)current; - throw UnsupportedFeatureException("setCurrent"); - } - // 设置电机使能 目前仅支持L25 - virtual void setMotorEnable(const std::vector &enable) - { - (void)enable; - throw UnsupportedFeatureException("setMotorEnable"); - } - // 设置电机使能 目前仅支持L25 - virtual void setMotorDisable(const std::vector &disable) - { - (void)disable; - throw UnsupportedFeatureException("setMotorDisable"); - } - - // --------------------------------------------------------------------- - - virtual std::vector getSubVector(const std::vector &vec) - { - std::vector result; - if (vec.size() > 1) result.insert(result.end(), vec.begin() + 1, vec.end()); - return result; - } - - virtual std::vector getSubVector(const std::vector& vec1, const std::vector& vec2) - { - std::vector result; - if (vec1.size() > 1) result.insert(result.end(), vec1.begin() + 1, vec1.end()); - if (vec2.size() > 1) result.insert(result.end(), vec2.begin() + 1, vec2.end()); - return result; - } - - virtual std::string getCurrentTime() - { - // 获取当前时间点 - auto now = std::chrono::high_resolution_clock::now(); - - // 使用std::put_time格式化时间点为字符串 - std::time_t time = std::chrono::system_clock::to_time_t(now); - std::stringstream ss; - ss << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S"); - - // 获取微秒部分并添加到字符串中 - auto duration = now.time_since_epoch(); - auto microseconds = std::chrono::duration_cast(duration % std::chrono::seconds(1)).count(); - // 只保留毫秒部分 - int milliseconds = microseconds / 1000; - ss << "." << std::setfill('0') << std::setw(3) << milliseconds; - // 微妙 - // ss << "." << std::setfill('0') << std::setw(6) << microseconds; - - // 打印格式化的时间字符串 - // std::cout << "send time: " << ss.str() << std::endl; - - return ss.str(); - } - -}; - -} // namespace hand -} // namespace linkerhand - -#endif // LINKERHAND_IHAND_H - diff --git a/include/LinkerHandApi.h b/include/LinkerHandApi.h deleted file mode 100644 index c0a1180..0000000 --- a/include/LinkerHandApi.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef LINKERHAND_API_H -#define LINKERHAND_API_H - -#include -#include -#include -#include -#include "HandFactory.h" -#include "Common.h" -#include "IHand.h" - -/** - * @brief LinkerHand API 主类 - * - * 提供统一的接口用于控制各种型号的灵巧手设备 - * - * 注意:为了与预编译库兼容,此类保持在全局命名空间 - */ -class LinkerHandApi -{ -public: - /** - * @brief 构造函数 - * @param handModel 手型号(LINKER_HAND 枚举) - * @param handType 手类型(左手/右手) - * @param commType 通信类型(默认 CAN_0) - */ - LinkerHandApi(const LINKER_HAND &handModel, const HAND_TYPE &handType, - const COMM_TYPE commType = COMM_CAN_0); - LinkerHandApi(const LINKER_HAND &handModel, const HAND_TYPE &handType, - const std::string canChannel, const int baudrate); - ~LinkerHandApi(); - - // 设置关节位置 - void fingerMove(const std::vector &pose); - void fingerMoveArc(const std::vector &pose); - // 设置速度 - void setSpeed(const std::vector &speed); - // 设置扭矩 - void setTorque(const std::vector &torque); - // 获取压感 - std::vector>> getForce(); - // 获取速度 - std::vector getSpeed(); - // 获取当前关节状态 - std::vector getState(); - std::vector getStateArc(); - // 获取版本号 - std::string getVersion(); - - // ---------------------------------------------------------- - - // 获取电机温度 - std::vector getTemperature(); - // 获取电机故障码 - std::vector getFaultCode(); - // 获取当前电流 - std::vector getCurrent(); - // 获取当前最大扭矩 - std::vector getTorque(); - // ------------------------- 待开发 -------------------------- - // 设置电流 目前仅支持L20 - void setCurrent(const std::vector ¤t); - // 清除电机故障码 目前仅支持L20 - void clearFaultCode(const std::vector &torque = std::vector(5, 1)); - // 设置电机使能 目前仅支持L25 - void setEnable(const std::vector &enable = std::vector(5, 0)); - // 设置电机使能 目前仅支持L25 - void setDisable(const std::vector &disable = std::vector(5, 1)); - -private: - // 获取法向压力 - void getNormalForce(); - // 获取切向压力 - void getTangentialForce(); - // 获取切向压力方向 - void getTangentialForceDir(); - // 获取接近感应 - void getApproachInc(); - -private: - std::unique_ptr hand; - uint32_t handId; -public: - LINKER_HAND handModel_; // 手型号(L6, L7, L10, L20, L21, L25 等) - HAND_TYPE handType_; -}; - -// 在新命名空间中提供类型别名(用于未来版本) -namespace linkerhand { -namespace api { - using LinkerHandApi = ::LinkerHandApi; -} // namespace api -} // namespace linkerhand - -#endif // LINKERHAND_API_H diff --git a/include/LinkerHandL10.h b/include/LinkerHandL10.h deleted file mode 100644 index 5bce8d4..0000000 --- a/include/LinkerHandL10.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef LINKERHAND_L10_H -#define LINKERHAND_L10_H - -#include -#include -#include -#include -#include -#include -#include - -#include "IHand.h" -#include "CanBusFactory.h" - -namespace linkerhand { -namespace hand { - -// L10 型号的帧属性枚举 -enum class L10FrameProperty -{ - // INVALID_FRAME_PROPERTY = 0x00, // 无效的can帧属性 - JOINT_POSITION_RCO = 0x01, // 关节1-6的关节位置 - TORQUE_LIMIT = 0x02, // 五根手指的转矩限制 - TORQUE_LIMIT_2 = 0x03, // 五根手指的转矩限制2 - JOINT_POSITION2_RCO = 0x04, // 关节7-10的关节位置 - JOINT_SPEED = 0x05, // 五根手指的速度 - JOINT_SPEED_2 = 0x06, // 五根手指的速度2 - REQUEST_DATA_RETURN = 0x09, // 获取所有关节位置和压力 - // JOINT_POSITION_N = 0x11, - // MAX_PRESS_N = 0x12, - HAND_NORMAL_FORCE = 0X20, // 五个手指的法向压力 - HAND_TANGENTIAL_FORCE = 0X21, // 五个手指的切向压力 - HAND_TANGENTIAL_FORCE_DIR = 0X22, // 五个手指的切向方向 - HAND_APPROACH_INC = 0X23, // 五个手指指接近感应 - THUMB_ALL_DATA = 0x28, // 大拇指所有数据 | 返回 1法向压力 2切向压力 3切向方向 4接近感应 - INDEX_FINGER_ALL_DATA = 0x29, // 食指所有数据 | 返回 1法向压力 2切向压力 3切向方向 4接近感应 - MIDDLE_FINGER_ALL_DATA = 0x30, // 中指所有数据 | 返回 1法向压力 2切向压力 3切向方向 4接近感应 - RING_FINGER_ALL_DATA = 0x31, // 无名指所有数据 | 返回 1法向压力 2切向压力 3切向方向 4接近感应 - LITTLE_FINGER_ALL_DATA = 0x32, // 小拇指所有数据 | 返回 1法向压力 2切向压力 3切向方向 4接近感应 - MOTOR_TEMPERATURE_1 = 0x33, // 电机温度1 - MOTOR_TEMPERATURE_2 = 0x34, // 电机温度2 - MOTOR_FAULT_CODE_1 = 0x35, // 电机故障码1 - MOTOR_FAULT_CODE_2 = 0x36, // 电机故障码2 - LINKER_HAND_VERSION = 0X64, // 版本号 - - // 新压感 - TOUCH_SENSOR_TYPE = 0xB0, // 触觉传感器类型 - THUMB_TOUCH = 0xB1, // 大拇指触觉传感 - INDEX_TOUCH = 0xB2, // 食指触觉传感 - MIDDLE_TOUCH = 0xB3, // 中指触觉传感 - RING_TOUCH = 0xB4, // 无名指触觉传感 - LITTLE_TOUCH = 0xB5, // 小拇指触觉传感 - PALM_TOUCH = 0xB6, // 手掌指触觉传感 -}; - -/** - * @brief L10 型号灵巧手实现类 - * - * 提供 L10 型号的所有功能实现 - */ -class L10Hand : public IHand -{ -public: - L10Hand(uint32_t handId, const std::string &canChannel, int baudrate); - ~L10Hand(); - - // 设置关节位置 - void setJointPositions(const std::vector &jointAngles) override; - void setJointPositionArc(const std::vector &jointAngles) override; - // 设置最大扭矩 - void setTorque(const std::vector &torque) override; - // 设置关节速度 - void setSpeed(const std::vector &speed) override; - // 获取当前速度 - std::vector getSpeed() override; - // 获取当前关节状态 - std::vector getCurrentStatus() override; - std::vector getCurrentStatusArc() override; - //-------------------------------------------------------------------- - // 获取所有压感数据 - std::vector>> getForce() override; - // 获取五个手指的法向压力 - std::vector getNormalForce() override; - // 获取五个手指的切向压力 - std::vector getTangentialForce() override; - // 获取五个手指的切向方向 - std::vector getTangentialForceDir() override; - // 获取五个手指指接近感应 - std::vector getApproachInc() override; - //-------------------------------------------------------------------- - // 获取版本信息 - std::string getVersion() override; - // 获取电机温度 - std::vector getTemperature() override; - // 获取电机故障码 - std::vector getFaultCode() override; - // 获取电机电流 - std::vector getCurrent() override; // 暂时无用 - // 获取所有关节位置和压力 - std::vector requestAllStatus(); // 暂时无用 - // 获取当前扭矩 - std::vector getTorque() override; - -private: - uint32_t handId; - std::unique_ptr bus; - std::thread receiveThread; - bool running; - std::mutex responseMutex; - - void receiveResponse(); - - std::queue> responseQueue; // 通用响应队列 - std::condition_variable queueCond; // 通用队列条件变量 - std::mutex queueMutex; // 通用队列互斥锁 - - // 队列和条件变量 - std::vector joint_position; - std::vector joint_position2; - std::vector joint_speed; - std::vector joint_speed_2; - - std::vector normal_force; - std::vector tangential_force; - std::vector tangential_force_dir; - std::vector approach_inc; - - std::vector thumb_pressure; - std::vector index_finger_pressure; - std::vector middle_finger_pressure; - std::vector ring_finger_pressure; - std::vector little_finger_pressure; - - std::vector>> touch_mats; - - // 最大扭矩 - std::vector max_torque; - std::vector max_torque_2; - - // 电机温度 - std::vector motorTemperature_1; - std::vector motorTemperature_2; - - // 电机故障码 - std::vector motorFaultCode_1; - std::vector motorFaultCode_2; - - // 版本信息 - std::vector version; - - uint8_t sensor_type = 0; -}; - -} // namespace hand -} // namespace linkerhand - -// 向后兼容:在旧命名空间中提供别名 -namespace LinkerHandL10 { - using FRAME_PROPERTY = linkerhand::hand::L10FrameProperty; - using LinkerHand = linkerhand::hand::L10Hand; -} // namespace LinkerHandL10 - -#endif // LINKERHAND_L10_H \ No newline at end of file diff --git a/include/LinkerHandL20.h b/include/LinkerHandL20.h deleted file mode 100644 index 0a44ea7..0000000 --- a/include/LinkerHandL20.h +++ /dev/null @@ -1,186 +0,0 @@ -#ifndef LINKERHAND_L20_H -#define LINKERHAND_L20_H - -#include -#include -#include -#include -#include -#include - -#include "IHand.h" -#include "CanBusFactory.h" - -namespace linkerhand { -namespace hand { - -// L20 型号的帧属性枚举 -enum class L20FrameProperty -{ - INVALID_FRAME_PROPERTY = 0x00, // 无效的can帧属性 | 无返回 - JOINT_PITCH_R = 0x01, // 短帧俯仰角-手指根部弯曲程度 | 返回本类型数据 - JOINT_YAW_R = 0x02, // 短帧航向角-手指横摆,控制间隙 | 返回本类型数据 - JOINT_ROLL_R = 0x03, // 短帧横滚角-只有大拇指副用到了 | 返回本类型数据 - JOINT_TIP_R = 0x04, // 短帧指尖角度弯曲程度 | 返回本类型数据 - JOINT_SPEED_R = 0x05, // 短帧速度 电机运行速度控制 | 返回本类型数据 - JOINT_CURRENT_R = 0x06, // 短帧电流 电机运行电流 | 返回本类型数据 - JOINT_FAULT_R = 0x07, // 短帧故障 电机运行故障 1清除 0查询 | 返回本类型数据 - ROTOR_LOCK_COUNT = 0x08, // 手指堵转或过流判断计数阀值 | 返回本类型数据 - REQUEST_DATA_RETURN = 0x09, // 请求数据返回 | 返回所有手指控制数据,返回数据会分若干帧发出。 - - JOINT_PITCH_NR = 0x11, // 俯仰角-手指根部弯曲 | 不返回本类型数据 - JOINT_YAW_NR = 0x12, // 航向角-手指横摆,控制间隙 | 不返回本类型数据 - JOINT_ROLL_NR = 0x13, // 横滚角-只有大拇指副用到了 | 不返回本类型数据 - JOINT_TIP_NR = 0x14, // 指尖角度控制 | 不返回本类型数据 - JOINT_SPEED_NR = 0x15, // 速度 电机运行速度控制 | 不返回本类型数据 - JOINT_CURRENT_NR = 0x16, // 电流 电机运行电流反馈 | 不返回本类型数据 - JOINT_FAULT_NR = 0x17, // 故障 电机运行故障反馈 | 不返回本类型数据 - HAND_NORMAL_FORCE = 0X20, // 返回五个手指的法向压力 - HAND_TANGENTIAL_FORCE = 0X21, // 返回五个手指的切向压力 - HAND_TANGENTIAL_FORCE_DIR = 0X22, // 返回五个手指的切向方向 数值0-127对应实际切向力角度0-359,无切向力保持255 - HAND_APPROACH_INC = 0X23, // 返回五个手指指接近感应 - - THUMB_ALL_DATA = 0x30, // 大拇指所有数据 | 返回 1法向压力 2切向压力 3切向方向 4接近感应 - INDEX_FINGER_ALL_DATA = 0x31, // 食指所有数据 | 返回 1法向压力 2切向压力 3切向方向 4接近感应 - MIDDLE_FINGER_ALL_DATA = 0x32, // 中指所有数据 | 返回 1法向压力 2切向压力 3切向方向 4接近感应 - RING_FINGER_ALL_DATA = 0x33, // 无名指所有数据 | 返回 1法向压力 2切向压力 3切向方向 4接近感应 - LITTLE_FINGER_ALL_DATA = 0x34, // 小拇指所有数据 | 返回 1法向压力 2切向压力 3切向方向 4接近感应 - - HAND_UID = 0xC0, // 设备唯一标识码 只读 -------- - HAND_HARDWARE_VERSION = 0xC1, // 硬件版本 只读 -------- - HAND_SOFTWARE_VERSION = 0xC2, // 软件版本 只读 -------- - HAND_COMM_ID = 0xC3, // 设备ID 可读写 1字节 - HAND_SAVE_PARAMETER = 0xCF, // 保存参数 只写 -------- - - // 新压感 - TOUCH_SENSOR_TYPE = 0xB0, // 触觉传感器类型 - THUMB_TOUCH = 0xB1, // 大拇指触觉传感 - INDEX_TOUCH = 0xB2, // 食指触觉传感 - MIDDLE_TOUCH = 0xB3, // 中指触觉传感 - RING_TOUCH = 0xB4, // 无名指触觉传感 - LITTLE_TOUCH = 0xB5, // 小拇指触觉传感 - PALM_TOUCH = 0xB6 // 手掌指触觉传感 -}; - -/** - * @brief L20 型号灵巧手实现类 - * - * 提供 L20 型号的所有功能实现 - */ -class L20Hand : public IHand { -public: - L20Hand(uint32_t handId, const std::string& canChannel, int baudrate); - ~L20Hand(); - - // 设置关节位置 - void setJointPositions(const std::vector &jointAngles) override; - void setJointPositionArc(const std::vector &jointAngles) override; - // 设置关节速度 - void setSpeed(const std::vector &speed) override; - // 获取当前速度 - std::vector getSpeed() override; - // 获取当前关节状态 - std::vector getCurrentStatus() override; - std::vector getCurrentStatusArc() override; - //-------------------------------------------------------------------- - // 获取所有压感数据 - std::vector>> getForce() override; - // 获取五个手指的法向压力 - std::vector getNormalForce() override; - // 获取五个手指的切向压力 - std::vector getTangentialForce() override; - // 获取五个手指的切向方向 - std::vector getTangentialForceDir() override; - // 获取五个手指指接近感应 - std::vector getApproachInc() override; - #if 0 - // 获取大拇指压感数据 - std::vector getThumbForce() override; - // 获取食指压感数据 - std::vector getIndexForce() override; - // 获取中指压感数据 - std::vector getMiddleForce() override; - // 获取无名指压感数据 - std::vector getRingForce() override; - // 获取小拇指压感数据 - std::vector getLittleForce() override; - #endif - //-------------------------------------------------------------------- - // 获取电机故障码 - std::vector getFaultCode() override; - // 获取电机电流 - std::vector getCurrent() override; - // 清除电机故障码 - void clearFaultCode(const std::vector &code = std::vector(5, 1)) override; - // 设置电流 - void setCurrent(const std::vector ¤t) override; - // 获取版本号 - std::string getVersion() override; - // 获取设备唯一标志 - std::vector getUID() override; - // 获取堵转计数 - std::vector getRotorLockCount() override; - -private: - uint32_t handId; - std::unique_ptr bus; - std::thread receiveThread; - bool running; - std::mutex responseMutex; - - void receiveResponse(); - - // 故障码 - std::vector motor_fault_code; - // 电流 - std::vector motor_current; - // 速度 - std::vector motor_speed; - - // 压感数据 - std::vector> force_data; - - std::vector normal_force; - std::vector tangential_force; - std::vector tangential_force_dir; - std::vector approach_inc; - - std::vector thumb_pressure; - std::vector index_finger_pressure; - std::vector middle_finger_pressure; - std::vector ring_finger_pressure; - std::vector little_finger_pressure; - - std::vector>> touch_mats; - - // 关节位置 - std::vector joint_position1; - std::vector joint_position2; - std::vector joint_position3; - std::vector joint_position4; - - // 版本号 - std::vector hand_hardware_version; - std::vector hand_software_version; - // 设备ID - std::vector hand_comm_id; - - // 设备唯一标志 - std::vector hand_uid; - - // 堵转计数 - std::vector rotor_lock_count; - - uint8_t sensor_type = 0; -}; - -} // namespace hand -} // namespace linkerhand - -// 向后兼容:在旧命名空间中提供别名 -namespace LinkerHandL20 { - using FRAME_PROPERTY = linkerhand::hand::L20FrameProperty; - using LinkerHand = linkerhand::hand::L20Hand; -} // namespace LinkerHandL20 - -#endif // LINKERHAND_L20_H \ No newline at end of file diff --git a/include/LinkerHandL25.h b/include/LinkerHandL25.h deleted file mode 100644 index b660f85..0000000 --- a/include/LinkerHandL25.h +++ /dev/null @@ -1,443 +0,0 @@ -#ifndef LINKERHAND_L25_H -#define LINKERHAND_L25_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include "IHand.h" -#include "CanBusFactory.h" - -namespace linkerhand { -namespace hand { - -// L25/L21 型号的帧属性枚举 -enum class L25FrameProperty -{ - INVALID_FRAME_PROPERTY = 0x00, // 无效的can帧属性 | 无返回 - // 并行指令区域 - ROLL_POS = 0x01, // 横滚关节位置 | 坐标系建在每个手指的指根部位,按手指伸直的状态去定义旋转角度 [10,11,12,13,14] - YAW_POS = 0x02, // 航向关节位置 | 坐标系建在每个手指的指根部位,按手指伸直的状态去定义旋转角度 [5,6,7,8,9] - ROOT1_POS = 0x03, // 指根1关节位置 | 最接近手掌的指根关节 [0,1,2,3,4] - ROOT2_POS = 0x04, // 指根2关节位置 | 最接近手掌的指根关节 [15, 16,17,18,19] - ROOT3_POS = 0x05, // 指根3关节位置 | 最接近手掌的指根关节 暂无 - TIP_POS = 0x06, // 指尖关节位置 | 最接近手掌的指根关节 [20,21,22,23,24] - - ROLL_SPEED = 0x09, // 横滚关节速度 | 坐标系建在每个手指的指根部位,按手指伸直的状态去定义旋转角度 - YAW_SPEED = 0x0A, // 航向关节速度 | 坐标系建在每个手指的指根部位,按手指伸直的状态去定义旋转角度 - ROOT1_SPEED = 0x0B, // 指根1关节速度 | 最接近手掌的指根关节 - ROOT2_SPEED = 0x0C, // 指根2关节速度 | 最接近手掌的指根关节 - ROOT3_SPEED = 0x0D, // 指根3关节速度 | 最接近手掌的指根关节 - TIP_SPEED = 0x0E, // 指尖关节速度 | 最接近手掌的指根关节 - - ROLL_TORQUE = 0x11, // 横滚关节扭矩 | 坐标系建在每个手指的指根部位,按手指伸直的状态去定义旋转角度 - YAW_TORQUE = 0x12, // 航向关节扭矩 | 坐标系建在每个手指的指根部位,按手指伸直的状态去定义旋转角度 - ROOT1_TORQUE = 0x13, // 指根1关节扭矩 | 最接近手掌的指根关节 - ROOT2_TORQUE = 0x14, // 指根2关节扭矩 | 最接近手掌的指根关节 - ROOT3_TORQUE = 0x15, // 指根3关节扭矩 | 最接近手掌的指根关节 - TIP_TORQUE = 0x16, // 指尖关节扭矩 | 最接近手掌的指根关节 - - ROLL_FAULT = 0x19, // 横滚关节故障码 | 坐标系建在每个手指的指根部位,按手指伸直的状态去定义旋转角度 - YAW_FAULT = 0x1A, // 航向关节故障码 | 坐标系建在每个手指的指根部位,按手指伸直的状态去定义旋转角度 - ROOT1_FAULT = 0x1B, // 指根1关节故障码 | 最接近手掌的指根关节 - ROOT2_FAULT = 0x1C, // 指根2关节故障码 | 最接近手掌的指根关节 - ROOT3_FAULT = 0x1D, // 指根3关节故障码 | 最接近手掌的指根关节 - TIP_FAULT = 0x1E, // 指尖关节故障码 | 最接近手掌的指根关节 - - ROLL_TEMPERATURE = 0x21, // 横滚关节温度 | 坐标系建在每个手指的指根部位,按手指伸直的状态去定义旋转角度 - YAW_TEMPERATURE = 0x22, // 航向关节温度 | 坐标系建在每个手指的指根部位,按手指伸直的状态去定义旋转角度 - ROOT1_TEMPERATURE = 0x23, // 指根1关节温度 | 最接近手掌的指根关节 - ROOT2_TEMPERATURE = 0x24, // 指根2关节温度 | 最接近手掌的指根关节 - ROOT3_TEMPERATURE = 0x25, // 指根3关节温度 | 最接近手掌的指根关节 - TIP_TEMPERATURE = 0x26, // 指尖关节温度 | 最接近手掌的指根关节 - // 并行指令区域 - - // 串行指令区域 - THUMB_POS = 0x41, // 大拇指指关节位置 | 返回本类型数据 - INDEX_POS = 0x42, // 食指关节位置 | 返回本类型数据 - MIDDLE_POS = 0x43, // 中指关节位置 | 返回本类型数据 - RING_POS = 0x44, // 无名指关节位置 | 返回本类型数据 - LITTLE_POS = 0x45, // 小拇指关节位置 | 返回本类型数据 - - THUMB_SPEED = 0x49, // 大拇指速度 | 返回本类型数据 - INDEX_SPEED = 0x4A, // 食指速度 | 返回本类型数据 - MIDDLE_SPEED = 0x4B, // 中指速度 | 返回本类型数据 - RING_SPEED = 0x4C, // 无名指速度 | 返回本类型数据 - LITTLE_SPEED = 0x4D, // 小拇指速度 | 返回本类型数据 - - THUMB_TORQUE = 0x51, // 大拇指扭矩 | 返回本类型数据 - INDEX_TORQUE = 0x52, // 食指扭矩 | 返回本类型数据 - MIDDLE_TORQUE = 0x53, // 中指扭矩 | 返回本类型数据 - RING_TORQUE = 0x54, // 无名指扭矩 | 返回本类型数据 - LITTLE_TORQUE = 0x55, // 小拇指扭矩 | 返回本类型数据 - - THUMB_FAULT = 0x59, // 大拇指故障码 | 返回本类型数据 - INDEX_FAULT = 0x5A, // 食指故障码 | 返回本类型数据 - MIDDLE_FAULT = 0x5B, // 中指故障码 | 返回本类型数据 - RING_FAULT = 0x5C, // 无名指故障码 | 返回本类型数据 - LITTLE_FAULT = 0x5D, // 小拇指故障码 | 返回本类型数据 - - THUMB_TEMPERATURE = 0x61, // 大拇指温度 | 返回本类型数据 - INDEX_TEMPERATURE = 0x62, // 食指温度 | 返回本类型数据 - MIDDLE_TEMPERATURE = 0x63, // 中指温度 | 返回本类型数据 - RING_TEMPERATURE = 0x64, // 无名指温度 | 返回本类型数据 - LITTLE_TEMPERATURE = 0x65, // 小拇指温度 | 返回本类型数据 - // 串行指令区域 - - // 合并指令区域,同一手指非必要单控数据合并 - FINGER_SPEED = 0x81, // 手指速度 | 返回本类型数据 - FINGER_TORQUE = 0x82, // 转矩 | 返回本类型数据 - FINGER_FAULT = 0x83, // 手指故障码 | 返回本类型数据 - MOTOR_ENABLE = 0x85, // 使能 | 返回本类型数据 - // 指尖传感器数据组 - HAND_NORMAL_FORCE = 0x90, // 五指法向压力 - HAND_TANGENTIAL_FORCE = 0x91, // 五指切向压力 - HAND_TANGENTIAL_FORCE_DIR = 0x92, // 五指切向方向 - HAND_APPROACH_INC = 0x93, // 五指接近感应 - - THUMB_ALL_DATA = 0x98, // 大拇指所有数据 - INDEX_ALL_DATA = 0x99, // 食指所有数据 - MIDDLE_ALL_DATA = 0x9A, // 中指所有数据 - RING_ALL_DATA = 0x9B, // 无名指所有数据 - LITTLE_ALL_DATA = 0x9C, // 小拇指所有数据 - // 动作指令 ·ACTION - ACTION_PLAY = 0xA0, // 动作,预设动作指令 - - // L21新增 - TOUCH_SENSOR_TYPE = 0xB0, // 触觉传感器类型 - THUMB_TOUCH = 0xB1, // 大拇指触觉传感 - INDEX_TOUCH = 0xB2, // 食指触觉传感 - MIDDLE_TOUCH = 0xB3, // 中指触觉传感 - RING_TOUCH = 0xB4, // 无名指触觉传感 - LITTLE_TOUCH = 0xB5, // 小拇指触觉传感 - PALM_TOUCH = 0xB6, // 手掌指触觉传感 - - - // 配置命令·CONFIG - HAND_UID = 0xC0, // 设备唯一标识码 - HAND_HARDWARE_VERSION = 0xC1, // 硬件版本 - HAND_SOFTWARE_VERSION = 0xC2, // 软件版本 - HAND_COMM_ID = 0xC3, // 设备id - HAND_FACTORY_RESET = 0xCE, // 恢复出厂设置 - HAND_SAVE_PARAMETER = 0xCF, // 保存参数 - - WHOLE_FRAME = 0xF0, // 整帧传输 | 返回一字节帧属性+整个结构体485及网络传输专属 -}; - -/** - * @brief L25/L21 型号灵巧手实现类 - * - * 提供 L25 和 L21 型号的所有功能实现 - */ -class L25Hand : public IHand { -public: - L25Hand(uint32_t handId, const std::string& canChannel, int baudrate, const int currentHandType = 0); - ~L25Hand(); - - // 设置关节位置 - void setJointPositions(const std::vector &jointAngles) override; - void setJointPositionArc(const std::vector &jointAngles) override; - #if 0 - // 横滚关节位置 - void setRoll(const std::vector &roll) override; - // 航向关节位置 - void setYaw(const std::vector &yaw) override; - // 指根1关节位置 - void setRoot1(const std::vector &root1) override; - // 指根2关节位置 - void setRoot2(const std::vector &root2) override; - // 指根3关节位置 - void setRoot3(const std::vector &root3) override; - // 指尖关节位置 - void setTip(const std::vector &tip) override; - #endif - - std::vector state_to_cmd(const std::vector& l25_state); - // 获取当前关节状态 - std::vector getCurrentStatus() override; - std::vector getCurrentStatusArc() override; - #if 0 - // 大拇指指关节位置 - std::vector getThumb() override; - // 食指关节位置 - std::vector getIndex() override; - // 中指关节位置 - std::vector getMiddle() override; - // 无名指关节位置 - std::vector getRing() override; - // 小拇指关节位置 - std::vector getLittle() override; - #endif - // 设置关节速度-有合并指令待确认 - void setSpeed(const std::vector &speed) override; - #if 0 - // 横滚关节速度 - void setRollSpeed(const std::vector &rollSpeed) override; - // 航向关节速度 - void setYawSpeed(const std::vector &yawSpeed) override; - // 指根1关节速度 - void setRoot1Speed(const std::vector &root1Speed) override; - // 指根2关节速度 - void setRoot2Speed(const std::vector &root2Speed) override; - // 指根3关节速度 - void setRoot3Speed(const std::vector &root3Speed) override; - // 指尖关节速度 - void setTipSpeed(const std::vector &tipSpeed) override; - #endif - // 获取当前速度-有合并指令待确认 - std::vector getSpeed() override; - #if 0 - // 大拇指速度 - std::vector getThumbSpeed() override; - // 食指速度 - std::vector getIndexSpeed() override; - // 中指速度 - std::vector getMiddleSpeed() override; - // 无名指速度 - std::vector getRingSpeed() override; - // 小拇指速度 - std::vector getLittleSpeed() override; - #endif - // 设置扭矩-有合并指令待确认 - void setTorque(const std::vector &torque) override; - #if 0 - // 横滚关节扭矩 - void setRollTorque(const std::vector &rollTorque) override; - // 航向关节扭矩 - void setYawTorque(const std::vector &yawTorque) override; - // 指根1关节扭矩 - void setRoot1Torque(const std::vector &root1Torque) override; - // 指根2关节扭矩 - void setRoot2Torque(const std::vector &root2Torque) override; - // 指根3关节扭矩 - void setRoot3Torque(const std::vector &root3Torque) override; - // 指尖关节扭矩 - void setTipTorque(const std::vector &tipTorque) override; - #endif - // 获取当前扭矩-有合并指令待确认 - std::vector getTorque() override; - #if 0 - // 大拇指扭矩 - std::vector getThumbTorque() override; - // 食指扭矩 - std::vector getIndexTorque() override; - // 中指扭矩 - std::vector getMiddleTorque() override; - // 无名指扭矩 - std::vector getRingTorque() override; - // 小拇指扭矩 - std::vector getLittleTorque() override; - #endif - // 获取故障码-有合并指令待确认 - std::vector getFaultCode() override; - #if 0 - // 清除电机故障码 - void clearFaultCode(const std::vector &torque = std::vector(5, 0)) override; - // 大拇指故障码 - std::vector getThumbFaultCode() override; - // 食指故障码 - std::vector getIndexFaultCode() override; - // 中指故障码 - std::vector getMiddleFaultCode() override; - // 无名指故障码 - std::vector getRingFaultCode() override; - // 小拇指故障码 - std::vector getLittleFaultCode() override; - // ------------------------------------------------以下函数待确认 - // 横滚关节故障码 - std::vector getRollFaultCode() override; - // 航向关节故障码 - std::vector getYawFaultCode() override; - // 指根1关节故障码 - std::vector getRoot1FaultCode() override; - // 指根2关节故障码 - std::vector getRoot2FaultCode() override; - // 指根3关节故障码 - std::vector getRoot3FaultCode() override; - // 指尖关节故障码 - std::vector getTipFaultCode() override; - #endif - //-------------------------------------------------------------------- - // 获取温度 - std::vector getTemperature() override; - #if 0 - // 大拇指温度 - std::vector getThumbTemperature() override; - // 食指温度 - std::vector getIndexTemperature() override; - // 中指温度 - std::vector getMiddleTemperature() override; - // 无名指温度 - std::vector getRingTemperature() override; - // 小拇指温度 - std::vector getLittleTemperature() override; - //----------------------------------------------------以下函数待确认 - // 获取横滚关节温度 - std::vector getRollTemperature() override; - // 获取航向关节温度 - std::vector getYawTemperature() override; - // 获取指根1关节温度 - std::vector getRoot1Temperature() override; - // 获取指根2关节温度 - std::vector getRoot2Temperature() override; - // 获取指根3关节温度 - std::vector getRoot3Temperature() override; - // 获取指尖关节温度 - std::vector getTipTemperature() override; - #endif - //-------------------------------------------------------------------- - // 获取所有压感数据 - std::vector> getForce(const int type = 0) override; - std::vector>> getForce() override; - #if 1 - // 获取大拇指压感数据 - std::vector getThumbForce() override; - // 获取食指压感数据 - std::vector getIndexForce() override; - // 获取中指压感数据 - std::vector getMiddleForce() override; - // 获取无名指压感数据 - std::vector getRingForce() override; - // 获取小拇指压感数据 - std::vector getLittleForce() override; - //----------------------------------------------- - // 获取五个手指的法向压力 - std::vector getNormalForce() override; - // 获取五个手指的切向压力 - std::vector getTangentialForce() override; - // 获取五个手指的切向方向 - std::vector getTangentialForceDir() override; - // 获取五个手指指接近感应 - std::vector getApproachInc() override; - #endif - //-------------------------------------------------------------------- - // 获取版本号 - std::string getVersion() override; - // 设置电机使能 目前仅支持L25 - void setMotorEnable(const std::vector &enable = std::vector(5, 0)); - // 设置电机使能 目前仅支持L25 - void setMotorDisable(const std::vector &disable = std::vector(5, 1)); - // 设备唯一标识码 - std::vector getUID(); - // 设备id - std::vector getCommID(); - // 恢复出厂设置 - void factoryReset(); - // 保存参数 - void saveParameter(); - - - #if 0 - // 动作,预设动作指令 - void playAction(const std::vector &action) override; - //-------------------------------------------------------------------- - - // 整帧传输 - void setWholeFrame(bool wholeFrame) override; - #endif - -private: - uint32_t handId; - std::unique_ptr bus; - std::thread receiveThread; - bool running; - std::mutex responseMutex; - - void receiveResponse(); - - // 故障码 - std::vector motor_fault_code; - // 电流 - std::vector motor_current; - - - // 速度 - // std::vector motor_speed; - std::vector thumb_speed; // 大拇指速度 - std::vector index_speed; // 食指速度 - std::vector middle_speed; // 中指速度 - std::vector ring_speed; // 无名指速度 - std::vector little_speed; // 小拇指速度 - - - // 关节位置 - // std::vector joint_pos; - std::vector thumb_pos; // 大拇指位置 - std::vector index_pos; // 食指位置 - std::vector middle_pos; // 中指位置 - std::vector ring_pos; // 无名指位置 - std::vector little_pos; // 小拇指位置 - - // 温度 - // std::vector motor_temperature; - std::vector thumb_temperature; // 大拇指温度 - std::vector index_temperature; // 食指温度 - std::vector middle_temperature; // 中指温度 - std::vector ring_temperature; // 无名指温度 - std::vector little_temperature; // 小拇指温度 - - - // 扭矩 - std::vector thumb_torque; // 大拇指扭矩 - std::vector index_torque; // 食指扭矩 - std::vector middle_torque; // 中指扭矩 - std::vector ring_torque; // 无名指扭矩 - std::vector little_torque; // 小拇指扭矩 - - // 故障 - std::vector thumb_fault; // 大拇指故障 - std::vector index_fault; // 食指故障 - std::vector middle_fault; // 中指故障 - std::vector ring_fault; // 无名指故障 - std::vector little_fault; // 小拇指故障 - - std::vector normal_force; - std::vector tangential_force; - std::vector tangential_force_dir; - std::vector approach_inc; - - std::vector thumb_pressure; - std::vector index_finger_pressure; - std::vector middle_finger_pressure; - std::vector ring_finger_pressure; - std::vector little_finger_pressure; - std::vector palm_force_data; - - // std::vector joint_position2; - // std::vector joint_position3; - // std::vector joint_position4; - // std::vector joint_position5; - - // 版本号 - std::vector hand_hardware_version; - std::vector hand_software_version; - - // 设备唯一标志 - std::vector hand_uid; - std::vector hand_comm_id; - - // 堵转计数 - std::vector rotor_lock_count; - - // 手型 - int current_hand_type = 0; // 0:L25 1:L21 - - uint8_t sensor_type = 0; - - std::vector>> touch_mats; -}; - -} // namespace hand -} // namespace linkerhand - -// 向后兼容:在旧命名空间中提供别名 -namespace LinkerHandL25 { - using FRAME_PROPERTY = linkerhand::hand::L25FrameProperty; - using LinkerHand = linkerhand::hand::L25Hand; -} // namespace LinkerHandL25 - -#endif // LINKERHAND_L25_H \ No newline at end of file diff --git a/include/LinkerHandL6.h b/include/LinkerHandL6.h deleted file mode 100644 index e8eeac1..0000000 --- a/include/LinkerHandL6.h +++ /dev/null @@ -1,161 +0,0 @@ -#ifndef LINKERHAND_L6_H -#define LINKERHAND_L6_H - -#include -#include -#include -#include -#include -#include -#include - -#include "IHand.h" -#include "CanBusFactory.h" - -namespace linkerhand { -namespace hand { - -// L6/O6 型号的帧属性枚举 -enum class L6FrameProperty -{ - // 指令码 指令功能 数据长度 CAN发送DLC CAN接收DLC 数据范围 - JOINT_POSITION = 0x01, // 关节1-6的关节位置 6 7 7 0-0xFF - TORQUE_LIMIT = 0x02, // 关节1-6的转矩限制 6 7 7 0-0xFF - JOINT_SPEED = 0x05, // 关节1-6的速度 6 7 7 0-0xFF - JOINT_ACCELERATION = 0x07, // 关节1-6的加速度 6 7 7 0-0xFE - MOTOR_TEMPERATURE = 0x33, // 关节1-6的温度信息 7 1 8 0-0xFF - MOTOR_ERROR_CODE = 0x35, // 关节1-6的错误码 7 1 8 0-0xFF - CLEAR_FAULT_CODE = 0x83, // 清除关节1-6的错误码 6 7 7 0-0xFF - RE_HOME_COMMAND = 0x38, // 重新调零点命令 8 8 2 - - // 设备信息指令 - DEVICE_SERIAL_NUMBER = 0xC0, // 设备出厂编码 24 1 3帧8字节 - DEVICE_HARDWARE_VERSION = 0xC1, // 设备硬件PCB版本号 3 1 4 - DEVICE_SOFTWARE_VERSION = 0xC2, // 设备软件版本号 3 1 4 - DEVICE_MECHANICAL_VERSION = 0xC4, // 设备机械结构版本号 3 1 4 - MODIFY_CAN_ID = 0xC3, // 修改CANID指令 3 - STALL_THRESHOLD = 0xC5, // 堵转阈值 - STALL_TIME = 0xC6, // 堵转时间 - STALL_TORQUE = 0xC7, // 堵转扭矩 - FACTORY_RESET = 0xCE, // 恢复出厂设置 - SAVE_PARAMETERS = 0xCF, // 保存参数 - - // 触觉传感器指令 - TOUCH_SENSOR_TYPE = 0xB0, // 触觉传感器类型 - THUMB_TOUCH = 0xB1, // 大拇指触觉传感 - INDEX_TOUCH = 0xB2, // 食指触觉传感 - MIDDLE_TOUCH = 0xB3, // 中指触觉传感 - RING_TOUCH = 0xB4, // 无名指触觉传感 - LITTLE_TOUCH = 0xB5, // 小拇指触觉传感 - PALM_TOUCH = 0xB6 // 手掌触觉传感 -}; - -// 协议辅助常量 -static constexpr uint8_t TOUCH_TYPE_MATRIX = 0x02; // 矩阵型触觉类型值 -static constexpr uint8_t TOUCH_PAGE_REQ = 0xC6; // 触觉分页读取的请求子命令 - -/** - * @brief L6/O6 型号灵巧手实现类 - * - * 提供 L6 和 O6 型号的所有功能实现 - */ -class L6Hand : public IHand -{ -public: - L6Hand(uint32_t handId, const std::string &canChannel, int baudrate); - ~L6Hand(); - - // 设置关节位置 - void setJointPositions(const std::vector &jointAngles) override; - void setJointPositionArc(const std::vector &jointAngles) override; - - void setSpeed(const std::vector &speed) override; - - void setTorque(const std::vector &torque); - - void setAcceleration(const std::vector &acceleration); - - // 重新调零 - void reHome(); - - // 获取当前关节状态 - std::vector getCurrentStatus() override; - std::vector getCurrentStatusArc() override; - - // 获取当前速度 - std::vector getSpeed() override; - - // 获取当前扭矩 - std::vector getTorque() override; - - // 获取当前加速度 - std::vector getAcceleration(); - - // 获取电机错误码 - std::vector getFaultCode() override; - - void clearFaultCode(const std::vector &code); - - // 获取压感数据 - std::vector>> getForce() override; - - // 获取电机温度 - std::vector getTemperature() override; - - // 获取版本信息 - std::string getVersion() override; - - // 获取设备序列号 - std::string getSerialNumber(); - - // 获取硬件版本 - std::string getHardwareVersion(); - - // 获取机械版本 - std::string getMechanicalVersion(); - - // 系统功能 - void factoryReset(); - void saveParameters(); - -private: - uint32_t handId; - std::unique_ptr bus; - std::thread receiveThread; - bool running; - std::mutex data_mutex_; - - void receiveResponse(); - - // 数据存储 - std::vector joint_position; - std::vector joint_speeds; - std::vector joint_torques; - std::vector joint_accelerations; - std::vector motor_temperature; - std::vector error_codes; - std::vector device_serial; - std::vector hardware_version; - std::vector software_version; - std::vector mechanical_version; - - std::vector>> touch_mats; - - uint8_t sensor_type = 0; - - // 辅助方法 - void requestDeviceInfo(); - void parseSerialNumber(const std::vector& data); - std::string getErrorDescription(uint8_t error_code); -}; - -} // namespace hand -} // namespace linkerhand - -// 向后兼容:在旧命名空间中提供别名 -namespace LinkerHandL6 { - using FRAME_PROPERTY = linkerhand::hand::L6FrameProperty; - using LinkerHand = linkerhand::hand::L6Hand; -} // namespace LinkerHandL6 - -#endif // LINKERHAND_L6_H diff --git a/include/LinkerHandL7.h b/include/LinkerHandL7.h deleted file mode 100644 index ddbb8f1..0000000 --- a/include/LinkerHandL7.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef LINKERHAND_L7_H -#define LINKERHAND_L7_H - -#include -#include -#include -#include -#include -#include -#include - -#include "IHand.h" -#include "CanBusFactory.h" - -namespace linkerhand { -namespace hand { - -// L7 型号的帧属性枚举 -enum class L7FrameProperty -{ - // 指令码 指令功能 数据长度 CAN发送DLC CAN接收DLC 数据范围 - JOINT_POSITION = 0x01, // 关节1-7的关节位置 7 8 8 0-0xFF - TORQUE_LIMIT = 0x02, // 关节1-7的转矩限制 7 8 8 0-0xFF - JOINT_SPEED = 0x05, // 关节1-7的速度 7 8 8 0-0xFF - HAND_NORMAL_FORCE = 0x20, // 五个手指的法向压力 5 1 6 0-0xFF - HAND_TANGENTIAL_FORCE = 0x21, // 五个手指的切向压力 5 1 6 0-0xFF - HAND_TANGENTIAL_FORCE_DIR = 0x22, // 五个手指的切向方向 5 1 6 0-0x7F 0xFF - HAND_APPROACH_INC = 0x23, // 五个手指指接近感应 5 1 6 0-0xFF - THUMB_ALL_DATA = 0x28, // 大拇指所有压力数据 4 1 5 0-0xFF - INDEX_FINGER_ALL_DATA = 0x29, // 食指所有压力数据 4 1 5 0-0xFF - MIDDLE_FINGER_ALL_DATA = 0x30, // 中指所有压力数据 4 1 5 0-0xFF - RING_FINGER_ALL_DATA = 0x31, // 无名指所有压力数据 4 1 5 0-0xFF - LITTLE_FINGER_ALL_DATA = 0x32, // 小拇指所有压力数据 4 1 5 0-0xFF - MOTOR_TEMPERATURE = 0x33, // 关节1-7的温度信息 7 1 8 0-0xFF - MOTOR_FAULT_CODE = 0x35, // 关节1-7的错误码 7 1 8 0-0xFF - RESET_ZERO_COMMAND = 0x38, // 重新调零点命令 1 1 2 - LINKER_HAND_VERSION = 0x64, // 版本号 8 1 8 0-0xFF - - // 新压感 - TOUCH_SENSOR_TYPE = 0xB0, // 触觉传感器类型 - THUMB_TOUCH = 0xB1, // 大拇指触觉传感 - INDEX_TOUCH = 0xB2, // 食指触觉传感 - MIDDLE_TOUCH = 0xB3, // 中指触觉传感 - RING_TOUCH = 0xB4, // 无名指触觉传感 - LITTLE_TOUCH = 0xB5, // 小拇指触觉传感 - PALM_TOUCH = 0xB6 // 手掌指触觉传感 -}; - -/** - * @brief L7 型号灵巧手实现类 - * - * 提供 L7 型号的所有功能实现 - */ -class L7Hand : public IHand -{ -public: - L7Hand(uint32_t handId, const std::string &canChannel, int baudrate); - ~L7Hand(); - - // 设置关节位置 - void setJointPositions(const std::vector &jointAngles) override; - void setJointPositionArc(const std::vector &jointAngles) override; - // 设置最大扭矩 - void setTorque(const std::vector &torque) override; - // 设置关节速度 - void setSpeed(const std::vector &speed) override; - // 获取当前速度 - std::vector getSpeed() override; - // 获取当前扭矩 - std::vector getTorque() override; - // 获取当前关节状态 - std::vector getCurrentStatus() override; - std::vector getCurrentStatusArc() override; - //-------------------------------------------------------------------- - // 获取所有压感数据 - std::vector>> getForce() override; - #if 1 - // 获取五个手指的法向压力 - std::vector getNormalForce() override; - // 获取五个手指的切向压力 - std::vector getTangentialForce() override; - // 获取五个手指的切向方向 - std::vector getTangentialForceDir() override; - // 获取五个手指指接近感应 - std::vector getApproachInc() override; - #endif - //-------------------------------------------------------------------- - // 获取电机温度 - std::vector getTemperature() override; - // 获取电机故障码 - std::vector getFaultCode() override; - // 获取版本信息 - std::string getVersion() override; - - -private: - uint32_t handId; - std::unique_ptr bus; - std::thread receiveThread; - bool running; - - void receiveResponse(); - - // 队列和条件变量 - std::vector joint_position; - std::vector joint_position2; - std::vector joint_speed; - - std::vector normal_force; - std::vector tangential_force; - std::vector tangential_force_dir; - std::vector approach_inc; - - std::vector thumb_pressure; - std::vector index_finger_pressure; - std::vector middle_finger_pressure; - std::vector ring_finger_pressure; - std::vector little_finger_pressure; - - std::vector>> touch_mats; - - // 最大扭矩 - std::vector max_torque; - - // 电机温度 - std::vector motorTemperature_1; - std::vector motorTemperature_2; - - // 电机故障码 - std::vector motorFaultCode_1; - std::vector motorFaultCode_2; - - // 版本信息 - std::vector version; - - uint8_t sensor_type = 0; -}; - -} // namespace hand -} // namespace linkerhand - -// 向后兼容:在旧命名空间中提供别名 -namespace LinkerHandL7 { - using FRAME_PROPERTY = linkerhand::hand::L7FrameProperty; - using LinkerHand = linkerhand::hand::L7Hand; -} // namespace LinkerHandL7 - -#endif // LINKERHAND_L7_H \ No newline at end of file diff --git a/include/Logger.h b/include/Logger.h deleted file mode 100644 index 84191b4..0000000 --- a/include/Logger.h +++ /dev/null @@ -1,197 +0,0 @@ -#ifndef LINKERHAND_LOGGER_H -#define LINKERHAND_LOGGER_H - -#include -#include -#include -#include -#include - -namespace linkerhand { -namespace logging { - -/** - * @brief 日志级别枚举 - */ -enum class LogLevel { - TRACE = 0, - DEBUG, - INFO, - WARN, - ERROR, - CRITICAL, - OFF -}; - -/** - * @brief 日志接口 - * - * 定义日志系统的接口,可以替换为 spdlog 或其他日志库 - */ -class ILogger { -public: - virtual ~ILogger() = default; - - virtual void log(LogLevel level, const std::string& message) = 0; - virtual void setLevel(LogLevel level) = 0; - virtual LogLevel getLevel() const = 0; - - void trace(const std::string& message) { log(LogLevel::TRACE, message); } - void debug(const std::string& message) { log(LogLevel::DEBUG, message); } - void info(const std::string& message) { log(LogLevel::INFO, message); } - void warn(const std::string& message) { log(LogLevel::WARN, message); } - void error(const std::string& message) { log(LogLevel::ERROR, message); } - void critical(const std::string& message) { log(LogLevel::CRITICAL, message); } -}; - -/** - * @brief 简单控制台日志实现 - * - * 使用 std::cout 和 std::cerr 输出日志 - * 可以后续替换为 spdlog - */ -class ConsoleLogger : public ILogger { -public: - explicit ConsoleLogger(LogLevel level = LogLevel::INFO) - : currentLevel_(level) {} - - void log(LogLevel level, const std::string& message) override { - if (level < currentLevel_ || level == LogLevel::OFF) { - return; - } - - std::lock_guard lock(mutex_); - - const char* levelStr = levelToString(level); - std::ostream& stream = (level >= LogLevel::ERROR) ? std::cerr : std::cout; - - stream << "[" << levelStr << "] " << message << std::endl; - } - - void setLevel(LogLevel level) override { - std::lock_guard lock(mutex_); - currentLevel_ = level; - } - - LogLevel getLevel() const override { - return currentLevel_; - } - -private: - static const char* levelToString(LogLevel level) { - switch (level) { - case LogLevel::TRACE: return "TRACE"; - case LogLevel::DEBUG: return "DEBUG"; - case LogLevel::INFO: return "INFO"; - case LogLevel::WARN: return "WARN"; - case LogLevel::ERROR: return "ERROR"; - case LogLevel::CRITICAL: return "CRITICAL"; - default: return "UNKNOWN"; - } - } - - LogLevel currentLevel_; - mutable std::mutex mutex_; -}; - -/** - * @brief 空日志实现(禁用日志) - */ -class NullLogger : public ILogger { -public: - void log(LogLevel, const std::string&) override {} - void setLevel(LogLevel) override {} - LogLevel getLevel() const override { return LogLevel::OFF; } -}; - -/** - * @brief 全局日志管理器 - */ -class Logger { -public: - /** - * @brief 获取默认日志实例 - */ - static ILogger& get() { - static std::unique_ptr instance = - std::make_unique(LogLevel::INFO); - return *instance; - } - - /** - * @brief 设置日志实例 - */ - static void setLogger(std::unique_ptr logger) { - static std::unique_ptr instance = std::move(logger); - get() = *instance; - } - - /** - * @brief 便捷方法:记录 TRACE 日志 - */ - static void trace(const std::string& message) { - get().trace(message); - } - - /** - * @brief 便捷方法:记录 DEBUG 日志 - */ - static void debug(const std::string& message) { - get().debug(message); - } - - /** - * @brief 便捷方法:记录 INFO 日志 - */ - static void info(const std::string& message) { - get().info(message); - } - - /** - * @brief 便捷方法:记录 WARN 日志 - */ - static void warn(const std::string& message) { - get().warn(message); - } - - /** - * @brief 便捷方法:记录 ERROR 日志 - */ - static void error(const std::string& message) { - get().error(message); - } - - /** - * @brief 便捷方法:记录 CRITICAL 日志 - */ - static void critical(const std::string& message) { - get().critical(message); - } - - /** - * @brief 设置日志级别 - */ - static void setLevel(LogLevel level) { - get().setLevel(level); - } - - /** - * @brief 获取日志级别 - */ - static LogLevel getLevel() { - return get().getLevel(); - } -}; - -} // namespace logging -} // namespace linkerhand - -// 便捷宏定义 -#define LINKERHAND_LOG_TRACE(msg) linkerhand::logging::Logger::trace(msg) -#define LINKERHAND_LOG_DEBUG(msg) linkerhand::logging::Logger::debug(msg) -#define LINKERHAND_LOG_INFO(msg) linkerhand::logging::Logger::info(msg) -#define LINKERHAND_LOG_WARN(msg) linkerhand::logging::Logger::warn(msg) -#define LINKERHAND_LOG_ERROR(msg) linkerhand::logging::Logger::error(msg) -#define LINKERHAND_LOG_CRITICAL(msg) linkerhand::logging::Logger::critical(msg) - -#endif // LINKERHAND_LOGGER_H diff --git a/include/ModBus.h b/include/ModBus.h deleted file mode 100644 index 0c7472f..0000000 --- a/include/ModBus.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef LINKERHAND_MOD_BUS_H -#define LINKERHAND_MOD_BUS_H -#if USE_RMAN -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include "rm_service.h" -#include "Common.h" -#include "ICommunication.h" - -namespace linkerhand { -namespace communication { - -/** - * @brief ModBus 通信实现 - */ -class ModBus : public ICommunication - { - public: - ModBus(uint32_t handId); - ~ModBus(); - - void send(const std::vector& data, uint32_t &id, const int &start_address = 0, const int &num = 0) override; - std::vector recv(uint32_t& id, const int &start_address = 0, const int &num = 0) override; - - bool writeHoldingRegister(const int &id, const int &start_address, const int &num, const std::vector &data); - std::vector readHoldingRegister(const int &id, const int &start_address, const int &num); - - private: - uint32_t handId; - int result = -1; - rm_robot_handle *robot_handle; - RM_Service robotic_arm; - - std::mutex send_mutex; - }; -} // namespace communication -} // namespace linkerhand - -// 向后兼容:在全局命名空间中提供别名 -namespace Communication = linkerhand::communication; - -#endif -#endif // LINKERHAND_MOD_BUS_H diff --git a/include/ModbusLinkerHandL10.h b/include/ModbusLinkerHandL10.h deleted file mode 100644 index 0efa7d5..0000000 --- a/include/ModbusLinkerHandL10.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef LINKERHAND_MODBUS_L10_H -#define LINKERHAND_MODBUS_L10_H -#if USE_RMAN -#include -#include -#include -#include -#include -#include -#include - -#include "ModBus.h" -#include "IHand.h" - -namespace linkerhand { -namespace hand { - -/** - * @brief Modbus L10 型号灵巧手实现类 - * - * 提供通过 Modbus 协议通信的 L10 型号功能实现 - */ -class ModbusL10Hand : public IHand -{ -public: - LinkerHand(uint32_t handId); - ~LinkerHand(); - - // 设置关节位置 - void setJointPositions(const std::vector &jointAngles) override; - void setJointPositionArc(const std::vector &jointAngles) override; - // 设置最大扭矩 - void setTorque(const std::vector &torque) override; - // 设置关节速度 - void setSpeed(const std::vector &speed) override; - // 获取当前速度 - std::vector getSpeed() override; - // 获取当前扭矩 - std::vector getTorque() override; - // 获取当前关节状态 - std::vector getCurrentStatus() override; - std::vector getCurrentStatusArc() override; - - -private: - uint32_t handId; - std::thread receiveThread; - - Communication::ModBus bus; - - bool running; - void receiveResponse(); - - std::vector joints; - std::vector speed; - std::vector torque; - -}; - -} // namespace hand -} // namespace linkerhand - -// 向后兼容:在旧命名空间中提供别名 -namespace ModbusLinkerHandL10 { - using LinkerHand = linkerhand::hand::ModbusL10Hand; -} // namespace ModbusLinkerHandL10 - -#endif -#endif // LINKERHAND_MODBUS_L10_H diff --git a/include/RangeToArc.h b/include/RangeToArc.h deleted file mode 100644 index 11a936c..0000000 --- a/include/RangeToArc.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef LINKERHAND_RANGE_TO_ARC_H -#define LINKERHAND_RANGE_TO_ARC_H - -#include -#include -#include -#include - -//--------------------------------------------------------------------------------------------------- -// L7 L OK -const std::vector l7_l_min = {0, 0, 0, 0, 0, 0, -0.52}; -const std::vector l7_l_max = {0.44, 1.43, 1.62, 1.62, 1.62, 1.62, 1.01}; -const std::vector l7_l_derict = {-1, -1, -1, -1, -1, -1, -1}; -// L7 R OK (urdf后续会更改!!!) -const std::vector l7_r_min = {0, -1.43, 0, 0, 0, 0, 0}; -const std::vector l7_r_max = {0.75, 0, 1.62, 1.62, 1.62, 1.62, 1.54}; -const std::vector l7_r_derict = {-1, 0, -1, -1, -1, -1, -1}; -//--------------------------------------------------------------------------------------------------- -// L10 L OK -const std::vector l10_l_min = {0, 0, 0, 0, 0, 0, 0, -0.26, -0.26, -0.52}; -const std::vector l10_l_max = {1.45, 1.43, 1.62, 1.62, 1.62, 1.62, 0.26, 0, 0, 1.01}; -const std::vector l10_l_derict = {-1, -1, -1, -1, -1, -1, 0, -1, -1, -1}; -// L10 R OK -const std::vector l10_r_min = {0, 0, 0, 0, 0, 0, -0.26, 0, 0, -0.52}; -const std::vector l10_r_max = {0.75, 1.43, 1.62, 1.62, 1.62, 1.62, 0, 0.13, 0.26, 1.01}; -const std::vector l10_r_derict = {-1, -1, -1, -1, -1, -1, -1, 0, 0, -1}; -//--------------------------------------------------------------------------------------------------- -// L20 L OK -const std::vector l20_l_min = {0, 0, 0, 0, 0, -0.297, -0.26, -0.26, -0.26, -0.26, 0.122, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -const std::vector l20_l_max = {0.87, 1.4, 1.4, 1.4, 1.4, 0.683, 0.26, 0.26, 0.26, 0.26, 1.78, 0, 0, 0, 0, 1.29, 1.08, 1.08, 1.08, 1.08}; -const std::vector l20_l_derict = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, -1, -1}; -// L20 R OK -const std::vector l20_r_min = {0, 0, 0, 0, 0, -0.297, -0.26, -0.26, -0.26, -0.26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -const std::vector l20_r_max = {0.87, 1.4, 1.4, 1.4, 1.4, 0.683, 0.26, 0.26, 0.26, 0.26, 1.78, 0, 0, 0, 0, 1.29, 1.08, 1.08, 1.08, 1.08}; -const std::vector l20_r_derict = {-1, -1, -1, -1, -1, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, -1, -1, -1, -1}; -//--------------------------------------------------------------------------------------------------- -// L21 L OK -const std::vector l21_l_min = {0, 0, 0, 0, 0, 0, 0, -0.18, -0.18, 0, -0.6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -const std::vector l21_l_max = {1, 1.57, 1.57, 1.57, 1.57, 1.6, 0.18, 0.18, 0.18, 0.18, 0.6, 0, 0, 0, 0, 1.57, 0, 0, 0, 0, 1.57, 1.57, 1.57, 1.57, 1.57}; -const std::vector l21_l_derict = {-1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, -1, -1, -1, -1}; -// L21 R OK -const std::vector l21_r_min = {0, 0, 0, 0, 0, 0, -0.18, -0.18, -0.18, -0.18, -0.6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -const std::vector l21_r_max = {1, 1.57, 1.57, 1.57, 1.57, 1.6, 0.18, 0.18, 0.18, 0.18, 0.6, 0, 0, 0, 0, 1.57, 0, 0, 0, 0, 1.57, 1.57, 1.57, 1.57, 1.57}; -const std::vector l21_r_derict = {-1, -1, -1, -1, -1, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, -1, -1, -1, -1}; -//--------------------------------------------------------------------------------------------------- -// L25 L OK -const std::vector l25_l_min = {0, 0, 0, 0, 0, 0, -0.26, -0.26, -0.26, -0.26, -0.26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -const std::vector l25_l_max = {0.9, 1.57, 1.57, 1.57, 1.57, 1.3, 0.26, 0.26, 0.26, 0.26, 0.61, 0, 0, 0, 0, 1.57, 1.57, 1.57, 1.57, 1.57, 1.57, 1.57, 1.57, 1.57, 1.57}; -const std::vector l25_l_derict = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; -// L25 R OK -const std::vector l25_r_min = {0, 0, 0, 0, 0, 0, -0.26, -0.26, -0.26, -0.26, -0.26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -const std::vector l25_r_max = {0.9, 1.57, 1.57, 1.57, 1.57, 1.3, 0.26, 0.26, 0.26, 0.26, 0.61, 0, 0, 0, 0, 1.57, 1.57, 1.57, 1.57, 1.57, 1.57, 1.57, 1.57, 1.57, 1.57}; -const std::vector l25_r_derict = {-1, -1, -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; -//--------------------------------------------------------------------------------------------------- - - -double is_within_range(double value, double min_value, double max_value); - -double scale_value(double original_value, double a_min, double a_max, double b_min, double b_max); - -bool should_skip_joint(int joints_type, int joint_index); - -bool initialize_params(int joints_type, const std::string& left_or_right, std::vector& min_limits, std::vector& max_limits, std::vector& derict); - -std::vector range_to_arc(const int &joints_type, const std::string &left_or_right, const std::vector &hand_range); - -std::vector arc_to_range(const int &joints_type, const std::string &left_or_right, const std::vector &hand_arc); - -#endif // LINKERHAND_RANGE_TO_ARC_H diff --git a/include/api/LinkerHandApi.h b/include/api/LinkerHandApi.h new file mode 100644 index 0000000..0fafd38 --- /dev/null +++ b/include/api/LinkerHandApi.h @@ -0,0 +1,117 @@ +#ifndef LINKER_HAND_API_H +#define LINKER_HAND_API_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Common.h" +#include "CommunicationCallbacks.h" +#include "ErrorCode.h" +#include "LinkerHandExport.h" + +// 仅前向声明 IHand,避免把 hand/ 子目录的实现细节带进公共头。 +// 实例化 std::unique_ptr 的析构在 LinkerHandApi.cpp 里完成。 +namespace linkerhand { namespace hand { class IHand; } } + +namespace linkerhand { +namespace api { + +class LINKERHAND_API LinkerHandApi +{ +public: + LinkerHandApi(const LINKER_HAND &handJoint, const HAND_TYPE &handType, const COMM_TYPE commType = COMM_TYPE::CAN); + // 新风格枚举重载:转发到旧版构造 + LinkerHandApi(::linkerhand::HandModel model, + ::linkerhand::HandType side, + ::linkerhand::CommType comm = ::linkerhand::CommType::CAN); + ~LinkerHandApi(); + + // 设置 CAN TX 回调函数(CAN 发送数据) + void setCanTxCallback(CanTxCallback can_tx_callback); + // 设置 CAN RX 回调函数(CAN 接收数据) + void setCanRxCallback(CanRxCallback can_rx_callback); + + void freeCanCallback(); + void freeModbusCallback(); + + // 设置 Modbus TX 回调函数(Modbus 发送) + void setModbusTxCallback(ModbusTxCallback modbus_tx_callback); + // 设置 Modbus RX 回调函数(Modbus 接收) + void setModbusRxCallback(ModbusRxCallback modbus_rx_callback); + + // 设置关节位置 + void fingerMove(const std::vector &pose); + void fingerMoveArc(const std::vector &pose); + // 获取关节位置 + std::vector getState(); + std::vector getStateArc(); + + // 设置速度 + void setSpeed(const std::vector &speed); + // 获取速度 + std::vector getSpeed(); + + // 设置扭矩 + void setTorque(const std::vector &torque); + // 获取扭矩 + std::vector getTorque(); + + // 获取压感 + std::vector>> getForce(); + + // 获取版本号 + std::string getVersion(); + // ---------------------------------------------------------- + // 获取电机温度 + std::vector getTemperature(); + // 获取电机故障码 + std::vector getFaultCode(); + + // ---------------------------------------------------------- + // 清除电机故障码 目前仅支持L20 + void clearFaultCode(const std::vector &torque = std::vector(5, 1)); + // 设置电机使能 目前仅支持L25 + void setEnable(const std::vector &enable = std::vector(5, 0)); + // 设置电机使能 目前仅支持L25 + void setDisable(const std::vector &disable = std::vector(5, 1)); + +private: + // 获取法向压力 + void getNormalForce(); + // 获取切向压力 + void getTangentialForce(); + // 获取切向压力方向 + void getTangentialForceDir(); + // 获取接近感应 + void getApproachInc(); + +private: + std::unique_ptr<::linkerhand::hand::IHand> hand; + uint32_t handId; + + CanTxCallback can_tx_callback_; // TX回调函数 + CanRxCallback can_rx_callback_; // RX回调函数 + ModbusTxCallback modbus_tx_callback_; // Modbus TX 回调 + ModbusRxCallback modbus_rx_callback_; // Modbus RX 回调 + +public: + LINKER_HAND handJoint_; + HAND_TYPE handType_; +}; + +} // namespace api +} // namespace linkerhand + +// 向后兼容 +using LinkerHandApi = ::linkerhand::api::LinkerHandApi; + +#endif diff --git a/include/communication/CanBus.h b/include/communication/CanBus.h new file mode 100644 index 0000000..0e3e978 --- /dev/null +++ b/include/communication/CanBus.h @@ -0,0 +1,73 @@ +#ifdef __linux__ +#ifndef CAN_BUS_H +#define CAN_BUS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "communication/ICanBus.h" +#include "core/Common.h" + +namespace linkerhand { +namespace communication { + class CanBus : public ICanBus { + public: + CanBus(const HAND_TYPE& hand_type); + CanBus(const std::string& interface, int bitrate = 1000000); + + virtual ~CanBus(); + + // 核心接口 + void send(const std::vector& data, uint32_t can_id, bool wait = false) override; + CANFrame recv() override; + void shutdown(); + + // 工具方法 + void setReceiveTimeout(int seconds, int microseconds); + static void globalShutdown(); + + private: + struct DetectionJob { + const char* name; + uint32_t id; + bool is_ext; + uint8_t data0; + uint8_t dlc; + uint8_t data[8]; + }; + + bool ping_interface(const std::string& ifname, const DetectionJob& job); + bool is_interface_up(const std::string& ifname); + std::vector detect_can_interfaces(); + std::string auto_detect_channel(HAND_TYPE hand_type); + + int socket_fd = -1; + std::string interface; + std::atomic is_shutting_down{false}; + + std::mutex mutex_comm; // 统一保护Socket读写安全 + + // 统计相关 + std::mutex rate_mutex; + int send_count = 0; + int recv_count = 0; + std::chrono::steady_clock::time_point last_stat_time; + void updateRates(bool is_send); + }; +} // namespace communication +} // namespace linkerhand + +namespace Communication { + using CanBus = ::linkerhand::communication::CanBus; +} + +#endif +#endif diff --git a/include/communication/CanBusFactory.h b/include/communication/CanBusFactory.h new file mode 100644 index 0000000..d34dc77 --- /dev/null +++ b/include/communication/CanBusFactory.h @@ -0,0 +1,19 @@ +#ifndef CAN_BUS_FACTORY_H +#define CAN_BUS_FACTORY_H + +// 历史名兼容:CanBusFactory 已重命名为 CommFactory(实际可创建 CanBus / PCANBus +// / CanFD / Modbus / EtherCAT)。本头保留作为零代价转发,避免破坏已发布客户代码。 +// 推荐新代码直接 include "CommFactory.h" 并使用 Communication::CommFactory。 +#include "communication/CommFactory.h" + +namespace linkerhand { +namespace communication { + using CanBusFactory = CommFactory; +} // namespace communication +} // namespace linkerhand + +namespace Communication { + using CanBusFactory = ::linkerhand::communication::CommFactory; +} + +#endif // CAN_BUS_FACTORY_H diff --git a/include/communication/CanFD.h b/include/communication/CanFD.h new file mode 100644 index 0000000..3690665 --- /dev/null +++ b/include/communication/CanFD.h @@ -0,0 +1,48 @@ +#ifndef CANFD_H +#define CANFD_H + +#include +#include +#include +#include +#include "communication/ICanFD.h" +#include "Hcanbus.h" +#include "core/LinkerHandExport.h" + +namespace linkerhand { +namespace communication +{ + class LINKERHAND_API CanFD : public ICanFD + { + public: + CanFD(uint32_t dev_num = 0, uint32_t ch_num = 0); + ~CanFD(); + + bool init(); + void close(); + bool isOpen() const override; + + void send(const std::vector& data, uint32_t can_id, bool is_extended = true) override; + CanFDFrame recv(int timeout_ms = 100) override; + + static int scanDevices(); + static bool readDeviceInfo(uint32_t dev_num, ::Dev_Info& info); + + static uint8_t lenToDLC(uint8_t len); + static uint8_t dlcToLen(uint8_t dlc); + + private: + uint32_t m_dev_num; + uint32_t m_ch_num; + std::atomic m_is_open; + std::mutex m_tx_mutex; + std::mutex m_rx_mutex; + }; +} // namespace communication +} // namespace linkerhand + +namespace Communication { + using CanFD = ::linkerhand::communication::CanFD; +} + +#endif // CANFD_H diff --git a/include/communication/CanFrame.h b/include/communication/CanFrame.h new file mode 100644 index 0000000..9d5acc1 --- /dev/null +++ b/include/communication/CanFrame.h @@ -0,0 +1,60 @@ +#ifndef CAN_FRAME_H +#define CAN_FRAME_H + +#include +#include +#include + +#ifdef _WIN32 +// 定义 NOMINMAX 以防止 Windows SDK 定义 min/max 宏与 std::min/std::max 冲突 +#define NOMINMAX +// 重命名 PCANBasic.h 中与 Hcanbus.h 冲突的函数 +#define CAN_Reset PCAN_Reset +#define CAN_GetStatus PCAN_GetStatus +#define CAN_Init PCAN_Init +#define CAN_Transmit PCAN_Transmit +#define CAN_TransmitRt PCAN_TransmitRt +#define CAN_GetReceiveNum PCAN_GetReceiveNum +#define CAN_Receive PCAN_Receive +#define CAN_CloseDevice PCAN_CloseDevice +#define CANFD_Init PCANFD_Init +#define CANFD_Transmit PCANFD_Transmit +#define CANFD_TransmitRt PCANFD_TransmitRt +#define CANFD_GetReceiveNum PCANFD_GetReceiveNum +#define CANFD_Receive PCANFD_Receive +#include "PCANBasic.h" +// 恢复原始函数名 +#undef CAN_Reset +#undef CAN_GetStatus +#undef CAN_Init +#undef CAN_Transmit +#undef CAN_TransmitRt +#undef CAN_GetReceiveNum +#undef CAN_Receive +#undef CAN_CloseDevice +#undef CANFD_Init +#undef CANFD_Transmit +#undef CANFD_TransmitRt +#undef CANFD_GetReceiveNum +#undef CANFD_Receive +using CanFrame = TPCANMsg; +#elif defined(__linux__) +#include +#include +using CanFrame = struct can_frame; +#elif defined(__APPLE__) && defined(__MACH__) +std::cout << "This is macOS!" << std::endl; +#else +#error "Unsupported platform" +#endif + +// 公共的 CAN 帧结构体 +struct CANFrame +{ + uint32_t can_id; // CAN 帧 ID + uint8_t can_dlc; // 数据长度 + uint8_t data[8]; // 数据 +}; + + +#endif // CAN_FRAME_H diff --git a/include/communication/CommFactory.h b/include/communication/CommFactory.h new file mode 100644 index 0000000..55c0cb8 --- /dev/null +++ b/include/communication/CommFactory.h @@ -0,0 +1,158 @@ +#ifndef COMM_FACTORY_H +#define COMM_FACTORY_H + +#include +#include +#include + +#include "core/Common.h" +#include "communication/ICanBus.h" +#include "communication/CanBus.h" +#include "communication/PCANBus.h" +#include "communication/ICanFD.h" +#include "communication/CanFD.h" +#include "communication/IModbus.h" +#include "communication/Modbus.h" +#if USE_ETHERCAT +#include "communication/EtherCAT.h" +#include "communication/IEtherCAT.h" +#endif + +namespace linkerhand { +namespace communication +{ + // 通信对象工厂。可创建:CanBus / PCANBus / CanFD / Modbus / EtherCAT。 + // 历史名 CanBusFactory 保留为兼容别名,见 CanBusFactory.h。 + class CommFactory + { + public: + // ====================== CAN ====================== + + // 按"通道字符串 + 比特率"创建 CAN 总线。 + // - Linux: interfaceOrChannel 直接透传给 SocketCAN(如 "can0" / "vcan0") + // - Windows: 解析尾部数字 N,映射到 PCAN_USBBUS{N+1}("can0"→USBBUS1); + // bitrate 必须为标准值之一:1000000 / 800000 / 500000 / 250000 / + // 125000 / 100000 / 50000 / 20000 + static std::unique_ptr createCanBus(const std::string& interfaceOrChannel, const int bitrate) + { + if (interfaceOrChannel.empty()) { + throw std::runtime_error("createCanBus: empty interface name"); + } + + #ifdef _WIN32 + // 解析 canN:取首个数字开始的整数后缀 + const auto pos = interfaceOrChannel.find_first_of("0123456789"); + if (pos == std::string::npos) { + throw std::runtime_error( + "createCanBus: cannot parse channel index from '" + interfaceOrChannel + "'"); + } + int idx = -1; + try { + idx = std::stoi(interfaceOrChannel.substr(pos)); + } catch (const std::exception&) { + throw std::runtime_error( + "createCanBus: invalid channel index in '" + interfaceOrChannel + "'"); + } + if (idx < 0 || idx > 15) { + throw std::runtime_error( + "createCanBus: PCAN supports can0..can15 only, got '" + interfaceOrChannel + "'"); + } + static const TPCANHandle kPcanHandles[16] = { + PCAN_USBBUS1, PCAN_USBBUS2, PCAN_USBBUS3, PCAN_USBBUS4, + PCAN_USBBUS5, PCAN_USBBUS6, PCAN_USBBUS7, PCAN_USBBUS8, + PCAN_USBBUS9, PCAN_USBBUS10, PCAN_USBBUS11, PCAN_USBBUS12, + PCAN_USBBUS13, PCAN_USBBUS14, PCAN_USBBUS15, PCAN_USBBUS16, + }; + TPCANHandle channel = kPcanHandles[idx]; + + TPCANBaudrate baud; + switch (bitrate) { + case 1000000: baud = PCAN_BAUD_1M; break; + case 800000: baud = PCAN_BAUD_800K; break; + case 500000: baud = PCAN_BAUD_500K; break; + case 250000: baud = PCAN_BAUD_250K; break; + case 125000: baud = PCAN_BAUD_125K; break; + case 100000: baud = PCAN_BAUD_100K; break; + case 50000: baud = PCAN_BAUD_50K; break; + case 20000: baud = PCAN_BAUD_20K; break; + default: + throw std::runtime_error( + "createCanBus: unsupported bitrate " + std::to_string(bitrate) + + "; valid: 1000000/800000/500000/250000/125000/100000/50000/20000"); + } + return std::make_unique(channel, baud); + #else + return std::make_unique(interfaceOrChannel, bitrate); + #endif + } + + static std::unique_ptr createCanBus(const HAND_TYPE hand) + { + if (hand == HAND_TYPE::LEFT || hand == HAND_TYPE::RIGHT) { + #ifdef _WIN32 + return std::make_unique(hand); + #else + return std::make_unique(hand); + #endif + } else { + throw std::runtime_error("Unsupported: " + hand); + } + } + + // ====================== CAN FD ====================== + // CanFD 类跨平台;构造参数 (dev_num, ch_num) 由 third_party libcanbus 定义。 + static std::unique_ptr createCanFD(uint32_t dev_num, uint32_t ch_num) + { + return std::unique_ptr(new CanFD(dev_num, ch_num)); + } + + // 按手别推断通道号(LEFT→ch0, RIGHT→ch1,dev 固定 0); + // 真实硬件如有不同布线,请改用上面带显式参数的重载。 + static std::unique_ptr createCanFD(const HAND_TYPE hand) + { + uint32_t ch = 0; + if (hand == HAND_TYPE::RIGHT) ch = 1; + else if (hand != HAND_TYPE::LEFT) { + throw std::runtime_error("createCanFD: Unsupported HAND_TYPE"); + } + return std::unique_ptr(new CanFD(0, ch)); + } + + // ====================== Modbus RTU ====================== + + static std::unique_ptr createModbus(const std::string& device, + int baudrate = 115200, + char parity = 'N') + { + return std::unique_ptr(new Modbus(device, baudrate, parity)); + } + + // 按手别自动检测串口(实现见 Modbus(HAND_TYPE,...) 构造) + static std::unique_ptr createModbus(HAND_TYPE hand, + int baudrate = 115200, + char parity = 'N') + { + if (hand != HAND_TYPE::LEFT && hand != HAND_TYPE::RIGHT) { + throw std::runtime_error("createModbus: Unsupported HAND_TYPE"); + } + return std::unique_ptr(new Modbus(hand, baudrate, parity)); + } + + // ====================== EtherCAT ====================== + // 仅 Linux + USE_ETHERCAT=ON。未启用编译选项时本方法不声明, + // 调用站点编译期可见缺失,便于排错。 + #if USE_ETHERCAT + static std::unique_ptr createEtherCAT(uint32_t handId) + { + return std::unique_ptr(new EtherCAT(handId)); + } + #endif + }; +} // namespace communication +} // namespace linkerhand + +namespace Communication { + using CommFactory = ::linkerhand::communication::CommFactory; +} + +#endif // COMM_FACTORY_H diff --git a/include/communication/CommunicationCallbacks.h b/include/communication/CommunicationCallbacks.h new file mode 100644 index 0000000..715c7a4 --- /dev/null +++ b/include/communication/CommunicationCallbacks.h @@ -0,0 +1,51 @@ +// CommunicationCallbacks.h +#pragma once +#include +#include +#include +#include +#include +#include +#include "communication/CanFrame.h" +#include "core/Common.h" + + +// 统一的消息ID类型 +// using MsgId = std::variant; + +// 统一的数据缓冲区 +using DataBuffer = std::vector; + +// 通用的发送回调函数类型 +// using CommTxCallback = std::function; +// 通用的接收回调函数类型 +// using CommRxCallback = std::function; + +// TX回调函数类型:发送数据 (CAN ID, 数据指针, 数据长度) -> 返回状态码 +using CanTxCallback = std::function; +// RX回调函数类型:接收数据 (CAN ID, 数据指针, 数据长度) -> 返回状态码 +using CanRxCallback = std::function; + +// using CanTxCallback = std::function; +// using CanRxCallback = std::function; + +using ModbusTxCallback = std::function; +using ModbusRxCallback = std::function; + +using EthercatTxCallback = std::function; +using EthercatRxCallback = std::function; + +// 协议类型枚举 +enum class ProtocolType { + CAN, + MODBUS, + ETHERCAT +}; diff --git a/include/EtherCAT.h b/include/communication/EtherCAT.h similarity index 84% rename from include/EtherCAT.h rename to include/communication/EtherCAT.h index fae6daa..dfd901a 100644 --- a/include/EtherCAT.h +++ b/include/communication/EtherCAT.h @@ -1,6 +1,6 @@ #ifdef __linux__ -#ifndef LINKERHAND_ETHERCAT_H -#define LINKERHAND_ETHERCAT_H +#ifndef ETHERCAT_H +#define ETHERCAT_H #include #include @@ -15,8 +15,8 @@ #include #include -#include "Common.h" -#include "ICanBus.h" +#include "core/Common.h" +#include "communication/IEtherCAT.h" // constexpr uint32_t PERIOD_US = 10000; // 10ms constexpr uint32_t PERIOD_US = 1000; // 10ms @@ -25,23 +25,21 @@ constexpr unsigned int MASTER_INDEX = 0; constexpr uint32_t cycle_ns = 8000000; // 8ms 周期 namespace linkerhand { -namespace communication { +namespace communication //Communicator +{ -/** - * @brief EtherCAT 通信实现 - */ -class EtherCAT : public ICanBus { + class EtherCAT : public IEtherCAT { public: EtherCAT(const uint32_t handId); ~EtherCAT(); - bool init(); - void start(); - void stop(); + bool init() override; + void start() override; + void stop() override; void send_can_data(const unsigned int id, const std::vector &data); - void send(const std::vector& data, uint32_t can_id, const bool wait = false) override; + void send(const std::vector& data, uint32_t can_id, bool wait = false) override; CANFrame recv(uint32_t& id) override; private: @@ -116,11 +114,12 @@ class EtherCAT : public ICanBus { bool is_detection_hand; uint32_t handId_; }; -} // namespace communication -} // namespace linkerhand +} // namespace communication +} // namespace linkerhand -// 向后兼容:在全局命名空间中提供别名 -namespace Communication = linkerhand::communication; +namespace Communication { + using EtherCAT = ::linkerhand::communication::EtherCAT; +} -#endif // LINKERHAND_ETHERCAT_H +#endif // ETHERCAT_H #endif diff --git a/include/communication/ICanBus.h b/include/communication/ICanBus.h new file mode 100644 index 0000000..58b09a5 --- /dev/null +++ b/include/communication/ICanBus.h @@ -0,0 +1,30 @@ +#ifndef I_CAN_BUS_H +#define I_CAN_BUS_H + +#include +#include +#include +#include "core/Common.h" +#include "communication/CanFrame.h" // 包含公共 CAN 帧声明 + +namespace linkerhand { +namespace communication +{ + class ICanBus + { + public: + virtual ~ICanBus() = default; + + virtual void send(const std::vector& data, uint32_t can_id, const bool wait = false) = 0; + virtual CANFrame recv() = 0; + }; +} // namespace communication +} // namespace linkerhand + +// 向后兼容别名:保留 Communication::ICanBus +namespace Communication +{ + using ICanBus = ::linkerhand::communication::ICanBus; +} + +#endif // I_CAN_BUS_H diff --git a/include/communication/ICanFD.h b/include/communication/ICanFD.h new file mode 100644 index 0000000..9e9b9af --- /dev/null +++ b/include/communication/ICanFD.h @@ -0,0 +1,41 @@ +#ifndef I_CANFD_H +#define I_CANFD_H + +#include +#include +#include +#include "core/Common.h" + +namespace linkerhand { +namespace communication +{ + struct CanFDFrame + { + bool valid; // 帧是否有效 + uint32_t can_id; // CAN FD 帧 ID + uint8_t can_dlc; // DLC (0-15) + uint8_t data[64]; // 数据 + uint8_t frame_type; // 帧类型 + uint8_t extern_flag; // 扩展帧标识 + }; + + class ICanFD + { + public: + virtual ~ICanFD() = default; + + virtual void send(const std::vector& data, uint32_t can_id, bool is_extended = true) = 0; + virtual CanFDFrame recv(int timeout_ms = 100) = 0; + virtual bool isOpen() const = 0; + }; +} // namespace communication +} // namespace linkerhand + +// 向后兼容别名 +namespace Communication +{ + using CanFDFrame = ::linkerhand::communication::CanFDFrame; + using ICanFD = ::linkerhand::communication::ICanFD; +} + +#endif // I_CANFD_H \ No newline at end of file diff --git a/include/communication/ICommunication.h b/include/communication/ICommunication.h new file mode 100644 index 0000000..539fbda --- /dev/null +++ b/include/communication/ICommunication.h @@ -0,0 +1,28 @@ +#ifndef I_COMMUNICATION_H +#define I_COMMUNICATION_H + +#include +#include +#include +#include + +namespace linkerhand { +namespace communication +{ + // 跨总线(CAN/Modbus/EtherCAT)抽象的占位接口。 + // 当前未被任何实现类继承——保留作为未来跨总线统一抽象的占位, + // 实际实现请走 ICanBus / ICanFD / IModbus / IEtherCAT 各自的接口。 + class ICommunication + { + public: + virtual ~ICommunication() = default; + virtual void send(const std::vector& data, uint32_t &id, const int &start_address = 0, const int &num = 0) = 0; + virtual std::vector recv(uint32_t& id, const int &start_address = 0, const int &num = 0) = 0; + }; +} // namespace communication +} // namespace linkerhand + +// 向后兼容:原本 ICommunication 是全局类 +using ICommunication = ::linkerhand::communication::ICommunication; + +#endif // I_COMMUNICATION_H \ No newline at end of file diff --git a/include/communication/IEtherCAT.h b/include/communication/IEtherCAT.h new file mode 100644 index 0000000..db9485f --- /dev/null +++ b/include/communication/IEtherCAT.h @@ -0,0 +1,45 @@ +#ifdef __linux__ +#ifndef I_ETHER_CAT_H +#define I_ETHER_CAT_H + +#include +#include + +#include "communication/CanFrame.h" + +namespace linkerhand { +namespace communication { + +// EtherCAT 抽象。EtherCAT 不是 CAN,但 SDK 把"CAN over EtherCAT"做成 +// 上层握手协议的兼容层,故仍以 CAN 帧作为收发单元。 +// +// 与 ICanBus 故意不共享:recv 签名带 out 参数 id,send 行为也由 EtherCAT +// 周期性 PDO 调度驱动而非"立即发送"。强行复用 ICanBus 会让两个接口的语义 +// 互相侵蚀(历史代码就是这么写错的)。 +class IEtherCAT { +public: + virtual ~IEtherCAT() = default; + + // 初始化主站、扫描从站、配置 PDO;失败返回 false + virtual bool init() = 0; + + // 起停周期任务(init 之后调用) + virtual void start() = 0; + virtual void stop() = 0; + + // 向 EtherCAT 总线写一帧"CAN 风格"数据;wait=true 时阻塞至 PDO 周期完成 + virtual void send(const std::vector& data, uint32_t can_id, bool wait = false) = 0; + + // 读一帧;id 通过 out 参数返回 + virtual CANFrame recv(uint32_t& id) = 0; +}; + +} // namespace communication +} // namespace linkerhand + +namespace Communication { + using IEtherCAT = ::linkerhand::communication::IEtherCAT; +} + +#endif // I_ETHER_CAT_H +#endif // __linux__ diff --git a/include/communication/IModbus.h b/include/communication/IModbus.h new file mode 100644 index 0000000..bcd2cec --- /dev/null +++ b/include/communication/IModbus.h @@ -0,0 +1,40 @@ +#ifndef I_MODBUS_H +#define I_MODBUS_H + +#include +#include + +namespace linkerhand { +namespace communication { + +// Modbus RTU 通信抽象。 +// 实例化由 CanBusFactory::createModbus 返回 std::unique_ptr。 +// 静态工具方法(detect_serial_ports / auto_detect_serial_port)保留在 +// 实现类 Modbus 上,不进抽象接口。 +class IModbus { +public: + virtual ~IModbus() = default; + + virtual bool isOpen() const = 0; + virtual void close() = 0; + + // 直接发送一帧字节(不做 CRC 处理) + virtual bool sendRawFrame(const uint8_t* data, size_t length) = 0; + + // 自动按 RTU 协议接收完整一帧;超时 timeout_ms 毫秒;返回字节数,失败 -1 + virtual int receiveCompleteFrame(uint8_t* buffer, size_t max_size, int timeout_ms = 500) = 0; + + // 原子事务:发送 request 并等待 response(线程安全);返回 response 长度,失败 -1 + virtual int transact(const uint8_t* request, size_t request_len, + uint8_t* response, size_t max_response_len, + int timeout_ms = 500) = 0; +}; + +} // namespace communication +} // namespace linkerhand + +namespace Communication { + using IModbus = ::linkerhand::communication::IModbus; +} + +#endif // I_MODBUS_H diff --git a/include/communication/Modbus.h b/include/communication/Modbus.h new file mode 100644 index 0000000..9f43728 --- /dev/null +++ b/include/communication/Modbus.h @@ -0,0 +1,98 @@ +#ifndef RS485_MODBUS_DEVICE_H +#define RS485_MODBUS_DEVICE_H + +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "core/Common.h" +#include "core/LinkerHandExport.h" +#include "communication/IModbus.h" + +namespace linkerhand { +namespace communication { + +class LINKERHAND_API Modbus : public IModbus { +public: + Modbus(const std::string& device = "/dev/ttyUSB0", int baudrate = 115200, char parity = 'N'); + Modbus(int baudrate, char parity); // 自动检测串口的构造函数 + Modbus(HAND_TYPE hand_type, int baudrate = 115200, char parity = 'N'); // 基于手型的自动检测构造函数 + ~Modbus(); + + bool initialize(); + void close() override; + + // 检查串口是否成功打开 +#ifdef _WIN32 + bool isOpen() const override { return hSerial_ != INVALID_HANDLE_VALUE; } +#else + bool isOpen() const override { return fd_ >= 0; } +#endif + + // 通用的发送与接收接口 + bool sendRawFrame(const uint8_t* data, size_t length) override; + + /** + * @brief 自动处理 Modbus RTU 响应的完整性接收 + * @return 接收到的总字节数,失败返回 -1 + */ + int receiveCompleteFrame(uint8_t* buffer, size_t max_size, int timeout_ms = 500) override; + + /** + * @brief 原子事务:发送请求并接收响应(线程安全) + * @param request 发送的请求数据 + * @param request_len 请求数据长度 + * @param response 存储响应的缓冲区 + * @param max_response_len 响应缓冲区最大长度 + * @param timeout_ms 超时时间(毫秒) + * @return 接收到的响应长度,失败返回 -1 + */ + int transact(const uint8_t* request, size_t request_len, uint8_t* response, size_t max_response_len, int timeout_ms = 500) override; + + void setDebugMode(bool enable) { debug_mode_ = enable; } + +public: + // 静态方法:检测可用串口列表 + static std::vector detect_serial_ports(); + // 静态方法:自动检测可用串口(返回第一个可用的串口) + static std::string auto_detect_serial_port(int baudrate); + // 静态方法:基于手型自动检测串口 + static std::string auto_detect_serial_port(HAND_TYPE hand_type, int baudrate); + +private: + std::string device_; + int baudrate_; + char parity_; +#ifdef _WIN32 + HANDLE hSerial_; +#else + int fd_; +#endif + std::mutex mutex_; + bool debug_mode_; + + bool configureSerialPort(); + int readWithTimeout(uint8_t* buf, size_t len, int timeout_ms); + + // 内部无锁版本的方法,供 transact 使用 + bool sendRawFrameInternal(const uint8_t* data, size_t length); + int receiveCompleteFrameInternal(uint8_t* buffer, size_t max_size, int timeout_ms); + + // 手型检测相关方法 + static bool ping_interface(const std::string& port, int baudrate, const struct DetectionJob& job); +}; + +} // namespace communication +} // namespace linkerhand + +// 向后兼容:原本 Modbus 是全局类 +using Modbus = ::linkerhand::communication::Modbus; + +#endif \ No newline at end of file diff --git a/include/PCANBus.h b/include/communication/PCANBus.h similarity index 58% rename from include/PCANBus.h rename to include/communication/PCANBus.h index 1578308..39cea94 100644 --- a/include/PCANBus.h +++ b/include/communication/PCANBus.h @@ -1,6 +1,6 @@ #ifdef _WIN32 -#ifndef LINKERHAND_PCAN_BUS_H -#define LINKERHAND_PCAN_BUS_H +#ifndef PCAN_BUS_H +#define PCAN_BUS_H #include #include @@ -15,22 +15,21 @@ #include #include -#include "ICanBus.h" +#include "core/LinkerHandExport.h" +#include "communication/ICanBus.h" namespace linkerhand { -namespace communication { - -/** - * @brief Windows PCAN 总线实现 - */ -class PCANBus : public ICanBus +namespace communication +{ + class LINKERHAND_API PCANBus : public ICanBus { public: - PCANBus(TPCANHandle channel, TPCANBaudrate bitrate, const LINKER_HAND linkerhand); + PCANBus(TPCANHandle channel, TPCANBaudrate bitrate); + PCANBus(HAND_TYPE hand_type); ~PCANBus(); std::string printMillisecondTime(); void send(const std::vector& data, uint32_t can_id, const bool wait = false) override; - CANFrame recv(uint32_t &id) override; + CANFrame recv() override; void updateSendRate(); void updateReceiveRate(); @@ -46,12 +45,17 @@ class PCANBus : public ICanBus std::atomic receive_count; std::chrono::steady_clock::time_point receive_last_time; std::queue send_queue; + + static std::vector detect_can_interfaces(); + static bool ping_interface(TPCANHandle channel, const struct DetectionJob& job); + static TPCANHandle auto_detect_channel(HAND_TYPE hand_type); }; -} // namespace communication -} // namespace linkerhand +} // namespace communication +} // namespace linkerhand -// 向后兼容:在全局命名空间中提供别名 -namespace Communication = linkerhand::communication; +namespace Communication { + using PCANBus = ::linkerhand::communication::PCANBus; +} -#endif // LINKERHAND_PCAN_BUS_H +#endif // PCAN_BUS_H #endif diff --git a/include/core/Common.h b/include/core/Common.h new file mode 100644 index 0000000..c9a9384 --- /dev/null +++ b/include/core/Common.h @@ -0,0 +1,94 @@ +#ifndef COMMON_H +#define COMMON_H + +#include + +enum LINKER_HAND { + L6, + L7, + L10, + L20, + L21, + L25, + O6, + G20, + O20 +}; + +enum HAND_TYPE { + LEFT = 0x28, + RIGHT = 0x27 +}; + +enum COMM_TYPE { + CAN, + MODBUS, + ETHERCAT +}; + +// 新风格枚举(推荐新代码使用)。 +// 旧的 LINKER_HAND / HAND_TYPE / COMM_TYPE 保留作向后兼容,不要删。 +namespace linkerhand +{ + +enum class HandModel : uint8_t { + L6, + L7, + L10, + L20, + L21, + L25, + G20, + O6, + O20 +}; + +enum class HandType : uint8_t { + LEFT = 0x28, + RIGHT = 0x27 +}; + +enum class CommType : uint8_t { + CAN, + MODBUS, + ETHERCAT +}; + +inline LINKER_HAND to_legacy(HandModel m) { + switch (m) { + case HandModel::L6: return LINKER_HAND::L6; + case HandModel::L7: return LINKER_HAND::L7; + case HandModel::L10: return LINKER_HAND::L10; + case HandModel::L20: return LINKER_HAND::L20; + case HandModel::L21: return LINKER_HAND::L21; + case HandModel::L25: return LINKER_HAND::L25; + case HandModel::G20: return LINKER_HAND::G20; + case HandModel::O6: return LINKER_HAND::O6; + case HandModel::O20: return LINKER_HAND::O20; + } + return LINKER_HAND::L10; +} + +inline HAND_TYPE to_legacy(HandType t) { + return t == HandType::LEFT ? HAND_TYPE::LEFT : HAND_TYPE::RIGHT; +} + +inline COMM_TYPE to_legacy(CommType c) { + switch (c) { + case CommType::CAN: return COMM_TYPE::CAN; + case CommType::MODBUS: return COMM_TYPE::MODBUS; + case CommType::ETHERCAT: return COMM_TYPE::ETHERCAT; + } + return COMM_TYPE::CAN; +} + +} // namespace linkerhand + +namespace Common +{ + extern float current_hand_version; +} +#define SEND_DEBUG 0 +#define RECV_DEBUG 0 + +#endif // COMMON_H diff --git a/include/core/ErrorCode.h b/include/core/ErrorCode.h new file mode 100644 index 0000000..1c729df --- /dev/null +++ b/include/core/ErrorCode.h @@ -0,0 +1,107 @@ +#ifndef LINKERHAND_ERROR_CODE_H +#define LINKERHAND_ERROR_CODE_H + +#include +#include +#include + +namespace linkerhand { + +// LinkerHand SDK 错误码 +enum class HandError { + Success = 0, + UnsupportedFeature, + CommunicationError, + InvalidParameter, + DeviceNotFound, + Timeout, + InvalidState, + OperationFailed, + NotInitialized, + AlreadyInitialized, + OutOfRange, + UnknownError +}; + +class HandErrorCategory : public std::error_category { +public: + const char* name() const noexcept override { + return "LinkerHand"; + } + + std::string message(int ev) const override { + switch (static_cast(ev)) { + case HandError::Success: return "Success"; + case HandError::UnsupportedFeature: return "Unsupported feature"; + case HandError::CommunicationError: return "Communication error"; + case HandError::InvalidParameter: return "Invalid parameter"; + case HandError::DeviceNotFound: return "Device not found"; + case HandError::Timeout: return "Timeout"; + case HandError::InvalidState: return "Invalid state"; + case HandError::OperationFailed: return "Operation failed"; + case HandError::NotInitialized: return "Not initialized"; + case HandError::AlreadyInitialized: return "Already initialized"; + case HandError::OutOfRange: return "Out of range"; + case HandError::UnknownError: + default: return "Unknown error"; + } + } +}; + +inline const HandErrorCategory& hand_error_category() { + static HandErrorCategory instance; + return instance; +} + +inline std::error_code make_error_code(HandError e) { + return std::error_code(static_cast(e), hand_error_category()); +} + +class HandException : public std::runtime_error { +public: + HandException(HandError error, const std::string& message) + : std::runtime_error(message), error_code_(error) {} + + HandError error_code() const noexcept { + return error_code_; + } + +private: + HandError error_code_; +}; + +class UnsupportedFeatureException : public HandException { +public: + explicit UnsupportedFeatureException(const std::string& feature_name) + : HandException(HandError::UnsupportedFeature, + "Unsupported feature: " + feature_name), + feature_name_(feature_name) {} + + const std::string& feature_name() const noexcept { + return feature_name_; + } + +private: + std::string feature_name_; +}; + +class CommunicationException : public HandException { +public: + explicit CommunicationException(const std::string& message) + : HandException(HandError::CommunicationError, message) {} +}; + +class InvalidParameterException : public HandException { +public: + explicit InvalidParameterException(const std::string& message) + : HandException(HandError::InvalidParameter, message) {} +}; + +} // namespace linkerhand + +namespace std { + template<> + struct is_error_code_enum : true_type {}; +} + +#endif // LINKERHAND_ERROR_CODE_H diff --git a/include/core/LinkerHandExport.h b/include/core/LinkerHandExport.h new file mode 100644 index 0000000..a23a559 --- /dev/null +++ b/include/core/LinkerHandExport.h @@ -0,0 +1,14 @@ +#ifndef LINKER_HAND_EXPORT_H +#define LINKER_HAND_EXPORT_H + +#if defined(_WIN32) || defined(_WIN64) + #if defined(LINKERHAND_EXPORTS) + #define LINKERHAND_API __declspec(dllexport) + #else + #define LINKERHAND_API __declspec(dllimport) + #endif +#else + #define LINKERHAND_API +#endif + +#endif // LINKER_HAND_EXPORT_H diff --git a/lib/aarch64/liblinkerhand_cpp_sdk.so b/lib/aarch64/liblinkerhand_cpp_sdk.so deleted file mode 120000 index 9f9b643..0000000 --- a/lib/aarch64/liblinkerhand_cpp_sdk.so +++ /dev/null @@ -1 +0,0 @@ -liblinkerhand_cpp_sdk.so.1 \ No newline at end of file diff --git a/lib/aarch64/liblinkerhand_cpp_sdk.so.1 b/lib/aarch64/liblinkerhand_cpp_sdk.so.1 deleted file mode 120000 index 14acb07..0000000 --- a/lib/aarch64/liblinkerhand_cpp_sdk.so.1 +++ /dev/null @@ -1 +0,0 @@ -liblinkerhand_cpp_sdk.so.1.5.8 \ No newline at end of file diff --git a/lib/aarch64/liblinkerhand_cpp_sdk.so.1.5.8 b/lib/aarch64/liblinkerhand_cpp_sdk.so.1.5.8 deleted file mode 100755 index e9175bd..0000000 Binary files a/lib/aarch64/liblinkerhand_cpp_sdk.so.1.5.8 and /dev/null differ diff --git a/lib/linux/arm64/linkerhand_cpp_sdk.so b/lib/linux/arm64/linkerhand_cpp_sdk.so new file mode 120000 index 0000000..2339b24 --- /dev/null +++ b/lib/linux/arm64/linkerhand_cpp_sdk.so @@ -0,0 +1 @@ +linkerhand_cpp_sdk.so.2 \ No newline at end of file diff --git a/lib/linux/arm64/linkerhand_cpp_sdk.so.2 b/lib/linux/arm64/linkerhand_cpp_sdk.so.2 new file mode 120000 index 0000000..5046f44 --- /dev/null +++ b/lib/linux/arm64/linkerhand_cpp_sdk.so.2 @@ -0,0 +1 @@ +linkerhand_cpp_sdk.so.2.0.0 \ No newline at end of file diff --git a/lib/linux/arm64/linkerhand_cpp_sdk.so.2.0.0 b/lib/linux/arm64/linkerhand_cpp_sdk.so.2.0.0 new file mode 100644 index 0000000..ea664d5 Binary files /dev/null and b/lib/linux/arm64/linkerhand_cpp_sdk.so.2.0.0 differ diff --git a/lib/linux/x86_64/linkerhand_cpp_sdk.so b/lib/linux/x86_64/linkerhand_cpp_sdk.so new file mode 120000 index 0000000..2339b24 --- /dev/null +++ b/lib/linux/x86_64/linkerhand_cpp_sdk.so @@ -0,0 +1 @@ +linkerhand_cpp_sdk.so.2 \ No newline at end of file diff --git a/lib/linux/x86_64/linkerhand_cpp_sdk.so.2 b/lib/linux/x86_64/linkerhand_cpp_sdk.so.2 new file mode 120000 index 0000000..5046f44 --- /dev/null +++ b/lib/linux/x86_64/linkerhand_cpp_sdk.so.2 @@ -0,0 +1 @@ +linkerhand_cpp_sdk.so.2.0.0 \ No newline at end of file diff --git a/lib/linux/x86_64/linkerhand_cpp_sdk.so.2.0.0 b/lib/linux/x86_64/linkerhand_cpp_sdk.so.2.0.0 new file mode 100644 index 0000000..b3f14f2 Binary files /dev/null and b/lib/linux/x86_64/linkerhand_cpp_sdk.so.2.0.0 differ diff --git a/lib/win64/mingw/libgcc_s_seh-1.dll b/lib/win64/mingw/libgcc_s_seh-1.dll new file mode 100644 index 0000000..2123922 Binary files /dev/null and b/lib/win64/mingw/libgcc_s_seh-1.dll differ diff --git a/lib/win64/mingw/libstdc++-6.dll b/lib/win64/mingw/libstdc++-6.dll new file mode 100644 index 0000000..72bf0fc Binary files /dev/null and b/lib/win64/mingw/libstdc++-6.dll differ diff --git a/lib/win64/mingw/linkerhand_cpp_sdk.dll b/lib/win64/mingw/linkerhand_cpp_sdk.dll new file mode 100644 index 0000000..f42b08f Binary files /dev/null and b/lib/win64/mingw/linkerhand_cpp_sdk.dll differ diff --git a/lib/win64/msvc/linkerhand_cpp_sdk.dll b/lib/win64/msvc/linkerhand_cpp_sdk.dll new file mode 100644 index 0000000..397448e Binary files /dev/null and b/lib/win64/msvc/linkerhand_cpp_sdk.dll differ diff --git a/lib/win64/msvc/linkerhand_cpp_sdk.lib b/lib/win64/msvc/linkerhand_cpp_sdk.lib new file mode 100644 index 0000000..68d32b8 Binary files /dev/null and b/lib/win64/msvc/linkerhand_cpp_sdk.lib differ diff --git a/lib/x86_64/liblinkerhand_cpp_sdk.so b/lib/x86_64/liblinkerhand_cpp_sdk.so deleted file mode 120000 index 9f9b643..0000000 --- a/lib/x86_64/liblinkerhand_cpp_sdk.so +++ /dev/null @@ -1 +0,0 @@ -liblinkerhand_cpp_sdk.so.1 \ No newline at end of file diff --git a/lib/x86_64/liblinkerhand_cpp_sdk.so.1 b/lib/x86_64/liblinkerhand_cpp_sdk.so.1 deleted file mode 120000 index 14acb07..0000000 --- a/lib/x86_64/liblinkerhand_cpp_sdk.so.1 +++ /dev/null @@ -1 +0,0 @@ -liblinkerhand_cpp_sdk.so.1.5.8 \ No newline at end of file diff --git a/lib/x86_64/liblinkerhand_cpp_sdk.so.1.5.8 b/lib/x86_64/liblinkerhand_cpp_sdk.so.1.5.8 deleted file mode 100755 index 7a41752..0000000 Binary files a/lib/x86_64/liblinkerhand_cpp_sdk.so.1.5.8 and /dev/null differ diff --git a/script.sh b/script.sh deleted file mode 100755 index 044e69b..0000000 --- a/script.sh +++ /dev/null @@ -1,241 +0,0 @@ -#!/bin/bash - -# 从 CMakeLists.txt 读取版本号 -VERSION=$(grep -E "^\s*VERSION\s+" CMakeLists.txt | head -1 | sed 's/.*VERSION\s\+\([0-9.]*\).*/\1/') -if [ -z "$VERSION" ]; then - # 如果无法读取,使用默认版本 - VERSION="1.1.7" -fi - -# 确定系统架构 -ARCH=$(uname -m) - -# 设置安装目录 -INSTALL_PREFIX="/usr/local" - - -function LoadedColor_information() -{ - # 文本颜色 - BLACK='\033[0;30m' - # 黑色 - RED='\033[0;31m' - # 红色 - GREEN='\033[0;32m' - # 绿色 - YELLOW='\033[0;33m' - # 黄色 - BLUE='\033[0;34m' - # 蓝色 - PURPLE='\033[0;35m' - # 紫色 - CYAN='\033[0;36m' - # 青色 - WHITE='\033[0;37m' - # 白色 - - RED_WHITE='\033[47;31m' - # 红色 - GREEN_WHITE='\033[47;32m' - # 绿色 - WHITE_BLACK='\033[40;37m' - # 白色+黑色 - YELLOW_WHITE='\033[47;33m' - - # 黄色+白色 - # 背景颜色 - BLACK_B='\033[40m' - # 黑色 - RED_B='\033[41m' - # 红色 - GREEN_B='\033[42m' - # 绿色 - yellow_B='\033[43m' - # 黄色 - blue_B='\033[44m' - # 蓝色 - purple_B='\033[45m' - # 紫色 - Cyan_B='\033[46m' - # 青色 - White_B='\033[47m' - # 白色 - - # 文本样式 - RESET='\033[0m' - # 重置所有属性 - BOLD='\033[1m' - # 粗体 - underline='\033[4m' - # 下划线 - Blinking='\033[5m' - # 闪烁 - Invert='\033[7m' - # 反显 - Hidden='\033[8m' - # 隐藏 -# echo "=========================================================" -# echo -e "${GREEN}Successfully loaded color information !${RESET}" -# echo "=========================================================" -} - -CLOSE_RESERVE="exce bash" # exce bash - -RUN() { - local launch=$1 - gnome-terminal -- bash -c "source devel/setup.sh; $launch; $CLOSE_RESERVE" - sleep 3 -} - - -RUN1() { - local launch=$1 - local command package launch_file - - IFS=' ' read -r command package launch_file <<< "$launch" - - gnome-terminal -- bash -c "source devel/setup.sh; $launch; $CLOSE_RESERVE" > /dev/null 2>&1 - - echo "Node: $package" - while ! rosnode list | grep -q $package; do - echo -e " starting..." - sleep 1 - done - echo -e " Startup completed" -} - - -function build_sdk(){ - mkdir build; cd build; cmake ..; make; cd .. -} - -function install_sdk(){ - # 安装脚本 - set -e - - echo "检测到系统架构: $ARCH" - echo "正在安装 linkerhand-cpp-sdk 到系统..." - - # 安装头文件 - echo "安装头文件到 $INSTALL_PREFIX/include/linkerhand-cpp-sdk..." - sudo mkdir -p $INSTALL_PREFIX/include/linkerhand-cpp-sdk - sudo cp -r include/* $INSTALL_PREFIX/include/linkerhand-cpp-sdk/ - - # 安装库文件 - if [ "$ARCH" = "x86_64" ]; then - echo "安装 x86_64 库文件..." - sudo mkdir -p $INSTALL_PREFIX/lib/linkerhand-cpp-sdk/x86_64 - sudo cp -r lib/x86_64/* $INSTALL_PREFIX/lib/linkerhand-cpp-sdk/x86_64/ - # 创建符号链接到标准库目录 - for lib_file in lib/x86_64/*.so*; do - lib_name=$(basename $lib_file) - sudo ln -sf $INSTALL_PREFIX/lib/linkerhand-cpp-sdk/x86_64/$lib_name $INSTALL_PREFIX/lib/ - done - elif [ "$ARCH" = "aarch64" ]; then - echo "安装 aarch64 库文件..." - sudo mkdir -p $INSTALL_PREFIX/lib/linkerhand-cpp-sdk/aarch64 - sudo cp -r lib/aarch64/* $INSTALL_PREFIX/lib/linkerhand-cpp-sdk/aarch64/ - # 创建符号链接到标准库目录 - for lib_file in lib/aarch64/*.so*; do - lib_name=$(basename $lib_file) - sudo ln -sf $INSTALL_PREFIX/lib/linkerhand-cpp-sdk/aarch64/$lib_name $INSTALL_PREFIX/lib/ - done - else - echo "不支持的架构: $ARCH" - exit 1 - fi - - # 更新动态链接库缓存 - echo "更新动态链接库缓存..." - sudo ldconfig - - echo "安装完成!" - echo "" - echo "使用示例:" - echo " 编译: g++ -o test test.cpp -llinkerhand_cpp_sdk -I/usr/local/include/linkerhand-cpp-sdk" - echo " 运行: LD_LIBRARY_PATH=/usr/local/lib ./test" -} - -function uninstall_sdk(){ - sudo rm -rf $INSTALL_PREFIX/lib/linkerhand-cpp-sdk - sudo rm -rf $INSTALL_PREFIX/include/linkerhand-cpp-sdk - sudo rm -rf $INSTALL_PREFIX/lib/liblinkerhand_cpp_sdk.so* -} - -function run_example(){ - cd build; ./toolset_example -} - -#------------------------------------------------ Select Menu ------------------------------------------ - -function select_menu(){ - cd $current_dir - echo -e "${GREEN}Please enter options: ${RESET}" - read -p "" select_num - case $select_num in - 1) - echo "Build SDK" - build_sdk - ;; - 2) - echo "Install SDK" - build_sdk - install_sdk - ;; - 3) - echo "Uninstall SDK" - uninstall_sdk - ;; - 6) - echo "Execution Example" - run_example - ;; - 0) - echo "Exit" - exit - ;; - *) - echo -e "${RED}Input error, please re-enter!${RESET}" - sleep 1 - ;; - esac -} - -#------------------------------------------------ Menu ------------------------------------------ -function show_Info(){ - echo -e "${YELLOW}" - echo "================================================" - echo -e "${YELLOW} LinkerHand CPP-SDK Version:${VERSION} ${RESET}" - echo -e "${YELLOW}================================================${RESET}" - - echo -e "${GREEN}" - echo "RUN Choose Task:" - echo -e "${YELLOW}————————————————————————————————————————————————${RESET}" - echo -e "${BLUE}[1]: Build SDK${RESET}" - echo -e "${YELLOW}————————————————————————————————————————————————${RESET}" - echo -e "${BLUE}[2]: Install SDK${RESET}" - echo -e "${YELLOW}————————————————————————————————————————————————${RESET}" - echo -e "${BLUE}[3]: Uninstall SDK${RESET}" - echo -e "${YELLOW}————————————————————————————————————————————————${RESET}" - echo -e "${RED}[0]: Exit${RESET}" - echo -e "${YELLOW}————————————————————————————————————————————————${RESET}" - # sudo make DESTDIR=/home/lst/Desktop/install install -} - -#------------------------------------------------ Init ------------------------------------------ - -function Init() -{ - LoadedColor_information - current_dir=$(pwd) - sleep 1 -} - -#------------------------------------------------ Main ------------------------------------------ - -Init -while true -do - show_Info - select_menu -done diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index 74bbb05..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "LinkerHandApi.h" - -int main() { - - // 调用API接口 - LinkerHandApi hand(LINKER_HAND::O6, HAND_TYPE::LEFT, "can0", 115200); - - // 获取版本信息 - std::cout << hand.getVersion() << std::endl; - - // 握拳 - std::vector fist_pose = {255, 255, 0, 0, 0, 0}; - hand.fingerMove(fist_pose); - std::this_thread::sleep_for(std::chrono::seconds(1)); - - // 张开 - std::vector open_pose = {255, 255, 255, 255, 255, 255}; - hand.fingerMove(open_pose); - std::this_thread::sleep_for(std::chrono::seconds(1)); - - return 0; -} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index a1b428d..0000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1,76 +0,0 @@ -# 测试配置 -# 只有在启用测试时才构建测试 - -if(BUILD_TESTING) - # 查找或下载 Google Test - include(FetchContent) - FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/refs/tags/v1.17.0.zip - # GIT_REPOSITORY https://github.com/google/googletest.git - # GIT_TAG v1.17.0 - ) - # 对于 Windows: 防止覆盖父项目的编译器/链接器设置 - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - FetchContent_MakeAvailable(googletest) - - # 启用测试 - enable_testing() - - # 包含目录 - include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/../include - ${LINKER_HAND_INCLUDE_DIR} - ) - - # 测试可执行文件列表 - set(TEST_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/unit/test_Common.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/unit/test_RangeToArc.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/unit/test_IHand_Utils.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/unit/test_CanFrame.cpp - ) - - # 为每个测试文件创建可执行文件 - foreach(TEST_SOURCE ${TEST_SOURCES}) - # 获取测试名称(从路径中提取) - get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE) - - # 创建测试可执行文件 - add_executable(${TEST_NAME} ${TEST_SOURCE}) - - # 链接库 - target_link_libraries(${TEST_NAME} - PRIVATE - gtest - gtest_main - pthread - ) - - # 如果测试需要 SDK 库,链接它 - # RangeToArc 函数在 SDK 库中实现 - if(TEST_SOURCE MATCHES "test_RangeToArc|test_LinkerHandApi|test_Hand") - target_link_libraries(${TEST_NAME} - PRIVATE - ${LINKER_HAND_LIB} - ) - endif() - - # 注册测试 - add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME}) - - # 设置测试属性 - set_tests_properties(${TEST_NAME} PROPERTIES - TIMEOUT 60 - ) - endforeach() - - # 创建运行所有测试的便捷目标 - add_custom_target(run_tests - COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure - DEPENDS ${TEST_SOURCES} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Running all tests" - ) -endif() - diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index 76dd2a8..0000000 --- a/tests/README.md +++ /dev/null @@ -1,675 +0,0 @@ -# 测试说明 - -本目录包含 LinkerHand-CPP-SDK 的单元测试。本文档介绍如何构建、运行测试,以及如何添加新测试。 - -## 目录 - -- [测试结构](#测试结构) -- [构建测试](#构建测试) -- [运行测试](#运行测试) -- [测试覆盖范围](#测试覆盖范围) -- [测试用例详解](#测试用例详解) -- [添加新测试](#添加新测试) -- [测试最佳实践](#测试最佳实践) -- [故障排查](#故障排查) -- [更多信息](#更多信息) - ---- - -## 测试结构 - -``` -tests/ -├── unit/ # 单元测试 -│ ├── test_Common.cpp # Common.h 的测试 -│ ├── test_RangeToArc.cpp # RangeToArc.h 的测试 -│ ├── test_IHand_Utils.cpp # IHand 工具函数的测试 -│ └── test_CanFrame.cpp # CanFrame 的测试 -├── CMakeLists.txt # 测试构建配置 -└── README.md # 本文件 -``` - ---- - -## 构建测试 - -### 方法一:使用 CMake 构建(推荐) - -```bash -# 在项目根目录 -mkdir build && cd build -cmake .. -DBUILD_TESTING=ON -make -``` - -**说明**: -- `-DBUILD_TESTING=ON` 启用测试构建(默认已启用) -- CMake 会自动下载 Google Test 框架(如果未安装) -- 确保网络连接正常,以便下载依赖 -- **注意**: 项目要求 CMake 3.15 或更高版本 - -### 方法二:禁用测试 - -如果不想构建测试: - -```bash -cmake .. -DBUILD_TESTING=OFF -``` - -或者不设置 `BUILD_TESTING` 选项(默认为 ON)。 - -### 方法三:仅构建测试(不构建主项目) - -```bash -cd build -cmake .. -DBUILD_TESTING=ON -make test_Common test_RangeToArc test_IHand_Utils test_CanFrame -``` - ---- - -## 运行测试 - -### 运行所有测试 - -```bash -cd build -ctest -``` - -**输出示例**: -``` -Test project /path/to/build - Start 1: test_Common -1/4 Test #1: test_Common ................... Passed 0.01 sec - Start 2: test_RangeToArc -2/4 Test #2: test_RangeToArc ............... Passed 0.02 sec - Start 3: test_IHand_Utils -3/4 Test #3: test_IHand_Utils .............. Passed 0.01 sec - Start 4: test_CanFrame -4/4 Test #4: test_CanFrame .................. Passed 0.01 sec - -100% tests passed, 0 tests failed out of 4 -``` - -### 运行所有测试(显示详细输出) - -```bash -cd build -ctest --output-on-failure -``` - -**说明**: 仅当测试失败时显示详细输出,成功时不显示。 - -### 运行所有测试(详细模式) - -```bash -cd build -ctest -V -# 或 -ctest --verbose -``` - -**说明**: 显示所有测试的详细输出,包括成功的测试。 - -### 运行特定测试 - -```bash -cd build -# 运行 test_Common -ctest -R test_Common - -# 运行多个测试(使用正则表达式) -ctest -R "test_Common|test_RangeToArc" -``` - -### 并行运行测试 - -```bash -cd build -# 使用 4 个并行任务 -ctest -j4 - -# 使用所有可用 CPU 核心 -ctest -j$(nproc) -``` - -**说明**: 并行运行可以加快测试速度,特别是测试较多时。 - -### 直接运行测试可执行文件 - -```bash -cd build -./test_Common -./test_RangeToArc -./test_IHand_Utils -./test_CanFrame -``` - -**说明**: 直接运行可执行文件可以看到更详细的输出,包括 Google Test 的详细日志。 - -### 使用便捷目标 - -```bash -cd build -make run_tests -``` - -**说明**: 如果 CMakeLists.txt 中定义了 `run_tests` 目标,可以使用此命令。 - ---- - -## 测试覆盖范围 - -### test_Common.cpp - -**测试内容**: Common.h 中的枚举和类型定义 - -**测试用例**: -- ✅ `LINKER_HAND` 枚举值测试 - - 验证所有型号枚举值(O6, L6, L7, L10, L20, L21, L25) -- ✅ `HAND_TYPE` 枚举值测试 - - 验证左手和右手枚举值 -- ✅ `COMM_TYPE` 枚举值测试 - - 验证所有通信类型枚举值 -- ✅ `Common` 命名空间版本号测试 - - 验证版本号定义 -- ✅ 参数化测试 - - 使用 Google Test 参数化测试测试多个值 - -**示例测试**: -```cpp -TEST(CommonTest, LinkerHandEnum) { - EXPECT_EQ(LINKER_HAND::O6, 0); - EXPECT_EQ(LINKER_HAND::L6, 1); - // ... -} -``` - ---- - -### test_RangeToArc.cpp - -**测试内容**: RangeToArc.h 中的转换函数 - -**测试用例**: -- ✅ `is_within_range()` 函数测试 - - 测试值是否在有效范围内 - - 边界值测试 -- ✅ `scale_value()` 函数测试 - - 测试值缩放功能 - - 边界情况测试 -- ✅ `should_skip_joint()` 函数测试 - - 测试关节跳过逻辑 -- ✅ `initialize_params()` 函数测试 - - 测试参数初始化 -- ✅ `range_to_arc()` 函数测试 - - 测试从 0-255 范围转换为弧度 - - 不同型号的转换测试 -- ✅ `arc_to_range()` 函数测试 - - 测试从弧度转换为 0-255 范围 -- ✅ 往返转换测试 - - 测试 `range_to_arc()` 和 `arc_to_range()` 的往返一致性 -- ✅ 边界值测试 - - 测试最小值(0)、最大值(255)、中间值(128) -- ✅ 不同型号测试 - - 测试 L10、L20、L21、L25 等不同型号的转换 - -**示例测试**: -```cpp -TEST(RangeToArcTest, RangeToArcConversion) { - double arc = range_to_arc(128, LINKER_HAND::L10, 0); - EXPECT_NEAR(arc, expected_value, 0.001); -} -``` - ---- - -### test_IHand_Utils.cpp - -**测试内容**: IHand 工具函数 - -**测试用例**: -- ✅ `getSubVector()` 单参数版本测试 - - 测试从向量中提取子向量 - - 边界情况测试(空向量、越界等) -- ✅ `getSubVector()` 双参数版本测试 - - 测试指定起始和结束位置的子向量提取 -- ✅ `getCurrentTime()` 函数测试 - - 测试时间获取功能 - - 时间格式验证 -- ✅ 边界情况测试 - - 空向量、单元素向量、越界访问等 - -**示例测试**: -```cpp -TEST(IHandUtilsTest, GetSubVector) { - std::vector vec = {1, 2, 3, 4, 5}; - auto sub = getSubVector(vec, 1, 3); - EXPECT_EQ(sub.size(), 2); - EXPECT_EQ(sub[0], 2); - EXPECT_EQ(sub[1], 3); -} -``` - ---- - -### test_CanFrame.cpp - -**测试内容**: CanFrame.h 中的 CAN 帧结构 - -**测试用例**: -- ✅ CANFrame 结构体测试 - - 结构体大小和布局验证 -- ✅ 数据设置和读取测试 - - 测试数据的设置和读取功能 -- ✅ 边界值测试 - - 测试最小值和最大值 -- ✅ ID 范围测试 - - 测试有效的 CAN ID 范围 -- ✅ 数据复制测试 - - 测试数据复制和移动语义 - -**示例测试**: -```cpp -TEST(CanFrameTest, DataSetting) { - CanFrame frame; - frame.setData({0x01, 0x02, 0x03, 0x04}); - auto data = frame.getData(); - EXPECT_EQ(data.size(), 4); - EXPECT_EQ(data[0], 0x01); -} -``` - ---- - -## 测试用例详解 - -### 测试命名规范 - -测试用例使用 Google Test 的命名规范: -- 测试套件名:描述被测试的模块(如 `CommonTest`、`RangeToArcTest`) -- 测试用例名:描述具体的测试内容(如 `LinkerHandEnum`、`RangeToArcConversion`) - -### 测试类型 - -1. **单元测试**: 测试单个函数或类的功能 -2. **参数化测试**: 使用 `TEST_P` 测试多个输入值 -3. **边界测试**: 测试边界值和极端情况 -4. **集成测试**: 测试多个组件的交互(当前未包含) - -### 测试覆盖率 - -当前测试覆盖: -- ✅ 核心工具函数(Common、RangeToArc、IHand Utils) -- ✅ 数据结构(CanFrame) -- ⚠️ API 函数(部分覆盖,需要硬件支持) -- ❌ 通信层(需要硬件支持) -- ❌ 端到端测试(需要硬件支持) - ---- - -## 添加新测试 - -### 步骤 1: 创建测试文件 - -在 `tests/unit/` 目录下创建新的测试文件,例如 `test_NewFeature.cpp`: - -```cpp -#include -#include "NewFeature.h" - -TEST(NewFeatureTest, BasicFunctionality) { - // 测试代码 - EXPECT_EQ(expected, actual); -} -``` - -### 命名规范说明 - -在编写测试时,请注意以下命名规范: - -1. **使用新的命名空间**(推荐): -```cpp -#include "LinkerHandL10.h" -#include "HandFactory.h" - -TEST(HandTest, L10HandCreation) { - using namespace linkerhand; - auto hand = factory::HandFactory::createHand( - LINKER_HAND::L10, - HAND_TYPE::RIGHT, - COMM_CAN_0 - ); - // 测试代码 -} -``` - -2. **向后兼容的旧命名**(可用但不推荐): -```cpp -#include "LinkerHandL10.h" - -TEST(HandTest, L10HandCreation) { - // 旧命名仍然可用,但建议使用新命名 - LinkerHandL10::LinkerHand hand(0x27, "can0", 1000000); - // 测试代码 -} -``` - -3. **接口测试**: -```cpp -#include "IHand.h" - -TEST(IHandTest, InterfaceTest) { - // 使用正确的命名空间 - class TestHand : public linkerhand::hand::IHand { - // 实现接口 - }; - // 测试代码 -} -``` - -更多关于命名规范的详细信息,请参考 [命名规范改进文档](../docs/NAMING_IMPROVEMENTS.md)。 - -### 步骤 2: 更新 CMakeLists.txt - -在 `tests/CMakeLists.txt` 的 `TEST_SOURCES` 列表中添加新文件: - -```cmake -set(TEST_SOURCES - unit/test_Common.cpp - unit/test_RangeToArc.cpp - unit/test_IHand_Utils.cpp - unit/test_CanFrame.cpp - unit/test_NewFeature.cpp # 添加新文件 -) -``` - -### 步骤 3: 配置链接(如需要) - -如果测试需要链接 SDK 库或其他库,在 CMakeLists.txt 中添加: - -```cmake -target_link_libraries(test_NewFeature - ${LINKER_HAND_LIB} # 如果需要链接 SDK 库 - pthread -) -``` - -### 步骤 4: 重新构建和运行 - -```bash -cd build -cmake .. -make -ctest -R test_NewFeature -``` - ---- - -## 测试最佳实践 - -### 1. 测试独立性 - -每个测试应该独立,不依赖其他测试: - -```cpp -// ✅ 好的做法 -TEST(MyTest, Test1) { - // 独立的测试代码 -} - -// ❌ 不好的做法 -TEST(MyTest, Test2) { - // 依赖 Test1 的结果 -} -``` - -### 2. 描述性命名 - -使用描述性的测试名称: - -```cpp -// ✅ 好的做法 -TEST(RangeToArcTest, ConvertsZeroToMinimumArc) - -// ❌ 不好的做法 -TEST(RangeToArcTest, Test1) -``` - -### 3. 测试多种情况 - -测试正常情况、边界情况和错误情况: - -```cpp -TEST(MyTest, NormalCase) { - // 正常情况 -} - -TEST(MyTest, BoundaryCase) { - // 边界值(0, 255, 最大值等) -} - -TEST(MyTest, ErrorCase) { - // 错误情况(无效输入等) -} -``` - -### 4. 使用参数化测试 - -对于需要测试多个输入值的情况,使用参数化测试: - -```cpp -class RangeToArcParamTest : public ::testing::TestWithParam {}; - -TEST_P(RangeToArcParamTest, ConvertsCorrectly) { - int input = GetParam(); - // 测试代码 -} - -INSTANTIATE_TEST_SUITE_P( - RangeValues, - RangeToArcParamTest, - ::testing::Values(0, 128, 255) -); -``` - -### 5. 保持测试简洁 - -测试代码应该简洁、可读: - -```cpp -// ✅ 好的做法 -TEST(MyTest, SimpleTest) { - int result = function(5); - EXPECT_EQ(result, 10); -} - -// ❌ 不好的做法 -TEST(MyTest, ComplexTest) { - // 100 行复杂的测试代码 -} -``` - -### 6. 使用适当的断言 - -选择合适的断言: - -```cpp -EXPECT_EQ(a, b); // 相等 -EXPECT_NE(a, b); // 不相等 -EXPECT_NEAR(a, b, 0.001); // 浮点数近似相等 -EXPECT_TRUE(condition); // 为真 -EXPECT_FALSE(condition); // 为假 -EXPECT_THROW(statement, ExceptionType); // 抛出异常 -``` - ---- - -## 故障排查 - -### 问题 1: 找不到 Google Test - -**错误信息**: -``` -Could not find gtest -``` - -**解决方案**: -1. CMake 会自动下载 Google Test,确保网络连接正常 -2. 如果网络有问题,可以手动安装 Google Test: - ```bash - # Ubuntu/Debian - sudo apt-get install libgtest-dev - ``` -3. 检查 CMake 版本(需要 3.15+) - ---- - -### 问题 2: 链接错误 - -**错误信息**: -``` -undefined reference to `...` -``` - -**解决方案**: -1. **检查 SDK 库是否正确找到**: - ```bash - ls -la lib/x86_64/liblinkerhand_cpp_sdk.so - ``` - -2. **检查测试是否需要链接 SDK 库**: - - 如果测试需要链接 SDK 库,在 `tests/CMakeLists.txt` 中添加: - ```cmake - target_link_libraries(test_name ${LINKER_HAND_LIB} pthread) - ``` - -3. **检查库路径**: - ```cmake - find_library(LINKER_HAND_LIB - NAMES linkerhand_cpp_sdk - PATHS ${CMAKE_CURRENT_SOURCE_DIR}/../lib/x86_64 - ) - ``` - ---- - -### 问题 3: 测试失败 - -**错误信息**: -``` -Test failed: ... -``` - -**解决方案**: -1. **查看详细输出**: - ```bash - ctest --output-on-failure - ``` - -2. **直接运行测试可执行文件**: - ```bash - ./test_Common - ``` - 这样可以查看更详细的错误信息。 - -3. **检查测试代码**: - - 验证测试逻辑是否正确 - - 检查期望值是否正确 - -4. **检查 SDK 库版本**: - - 确保使用的 SDK 库版本与测试代码匹配 - - 检查是否有 API 变更 - -5. **检查环境**: - - 确保测试环境正确配置 - - 检查依赖项是否完整 - ---- - -### 问题 4: 测试运行缓慢 - -**可能原因**: -- 测试数量多 -- 测试包含耗时操作 -- 系统负载高 - -**解决方案**: -1. **并行运行测试**: - ```bash - ctest -j4 - ``` - -2. **优化测试代码**: - - 减少不必要的操作 - - 使用 mock 对象替代真实对象 - -3. **选择性运行测试**: - ```bash - ctest -R test_Common # 只运行特定测试 - ``` - ---- - -### 问题 5: CMake 配置错误 - -**错误信息**: -``` -CMake Error: ... -``` - -**解决方案**: -1. **清理构建目录**: - ```bash - rm -rf build - mkdir build && cd build - ``` - -2. **检查 CMake 版本**: - ```bash - cmake --version # 需要 3.15+ - ``` - -3. **检查 CMakeLists.txt 语法**: - - 确保语法正确 - - 检查变量名和路径 - ---- - -## 更多信息 - -### 相关文档 - -- **详细测试文档**: [测试文档](../docs/TESTING.md)(如果存在) -- **API 参考**: [API 参考文档](../docs/API-Reference.md) -- **故障排查**: [故障排查指南](../docs/TROUBLESHOOTING.md) -- **常见问题**: [常见问题解答](../docs/FAQ.md) -- **命名规范**: [命名规范改进文档](../docs/NAMING_IMPROVEMENTS.md) - -### Google Test 文档 - -- [Google Test 官方文档](https://google.github.io/googletest/) -- [Google Test Primer](https://google.github.io/googletest/primer.html) -- [Google Test Advanced](https://google.github.io/googletest/advanced.html) - -### 测试工具 - -- **ctest**: CMake 测试运行器 -- **gtest**: Google Test 框架 -- **valgrind**: 内存检查工具(可选) -- **gcov/lcov**: 代码覆盖率工具(可选) - ---- - -## 贡献测试 - -欢迎贡献新的测试用例!在添加新测试时,请: - -1. 遵循测试最佳实践 -2. 确保测试独立且可重复 -3. 添加适当的注释和文档 -4. 运行所有测试确保没有破坏现有功能 -5. 提交 Pull Request - -如有问题,请参考 [故障排查指南](../docs/TROUBLESHOOTING.md) 或联系技术支持。 \ No newline at end of file diff --git a/tests/run_tests.sh b/tests/run_tests.sh deleted file mode 100755 index 7a905fd..0000000 --- a/tests/run_tests.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash - -# 测试运行脚本 -# 用法: ./run_tests.sh [build_dir] - -set -e - -# 获取构建目录,默认为 ../build -BUILD_DIR=${1:-../build} - -# 检查构建目录是否存在 -if [ ! -d "$BUILD_DIR" ]; then - echo "错误: 构建目录 '$BUILD_DIR' 不存在" - echo "请先运行: mkdir build && cd build && cmake .. -DBUILD_TESTING=ON && make" - exit 1 -fi - -# 进入构建目录 -cd "$BUILD_DIR" - -# 检查是否启用了测试 -if [ ! -f "CMakeCache.txt" ]; then - echo "错误: CMakeCache.txt 不存在,请先运行 cmake" - exit 1 -fi - -# 运行测试 -echo "运行所有测试..." -echo "==========================================" -ctest --output-on-failure - -echo "" -echo "==========================================" -echo "测试完成!" - diff --git a/tests/unit/test_CanFrame.cpp b/tests/unit/test_CanFrame.cpp deleted file mode 100644 index 6dd8591..0000000 --- a/tests/unit/test_CanFrame.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include "CanFrame.h" -#include - -// 测试 CANFrame 结构体 -TEST(CanFrameTest, CANFrameStructure) { - CANFrame frame; - - // 初始化测试 - frame.can_id = 0x123; - frame.can_dlc = 8; - memset(frame.data, 0, sizeof(frame.data)); - - // 验证结构体成员 - EXPECT_EQ(frame.can_id, 0x123); - EXPECT_EQ(frame.can_dlc, 8); - - // 验证数据数组大小 - EXPECT_EQ(sizeof(frame.data), 8); -} - -// 测试 CANFrame 数据设置和读取 -TEST(CanFrameTest, CANFrameData) { - CANFrame frame; - - frame.can_id = 0x456; - frame.can_dlc = 4; - - // 设置数据 - frame.data[0] = 0x01; - frame.data[1] = 0x02; - frame.data[2] = 0x03; - frame.data[3] = 0x04; - - // 验证数据 - EXPECT_EQ(frame.data[0], 0x01); - EXPECT_EQ(frame.data[1], 0x02); - EXPECT_EQ(frame.data[2], 0x03); - EXPECT_EQ(frame.data[3], 0x04); - - // 验证 can_dlc 与实际数据长度一致 - EXPECT_EQ(frame.can_dlc, 4); -} - -// 测试 CANFrame 边界值 -TEST(CanFrameTest, CANFrameBoundaries) { - CANFrame frame; - - // 测试最大 can_dlc - frame.can_dlc = 8; - for (int i = 0; i < 8; ++i) { - frame.data[i] = static_cast(i); - } - - EXPECT_EQ(frame.can_dlc, 8); - for (int i = 0; i < 8; ++i) { - EXPECT_EQ(frame.data[i], static_cast(i)); - } - - // 测试最小 can_dlc - frame.can_dlc = 0; - EXPECT_EQ(frame.can_dlc, 0); - - // 测试 can_dlc = 1 - frame.can_dlc = 1; - frame.data[0] = 0xFF; - EXPECT_EQ(frame.can_dlc, 1); - EXPECT_EQ(frame.data[0], 0xFF); -} - -// 测试 CANFrame 的 can_id 范围 -TEST(CanFrameTest, CANFrameIdRange) { - CANFrame frame; - - // 测试标准 CAN ID (11位,0-0x7FF) - frame.can_id = 0x000; - EXPECT_EQ(frame.can_id, 0x000); - - frame.can_id = 0x7FF; - EXPECT_EQ(frame.can_id, 0x7FF); - - // 测试扩展 CAN ID (29位,可以更大) - frame.can_id = 0x1FFFFFFF; - EXPECT_EQ(frame.can_id, 0x1FFFFFFF); - - // 测试常见 ID 值 - frame.can_id = 0x123; - EXPECT_EQ(frame.can_id, 0x123); -} - -// 测试 CANFrame 数据清零 -TEST(CanFrameTest, CANFrameDataZero) { - CANFrame frame; - - frame.can_id = 0x789; - frame.can_dlc = 8; - - // 设置一些数据 - memset(frame.data, 0xFF, sizeof(frame.data)); - - // 清零数据 - memset(frame.data, 0, sizeof(frame.data)); - - // 验证所有数据都是 0 - for (int i = 0; i < 8; ++i) { - EXPECT_EQ(frame.data[i], 0); - } -} - -// 测试 CANFrame 数据复制 -TEST(CanFrameTest, CANFrameDataCopy) { - CANFrame frame1, frame2; - - // 设置 frame1 - frame1.can_id = 0xABC; - frame1.can_dlc = 5; - for (int i = 0; i < 5; ++i) { - frame1.data[i] = static_cast(0x10 + i); - } - - // 复制到 frame2 - frame2.can_id = frame1.can_id; - frame2.can_dlc = frame1.can_dlc; - memcpy(frame2.data, frame1.data, frame1.can_dlc); - - // 验证复制结果 - EXPECT_EQ(frame2.can_id, frame1.can_id); - EXPECT_EQ(frame2.can_dlc, frame1.can_dlc); - for (int i = 0; i < 5; ++i) { - EXPECT_EQ(frame2.data[i], frame1.data[i]); - } -} - -// 测试 CANFrame 结构体大小 -TEST(CanFrameTest, CANFrameSize) { - CANFrame frame; - - // 验证结构体大小合理(can_id + can_dlc + data[8] + 可能的填充) - size_t expected_min_size = sizeof(uint32_t) + sizeof(uint8_t) + 8; - EXPECT_GE(sizeof(frame), expected_min_size); - - // 验证数据数组确实是 8 字节 - EXPECT_EQ(sizeof(frame.data), 8); -} - diff --git a/tests/unit/test_Common.cpp b/tests/unit/test_Common.cpp deleted file mode 100644 index 8194e2e..0000000 --- a/tests/unit/test_Common.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include "Common.h" - -// 测试 LINKER_HAND 枚举值 -TEST(CommonTest, LinkerHandEnumValues) { - // 验证枚举值是否正确定义 - EXPECT_EQ(static_cast(O6), 0); - EXPECT_EQ(static_cast(L6), 1); - EXPECT_EQ(static_cast(L7), 2); - EXPECT_EQ(static_cast(L10), 3); - EXPECT_EQ(static_cast(L20), 4); - EXPECT_EQ(static_cast(L21), 5); - EXPECT_EQ(static_cast(L25), 6); -} - -// 测试 HAND_TYPE 枚举值 -TEST(CommonTest, HandTypeEnumValues) { - EXPECT_EQ(static_cast(LEFT), 0x28); - EXPECT_EQ(static_cast(RIGHT), 0x27); - - // 验证左右手类型不同 - EXPECT_NE(LEFT, RIGHT); -} - -// 测试 COMM_TYPE 枚举值 -TEST(CommonTest, CommTypeEnumValues) { - EXPECT_EQ(static_cast(COMM_CAN_0), 0); - EXPECT_EQ(static_cast(COMM_CAN_1), 1); - EXPECT_EQ(static_cast(COMM_MODBUS), 2); - EXPECT_EQ(static_cast(COMM_ETHERCAT), 3); -} - -// 测试 Common 命名空间中的版本号 -TEST(CommonTest, CurrentHandVersion) { - EXPECT_GT(linkerhand::Common::current_hand_version, 0.0f); - EXPECT_LE(linkerhand::Common::current_hand_version, 10.0f); // 合理的版本号范围 -} - -// 测试枚举值的类型转换 -TEST(CommonTest, EnumTypeConversions) { - LINKER_HAND hand = L10; - HAND_TYPE type = RIGHT; - COMM_TYPE comm = COMM_CAN_0; - - EXPECT_EQ(hand, L10); - EXPECT_EQ(type, RIGHT); - EXPECT_EQ(comm, COMM_CAN_0); -} - -// 参数化测试:测试所有 LINKER_HAND 类型 -class LinkerHandTypeTest : public ::testing::TestWithParam {}; - -TEST_P(LinkerHandTypeTest, ValidHandTypes) { - LINKER_HAND hand = GetParam(); - // 验证是有效的枚举值 - EXPECT_GE(static_cast(hand), 0); - EXPECT_LE(static_cast(hand), 6); -} - -INSTANTIATE_TEST_SUITE_P( - AllHandTypes, - LinkerHandTypeTest, - ::testing::Values(O6, L6, L7, L10, L20, L21, L25) -); - -// 参数化测试:测试所有 COMM_TYPE 类型 -class CommTypeTest : public ::testing::TestWithParam {}; - -TEST_P(CommTypeTest, ValidCommTypes) { - COMM_TYPE comm = GetParam(); - // 验证是有效的枚举值 - EXPECT_GE(static_cast(comm), 0); - EXPECT_LE(static_cast(comm), 3); -} - -INSTANTIATE_TEST_SUITE_P( - AllCommTypes, - CommTypeTest, - ::testing::Values(COMM_CAN_0, COMM_CAN_1, COMM_MODBUS, COMM_ETHERCAT) -); - diff --git a/tests/unit/test_IHand_Utils.cpp b/tests/unit/test_IHand_Utils.cpp deleted file mode 100644 index 1b0a715..0000000 --- a/tests/unit/test_IHand_Utils.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include -#include "IHand.h" -#include -#include -#include - -// 创建一个测试用的 IHand 实现类 -class TestHand : public linkerhand::hand::IHand { -public: - void setJointPositions(const std::vector &jointAngles) override { - (void)jointAngles; - } -}; - -// 测试 getSubVector 函数(单参数版本) -TEST(IHandUtilsTest, GetSubVectorSingleArg) { - TestHand hand; - - // 测试正常情况 - std::vector vec = {0, 1, 2, 3, 4, 5}; - std::vector result = hand.getSubVector(vec); - - EXPECT_EQ(result.size(), 5); - EXPECT_EQ(result[0], 1); - EXPECT_EQ(result[1], 2); - EXPECT_EQ(result[4], 5); - - // 测试只有一个元素的情况 - std::vector vec_single = {0}; - std::vector result_single = hand.getSubVector(vec_single); - EXPECT_TRUE(result_single.empty()); - - // 测试空向量 - std::vector vec_empty = {}; - std::vector result_empty = hand.getSubVector(vec_empty); - EXPECT_TRUE(result_empty.empty()); - - // 测试两个元素的情况 - std::vector vec_two = {0, 1}; - std::vector result_two = hand.getSubVector(vec_two); - EXPECT_EQ(result_two.size(), 1); - EXPECT_EQ(result_two[0], 1); -} - -// 测试 getSubVector 函数(双参数版本) -TEST(IHandUtilsTest, GetSubVectorDoubleArg) { - TestHand hand; - - // 测试正常情况 - std::vector vec1 = {0, 1, 2, 3}; - std::vector vec2 = {0, 4, 5, 6}; - std::vector result = hand.getSubVector(vec1, vec2); - - EXPECT_EQ(result.size(), 6); // 3 + 3 - EXPECT_EQ(result[0], 1); - EXPECT_EQ(result[1], 2); - EXPECT_EQ(result[2], 3); - EXPECT_EQ(result[3], 4); - EXPECT_EQ(result[4], 5); - EXPECT_EQ(result[5], 6); - - // 测试一个向量只有一个元素 - std::vector vec_single = {0}; - std::vector vec_normal = {0, 1, 2}; - std::vector result_mixed = hand.getSubVector(vec_single, vec_normal); - EXPECT_EQ(result_mixed.size(), 2); // 0 + 2 - EXPECT_EQ(result_mixed[0], 1); - EXPECT_EQ(result_mixed[1], 2); - - // 测试两个向量都只有一个元素 - std::vector vec1_single = {0}; - std::vector vec2_single = {0}; - std::vector result_both_single = hand.getSubVector(vec1_single, vec2_single); - EXPECT_TRUE(result_both_single.empty()); - - // 测试空向量 - std::vector vec_empty = {}; - std::vector vec_normal2 = {0, 1, 2}; - std::vector result_empty = hand.getSubVector(vec_empty, vec_normal2); - EXPECT_EQ(result_empty.size(), 2); -} - -// 测试 getCurrentTime 函数 -TEST(IHandUtilsTest, GetCurrentTime) { - TestHand hand; - - // 获取时间字符串 - std::string time1 = hand.getCurrentTime(); - - // 验证时间字符串不为空 - EXPECT_FALSE(time1.empty()); - - // 验证时间字符串格式(应该包含日期和时间) - // 格式应该是 "YYYY-MM-DD HH:MM:SS.mmm" - EXPECT_GT(time1.length(), 19); // 至少包含日期和时间部分 - - // 验证包含日期分隔符 - EXPECT_NE(time1.find('-'), std::string::npos); - - // 验证包含时间分隔符 - EXPECT_NE(time1.find(':'), std::string::npos); - - // 等待一小段时间后再次获取时间 - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - std::string time2 = hand.getCurrentTime(); - - // 验证两次获取的时间不同(或至少格式相同) - EXPECT_EQ(time1.length(), time2.length()); - - // 验证时间字符串格式一致 - // 都应该是 "YYYY-MM-DD HH:MM:SS.mmm" 格式 - size_t space_pos1 = time1.find(' '); - size_t space_pos2 = time2.find(' '); - EXPECT_NE(space_pos1, std::string::npos); - EXPECT_NE(space_pos2, std::string::npos); - - // 验证日期部分格式 - std::string date1 = time1.substr(0, space_pos1); - std::string date2 = time2.substr(0, space_pos2); - EXPECT_EQ(date1.length(), 10); // "YYYY-MM-DD" - EXPECT_EQ(date2.length(), 10); - - // 验证日期部分包含两个连字符 - size_t dash_count1 = 0; - size_t dash_count2 = 0; - for (char c : date1) { - if (c == '-') dash_count1++; - } - for (char c : date2) { - if (c == '-') dash_count2++; - } - EXPECT_EQ(dash_count1, 2); - EXPECT_EQ(dash_count2, 2); -} - -// 测试 getCurrentTime 的时间递增 -TEST(IHandUtilsTest, GetCurrentTimeIncrement) { - TestHand hand; - - std::string time1 = hand.getCurrentTime(); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - std::string time2 = hand.getCurrentTime(); - - // 由于我们等待了 100ms,时间应该不同 - // 注意:由于时间格式包含毫秒,两次时间应该不同 - // 但由于时间精度问题,我们只验证格式正确 - EXPECT_FALSE(time1.empty()); - EXPECT_FALSE(time2.empty()); -} - -// 测试 getSubVector 的边界情况 -TEST(IHandUtilsTest, GetSubVectorEdgeCases) { - TestHand hand; - - // 测试大向量 - std::vector large_vec(1000, 0); - for (size_t i = 0; i < large_vec.size(); ++i) { - large_vec[i] = static_cast(i % 256); - } - std::vector result = hand.getSubVector(large_vec); - - // 验证大小:跳过第一个元素,所以应该是 999 - EXPECT_EQ(result.size(), 999); - - // 验证第一个元素:应该是原始向量的第二个元素 (1) - EXPECT_EQ(result[0], 1); - - // 修复:result[998] 对应 large_vec[999] - // large_vec[999] = 999 % 256 = 231 - EXPECT_EQ(static_cast(result[998]), 231); - - // 附加验证:确保理解正确 - // result[254] 对应 large_vec[255] = 255 - EXPECT_EQ(static_cast(result[254]), 255); -} - diff --git a/tests/unit/test_RangeToArc.cpp b/tests/unit/test_RangeToArc.cpp deleted file mode 100644 index 2e659bd..0000000 --- a/tests/unit/test_RangeToArc.cpp +++ /dev/null @@ -1,182 +0,0 @@ -#include -#include "RangeToArc.h" -#include -#include - -// 测试 is_within_range 函数 -TEST(RangeToArcTest, IsWithinRange) { - // 值在范围内 - EXPECT_DOUBLE_EQ(is_within_range(5.0, 0.0, 10.0), 5.0); - EXPECT_DOUBLE_EQ(is_within_range(0.0, 0.0, 10.0), 0.0); // 边界值 - EXPECT_DOUBLE_EQ(is_within_range(10.0, 0.0, 10.0), 10.0); // 边界值 - - // 值小于最小值 - EXPECT_DOUBLE_EQ(is_within_range(-5.0, 0.0, 10.0), 0.0); - - // 值大于最大值 - EXPECT_DOUBLE_EQ(is_within_range(15.0, 0.0, 10.0), 10.0); - - // 负值范围 - EXPECT_DOUBLE_EQ(is_within_range(-2.0, -5.0, -1.0), -2.0); - EXPECT_DOUBLE_EQ(is_within_range(-6.0, -5.0, -1.0), -5.0); - EXPECT_DOUBLE_EQ(is_within_range(0.0, -5.0, -1.0), -1.0); -} - -// 测试 scale_value 函数 -TEST(RangeToArcTest, ScaleValue) { - // 基本缩放测试 - EXPECT_NEAR(scale_value(5.0, 0.0, 10.0, 0.0, 100.0), 50.0, 0.001); - EXPECT_NEAR(scale_value(0.0, 0.0, 10.0, 0.0, 100.0), 0.0, 0.001); - EXPECT_NEAR(scale_value(10.0, 0.0, 10.0, 0.0, 100.0), 100.0, 0.001); - - // 负值范围缩放 - EXPECT_NEAR(scale_value(-2.0, -5.0, 0.0, 0.0, 100.0), 60.0, 0.001); - - // 不同范围的缩放 - EXPECT_NEAR(scale_value(128, 0, 255, 0.0, 1.57), 0.785, 0.01); -} - -// 测试 should_skip_joint 函数 -TEST(RangeToArcTest, ShouldSkipJoint) { - // 测试不同的关节类型和索引 - // 注意:这个函数的具体实现需要查看源代码 - // 这里假设一些基本行为 - bool result1 = should_skip_joint(0, 0); - bool result2 = should_skip_joint(0, 1); - // 验证函数不会崩溃 - EXPECT_TRUE(result1 == true || result1 == false); - EXPECT_TRUE(result2 == true || result2 == false); -} - -// 测试 initialize_params 函数 -TEST(RangeToArcTest, InitializeParams) { - std::vector min_limits; - std::vector max_limits; - std::vector derict; - - // 测试 L10 左手参数初始化 - bool result = initialize_params(static_cast(10), "left", min_limits, max_limits, derict); - EXPECT_TRUE(result); - EXPECT_FALSE(min_limits.empty()); - EXPECT_FALSE(max_limits.empty()); - EXPECT_FALSE(derict.empty()); - EXPECT_EQ(min_limits.size(), max_limits.size()); - EXPECT_EQ(min_limits.size(), derict.size()); - - // 验证 L10 左手应该有 10 个关节 - EXPECT_EQ(min_limits.size(), 10); - - // 验证每个关节的最小值小于等于最大值 - for (size_t i = 0; i < min_limits.size(); ++i) { - EXPECT_LE(min_limits[i], max_limits[i]); - } -} - -// 测试 range_to_arc 函数 -TEST(RangeToArcTest, RangeToArc) { - // 测试 L10 左手的转换 - std::vector hand_range = {128, 128, 128, 128, 128, 128, 128, 128, 128, 128}; - std::vector result = range_to_arc(static_cast(10), "left", hand_range); - - EXPECT_FALSE(result.empty()); - EXPECT_EQ(result.size(), hand_range.size()); - - // 验证结果在合理范围内(对于 L10 左手) - for (size_t i = 0; i < result.size(); ++i) { - // L10 左手的范围应该在定义的 min/max 之间 - EXPECT_GE(result[i], l10_l_min[i] - 0.1); // 允许小的误差 - EXPECT_LE(result[i], l10_l_max[i] + 0.1); - } -} - -// 测试 arc_to_range 函数 -TEST(RangeToArcTest, ArcToRange) { - // 测试 L10 左手的转换 - // 使用中间值进行测试 - std::vector hand_arc(10, 0.5); - std::vector result = arc_to_range(static_cast(10), "left", hand_arc); - - EXPECT_FALSE(result.empty()); - EXPECT_EQ(result.size(), hand_arc.size()); - - // 验证结果在 0-255 范围内 - for (uint8_t value : result) { - EXPECT_GE(value, 0); - EXPECT_LE(value, 255); - } -} - -// 测试 range_to_arc 和 arc_to_range 的往返转换 -TEST(RangeToArcTest, RoundTripConversion) { - // 测试往返转换的精度 - std::vector original = {0, 64, 128, 192, 255, 100, 150, 200, 50, 75}; - std::vector arc = range_to_arc(static_cast(10), "left", original); - std::vector converted_back = arc_to_range(static_cast(10), "left", arc); - - EXPECT_EQ(original.size(), converted_back.size()); - - // 由于浮点数精度和范围限制,允许一定的误差 - for (size_t i = 0; i < original.size(); ++i) { - int diff = std::abs(static_cast(original[i]) - static_cast(converted_back[i])); - EXPECT_LE(diff, 2); // 允许最多 2 的误差 - } -} - -// 测试边界值 -TEST(RangeToArcTest, BoundaryValues) { - // 测试最小值 - std::vector min_range(10, 0); - std::vector min_arc = range_to_arc(static_cast(10), "left", min_range); - EXPECT_FALSE(min_arc.empty()); - - // 测试最大值 - std::vector max_range(10, 255); - std::vector max_arc = range_to_arc(static_cast(10), "left", max_range); - EXPECT_FALSE(max_arc.empty()); - - // 测试中间值 - std::vector mid_range(10, 128); - std::vector mid_arc = range_to_arc(static_cast(10), "left", mid_range); - EXPECT_FALSE(mid_arc.empty()); -} - -// 测试不同型号的转换 -TEST(RangeToArcTest, DifferentHandTypes) { - // 只测试代码中支持的手型 - - // 测试 L7 - 支持 - std::vector l7_range = {128, 128, 128, 128, 128, 128, 128}; - std::vector l7_arc = range_to_arc(7, "left", l7_range); - EXPECT_FALSE(l7_arc.empty()); - EXPECT_EQ(l7_arc.size(), 7); - - // 测试 L10 - 支持 - std::vector l10_range = {128, 128, 128, 128, 128, 128, 128, 128, 128, 128}; - std::vector l10_arc = range_to_arc(10, "left", l10_range); - EXPECT_FALSE(l10_arc.empty()); - EXPECT_EQ(l10_arc.size(), 10); - - // 测试 L20 - 支持 - std::vector l20_range(20, 128); - std::vector l20_arc = range_to_arc(20, "left", l20_range); - EXPECT_FALSE(l20_arc.empty()); - EXPECT_EQ(l20_arc.size(), 20); - - // 测试 L21 - 支持 - std::vector l21_range(25, 128); - std::vector l21_arc = range_to_arc(21, "left", l21_range); - EXPECT_FALSE(l21_arc.empty()); - EXPECT_EQ(l21_arc.size(), 25); - - // 测试 L25 - 支持 - std::vector l25_range(25, 128); - std::vector l25_arc = range_to_arc(25, "left", l25_range); - EXPECT_FALSE(l25_arc.empty()); - EXPECT_EQ(l25_arc.size(), 25); - - // 注意:不要测试不支持的手型,如 L6 (6) - // std::vector l6_range = {128, 128, 128, 128, 128, 128}; - // std::vector l6_arc = range_to_arc(6, "left", l6_range); - // EXPECT_FALSE(l6_arc.empty()); // 这会失败! -} - diff --git a/third_party/PCAN_Basic/Include/PCANBasic.h b/third_party/PCAN_Basic/Include/PCANBasic.h index b72f994..0157d1e 100644 --- a/third_party/PCAN_Basic/Include/PCANBasic.h +++ b/third_party/PCAN_Basic/Include/PCANBasic.h @@ -1,588 +1,588 @@ -// PCANBasic.h -// -// ~~~~~~~~~~~~ -// -// PCAN-Basic API -// -// ~~~~~~~~~~~~ -// -// ------------------------------------------------------------------ -// Author : Keneth Wagner -// Last change: 2022-07-06 -// -// Language: ANSI-C -// ------------------------------------------------------------------ -// -// Copyright (C) 1999-2022 PEAK-System Technik GmbH, Darmstadt -// more Info at http://www.peak-system.com -// -#ifndef __PCANBASICH__ -#define __PCANBASICH__ - -//////////////////////////////////////////////////////////// -// Value definitions -//////////////////////////////////////////////////////////// - -// Currently defined and supported PCAN channels -// -#define PCAN_NONEBUS 0x00U // Undefined/default value for a PCAN bus - -#define PCAN_ISABUS1 0x21U // PCAN-ISA interface, channel 1 -#define PCAN_ISABUS2 0x22U // PCAN-ISA interface, channel 2 -#define PCAN_ISABUS3 0x23U // PCAN-ISA interface, channel 3 -#define PCAN_ISABUS4 0x24U // PCAN-ISA interface, channel 4 -#define PCAN_ISABUS5 0x25U // PCAN-ISA interface, channel 5 -#define PCAN_ISABUS6 0x26U // PCAN-ISA interface, channel 6 -#define PCAN_ISABUS7 0x27U // PCAN-ISA interface, channel 7 -#define PCAN_ISABUS8 0x28U // PCAN-ISA interface, channel 8 - -#define PCAN_DNGBUS1 0x31U // PCAN-Dongle/LPT interface, channel 1 - -#define PCAN_PCIBUS1 0x41U // PCAN-PCI interface, channel 1 -#define PCAN_PCIBUS2 0x42U // PCAN-PCI interface, channel 2 -#define PCAN_PCIBUS3 0x43U // PCAN-PCI interface, channel 3 -#define PCAN_PCIBUS4 0x44U // PCAN-PCI interface, channel 4 -#define PCAN_PCIBUS5 0x45U // PCAN-PCI interface, channel 5 -#define PCAN_PCIBUS6 0x46U // PCAN-PCI interface, channel 6 -#define PCAN_PCIBUS7 0x47U // PCAN-PCI interface, channel 7 -#define PCAN_PCIBUS8 0x48U // PCAN-PCI interface, channel 8 -#define PCAN_PCIBUS9 0x409U // PCAN-PCI interface, channel 9 -#define PCAN_PCIBUS10 0x40AU // PCAN-PCI interface, channel 10 -#define PCAN_PCIBUS11 0x40BU // PCAN-PCI interface, channel 11 -#define PCAN_PCIBUS12 0x40CU // PCAN-PCI interface, channel 12 -#define PCAN_PCIBUS13 0x40DU // PCAN-PCI interface, channel 13 -#define PCAN_PCIBUS14 0x40EU // PCAN-PCI interface, channel 14 -#define PCAN_PCIBUS15 0x40FU // PCAN-PCI interface, channel 15 -#define PCAN_PCIBUS16 0x410U // PCAN-PCI interface, channel 16 - -#define PCAN_USBBUS1 0x51U // PCAN-USB interface, channel 1 -#define PCAN_USBBUS2 0x52U // PCAN-USB interface, channel 2 -#define PCAN_USBBUS3 0x53U // PCAN-USB interface, channel 3 -#define PCAN_USBBUS4 0x54U // PCAN-USB interface, channel 4 -#define PCAN_USBBUS5 0x55U // PCAN-USB interface, channel 5 -#define PCAN_USBBUS6 0x56U // PCAN-USB interface, channel 6 -#define PCAN_USBBUS7 0x57U // PCAN-USB interface, channel 7 -#define PCAN_USBBUS8 0x58U // PCAN-USB interface, channel 8 -#define PCAN_USBBUS9 0x509U // PCAN-USB interface, channel 9 -#define PCAN_USBBUS10 0x50AU // PCAN-USB interface, channel 10 -#define PCAN_USBBUS11 0x50BU // PCAN-USB interface, channel 11 -#define PCAN_USBBUS12 0x50CU // PCAN-USB interface, channel 12 -#define PCAN_USBBUS13 0x50DU // PCAN-USB interface, channel 13 -#define PCAN_USBBUS14 0x50EU // PCAN-USB interface, channel 14 -#define PCAN_USBBUS15 0x50FU // PCAN-USB interface, channel 15 -#define PCAN_USBBUS16 0x510U // PCAN-USB interface, channel 16 - -#define PCAN_PCCBUS1 0x61U // PCAN-PC Card interface, channel 1 -#define PCAN_PCCBUS2 0x62U // PCAN-PC Card interface, channel 2 - -#define PCAN_LANBUS1 0x801U // PCAN-LAN interface, channel 1 -#define PCAN_LANBUS2 0x802U // PCAN-LAN interface, channel 2 -#define PCAN_LANBUS3 0x803U // PCAN-LAN interface, channel 3 -#define PCAN_LANBUS4 0x804U // PCAN-LAN interface, channel 4 -#define PCAN_LANBUS5 0x805U // PCAN-LAN interface, channel 5 -#define PCAN_LANBUS6 0x806U // PCAN-LAN interface, channel 6 -#define PCAN_LANBUS7 0x807U // PCAN-LAN interface, channel 7 -#define PCAN_LANBUS8 0x808U // PCAN-LAN interface, channel 8 -#define PCAN_LANBUS9 0x809U // PCAN-LAN interface, channel 9 -#define PCAN_LANBUS10 0x80AU // PCAN-LAN interface, channel 10 -#define PCAN_LANBUS11 0x80BU // PCAN-LAN interface, channel 11 -#define PCAN_LANBUS12 0x80CU // PCAN-LAN interface, channel 12 -#define PCAN_LANBUS13 0x80DU // PCAN-LAN interface, channel 13 -#define PCAN_LANBUS14 0x80EU // PCAN-LAN interface, channel 14 -#define PCAN_LANBUS15 0x80FU // PCAN-LAN interface, channel 15 -#define PCAN_LANBUS16 0x810U // PCAN-LAN interface, channel 16 - -// Represent the PCAN error and status codes -// -#define PCAN_ERROR_OK 0x00000U // No error -#define PCAN_ERROR_XMTFULL 0x00001U // Transmit buffer in CAN controller is full -#define PCAN_ERROR_OVERRUN 0x00002U // CAN controller was read too late -#define PCAN_ERROR_BUSLIGHT 0x00004U // Bus error: an error counter reached the 'light' limit -#define PCAN_ERROR_BUSHEAVY 0x00008U // Bus error: an error counter reached the 'heavy' limit -#define PCAN_ERROR_BUSWARNING PCAN_ERROR_BUSHEAVY // Bus error: an error counter reached the 'warning' limit -#define PCAN_ERROR_BUSPASSIVE 0x40000U // Bus error: the CAN controller is error passive -#define PCAN_ERROR_BUSOFF 0x00010U // Bus error: the CAN controller is in bus-off state -#define PCAN_ERROR_ANYBUSERR (PCAN_ERROR_BUSWARNING | PCAN_ERROR_BUSLIGHT | PCAN_ERROR_BUSHEAVY | PCAN_ERROR_BUSOFF | PCAN_ERROR_BUSPASSIVE) // Mask for all bus errors -#define PCAN_ERROR_QRCVEMPTY 0x00020U // Receive queue is empty -#define PCAN_ERROR_QOVERRUN 0x00040U // Receive queue was read too late -#define PCAN_ERROR_QXMTFULL 0x00080U // Transmit queue is full -#define PCAN_ERROR_REGTEST 0x00100U // Test of the CAN controller hardware registers failed (no hardware found) -#define PCAN_ERROR_NODRIVER 0x00200U // Driver not loaded -#define PCAN_ERROR_HWINUSE 0x00400U // Hardware already in use by a Net -#define PCAN_ERROR_NETINUSE 0x00800U // A Client is already connected to the Net -#define PCAN_ERROR_ILLHW 0x01400U // Hardware handle is invalid -#define PCAN_ERROR_ILLNET 0x01800U // Net handle is invalid -#define PCAN_ERROR_ILLCLIENT 0x01C00U // Client handle is invalid -#define PCAN_ERROR_ILLHANDLE (PCAN_ERROR_ILLHW | PCAN_ERROR_ILLNET | PCAN_ERROR_ILLCLIENT) // Mask for all handle errors -#define PCAN_ERROR_RESOURCE 0x02000U // Resource (FIFO, Client, timeout) cannot be created -#define PCAN_ERROR_ILLPARAMTYPE 0x04000U // Invalid parameter -#define PCAN_ERROR_ILLPARAMVAL 0x08000U // Invalid parameter value -#define PCAN_ERROR_UNKNOWN 0x10000U // Unknown error -#define PCAN_ERROR_ILLDATA 0x20000U // Invalid data, function, or action -#define PCAN_ERROR_ILLMODE 0x80000U // Driver object state is wrong for the attempted operation -#define PCAN_ERROR_CAUTION 0x2000000U // An operation was successfully carried out, however, irregularities were registered -#define PCAN_ERROR_INITIALIZE 0x4000000U // Channel is not initialized [Value was changed from 0x40000 to 0x4000000] -#define PCAN_ERROR_ILLOPERATION 0x8000000U // Invalid operation [Value was changed from 0x80000 to 0x8000000] - -// PCAN devices -// -#define PCAN_NONE 0x00U // Undefined, unknown or not selected PCAN device value -#define PCAN_PEAKCAN 0x01U // PCAN Non-PnP devices. NOT USED WITHIN PCAN-Basic API -#define PCAN_ISA 0x02U // PCAN-ISA, PCAN-PC/104, and PCAN-PC/104-Plus -#define PCAN_DNG 0x03U // PCAN-Dongle -#define PCAN_PCI 0x04U // PCAN-PCI, PCAN-cPCI, PCAN-miniPCI, and PCAN-PCI Express -#define PCAN_USB 0x05U // PCAN-USB and PCAN-USB Pro -#define PCAN_PCC 0x06U // PCAN-PC Card -#define PCAN_VIRTUAL 0x07U // PCAN Virtual hardware. NOT USED WITHIN PCAN-Basic API -#define PCAN_LAN 0x08U // PCAN Gateway devices - -// PCAN parameters -// -#define PCAN_DEVICE_ID 0x01U // Device identifier parameter -#define PCAN_5VOLTS_POWER 0x02U // 5-Volt power parameter -#define PCAN_RECEIVE_EVENT 0x03U // PCAN receive event handler parameter -#define PCAN_MESSAGE_FILTER 0x04U // PCAN message filter parameter -#define PCAN_API_VERSION 0x05U // PCAN-Basic API version parameter -#define PCAN_CHANNEL_VERSION 0x06U // PCAN device channel version parameter -#define PCAN_BUSOFF_AUTORESET 0x07U // PCAN Reset-On-Busoff parameter -#define PCAN_LISTEN_ONLY 0x08U // PCAN Listen-Only parameter -#define PCAN_LOG_LOCATION 0x09U // Directory path for log files -#define PCAN_LOG_STATUS 0x0AU // Debug-Log activation status -#define PCAN_LOG_CONFIGURE 0x0BU // Configuration of the debugged information (LOG_FUNCTION_***) -#define PCAN_LOG_TEXT 0x0CU // Custom insertion of text into the log file -#define PCAN_CHANNEL_CONDITION 0x0DU // Availability status of a PCAN-Channel -#define PCAN_HARDWARE_NAME 0x0EU // PCAN hardware name parameter -#define PCAN_RECEIVE_STATUS 0x0FU // Message reception status of a PCAN-Channel -#define PCAN_CONTROLLER_NUMBER 0x10U // CAN-Controller number of a PCAN-Channel -#define PCAN_TRACE_LOCATION 0x11U // Directory path for PCAN trace files -#define PCAN_TRACE_STATUS 0x12U // CAN tracing activation status -#define PCAN_TRACE_SIZE 0x13U // Configuration of the maximum file size of a CAN trace -#define PCAN_TRACE_CONFIGURE 0x14U // Configuration of the trace file storing mode (TRACE_FILE_***) -#define PCAN_CHANNEL_IDENTIFYING 0x15U // Physical identification of a USB based PCAN-Channel by blinking its associated LED -#define PCAN_CHANNEL_FEATURES 0x16U // Capabilities of a PCAN device (FEATURE_***) -#define PCAN_BITRATE_ADAPTING 0x17U // Using of an existing bit rate (PCAN-View connected to a channel) -#define PCAN_BITRATE_INFO 0x18U // Configured bit rate as Btr0Btr1 value -#define PCAN_BITRATE_INFO_FD 0x19U // Configured bit rate as TPCANBitrateFD string -#define PCAN_BUSSPEED_NOMINAL 0x1AU // Configured nominal CAN Bus speed as Bits per seconds -#define PCAN_BUSSPEED_DATA 0x1BU // Configured CAN data speed as Bits per seconds -#define PCAN_IP_ADDRESS 0x1CU // Remote address of a LAN channel as string in IPv4 format -#define PCAN_LAN_SERVICE_STATUS 0x1DU // Status of the Virtual PCAN-Gateway Service -#define PCAN_ALLOW_STATUS_FRAMES 0x1EU // Status messages reception status within a PCAN-Channel -#define PCAN_ALLOW_RTR_FRAMES 0x1FU // RTR messages reception status within a PCAN-Channel -#define PCAN_ALLOW_ERROR_FRAMES 0x20U // Error messages reception status within a PCAN-Channel -#define PCAN_INTERFRAME_DELAY 0x21U // Delay, in microseconds, between sending frames -#define PCAN_ACCEPTANCE_FILTER_11BIT 0x22U // Filter over code and mask patterns for 11-Bit messages -#define PCAN_ACCEPTANCE_FILTER_29BIT 0x23U // Filter over code and mask patterns for 29-Bit messages -#define PCAN_IO_DIGITAL_CONFIGURATION 0x24U // Output mode of 32 digital I/O pin of a PCAN-USB Chip. 1: Output-Active 0 : Output Inactive -#define PCAN_IO_DIGITAL_VALUE 0x25U // Value assigned to a 32 digital I/O pins of a PCAN-USB Chip -#define PCAN_IO_DIGITAL_SET 0x26U // Value assigned to a 32 digital I/O pins of a PCAN-USB Chip - Multiple digital I/O pins to 1 = High -#define PCAN_IO_DIGITAL_CLEAR 0x27U // Clear multiple digital I/O pins to 0 -#define PCAN_IO_ANALOG_VALUE 0x28U // Get value of a single analog input pin -#define PCAN_FIRMWARE_VERSION 0x29U // Get the version of the firmware used by the device associated with a PCAN-Channel -#define PCAN_ATTACHED_CHANNELS_COUNT 0x2AU // Get the amount of PCAN channels attached to a system -#define PCAN_ATTACHED_CHANNELS 0x2BU // Get information about PCAN channels attached to a system -#define PCAN_ALLOW_ECHO_FRAMES 0x2CU // Echo messages reception status within a PCAN-Channel -#define PCAN_DEVICE_PART_NUMBER 0x2DU // Get the part number associated to a device - -// DEPRECATED parameters -// -#define PCAN_DEVICE_NUMBER PCAN_DEVICE_ID // Deprecated parameter. Use PCAN_DEVICE_ID instead - -// PCAN parameter values -// -#define PCAN_PARAMETER_OFF 0x00U // The PCAN parameter is not set (inactive) -#define PCAN_PARAMETER_ON 0x01U // The PCAN parameter is set (active) -#define PCAN_FILTER_CLOSE 0x00U // The PCAN filter is closed. No messages will be received -#define PCAN_FILTER_OPEN 0x01U // The PCAN filter is fully opened. All messages will be received -#define PCAN_FILTER_CUSTOM 0x02U // The PCAN filter is custom configured. Only registered messages will be received -#define PCAN_CHANNEL_UNAVAILABLE 0x00U // The PCAN-Channel handle is illegal, or its associated hardware is not available -#define PCAN_CHANNEL_AVAILABLE 0x01U // The PCAN-Channel handle is available to be connected (PnP Hardware: it means furthermore that the hardware is plugged-in) -#define PCAN_CHANNEL_OCCUPIED 0x02U // The PCAN-Channel handle is valid, and is already being used -#define PCAN_CHANNEL_PCANVIEW (PCAN_CHANNEL_AVAILABLE | PCAN_CHANNEL_OCCUPIED) // The PCAN-Channel handle is already being used by a PCAN-View application, but is available to connect - -#define LOG_FUNCTION_DEFAULT 0x00U // Logs system exceptions / errors -#define LOG_FUNCTION_ENTRY 0x01U // Logs the entries to the PCAN-Basic API functions -#define LOG_FUNCTION_PARAMETERS 0x02U // Logs the parameters passed to the PCAN-Basic API functions -#define LOG_FUNCTION_LEAVE 0x04U // Logs the exits from the PCAN-Basic API functions -#define LOG_FUNCTION_WRITE 0x08U // Logs the CAN messages passed to the CAN_Write function -#define LOG_FUNCTION_READ 0x10U // Logs the CAN messages received within the CAN_Read function -#define LOG_FUNCTION_ALL 0xFFFFU // Logs all possible information within the PCAN-Basic API functions - -#define TRACE_FILE_SINGLE 0x00U // A single file is written until it size reaches PAN_TRACE_SIZE -#define TRACE_FILE_SEGMENTED 0x01U // Traced data is distributed in several files with size PAN_TRACE_SIZE -#define TRACE_FILE_DATE 0x02U // Includes the date into the name of the trace file -#define TRACE_FILE_TIME 0x04U // Includes the start time into the name of the trace file -#define TRACE_FILE_OVERWRITE 0x80U // Causes the overwriting of available traces (same name) - -#define FEATURE_FD_CAPABLE 0x01U // Device supports flexible data-rate (CAN-FD) -#define FEATURE_DELAY_CAPABLE 0x02U // Device supports a delay between sending frames (FPGA based USB devices) -#define FEATURE_IO_CAPABLE 0x04U // Device supports I/O functionality for electronic circuits (USB-Chip devices) - -#define SERVICE_STATUS_STOPPED 0x01U // The service is not running -#define SERVICE_STATUS_RUNNING 0x04U // The service is running - -// Other constants -// -#define MAX_LENGTH_HARDWARE_NAME 33 // Maximum length of the name of a device: 32 characters + terminator -#define MAX_LENGTH_VERSION_STRING 256 // Maximum length of a version string: 255 characters + terminator - -// PCAN message types -// -#define PCAN_MESSAGE_STANDARD 0x00U // The PCAN message is a CAN Standard Frame (11-bit identifier) -#define PCAN_MESSAGE_RTR 0x01U // The PCAN message is a CAN Remote-Transfer-Request Frame -#define PCAN_MESSAGE_EXTENDED 0x02U // The PCAN message is a CAN Extended Frame (29-bit identifier) -#define PCAN_MESSAGE_FD 0x04U // The PCAN message represents a FD frame in terms of CiA Specs -#define PCAN_MESSAGE_BRS 0x08U // The PCAN message represents a FD bit rate switch (CAN data at a higher bit rate) -#define PCAN_MESSAGE_ESI 0x10U // The PCAN message represents a FD error state indicator(CAN FD transmitter was error active) -#define PCAN_MESSAGE_ECHO 0x20U // The PCAN message represents an echo CAN Frame -#define PCAN_MESSAGE_ERRFRAME 0x40U // The PCAN message represents an error frame -#define PCAN_MESSAGE_STATUS 0x80U // The PCAN message represents a PCAN status message - -// LookUp Parameters -// -#define LOOKUP_DEVICE_TYPE __T("devicetype") // Lookup channel by Device type (see PCAN devices e.g. PCAN_USB) -#define LOOKUP_DEVICE_ID __T("deviceid") // Lookup channel by device id -#define LOOKUP_CONTROLLER_NUMBER __T("controllernumber") // Lookup channel by CAN controller 0-based index -#define LOOKUP_IP_ADDRESS __T("ipaddress") // Lookup channel by IP address (LAN channels only) - -// Frame Type / Initialization Mode -// -#define PCAN_MODE_STANDARD PCAN_MESSAGE_STANDARD -#define PCAN_MODE_EXTENDED PCAN_MESSAGE_EXTENDED - -// Baud rate codes = BTR0/BTR1 register values for the CAN controller. -// You can define your own Baud rate with the BTROBTR1 register. -// Take a look at www.peak-system.com for our free software "BAUDTOOL" -// to calculate the BTROBTR1 register for every bit rate and sample point. -// -#define PCAN_BAUD_1M 0x0014U // 1 MBit/s -#define PCAN_BAUD_800K 0x0016U // 800 kBit/s -#define PCAN_BAUD_500K 0x001CU // 500 kBit/s -#define PCAN_BAUD_250K 0x011CU // 250 kBit/s -#define PCAN_BAUD_125K 0x031CU // 125 kBit/s -#define PCAN_BAUD_100K 0x432FU // 100 kBit/s -#define PCAN_BAUD_95K 0xC34EU // 95,238 kBit/s -#define PCAN_BAUD_83K 0x852BU // 83,333 kBit/s -#define PCAN_BAUD_50K 0x472FU // 50 kBit/s -#define PCAN_BAUD_47K 0x1414U // 47,619 kBit/s -#define PCAN_BAUD_33K 0x8B2FU // 33,333 kBit/s -#define PCAN_BAUD_20K 0x532FU // 20 kBit/s -#define PCAN_BAUD_10K 0x672FU // 10 kBit/s -#define PCAN_BAUD_5K 0x7F7FU // 5 kBit/s - -// Represents the configuration for a CAN bit rate -// Note: -// * Each parameter and its value must be separated with a '='. -// * Each pair of parameter/value must be separated using ','. -// -// Example: -// f_clock=80000000,nom_brp=10,nom_tseg1=5,nom_tseg2=2,nom_sjw=1,data_brp=4,data_tseg1=7,data_tseg2=2,data_sjw=1 -// -#define PCAN_BR_CLOCK __T("f_clock") -#define PCAN_BR_CLOCK_MHZ __T("f_clock_mhz") -#define PCAN_BR_NOM_BRP __T("nom_brp") -#define PCAN_BR_NOM_TSEG1 __T("nom_tseg1") -#define PCAN_BR_NOM_TSEG2 __T("nom_tseg2") -#define PCAN_BR_NOM_SJW __T("nom_sjw") -#define PCAN_BR_NOM_SAMPLE __T("nom_sam") -#define PCAN_BR_DATA_BRP __T("data_brp") -#define PCAN_BR_DATA_TSEG1 __T("data_tseg1") -#define PCAN_BR_DATA_TSEG2 __T("data_tseg2") -#define PCAN_BR_DATA_SJW __T("data_sjw") -#define PCAN_BR_DATA_SAMPLE __T("data_ssp_offset") - -// Type of PCAN (Non-PnP) hardware -// -#define PCAN_TYPE_ISA 0x01U // PCAN-ISA 82C200 -#define PCAN_TYPE_ISA_SJA 0x09U // PCAN-ISA SJA1000 -#define PCAN_TYPE_ISA_PHYTEC 0x04U // PHYTEC ISA -#define PCAN_TYPE_DNG 0x02U // PCAN-Dongle 82C200 -#define PCAN_TYPE_DNG_EPP 0x03U // PCAN-Dongle EPP 82C200 -#define PCAN_TYPE_DNG_SJA 0x05U // PCAN-Dongle SJA1000 -#define PCAN_TYPE_DNG_SJA_EPP 0x06U // PCAN-Dongle EPP SJA1000 - -//////////////////////////////////////////////////////////// -// Type definitions -//////////////////////////////////////////////////////////// - -#define TPCANHandle WORD // Represents a PCAN hardware channel handle -#define TPCANStatus DWORD // Represents a PCAN status/error code -#define TPCANParameter BYTE // Represents a PCAN parameter to be read or set -#define TPCANDevice BYTE // Represents a PCAN device -#define TPCANMessageType BYTE // Represents the type of a PCAN message -#define TPCANType BYTE // Represents the type of PCAN hardware to be initialized -#define TPCANMode BYTE // Represents a PCAN filter mode -#define TPCANBaudrate WORD // Represents a PCAN Baud rate register value -#define TPCANBitrateFD LPSTR // Represents a PCAN-FD bit rate string -#define TPCANTimestampFD UINT64 // Represents a timestamp of a received PCAN FD message - -//////////////////////////////////////////////////////////// -// Structure definitions -//////////////////////////////////////////////////////////// - -#include -#include - -// Represents a PCAN message -// -typedef struct tagTPCANMsg -{ - DWORD ID; // 11/29-bit message identifier - TPCANMessageType MSGTYPE; // Type of the message - BYTE LEN; // Data Length Code of the message (0..8) - BYTE DATA[8]; // Data of the message (DATA[0]..DATA[7]) -} TPCANMsg; - -// Represents a timestamp of a received PCAN message -// Total Microseconds = micros + 1000 * millis + 0x100000000 * 1000 * millis_overflow -// -typedef struct tagTPCANTimestamp -{ - DWORD millis; // Base-value: milliseconds: 0.. 2^32-1 - WORD millis_overflow; // Roll-arounds of millis - WORD micros; // Microseconds: 0..999 -} TPCANTimestamp; - -// Represents a PCAN message from a FD capable hardware -// -typedef struct tagTPCANMsgFD -{ - DWORD ID; // 11/29-bit message identifier - TPCANMessageType MSGTYPE; // Type of the message - BYTE DLC; // Data Length Code of the message (0..15) - BYTE DATA[64]; // Data of the message (DATA[0]..DATA[63]) -} TPCANMsgFD; - -// Describes an available PCAN channel -// -typedef struct tagTPCANChannelInformation -{ - TPCANHandle channel_handle; // PCAN channel handle - TPCANDevice device_type; // Kind of PCAN device - BYTE controller_number; // CAN-Controller number - DWORD device_features; // Device capabilities flag (see FEATURE_*) - char device_name[MAX_LENGTH_HARDWARE_NAME]; // Device name - DWORD device_id; // Device number - DWORD channel_condition; // Availability status of a PCAN-Channel -}TPCANChannelInformation; - -#ifdef __cplusplus -extern "C" { -#define _DEF_ARG =0 -#else -#define _DEF_ARG -#endif - -//////////////////////////////////////////////////////////// -// PCAN-Basic API function declarations -//////////////////////////////////////////////////////////// - - -/// -/// Initializes a PCAN Channel -/// -/// "The handle of a PCAN Channel" -/// "The speed for the communication (BTR0BTR1 code)" -/// "Non-PnP: The type of hardware and operation mode" -/// "Non-PnP: The I/O address for the parallel port" -/// "Non-PnP: Interrupt number of the parallel port" -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_Initialize( - TPCANHandle Channel, - TPCANBaudrate Btr0Btr1, - TPCANType HwType _DEF_ARG, - DWORD IOPort _DEF_ARG, - WORD Interrupt _DEF_ARG); - - -/// -/// Initializes a FD capable PCAN Channel -/// -/// "The handle of a FD capable PCAN Channel" -/// "The speed for the communication (FD bit rate string)" -/// See PCAN_BR_* values -/// * Parameter and values must be separated by '=' -/// * Couples of Parameter/value must be separated by ',' -/// * Following Parameter must be filled out: f_clock, data_brp, data_sjw, data_tseg1, data_tseg2, -/// nom_brp, nom_sjw, nom_tseg1, nom_tseg2. -/// * Following Parameters are optional (not used yet): data_ssp_offset, nom_sam -/// -/// f_clock=80000000,nom_brp=10,nom_tseg1=5,nom_tseg2=2,nom_sjw=1,data_brp=4,data_tseg1=7,data_tseg2=2,data_sjw=1 -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_InitializeFD( - TPCANHandle Channel, - TPCANBitrateFD BitrateFD); - - -/// -/// Uninitializes one or all PCAN Channels initialized by CAN_Initialize -/// -/// Giving the TPCANHandle value "PCAN_NONEBUS", -/// uninitialize all initialized channels -/// "The handle of a PCAN Channel" -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_Uninitialize( - TPCANHandle Channel); - - -/// -/// Resets the receive and transmit queues of the PCAN Channel -/// -/// -/// A reset of the CAN controller is not performed. -/// -/// "The handle of a PCAN Channel" -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_Reset( - TPCANHandle Channel); - - -/// -/// Gets the current status of a PCAN Channel -/// -/// "The handle of a PCAN Channel" -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_GetStatus( - TPCANHandle Channel); - - -/// -/// Reads a CAN message from the receive queue of a PCAN Channel -/// -/// "The handle of a PCAN Channel" -/// "A TPCANMsg structure buffer to store the CAN message" -/// "A TPCANTimestamp structure buffer to get -/// the reception time of the message. If this value is not desired, this parameter -/// should be passed as NULL" -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_Read( - TPCANHandle Channel, - TPCANMsg* MessageBuffer, - TPCANTimestamp* TimestampBuffer); - - -/// -/// Reads a CAN message from the receive queue of a FD capable PCAN Channel -/// -/// "The handle of a FD capable PCAN Channel" -/// "A TPCANMsgFD structure buffer to store the CAN message" -/// "A TPCANTimestampFD buffer to get -/// the reception time of the message. If this value is not desired, this parameter -/// should be passed as NULL" -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_ReadFD( - TPCANHandle Channel, - TPCANMsgFD* MessageBuffer, - TPCANTimestampFD *TimestampBuffer); - - -/// -/// Transmits a CAN message -/// -/// "The handle of a PCAN Channel" -/// "A TPCANMsg buffer with the message to be sent" -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_Write( - TPCANHandle Channel, - TPCANMsg* MessageBuffer); - - -/// -/// Transmits a CAN message over a FD capable PCAN Channel -/// -/// "The handle of a FD capable PCAN Channel" -/// "A TPCANMsgFD buffer with the message to be sent" -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_WriteFD( - TPCANHandle Channel, - TPCANMsgFD* MessageBuffer); - - -/// -/// Configures the reception filter. -/// -/// The message filter will be expanded with every call to -/// this function. If it is desired to reset the filter, please use -/// the CAN_SetValue function -/// "The handle of a PCAN Channel" -/// "The lowest CAN ID to be received" -/// "The highest CAN ID to be received" -/// "Message type, Standard (11-bit identifier) or -/// Extended (29-bit identifier)" -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_FilterMessages( - TPCANHandle Channel, - DWORD FromID, - DWORD ToID, - TPCANMode Mode); - - -/// -/// Retrieves a PCAN Channel value -/// -/// Parameters can be present or not according with the kind -/// of Hardware (PCAN Channel) being used. If a parameter is not available, -/// a PCAN_ERROR_ILLPARAMTYPE error will be returned -/// "The handle of a PCAN Channel" -/// "The TPCANParameter parameter to get" -/// "Buffer for the parameter value" -/// "Size in bytes of the buffer" -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_GetValue( - TPCANHandle Channel, - TPCANParameter Parameter, - void* Buffer, - DWORD BufferLength); - - -/// -/// Configures or sets a PCAN Channel value -/// -/// Parameters can be present or not according with the kind -/// of Hardware (PCAN Channel) being used. If a parameter is not available, -/// a PCAN_ERROR_ILLPARAMTYPE error will be returned -/// "The handle of a PCAN Channel" -/// "The TPCANParameter parameter to set" -/// "Buffer with the value to be set" -/// "Size in bytes of the buffer" -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_SetValue( - TPCANHandle Channel, - TPCANParameter Parameter, - void* Buffer, - DWORD BufferLength); - - -/// -/// Returns a descriptive text of a given TPCANStatus error -/// code, in any desired language -/// -/// The current languages available for translation are: -/// Neutral (0x00), German (0x07), English (0x09), Spanish (0x0A), -/// Italian (0x10) and French (0x0C) -/// "A TPCANStatus error code" -/// "Indicates a 'Primary language ID'" -/// "Buffer for a null terminated char array" -/// "A TPCANStatus error code" -TPCANStatus __stdcall CAN_GetErrorText( - TPCANStatus Error, - WORD Language, - LPSTR Buffer); - -/// -/// Finds a PCAN-Basic channel that matches with the given parameters -/// -/// A comma separated string contained pairs of -/// parameter-name/value to be matched within a PCAN-Basic channel -/// Buffer for returning the PCAN-Basic channel, -/// when found -/// A TPCANStatus error code -TPCANStatus __stdcall CAN_LookUpChannel( - LPSTR Parameters, - TPCANHandle* FoundChannel); - -#ifdef __cplusplus -} -#endif - +// PCANBasic.h +// +// ~~~~~~~~~~~~ +// +// PCAN-Basic API +// +// ~~~~~~~~~~~~ +// +// ------------------------------------------------------------------ +// Author : Keneth Wagner +// Last change: 2022-07-06 +// +// Language: ANSI-C +// ------------------------------------------------------------------ +// +// Copyright (C) 1999-2022 PEAK-System Technik GmbH, Darmstadt +// more Info at http://www.peak-system.com +// +#ifndef __PCANBASICH__ +#define __PCANBASICH__ + +//////////////////////////////////////////////////////////// +// Value definitions +//////////////////////////////////////////////////////////// + +// Currently defined and supported PCAN channels +// +#define PCAN_NONEBUS 0x00U // Undefined/default value for a PCAN bus + +#define PCAN_ISABUS1 0x21U // PCAN-ISA interface, channel 1 +#define PCAN_ISABUS2 0x22U // PCAN-ISA interface, channel 2 +#define PCAN_ISABUS3 0x23U // PCAN-ISA interface, channel 3 +#define PCAN_ISABUS4 0x24U // PCAN-ISA interface, channel 4 +#define PCAN_ISABUS5 0x25U // PCAN-ISA interface, channel 5 +#define PCAN_ISABUS6 0x26U // PCAN-ISA interface, channel 6 +#define PCAN_ISABUS7 0x27U // PCAN-ISA interface, channel 7 +#define PCAN_ISABUS8 0x28U // PCAN-ISA interface, channel 8 + +#define PCAN_DNGBUS1 0x31U // PCAN-Dongle/LPT interface, channel 1 + +#define PCAN_PCIBUS1 0x41U // PCAN-PCI interface, channel 1 +#define PCAN_PCIBUS2 0x42U // PCAN-PCI interface, channel 2 +#define PCAN_PCIBUS3 0x43U // PCAN-PCI interface, channel 3 +#define PCAN_PCIBUS4 0x44U // PCAN-PCI interface, channel 4 +#define PCAN_PCIBUS5 0x45U // PCAN-PCI interface, channel 5 +#define PCAN_PCIBUS6 0x46U // PCAN-PCI interface, channel 6 +#define PCAN_PCIBUS7 0x47U // PCAN-PCI interface, channel 7 +#define PCAN_PCIBUS8 0x48U // PCAN-PCI interface, channel 8 +#define PCAN_PCIBUS9 0x409U // PCAN-PCI interface, channel 9 +#define PCAN_PCIBUS10 0x40AU // PCAN-PCI interface, channel 10 +#define PCAN_PCIBUS11 0x40BU // PCAN-PCI interface, channel 11 +#define PCAN_PCIBUS12 0x40CU // PCAN-PCI interface, channel 12 +#define PCAN_PCIBUS13 0x40DU // PCAN-PCI interface, channel 13 +#define PCAN_PCIBUS14 0x40EU // PCAN-PCI interface, channel 14 +#define PCAN_PCIBUS15 0x40FU // PCAN-PCI interface, channel 15 +#define PCAN_PCIBUS16 0x410U // PCAN-PCI interface, channel 16 + +#define PCAN_USBBUS1 0x51U // PCAN-USB interface, channel 1 +#define PCAN_USBBUS2 0x52U // PCAN-USB interface, channel 2 +#define PCAN_USBBUS3 0x53U // PCAN-USB interface, channel 3 +#define PCAN_USBBUS4 0x54U // PCAN-USB interface, channel 4 +#define PCAN_USBBUS5 0x55U // PCAN-USB interface, channel 5 +#define PCAN_USBBUS6 0x56U // PCAN-USB interface, channel 6 +#define PCAN_USBBUS7 0x57U // PCAN-USB interface, channel 7 +#define PCAN_USBBUS8 0x58U // PCAN-USB interface, channel 8 +#define PCAN_USBBUS9 0x509U // PCAN-USB interface, channel 9 +#define PCAN_USBBUS10 0x50AU // PCAN-USB interface, channel 10 +#define PCAN_USBBUS11 0x50BU // PCAN-USB interface, channel 11 +#define PCAN_USBBUS12 0x50CU // PCAN-USB interface, channel 12 +#define PCAN_USBBUS13 0x50DU // PCAN-USB interface, channel 13 +#define PCAN_USBBUS14 0x50EU // PCAN-USB interface, channel 14 +#define PCAN_USBBUS15 0x50FU // PCAN-USB interface, channel 15 +#define PCAN_USBBUS16 0x510U // PCAN-USB interface, channel 16 + +#define PCAN_PCCBUS1 0x61U // PCAN-PC Card interface, channel 1 +#define PCAN_PCCBUS2 0x62U // PCAN-PC Card interface, channel 2 + +#define PCAN_LANBUS1 0x801U // PCAN-LAN interface, channel 1 +#define PCAN_LANBUS2 0x802U // PCAN-LAN interface, channel 2 +#define PCAN_LANBUS3 0x803U // PCAN-LAN interface, channel 3 +#define PCAN_LANBUS4 0x804U // PCAN-LAN interface, channel 4 +#define PCAN_LANBUS5 0x805U // PCAN-LAN interface, channel 5 +#define PCAN_LANBUS6 0x806U // PCAN-LAN interface, channel 6 +#define PCAN_LANBUS7 0x807U // PCAN-LAN interface, channel 7 +#define PCAN_LANBUS8 0x808U // PCAN-LAN interface, channel 8 +#define PCAN_LANBUS9 0x809U // PCAN-LAN interface, channel 9 +#define PCAN_LANBUS10 0x80AU // PCAN-LAN interface, channel 10 +#define PCAN_LANBUS11 0x80BU // PCAN-LAN interface, channel 11 +#define PCAN_LANBUS12 0x80CU // PCAN-LAN interface, channel 12 +#define PCAN_LANBUS13 0x80DU // PCAN-LAN interface, channel 13 +#define PCAN_LANBUS14 0x80EU // PCAN-LAN interface, channel 14 +#define PCAN_LANBUS15 0x80FU // PCAN-LAN interface, channel 15 +#define PCAN_LANBUS16 0x810U // PCAN-LAN interface, channel 16 + +// Represent the PCAN error and status codes +// +#define PCAN_ERROR_OK 0x00000U // No error +#define PCAN_ERROR_XMTFULL 0x00001U // Transmit buffer in CAN controller is full +#define PCAN_ERROR_OVERRUN 0x00002U // CAN controller was read too late +#define PCAN_ERROR_BUSLIGHT 0x00004U // Bus error: an error counter reached the 'light' limit +#define PCAN_ERROR_BUSHEAVY 0x00008U // Bus error: an error counter reached the 'heavy' limit +#define PCAN_ERROR_BUSWARNING PCAN_ERROR_BUSHEAVY // Bus error: an error counter reached the 'warning' limit +#define PCAN_ERROR_BUSPASSIVE 0x40000U // Bus error: the CAN controller is error passive +#define PCAN_ERROR_BUSOFF 0x00010U // Bus error: the CAN controller is in bus-off state +#define PCAN_ERROR_ANYBUSERR (PCAN_ERROR_BUSWARNING | PCAN_ERROR_BUSLIGHT | PCAN_ERROR_BUSHEAVY | PCAN_ERROR_BUSOFF | PCAN_ERROR_BUSPASSIVE) // Mask for all bus errors +#define PCAN_ERROR_QRCVEMPTY 0x00020U // Receive queue is empty +#define PCAN_ERROR_QOVERRUN 0x00040U // Receive queue was read too late +#define PCAN_ERROR_QXMTFULL 0x00080U // Transmit queue is full +#define PCAN_ERROR_REGTEST 0x00100U // Test of the CAN controller hardware registers failed (no hardware found) +#define PCAN_ERROR_NODRIVER 0x00200U // Driver not loaded +#define PCAN_ERROR_HWINUSE 0x00400U // Hardware already in use by a Net +#define PCAN_ERROR_NETINUSE 0x00800U // A Client is already connected to the Net +#define PCAN_ERROR_ILLHW 0x01400U // Hardware handle is invalid +#define PCAN_ERROR_ILLNET 0x01800U // Net handle is invalid +#define PCAN_ERROR_ILLCLIENT 0x01C00U // Client handle is invalid +#define PCAN_ERROR_ILLHANDLE (PCAN_ERROR_ILLHW | PCAN_ERROR_ILLNET | PCAN_ERROR_ILLCLIENT) // Mask for all handle errors +#define PCAN_ERROR_RESOURCE 0x02000U // Resource (FIFO, Client, timeout) cannot be created +#define PCAN_ERROR_ILLPARAMTYPE 0x04000U // Invalid parameter +#define PCAN_ERROR_ILLPARAMVAL 0x08000U // Invalid parameter value +#define PCAN_ERROR_UNKNOWN 0x10000U // Unknown error +#define PCAN_ERROR_ILLDATA 0x20000U // Invalid data, function, or action +#define PCAN_ERROR_ILLMODE 0x80000U // Driver object state is wrong for the attempted operation +#define PCAN_ERROR_CAUTION 0x2000000U // An operation was successfully carried out, however, irregularities were registered +#define PCAN_ERROR_INITIALIZE 0x4000000U // Channel is not initialized [Value was changed from 0x40000 to 0x4000000] +#define PCAN_ERROR_ILLOPERATION 0x8000000U // Invalid operation [Value was changed from 0x80000 to 0x8000000] + +// PCAN devices +// +#define PCAN_NONE 0x00U // Undefined, unknown or not selected PCAN device value +#define PCAN_PEAKCAN 0x01U // PCAN Non-PnP devices. NOT USED WITHIN PCAN-Basic API +#define PCAN_ISA 0x02U // PCAN-ISA, PCAN-PC/104, and PCAN-PC/104-Plus +#define PCAN_DNG 0x03U // PCAN-Dongle +#define PCAN_PCI 0x04U // PCAN-PCI, PCAN-cPCI, PCAN-miniPCI, and PCAN-PCI Express +#define PCAN_USB 0x05U // PCAN-USB and PCAN-USB Pro +#define PCAN_PCC 0x06U // PCAN-PC Card +#define PCAN_VIRTUAL 0x07U // PCAN Virtual hardware. NOT USED WITHIN PCAN-Basic API +#define PCAN_LAN 0x08U // PCAN Gateway devices + +// PCAN parameters +// +#define PCAN_DEVICE_ID 0x01U // Device identifier parameter +#define PCAN_5VOLTS_POWER 0x02U // 5-Volt power parameter +#define PCAN_RECEIVE_EVENT 0x03U // PCAN receive event handler parameter +#define PCAN_MESSAGE_FILTER 0x04U // PCAN message filter parameter +#define PCAN_API_VERSION 0x05U // PCAN-Basic API version parameter +#define PCAN_CHANNEL_VERSION 0x06U // PCAN device channel version parameter +#define PCAN_BUSOFF_AUTORESET 0x07U // PCAN Reset-On-Busoff parameter +#define PCAN_LISTEN_ONLY 0x08U // PCAN Listen-Only parameter +#define PCAN_LOG_LOCATION 0x09U // Directory path for log files +#define PCAN_LOG_STATUS 0x0AU // Debug-Log activation status +#define PCAN_LOG_CONFIGURE 0x0BU // Configuration of the debugged information (LOG_FUNCTION_***) +#define PCAN_LOG_TEXT 0x0CU // Custom insertion of text into the log file +#define PCAN_CHANNEL_CONDITION 0x0DU // Availability status of a PCAN-Channel +#define PCAN_HARDWARE_NAME 0x0EU // PCAN hardware name parameter +#define PCAN_RECEIVE_STATUS 0x0FU // Message reception status of a PCAN-Channel +#define PCAN_CONTROLLER_NUMBER 0x10U // CAN-Controller number of a PCAN-Channel +#define PCAN_TRACE_LOCATION 0x11U // Directory path for PCAN trace files +#define PCAN_TRACE_STATUS 0x12U // CAN tracing activation status +#define PCAN_TRACE_SIZE 0x13U // Configuration of the maximum file size of a CAN trace +#define PCAN_TRACE_CONFIGURE 0x14U // Configuration of the trace file storing mode (TRACE_FILE_***) +#define PCAN_CHANNEL_IDENTIFYING 0x15U // Physical identification of a USB based PCAN-Channel by blinking its associated LED +#define PCAN_CHANNEL_FEATURES 0x16U // Capabilities of a PCAN device (FEATURE_***) +#define PCAN_BITRATE_ADAPTING 0x17U // Using of an existing bit rate (PCAN-View connected to a channel) +#define PCAN_BITRATE_INFO 0x18U // Configured bit rate as Btr0Btr1 value +#define PCAN_BITRATE_INFO_FD 0x19U // Configured bit rate as TPCANBitrateFD string +#define PCAN_BUSSPEED_NOMINAL 0x1AU // Configured nominal CAN Bus speed as Bits per seconds +#define PCAN_BUSSPEED_DATA 0x1BU // Configured CAN data speed as Bits per seconds +#define PCAN_IP_ADDRESS 0x1CU // Remote address of a LAN channel as string in IPv4 format +#define PCAN_LAN_SERVICE_STATUS 0x1DU // Status of the Virtual PCAN-Gateway Service +#define PCAN_ALLOW_STATUS_FRAMES 0x1EU // Status messages reception status within a PCAN-Channel +#define PCAN_ALLOW_RTR_FRAMES 0x1FU // RTR messages reception status within a PCAN-Channel +#define PCAN_ALLOW_ERROR_FRAMES 0x20U // Error messages reception status within a PCAN-Channel +#define PCAN_INTERFRAME_DELAY 0x21U // Delay, in microseconds, between sending frames +#define PCAN_ACCEPTANCE_FILTER_11BIT 0x22U // Filter over code and mask patterns for 11-Bit messages +#define PCAN_ACCEPTANCE_FILTER_29BIT 0x23U // Filter over code and mask patterns for 29-Bit messages +#define PCAN_IO_DIGITAL_CONFIGURATION 0x24U // Output mode of 32 digital I/O pin of a PCAN-USB Chip. 1: Output-Active 0 : Output Inactive +#define PCAN_IO_DIGITAL_VALUE 0x25U // Value assigned to a 32 digital I/O pins of a PCAN-USB Chip +#define PCAN_IO_DIGITAL_SET 0x26U // Value assigned to a 32 digital I/O pins of a PCAN-USB Chip - Multiple digital I/O pins to 1 = High +#define PCAN_IO_DIGITAL_CLEAR 0x27U // Clear multiple digital I/O pins to 0 +#define PCAN_IO_ANALOG_VALUE 0x28U // Get value of a single analog input pin +#define PCAN_FIRMWARE_VERSION 0x29U // Get the version of the firmware used by the device associated with a PCAN-Channel +#define PCAN_ATTACHED_CHANNELS_COUNT 0x2AU // Get the amount of PCAN channels attached to a system +#define PCAN_ATTACHED_CHANNELS 0x2BU // Get information about PCAN channels attached to a system +#define PCAN_ALLOW_ECHO_FRAMES 0x2CU // Echo messages reception status within a PCAN-Channel +#define PCAN_DEVICE_PART_NUMBER 0x2DU // Get the part number associated to a device + +// DEPRECATED parameters +// +#define PCAN_DEVICE_NUMBER PCAN_DEVICE_ID // Deprecated parameter. Use PCAN_DEVICE_ID instead + +// PCAN parameter values +// +#define PCAN_PARAMETER_OFF 0x00U // The PCAN parameter is not set (inactive) +#define PCAN_PARAMETER_ON 0x01U // The PCAN parameter is set (active) +#define PCAN_FILTER_CLOSE 0x00U // The PCAN filter is closed. No messages will be received +#define PCAN_FILTER_OPEN 0x01U // The PCAN filter is fully opened. All messages will be received +#define PCAN_FILTER_CUSTOM 0x02U // The PCAN filter is custom configured. Only registered messages will be received +#define PCAN_CHANNEL_UNAVAILABLE 0x00U // The PCAN-Channel handle is illegal, or its associated hardware is not available +#define PCAN_CHANNEL_AVAILABLE 0x01U // The PCAN-Channel handle is available to be connected (PnP Hardware: it means furthermore that the hardware is plugged-in) +#define PCAN_CHANNEL_OCCUPIED 0x02U // The PCAN-Channel handle is valid, and is already being used +#define PCAN_CHANNEL_PCANVIEW (PCAN_CHANNEL_AVAILABLE | PCAN_CHANNEL_OCCUPIED) // The PCAN-Channel handle is already being used by a PCAN-View application, but is available to connect + +#define LOG_FUNCTION_DEFAULT 0x00U // Logs system exceptions / errors +#define LOG_FUNCTION_ENTRY 0x01U // Logs the entries to the PCAN-Basic API functions +#define LOG_FUNCTION_PARAMETERS 0x02U // Logs the parameters passed to the PCAN-Basic API functions +#define LOG_FUNCTION_LEAVE 0x04U // Logs the exits from the PCAN-Basic API functions +#define LOG_FUNCTION_WRITE 0x08U // Logs the CAN messages passed to the CAN_Write function +#define LOG_FUNCTION_READ 0x10U // Logs the CAN messages received within the CAN_Read function +#define LOG_FUNCTION_ALL 0xFFFFU // Logs all possible information within the PCAN-Basic API functions + +#define TRACE_FILE_SINGLE 0x00U // A single file is written until it size reaches PAN_TRACE_SIZE +#define TRACE_FILE_SEGMENTED 0x01U // Traced data is distributed in several files with size PAN_TRACE_SIZE +#define TRACE_FILE_DATE 0x02U // Includes the date into the name of the trace file +#define TRACE_FILE_TIME 0x04U // Includes the start time into the name of the trace file +#define TRACE_FILE_OVERWRITE 0x80U // Causes the overwriting of available traces (same name) + +#define FEATURE_FD_CAPABLE 0x01U // Device supports flexible data-rate (CAN-FD) +#define FEATURE_DELAY_CAPABLE 0x02U // Device supports a delay between sending frames (FPGA based USB devices) +#define FEATURE_IO_CAPABLE 0x04U // Device supports I/O functionality for electronic circuits (USB-Chip devices) + +#define SERVICE_STATUS_STOPPED 0x01U // The service is not running +#define SERVICE_STATUS_RUNNING 0x04U // The service is running + +// Other constants +// +#define MAX_LENGTH_HARDWARE_NAME 33 // Maximum length of the name of a device: 32 characters + terminator +#define MAX_LENGTH_VERSION_STRING 256 // Maximum length of a version string: 255 characters + terminator + +// PCAN message types +// +#define PCAN_MESSAGE_STANDARD 0x00U // The PCAN message is a CAN Standard Frame (11-bit identifier) +#define PCAN_MESSAGE_RTR 0x01U // The PCAN message is a CAN Remote-Transfer-Request Frame +#define PCAN_MESSAGE_EXTENDED 0x02U // The PCAN message is a CAN Extended Frame (29-bit identifier) +#define PCAN_MESSAGE_FD 0x04U // The PCAN message represents a FD frame in terms of CiA Specs +#define PCAN_MESSAGE_BRS 0x08U // The PCAN message represents a FD bit rate switch (CAN data at a higher bit rate) +#define PCAN_MESSAGE_ESI 0x10U // The PCAN message represents a FD error state indicator(CAN FD transmitter was error active) +#define PCAN_MESSAGE_ECHO 0x20U // The PCAN message represents an echo CAN Frame +#define PCAN_MESSAGE_ERRFRAME 0x40U // The PCAN message represents an error frame +#define PCAN_MESSAGE_STATUS 0x80U // The PCAN message represents a PCAN status message + +// LookUp Parameters +// +#define LOOKUP_DEVICE_TYPE __T("devicetype") // Lookup channel by Device type (see PCAN devices e.g. PCAN_USB) +#define LOOKUP_DEVICE_ID __T("deviceid") // Lookup channel by device id +#define LOOKUP_CONTROLLER_NUMBER __T("controllernumber") // Lookup channel by CAN controller 0-based index +#define LOOKUP_IP_ADDRESS __T("ipaddress") // Lookup channel by IP address (LAN channels only) + +// Frame Type / Initialization Mode +// +#define PCAN_MODE_STANDARD PCAN_MESSAGE_STANDARD +#define PCAN_MODE_EXTENDED PCAN_MESSAGE_EXTENDED + +// Baud rate codes = BTR0/BTR1 register values for the CAN controller. +// You can define your own Baud rate with the BTROBTR1 register. +// Take a look at www.peak-system.com for our free software "BAUDTOOL" +// to calculate the BTROBTR1 register for every bit rate and sample point. +// +#define PCAN_BAUD_1M 0x0014U // 1 MBit/s +#define PCAN_BAUD_800K 0x0016U // 800 kBit/s +#define PCAN_BAUD_500K 0x001CU // 500 kBit/s +#define PCAN_BAUD_250K 0x011CU // 250 kBit/s +#define PCAN_BAUD_125K 0x031CU // 125 kBit/s +#define PCAN_BAUD_100K 0x432FU // 100 kBit/s +#define PCAN_BAUD_95K 0xC34EU // 95,238 kBit/s +#define PCAN_BAUD_83K 0x852BU // 83,333 kBit/s +#define PCAN_BAUD_50K 0x472FU // 50 kBit/s +#define PCAN_BAUD_47K 0x1414U // 47,619 kBit/s +#define PCAN_BAUD_33K 0x8B2FU // 33,333 kBit/s +#define PCAN_BAUD_20K 0x532FU // 20 kBit/s +#define PCAN_BAUD_10K 0x672FU // 10 kBit/s +#define PCAN_BAUD_5K 0x7F7FU // 5 kBit/s + +// Represents the configuration for a CAN bit rate +// Note: +// * Each parameter and its value must be separated with a '='. +// * Each pair of parameter/value must be separated using ','. +// +// Example: +// f_clock=80000000,nom_brp=10,nom_tseg1=5,nom_tseg2=2,nom_sjw=1,data_brp=4,data_tseg1=7,data_tseg2=2,data_sjw=1 +// +#define PCAN_BR_CLOCK __T("f_clock") +#define PCAN_BR_CLOCK_MHZ __T("f_clock_mhz") +#define PCAN_BR_NOM_BRP __T("nom_brp") +#define PCAN_BR_NOM_TSEG1 __T("nom_tseg1") +#define PCAN_BR_NOM_TSEG2 __T("nom_tseg2") +#define PCAN_BR_NOM_SJW __T("nom_sjw") +#define PCAN_BR_NOM_SAMPLE __T("nom_sam") +#define PCAN_BR_DATA_BRP __T("data_brp") +#define PCAN_BR_DATA_TSEG1 __T("data_tseg1") +#define PCAN_BR_DATA_TSEG2 __T("data_tseg2") +#define PCAN_BR_DATA_SJW __T("data_sjw") +#define PCAN_BR_DATA_SAMPLE __T("data_ssp_offset") + +// Type of PCAN (Non-PnP) hardware +// +#define PCAN_TYPE_ISA 0x01U // PCAN-ISA 82C200 +#define PCAN_TYPE_ISA_SJA 0x09U // PCAN-ISA SJA1000 +#define PCAN_TYPE_ISA_PHYTEC 0x04U // PHYTEC ISA +#define PCAN_TYPE_DNG 0x02U // PCAN-Dongle 82C200 +#define PCAN_TYPE_DNG_EPP 0x03U // PCAN-Dongle EPP 82C200 +#define PCAN_TYPE_DNG_SJA 0x05U // PCAN-Dongle SJA1000 +#define PCAN_TYPE_DNG_SJA_EPP 0x06U // PCAN-Dongle EPP SJA1000 + +//////////////////////////////////////////////////////////// +// Type definitions +//////////////////////////////////////////////////////////// + +#define TPCANHandle WORD // Represents a PCAN hardware channel handle +#define TPCANStatus DWORD // Represents a PCAN status/error code +#define TPCANParameter BYTE // Represents a PCAN parameter to be read or set +#define TPCANDevice BYTE // Represents a PCAN device +#define TPCANMessageType BYTE // Represents the type of a PCAN message +#define TPCANType BYTE // Represents the type of PCAN hardware to be initialized +#define TPCANMode BYTE // Represents a PCAN filter mode +#define TPCANBaudrate WORD // Represents a PCAN Baud rate register value +#define TPCANBitrateFD LPSTR // Represents a PCAN-FD bit rate string +#define TPCANTimestampFD UINT64 // Represents a timestamp of a received PCAN FD message + +//////////////////////////////////////////////////////////// +// Structure definitions +//////////////////////////////////////////////////////////// + +#include +#include + +// Represents a PCAN message +// +typedef struct tagTPCANMsg +{ + DWORD ID; // 11/29-bit message identifier + TPCANMessageType MSGTYPE; // Type of the message + BYTE LEN; // Data Length Code of the message (0..8) + BYTE DATA[8]; // Data of the message (DATA[0]..DATA[7]) +} TPCANMsg; + +// Represents a timestamp of a received PCAN message +// Total Microseconds = micros + 1000 * millis + 0x100000000 * 1000 * millis_overflow +// +typedef struct tagTPCANTimestamp +{ + DWORD millis; // Base-value: milliseconds: 0.. 2^32-1 + WORD millis_overflow; // Roll-arounds of millis + WORD micros; // Microseconds: 0..999 +} TPCANTimestamp; + +// Represents a PCAN message from a FD capable hardware +// +typedef struct tagTPCANMsgFD +{ + DWORD ID; // 11/29-bit message identifier + TPCANMessageType MSGTYPE; // Type of the message + BYTE DLC; // Data Length Code of the message (0..15) + BYTE DATA[64]; // Data of the message (DATA[0]..DATA[63]) +} TPCANMsgFD; + +// Describes an available PCAN channel +// +typedef struct tagTPCANChannelInformation +{ + TPCANHandle channel_handle; // PCAN channel handle + TPCANDevice device_type; // Kind of PCAN device + BYTE controller_number; // CAN-Controller number + DWORD device_features; // Device capabilities flag (see FEATURE_*) + char device_name[MAX_LENGTH_HARDWARE_NAME]; // Device name + DWORD device_id; // Device number + DWORD channel_condition; // Availability status of a PCAN-Channel +}TPCANChannelInformation; + +#ifdef __cplusplus +extern "C" { +#define _DEF_ARG =0 +#else +#define _DEF_ARG +#endif + +//////////////////////////////////////////////////////////// +// PCAN-Basic API function declarations +//////////////////////////////////////////////////////////// + + +/// +/// Initializes a PCAN Channel +/// +/// "The handle of a PCAN Channel" +/// "The speed for the communication (BTR0BTR1 code)" +/// "Non-PnP: The type of hardware and operation mode" +/// "Non-PnP: The I/O address for the parallel port" +/// "Non-PnP: Interrupt number of the parallel port" +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_Initialize( + TPCANHandle Channel, + TPCANBaudrate Btr0Btr1, + TPCANType HwType _DEF_ARG, + DWORD IOPort _DEF_ARG, + WORD Interrupt _DEF_ARG); + + +/// +/// Initializes a FD capable PCAN Channel +/// +/// "The handle of a FD capable PCAN Channel" +/// "The speed for the communication (FD bit rate string)" +/// See PCAN_BR_* values +/// * Parameter and values must be separated by '=' +/// * Couples of Parameter/value must be separated by ',' +/// * Following Parameter must be filled out: f_clock, data_brp, data_sjw, data_tseg1, data_tseg2, +/// nom_brp, nom_sjw, nom_tseg1, nom_tseg2. +/// * Following Parameters are optional (not used yet): data_ssp_offset, nom_sam +/// +/// f_clock=80000000,nom_brp=10,nom_tseg1=5,nom_tseg2=2,nom_sjw=1,data_brp=4,data_tseg1=7,data_tseg2=2,data_sjw=1 +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_InitializeFD( + TPCANHandle Channel, + TPCANBitrateFD BitrateFD); + + +/// +/// Uninitializes one or all PCAN Channels initialized by CAN_Initialize +/// +/// Giving the TPCANHandle value "PCAN_NONEBUS", +/// uninitialize all initialized channels +/// "The handle of a PCAN Channel" +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_Uninitialize( + TPCANHandle Channel); + + +/// +/// Resets the receive and transmit queues of the PCAN Channel +/// +/// +/// A reset of the CAN controller is not performed. +/// +/// "The handle of a PCAN Channel" +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_Reset( + TPCANHandle Channel); + + +/// +/// Gets the current status of a PCAN Channel +/// +/// "The handle of a PCAN Channel" +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_GetStatus( + TPCANHandle Channel); + + +/// +/// Reads a CAN message from the receive queue of a PCAN Channel +/// +/// "The handle of a PCAN Channel" +/// "A TPCANMsg structure buffer to store the CAN message" +/// "A TPCANTimestamp structure buffer to get +/// the reception time of the message. If this value is not desired, this parameter +/// should be passed as NULL" +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_Read( + TPCANHandle Channel, + TPCANMsg* MessageBuffer, + TPCANTimestamp* TimestampBuffer); + + +/// +/// Reads a CAN message from the receive queue of a FD capable PCAN Channel +/// +/// "The handle of a FD capable PCAN Channel" +/// "A TPCANMsgFD structure buffer to store the CAN message" +/// "A TPCANTimestampFD buffer to get +/// the reception time of the message. If this value is not desired, this parameter +/// should be passed as NULL" +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_ReadFD( + TPCANHandle Channel, + TPCANMsgFD* MessageBuffer, + TPCANTimestampFD *TimestampBuffer); + + +/// +/// Transmits a CAN message +/// +/// "The handle of a PCAN Channel" +/// "A TPCANMsg buffer with the message to be sent" +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_Write( + TPCANHandle Channel, + TPCANMsg* MessageBuffer); + + +/// +/// Transmits a CAN message over a FD capable PCAN Channel +/// +/// "The handle of a FD capable PCAN Channel" +/// "A TPCANMsgFD buffer with the message to be sent" +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_WriteFD( + TPCANHandle Channel, + TPCANMsgFD* MessageBuffer); + + +/// +/// Configures the reception filter. +/// +/// The message filter will be expanded with every call to +/// this function. If it is desired to reset the filter, please use +/// the CAN_SetValue function +/// "The handle of a PCAN Channel" +/// "The lowest CAN ID to be received" +/// "The highest CAN ID to be received" +/// "Message type, Standard (11-bit identifier) or +/// Extended (29-bit identifier)" +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_FilterMessages( + TPCANHandle Channel, + DWORD FromID, + DWORD ToID, + TPCANMode Mode); + + +/// +/// Retrieves a PCAN Channel value +/// +/// Parameters can be present or not according with the kind +/// of Hardware (PCAN Channel) being used. If a parameter is not available, +/// a PCAN_ERROR_ILLPARAMTYPE error will be returned +/// "The handle of a PCAN Channel" +/// "The TPCANParameter parameter to get" +/// "Buffer for the parameter value" +/// "Size in bytes of the buffer" +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_GetValue( + TPCANHandle Channel, + TPCANParameter Parameter, + void* Buffer, + DWORD BufferLength); + + +/// +/// Configures or sets a PCAN Channel value +/// +/// Parameters can be present or not according with the kind +/// of Hardware (PCAN Channel) being used. If a parameter is not available, +/// a PCAN_ERROR_ILLPARAMTYPE error will be returned +/// "The handle of a PCAN Channel" +/// "The TPCANParameter parameter to set" +/// "Buffer with the value to be set" +/// "Size in bytes of the buffer" +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_SetValue( + TPCANHandle Channel, + TPCANParameter Parameter, + void* Buffer, + DWORD BufferLength); + + +/// +/// Returns a descriptive text of a given TPCANStatus error +/// code, in any desired language +/// +/// The current languages available for translation are: +/// Neutral (0x00), German (0x07), English (0x09), Spanish (0x0A), +/// Italian (0x10) and French (0x0C) +/// "A TPCANStatus error code" +/// "Indicates a 'Primary language ID'" +/// "Buffer for a null terminated char array" +/// "A TPCANStatus error code" +TPCANStatus __stdcall CAN_GetErrorText( + TPCANStatus Error, + WORD Language, + LPSTR Buffer); + +/// +/// Finds a PCAN-Basic channel that matches with the given parameters +/// +/// A comma separated string contained pairs of +/// parameter-name/value to be matched within a PCAN-Basic channel +/// Buffer for returning the PCAN-Basic channel, +/// when found +/// A TPCANStatus error code +TPCANStatus __stdcall CAN_LookUpChannel( + LPSTR Parameters, + TPCANHandle* FoundChannel); + +#ifdef __cplusplus +} +#endif + #endif \ No newline at end of file diff --git a/third_party/PCAN_Basic/Include/PCANBasicCLR.h b/third_party/PCAN_Basic/Include/PCANBasicCLR.h index fcd7498..a9ef313 100644 --- a/third_party/PCAN_Basic/Include/PCANBasicCLR.h +++ b/third_party/PCAN_Basic/Include/PCANBasicCLR.h @@ -1,1510 +1,1510 @@ -// PCANBasicCLR.h -// -// ~~~~~~~~~~~~ -// -// PCAN-Basic API -// -// ~~~~~~~~~~~~ -// -// ------------------------------------------------------------------ -// Author : Keneth Wagner -// Last change: 2022-07-06 -// -// Language: C++/CLR -// ------------------------------------------------------------------ -// -// Copyright (C) 1999-2022 PEAK-System Technik GmbH, Darmstadt -// more Info at http://www.peak-system.com -// -using namespace System; -using namespace System::Text; -using namespace System::Runtime::InteropServices; - -//////////////////////////////////////////////////////////// -// Type definitions -//////////////////////////////////////////////////////////// -#define TPCANHandle System::UInt16 // Represents a PCAN hardware channel handle -#define TPCANBitrateFD System::String^ // Represents a bit rate String (Flexible Data rate) -#define TPCANTimestampFD System::UInt64 // Represents a timestamp in microseconds - -namespace Peak -{ - namespace Can - { - namespace Basic - { - #pragma region Other Constants - /// - /// Maximum length of the name of a device: 32 characters + terminator - /// - static const int MAX_LENGTH_HARDWARE_NAME = 33; - /// - /// Maximum length of a version string: 255 characters + terminator - /// - static const int MAX_LENGTH_VERSION_STRING = 256; - #pragma endregion - - #pragma region Enumerations - /// - /// Represents a PCAN status/error code - /// - [Flags] - public enum class TPCANStatus : UInt32 - { - /// - /// No error - /// - PCAN_ERROR_OK = 0x00000, - /// - /// Transmit buffer in CAN controller is full - /// - PCAN_ERROR_XMTFULL = 0x00001, - /// - /// CAN controller was read too late - /// - PCAN_ERROR_OVERRUN = 0x00002, - /// - /// Bus error: an error counter reached the 'light' limit - /// - PCAN_ERROR_BUSLIGHT = 0x00004, - /// - /// Bus error: an error counter reached the 'heavy' limit - /// - PCAN_ERROR_BUSHEAVY = 0x00008, - /// - /// Bus error: an error counter reached the 'warning' limit - /// - PCAN_ERROR_BUSWARNING = PCAN_ERROR_BUSHEAVY, - /// - /// Bus error: the CAN controller is error passive - /// - PCAN_ERROR_BUSPASSIVE = 0x40000, - /// - /// Bus error: the CAN controller is in bus-off state - /// - PCAN_ERROR_BUSOFF = 0x00010, - /// - /// Mask for all bus errors - /// - PCAN_ERROR_ANYBUSERR = (PCAN_ERROR_BUSWARNING | PCAN_ERROR_BUSLIGHT | PCAN_ERROR_BUSHEAVY | PCAN_ERROR_BUSOFF | PCAN_ERROR_BUSPASSIVE), - /// - /// Receive queue is empty - /// - PCAN_ERROR_QRCVEMPTY = 0x00020, - /// - /// Receive queue was read too late - /// - PCAN_ERROR_QOVERRUN = 0x00040, - /// - /// Transmit queue is full - /// - PCAN_ERROR_QXMTFULL = 0x00080, - /// - /// Test of the CAN controller hardware registers failed (no hardware found) - /// - PCAN_ERROR_REGTEST = 0x00100, - /// - /// Driver not loaded - /// - PCAN_ERROR_NODRIVER = 0x00200, - /// - /// Hardware already in use by a Net - /// - PCAN_ERROR_HWINUSE = 0x00400, - /// - /// A Client is already connected to the Net - /// - PCAN_ERROR_NETINUSE = 0x00800, - /// - /// Hardware handle is invalid - /// - PCAN_ERROR_ILLHW = 0x01400, - /// - /// Net handle is invalid - /// - PCAN_ERROR_ILLNET = 0x01800, - /// - /// Client handle is invalid - /// - PCAN_ERROR_ILLCLIENT = 0x01C00, - /// - /// Mask for all handle errors - /// - PCAN_ERROR_ILLHANDLE = (PCAN_ERROR_ILLHW | PCAN_ERROR_ILLNET | PCAN_ERROR_ILLCLIENT), - /// - /// Resource (FIFO, Client, timeout) cannot be created - /// - PCAN_ERROR_RESOURCE = 0x02000, - /// - /// Invalid parameter - /// - PCAN_ERROR_ILLPARAMTYPE = 0x04000, - /// - /// Invalid parameter value - /// - PCAN_ERROR_ILLPARAMVAL = 0x08000, - /// - /// Unknown error - /// - PCAN_ERROR_UNKNOWN = 0x10000, - /// - /// Invalid data, function, or action. - /// - PCAN_ERROR_ILLDATA = 0x20000, - /// - /// Driver object state is wrong for the attempted operation - /// - PCAN_ERROR_ILLMODE = 0x80000, - /// - /// An operation was successfully carried out, however, irregularities were registered - /// - PCAN_ERROR_CAUTION = 0x2000000, - /// - /// Channel is not initialized - /// Value was changed from 0x40000 to 0x4000000 - /// - PCAN_ERROR_INITIALIZE = 0x4000000, - /// - /// Invalid operation - /// Value was changed from 0x80000 to 0x8000000 - /// - PCAN_ERROR_ILLOPERATION = 0x8000000, - }; - - /// - /// Represents a PCAN device - /// - public enum class TPCANDevice : Byte - { - /// - /// Undefined, unknown or not selected PCAN device value - /// - PCAN_NONE = 0, - /// - /// PCAN Non-PnP devices. NOT USED WITHIN PCAN-Basic API - /// - PCAN_PEAKCAN = 1, - /// - /// PCAN-ISA, PCAN-PC/104, and PCAN-PC/104-Plus - /// - PCAN_ISA = 2, - /// - /// PCAN-Dongle - /// - PCAN_DNG = 3, - /// - /// PCAN-PCI, PCAN-cPCI, PCAN-miniPCI, and PCAN-PCI Express - /// - PCAN_PCI = 4, - /// - /// PCAN-USB and PCAN-USB Pro - /// - PCAN_USB = 5, - /// - /// PCAN-PC Card - /// - PCAN_PCC = 6, - /// - /// PCAN Virtual hardware. NOT USED WITHIN PCAN-Basic API - /// - PCAN_VIRTUAL = 7, - /// - /// PCAN Gateway devices - /// - PCAN_LAN = 8 - }; - - /// - /// Represents a PCAN parameter to be read or set - /// - public enum class TPCANParameter : Byte - { - /// - /// Device identifier parameter - /// - PCAN_DEVICE_ID = 1, - /// - /// DEPRECATED. Use PCAN_DEVICE_ID instead - /// - [Obsolete] - PCAN_DEVICE_NUMBER = PCAN_DEVICE_ID, - /// - /// 5-Volt power parameter - /// - PCAN_5VOLTS_POWER = 2, - /// - /// PCAN receive event handler parameter - /// - PCAN_RECEIVE_EVENT = 3, - /// - /// PCAN message filter parameter - /// - PCAN_MESSAGE_FILTER = 4, - /// - /// PCAN-Basic API version parameter - /// - PCAN_API_VERSION = 5, - /// - /// PCAN device channel version parameter - /// - PCAN_CHANNEL_VERSION = 6, - /// - /// PCAN Reset-On-Busoff parameter - /// - PCAN_BUSOFF_AUTORESET = 7, - /// - /// PCAN Listen-Only parameter - /// - PCAN_LISTEN_ONLY = 8, - /// - /// Directory path for log files - /// - PCAN_LOG_LOCATION = 9, - /// - /// Debug-Log activation status - /// - PCAN_LOG_STATUS = 10, - /// - /// Configuration of the debugged information (LOG_FUNCTION_***) - /// - PCAN_LOG_CONFIGURE = 11, - /// - /// Custom insertion of text into the log file - /// - PCAN_LOG_TEXT = 12, - /// - /// Availability status of a PCAN-Channel - /// - PCAN_CHANNEL_CONDITION = 13, - /// - /// PCAN hardware name parameter - /// - PCAN_HARDWARE_NAME = 14, - /// - /// Message reception status of a PCAN-Channel - /// - PCAN_RECEIVE_STATUS = 15, - /// - /// CAN-Controller number of a PCAN-Channel - /// - PCAN_CONTROLLER_NUMBER = 16, - /// - /// Directory path for PCAN trace files - /// - PCAN_TRACE_LOCATION = 17, - /// - /// CAN tracing activation status - /// - PCAN_TRACE_STATUS = 18, - /// - /// Configuration of the maximum file size of a CAN trace - /// - PCAN_TRACE_SIZE = 19, - /// - /// Configuration of the trace file storing mode (TRACE_FILE_***) - /// - PCAN_TRACE_CONFIGURE = 20, - /// - /// Physical identification of a USB based PCAN-Channel by blinking its associated LED - /// - PCAN_CHANNEL_IDENTIFYING = 21, - /// - /// Capabilities of a PCAN device (FEATURE_***) - /// - PCAN_CHANNEL_FEATURES = 22, - /// - /// Using of an existing bit rate (PCAN-View connected to a channel) - /// - PCAN_BITRATE_ADAPTING = 23, - /// - /// Configured bit rate as Btr0Btr1 value - /// - PCAN_BITRATE_INFO = 24, - /// - /// Configured bit rate as TPCANBitrateFD string - /// - PCAN_BITRATE_INFO_FD = 25, - /// - /// Configured nominal CAN Bus speed as Bits per seconds - /// - PCAN_BUSSPEED_NOMINAL = 26, - /// - /// Configured CAN data speed as Bits per seconds - /// - PCAN_BUSSPEED_DATA = 27, - /// - /// Remote address of a LAN channel as string in IPv4 format - /// - PCAN_IP_ADDRESS = 28, - /// - /// Status of the Virtual PCAN-Gateway Service - /// - PCAN_LAN_SERVICE_STATUS = 29, - /// - /// Status messages reception status within a PCAN-Channel - /// - PCAN_ALLOW_STATUS_FRAMES = 30, - /// - /// RTR messages reception status within a PCAN-Channel - /// - PCAN_ALLOW_RTR_FRAMES = 31, - /// - /// Error messages reception status within a PCAN-Channel - /// - PCAN_ALLOW_ERROR_FRAMES = 32, - /// - /// Delay, in microseconds, between sending frames - /// - PCAN_INTERFRAME_DELAY = 33, - /// - /// Filter over code and mask patterns for 11-Bit messages - /// - PCAN_ACCEPTANCE_FILTER_11BIT = 34, - /// - /// Filter over code and mask patterns for 29-Bit messages - /// - PCAN_ACCEPTANCE_FILTER_29BIT = 35, - /// - /// Output mode of 32 digital I/O pin of a PCAN-USB Chip. 1: Output-Active 0 : Output Inactive - /// - PCAN_IO_DIGITAL_CONFIGURATION = 36, - /// - /// Value assigned to a 32 digital I/O pins of a PCAN-USB Chip - /// - PCAN_IO_DIGITAL_VALUE = 37, - /// - /// Value assigned to a 32 digital I/O pins of a PCAN-USB Chip - Multiple digital I/O pins to 1 = High - /// - PCAN_IO_DIGITAL_SET = 38, - /// - /// Clear multiple digital I/O pins to 0 - /// - PCAN_IO_DIGITAL_CLEAR = 39, - /// - /// Get value of a single analog input pin - /// - PCAN_IO_ANALOG_VALUE = 40, - /// - /// Get the version of the firmware used by the device associated with a PCAN-Channel - /// - PCAN_FIRMWARE_VERSION = 41, - /// - /// Get the amount of PCAN channels attached to a system - /// - PCAN_ATTACHED_CHANNELS_COUNT = 42, - /// - /// Get information about PCAN channels attached to a system - /// - PCAN_ATTACHED_CHANNELS = 43, - /// - /// Echo messages reception status within a PCAN-Channel - /// - PCAN_ALLOW_ECHO_FRAMES = 44, - /// - /// Get the part number associated to a device - /// - PCAN_DEVICE_PART_NUMBER = 45, - }; - - /// Represents the type of a PCAN message - /// - [Flags] - public enum class TPCANMessageType : Byte - { - /// - /// The PCAN message is a CAN Standard Frame (11-bit identifier) - /// - PCAN_MESSAGE_STANDARD = 0x00, - /// - /// The PCAN message is a CAN Remote-Transfer-Request Frame - /// - PCAN_MESSAGE_RTR = 0x01, - /// - /// The PCAN message is a CAN Extended Frame (29-bit identifier) - /// - PCAN_MESSAGE_EXTENDED = 0x02, - /// - /// The PCAN message represents a FD frame in terms of CiA Specs - /// - PCAN_MESSAGE_FD = 0x04, - /// - /// The PCAN message represents a FD bit rate switch (CAN data at a higher bit rate) - /// - PCAN_MESSAGE_BRS = 0x08, - /// - /// The PCAN message represents a FD error state indicator(CAN FD transmitter was error active) - /// - PCAN_MESSAGE_ESI = 0x10, - /// - /// The PCAN message represents an echo CAN Frame - /// - PCAN_MESSAGE_ECHO = 0x20, - /// - /// The PCAN message represents an error frame - /// - PCAN_MESSAGE_ERRFRAME = 0x40, - /// - /// The PCAN message represents a PCAN status message - /// - /// - PCAN_MESSAGE_STATUS = 0x80, - }; - - /// - /// Represents a PCAN filter mode - /// - public enum class TPCANMode : Byte - { - /// - /// Mode is Standard (11-bit identifier) - /// - PCAN_MODE_STANDARD = TPCANMessageType::PCAN_MESSAGE_STANDARD, - /// - /// Mode is Extended (29-bit identifier) - /// - PCAN_MODE_EXTENDED = TPCANMessageType::PCAN_MESSAGE_EXTENDED, - }; - - /// - /// Represents a PCAN Baud rate register value - /// - public enum class TPCANBaudrate : UInt16 - { - /// - /// 1 MBit/s - /// - PCAN_BAUD_1M = 0x0014, - /// - /// 800 kBit/s - /// - PCAN_BAUD_800K = 0x0016, - /// - /// 500 kBit/s - /// - PCAN_BAUD_500K = 0x001C, - /// - /// 250 kBit/s - /// - PCAN_BAUD_250K = 0x011C, - /// - /// 125 kBit/s - /// - PCAN_BAUD_125K = 0x031C, - /// - /// 100 kBit/s - /// - PCAN_BAUD_100K = 0x432F, - /// - /// 95,238 kBit/s - /// - PCAN_BAUD_95K = 0xC34E, - /// - /// 83,333 kBit/s - /// - PCAN_BAUD_83K = 0x852B, - /// - /// 50 kBit/s - /// - PCAN_BAUD_50K = 0x472F, - /// - /// 47,619 kBit/s - /// - PCAN_BAUD_47K = 0x1414, - /// - /// 33,333 kBit/s - /// - PCAN_BAUD_33K = 0x8B2F, - /// - /// 20 kBit/s - /// - PCAN_BAUD_20K = 0x532F, - /// - /// 10 kBit/s - /// - PCAN_BAUD_10K = 0x672F, - /// - /// 5 kBit/s - /// - PCAN_BAUD_5K = 0x7F7F, - }; - - /// - /// Represents the type of PCAN (Non-PnP) hardware to be initialized - /// - public enum class TPCANType : Byte - { - /// - /// PCAN-ISA 82C200 - /// - PCAN_TYPE_ISA = 0x01, - /// - /// PCAN-ISA SJA1000 - /// - PCAN_TYPE_ISA_SJA = 0x09, - /// - /// PHYTEC ISA - /// - PCAN_TYPE_ISA_PHYTEC = 0x04, - /// - /// PCAN-Dongle 82C200 - /// - PCAN_TYPE_DNG = 0x02, - /// - /// PCAN-Dongle EPP 82C200 - /// - PCAN_TYPE_DNG_EPP = 0x03, - /// - /// PCAN-Dongle SJA1000 - /// - PCAN_TYPE_DNG_SJA = 0x05, - /// - /// PCAN-Dongle EPP SJA1000 - /// - PCAN_TYPE_DNG_SJA_EPP = 0x06, - }; - #pragma endregion - - #pragma region Strutures - /// - /// Represents a PCAN message - /// - public value struct TPCANMsg - { - /// - /// 11/29-bit message identifier - /// - UInt32 ID; - /// - /// Type of the message - /// - [MarshalAs(UnmanagedType::U1)] - TPCANMessageType MSGTYPE; - /// - /// Data Length Code of the message (0..8) - /// - Byte LEN; - /// - /// Data of the message (DATA[0]..DATA[7]) - /// - [MarshalAs(UnmanagedType::ByValArray, SizeConst = 8)] - array^ DATA; - }; - - /// - /// Represents a timestamp of a received PCAN message. - /// Total Microseconds = micros + 1000 * millis + 0x100000000 * 1000 * millis_overflow - /// - public value struct TPCANTimestamp - { - /// - /// Base-value: milliseconds: 0.. 2^32-1 - /// - UInt32 millis; - /// - /// Roll-arounds of millis - /// - UInt16 millis_overflow; - /// - /// Microseconds: 0..999 - /// - UInt16 micros; - }; - - /// - /// Represents a PCAN message from a FD capable hardware - /// - public value struct TPCANMsgFD - { - /// - /// 11/29-bit message identifier - /// - UInt32 ID; - /// - /// Type of the message - /// - [MarshalAs(UnmanagedType::U1)] - TPCANMessageType MSGTYPE; - /// - /// Data Length Code of the message (0..15) - /// - Byte DLC; - /// - /// Data of the message (DATA[0]..DATA[63]) - /// - [MarshalAs(UnmanagedType::ByValArray, SizeConst = 64)] - array^ DATA; - }; - - /// - /// Describes an available PCAN channel - /// - public value struct TPCANChannelInformation - { - /// - /// PCAN channel handle - /// - [MarshalAs(UnmanagedType::U2)] - TPCANHandle channel_handle; - /// - /// Kind of PCAN device - /// - [MarshalAs(UnmanagedType::U1)] - TPCANDevice device_type; - /// - /// CAN-Controller number - /// - Byte controller_number; - /// - /// Device capabilities flag (see FEATURE_*) - /// - UInt32 device_features; - /// - /// Device name - /// - [MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_LENGTH_HARDWARE_NAME)] - String^ device_name; - /// - /// Device number - /// - UInt32 device_id; - /// - /// Availability status of a PCAN-Channel - /// - UInt32 channel_condition; - }; - #pragma endregion - - #pragma region PCANBasic class - /// - /// PCAN-Basic API class implementation - /// - public ref class PCANBasic abstract sealed - { - public: - #pragma region PCAN-BUS Handles Definition - /// - /// Undefined/default value for a PCAN bus - /// - static const TPCANHandle PCAN_NONEBUS = 0x00; - - /// - /// PCAN-ISA interface, channel 1 - /// - static const TPCANHandle PCAN_ISABUS1 = 0x21; - /// - /// PCAN-ISA interface, channel 2 - /// - static const TPCANHandle PCAN_ISABUS2 = 0x22; - /// - /// PCAN-ISA interface, channel 3 - /// - static const TPCANHandle PCAN_ISABUS3 = 0x23; - /// - /// PCAN-ISA interface, channel 4 - /// - static const TPCANHandle PCAN_ISABUS4 = 0x24; - /// - /// PCAN-ISA interface, channel 5 - /// - static const TPCANHandle PCAN_ISABUS5 = 0x25; - /// - /// PCAN-ISA interface, channel 6 - /// - static const TPCANHandle PCAN_ISABUS6 = 0x26; - /// - /// PCAN-ISA interface, channel 7 - /// - static const TPCANHandle PCAN_ISABUS7 = 0x27; - /// - /// PCAN-ISA interface, channel 8 - /// - static const TPCANHandle PCAN_ISABUS8 = 0x28; - - /// - /// PPCAN-Dongle/LPT interface, channel 1 - /// - static const TPCANHandle PCAN_DNGBUS1 = 0x31; - - /// - /// PCAN-PCI interface, channel 1 - /// - static const TPCANHandle PCAN_PCIBUS1 = 0x41; - /// - /// PCAN-PCI interface, channel 2 - /// - static const TPCANHandle PCAN_PCIBUS2 = 0x42; - /// - /// PCAN-PCI interface, channel 3 - /// - static const TPCANHandle PCAN_PCIBUS3 = 0x43; - /// - /// PCAN-PCI interface, channel 4 - /// - static const TPCANHandle PCAN_PCIBUS4 = 0x44; - /// - /// PCAN-PCI interface, channel 5 - /// - static const TPCANHandle PCAN_PCIBUS5 = 0x45; - /// - /// PCAN-PCI interface, channel 6 - /// - static const TPCANHandle PCAN_PCIBUS6 = 0x46; - /// - /// PCAN-PCI interface, channel 7 - /// - static const TPCANHandle PCAN_PCIBUS7 = 0x47; - /// - /// PCAN-PCI interface, channel 8 - /// - static const TPCANHandle PCAN_PCIBUS8 = 0x48; - /// - /// PCAN-PCI interface, channel 9 - /// - static const TPCANHandle PCAN_PCIBUS9 = 0x409; - /// - /// PCAN-PCI interface, channel 10 - /// - static const TPCANHandle PCAN_PCIBUS10 = 0x40A; - /// - /// PCAN-PCI interface, channel 11 - /// - static const TPCANHandle PCAN_PCIBUS11 = 0x40B; - /// - /// PCAN-PCI interface, channel 12 - /// - static const TPCANHandle PCAN_PCIBUS12 = 0x40C; - /// - /// PCAN-PCI interface, channel 13 - /// - static const TPCANHandle PCAN_PCIBUS13 = 0x40D; - /// - /// PCAN-PCI interface, channel 14 - /// - static const TPCANHandle PCAN_PCIBUS14 = 0x40E; - /// - /// PCAN-PCI interface, channel 15 - /// - static const TPCANHandle PCAN_PCIBUS15 = 0x40F; - /// - /// PCAN-PCI interface, channel 16 - /// - static const TPCANHandle PCAN_PCIBUS16 = 0x410; - - /// - /// PCAN-USB interface, channel 1 - /// - static const TPCANHandle PCAN_USBBUS1 = 0x51; - /// - /// PCAN-USB interface, channel 2 - /// - static const TPCANHandle PCAN_USBBUS2 = 0x52; - /// - /// PCAN-USB interface, channel 3 - /// - static const TPCANHandle PCAN_USBBUS3 = 0x53; - /// - /// PCAN-USB interface, channel 4 - /// - static const TPCANHandle PCAN_USBBUS4 = 0x54; - /// - /// PCAN-USB interface, channel 5 - /// - static const TPCANHandle PCAN_USBBUS5 = 0x55; - /// - /// PCAN-USB interface, channel 6 - /// - static const TPCANHandle PCAN_USBBUS6 = 0x56; - /// - /// PCAN-USB interface, channel 7 - /// - static const TPCANHandle PCAN_USBBUS7 = 0x57; - /// - /// PCAN-USB interface, channel 8 - /// - static const TPCANHandle PCAN_USBBUS8 = 0x58; - /// - /// PCAN-USB interface, channel 9 - /// - static const TPCANHandle PCAN_USBBUS9 = 0x509; - /// - /// PCAN-USB interface, channel 10 - /// - static const TPCANHandle PCAN_USBBUS10 = 0x50A; - /// - /// PCAN-USB interface, channel 11 - /// - static const TPCANHandle PCAN_USBBUS11 = 0x50B; - /// - /// PCAN-USB interface, channel 12 - /// - static const TPCANHandle PCAN_USBBUS12 = 0x50C; - /// - /// PCAN-USB interface, channel 13 - /// - static const TPCANHandle PCAN_USBBUS13 = 0x50D; - /// - /// PCAN-USB interface, channel 14 - /// - static const TPCANHandle PCAN_USBBUS14 = 0x50E; - /// - /// PCAN-USB interface, channel 15 - /// - static const TPCANHandle PCAN_USBBUS15 = 0x50F; - /// - /// PCAN-USB interface, channel 16 - /// - static const TPCANHandle PCAN_USBBUS16 = 0x510; - - /// - /// PCAN-PC Card interface, channel 1 - /// - static const TPCANHandle PCAN_PCCBUS1 = 0x61; - /// - /// PCAN-PC Card interface, channel 2 - /// - static const TPCANHandle PCAN_PCCBUS2 = 0x62; - - /// - /// PCAN-LAN interface, channel 1 - /// - static const TPCANHandle PCAN_LANBUS1 = 0x801; - /// - /// PCAN-LAN interface, channel 2 - /// - static const TPCANHandle PCAN_LANBUS2 = 0x802; - /// - /// PCAN-LAN interface, channel 3 - /// - static const TPCANHandle PCAN_LANBUS3 = 0x803; - /// - /// PCAN-LAN interface, channel 4 - /// - static const TPCANHandle PCAN_LANBUS4 = 0x804; - /// - /// PCAN-LAN interface, channel 5 - /// - static const TPCANHandle PCAN_LANBUS5 = 0x805; - /// - /// PCAN-LAN interface, channel 6 - /// - static const TPCANHandle PCAN_LANBUS6 = 0x806; - /// - /// PCAN-LAN interface, channel 7 - /// - static const TPCANHandle PCAN_LANBUS7 = 0x807; - /// - /// PCAN-LAN interface, channel 8 - /// - static const TPCANHandle PCAN_LANBUS8 = 0x808; - /// - /// PCAN-LAN interface, channel 9 - /// - static const TPCANHandle PCAN_LANBUS9 = 0x809; - /// - /// PCAN-LAN interface, channel 10 - /// - static const TPCANHandle PCAN_LANBUS10 = 0x80A; - /// - /// PCAN-LAN interface, channel 11 - /// - static const TPCANHandle PCAN_LANBUS11 = 0x80B; - /// - /// PCAN-LAN interface, channel 12 - /// - static const TPCANHandle PCAN_LANBUS12 = 0x80C; - /// - /// PCAN-LAN interface, channel 13 - /// - static const TPCANHandle PCAN_LANBUS13 = 0x80D; - /// - /// PCAN-LAN interface, channel 14 - /// - static const TPCANHandle PCAN_LANBUS14 = 0x80E; - /// - /// PCAN-LAN interface, channel 15 - /// - static const TPCANHandle PCAN_LANBUS15 = 0x80F; - /// - /// PCAN-LAN interface, channel 16 - /// - static const TPCANHandle PCAN_LANBUS16 = 0x810; - #pragma endregion - - #pragma region FD Bit rate definition - /// - /// Clock frequency in Herz (80000000, 60000000, 40000000, 30000000, 24000000, 20000000) - /// - static const String^ PCAN_BR_CLOCK = "f_clock"; - /// - /// Clock frequency in Megaherz (80, 60, 40, 30, 24, 20) - /// - static const String^ PCAN_BR_CLOCK_MHZ = "f_clock_mhz"; - /// - /// Clock prescaler for nominal time quantum - /// - static const String^ PCAN_BR_NOM_BRP = "nom_brp"; - /// - /// TSEG1 segment for nominal bit rate in time quanta - /// - static const String^ PCAN_BR_NOM_TSEG1 = "nom_tseg1"; - /// - /// TSEG2 segment for nominal bit rate in time quanta - /// - static const String^ PCAN_BR_NOM_TSEG2 = "nom_tseg2"; - /// - /// Synchronization Jump Width for nominal bit rate in time quanta - /// - static const String^ PCAN_BR_NOM_SJW = "nom_sjw"; - /// - /// Sample point for nominal bit rate - /// - static const String^ PCAN_BR_NOM_SAMPLE = "nom_sam"; - /// - /// Clock prescaler for highspeed data time quantum - /// - static const String^ PCAN_BR_DATA_BRP = "data_brp"; - /// - /// TSEG1 segment for fast data bit rate in time quanta - /// - static const String^ PCAN_BR_DATA_TSEG1 = "data_tseg1"; - /// - /// TSEG2 segment for fast data bit rate in time quanta - /// - static const String^ PCAN_BR_DATA_TSEG2 = "data_tseg2"; - /// - /// Synchronization Jump Width for highspeed data bit rate in time quanta - /// - static const String^ PCAN_BR_DATA_SJW = "data_sjw"; - /// - /// Secondary sample point delay for highspeed data bit rate in cyles - /// - static const String^ PCAN_BR_DATA_SAMPLE = "data_ssp_offset"; - #pragma endregion - - #pragma region Parameter values definition - /// - /// The PCAN parameter is not set (inactive) - /// - static const int PCAN_PARAMETER_OFF = 0; - /// - /// The PCAN parameter is set (active) - /// - static const int PCAN_PARAMETER_ON = 1; - /// - /// The PCAN filter is closed. No messages will be received - /// - static const int PCAN_FILTER_CLOSE = 0; - /// - /// The PCAN filter is fully opened. All messages will be received - /// - static const int PCAN_FILTER_OPEN = 1; - /// - /// The PCAN filter is custom configured. Only registered - /// messages will be received - /// - static const int PCAN_FILTER_CUSTOM = 2; - /// - /// The PCAN-Channel handle is illegal, or its associated hardware is not available - /// - static const int PCAN_CHANNEL_UNAVAILABLE = 0; - /// - /// The PCAN-Channel handle is available to be connected (PnP Hardware: it means furthermore that the hardware is plugged-in) - /// - static const int PCAN_CHANNEL_AVAILABLE = 1; - /// - /// The PCAN-Channel handle is valid, and is already being used - /// - static const int PCAN_CHANNEL_OCCUPIED = 2; - /// - /// The PCAN-Channel handle is already being used by a PCAN-View application, but is available to connect - /// - static const int PCAN_CHANNEL_PCANVIEW = PCAN_CHANNEL_AVAILABLE | PCAN_CHANNEL_OCCUPIED; - - /// - /// Logs system exceptions / errors - /// - static const int LOG_FUNCTION_DEFAULT = 0x00; - /// - /// Logs the entries to the PCAN-Basic API functions - /// - static const int LOG_FUNCTION_ENTRY = 0x01; - /// - /// Logs the parameters passed to the PCAN-Basic API functions - /// - static const int LOG_FUNCTION_PARAMETERS = 0x02; - /// - /// Logs the exits from the PCAN-Basic API functions - /// - static const int LOG_FUNCTION_LEAVE = 0x04; - /// - /// Logs the CAN messages passed to the CAN_Write function - /// - static const int LOG_FUNCTION_WRITE = 0x08; - /// - /// Logs the CAN messages received within the CAN_Read function - /// - static const int LOG_FUNCTION_READ = 0x10; - /// - /// Logs all possible information within the PCAN-Basic API functions - /// - static const int LOG_FUNCTION_ALL = 0xFFFF; - - /// - /// A single file is written until it size reaches PAN_TRACE_SIZE - /// - static const int TRACE_FILE_SINGLE = 0x00; - /// - /// Traced data is distributed in several files with size PAN_TRACE_SIZE - /// - static const int TRACE_FILE_SEGMENTED = 0x01; - /// - /// Includes the date into the name of the trace file - /// - static const int TRACE_FILE_DATE = 0x02; - /// - /// Includes the start time into the name of the trace file - /// - static const int TRACE_FILE_TIME = 0x04; - /// - /// Causes the overwriting of available traces (same name) - /// - static const int TRACE_FILE_OVERWRITE = 0x80; - - /// - /// Device supports flexible data-rate (CAN-FD) - /// - static const int FEATURE_FD_CAPABLE = 0x01; - /// - /// Device supports a delay between sending frames (FPGA based USB devices) - /// - static const int FEATURE_DELAY_CAPABLE = 0x02; - /// - /// Device supports I/O functionality for electronic circuits (USB-Chip devices) - /// - static const int FEATURE_IO_CAPABLE = 0x04; - - /// The service is not running - /// - /// - static const int SERVICE_STATUS_STOPPED = 0x01; - /// - /// The service is running - /// - static const int SERVICE_STATUS_RUNNING = 0x04; - #pragma endregion - - #pragma region Lookup Parameters - /// - /// Lookup channel by Device type (see PCAN devices e.g. PCAN_USB) - /// - static const String^ LOOKUP_DEVICE_TYPE = "devicetype"; - /// - /// Lookup channel by device id - /// - static const String^ LOOKUP_DEVICE_ID = "deviceid"; - /// - /// Lookup channel by CAN controller 0-based index - /// - static const String^ LOOKUP_CONTROLLER_NUMBER = "controllernumber"; - /// - /// Lookup channel by IP address (LAN channels only) - /// - static const String^ LOOKUP_IP_ADDRESS = "ipaddress"; - #pragma endregion - - #pragma region PCANBasic API Implementation - /// - /// Initializes a PCAN Channel - /// - /// The handle of a PCAN Channel - /// The speed for the communication (BTR0BTR1 code) - /// Non-PnP: The type of hardware and operation mode - /// Non-PnP: The I/O address for the parallel port - /// Non-PnP: Interrupt number of the parallel por - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_Initialize")] - static TPCANStatus Initialize( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - [MarshalAs(UnmanagedType::U2)] - TPCANBaudrate Btr0Btr1, - [MarshalAs(UnmanagedType::U1)] - TPCANType HwType, - UInt32 IOPort, - UInt16 Interrupt); - - /// - /// Initializes a PCAN Channel - /// - /// The handle of a PCAN Channel - /// The speed for the communication (BTR0BTR1 code) - /// A TPCANStatus error code - static TPCANStatus Initialize( - TPCANHandle Channel, - TPCANBaudrate Btr0Btr1) - { - return Initialize(Channel, Btr0Btr1, (TPCANType)0, 0, 0); - } - - /// - /// Initializes a FD capable PCAN Channel - /// - /// The handle of a FD capable PCAN Channel - /// The speed for the communication (FD bit rate string) - /// See PCAN_BR_* values - /// Bit rate string must follow the following construction rules: - /// * parameter and values must be separated by '=' - /// * Couples of Parameter/value must be separated by ',' - /// * Following Parameter must be filled out: f_clock, data_brp, data_sjw, data_tseg1, data_tseg2, - /// nom_brp, nom_sjw, nom_tseg1, nom_tseg2. - /// * Following Parameters are optional (not used yet): data_ssp_offset, nom_sam - /// f_clock=80000000,nom_brp=10,nom_tseg1=5,nom_tseg2=2,nom_sjw=1,data_brp=4,data_tseg1=7,data_tseg2=2,data_sjw=1 - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_InitializeFD")] - static TPCANStatus InitializeFD( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - TPCANBitrateFD BitrateFD); - - /// - /// Uninitializes one or all PCAN Channels initialized by CAN_Initialize - /// - /// Giving the TPCANHandle value "PCAN_NONEBUS", - /// uninitialize all initialized channels - /// The handle of a PCAN Channel - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_Uninitialize")] - static TPCANStatus Uninitialize( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel); - - /// - /// Resets the receive and transmit queues of the PCAN Channel - /// - /// A reset of the CAN controller is not performed - /// The handle of a PCAN Channel - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_Reset")] - static TPCANStatus Reset( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel); - - /// - /// Gets the current status of a PCAN Channel - /// - /// The handle of a PCAN Channel - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_GetStatus")] - static TPCANStatus GetStatus( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel); - - /// - /// Reads a CAN message from the receive queue of a PCAN Channel - /// - /// The handle of a PCAN Channel - /// A TPCANMsg structure buffer to store the CAN message - /// A TPCANTimestamp structure buffer to get - /// the reception time of the message - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_Read")] - static TPCANStatus Read( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - TPCANMsg %MessageBuffer, - TPCANTimestamp %TimestampBuffer); - - private: - [DllImport("PCANBasic.dll", EntryPoint = "CAN_Read")] - static TPCANStatus Read( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - TPCANMsg %MessageBuffer, - IntPtr bufferPointer); - - public: - /// - /// Reads a CAN message from the receive queue of a PCAN Channel - /// - /// The handle of a PCAN Channel - /// A TPCANMsg structure buffer to store the CAN message - /// A TPCANStatus error code - static TPCANStatus Read( - TPCANHandle Channel, - TPCANMsg %MessageBuffer) - { - return Read(Channel, MessageBuffer, IntPtr::Zero); - } - - /// - /// Reads a CAN message from the receive queue of a FD capable PCAN Channel - /// - /// The handle of a FD capable PCAN Channel - /// A TPCANMsgFD structure buffer to store the CAN message - /// A TPCANTimestampFD buffer to get the - /// reception time of the message - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_ReadFD")] - static TPCANStatus ReadFD( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - TPCANMsgFD %MessageBuffer, - TPCANTimestampFD %TimestampBuffer); - - private: - [DllImport("PCANBasic.dll", EntryPoint = "CAN_ReadFD")] - static TPCANStatus ReadFD( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - TPCANMsgFD %MessageBuffer, - IntPtr bufferPointer); - - public: - /// - /// Reads a CAN message from the receive queue of a FD capable PCAN Channel - /// - /// The handle of a FD capable PCAN Channel - /// A TPCANMsgFD structure buffer to store the CAN message - /// A TPCANTimestampFD buffer to get the - /// reception time of the message - /// A TPCANStatus error code - static TPCANStatus ReadFD( - TPCANHandle Channel, - TPCANMsgFD %MessageBuffer) - { - return ReadFD(Channel, MessageBuffer, IntPtr::Zero); - } - - /// - /// Transmits a CAN message - /// - /// The handle of a PCAN Channel - /// A TPCANMsg buffer with the message to be sent - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_Write")] - static TPCANStatus Write( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - TPCANMsg %MessageBuffer); - - /// - /// Transmits a CAN message over a FD capable PCAN Channel - /// - /// The handle of a FD capable PCAN Channel - /// A TPCANMsgFD buffer with the message to be sent - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_WriteFD")] - static TPCANStatus WriteFD( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - TPCANMsgFD %MessageBuffer); - - /// - /// Configures the reception filter - /// - /// The message filter will be expanded with every call to - /// this function. If it is desired to reset the filter, please use - /// the 'SetValue' function - /// The handle of a PCAN Channel - /// The lowest CAN ID to be received - /// The highest CAN ID to be received - /// Message type, Standard (11-bit identifier) or - /// Extended (29-bit identifier) - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_FilterMessages")] - static TPCANStatus FilterMessages( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - UInt32 FromID, - UInt32 ToID, - [MarshalAs(UnmanagedType::U1)] - TPCANMode Mode); - - /// - /// Retrieves a PCAN Channel value - /// - /// Parameters can be present or not according with the kind - /// of Hardware (PCAN Channel) being used. If a parameter is not available, - /// a PCAN_ERROR_ILLPARAMTYPE error will be returned - /// The handle of a PCAN Channel - /// The TPCANParameter parameter to get - /// Buffer for the parameter value - /// Size in bytes of the buffer - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_GetValue")] - static TPCANStatus GetValue( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - [MarshalAs(UnmanagedType::U1)] - TPCANParameter Parameter, - StringBuilder^ StringBuffer, - UInt32 BufferLength); - - /// - /// Retrieves a PCAN Channel value - /// - /// Parameters can be present or not according with the kind - /// of Hardware (PCAN Channel) being used. If a parameter is not available, - /// a PCAN_ERROR_ILLPARAMTYPE error will be returned - /// The handle of a PCAN Channel - /// The TPCANParameter parameter to get - /// Buffer for the parameter value - /// Size in bytes of the buffer - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_GetValue")] - static TPCANStatus GetValue( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - [MarshalAs(UnmanagedType::U1)] - TPCANParameter Parameter, - UInt32 %NumericBuffer, - UInt32 BufferLength); - - /// - /// Retrieves a PCAN Channel value - /// - /// Parameters can be present or not according with the kind - /// of Hardware (PCAN Channel) being used. If a parameter is not available, - /// a PCAN_ERROR_ILLPARAMTYPE error will be returned - /// The handle of a PCAN Channel - /// The TPCANParameter parameter to get - /// Buffer for the parameter value - /// Size in bytes of the buffer - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_GetValue")] - static TPCANStatus GetValue( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - [MarshalAs(UnmanagedType::U1)] - TPCANParameter Parameter, - UInt64 %NumericBuffer, - UInt32 BufferLength); - - private: - [DllImport("PCANBasic.dll", EntryPoint = "CAN_GetValue")] - static TPCANStatus GetValue( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - [MarshalAs(UnmanagedType::U1)] - TPCANParameter Parameter, - [MarshalAs(UnmanagedType::LPArray, SizeParamIndex=3)] - [In, Out]array ^ChannelBuffer, - UInt32 BufferLength); - public: - /// - /// Retrieves a PCAN Channel value - /// - /// Parameters can be present or not according with the kind - /// of Hardware (PCAN Channel) being used. If a parameter is not available, - /// a PCAN_ERROR_ILLPARAMTYPE error will be returned - /// The handle of a PCAN Channel - /// The TPCANParameter parameter to get - /// Buffer for the parameter value - /// A TPCANStatus error code - static TPCANStatus GetValue( - TPCANHandle Channel, - TPCANParameter Parameter, - array ^ChannelsBuffer) - { - if(ChannelsBuffer == nullptr) - return TPCANStatus::PCAN_ERROR_ILLPARAMVAL; - return GetValue(Channel, Parameter, ChannelsBuffer, ChannelsBuffer->Length * Marshal::SizeOf(TPCANChannelInformation::typeid)); - } - - /// - /// Configures a PCAN Channel value - /// - /// Parameters can be present or not according with the kind - /// of Hardware (PCAN Channel) being used. If a parameter is not available, - /// a PCAN_ERROR_ILLPARAMTYPE error will be returned - /// The handle of a PCAN Channel - /// The TPCANParameter parameter to set - /// Buffer with the value to be set - /// Size in bytes of the buffer - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_SetValue")] - static TPCANStatus SetValue( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - [MarshalAs(UnmanagedType::U1)] - TPCANParameter Parameter, - UInt32% NumericBuffer, - UInt32 BufferLength); - - /// - /// Configures a PCAN Channel value - /// - /// Parameters can be present or not according with the kind - /// of Hardware (PCAN Channel) being used. If a parameter is not available, - /// a PCAN_ERROR_ILLPARAMTYPE error will be returned - /// The handle of a PCAN Channel - /// The TPCANParameter parameter to set - /// Buffer with the value to be set - /// Size in bytes of the buffer - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_SetValue")] - static TPCANStatus SetValue( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - [MarshalAs(UnmanagedType::U1)] - TPCANParameter Parameter, - UInt64% NumericBuffer, - UInt32 BufferLength); - - /// - /// Configures a PCAN Channel value - /// - /// Parameters can be present or not according with the kind - /// of Hardware (PCAN Channel) being used. If a parameter is not available, - /// a PCAN_ERROR_ILLPARAMTYPE error will be returned - /// The handle of a PCAN Channel - /// - /// Buffer with the value to be set - /// Size in bytes of the buffer - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_SetValue")] - static TPCANStatus SetValue( - [MarshalAs(UnmanagedType::U2)] - TPCANHandle Channel, - [MarshalAs(UnmanagedType::U1)] - TPCANParameter Parameter, - [MarshalAs(UnmanagedType::LPStr,SizeParamIndex=3)] - String^ StringBuffer, - UInt32 BufferLength); - - /// - /// Returns a descriptive text of a given TPCANStatus error - /// code, in any desired language - /// - /// The current languages available for translation are: - /// Neutral (0x00), German (0x07), English (0x09), Spanish (0x0A), - /// Italian (0x10) and French (0x0C) - /// A TPCANStatus error code - /// Indicates a 'Primary language ID' - /// Buffer for the text (must be at least 256 in length) - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_GetErrorText")] - static TPCANStatus GetErrorText( - [MarshalAs(UnmanagedType::U4)] - TPCANStatus Error, - UInt16 Language, - StringBuilder^ StringBuffer); - - /// - /// Finds a PCAN-Basic channel that matches with the given parameters - /// - /// A comma separated string contained pairs of - /// parameter-name/value to be matched within a PCAN-Basic channel - /// Buffer for returning the PCAN-Basic channel, - /// when found - /// A TPCANStatus error code - [DllImport("PCANBasic.dll", EntryPoint = "CAN_LookUpChannel")] - static TPCANStatus LookUpChannel( - String^ Parameters, - TPCANHandle% FoundChannel); - #pragma endregion - }; - #pragma endregion - } - } +// PCANBasicCLR.h +// +// ~~~~~~~~~~~~ +// +// PCAN-Basic API +// +// ~~~~~~~~~~~~ +// +// ------------------------------------------------------------------ +// Author : Keneth Wagner +// Last change: 2022-07-06 +// +// Language: C++/CLR +// ------------------------------------------------------------------ +// +// Copyright (C) 1999-2022 PEAK-System Technik GmbH, Darmstadt +// more Info at http://www.peak-system.com +// +using namespace System; +using namespace System::Text; +using namespace System::Runtime::InteropServices; + +//////////////////////////////////////////////////////////// +// Type definitions +//////////////////////////////////////////////////////////// +#define TPCANHandle System::UInt16 // Represents a PCAN hardware channel handle +#define TPCANBitrateFD System::String^ // Represents a bit rate String (Flexible Data rate) +#define TPCANTimestampFD System::UInt64 // Represents a timestamp in microseconds + +namespace Peak +{ + namespace Can + { + namespace Basic + { + #pragma region Other Constants + /// + /// Maximum length of the name of a device: 32 characters + terminator + /// + static const int MAX_LENGTH_HARDWARE_NAME = 33; + /// + /// Maximum length of a version string: 255 characters + terminator + /// + static const int MAX_LENGTH_VERSION_STRING = 256; + #pragma endregion + + #pragma region Enumerations + /// + /// Represents a PCAN status/error code + /// + [Flags] + public enum class TPCANStatus : UInt32 + { + /// + /// No error + /// + PCAN_ERROR_OK = 0x00000, + /// + /// Transmit buffer in CAN controller is full + /// + PCAN_ERROR_XMTFULL = 0x00001, + /// + /// CAN controller was read too late + /// + PCAN_ERROR_OVERRUN = 0x00002, + /// + /// Bus error: an error counter reached the 'light' limit + /// + PCAN_ERROR_BUSLIGHT = 0x00004, + /// + /// Bus error: an error counter reached the 'heavy' limit + /// + PCAN_ERROR_BUSHEAVY = 0x00008, + /// + /// Bus error: an error counter reached the 'warning' limit + /// + PCAN_ERROR_BUSWARNING = PCAN_ERROR_BUSHEAVY, + /// + /// Bus error: the CAN controller is error passive + /// + PCAN_ERROR_BUSPASSIVE = 0x40000, + /// + /// Bus error: the CAN controller is in bus-off state + /// + PCAN_ERROR_BUSOFF = 0x00010, + /// + /// Mask for all bus errors + /// + PCAN_ERROR_ANYBUSERR = (PCAN_ERROR_BUSWARNING | PCAN_ERROR_BUSLIGHT | PCAN_ERROR_BUSHEAVY | PCAN_ERROR_BUSOFF | PCAN_ERROR_BUSPASSIVE), + /// + /// Receive queue is empty + /// + PCAN_ERROR_QRCVEMPTY = 0x00020, + /// + /// Receive queue was read too late + /// + PCAN_ERROR_QOVERRUN = 0x00040, + /// + /// Transmit queue is full + /// + PCAN_ERROR_QXMTFULL = 0x00080, + /// + /// Test of the CAN controller hardware registers failed (no hardware found) + /// + PCAN_ERROR_REGTEST = 0x00100, + /// + /// Driver not loaded + /// + PCAN_ERROR_NODRIVER = 0x00200, + /// + /// Hardware already in use by a Net + /// + PCAN_ERROR_HWINUSE = 0x00400, + /// + /// A Client is already connected to the Net + /// + PCAN_ERROR_NETINUSE = 0x00800, + /// + /// Hardware handle is invalid + /// + PCAN_ERROR_ILLHW = 0x01400, + /// + /// Net handle is invalid + /// + PCAN_ERROR_ILLNET = 0x01800, + /// + /// Client handle is invalid + /// + PCAN_ERROR_ILLCLIENT = 0x01C00, + /// + /// Mask for all handle errors + /// + PCAN_ERROR_ILLHANDLE = (PCAN_ERROR_ILLHW | PCAN_ERROR_ILLNET | PCAN_ERROR_ILLCLIENT), + /// + /// Resource (FIFO, Client, timeout) cannot be created + /// + PCAN_ERROR_RESOURCE = 0x02000, + /// + /// Invalid parameter + /// + PCAN_ERROR_ILLPARAMTYPE = 0x04000, + /// + /// Invalid parameter value + /// + PCAN_ERROR_ILLPARAMVAL = 0x08000, + /// + /// Unknown error + /// + PCAN_ERROR_UNKNOWN = 0x10000, + /// + /// Invalid data, function, or action. + /// + PCAN_ERROR_ILLDATA = 0x20000, + /// + /// Driver object state is wrong for the attempted operation + /// + PCAN_ERROR_ILLMODE = 0x80000, + /// + /// An operation was successfully carried out, however, irregularities were registered + /// + PCAN_ERROR_CAUTION = 0x2000000, + /// + /// Channel is not initialized + /// Value was changed from 0x40000 to 0x4000000 + /// + PCAN_ERROR_INITIALIZE = 0x4000000, + /// + /// Invalid operation + /// Value was changed from 0x80000 to 0x8000000 + /// + PCAN_ERROR_ILLOPERATION = 0x8000000, + }; + + /// + /// Represents a PCAN device + /// + public enum class TPCANDevice : Byte + { + /// + /// Undefined, unknown or not selected PCAN device value + /// + PCAN_NONE = 0, + /// + /// PCAN Non-PnP devices. NOT USED WITHIN PCAN-Basic API + /// + PCAN_PEAKCAN = 1, + /// + /// PCAN-ISA, PCAN-PC/104, and PCAN-PC/104-Plus + /// + PCAN_ISA = 2, + /// + /// PCAN-Dongle + /// + PCAN_DNG = 3, + /// + /// PCAN-PCI, PCAN-cPCI, PCAN-miniPCI, and PCAN-PCI Express + /// + PCAN_PCI = 4, + /// + /// PCAN-USB and PCAN-USB Pro + /// + PCAN_USB = 5, + /// + /// PCAN-PC Card + /// + PCAN_PCC = 6, + /// + /// PCAN Virtual hardware. NOT USED WITHIN PCAN-Basic API + /// + PCAN_VIRTUAL = 7, + /// + /// PCAN Gateway devices + /// + PCAN_LAN = 8 + }; + + /// + /// Represents a PCAN parameter to be read or set + /// + public enum class TPCANParameter : Byte + { + /// + /// Device identifier parameter + /// + PCAN_DEVICE_ID = 1, + /// + /// DEPRECATED. Use PCAN_DEVICE_ID instead + /// + [Obsolete] + PCAN_DEVICE_NUMBER = PCAN_DEVICE_ID, + /// + /// 5-Volt power parameter + /// + PCAN_5VOLTS_POWER = 2, + /// + /// PCAN receive event handler parameter + /// + PCAN_RECEIVE_EVENT = 3, + /// + /// PCAN message filter parameter + /// + PCAN_MESSAGE_FILTER = 4, + /// + /// PCAN-Basic API version parameter + /// + PCAN_API_VERSION = 5, + /// + /// PCAN device channel version parameter + /// + PCAN_CHANNEL_VERSION = 6, + /// + /// PCAN Reset-On-Busoff parameter + /// + PCAN_BUSOFF_AUTORESET = 7, + /// + /// PCAN Listen-Only parameter + /// + PCAN_LISTEN_ONLY = 8, + /// + /// Directory path for log files + /// + PCAN_LOG_LOCATION = 9, + /// + /// Debug-Log activation status + /// + PCAN_LOG_STATUS = 10, + /// + /// Configuration of the debugged information (LOG_FUNCTION_***) + /// + PCAN_LOG_CONFIGURE = 11, + /// + /// Custom insertion of text into the log file + /// + PCAN_LOG_TEXT = 12, + /// + /// Availability status of a PCAN-Channel + /// + PCAN_CHANNEL_CONDITION = 13, + /// + /// PCAN hardware name parameter + /// + PCAN_HARDWARE_NAME = 14, + /// + /// Message reception status of a PCAN-Channel + /// + PCAN_RECEIVE_STATUS = 15, + /// + /// CAN-Controller number of a PCAN-Channel + /// + PCAN_CONTROLLER_NUMBER = 16, + /// + /// Directory path for PCAN trace files + /// + PCAN_TRACE_LOCATION = 17, + /// + /// CAN tracing activation status + /// + PCAN_TRACE_STATUS = 18, + /// + /// Configuration of the maximum file size of a CAN trace + /// + PCAN_TRACE_SIZE = 19, + /// + /// Configuration of the trace file storing mode (TRACE_FILE_***) + /// + PCAN_TRACE_CONFIGURE = 20, + /// + /// Physical identification of a USB based PCAN-Channel by blinking its associated LED + /// + PCAN_CHANNEL_IDENTIFYING = 21, + /// + /// Capabilities of a PCAN device (FEATURE_***) + /// + PCAN_CHANNEL_FEATURES = 22, + /// + /// Using of an existing bit rate (PCAN-View connected to a channel) + /// + PCAN_BITRATE_ADAPTING = 23, + /// + /// Configured bit rate as Btr0Btr1 value + /// + PCAN_BITRATE_INFO = 24, + /// + /// Configured bit rate as TPCANBitrateFD string + /// + PCAN_BITRATE_INFO_FD = 25, + /// + /// Configured nominal CAN Bus speed as Bits per seconds + /// + PCAN_BUSSPEED_NOMINAL = 26, + /// + /// Configured CAN data speed as Bits per seconds + /// + PCAN_BUSSPEED_DATA = 27, + /// + /// Remote address of a LAN channel as string in IPv4 format + /// + PCAN_IP_ADDRESS = 28, + /// + /// Status of the Virtual PCAN-Gateway Service + /// + PCAN_LAN_SERVICE_STATUS = 29, + /// + /// Status messages reception status within a PCAN-Channel + /// + PCAN_ALLOW_STATUS_FRAMES = 30, + /// + /// RTR messages reception status within a PCAN-Channel + /// + PCAN_ALLOW_RTR_FRAMES = 31, + /// + /// Error messages reception status within a PCAN-Channel + /// + PCAN_ALLOW_ERROR_FRAMES = 32, + /// + /// Delay, in microseconds, between sending frames + /// + PCAN_INTERFRAME_DELAY = 33, + /// + /// Filter over code and mask patterns for 11-Bit messages + /// + PCAN_ACCEPTANCE_FILTER_11BIT = 34, + /// + /// Filter over code and mask patterns for 29-Bit messages + /// + PCAN_ACCEPTANCE_FILTER_29BIT = 35, + /// + /// Output mode of 32 digital I/O pin of a PCAN-USB Chip. 1: Output-Active 0 : Output Inactive + /// + PCAN_IO_DIGITAL_CONFIGURATION = 36, + /// + /// Value assigned to a 32 digital I/O pins of a PCAN-USB Chip + /// + PCAN_IO_DIGITAL_VALUE = 37, + /// + /// Value assigned to a 32 digital I/O pins of a PCAN-USB Chip - Multiple digital I/O pins to 1 = High + /// + PCAN_IO_DIGITAL_SET = 38, + /// + /// Clear multiple digital I/O pins to 0 + /// + PCAN_IO_DIGITAL_CLEAR = 39, + /// + /// Get value of a single analog input pin + /// + PCAN_IO_ANALOG_VALUE = 40, + /// + /// Get the version of the firmware used by the device associated with a PCAN-Channel + /// + PCAN_FIRMWARE_VERSION = 41, + /// + /// Get the amount of PCAN channels attached to a system + /// + PCAN_ATTACHED_CHANNELS_COUNT = 42, + /// + /// Get information about PCAN channels attached to a system + /// + PCAN_ATTACHED_CHANNELS = 43, + /// + /// Echo messages reception status within a PCAN-Channel + /// + PCAN_ALLOW_ECHO_FRAMES = 44, + /// + /// Get the part number associated to a device + /// + PCAN_DEVICE_PART_NUMBER = 45, + }; + + /// Represents the type of a PCAN message + /// + [Flags] + public enum class TPCANMessageType : Byte + { + /// + /// The PCAN message is a CAN Standard Frame (11-bit identifier) + /// + PCAN_MESSAGE_STANDARD = 0x00, + /// + /// The PCAN message is a CAN Remote-Transfer-Request Frame + /// + PCAN_MESSAGE_RTR = 0x01, + /// + /// The PCAN message is a CAN Extended Frame (29-bit identifier) + /// + PCAN_MESSAGE_EXTENDED = 0x02, + /// + /// The PCAN message represents a FD frame in terms of CiA Specs + /// + PCAN_MESSAGE_FD = 0x04, + /// + /// The PCAN message represents a FD bit rate switch (CAN data at a higher bit rate) + /// + PCAN_MESSAGE_BRS = 0x08, + /// + /// The PCAN message represents a FD error state indicator(CAN FD transmitter was error active) + /// + PCAN_MESSAGE_ESI = 0x10, + /// + /// The PCAN message represents an echo CAN Frame + /// + PCAN_MESSAGE_ECHO = 0x20, + /// + /// The PCAN message represents an error frame + /// + PCAN_MESSAGE_ERRFRAME = 0x40, + /// + /// The PCAN message represents a PCAN status message + /// + /// + PCAN_MESSAGE_STATUS = 0x80, + }; + + /// + /// Represents a PCAN filter mode + /// + public enum class TPCANMode : Byte + { + /// + /// Mode is Standard (11-bit identifier) + /// + PCAN_MODE_STANDARD = TPCANMessageType::PCAN_MESSAGE_STANDARD, + /// + /// Mode is Extended (29-bit identifier) + /// + PCAN_MODE_EXTENDED = TPCANMessageType::PCAN_MESSAGE_EXTENDED, + }; + + /// + /// Represents a PCAN Baud rate register value + /// + public enum class TPCANBaudrate : UInt16 + { + /// + /// 1 MBit/s + /// + PCAN_BAUD_1M = 0x0014, + /// + /// 800 kBit/s + /// + PCAN_BAUD_800K = 0x0016, + /// + /// 500 kBit/s + /// + PCAN_BAUD_500K = 0x001C, + /// + /// 250 kBit/s + /// + PCAN_BAUD_250K = 0x011C, + /// + /// 125 kBit/s + /// + PCAN_BAUD_125K = 0x031C, + /// + /// 100 kBit/s + /// + PCAN_BAUD_100K = 0x432F, + /// + /// 95,238 kBit/s + /// + PCAN_BAUD_95K = 0xC34E, + /// + /// 83,333 kBit/s + /// + PCAN_BAUD_83K = 0x852B, + /// + /// 50 kBit/s + /// + PCAN_BAUD_50K = 0x472F, + /// + /// 47,619 kBit/s + /// + PCAN_BAUD_47K = 0x1414, + /// + /// 33,333 kBit/s + /// + PCAN_BAUD_33K = 0x8B2F, + /// + /// 20 kBit/s + /// + PCAN_BAUD_20K = 0x532F, + /// + /// 10 kBit/s + /// + PCAN_BAUD_10K = 0x672F, + /// + /// 5 kBit/s + /// + PCAN_BAUD_5K = 0x7F7F, + }; + + /// + /// Represents the type of PCAN (Non-PnP) hardware to be initialized + /// + public enum class TPCANType : Byte + { + /// + /// PCAN-ISA 82C200 + /// + PCAN_TYPE_ISA = 0x01, + /// + /// PCAN-ISA SJA1000 + /// + PCAN_TYPE_ISA_SJA = 0x09, + /// + /// PHYTEC ISA + /// + PCAN_TYPE_ISA_PHYTEC = 0x04, + /// + /// PCAN-Dongle 82C200 + /// + PCAN_TYPE_DNG = 0x02, + /// + /// PCAN-Dongle EPP 82C200 + /// + PCAN_TYPE_DNG_EPP = 0x03, + /// + /// PCAN-Dongle SJA1000 + /// + PCAN_TYPE_DNG_SJA = 0x05, + /// + /// PCAN-Dongle EPP SJA1000 + /// + PCAN_TYPE_DNG_SJA_EPP = 0x06, + }; + #pragma endregion + + #pragma region Strutures + /// + /// Represents a PCAN message + /// + public value struct TPCANMsg + { + /// + /// 11/29-bit message identifier + /// + UInt32 ID; + /// + /// Type of the message + /// + [MarshalAs(UnmanagedType::U1)] + TPCANMessageType MSGTYPE; + /// + /// Data Length Code of the message (0..8) + /// + Byte LEN; + /// + /// Data of the message (DATA[0]..DATA[7]) + /// + [MarshalAs(UnmanagedType::ByValArray, SizeConst = 8)] + array^ DATA; + }; + + /// + /// Represents a timestamp of a received PCAN message. + /// Total Microseconds = micros + 1000 * millis + 0x100000000 * 1000 * millis_overflow + /// + public value struct TPCANTimestamp + { + /// + /// Base-value: milliseconds: 0.. 2^32-1 + /// + UInt32 millis; + /// + /// Roll-arounds of millis + /// + UInt16 millis_overflow; + /// + /// Microseconds: 0..999 + /// + UInt16 micros; + }; + + /// + /// Represents a PCAN message from a FD capable hardware + /// + public value struct TPCANMsgFD + { + /// + /// 11/29-bit message identifier + /// + UInt32 ID; + /// + /// Type of the message + /// + [MarshalAs(UnmanagedType::U1)] + TPCANMessageType MSGTYPE; + /// + /// Data Length Code of the message (0..15) + /// + Byte DLC; + /// + /// Data of the message (DATA[0]..DATA[63]) + /// + [MarshalAs(UnmanagedType::ByValArray, SizeConst = 64)] + array^ DATA; + }; + + /// + /// Describes an available PCAN channel + /// + public value struct TPCANChannelInformation + { + /// + /// PCAN channel handle + /// + [MarshalAs(UnmanagedType::U2)] + TPCANHandle channel_handle; + /// + /// Kind of PCAN device + /// + [MarshalAs(UnmanagedType::U1)] + TPCANDevice device_type; + /// + /// CAN-Controller number + /// + Byte controller_number; + /// + /// Device capabilities flag (see FEATURE_*) + /// + UInt32 device_features; + /// + /// Device name + /// + [MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_LENGTH_HARDWARE_NAME)] + String^ device_name; + /// + /// Device number + /// + UInt32 device_id; + /// + /// Availability status of a PCAN-Channel + /// + UInt32 channel_condition; + }; + #pragma endregion + + #pragma region PCANBasic class + /// + /// PCAN-Basic API class implementation + /// + public ref class PCANBasic abstract sealed + { + public: + #pragma region PCAN-BUS Handles Definition + /// + /// Undefined/default value for a PCAN bus + /// + static const TPCANHandle PCAN_NONEBUS = 0x00; + + /// + /// PCAN-ISA interface, channel 1 + /// + static const TPCANHandle PCAN_ISABUS1 = 0x21; + /// + /// PCAN-ISA interface, channel 2 + /// + static const TPCANHandle PCAN_ISABUS2 = 0x22; + /// + /// PCAN-ISA interface, channel 3 + /// + static const TPCANHandle PCAN_ISABUS3 = 0x23; + /// + /// PCAN-ISA interface, channel 4 + /// + static const TPCANHandle PCAN_ISABUS4 = 0x24; + /// + /// PCAN-ISA interface, channel 5 + /// + static const TPCANHandle PCAN_ISABUS5 = 0x25; + /// + /// PCAN-ISA interface, channel 6 + /// + static const TPCANHandle PCAN_ISABUS6 = 0x26; + /// + /// PCAN-ISA interface, channel 7 + /// + static const TPCANHandle PCAN_ISABUS7 = 0x27; + /// + /// PCAN-ISA interface, channel 8 + /// + static const TPCANHandle PCAN_ISABUS8 = 0x28; + + /// + /// PPCAN-Dongle/LPT interface, channel 1 + /// + static const TPCANHandle PCAN_DNGBUS1 = 0x31; + + /// + /// PCAN-PCI interface, channel 1 + /// + static const TPCANHandle PCAN_PCIBUS1 = 0x41; + /// + /// PCAN-PCI interface, channel 2 + /// + static const TPCANHandle PCAN_PCIBUS2 = 0x42; + /// + /// PCAN-PCI interface, channel 3 + /// + static const TPCANHandle PCAN_PCIBUS3 = 0x43; + /// + /// PCAN-PCI interface, channel 4 + /// + static const TPCANHandle PCAN_PCIBUS4 = 0x44; + /// + /// PCAN-PCI interface, channel 5 + /// + static const TPCANHandle PCAN_PCIBUS5 = 0x45; + /// + /// PCAN-PCI interface, channel 6 + /// + static const TPCANHandle PCAN_PCIBUS6 = 0x46; + /// + /// PCAN-PCI interface, channel 7 + /// + static const TPCANHandle PCAN_PCIBUS7 = 0x47; + /// + /// PCAN-PCI interface, channel 8 + /// + static const TPCANHandle PCAN_PCIBUS8 = 0x48; + /// + /// PCAN-PCI interface, channel 9 + /// + static const TPCANHandle PCAN_PCIBUS9 = 0x409; + /// + /// PCAN-PCI interface, channel 10 + /// + static const TPCANHandle PCAN_PCIBUS10 = 0x40A; + /// + /// PCAN-PCI interface, channel 11 + /// + static const TPCANHandle PCAN_PCIBUS11 = 0x40B; + /// + /// PCAN-PCI interface, channel 12 + /// + static const TPCANHandle PCAN_PCIBUS12 = 0x40C; + /// + /// PCAN-PCI interface, channel 13 + /// + static const TPCANHandle PCAN_PCIBUS13 = 0x40D; + /// + /// PCAN-PCI interface, channel 14 + /// + static const TPCANHandle PCAN_PCIBUS14 = 0x40E; + /// + /// PCAN-PCI interface, channel 15 + /// + static const TPCANHandle PCAN_PCIBUS15 = 0x40F; + /// + /// PCAN-PCI interface, channel 16 + /// + static const TPCANHandle PCAN_PCIBUS16 = 0x410; + + /// + /// PCAN-USB interface, channel 1 + /// + static const TPCANHandle PCAN_USBBUS1 = 0x51; + /// + /// PCAN-USB interface, channel 2 + /// + static const TPCANHandle PCAN_USBBUS2 = 0x52; + /// + /// PCAN-USB interface, channel 3 + /// + static const TPCANHandle PCAN_USBBUS3 = 0x53; + /// + /// PCAN-USB interface, channel 4 + /// + static const TPCANHandle PCAN_USBBUS4 = 0x54; + /// + /// PCAN-USB interface, channel 5 + /// + static const TPCANHandle PCAN_USBBUS5 = 0x55; + /// + /// PCAN-USB interface, channel 6 + /// + static const TPCANHandle PCAN_USBBUS6 = 0x56; + /// + /// PCAN-USB interface, channel 7 + /// + static const TPCANHandle PCAN_USBBUS7 = 0x57; + /// + /// PCAN-USB interface, channel 8 + /// + static const TPCANHandle PCAN_USBBUS8 = 0x58; + /// + /// PCAN-USB interface, channel 9 + /// + static const TPCANHandle PCAN_USBBUS9 = 0x509; + /// + /// PCAN-USB interface, channel 10 + /// + static const TPCANHandle PCAN_USBBUS10 = 0x50A; + /// + /// PCAN-USB interface, channel 11 + /// + static const TPCANHandle PCAN_USBBUS11 = 0x50B; + /// + /// PCAN-USB interface, channel 12 + /// + static const TPCANHandle PCAN_USBBUS12 = 0x50C; + /// + /// PCAN-USB interface, channel 13 + /// + static const TPCANHandle PCAN_USBBUS13 = 0x50D; + /// + /// PCAN-USB interface, channel 14 + /// + static const TPCANHandle PCAN_USBBUS14 = 0x50E; + /// + /// PCAN-USB interface, channel 15 + /// + static const TPCANHandle PCAN_USBBUS15 = 0x50F; + /// + /// PCAN-USB interface, channel 16 + /// + static const TPCANHandle PCAN_USBBUS16 = 0x510; + + /// + /// PCAN-PC Card interface, channel 1 + /// + static const TPCANHandle PCAN_PCCBUS1 = 0x61; + /// + /// PCAN-PC Card interface, channel 2 + /// + static const TPCANHandle PCAN_PCCBUS2 = 0x62; + + /// + /// PCAN-LAN interface, channel 1 + /// + static const TPCANHandle PCAN_LANBUS1 = 0x801; + /// + /// PCAN-LAN interface, channel 2 + /// + static const TPCANHandle PCAN_LANBUS2 = 0x802; + /// + /// PCAN-LAN interface, channel 3 + /// + static const TPCANHandle PCAN_LANBUS3 = 0x803; + /// + /// PCAN-LAN interface, channel 4 + /// + static const TPCANHandle PCAN_LANBUS4 = 0x804; + /// + /// PCAN-LAN interface, channel 5 + /// + static const TPCANHandle PCAN_LANBUS5 = 0x805; + /// + /// PCAN-LAN interface, channel 6 + /// + static const TPCANHandle PCAN_LANBUS6 = 0x806; + /// + /// PCAN-LAN interface, channel 7 + /// + static const TPCANHandle PCAN_LANBUS7 = 0x807; + /// + /// PCAN-LAN interface, channel 8 + /// + static const TPCANHandle PCAN_LANBUS8 = 0x808; + /// + /// PCAN-LAN interface, channel 9 + /// + static const TPCANHandle PCAN_LANBUS9 = 0x809; + /// + /// PCAN-LAN interface, channel 10 + /// + static const TPCANHandle PCAN_LANBUS10 = 0x80A; + /// + /// PCAN-LAN interface, channel 11 + /// + static const TPCANHandle PCAN_LANBUS11 = 0x80B; + /// + /// PCAN-LAN interface, channel 12 + /// + static const TPCANHandle PCAN_LANBUS12 = 0x80C; + /// + /// PCAN-LAN interface, channel 13 + /// + static const TPCANHandle PCAN_LANBUS13 = 0x80D; + /// + /// PCAN-LAN interface, channel 14 + /// + static const TPCANHandle PCAN_LANBUS14 = 0x80E; + /// + /// PCAN-LAN interface, channel 15 + /// + static const TPCANHandle PCAN_LANBUS15 = 0x80F; + /// + /// PCAN-LAN interface, channel 16 + /// + static const TPCANHandle PCAN_LANBUS16 = 0x810; + #pragma endregion + + #pragma region FD Bit rate definition + /// + /// Clock frequency in Herz (80000000, 60000000, 40000000, 30000000, 24000000, 20000000) + /// + static const String^ PCAN_BR_CLOCK = "f_clock"; + /// + /// Clock frequency in Megaherz (80, 60, 40, 30, 24, 20) + /// + static const String^ PCAN_BR_CLOCK_MHZ = "f_clock_mhz"; + /// + /// Clock prescaler for nominal time quantum + /// + static const String^ PCAN_BR_NOM_BRP = "nom_brp"; + /// + /// TSEG1 segment for nominal bit rate in time quanta + /// + static const String^ PCAN_BR_NOM_TSEG1 = "nom_tseg1"; + /// + /// TSEG2 segment for nominal bit rate in time quanta + /// + static const String^ PCAN_BR_NOM_TSEG2 = "nom_tseg2"; + /// + /// Synchronization Jump Width for nominal bit rate in time quanta + /// + static const String^ PCAN_BR_NOM_SJW = "nom_sjw"; + /// + /// Sample point for nominal bit rate + /// + static const String^ PCAN_BR_NOM_SAMPLE = "nom_sam"; + /// + /// Clock prescaler for highspeed data time quantum + /// + static const String^ PCAN_BR_DATA_BRP = "data_brp"; + /// + /// TSEG1 segment for fast data bit rate in time quanta + /// + static const String^ PCAN_BR_DATA_TSEG1 = "data_tseg1"; + /// + /// TSEG2 segment for fast data bit rate in time quanta + /// + static const String^ PCAN_BR_DATA_TSEG2 = "data_tseg2"; + /// + /// Synchronization Jump Width for highspeed data bit rate in time quanta + /// + static const String^ PCAN_BR_DATA_SJW = "data_sjw"; + /// + /// Secondary sample point delay for highspeed data bit rate in cyles + /// + static const String^ PCAN_BR_DATA_SAMPLE = "data_ssp_offset"; + #pragma endregion + + #pragma region Parameter values definition + /// + /// The PCAN parameter is not set (inactive) + /// + static const int PCAN_PARAMETER_OFF = 0; + /// + /// The PCAN parameter is set (active) + /// + static const int PCAN_PARAMETER_ON = 1; + /// + /// The PCAN filter is closed. No messages will be received + /// + static const int PCAN_FILTER_CLOSE = 0; + /// + /// The PCAN filter is fully opened. All messages will be received + /// + static const int PCAN_FILTER_OPEN = 1; + /// + /// The PCAN filter is custom configured. Only registered + /// messages will be received + /// + static const int PCAN_FILTER_CUSTOM = 2; + /// + /// The PCAN-Channel handle is illegal, or its associated hardware is not available + /// + static const int PCAN_CHANNEL_UNAVAILABLE = 0; + /// + /// The PCAN-Channel handle is available to be connected (PnP Hardware: it means furthermore that the hardware is plugged-in) + /// + static const int PCAN_CHANNEL_AVAILABLE = 1; + /// + /// The PCAN-Channel handle is valid, and is already being used + /// + static const int PCAN_CHANNEL_OCCUPIED = 2; + /// + /// The PCAN-Channel handle is already being used by a PCAN-View application, but is available to connect + /// + static const int PCAN_CHANNEL_PCANVIEW = PCAN_CHANNEL_AVAILABLE | PCAN_CHANNEL_OCCUPIED; + + /// + /// Logs system exceptions / errors + /// + static const int LOG_FUNCTION_DEFAULT = 0x00; + /// + /// Logs the entries to the PCAN-Basic API functions + /// + static const int LOG_FUNCTION_ENTRY = 0x01; + /// + /// Logs the parameters passed to the PCAN-Basic API functions + /// + static const int LOG_FUNCTION_PARAMETERS = 0x02; + /// + /// Logs the exits from the PCAN-Basic API functions + /// + static const int LOG_FUNCTION_LEAVE = 0x04; + /// + /// Logs the CAN messages passed to the CAN_Write function + /// + static const int LOG_FUNCTION_WRITE = 0x08; + /// + /// Logs the CAN messages received within the CAN_Read function + /// + static const int LOG_FUNCTION_READ = 0x10; + /// + /// Logs all possible information within the PCAN-Basic API functions + /// + static const int LOG_FUNCTION_ALL = 0xFFFF; + + /// + /// A single file is written until it size reaches PAN_TRACE_SIZE + /// + static const int TRACE_FILE_SINGLE = 0x00; + /// + /// Traced data is distributed in several files with size PAN_TRACE_SIZE + /// + static const int TRACE_FILE_SEGMENTED = 0x01; + /// + /// Includes the date into the name of the trace file + /// + static const int TRACE_FILE_DATE = 0x02; + /// + /// Includes the start time into the name of the trace file + /// + static const int TRACE_FILE_TIME = 0x04; + /// + /// Causes the overwriting of available traces (same name) + /// + static const int TRACE_FILE_OVERWRITE = 0x80; + + /// + /// Device supports flexible data-rate (CAN-FD) + /// + static const int FEATURE_FD_CAPABLE = 0x01; + /// + /// Device supports a delay between sending frames (FPGA based USB devices) + /// + static const int FEATURE_DELAY_CAPABLE = 0x02; + /// + /// Device supports I/O functionality for electronic circuits (USB-Chip devices) + /// + static const int FEATURE_IO_CAPABLE = 0x04; + + /// The service is not running + /// + /// + static const int SERVICE_STATUS_STOPPED = 0x01; + /// + /// The service is running + /// + static const int SERVICE_STATUS_RUNNING = 0x04; + #pragma endregion + + #pragma region Lookup Parameters + /// + /// Lookup channel by Device type (see PCAN devices e.g. PCAN_USB) + /// + static const String^ LOOKUP_DEVICE_TYPE = "devicetype"; + /// + /// Lookup channel by device id + /// + static const String^ LOOKUP_DEVICE_ID = "deviceid"; + /// + /// Lookup channel by CAN controller 0-based index + /// + static const String^ LOOKUP_CONTROLLER_NUMBER = "controllernumber"; + /// + /// Lookup channel by IP address (LAN channels only) + /// + static const String^ LOOKUP_IP_ADDRESS = "ipaddress"; + #pragma endregion + + #pragma region PCANBasic API Implementation + /// + /// Initializes a PCAN Channel + /// + /// The handle of a PCAN Channel + /// The speed for the communication (BTR0BTR1 code) + /// Non-PnP: The type of hardware and operation mode + /// Non-PnP: The I/O address for the parallel port + /// Non-PnP: Interrupt number of the parallel por + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_Initialize")] + static TPCANStatus Initialize( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + [MarshalAs(UnmanagedType::U2)] + TPCANBaudrate Btr0Btr1, + [MarshalAs(UnmanagedType::U1)] + TPCANType HwType, + UInt32 IOPort, + UInt16 Interrupt); + + /// + /// Initializes a PCAN Channel + /// + /// The handle of a PCAN Channel + /// The speed for the communication (BTR0BTR1 code) + /// A TPCANStatus error code + static TPCANStatus Initialize( + TPCANHandle Channel, + TPCANBaudrate Btr0Btr1) + { + return Initialize(Channel, Btr0Btr1, (TPCANType)0, 0, 0); + } + + /// + /// Initializes a FD capable PCAN Channel + /// + /// The handle of a FD capable PCAN Channel + /// The speed for the communication (FD bit rate string) + /// See PCAN_BR_* values + /// Bit rate string must follow the following construction rules: + /// * parameter and values must be separated by '=' + /// * Couples of Parameter/value must be separated by ',' + /// * Following Parameter must be filled out: f_clock, data_brp, data_sjw, data_tseg1, data_tseg2, + /// nom_brp, nom_sjw, nom_tseg1, nom_tseg2. + /// * Following Parameters are optional (not used yet): data_ssp_offset, nom_sam + /// f_clock=80000000,nom_brp=10,nom_tseg1=5,nom_tseg2=2,nom_sjw=1,data_brp=4,data_tseg1=7,data_tseg2=2,data_sjw=1 + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_InitializeFD")] + static TPCANStatus InitializeFD( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + TPCANBitrateFD BitrateFD); + + /// + /// Uninitializes one or all PCAN Channels initialized by CAN_Initialize + /// + /// Giving the TPCANHandle value "PCAN_NONEBUS", + /// uninitialize all initialized channels + /// The handle of a PCAN Channel + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_Uninitialize")] + static TPCANStatus Uninitialize( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel); + + /// + /// Resets the receive and transmit queues of the PCAN Channel + /// + /// A reset of the CAN controller is not performed + /// The handle of a PCAN Channel + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_Reset")] + static TPCANStatus Reset( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel); + + /// + /// Gets the current status of a PCAN Channel + /// + /// The handle of a PCAN Channel + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_GetStatus")] + static TPCANStatus GetStatus( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel); + + /// + /// Reads a CAN message from the receive queue of a PCAN Channel + /// + /// The handle of a PCAN Channel + /// A TPCANMsg structure buffer to store the CAN message + /// A TPCANTimestamp structure buffer to get + /// the reception time of the message + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_Read")] + static TPCANStatus Read( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + TPCANMsg %MessageBuffer, + TPCANTimestamp %TimestampBuffer); + + private: + [DllImport("PCANBasic.dll", EntryPoint = "CAN_Read")] + static TPCANStatus Read( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + TPCANMsg %MessageBuffer, + IntPtr bufferPointer); + + public: + /// + /// Reads a CAN message from the receive queue of a PCAN Channel + /// + /// The handle of a PCAN Channel + /// A TPCANMsg structure buffer to store the CAN message + /// A TPCANStatus error code + static TPCANStatus Read( + TPCANHandle Channel, + TPCANMsg %MessageBuffer) + { + return Read(Channel, MessageBuffer, IntPtr::Zero); + } + + /// + /// Reads a CAN message from the receive queue of a FD capable PCAN Channel + /// + /// The handle of a FD capable PCAN Channel + /// A TPCANMsgFD structure buffer to store the CAN message + /// A TPCANTimestampFD buffer to get the + /// reception time of the message + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_ReadFD")] + static TPCANStatus ReadFD( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + TPCANMsgFD %MessageBuffer, + TPCANTimestampFD %TimestampBuffer); + + private: + [DllImport("PCANBasic.dll", EntryPoint = "CAN_ReadFD")] + static TPCANStatus ReadFD( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + TPCANMsgFD %MessageBuffer, + IntPtr bufferPointer); + + public: + /// + /// Reads a CAN message from the receive queue of a FD capable PCAN Channel + /// + /// The handle of a FD capable PCAN Channel + /// A TPCANMsgFD structure buffer to store the CAN message + /// A TPCANTimestampFD buffer to get the + /// reception time of the message + /// A TPCANStatus error code + static TPCANStatus ReadFD( + TPCANHandle Channel, + TPCANMsgFD %MessageBuffer) + { + return ReadFD(Channel, MessageBuffer, IntPtr::Zero); + } + + /// + /// Transmits a CAN message + /// + /// The handle of a PCAN Channel + /// A TPCANMsg buffer with the message to be sent + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_Write")] + static TPCANStatus Write( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + TPCANMsg %MessageBuffer); + + /// + /// Transmits a CAN message over a FD capable PCAN Channel + /// + /// The handle of a FD capable PCAN Channel + /// A TPCANMsgFD buffer with the message to be sent + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_WriteFD")] + static TPCANStatus WriteFD( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + TPCANMsgFD %MessageBuffer); + + /// + /// Configures the reception filter + /// + /// The message filter will be expanded with every call to + /// this function. If it is desired to reset the filter, please use + /// the 'SetValue' function + /// The handle of a PCAN Channel + /// The lowest CAN ID to be received + /// The highest CAN ID to be received + /// Message type, Standard (11-bit identifier) or + /// Extended (29-bit identifier) + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_FilterMessages")] + static TPCANStatus FilterMessages( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + UInt32 FromID, + UInt32 ToID, + [MarshalAs(UnmanagedType::U1)] + TPCANMode Mode); + + /// + /// Retrieves a PCAN Channel value + /// + /// Parameters can be present or not according with the kind + /// of Hardware (PCAN Channel) being used. If a parameter is not available, + /// a PCAN_ERROR_ILLPARAMTYPE error will be returned + /// The handle of a PCAN Channel + /// The TPCANParameter parameter to get + /// Buffer for the parameter value + /// Size in bytes of the buffer + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_GetValue")] + static TPCANStatus GetValue( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + [MarshalAs(UnmanagedType::U1)] + TPCANParameter Parameter, + StringBuilder^ StringBuffer, + UInt32 BufferLength); + + /// + /// Retrieves a PCAN Channel value + /// + /// Parameters can be present or not according with the kind + /// of Hardware (PCAN Channel) being used. If a parameter is not available, + /// a PCAN_ERROR_ILLPARAMTYPE error will be returned + /// The handle of a PCAN Channel + /// The TPCANParameter parameter to get + /// Buffer for the parameter value + /// Size in bytes of the buffer + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_GetValue")] + static TPCANStatus GetValue( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + [MarshalAs(UnmanagedType::U1)] + TPCANParameter Parameter, + UInt32 %NumericBuffer, + UInt32 BufferLength); + + /// + /// Retrieves a PCAN Channel value + /// + /// Parameters can be present or not according with the kind + /// of Hardware (PCAN Channel) being used. If a parameter is not available, + /// a PCAN_ERROR_ILLPARAMTYPE error will be returned + /// The handle of a PCAN Channel + /// The TPCANParameter parameter to get + /// Buffer for the parameter value + /// Size in bytes of the buffer + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_GetValue")] + static TPCANStatus GetValue( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + [MarshalAs(UnmanagedType::U1)] + TPCANParameter Parameter, + UInt64 %NumericBuffer, + UInt32 BufferLength); + + private: + [DllImport("PCANBasic.dll", EntryPoint = "CAN_GetValue")] + static TPCANStatus GetValue( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + [MarshalAs(UnmanagedType::U1)] + TPCANParameter Parameter, + [MarshalAs(UnmanagedType::LPArray, SizeParamIndex=3)] + [In, Out]array ^ChannelBuffer, + UInt32 BufferLength); + public: + /// + /// Retrieves a PCAN Channel value + /// + /// Parameters can be present or not according with the kind + /// of Hardware (PCAN Channel) being used. If a parameter is not available, + /// a PCAN_ERROR_ILLPARAMTYPE error will be returned + /// The handle of a PCAN Channel + /// The TPCANParameter parameter to get + /// Buffer for the parameter value + /// A TPCANStatus error code + static TPCANStatus GetValue( + TPCANHandle Channel, + TPCANParameter Parameter, + array ^ChannelsBuffer) + { + if(ChannelsBuffer == nullptr) + return TPCANStatus::PCAN_ERROR_ILLPARAMVAL; + return GetValue(Channel, Parameter, ChannelsBuffer, ChannelsBuffer->Length * Marshal::SizeOf(TPCANChannelInformation::typeid)); + } + + /// + /// Configures a PCAN Channel value + /// + /// Parameters can be present or not according with the kind + /// of Hardware (PCAN Channel) being used. If a parameter is not available, + /// a PCAN_ERROR_ILLPARAMTYPE error will be returned + /// The handle of a PCAN Channel + /// The TPCANParameter parameter to set + /// Buffer with the value to be set + /// Size in bytes of the buffer + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_SetValue")] + static TPCANStatus SetValue( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + [MarshalAs(UnmanagedType::U1)] + TPCANParameter Parameter, + UInt32% NumericBuffer, + UInt32 BufferLength); + + /// + /// Configures a PCAN Channel value + /// + /// Parameters can be present or not according with the kind + /// of Hardware (PCAN Channel) being used. If a parameter is not available, + /// a PCAN_ERROR_ILLPARAMTYPE error will be returned + /// The handle of a PCAN Channel + /// The TPCANParameter parameter to set + /// Buffer with the value to be set + /// Size in bytes of the buffer + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_SetValue")] + static TPCANStatus SetValue( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + [MarshalAs(UnmanagedType::U1)] + TPCANParameter Parameter, + UInt64% NumericBuffer, + UInt32 BufferLength); + + /// + /// Configures a PCAN Channel value + /// + /// Parameters can be present or not according with the kind + /// of Hardware (PCAN Channel) being used. If a parameter is not available, + /// a PCAN_ERROR_ILLPARAMTYPE error will be returned + /// The handle of a PCAN Channel + /// + /// Buffer with the value to be set + /// Size in bytes of the buffer + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_SetValue")] + static TPCANStatus SetValue( + [MarshalAs(UnmanagedType::U2)] + TPCANHandle Channel, + [MarshalAs(UnmanagedType::U1)] + TPCANParameter Parameter, + [MarshalAs(UnmanagedType::LPStr,SizeParamIndex=3)] + String^ StringBuffer, + UInt32 BufferLength); + + /// + /// Returns a descriptive text of a given TPCANStatus error + /// code, in any desired language + /// + /// The current languages available for translation are: + /// Neutral (0x00), German (0x07), English (0x09), Spanish (0x0A), + /// Italian (0x10) and French (0x0C) + /// A TPCANStatus error code + /// Indicates a 'Primary language ID' + /// Buffer for the text (must be at least 256 in length) + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_GetErrorText")] + static TPCANStatus GetErrorText( + [MarshalAs(UnmanagedType::U4)] + TPCANStatus Error, + UInt16 Language, + StringBuilder^ StringBuffer); + + /// + /// Finds a PCAN-Basic channel that matches with the given parameters + /// + /// A comma separated string contained pairs of + /// parameter-name/value to be matched within a PCAN-Basic channel + /// Buffer for returning the PCAN-Basic channel, + /// when found + /// A TPCANStatus error code + [DllImport("PCANBasic.dll", EntryPoint = "CAN_LookUpChannel")] + static TPCANStatus LookUpChannel( + String^ Parameters, + TPCANHandle% FoundChannel); + #pragma endregion + }; + #pragma endregion + } + } } \ No newline at end of file diff --git a/third_party/Robotic_Arm/include/rm_define.h b/third_party/Robotic_Arm/include/rm_define.h deleted file mode 100644 index 40ec038..0000000 --- a/third_party/Robotic_Arm/include/rm_define.h +++ /dev/null @@ -1,1032 +0,0 @@ -#ifndef RM_DEFINE_H -#define RM_DEFINE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#define ARM_DOF 7 -#define M_PI 3.14159265358979323846 - -#define RM_MOVE_NBLOCK 0 ///<机械臂运动设置,非阻塞模式 -#define RM_MOVE_MULTI_BLOCK 1 ///<机械臂运动设置,多线程阻塞模式 -static inline int RM_MOVE_SINGLE_BLOCK(int timeout){return timeout;} ///<机械臂运动设置,单线程阻塞模式超时时间 - -/** - * @brief 线程模式 - * @ingroup Init_Class - */ -typedef enum { - RM_SINGLE_MODE_E, ///< 单线程模式,单线程非阻塞等待数据返回 - RM_DUAL_MODE_E, ///< 双线程模式,增加接收线程监测队列中的数据 - RM_TRIPLE_MODE_E, ///< 三线程模式,在双线程模式基础上增加线程监测UDP接口数据 -}rm_thread_mode_e; - -/** - * @brief 机械臂型号 - * @ingroup Algo - */ -typedef enum{ - RM_MODEL_RM_65_E, ///< RM_65 - RM_MODEL_RM_75_E, ///< RM_75 - RM_MODEL_RM_63_I_E, ///< RML_63I(已弃用) - RM_MODEL_RM_63_II_E, ///< RML_63II - RM_MODEL_RM_63_III_E, ///< RML_63III - RM_MODEL_ECO_65_E, ///< ECO_65 - RM_MODEL_ECO_62_E, ///< ECO_62 - RM_MODEL_GEN_72_E, ///< GEN_72 - RM_MODEL_ECO_63_E, ///< ECO63 - RM_MODEL_UNIVERSAL_E -}rm_robot_arm_model_e; - -/** - * @brief 机械臂末端力传感器版本 - * @ingroup Algo - */ -typedef enum{ - RM_MODEL_RM_B_E, ///< 标准版 - RM_MODEL_RM_ZF_E, ///< 一维力版 - RM_MODEL_RM_SF_E, ///< 六维力版 - RM_MODEL_RM_ISF_E, ///< 一体化六维力版 -}rm_force_type_e; - -/** - * @brief 事件类型 - * @ingroup Init_Class - */ -typedef enum -{ - RM_NONE_EVENT_E, ///< 无事件 - RM_CURRENT_TRAJECTORY_STATE_E, ///< 当前轨迹到位 - RM_PROGRAM_RUN_FINISH_E, ///< 在线编程运行结束 -} rm_event_type_e; - -/** - * @brief 事件信息 - * @ingroup Init_Class - */ -typedef struct -{ - int handle_id; ///< 返回消息的机械臂id - rm_event_type_e event_type; ///< 事件类型,包含无事件、当前轨迹到位、在线编程运行结束 - bool trajectory_state; ///< 当前轨迹到位状态 - int device; ///< 到位设备,0:关节 1:夹爪 2:灵巧手 3:升降机构 4:扩展关节 其他:保留 - int trajectory_connect; ///< 是否连接下一条轨迹,0:全部到位,1:连接下一条轨迹 - int program_id; ///< 运行结束的在线编程程序id -}rm_event_push_data_t; - -/** - * @brief 机械臂当前规划类型 - * - */ -typedef enum -{ - RM_NO_PLANNING_E, ///< 无规划 - RM_JOINT_SPACE_PLANNING_E, ///< 关节空间规划 - RM_CARTESIAN_LINEAR_PLANNING_E, ///< 笛卡尔空间直线规划 - RM_CARTESIAN_ARC_PLANNING_E, ///< 笛卡尔空间圆弧规划 - RM_SPLINE_CURVE_MOTION_PLANNING_E, ///< 样条曲线运动规划 - RM_TRAJECTORY_REPLAY_PLANNING_E, ///< 示教轨迹复现规划 -}rm_arm_current_trajectory_e; - -typedef struct -{ - int joint_speed; ///< 关节速度。 - int lift_state; ///< 升降关节信息。1:上报;0:关闭上报;-1:不设置,保持之前的状态 - int expand_state; ///< 扩展关节信息(升降关节和扩展关节为二选一,优先显示升降关节)1:上报;0:关闭上报;-1:不设置,保持之前的状态 - int hand_state; ///< 灵巧手状态。1:上报;0:关闭上报;-1:不设置,保持之前的状态(1.7.0版本无这个) - int arm_current_status; ///< 机械臂当前状态。1:上报;0:关闭上报;-1:不设置,保持之前的状态 - int aloha_state; ///< aloha主臂状态是否上报。1:上报;0:关闭上报;-1:不设置,保持之前的状态 - int plus_base; ///< 末端设备基础信息。1:上报;0:关闭上报;-1:不设置,保持之前的状态 - int plus_state; ///< 末端设备实时信息。1:上报;0:关闭上报;-1:不设置,保持之前的状态 -}rm_udp_custom_config_t; - -/** - * @brief 机械臂主动上报接口配置 - * @ingroup UdpConfig - */ -typedef struct { - int cycle; ///< 广播周期,5ms的倍数 - bool enable; ///< 使能,是否主动上报 - int port; ///< 广播的端口号 - int force_coordinate; ///< 系统外受力数据的坐标系,-1不支持力传感器 0为传感器坐标系 1为当前工作坐标系 2为当前工具坐标系 - char ip[28]; ///< 自定义的上报目标IP地址 - rm_udp_custom_config_t custom_config; ///< 自定义项内容 -} rm_realtime_push_config_t; - -/** - * @brief 四元数 - * - */ -typedef struct -{ - float w; - float x; - float y; - float z; -} rm_quat_t; - -/** - * @brief 位置坐标 - * - */ -typedef struct -{ - float x; //* unit: m - float y; - float z; -} rm_position_t; - -/** - * @brief 欧拉角 - * - */ -typedef struct -{ - float rx; //* unit: rad - float ry; - float rz; -} rm_euler_t; - -/** - * @brief 机械臂位置姿态结构体 - * @ingroup Algo - */ -typedef struct -{ - rm_position_t position; ///< 位置,单位:m - rm_quat_t quaternion; ///< 四元数 - rm_euler_t euler; ///< 欧拉角,单位:rad -}rm_pose_t; - -/** - * @brief 坐标系名称 - * 不超过10个字符 - * @ingroup ToolCoordinateConfig - * @ingroup WorkCoordinateConfig - */ -typedef struct -{ - char name[12]; -}rm_frame_name_t; - - -/** - * @brief 坐标系 - * @ingroup Algo - * @ingroup ToolCoordinateConfig - * @ingroup WorkCoordinateConfig - */ -typedef struct -{ - char frame_name[12]; ///< 坐标系名称 - rm_pose_t pose; ///< 坐标系位姿 - float payload; ///< 坐标系末端负载重量,单位:kg - float x; ///< 坐标系末端负载质心位置,单位:m - float y; ///< 坐标系末端负载质心位置,单位:m - float z; ///< 坐标系末端负载质心位置,单位:m -}rm_frame_t; - -typedef struct{ - char build_time[20]; ///< 编译时间 - char version[20]; ///< 版本号 -}rm_ctrl_version_t; - -typedef struct{ - char model_version[5]; ///< 动力学模型版本号 -}rm_dynamic_version_t; - -typedef struct{ - char build_time[20]; ///<编译时间 - char version[20]; ///< 版本号 -}rm_planinfo_t; - -typedef struct { - char version[20]; ///< 算法库版本号 -}rm_algorithm_version_t; - -typedef struct { - char build_time[20]; ///<编译时间 - char version[20]; ///< 版本号 -}rm_software_build_info_t; -/** - * @brief 机械臂软件信息 - * - */ -typedef struct -{ - char product_version[20]; ///< 机械臂型号 - char robot_controller_version[10]; ///< 机械臂控制器版本,若为四代控制器,则该字段为"4.0" - rm_algorithm_version_t algorithm_info; ///< 算法库信息 - rm_software_build_info_t ctrl_info; ///< ctrl 层软件信息 - rm_dynamic_version_t dynamic_info; ///< 动力学版本(三代) - rm_software_build_info_t plan_info; ///< plan 层软件信息(三代) - rm_software_build_info_t com_info; ///< communication 模块软件信息(四代) - rm_software_build_info_t program_info; ///< 流程图编程模块软件信息(四代) -}rm_arm_software_version_t; - -/** - * @brief 错误代码结构体 - * -*/ -typedef struct -{ - uint8_t err_len; ///< 错误代码个数 - int err[24]; ///< 错误代码数组 -}rm_err_t; - -/** - * @brief 机械臂当前状态 - * -*/ -typedef struct -{ - rm_pose_t pose; ///< 机械臂当前位姿 - float joint[ARM_DOF]; ///< 机械臂当前关节角度 - rm_err_t err; -}rm_current_arm_state_t; - -/** - * @brief 机械臂关节状态参数 - * -*/ -typedef struct -{ - float joint_current[ARM_DOF]; ///< 关节电流,单位mA,精度:0.001mA - bool joint_en_flag[ARM_DOF]; ///< 当前关节使能状态 ,1为上使能,0为掉使能 - uint16_t joint_err_code[ARM_DOF]; ///< 当前关节错误码 - float joint_position[ARM_DOF]; ///< 关节角度,单位°,精度:0.001° - float joint_temperature[ARM_DOF]; ///< 当前关节温度,精度0.001℃ - float joint_voltage[ARM_DOF]; ///< 当前关节电压,精度0.001V - float joint_speed[ARM_DOF]; ///< 当前关节速度,精度0.01RPM。 -}rm_joint_status_t; - -/** - * @brief 位置示教方向 - * - */ -typedef enum -{ - RM_X_DIR_E, ///< 位置示教,x轴方向 - RM_Y_DIR_E, ///< 位置示教,y轴方向 - RM_Z_DIR_E, ///< 位置示教,z轴方向 -}rm_pos_teach_type_e; - -/** - * @brief 姿态示教方向 - * - */ -typedef enum -{ - RM_RX_ROTATE_E, ///< 姿态示教,绕x轴旋转 - RM_RY_ROTATE_E, ///< 姿态示教,绕y轴旋转 - RM_RZ_ROTATE_E, ///< 姿态示教,绕z轴旋转 -}rm_ort_teach_type_e; - -/** - * @brief 数字IO配置结构体 - * io_mode:模式,0-通用输入模式、1-通用输出模式、2-输入开始功能复用模式、3-输入暂停功能复用模式、 - * 4-输入继续功能复用模式、5-输入急停功能复用模式、6-输入进入电流环拖动复用模式 - * 7-输入进入力只动位置拖动模式(六维力版本可配置)、8-输入进入力只动姿态拖动模式(六维力版本可配置) - * 9-输入进入力位姿结合拖动复用模式(六维力版本可配置)、10-输入外部轴最大软限位复用模式(外部轴模式可配置) - * 11-输入外部轴最小软限位复用模式(外部轴模式可配置)、12-输入初始位姿功能复用模式 - * 13-输出碰撞功能复用模式、14-实时调速功能复用模式 - * io_state:数字io状态(0低 1高)(该成员在set时无效) - * io_real_time_config_t:实时调速功能,io配置 - * speed:速度取值范围0-100 (当io_mode不为14时,默认值为-1) - * mode :模式取值范围1或2 (当io_mode不为14时,默认值为-1) - * 1表示单次触发模式,单次触发模式下当IO拉低速度设置为speed参数值,IO恢复高电平速度设置为初始值 - * 2表示连续触发模式,连续触发模式下IO拉低速度设置为speed参数值,IO恢复高电平速度维持当前值 - */ -typedef struct -{ - int io_mode; // io_mode:模式0~14 - struct - { - int speed; // speed:速度取值范围0-100 - int mode; // mode :模式取值范围1或2 - }io_real_time_config_t; -}rm_io_config_t; - -/** - * @brief 数字IO状态获取结构体 - * io_state:数字io状态(0低 1高)(该成员在set时无效) - * io_config:io配置结构体 - */ -typedef struct -{ - int io_state; // io_state:数字io状态(0低 1高) - rm_io_config_t io_config; // io_config:数字io配置结构体 -}rm_io_get_t; - -/** - * @brief 复合模式拖动示教参数 - * - */ -typedef struct{ - int free_axes[6]; ///< 自由驱动方向[x,y,z,rx,ry,rz],0-在参考坐标系对应方向轴上不可拖动,1-在参考坐标系对应方向轴上可拖动 - int frame; ///< 参考坐标系,0-工作坐标系 1-工具坐标系。 - int singular_wall; ///< 仅在六维力模式拖动示教中生效,用于指定是否开启拖动奇异墙,0表示关闭拖动奇异墙,1表示开启拖动奇异墙,若无配置参数,默认启动拖动奇异墙 -}rm_multi_drag_teach_t; - -/** - * @brief 力位混合控制传感器枚举 - * - */ -typedef enum{ - RM_FP_OF_SENSOR_E = 0, ///<一维力 - RM_FP_SF_SENSOR_E, ///<六维力 -}rm_force_position_sensor_e; - -/** - * @brief 力位混合控制模式枚举 - * - */ -typedef enum{ - RM_FP_BASE_COORDINATE_E = 0, ///<基坐标系力控 - RM_FP_TOOL_COORDINATE_E, ///<工具坐标系力控 -}rm_force_position_mode_e; - -/** - * @brief 力位混合控制模式(单方向)力控方向枚举 - * - */ -typedef enum{ - RM_FP_X_E = 0, ///<沿X轴 - RM_FP_Y_E, ///<沿Y轴 - RM_FP_Z_E, ///<沿Z轴 - RM_FP_RX_E, ///<沿RX姿态方向 - RM_FP_RY_E, ///<沿RY姿态方向 - RM_FP_RZ_E, ///<沿RZ姿态方向 -}rm_force_position_dir_e; - -/** - * @brief 力位混合控制参数 - * - */ -typedef struct -{ - int sensor; ///< 传感器,0-一维力;1-六维力 - int mode; ///< 0-基坐标系力控;1-工具坐标系力控; - int control_mode[6]; ///< 6个力控方向(Fx Fy Fz Mx My Mz)的模式 0-固定模式 1-浮动模式 2-弹簧模式 3-运动模 4-力跟踪模式 8-力跟踪+姿态自适应模式 - float desired_force[6]; ///< 力控轴维持的期望力/力矩,力控轴的力控模式为力跟踪模式时,期望力/力矩设置才会生效 ,精度0.1N。 - float limit_vel[6]; ///< 力控轴的最大线速度和最大角速度限制,只对开启力控方向生效。 -}rm_force_position_t; - -/** - * @brief 透传力位混合补偿参数 - * 建议初始化方式,避免一些未知错误 - * rm_force_position_move_t my_fp_move = (rm_force_position_move_t){ 0 }; - */ -typedef struct -{ - int flag; ///< 0-下发目标角度,1-下发目标位姿 - rm_pose_t pose; ///< 当前坐标系下的目标位姿,支持四元数/欧拉角表示姿态。位置精度:0.001mm,欧拉角表示姿态,姿态精度:0.001rad,四元数方式表示姿态,姿态精度:0.000001 - float joint[ARM_DOF]; ///< 目标关节角度,单位:°,精度:0.001° - int sensor; ///< 传感器,0-一维力;1-六维力 - int mode; ///< 0-基坐标系力控;1-工具坐标系力控; - bool follow; ///< 表示驱动器的运动跟随效果,true 为高跟随,false 为低跟随。 - int control_mode[6]; ///< 6个力控方向的模式 0-固定模式 1-浮动模式 2-弹簧模式 3-运动模式 4-力跟踪模式 5-浮动+运动模式 6-弹簧+运动模式 7-力跟踪+运动模式 8-姿态自适应模式 - float desired_force[6]; ///< 力控轴维持的期望力/力矩,力控轴的力控模式为力跟踪模式时,期望力/力矩设置才会生效 ,精度0.1N。 - float limit_vel[6]; ///< 力控轴的最大线速度和最大角速度限制,只对开启力控方向生效。 - int trajectory_mode; ///< 高跟随模式下,0-完全透传模式、1-曲线拟合模式、2-滤波模式 - int radio; ///< 曲线拟合模式0-100和滤波模式下的平滑系数(数值越大效果越好),滤波模式下取值范围0~1000,曲线拟合模式下取值范围0~100 -}rm_force_position_move_t; - -/** - * @brief 角度透传模式结构体 - * 建议初始化方式,避免一些未知错误 - * rm_movej_canfd_mode_t my_j_canfd = (rm_movej_canfd_mode_t){ 0 }; - */ -typedef struct -{ - float* joint; // 关节角度(若为六轴机械臂,那么最后一个元素无效),单位° - float expand; // 扩展关节角度(若没有扩展关节,那么此成员值无效) - bool follow; // 跟随模式,0-低跟随,1-高跟随,若使用高跟随,透传周期要求不超过 10ms - int trajectory_mode; // 高跟随模式下,0-完全透传模式、1-曲线拟合模式、2-滤波模式 - int radio; // 曲线拟合模式和滤波模式下的平滑系数(数值越大效果越好),滤波模式下取值范围0~1000,曲线拟合模式下取值范围0~100 -}rm_movej_canfd_mode_t; - -/** - * @brief 姿态透传模式结构体 - * 建议初始化方式,避免一些未知错误 - * rm_movep_canfd_mode_t my_p_canfd = (rm_movep_canfd_mode_t){ 0 }; - */ -typedef struct -{ - rm_pose_t pose; // 位姿 (优先采用四元数表达) - bool follow; // 跟随模式,0-低跟随,1-高跟随,若使用高跟随,透传周期要求不超过 10ms - int trajectory_mode; // 高跟随模式下,0-完全透传模式、1-曲线拟合模式、2-滤波模式 - int radio; // 曲线拟合模式和滤波模式下的平滑系数(数值越大效果越好),滤波模式下取值范围0~1000,曲线拟合模式下取值范围0~100 -}rm_movep_canfd_mode_t; - -/** - * @brief 无线网络信息结构体 - * - */ -typedef struct{ - int channel; ///< 如果是 AP 模式,则存在此字段,标识 wifi 热点的物理信道号 - char ip[16]; ///< IP 地址 - char mac[18]; ///< MAC 地址 - char mask[16]; ///< 子网掩码 - char mode[5]; ///< ap 代表热点模式,sta 代表联网模式,off 代表未开启无线模式 - char password[16]; ///< 密码 - char ssid[32]; ///< 网络名称 (SSID) -}rm_wifi_net_t; - -/** - * @brief 机械臂所有状态参数 - * -*/ -typedef struct -{ - float joint_current[ARM_DOF]; ///< 关节电流,单位mA - int joint_en_flag[ARM_DOF]; ///< 关节使能状态 - float joint_temperature[ARM_DOF]; ///< 关节温度,单位℃ - float joint_voltage[ARM_DOF]; ///< 关节电压,单位V - int joint_err_code[ARM_DOF]; ///< 关节错误码 - rm_err_t err; ///< 错误代码 -}rm_arm_all_state_t; - -/** - * @brief 夹爪状态 - * - */ -typedef struct -{ - int enable_state; ///< 夹爪使能标志,0 表示未使能,1 表示使能 - int status; ///< 夹爪在线状态,0 表示离线, 1表示在线 - int error; ///< 夹爪错误信息,低8位表示夹爪内部的错误信息bit5-7 保留bit4 内部通bit3 驱动器bit2 过流 bit1 过温bit0 堵转 - int mode; ///< 当前工作状态:1 夹爪张开到最大且空闲,2 夹爪闭合到最小且空闲,3 夹爪停止且空闲,4 夹爪正在闭合,5 夹爪正在张开,6 夹爪闭合过程中遇到力控停止 - int current_force; ///< 夹爪当前的压力,单位g - int temperature; ///< 当前温度,单位℃ - int actpos; ///< 夹爪开口度 -}rm_gripper_state_t; - -/** - * @brief 六维力传感器数据结构体 - * -*/ -typedef struct { - float force_data[6]; ///< 当前力传感器原始数据,力的单位为N;力矩单位为Nm。 - float zero_force_data[6]; ///< 当前力传感器系统外受力数据,力的单位为N;力矩单位为Nm。 - float work_zero_force_data[6]; ///< 当前工作坐标系下系统外受力原始数据,力的单位为N;力矩单位为Nm。 - float tool_zero_force_data[6]; ///< 当前工具坐标系下系统外受力原始数据,力的单位为N;力矩单位为Nm。 -} rm_force_data_t; - -/** - * @brief 一维力传感器数据结构体 - * -*/ -typedef struct { - float Fz; ///< 原始数据 - float zero_Fz; ///< 传感器坐标系下系统外受力数据,力的单位为N;力矩单位为Nm。 - float work_zero_Fz; ///< 当前工作坐标系下系统外受力原始数据,力的单位为N;力矩单位为Nm。 - float tool_zero_Fz; ///< 当前工具坐标系下系统外受力原始数据,力的单位为N;力矩单位为Nm。 -} rm_fz_data_t; - -/** - * @brief 外设数据读写参数结构体 - * -*/ -typedef struct { - int port; ///< 通讯端口,0-控制器RS485端口,1-末端接口板RS485接口,3-控制器ModbusTCP设备 - int address; ///< 数据起始地址 - int device; ///< 外设设备地址 - int num; ///< 要读的数据的数量 -} rm_peripheral_read_write_params_t; - -/** - * @brief 升降机构、扩展关节状态结构体 - * -*/ -typedef struct { - int pos; ///< 扩展关节角度,单位度,精度 0.001°(若为升降机构高度,则单位:mm,精度:1mm,范围:0 ~2300) - int current; ///< 驱动电流,单位:mA,精度:1mA - int err_flag; ///< 驱动错误代码,错误代码类型参考关节错误代码 - int mode; ///< 当前状态,0-空闲,1-正方向速度运动,2-正方向位置运动,3-负方向速度运动,4-负方向位置运动 -} rm_expand_state_t; - -/** - * @brief 文件下发 - * @ingroup OnlineProgramming - */ -typedef struct { - char project_path[300]; ///< 下发文件路径文件名 - int project_path_len; ///< 名称长度 - int plan_speed; ///< 规划速度比例系数 - int only_save; ///< 0-保存并运行文件,1-仅保存文件,不运行 - int save_id; ///< 保存到控制器中的编号 - int step_flag; ///< 设置单步运行方式模式,1-设置单步模式 0-设置正常运动模式 - int auto_start; ///< 设置默认在线编程文件,1-设置默认 0-设置非默认 - int project_type; ///< 下发文件类型。0-在线编程文件,1-拖动示教轨迹文件 - // int err_line; ///< 若运行失败,该参数返回有问题的工程行数,err_line 为 0,则代表校验数据长度不对 -} rm_send_project_t; - -/** - * @brief 在线编程存储信息 - * @ingroup OnlineProgramming - */ -typedef struct { - int id; ///< 在线编程文件id - int size; ///< 文件大小 - int speed; ///< 默认运行速度 - char trajectory_name[32]; ///< 文件名称 -}rm_trajectory_data_t; -/** - * @brief 查询在线编程列表 - * @ingroup OnlineProgramming - */ -typedef struct -{ - int page_num; // 页码 - int page_size; // 每页大小 - int list_size; //返回总数量 - char vague_search[32]; // 模糊搜索 - rm_trajectory_data_t trajectory_list[100]; // 符合的在线编程列表 -}rm_program_trajectorys_t; - -/** - * @brief 在线编程运行状态 - * @ingroup OnlineProgramming - */ -typedef struct -{ - int run_state; ///< 运行状态 0 未开始 1运行中 2暂停中 - int id; ///< 运行轨迹编号 - int edit_id; ///< 上次编辑的在线编程编号 id - int plan_num; ///< 运行行数 - int total_loop; ///< 循环指令数量 - int step_mode; ///< 单步模式,1 为单步模式,0 为非单步模式 - int plan_speed; ///< 全局规划速度比例 1-100 - int loop_num[100]; ///< 循环行数 - int loop_cont[100]; ///< 对应循环次数 -}rm_program_run_state_t; - -/** - * @brief 流程图程序运行状态 - */ -typedef struct -{ - int run_state; ///< 运行状态 0 未开始 1运行中 2暂停中 - int id; ///< 当前使能的文件id。 - char name[32]; ///< 当前使能的文件名称。 - int plan_speed; ///< 当前使能的文件全局规划速度比例 1-100。 - int step_mode; ///< 单步模式,0为空,1为正常, 2为单步。 - char modal_id[50]; ///< 运行到的流程图块的id。未运行则不返回 -}rm_flowchart_run_state_t; - -/** - * @brief 全局路点存储信息 - * @ingroup OnlineProgramming - */ -typedef struct -{ - char point_name[20]; ///< 路点名称 - float joint[ARM_DOF]; ///< 关节角度 - rm_pose_t pose; ///< 位姿信息 - char work_frame[12]; ///< 工作坐标系名称 - char tool_frame[12]; ///< 工具坐标系名称 - char time[50]; ///< 路点新增或修改时间 -}rm_waypoint_t; -/** - * @brief 全局路点列表 - * @ingroup OnlineProgramming - */ -typedef struct{ - int page_num; ///< 页码 - int page_size; ///< 每页大小 - int total_size; ///< 列表长度 - char vague_search[32]; ///< 模糊搜索 - int list_len; ///<返回符合的全局路点列表长度 - rm_waypoint_t points_list[100]; ///< 返回符合的全局路点列表 -}rm_waypoint_list_t; - -/** - * @brief 几何模型长方体参数 - * @ingroup Electronic_Fence - */ -typedef struct{ - float x_min_limit; ///< 长方体基于世界坐标系 X 方向最小位置,单位 m - float x_max_limit; ///< 长方体基于世界坐标系 X 方向最大位置,单位 m - float y_min_limit; ///< 长方体基于世界坐标系 Y 方向最小位置,单位 m - float y_max_limit; ///< 长方体基于世界坐标系 Y 方向最大位置,单位 m - float z_min_limit; ///< 长方体基于世界坐标系 Z 方向最小位置,单位 m - float z_max_limit; ///< 长方体基于世界坐标系 Z 方向最大位置,单位 m -}rm_fence_config_cube_t; -/** - * @brief 几何模型点面矢量平面参数 - * @ingroup Electronic_Fence - */ -typedef struct{ - float x1, y1, z1; ///< 点面矢量平面三点法中的第一个点坐标,单位 m - float x2, y2, z2; ///< 点面矢量平面三点法中的第二个点坐标,单位 m - float x3, y3, z3; ///< 点面矢量平面三点法中的第三个点坐标,单位 m -}rm_fence_config_plane_t; -/** - * @brief 几何模型球体参数 - * @ingroup Electronic_Fence - */ -typedef struct{ - float x; ///< 表示球心在世界坐标系 X 轴的坐标,单位 m - float y; ///< 表示球心在世界坐标系 Y 轴的坐标,单位 m - float z; ///< 表示球心在世界坐标系 Z 轴的坐标,单位 m - float radius; ///< 表示半径,单位 m -}rm_fence_config_sphere_t; -/** - * @brief 几何模型参数 - * @ingroup Electronic_Fence - */ -typedef struct{ - int form; ///< 形状,1 表示长方体,2 表示点面矢量平面,3 表示球体 - char name[12]; ///< 电子围栏名称,不超过 10 个字节,支持字母、数字、下划线 - rm_fence_config_cube_t cube; ///< 长方体参数 - rm_fence_config_plane_t plan; ///< 点面矢量平面参数 - rm_fence_config_sphere_t sphere; ///< 球体参数 -}rm_fence_config_t; - -/** - * @brief 几何模型名称结构体 - * @ingroup Electronic_Fence - */ -typedef struct -{ - char name[12]; ///< 几何模型名称,不超过10个字符 -}rm_fence_names_t; - -/** - * @brief 几何模型参数列表 - * @ingroup Electronic_Fence - */ -typedef struct -{ - rm_fence_config_t config[10]; -}rm_fence_config_list_t; -/** - * @brief 包络球参数 - * - */ -typedef struct{ - char name[12]; ///< 工具包络球体的名称,1-10 个字节,支持字母数字下划线 - float radius; ///< 工具包络球体的半径,单位 m - float x; ///< 工具包络球体球心基于末端法兰坐标系的 X 轴坐标,单位 m - float y; ///< 工具包络球体球心基于末端法兰坐标系的 Y 轴坐标,单位 m - float z; ///< 工具包络球体球心基于末端法兰坐标系的 Z 轴坐标,单位 m -}rm_envelopes_ball_t; -/** - * @brief 包络球参数集合 - * - */ -typedef struct{ - rm_envelopes_ball_t balls[5];///< 包络参数列表,每个工具最多支持 5 个包络球,可以没有包络 - int size; ///< 包络球数量 - char tool_name[12];///< 控制器中已存在的工具坐标系名称,如果不存在该字段,则为临时设置当前包络参数 -}rm_envelope_balls_list_t; - -/** - * @brief 电子围栏/虚拟墙使能状态参数 - * - */ -typedef struct -{ - bool enable_state; ///< 电子围栏/虚拟墙使能状态,true 代表使能,false 代表禁使能 - int in_out_side; ///< 0-机器人在电子围栏/虚拟墙内部,1-机器人在电子围栏外部 - int effective_region; ///< 0-电子围栏针对整臂区域生效,1-虚拟墙针对末端生效 -}rm_electronic_fence_enable_t; - - -/** - * @brief (UDP主动上报机械臂信息)力传感器数据结构体 - * -*/ -typedef struct { - float force[6]; ///< 当前力传感器原始数据,0.001N或0.001Nm - float zero_force[6]; ///< 当前力传感器系统外受力数据,0.001N或0.001Nm - int coordinate; ///< 系统外受力数据的坐标系,0为传感器坐标系 1为当前工作坐标系 2为当前工具坐标系 -} rm_force_sensor_t; - -/*** - * 扩展关节数据 - * - */ -typedef struct { - float pos; ///< 当前角度 精度 0.001°,单位:° - int current; ///< 当前驱动电流,单位:mA,精度:1mA - int err_flag; ///< 驱动错误代码,错误代码类型参考关节错误代码 - int en_flag; ///< 当前关节使能状态 ,1 为上使能,0 为掉使能 - int joint_id; ///< 关节id号 - int mode; ///< 当前升降状态,0-空闲,1-正方向速度运动,2-正方向位置运动,3-负方向速度运动,4-负方向位置运动 -} rm_udp_expand_state_t; - -/*** - * 升降机构状态 - * - */ -typedef struct { - int height; ///< 当前升降机构高度,单位:mm,精度:1mm - float pos; ///< 当前角度 精度 0.001°,单位:° - int current; ///< 当前驱动电流,单位:mA,精度:1mA - int err_flag; ///< 驱动错误代码,错误代码类型参考关节错误代码 - int en_flag; ///< 当前关节使能状态 ,1 为上使能,0 为掉使能 -} rm_udp_lift_state_t; -/*** - * 灵巧手状态 - * - */ -typedef struct { - int hand_pos[6]; ///< 表示灵巧手位置 - int hand_angle[6]; ///< 表示灵巧手角度 - int hand_force[6]; ///< 表示灵巧手自由度力,单位mN - int hand_state[6]; ///< 表示灵巧手自由度状态,由灵巧手厂商定义状态含义 - int hand_err; ///< 表示灵巧手系统错误,由灵巧手厂商定义错误含义,例如因时状态码如下:1表示有错误,0表示无错误 -} rm_udp_hand_state_t; - -/*** - * - * 轨迹连接配置 - */ -typedef enum{ - RM_TRAJECTORY_DISCONNECT_E = 0, ///<立即规划并执行轨迹,不连接后续轨迹 - RM_TRAJECTORY_CONNECT_E ///<将当前轨迹与下一条轨迹一起规划 -}rm_trajectory_connect_config_e; - -/** - * @brief 机械臂当前状态 - * - */ -typedef enum { - RM_IDLE_E, // 使能但空闲状态 - RM_MOVE_L_E, // move L运动中状态 - RM_MOVE_J_E, // move J运动中状态 - RM_MOVE_C_E, // move C运动中状态 - RM_MOVE_S_E, // move S运动中状态 - RM_MOVE_THROUGH_JOINT_E, // 角度透传状态 - RM_MOVE_THROUGH_POSE_E, // 位姿透传状态 - RM_MOVE_THROUGH_FORCE_POSE_E, // 力控透传状态 - RM_MOVE_THROUGH_CURRENT_E, // 电流环透传状态 - RM_STOP_E, // 急停状态 - RM_SLOW_STOP_E, // 缓停状态 - RM_PAUSE_E, // 暂停状态 - RM_CURRENT_DRAG_E, // 电流环拖动状态 - RM_SENSOR_DRAG_E, // 六维力拖动状态 - RM_TECH_DEMONSTRATION_E // 示教状态 -} rm_udp_arm_current_status_e; - -/*** - * aloha主臂状态 - * - */ -typedef struct { - int io1_state; ///< IO1状态(手柄光电检测),0为按键未触发,1为按键触发。 - int io2_state; ///< IO2状态(手柄光电检测),0为按键未触发,1为按键触发。 -} rm_udp_aloha_state_t; - -/** - * 末端设备基础信息(末端生态协议支持) -*/ -typedef struct{ - char manu[10]; // 设备厂家 - int type; // 设备类型 1:两指夹爪 2:五指灵巧手 3:三指夹爪 - char hv[10]; // 硬件版本 - char sv[10]; // 软件版本 - char bv[10]; // boot版本 - int id; // 设备ID - int dof; // 自由度 - int check; // 自检开关 - int bee; // 蜂鸣器开关 - bool force; // 力控支持 - bool touch; // 触觉支持 - int touch_num; // 触觉个数 - int touch_sw; // 触觉开关 - int hand; // 手方向 1 :左手 2: 右手 - int pos_up[12]; // 位置上限,单位:无量纲 - int pos_low[12]; // 位置下限,单位:无量纲 - int angle_up[12]; // 角度上限,单位:0.01度 - int angle_low[12]; // 角度下限,单位:0.01度 - int speed_up[12]; // 速度上限,单位:无量纲 - int speed_low[12]; // 速度下限,单位:无量纲 - int force_up[12]; // 力上限,单位:0.001N - int force_low[12]; // 力下限,单位:0.001N -} rm_plus_base_info_t; -// 单位:无量纲 -/** - * 末端设备实时信息(末端生态协议支持) -*/ -typedef struct{ - int sys_state; // 系统状态:0正常1设备故障 - int dof_state[12]; // 各自由度当前状态:0正在松开1正在闭合2位置到位停止3力控到位停止4触觉到位停止5电流保护停止6发生故障 - int dof_err[12]; // 各自由度错误信息 - int pos[12]; // 各自由度当前位置,单位:无量纲 - int speed[12]; //各自由度当前速度,闭合正,松开负,单位:无量纲 - int angle[12]; // 各自由度当前角度,单位:0.01度 - int current[12]; // 各自由度当前电流,单位:mA - int normal_force[18]; // 自由度触觉三维力的法向力,1-6自由度触觉三维力的法向力*3 - int tangential_force[18]; // 自由度触觉三维力的切向力 - int tangential_force_dir[18]; // 自由度触觉三维力的切向力方向 - uint32_t tsa[12]; // 自由度触觉自接近 - uint32_t tma[12]; // 自由度触觉互接近 - int touch_data[18]; // 触觉传感器原始数据(示例中有,但未显示数据的JSON情况) - int force[12]; //自由度力矩,闭合正,松开负,单位0.001N -} rm_plus_state_info_t; - - -/** - * @brief udp主动上报机械臂信息 - * -*/ -typedef struct -{ - int errCode; ///< 数据解析错误码,-3为数据解析错误,代表推送的数据不完整或格式不正确 - char arm_ip[16]; ///< 推送数据的机械臂的IP地址 - rm_joint_status_t joint_status; ///< 关节状态 - rm_force_sensor_t force_sensor; ///< 力数据(六维力或一维力版本支持) - rm_err_t err; ///< 错误码 - rm_pose_t waypoint; ///< 当前路点信息 - rm_udp_lift_state_t liftState; ///< 升降关节数据 - rm_udp_expand_state_t expandState; ///< 扩展关节数据 - rm_udp_hand_state_t handState; ///< 灵巧手数据 - rm_udp_arm_current_status_e arm_current_status; ///< 机械臂状态 - rm_udp_aloha_state_t aloha_state; ///< aloha主臂状态 - int rm_plus_state; ///< 末端设备状态,0-设备在线,1-表示协议未开启,2-表示协议开启但是设备不在线 - rm_plus_base_info_t plus_base_info; ///< 末端设备基础信息 - rm_plus_state_info_t plus_state_info; ///< 末端设备实时信息 -}rm_realtime_arm_joint_state_t; - -/** - * @brief 逆解参数 - * @ingroup Algo - */ -typedef struct { - float q_in[ARM_DOF]; ///< 上一时刻关节角度,单位° - rm_pose_t q_pose; ///< 目标位姿 - uint8_t flag; ///< 姿态参数类别:0-四元数;1-欧拉角 -} rm_inverse_kinematics_params_t; - -typedef struct { - int result; // 0:成功,1:逆解失败,-1:上一时刻关节角度输入为空或超关节限位,-2:目标位姿四元数不合法, -3:当前机器人非六自由度,当前仅支持六自由度机器人 - int num; // number of solutions - float q_ref[8]; // 参考关节角度,通常是当前关节角度, 单位 ° - float q_solve[8][8]; // 关节角全解, 单位 ° -} rm_inverse_kinematics_all_solve_t; - -/** - * @brief 包络球描述数据结构 -*/ -typedef struct -{ - float radius; // 球体半径(单位:m) - float centrePoint[3]; // 球体中心位置(单位:m,以法兰坐标系为参考坐标系) -} rm_tool_sphere_t; // 工具包络球参数 - - -/** - * @brief 旋转矩阵 - * @ingroup Algo - */ -typedef struct -{ - short irow; - short iline; - float data[4][4]; -} rm_matrix_t; -/** - * @brief 机械臂事件回调函数 - * @ingroup Init_Class - */ -typedef void (*rm_event_callback_ptr)(rm_event_push_data_t data); -/** - * @brief UDP机械臂状态主动上报回调函数 - * @ingroup Init_Class - */ -typedef void (*rm_realtime_arm_state_callback_ptr)(rm_realtime_arm_joint_state_t data); - -/** - * @brief 机械臂基本信息 - * @ingroup Init_Class - */ -typedef struct -{ - uint8_t arm_dof; ///< 机械臂自由度 - rm_robot_arm_model_e arm_model; ///< 机械臂型号 - rm_force_type_e force_type; ///< 末端力传感器版本 - uint8_t robot_controller_version; ///< 机械臂控制器版本,4:四代控制器,3:三代控制器。 -}rm_robot_info_t; - -/** - * @brief 机械臂控制句柄 - * @ingroup Init_Class - */ -typedef struct { - int id; ///< 句柄id,连接成功id大于0,连接失败返回-1 -}rm_robot_handle; - - -typedef struct -{ - float d[8]; //* unit: m - float a[8]; //* unit: m - float alpha[8]; //* unit: ° - float offset[8]; //* unit: ° -} rm_dh_t; - -/** - * @brief 版本号结构体 - * 不超过10个字符 - * @ingroup ToolCoordinateConfig - * @ingroup WorkCoordinateConfig - */ -typedef struct { - char version[10]; -} rm_version_t; - -/** - * @brief 轨迹信息结构体 - */ -typedef struct { - int point_num; ///< 轨迹点数量 - char name[20]; ///< 轨迹名称 - char create_time[20]; ///< 创建时间 -}rm_trajectory_info_t; -/** - * @brief 轨迹列表结构体 - * @ingroup OnlineProgramming - */ -typedef struct{ - int page_num; ///< 页码 - int page_size; ///< 每页大小 - int total_size; ///< 列表长度 - char vague_search[32]; ///< 模糊搜索 - int list_len; ///<返回符合的轨迹列表长度 - rm_trajectory_info_t tra_list[100]; ///< 返回符合的轨迹列表 -}rm_trajectory_list_t; -/** - * @brief Modbus TCP主站信息结构体 - */ -typedef struct { - char master_name[20]; // Modbus 主站名称,最大长度15个字符,不超过15个字符 - char ip[16]; // TCP主站 IP 地址 - int port; // TCP主站端口号 -}rm_modbus_tcp_master_info_t; -/** - * @brief Modbus TCP主站列表结构体 - */ -typedef struct{ - int page_num; ///< 页码 - int page_size; ///< 每页大小 - int total_size; ///< 列表长度 - char vague_search[32]; ///< 模糊搜索 - int list_len; ///<返回符合的TCP主站列表长度 - rm_modbus_tcp_master_info_t master_list[100]; ///< 返回符合的TCP主站列表 -}rm_modbus_tcp_master_list_t; - -/** - * @brief Modbus RTU读数据参数结构体 - */ -typedef struct { - int address; ///< 数据起始地址 - int device; ///< 外设设备地址 - int type; ///< 0-控制器端modbus主机;1-工具端modbus主机。 - int num; ///< 要读的数据的数量,数据长度不超过109 -}rm_modbus_rtu_read_params_t; -/** - * @brief Modbus RTU写数据结构体 - */ -typedef struct { - int address; ///< 数据起始地址 - int device; ///< 外设设备地址 - int type; ///< 0-控制器端modbus主机;1-工具端modbus主机。 - int num; ///< 要写的数据的数量,最大不超过100 - int data[120]; ///< 要写的数据,数据长度不超过100 -}rm_modbus_rtu_write_params_t; - -/** - * @brief Modbus TCP读数据参数结构体 - */ -typedef struct { - int address; // 数据起始地址 - char master_name[20]; // Modbus 主站名称,最大长度15个字符,不超过15个字符(master_name与IP二选一,若有IP和port优先使用IP和port) - char ip[16]; // 主机连接的 IP 地址(master_name与IP二选一,若有IP和port优先使用IP和port) - int port; // 主机连接的端口号 - int num; // 读取数据数量,最大不超过100 -}rm_modbus_tcp_read_params_t; -/** - * @brief Modbus TCP写数据结构体 - */ -typedef struct { - int address; // 数据起始地址 - char master_name[20]; // Modbus 主站名称,最大长度15个字符,不超过15个字符(master_name与IP二选一,若有IP和port优先使用IP和port) - char ip[16]; // 主机连接的 IP 地址(master_name与IP二选一,若有IP和port优先使用IP和port) - int port; // 主机连接的端口号 - int num; // 写入数据数量,最大不超过100 - int data[120]; // 写入的数据,数据长度不超过100 -}rm_modbus_tcp_write_params_t; - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/third_party/Robotic_Arm/include/rm_interface.h b/third_party/Robotic_Arm/include/rm_interface.h deleted file mode 100644 index 4c36968..0000000 --- a/third_party/Robotic_Arm/include/rm_interface.h +++ /dev/null @@ -1,4517 +0,0 @@ -/** - * @file rm_interface.h - * @brief 该文档声明了机械臂所有操作接口 - * @author aisha - * @version 0.1.0 - * @date 2024.4.20 - * @copyright 睿尔曼智能科技有限公司 - */ - -#ifndef RM_FUNCTION_H -#define RM_FUNCTION_H - -#include "rm_define.h" -#include "rm_interface_global.h" -#include "rm_version.h" -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @defgroup Init_Class 连接机械臂 - * - * 此模块为API及机械臂初始化相关接口,包含API版本号查询、API初始化、连接/断开机械臂、日志设置、 - * 机械臂仿真/真实模式设置、机械臂信息获取、运动到位信息及机械臂实时状态信息回调函数注册等 - * @{ - */ -/** - * @brief 查询sdk版本号 - * @return char* 返回版本号 - * @code - * char *version = rm_api_version(); - * printf("api version: %s\n", version); - * @endcode - */ -RM_INTERFACE_EXPORT char* rm_api_version(void); -/** - * @brief 初始化线程模式 - * - * @param mode RM_SINGLE_MODE_E:单线程模式,单线程非阻塞等待数据返回; - * RM_DUAL_MODE_E:双线程模式,增加接收线程监测队列中的数据; - * RM_TRIPLE_MODE_E:三线程模式,在双线程模式基础上增加线程监测UDP接口数据; - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 创建线程失败。查看日志以获取具体错误 - */ -RM_INTERFACE_EXPORT int rm_init(rm_thread_mode_e mode); - -/** - * @brief 关闭所有连接,销毁所有线程 - * - * @return int 函数执行的状态码。 - - 0: 成功。 - */ -RM_INTERFACE_EXPORT int rm_destory(void); - -/** - * @brief 日志打印配置 - * - * @param LogCallback 日志打印回调函数 - * @param level 日志打印等级,0:debug级别,1:info级别,2:warn:级别,3:error级别 - */ -RM_INTERFACE_EXPORT void rm_set_log_call_back(void (*LogCallback)(const char* message, va_list args),int level); - -/** - * @brief 保存日志到文件 - * - * @param path 日志保存文件路径 - */ -RM_INTERFACE_EXPORT void rm_set_log_save(const char* path); - -/** - * @brief 设置全局超时时间 - * - * @param timeout 接收控制器返回指令超时时间,多数接口默认超时时间为500ms,单位ms - */ -RM_INTERFACE_EXPORT void rm_set_timeout(int timeout); - -/** - * @brief 创建一个机械臂,用于实现对该机械臂的控制 - * - * @param ip 机械臂的ip地址 - * @param port 机械臂的端口号 - * @return rm_robot_handle* 创建成功后,返回机械臂控制句柄,连接成功句柄id大于0,连接失败句柄id返回-1,达到最大连接数5创建失败返回空 - */ -RM_INTERFACE_EXPORT rm_robot_handle *rm_create_robot_arm(const char *ip,int port); - -/** - * @brief 手动设置机械臂自由度 - * - * @param handle 机械臂控制句柄 - * @param dof 机械臂自由度 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 未找到对应句柄,句柄为空或已被删除。 - - -2: 设置失败,自由度设置不合理(负数或者大于10)。 - */ -RM_INTERFACE_EXPORT int rm_set_robot_dof(rm_robot_handle *handle, int dof); - -/** - * @brief 根据句柄删除机械臂 - * - * @param handle 需要删除的机械臂句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 未找到对应句柄,句柄为空或已被删除。 - */ -RM_INTERFACE_EXPORT int rm_delete_robot_arm(rm_robot_handle *handle); -/** - * @brief 机械臂仿真/真实模式设置 - * - * @param handle 机械臂控制句柄 - * @param mode 模式 0:仿真模式 1:真实模式 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_run_mode(rm_robot_handle *handle, int mode); -/** - * @brief 机械臂仿真/真实模式获取 - * - * @param handle 机械臂控制句柄 - * @param mode 模式 0:仿真模式 1:真实模式 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_run_mode(rm_robot_handle *handle,int *mode); -/** - * @brief 获取机械臂基本信息 - * - * @param handle 机械臂控制句柄 - * @param robot_info 存放机械臂基本信息结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 未找到对应句柄,句柄为空或已被删除。 - - -2: 获取到的机械臂基本信息非法,检查句柄是否已被删除。 - */ -RM_INTERFACE_EXPORT int rm_get_robot_info(rm_robot_handle *handle, rm_robot_info_t *robot_info); -/** - * @brief 机械臂事件回调函数注册 - * @details 当机械臂返回运动到位指令或者文件运行结束指令时会有数据返回 - * @attention 单线程无法使用该函数获取到位信息 - * @param handle 机械臂控制句柄 - * @param event_callback 机械臂事件回调函数,该回调函数接收rm_event_push_data_t类型的数据作为参数,没有返回值。 - */ -RM_INTERFACE_EXPORT void rm_get_arm_event_call_back(rm_event_callback_ptr event_callback); -/** - * @brief UDP机械臂状态主动上报信息回调注册 - * - * @param handle 机械臂控制句柄 - * @param realtime_callback 机械臂状态信息回调函数 - */ -RM_INTERFACE_EXPORT void rm_realtime_arm_state_call_back(rm_realtime_arm_state_callback_ptr realtime_callback); -/** @} */ // 结束初始化组的定义 -/** - * @defgroup Joint_Config 关节配置 - * - * 对机械臂的关节参数进行设置,如果关节发生错误,则无法修改关节参数,必须先清除关节错误代码。另外设置关节之前, - * 必须先将关节掉使能,否则会设置不成功。 - * 关节所有参数在修改完成后,会自动保存到关节 Flash,立即生效,之后关节处于掉使能状态,修改完参数后必须 - * 发送指令控制关节上使能。 - * @attention 睿尔曼机械臂在出厂前所有参数都已经配置到最佳状态,一般不建议用户修改关节的底层参数。若用户确需修改,首先 - * 应使机械臂处于非使能状态,然后再发送修改参数指令,参数设置成功后,发送关节恢复使能指令。需要注意的是,关节恢复 - * 使能时,用户需要保证关节处于静止状态,以免上使能过程中关节发生报错。关节正常上使能后,用户方可控制关节运动。 - * @{ - */ -/** - * @brief 设置关节最大速度 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param max_speed 关节最大速度,单位:°/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_max_speed(rm_robot_handle *handle,int joint_num,float max_speed); -/** - * @brief 设置关节最大加速度 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param max_acc 关节最大加速度,单位:°/s² - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_max_acc(rm_robot_handle *handle,int joint_num,float max_acc); -/** - * @brief 设置关节最小限位 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param min_pos 关节最小位置,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_min_pos(rm_robot_handle *handle,int joint_num,float min_pos); -/** - * @brief 设置关节最大限位 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param max_pos 关节最大位置,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_max_pos(rm_robot_handle *handle,int joint_num,float max_pos); -/** - * @brief 设置关节最大速度(驱动器) - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param max_speed 关节最大速度,单位:°/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_drive_max_speed(rm_robot_handle *handle,int joint_num,float max_speed); -/** - * @brief 设置关节最大加速度(驱动器) - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param max_acc 关节最大加速度,单位:°/s² - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_drive_max_acc(rm_robot_handle *handle,int joint_num,float max_acc); -/** - * @brief 设置关节最小限位(驱动器) - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param min_pos 关节最小位置 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_drive_min_pos(rm_robot_handle *handle,int joint_num,float min_pos); -/** - * @brief 设置关节最大限位(驱动器) - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param max_pos 关节最大位置 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_drive_max_pos(rm_robot_handle *handle,int joint_num,float max_pos); -/** - * @brief 设置关节使能状态 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param en_state 1:上使能 0:掉使能 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_en_state(rm_robot_handle *handle,int joint_num,int en_state); -/** - * @brief 设置关节零位 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_zero_pos(rm_robot_handle *handle,int joint_num); -/** - * @brief 清除关节错误代码 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_clear_err(rm_robot_handle *handle,int joint_num); -/** - * @brief 一键设置关节限位 - * - * @param handle 机械臂句柄 - * @param limit_mode 1-正式模式,各关节限位为规格参数中的软限位和硬件限位 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_auto_set_joint_limit(rm_robot_handle *handle,int limit_mode); -/** - * @brief 查询关节最大速度 - * - * @param handle 机械臂句柄 - * @param max_speed 关节1~7转速数组,单位:°/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_max_speed(rm_robot_handle *handle,float *max_speed); -/** - * @brief 查询关节最大加速度 - * - * @param handle 机械臂句柄 - * @param max_acc 关节1~7加速度数组,单位:°/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_max_acc(rm_robot_handle *handle,float *max_acc); -/** - * @brief 查询关节最小限位 - * - * @param handle 机械臂句柄 - * @param min_pos 关节1~7最小位置数组,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_min_pos(rm_robot_handle *handle,float *min_pos); -/** - * @brief 查询关节最大限位 - * - * @param handle 机械臂句柄 - * @param max_pos 关节1~7最大位置数组,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_max_pos(rm_robot_handle *handle,float *max_pos); -/** - * @brief 查询关节(驱动器)最大速度 - * - * @param handle 机械臂句柄 - * @param max_speed 关节1~7转速数组,单位:°/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_drive_max_speed(rm_robot_handle *handle,float *max_speed); -/** - * @brief 查询关节(驱动器)最大加速度 - * - * @param handle 机械臂句柄 - * @param max_acc 关节1~7加速度数组,单位:°/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_drive_max_acc(rm_robot_handle *handle,float *max_acc); -/** - * @brief 查询关节(驱动器)最小限位 - * - * @param handle 机械臂句柄 - * @param min_pos 关节1~7最小位置数组,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_drive_min_pos(rm_robot_handle *handle,float *min_pos); -/** - * @brief 查询关节(驱动器)最大限位 - * - * @param handle 机械臂句柄 - * @param max_pos 关节1~7最大位置数组,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_drive_max_pos(rm_robot_handle *handle,float *max_pos); -/** - * @brief 查询关节使能状态 - * - * @param handle 机械臂句柄 - * @param en_state 关节1~7使能状态数组,1-使能状态,0-掉使能状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_en_state(rm_robot_handle *handle,uint8_t *en_state); -/** - * @brief 查询关节错误代码 - * - * @param handle 机械臂句柄 - * @param err_flag 反馈关节错误代码,错误码请参见 \ref robotic_error - * @param brake_state 反馈关节抱闸状态,1 代表抱闸未打开,0 代表抱闸已打开 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_err_flag(rm_robot_handle *handle,uint16_t *err_flag,uint16_t *brake_state); -/** @} */ // 结束关节配置组的定义 - -/** - * @defgroup ArmTipVelocityParameters 机械臂末端参数配置 - * - * 机械臂末端运动参数设置及获取 - * @{ - */ -/** - * @brief 设置机械臂末端最大线速度 - * - * @param handle 机械臂句柄 - * @param speed 末端最大线速度,单位m/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_max_line_speed(rm_robot_handle *handle,float speed); -/** - * @brief 设置机械臂末端最大线加速度 - * - * @param handle 机械臂句柄 - * @param acc 末端最大线加速度,单位m/s^2 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_max_line_acc(rm_robot_handle *handle,float acc); -/** - * @brief 设置机械臂末端最大角速度 - * - * @param handle 机械臂句柄 - * @param speed 末端最大角速度,单位rad/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_max_angular_speed(rm_robot_handle *handle,float speed); -/** - * @brief 设置机械臂末端最大角加速度 - * - * @param handle 机械臂句柄 - * @param acc 末端最大角加速度,单位rad/s^2 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_max_angular_acc(rm_robot_handle *handle,float acc); -/** - * @brief 设置机械臂末端参数为默认值 - * - * @param handle 机械臂句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_tcp_init(rm_robot_handle *handle); -/** - * @brief 设置机械臂动力学碰撞检测等级 - * - * @param handle 机械臂句柄 - * @param collision_stage 存放碰撞等级值,数据为0-8,0-无碰撞检测,8-碰撞检测最灵敏 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_collision_state(rm_robot_handle *handle,int collision_stage); -/** - * @brief 查询碰撞防护等级 - * - * @param handle 机械臂句柄 - * @param collision_stage 等级,范围:0~8 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_collision_stage(rm_robot_handle *handle,int *collision_stage); -/** - * @brief 获取机械臂末端最大线速度 - * - * @param handle 机械臂句柄 - * @param speed 末端最大线速度,单位m/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_max_line_speed(rm_robot_handle *handle, float *speed); -/** - * @brief 获取机械臂末端最大线加速度 - * - * @param handle 机械臂句柄 - * @param acc 末端最大线加速度,单位m/s^2 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_max_line_acc(rm_robot_handle *handle, float *acc); -/** - * @brief 获取机械臂末端最大角速度 - * - * @param handle 机械臂句柄 - * @param speed 末端最大角速度,单位rad/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_max_angular_speed(rm_robot_handle *handle, float *speed); -/** - * @brief 获取机械臂末端最大角加速度 - * - * @param handle 机械臂句柄 - * @param acc 末端最大角加速度,单位rad/s^2 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_max_angular_acc(rm_robot_handle *handle, float *acc); -/** - * @brief 设置DH参数 - * - * @param handle 机械臂控制句柄 - * @param dh DH参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_DH_data(rm_robot_handle *handle, rm_dh_t dh); -/** - * @brief 获取DH参数 - * - * @param handle 机械臂控制句柄 - * @param dh DH参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_DH_data(rm_robot_handle *handle, rm_dh_t *dh); -/** - * @brief 恢复机械臂默认 DH 参数 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_DH_data_default(rm_robot_handle *handle); -/** @} */ // 结束组的定义 -/** - * @defgroup ToolCoordinateConfig 工具坐标系配置 - * - * 工具坐标系标定、切换、删除、修改、查询及工具包络参数等管理 - * @{ - */ -/** - * @brief 六点法自动设置工具坐标系 标记点位 - * - * @param handle 机械臂控制句柄 - * @param point_num 1~6代表6个标定点 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_auto_tool_frame(rm_robot_handle *handle,int point_num); -/** - * @brief 六点法自动设置工具坐标系 提交 - * - * @param handle 机械臂控制句柄 - * @param name 工具坐标系名称,不能超过十个字节。 - * @param payload 新工具执行末端负载重量 单位kg - * @param x 新工具执行末端负载位置 位置x 单位m - * @param y 新工具执行末端负载位置 位置y 单位m - * @param z 新工具执行末端负载位置 位置z 单位m - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_generate_auto_tool_frame(rm_robot_handle *handle, const char *name,float payload,float x,float y,float z); -/** - * @brief 手动设置工具坐标系 - * - * @param handle 机械臂句柄 - * @param frame 新工具坐标系参数结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 可能情况:要设置的坐标系名称已存在 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_manual_tool_frame(rm_robot_handle *handle, rm_frame_t frame); -/** - * @brief 切换当前工具坐标系 - * - * @param handle 机械臂句柄 - * @param tool_name 目标工具坐标系名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。可能情况:切换的坐标系不存在 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_change_tool_frame(rm_robot_handle *handle, const char* tool_name); -/** - * @brief 删除指定工具坐标系 - * - * @param handle 机械臂句柄 - * @param tool_name 要删除的工具坐标系名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_delete_tool_frame(rm_robot_handle *handle, const char* tool_name); -/** - * @brief 修改指定工具坐标系 - * - * @param handle 机械臂控制句柄 - * @param frame 要修改的工具坐标系参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_update_tool_frame(rm_robot_handle *handle, rm_frame_t frame); -/** - * @brief 获取所有工具坐标系名称 - * - * @param handle 机械臂控制句柄 - * @param frame_names 返回的工具坐标系名称字符数组 - * @param len 返回的工具坐标系名称长度 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_total_tool_frame(rm_robot_handle *handle, rm_frame_name_t *frame_names, int *len); -/** - * @brief 获取指定工具坐标系 - * - * @param handle 机械臂控制句柄 - * @param name 指定的工具坐标系名称 - * @param frame 返回的工具参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。可能情况:查询的工具坐标系不存在 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_given_tool_frame(rm_robot_handle *handle, const char *name, rm_frame_t *frame); -/** - * @brief 获取当前工具坐标系 - * - * @param handle 机械臂控制句柄 - * @param tool_frame 返回的坐标系 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_current_tool_frame(rm_robot_handle *handle, rm_frame_t *tool_frame); -/** - * @brief 设置工具坐标系的包络参数 - * - * @param handle 机械臂控制句柄 - * @param envelope 包络参数列表,每个工具最多支持 5 个包络球,可以没有包络 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_tool_envelope(rm_robot_handle *handle, rm_envelope_balls_list_t envelope); -/** - * @brief 获取工具坐标系的包络参数 - * - * @param handle 机械臂控制句柄 - * @param tool_name 控制器中已存在的工具坐标系名称 - * @param envelope 包络参数列表,每个工具最多支持 5 个包络球,可以没有包络 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回获取失败,可能情况:获取的工具坐标系不存在。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_tool_envelope(rm_robot_handle *handle, const char* tool_name, rm_envelope_balls_list_t *envelope); -/** @} */ // 结束组的定义 - -/** - * @defgroup WorkCoordinateConfig 工作坐标系配置 - * - * 工作坐标系标定、切换、删除、修改、查询等管理 - * @{ - */ -/** - * @brief 三点法自动设置工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param workname 工作坐标系名称,不能超过十个字节。 - * @param point_num 1~3代表3个标定点,依次为原点、X轴一点、Y轴一点,4代表生成坐标系。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_auto_work_frame(rm_robot_handle *handle,const char *workname, int point_num); -/** - * @brief 手动设置工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param work_name 工作坐标系名称,不能超过十个字节。 - * @param pose 新工作坐标系相对于基坐标系的位姿 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_manual_work_frame(rm_robot_handle *handle, const char* work_name, rm_pose_t pose); -/** - * @brief 切换当前工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param work_name 目标工作坐标系名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_change_work_frame(rm_robot_handle *handle, const char* work_name); -/** - * @brief 删除指定工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param work_name 要删除的工作坐标系名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_delete_work_frame(rm_robot_handle *handle, const char* work_name); -/** - * @brief 修改指定工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param work_name 指定工具坐标系名称 - * @param pose 更新工作坐标系相对于基坐标系的位姿 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_update_work_frame(rm_robot_handle *handle, const char* work_name, rm_pose_t pose); -/** - * @brief 获取所有工作坐标系名称 - * - * @param handle 机械臂控制句柄 - * @param frame_names 返回的工作坐标系名称字符数组 - * @param len 返回的工作坐标系名称长度 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_total_work_frame(rm_robot_handle *handle, rm_frame_name_t *frame_names, int *len); -/** - * @brief 获取指定工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param name 指定的工作坐标系名称 - * @param pose 获取到的位姿 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。例如:查询的工具坐标系不存在 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_given_work_frame(rm_robot_handle *handle, const char *name, rm_pose_t *pose); -/** - * @brief 获取当前工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param work_frame 返回的坐标系 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_current_work_frame(rm_robot_handle *handle, rm_frame_t *work_frame); -/** @} */ // 结束组的定义 - -/** - * @defgroup ArmState 机械臂状态查询 - * - * 机械臂当前状态、关节温度、电流、电压查询 - * @{ - */ -/** - * @brief 获取机械臂当前状态 - * - * @param handle 机械臂控制句柄 - * @param state 机械臂当前状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_current_arm_state(rm_robot_handle *handle,rm_current_arm_state_t *state); -/** - * @brief 获取关节当前温度 - * - * @param handle 机械臂控制句柄 - * @param temperature 关节1~7温度数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_current_joint_temperature(rm_robot_handle *handle, float *temperature); -/** - * @brief 获取关节当前电流 - * - * @param handle 机械臂控制句柄 - * @param current 关节1~7电流数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_current_joint_current(rm_robot_handle *handle, float *current); -/** - * @brief 获取关节当前电压 - * - * @param handle 机械臂控制句柄 - * @param voltage 关节1~7电压数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_current_joint_voltage(rm_robot_handle *handle, float *voltage); -/** - * @brief 获取当前关节角度 - * - * @param handle 机械臂控制句柄 - * @param joint 当前7个关节的角度数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_degree(rm_robot_handle *handle, float *joint); -/** - * @brief 获取机械臂所有状态信息 - * - * @param handle 机械臂控制句柄 - * @param state 存储机械臂信息的结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_all_state(rm_robot_handle *handle, rm_arm_all_state_t *state); -/** @} */ // 结束组的定义 - -/** - * @defgroup InitPose 初始位置设置 - * - * 记录机械臂初始位置 - * @{ - */ -/** - * @brief 设置机械臂的初始位置角度 - * - * @param handle 机械臂控制句柄 - * @param joint 机械臂初始位置关节角度数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_init_pose(rm_robot_handle *handle, float *joint); -/** - * @brief 获取机械臂初始位置角度 - * - * @param handle 机械臂控制句柄 - * @param joint 机械臂初始位置关节角度数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_init_pose(rm_robot_handle *handle, float *joint); -/** @} */ // 结束组的定义 - -/** - * @defgroup MovePlan 机械臂轨迹指令类 - * - * 关节运动、笛卡尔空间运动以及角度及位姿透传 - * @{ - */ -/** - * @brief 关节空间运动 - * - * @param handle 机械臂控制句柄 - * @param joint 目标关节1~7角度数组 - * @param v 速度百分比系数,1~100 - * @param r 交融半径百分比系数,0~100。 - * @param trajectory_connect 轨迹连接标志 - * - 0:立即规划并执行轨迹,不与后续轨迹连接。 - * - 1:将当前轨迹与下一条轨迹一起规划,但不立即执行。阻塞模式下,即使发送成功也会立即返回。 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - - -6: 机械臂停止运动规划,外部发送了停止运动指令。 - */ -RM_INTERFACE_EXPORT int rm_movej(rm_robot_handle *handle, const float *joint, int v, int r,int trajectory_connect,int block); -/** - * @brief 笛卡尔空间直线运动 - * - * @param handle 机械臂控制句柄 - * @param pose 目标位姿,位置单位:米,姿态单位:弧度 - * @param v 速度百分比系数,1~100 - * @param r 交融半径百分比系数,0~100。 - * @param trajectory_connect 轨迹连接标志 - * - 0:立即规划并执行轨迹,不与后续轨迹连接。 - * - 1:将当前轨迹与下一条轨迹一起规划,但不立即执行。阻塞模式下,即使发送成功也会立即返回。 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_movel(rm_robot_handle *handle,rm_pose_t pose, int v, int r, int trajectory_connect, int block); -/** - * @brief 笛卡尔空间直线偏移运动 - * @details 该函数用于机械臂末端在当前位姿的基础上沿某坐标系(工具或工作)进行位移或旋转运动。 - * @param handle 机械臂控制句柄 - * @param offset 位置姿态偏移,位置单位:米,姿态单位:弧度 - * @param v 速度百分比系数,1~100 - * @param r 交融半径百分比系数,0~100。 - * @param trajectory_connect 轨迹连接标志 - * - 0:立即规划并执行轨迹,不与后续轨迹连接。 - * - 1:将当前轨迹与下一条轨迹一起规划,但不立即执行。阻塞模式下,即使发送成功也会立即返回。 - * @param frame_type 参考坐标系类型:0-工作,1-工具 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_movel_offset(rm_robot_handle *handle,rm_pose_t offset, int v, int r, int trajectory_connect, int frame_type, int block); -/** - * @brief 样条曲线运动 - * - * @param handle 机械臂控制句柄 - * @param pose 目标位姿,位置单位:米,姿态单位:弧度 - * @param v 速度百分比系数,1~100 - * @param r 交融半径百分比系数,0~100。 - * @param trajectory_connect 轨迹连接标志 - * - 0:立即规划并执行轨迹,不与后续轨迹连接。 - * - 1:将当前轨迹与下一条轨迹一起规划,但不立即执行。阻塞模式下,即使发送成功也会立即返回。 - * @note 样条曲线运动需至少连续下发三个点位(trajectory_connect设置为1),否则运动轨迹为直线 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_moves(rm_robot_handle *handle,rm_pose_t pose, int v, int r, int trajectory_connect, int block); -/** - * @brief 笛卡尔空间圆弧运动 - * - * @param handle 机械臂控制句柄 - * @param pose_via 中间点位姿,位置单位:米,姿态单位:弧度 - * @param pose_to 终点位姿 - * @param v 速度比例1~100,即规划速度和加速度占机械臂末端最大角速度和角加速度的百分比 - * @param r 交融半径百分比系数,0~100。 - * @param loop 规划圈数. - * @param trajectory_connect 轨迹连接标志 - * - 0:立即规划并执行轨迹,不与后续轨迹连接。 - * - 1:将当前轨迹与下一条轨迹一起规划,但不立即执行。阻塞模式下,即使发送成功也会立即返回。 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_movec(rm_robot_handle *handle,rm_pose_t pose_via, rm_pose_t pose_to, int v, int r, int loop, int trajectory_connect, int block); -/** - * @brief 该函数用于关节空间运动到目标位姿 - * - * @param handle 机械臂控制句柄 - * @param pose 目标位姿,位置单位:米,姿态单位:弧度。 - * @param v 速度百分比系数,1~100 - * @param r 交融半径百分比系数,0~100。 - * @param trajectory_connect 轨迹连接标志 - * - 0:立即规划并执行轨迹,不与后续轨迹连接。 - * - 1:将当前轨迹与下一条轨迹一起规划,但不立即执行。阻塞模式下,即使发送成功也会立即返回。 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_movej_p(rm_robot_handle *handle,rm_pose_t pose, int v, int r, int trajectory_connect, int block); -/** - * @brief 角度不经规划,直接通过CANFD透传给机械臂 - * @details 角度透传到 CANFD,若指令正确,机械臂立即执行 - * 备注: - * 透传效果受通信周期和轨迹平滑度影响,因此要求通信周期稳定,避免大幅波动。 - * 用户在使用此功能时,建议进行良好的轨迹规划,以确保机械臂的稳定运行。 - * I系列有线网口周期最快可达2ms,提供了更高的实时性。 - * @param handle 机械臂控制句柄 - * @param config 角度透传模式配置结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - */ -RM_INTERFACE_EXPORT int rm_movej_canfd(rm_robot_handle *handle, rm_movej_canfd_mode_t config); -/** - * @brief 位姿不经规划,直接通过CANFD透传给机械臂 - * @details 当目标位姿被透传到机械臂控制器时,控制器首先尝试进行逆解计算。 - * 若逆解成功且计算出的各关节角度与当前角度差异不大,则直接下发至关节执行,跳过额外的轨迹规划步骤。 - * 这一特性适用于需要周期性调整位姿的场景,如视觉伺服等应用。 - * 备注: - * 透传效果受通信周期和轨迹平滑度影响,因此要求通信周期稳定,避免大幅波动。 - * 用户在使用此功能时,建议进行良好的轨迹规划,以确保机械臂的稳定运行。 - * I系列有线网口周期最快可达2ms,提供了更高的实时性。 - * @param handle 机械臂控制句柄 - * @param config 姿态透传模式结构体 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - -1: 数据发送失败,通信过程中出现问题。 - */ -RM_INTERFACE_EXPORT int rm_movep_canfd(rm_robot_handle *handle, rm_movep_canfd_mode_t config); -/** - * @brief 关节空间跟随运动 - * @param handle 机械臂控制句柄 - * @param joint 关节1~7目标角度数组,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - */ -RM_INTERFACE_EXPORT int rm_movej_follow(rm_robot_handle *handle,float *joint); -/** - * @brief 笛卡尔空间跟随运动 - * @param handle 机械臂控制句柄 - * @param pose 位姿 (优先采用四元数表达) - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - */ -RM_INTERFACE_EXPORT int rm_movep_follow(rm_robot_handle *handle, rm_pose_t pose); -/** @} */ // 结束组的定义 - -/** - * @defgroup ArmMotionControl 机械臂运动控制指令类 - * - * 控制运动的急停、缓停、暂停、继续、清除轨迹以及查询当前规划类型 - * @{ - */ -/** - * @brief 轨迹缓停,在当前正在运行的轨迹上停止 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_slow_stop(rm_robot_handle *handle); -/** - * @brief 轨迹急停,关节最快速度停止,轨迹不可恢复 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_stop(rm_robot_handle *handle); -/** - * @brief 轨迹暂停,暂停在规划轨迹上,轨迹可恢复 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_pause(rm_robot_handle *handle); -/** - * @brief 轨迹暂停后,继续当前轨迹运动 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_continue(rm_robot_handle *handle); -/** - * @brief 清除当前轨迹 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 必须在暂停后使用,否则机械臂会发生意外!!!! - */ -RM_INTERFACE_EXPORT int rm_set_delete_current_trajectory(rm_robot_handle *handle); -/** - * @brief 清除所有轨迹 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 必须在暂停后使用,否则机械臂会发生意外!!!! - */ -RM_INTERFACE_EXPORT int rm_set_arm_delete_trajectory(rm_robot_handle *handle); -/** - * @brief 获取当前正在规划的轨迹信息 - * - * @param handle 机械臂控制句柄 - * @param type 返回的规划类型 - * @param data 无规划和关节空间规划为当前关节1~7角度数组;笛卡尔空间规划则为当前末端位姿 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_current_trajectory(rm_robot_handle *handle,rm_arm_current_trajectory_e *type,float *data); -/** @} */ // 结束组的定义 - -/** - * @defgroup ArmTeachMove 机械臂示教指令类 - * - * 关节、位置、姿态的示教及步进控制 - * @{ - */ -/** - * @brief 关节步进 - * - * @param handle 机械臂控制句柄 - * @param joint_num 关节序号,1~7 - * @param step 步进的角度, - * @param v 速度百分比系数,1~100 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_step(rm_robot_handle *handle,int joint_num, float step, int v, int block); -/** - * @brief 当前工作坐标系下,位置步进 - * - * @param handle 机械臂控制句柄 - * @param type 示教类型 - * @param step 步进的距离,单位m,精确到0.001mm - * @param v 速度百分比系数,1~100 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - * @attention 参考坐标系默认为当前工作坐标系,可调用rm_set_teach_frame修改为工具坐标系, - */ -RM_INTERFACE_EXPORT int rm_set_pos_step(rm_robot_handle *handle, rm_pos_teach_type_e type, float step, int v, int block); -/** - * @brief 当前工作坐标系下,姿态步进 - * - * @param handle 机械臂控制句柄 - * @param type 示教类型 - * @param step 步进的弧度,单位rad,精确到0.001rad - * @param v 速度百分比系数,1~100 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - * @attention 参考坐标系默认为当前工作坐标系,可调用rm_set_teach_frame修改为工具坐标系, - */ -RM_INTERFACE_EXPORT int rm_set_ort_step(rm_robot_handle *handle, rm_ort_teach_type_e type, float step, int v, int block); -/** - * @brief 切换示教运动坐标系 - * - * @param handle 机械臂控制句柄 - * @param frame_type 0: 工作坐标系运动, 1: 工具坐标系运动 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_teach_frame(rm_robot_handle *handle, int frame_type); -/** - * @brief 获取示教参考坐标系 - * - * @param handle 机械臂控制句柄 - * @param frame_type 0: 工作坐标系运动, 1: 工具坐标系运动 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_teach_frame(rm_robot_handle *handle,int *frame_type); -/** - * @brief 关节示教 - * - * @param handle 机械臂控制句柄 - * @param joint_num 示教关节的序号,1~7 - * @param direction 示教方向,0-负方向,1-正方向 - * @param v 速度比例1~100,即规划速度和加速度占关节最大线转速和加速度的百分比 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_teach(rm_robot_handle *handle,int joint_num, int direction, int v); -/** - * @brief 当前工作坐标系下,笛卡尔空间位置示教 - * - * @param handle 机械臂控制句柄 - * @param type 示教类型 - * @param direction 示教方向,0-负方向,1-正方向 - * @param v 即规划速度和加速度占机械臂末端最大线速度和线加速度的百分比 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 参考坐标系默认为当前工作坐标系,可调用rm_set_teach_frame修改为工具坐标系, - */ -RM_INTERFACE_EXPORT int rm_set_pos_teach(rm_robot_handle *handle,rm_pos_teach_type_e type, int direction, int v); -/** - * @brief 当前工作坐标系下,笛卡尔空间姿态示教 - * - * @param handle 机械臂控制句柄 - * @param type 示教类型 - * @param direction 示教方向,0-负方向,1-正方向 - * @param v 速度比例1~100,即规划速度和加速度占机械臂末端最大角速度和角加速度的百分比 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 参考坐标系默认为当前工作坐标系,可调用rm_set_teach_frame修改为工具坐标系, - */ -RM_INTERFACE_EXPORT int rm_set_ort_teach(rm_robot_handle *handle,rm_ort_teach_type_e type, int direction, int v); -/** - * @brief 示教停止 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_stop_teach(rm_robot_handle *handle); -/** @} */ // 结束组的定义 - -/** - * @defgroup ControllerConfig 系统配置 - * - * 控制器状态获取、电源控制、错误清除、有线网口IP地址配置、软件信息获取 - * @{ - */ -/** - * @brief 获取控制器状态 - * - * @param handle 机械臂控制句柄 - * @param voltage 返回的电压 - * @param current 返回的电流 - * @param temperature 返回的温度 - * @param err_flag 控制器运行错误代码 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_controller_state(rm_robot_handle *handle, float *voltage, float *current, float *temperature, int *err_flag); -/** - * @brief 设置机械臂电源 - * - * @param handle 机械臂控制句柄 - * @param arm_power 1-上电状态,0 断电状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_power(rm_robot_handle *handle, int arm_power); -/** - * @brief 读取机械臂电源状态 - * - * @param handle 机械臂控制句柄 - * @param power_state 获取到的机械臂电源状态,1-上电状态,0 断电状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_power_state(rm_robot_handle *handle, int *power_state); -/** - * @brief 读取控制器的累计运行时间 - * - * @param handle 机械臂控制句柄 - * @param day 读取到的时间 - * @param hour 读取到的时间 - * @param min 读取到的时间 - * @param sec 读取到的时间 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_system_runtime(rm_robot_handle *handle, int *day, int *hour, int *min, int *sec); -/** - * @brief 清零控制器的累计运行时间 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_clear_system_runtime(rm_robot_handle *handle); -/** - * @brief 读取关节的累计转动角度 - * - * @param handle 机械臂控制句柄 - * @param joint_odom 各关节累计的转动角度,单位° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_odom(rm_robot_handle *handle, float *joint_odom); -/** - * @brief 清零关节累计转动的角度 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_clear_joint_odom(rm_robot_handle *handle); -/** - * @brief 配置有线网口 IP 地址 - * - * @param handle 机械臂控制句柄 - * @param ip 有线网口 IP 地址 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_NetIP(rm_robot_handle *handle, const char* ip); -/** - * @brief 清除系统错误 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_clear_system_err(rm_robot_handle *handle); -/** - * @brief 读取机械臂软件信息 - * - * @param handle 机械臂控制句柄 - * @param software_info 机械臂软件信息结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_software_info(rm_robot_handle *handle,rm_arm_software_version_t *software_info); -/** - * @brief 查询控制器RS485模式 - * - * @param handle 机械臂控制句柄 - * @param mode 0-代表默认 RS485 串行通讯,1-代表 modbus-RTU 主站模式,2-代表 modbus-RTU 从站模式; - * @param baudrate 波特率 - * @param timeout modbus 协议超时时间,单位 100ms,仅在 modbus-RTU 模式下提供此字段 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_controller_RS485_mode(rm_robot_handle *handle, int* mode, int* baudrate, int* timeout); -/** - * @brief 查询工具端 RS485 模式 - * - * @param handle 机械臂控制句柄 - * @param mode 0-代表默认 RS485 串行通讯 1-代表 modbus-RTU 主站模式 - * @param baudrate 波特率 - * @param timeout modbus 协议超时时间,单位 100ms,仅在 modbus-RTU 模式下提供此字段 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_tool_RS485_mode(rm_robot_handle *handle, int* mode, int* baudrate, int* timeout); -/** - * @brief 查询关节软件版本号 - * - * @param handle 机械臂控制句柄 - * @param version (三代控制器)获取到的各关节软件版本号数组,需转换为十六进制,例如获取某关节版本为54536,转换为十六进制为D508,则当前关节的版本号为 Vd5.0.8 - * @param joint_v (四代控制器)获取到的各关节软件版本号字符串数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_software_version(rm_robot_handle *handle,int *version, rm_version_t *joint_v); -/** - * @brief 查询末端接口板软件版本号 - * - * @param handle 机械臂控制句柄 - * @param version (三代控制器)获取到的末端接口板软件版本号,需转换为十六进制,例如获取到版本号393,转换为十六进制为189,则当前关节的版本号为 V1.8.9 - * @param tool_v (四代控制器)获取到的末端接口板软件版本号字符串 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_tool_software_version(rm_robot_handle *handle, int *version, rm_version_t *tool_v); -/** @} */ // 结束组的定义 - -/** - * @defgroup CommunicationConfig 配置通讯内容 - * - * 机械臂控制器可通过网口、WIFI、RS232-USB 接口和 RS485 接口与用户通信,用户使用时无需切换,可使用上述任一接口, - * 控制器收到指令后,若指令格式正确,则会通过相同的接口反馈数据。 - * @{ - */ -/** - * @brief 配置 wifiAP 模式 - * - * @param handle 机械臂控制句柄 - * @param wifi_name wifi名称 - * @param password wifi密码 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - * @attention 设置成功后蜂鸣器响,手动重启控制器进入 WIFIAP 模式。 - */ -RM_INTERFACE_EXPORT int rm_set_wifi_ap(rm_robot_handle *handle, const char* wifi_name, const char* password); -/** - * @brief 配置WiFi STA模式 - * - * @param handle 机械臂控制句柄 - * @param router_name 路由器名称 - * @param password 路由器Wifi密码 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - * @attention 设置成功后蜂鸣器响,手动重启控制器进入 WIFISTA 模式。 - */ -RM_INTERFACE_EXPORT int rm_set_wifi_sta(rm_robot_handle *handle, const char* router_name, const char* password); - -/** - * @brief 控制器RS485接口波特率设置,设置成功后蜂鸣器响 - * - * @param handle 机械臂控制句柄 - * @param baudrate 波特率:9600,19200,38400,115200和460800,若用户设置其他数据,控制器会默认按照460800处理。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 四代控制器不支持该接口 - * @attention 该指令下发后控制器会记录当前波特率,断电重启后仍会使用该波特率对外通信。 - */ -RM_INTERFACE_EXPORT int rm_set_RS485(rm_robot_handle *handle, int baudrate); -/** - * @brief 获取有线网卡信息,未连接有线网卡则会返回无效数据 - * - * @param handle 机械臂控制句柄 - * @param ip 网络地址 - * @param mask 子网掩码 - * @param mac MAC地址 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_wired_net(rm_robot_handle *handle, char * ip, char * mask, char * mac); -/** - * @brief 查询无线网卡网络信息 - * - * @param handle 机械臂控制句柄 - * @param wifi_net 无线网卡网络信息结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 结构体中的channel值只有在AP模式时才可获取到,标识 wifi 热点的物理信道号 - */ -RM_INTERFACE_EXPORT int rm_get_wifi_net(rm_robot_handle *handle, rm_wifi_net_t *wifi_net); -/** - * @brief 恢复网络出厂设置 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_net_default(rm_robot_handle *handle); -/** - * @brief 配置关闭 wifi 功能,需要重启后生效 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_wifi_close(rm_robot_handle *handle); -/** @} */ // 结束组的定义 - -/** - * @defgroup ControllerIOConfig 控制器IO配置及获取 - * - * 机械臂控制器提供IO端口,用于与外部设备交互。数量和分类如下所示: - * - * @image html io.png - * @{ - */ -/** - * @brief 设置数字IO模式 - * - * @param handle 机械臂控制句柄 - * @param io_num 数字IO端口号,范围:1~4 - * @param config 数字IO配置结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_IO_mode(rm_robot_handle *handle, int io_num, rm_io_config_t config); -/** - * @brief 设置数字IO输出 - * - * @param handle 机械臂控制句柄 - * @param io_num IO 端口号,范围:1~4 - * @param state IO 状态,1-输出高,0-输出低 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_DO_state(rm_robot_handle *handle, int io_num, int state); -/** - * @brief 获取数字 IO 状态 - * - * @param handle 机械臂控制句柄 - * @param config 数字IO配置结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_IO_state(rm_robot_handle *handle, int io_num, rm_io_get_t* config); -/** - * @brief 获取所有 IO 输入状态 - * - * @param handle 机械臂控制句柄 - * @param DI_state 1~4端口数字输入状态数组,1:高,0:低,-1:该端口不是输入模式 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_IO_input(rm_robot_handle *handle, int *DI_state); -/** - * @brief 获取所有 IO 输出状态 - * - * @param handle 机械臂控制句柄 - * @param DO_state 1~4端口数字输出状态数组,1:高,0:低,-1:该端口不是输出模式 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_IO_output(rm_robot_handle *handle, int *DO_state); -/** - * @brief 设置控制器电源输出 - * - * @param handle 机械臂控制句柄 - * @param voltage_type 电源输出类型,0:0V,2:12V,3:24V - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_voltage(rm_robot_handle *handle, int voltage_type); -/** - * @brief 获取控制器电源输出类 - * - * @param handle 机械臂控制句柄 - * @param voltage_type 电源输出类型,0:0V,2:12V,3:24V - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_voltage(rm_robot_handle *handle, int *voltage_type); -/** @} */ // 结束组的定义 - -/** - * @defgroup ToolIOConfig 末端工具 IO 控制 - * - * 机械臂末端工具端提供多种IO端口,用于与外部设备交互。数量和分类如下所示: - * @image html tool_io.png - * @{ - */ -/** - * @brief 设置工具端数字 IO 输出 - * - * @param handle 机械臂控制句柄 - * @param io_num IO 端口号,范围:1~2 - * @param state IO 状态,1-输出高,0-输出低 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_tool_DO_state(rm_robot_handle *handle, int io_num, int state); -/** - * @brief 设置工具端数字 IO 模式 - * - * @param handle 机械臂控制句柄 - * @param io_num IO 端口号,范围:1~2 - * @param io_mode 模式,0-输入状态,1-输出状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_tool_IO_mode(rm_robot_handle *handle, int io_num, int io_mode); -/** - * @brief 获取数字 IO 状态 - * - * @param handle 机械臂控制句柄 - * @param mode 0-输入模式,1-输出模式 - * @param state 0-低,1-高 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_tool_IO_state(rm_robot_handle *handle, int* mode, int* state); -/** - * @brief 设置工具端电源输出 - * - * @param handle 机械臂控制句柄 - * @param voltage_type 电源输出类型,0:0V,1:5V,2:12V,3:24V, - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 电源输出设置为 5V 时,工具端的IO 暂不支持输入输出功能 - */ -RM_INTERFACE_EXPORT int rm_set_tool_voltage(rm_robot_handle *handle, int voltage_type); -/** - * @brief 获取工具端电源输出 - * - * @param handle 机械臂控制句柄 - * @param voltage_type 电源输出类型,0:0V,1:5V,2:12V,3:24V, - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_tool_voltage(rm_robot_handle *handle, int *voltage_type); -/** @} */ // 结束组的定义 - -/** - * @defgroup GripperControl 末端工具—手爪控制 - * - * 睿尔曼机械臂末端配备了因时机器人公司的 EG2-4C2 手爪,为了便于用户操作手爪,机械臂控制器 - * 对用户开放了手爪的控制协议(手爪控制协议与末端modbus 功能互斥) - * @{ - */ -/** - * @brief 设置手爪行程,即手爪开口的最大值和最小值,设置成功后会自动保存,手爪断电不丢失 - * - * @param handle 机械臂控制句柄 - * @param min_limit 手爪开口最小值,范围:0~1000,无单位量纲 - * @param max_limit 手爪开口最大值,范围:0~1000,无单位量纲 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_gripper_route(rm_robot_handle *handle, int min_limit, int max_limit); -/** - * @brief 松开手爪,即手爪以指定的速度运动到开口最大处 - * - * @param handle 机械臂控制句柄 - * @param speed 手爪松开速度,范围 1~1000,无单位量纲 - * @param block true 表示阻塞模式,等待控制器返回夹爪到位指令;false 表示非阻塞模式,不接收夹爪到位指令; - * @param timeout 阻塞模式:设置等待夹爪到位超时时间,单位:秒 - * 非阻塞模式:0-发送后立即返回;其他值-接收设置成功指令后返回; - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 到位设备检验失败 - - -5: 超时 - */ -RM_INTERFACE_EXPORT int rm_set_gripper_release(rm_robot_handle *handle, int speed, bool block, int timeout); -/** - * @brief 手爪力控夹取,手爪以设定的速度和力夹取,当夹持力超过设定的力阈值后,停止夹取 - * - * @param handle 机械臂控制句柄 - * @param speed 手爪夹取速度,范围 1~1000,无单位量纲 - * @param force 力控阈值,范围:50~1000,无单位量纲 - * @param block true 表示阻塞模式,等待控制器返回夹爪到位指令;false 表示非阻塞模式,不接收夹爪到位指令; - * @param timeout 阻塞模式:设置等待夹爪到位超时时间,单位:秒 - * 非阻塞模式:0-发送后立即返回;其他值-接收设置成功指令后返回; - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 到位设备检验失败 - - -5: 超时 - */ -RM_INTERFACE_EXPORT int rm_set_gripper_pick(rm_robot_handle *handle, int speed, int force, bool block, int timeout); -/** - * @brief 手爪持续力控夹取 - * - * @param handle 机械臂控制句柄 - * @param speed 手爪夹取速度,范围 1~1000,无单位量纲 - * @param force 力控阈值,范围:50~1000,无单位量纲 - * @param block true 表示阻塞模式,等待控制器返回夹爪到位指令;false 表示非阻塞模式,不接收夹爪到位指令; - * @param timeout 阻塞模式:设置等待夹爪到位超时时间,单位:秒 - * 非阻塞模式:0-发送后立即返回;其他值-接收设置成功指令后返回; - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 到位设备检验失败 - - -5: 超时 - */ -RM_INTERFACE_EXPORT int rm_set_gripper_pick_on(rm_robot_handle *handle, int speed, int force, bool block, int timeout); -/** - * @brief 设置手爪达到指定位置 - * @details 手爪到达指定位置,当当前开口小于指定开口时,手爪以指定速度松开到指定开口位置;当当前开口大于指定开口时, - * 手爪以指定速度和力矩闭合往指定开口处闭合,当夹持力超过力矩阈值或者达到指定位置后,手爪停止。 - * @param handle 机械臂控制句柄 - * @param position 手爪开口位置,范围:1~1000,无单位量纲 - * @param block true 表示阻塞模式,等待控制器返回夹爪到位指令;false 表示非阻塞模式,不接收夹爪到位指令; - * @param timeout 阻塞模式:设置等待夹爪到位超时时间,单位:秒 - * 非阻塞模式:0-发送后立即返回;其他值-接收设置成功指令后返回; - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 到位设备检验失败 - - -5: 超时 - */ -RM_INTERFACE_EXPORT int rm_set_gripper_position(rm_robot_handle *handle, int position, bool block, int timeout); -/** - * @brief 查询夹爪状态 - * - * @param handle 机械臂控制句柄 - * @param state 夹爪状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 此接口默认不更新数据,从首次控制夹爪开始后,使能更新状态,如果此时控制灵巧手或打开末端modbus功能,将不再更新数据。另外夹爪需要支持最新的固件,方可支持此功能 - */ -RM_INTERFACE_EXPORT int rm_get_gripper_state(rm_robot_handle *handle, rm_gripper_state_t *state); -/** @} */ // 结束组的定义 - -/** - * @defgroup ForceSensor 末端传感器六维力 - * - * 睿尔曼机械臂六维力版末端配备集成式六维力传感器,无需外部走线,用户可直接通过协议对六维力进行操作, - * 获取六维力数据。如下图所示,正上方为六维力的 Z 轴,航插反方向为六维力的 Y 轴,坐标系符合右手定则。 - * 机械臂位于零位姿态时,工具坐标系与六维力的坐标系方向一致。 - * 另外,六维力额定力 200N,额定力矩 8Nm,过载水平 300%FS,工作温度 5~80℃,准度 0.5%FS。使用过程中 - * 注意使用要求,防止损坏六维力传感器。 - * - * @image html force.png "六维力坐标系" - * @{ - */ -/** - * @brief 查询当前六维力传感器得到的力和力矩信息:Fx,Fy,Fz,Mx,My,Mz - * - * @param handle 机械臂控制句柄 - * @param data 力传感器数据结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。可能情况:当前机械臂不是六维力版本。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_force_data(rm_robot_handle *handle, rm_force_data_t *data); -/** - * @brief 将六维力数据清零,标定当前状态下的零位 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_clear_force_data(rm_robot_handle *handle); -/** - * @brief 自动设置六维力重心参数 - * @details 设置六维力重心参数,六维力重新安装后,必须重新计算六维力所受到的初始力和重心。分别在不同姿态下,获取六维力的数据, - * 用于计算重心位置。该指令下发后,机械臂以固定的速度运动到各标定点。 - * 以RM65机械臂为例,四个标定点的关节角度分别为: - * 位置1关节角度:{0,0,-60,0,60,0} - * 位置2关节角度:{0,0,-60,0,-30,0} - * 位置3关节角度:{0,0,-60,0,-30,180} - * 位置4关节角度:{0,0,-60,0,-120,0} - * @attention 必须保证在机械臂静止状态下标定; - * 该过程不可中断,中断后必须重新标定。 - * @param handle 机械臂控制句柄 - * @param block true 表示阻塞模式,等待标定完成后返回;false 表示非阻塞模式,发送后立即返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_force_sensor(rm_robot_handle *handle, bool block); -/** - * @brief 手动标定六维力数据 - * @details 六维力重新安装后,必须重新计算六维力所受到的初始力和重心。该手动标定流程,适用于空间狭窄工作区域,以防自动标定过程中 - * 机械臂发生碰撞,用户可以手动选取四个位置下发,当下发完四个点后,机械臂开始自动沿用户设置的目标运动,并在此过程中计算六维力重心。 - * @attention 上述4个位置必须按照顺序依次下发,当下发完位置4后,机械臂开始自动运行计算重心。 - * @param handle 机械臂控制句柄 - * @param count 点位;1~4 - * @param joint 关节角度,单位:° - * @param block true 表示阻塞模式,等待标定完成后返回;false 表示非阻塞模式,发送后立即返回 - * @return int 函数执行的状态码。 - - 0: 计算成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_manual_set_force(rm_robot_handle *handle, int count, float *joint, bool block); -/** - * @brief 停止标定力传感器重心 - * @details 在标定力传感器过程中,如果发生意外,发送该指令,停止机械臂运动,退出标定流程 - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_stop_set_force_sensor(rm_robot_handle *handle); -/** @} */ // 结束组的定义 - -/** - * @defgroup OneForceSensor 末端传感器一维力 - * - * 睿尔曼机械臂末端接口板集成了一维力传感器,可获取 Z 方向的力,量程200N,准度 0.5%FS。 - * @image html oneforce.png "一维力坐标系" - * @{ - */ -/** - * @brief 查询末端一维力数据 - * - * @param handle 机械臂控制句柄 - * @param data 一维力数据结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 非力控版本机械臂,不支持此功能。 - */ -RM_INTERFACE_EXPORT int rm_get_Fz(rm_robot_handle *handle, rm_fz_data_t *data); -/** - * @brief 清零末端一维力数据,清空一维力数据后,后续所有获取到的数据都是基于当前的偏置。 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_clear_Fz(rm_robot_handle *handle); -/** - * @brief 自动标定一维力数据 - * @details 设置一维力重心参数,一维力重新安装后,必须重新计算一维力所受到的初始力和重心。 - * 分别在不同姿态下,获取一维力的数据,用于计算重心位置,该步骤对于基于一维力的力位混合控制操作具有重要意义。 - * @param handle 机械臂控制句柄 - * @param block true 表示阻塞模式,等待标定完成后返回;false 表示非阻塞模式,发送后立即返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_auto_set_Fz(rm_robot_handle *handle, bool block); -/** - * @brief 手动标定一维力数据 - * @details 设置一维力重心参数,一维力重新安装后,必须重新计算一维力所受到的初始力和重心。该手动标定流程, - * 适用于空间狭窄工作区域,以防自动标定过程中机械臂发生碰撞,用户可以手动选取2个位置下发,当下发完后, - * 机械臂开始自动沿用户设置的目标运动,并在此过程中计算一维力重心。 - * @param handle 机械臂控制句柄 - * @param joint1 位置1关节角度数组,单位:度 - * @param joint2 位置2关节角度数组,单位:度 - * @param block true 表示阻塞模式,等待标定完成后返回;false 表示非阻塞模式,发送后立即返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_manual_set_Fz(rm_robot_handle *handle, float *joint1, float *joint2, bool block); -/** @} */ // 结束组的定义 - -/** - * @defgroup DragTeach 拖动示教 - * - * 睿尔曼机械臂在拖动示教过程中,可记录拖动的轨迹点,并根据用户的指令对轨迹进行复现。 - * @{ - */ -/** - * @brief 拖动示教开始 - * - * @param handle 机械臂控制句柄 - * @param trajectory_record 拖动示教时记录轨迹,0-不记录,1-记录轨迹 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_start_drag_teach(rm_robot_handle *handle, int trajectory_record); -/** - * @brief 拖动示教结束 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_stop_drag_teach(rm_robot_handle *handle); -/** - * @brief 开始复合模式拖动示教 - * @attention 仅支持三代控制器,四代控制器使用rm_start_multi_drag_teach_new - * @param handle 机械臂控制句柄 - * @param mode 拖动示教模式 0-电流环模式,1-使用末端六维力,只动位置,2-使用末端六维力,只动姿态,3-使用末端六维力,位置和姿态同时动 - * @param singular_wall 仅在六维力模式拖动示教中生效,用于指定是否开启拖动奇异墙,0表示关闭拖动奇异墙,1表示开启拖动奇异墙 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口。 - * @note 失败的可能原因: - - 当前机械臂非六维力版本(六维力拖动示教)。 - - 机械臂当前处于 IO 急停状态 - - 机械臂当前处于仿真模式 - - 输入参数有误 - - 使用六维力模式拖动示教时,当前已处于奇异区 - */ -RM_INTERFACE_EXPORT int rm_start_multi_drag_teach(rm_robot_handle *handle, int mode, int singular_wall); -/** - * @brief 开始复合模式拖动示教-新参数 - * - * @param handle 机械臂控制句柄 - * @param teach_state 复合拖动示教参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @note 失败的可能原因: - - 当前机械臂非六维力版本(六维力拖动示教)。 - - 机械臂当前处于 IO 急停状态 - - 机械臂当前处于仿真模式 - - 输入参数有误 - - 使用六维力模式拖动示教时,当前已处于奇异区 - */ -RM_INTERFACE_EXPORT int rm_start_multi_drag_teach_new(rm_robot_handle *handle,rm_multi_drag_teach_t teach_state); -/** - * @brief 设置电流环拖动示教灵敏度 - * - * @param handle 机械臂控制句柄 - * @param grade 等级,0到100,表示0~100%,当设置为100时保持初始状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_drag_teach_sensitivity(rm_robot_handle *handle, int grade); -/** - * @brief 获取电流环拖动示教灵敏度 - * - * @param handle 机械臂控制句柄 - * @param grade 等级,0到100,表示0~100%,当设置为100时保持初始状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_drag_teach_sensitivity(rm_robot_handle *handle, int *grade); -/** - * @brief 运动到轨迹起点 - * @details 轨迹复现前,必须控制机械臂运动到轨迹起点,如果设置正确,机械臂将以20%的速度运动到轨迹起点 - * @param handle 机械臂控制句柄 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - * @see rm_run_drag_trajectory - */ -RM_INTERFACE_EXPORT int rm_drag_trajectory_origin(rm_robot_handle *handle, int block); -/** - * @brief 轨迹复现开始 - * - * @param handle 机械臂控制句柄 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误,请确保机械臂当前位置为拖动示教起点。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - * @attention 必须在拖动示教结束后才能使用,同时保证机械臂位于拖动示教的起点位置,可调用rm_drag_trajectory_origin接口运动至起点位置 - * @see rm_drag_trajectory_origin - */ -RM_INTERFACE_EXPORT int rm_run_drag_trajectory(rm_robot_handle *handle, int block); -/** - * @brief 控制机械臂在轨迹复现过程中的暂停 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_pause_drag_trajectory(rm_robot_handle *handle); -/** - * @brief 控制机械臂在轨迹复现过程中暂停之后的继续, - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_continue_drag_trajectory(rm_robot_handle *handle); -/** - * @brief 控制机械臂在轨迹复现过程中的停止 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_stop_drag_trajectory(rm_robot_handle *handle); -/** - * @brief 保存拖动示教轨迹 - * - * @param handle 机械臂控制句柄 - * @param name 轨迹要保存的文件路径及名称,长度不超过300个字符,例: c:/rm_test.txt - * @param num 轨迹点数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,确保有拖动示教点位可保存。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 文件打开失败 - - -5: 文件名称截取失败 - - -6: 获取到的点位解析错误,保存失败 - */ -RM_INTERFACE_EXPORT int rm_save_trajectory(rm_robot_handle *handle,const char* name, int *num); -/** - * @brief 力位混合控制 - * @details 在笛卡尔空间轨迹规划时,使用该功能可保证机械臂末端接触力恒定,使用时力的方向与机械臂运动方向不能在同一方向。 - * 开启力位混合控制,执行笛卡尔空间运动,接收到运动完成反馈后,需要等待2S后继续下发下一条运动指令。 - * @param handle 机械臂控制句柄 - * @param sensor 0-一维力;1-六维力 - * @param mode 0-基坐标系力控;1-工具坐标系力控; - * @param direction 力控方向;0-沿X轴;1-沿Y轴;2-沿Z轴;3-沿RX姿态方向;4-沿RY姿态方向;5-沿RZ姿态方向 - * @param N 力的大小,单位N - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_force_position(rm_robot_handle *handle, int sensor, int mode, int direction, float N); -/** - * @brief 力位混合控制-新参数 - * @details 在笛卡尔空间轨迹规划时,使用该功能可保证机械臂末端接触力恒定,使用时力的方向与机械臂运动方向不能在同一方向。 - * 开启力位混合控制,执行笛卡尔空间运动,接收到运动完成反馈后,需要等待2S后继续下发下一条运动指令。 - * @param handle 机械臂控制句柄 - * @param param 力位混合控制参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_force_position_new(rm_robot_handle *handle, rm_force_position_t param); - -/** - * @brief 结束力位混合控制 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_stop_force_position(rm_robot_handle *handle); -/** - * @brief 设置六维力拖动示教模式 - * - * @param handle 机械臂控制句柄 - * @param mode 0表示快速拖动模式 1表示精准拖动模式 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 非六维力版本机械臂,不支持此功能。 - */ -RM_INTERFACE_EXPORT int rm_set_force_drag_mode(rm_robot_handle *handle, int mode); -/** - * @brief 获取六维力拖动示教模式 - * - * @param handle 机械臂控制句柄 - * @param mode 0表示快速拖动模式 1表示精准拖动模式 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。处理建议:1、联系睿尔曼公司技术支持确认控制器版本是否支持此功能; - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 非六维力版本机械臂,不支持此功能。 - */ -RM_INTERFACE_EXPORT int rm_get_force_drag_mode(rm_robot_handle *handle, int *mode); -/** @} */ // 结束组的定义 - -/** - * @defgroup HandControl 五指灵巧手 - * - * 睿尔曼机械臂末端配置因时的五指灵巧手,可通过协议对灵巧手进行设置。 - * @{ - */ -/** - * @brief 设置灵巧手目标手势序列号 - * - * @param handle 机械臂控制句柄 - * @param posture_num 预先保存在灵巧手内的手势序号,范围:1~40 - * @param block true 表示阻塞模式,等待灵巧手运动结束后返回;false 表示非阻塞模式,发送后立即返回 - * @param timeout 阻塞模式下超时时间设置,单位:秒 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为灵巧手 - - -5: 超时未返回。 - */ -RM_INTERFACE_EXPORT int rm_set_hand_posture(rm_robot_handle *handle, int posture_num, bool block, int timeout); -/** - * @brief 设置灵巧手目标手势序列号 - * - * @param handle 机械臂控制句柄 - * @param seq_num 预先保存在灵巧手内的手势序号,范围:1~40 - * @param block true 表示阻塞模式,等待灵巧手运动结束后返回;false 表示非阻塞模式,发送后立即返回 - * @param timeout 阻塞模式下超时时间设置,单位:秒 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为灵巧手 - - -5: 超时未返回。 - */ -RM_INTERFACE_EXPORT int rm_set_hand_seq(rm_robot_handle *handle, int seq_num, bool block, int timeout); -/** - * @brief 设置灵巧手各自由度角度 - * @details 设置灵巧手角度,灵巧手有6个自由度,从1~6分别为小拇指,无名指,中指,食指,大拇指弯曲,大拇指旋转 - * @param handle 机械臂控制句柄 - * @param hand_angle 手指角度数组,6个元素分别代表6个自由度的角度,范围:0~1000. 另外,-1代表该自由度不执行任何操作,保持当前状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_hand_angle(rm_robot_handle *handle, const int *hand_angle); -/** - * @brief 设置灵巧手角度跟随控制 - * @details 设置灵巧手跟随角度,灵巧手有6个自由度,从1~6分别为小拇指,无名指,中指,食指,大拇指弯曲,大拇指旋转,最高50Hz的控制频率 - * @param handle 机械臂控制句柄 - * @param hand_angle 手指角度数组,最大表示范围为-32768到+32767,按照灵巧手厂商定义的角度做控制,例如因时的范围为0-2000 - * @param block 设置0时为非阻塞模式;设置1时为阻塞模式,阻塞模式时超时20ms未返回认为接受失败。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_hand_follow_angle(rm_robot_handle *handle, const int *hand_angle, bool block); -/** - * @brief 灵巧手位置跟随控制 - * @details 设置灵巧手跟随位置,灵巧手有6个自由度,从1~6分别为小拇指,无名指,中指,食指,大拇指弯曲,大拇指旋转,最高50Hz的控制频率 - * @param handle 机械臂控制句柄 - * @param hand_pos 手指位置数组,最大范围为0-65535,按照灵巧手厂商定义的角度做控制,例如因时的范围为0-1000 - * @param block 设置0时为非阻塞模式;设置1时为阻塞模式,阻塞模式时超时20ms未返回认为接受失败。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_hand_follow_pos(rm_robot_handle *handle, const int *hand_pos, bool block); -/** - * @brief 设置灵巧手速度 - * - * @param handle 机械臂控制句柄 - * @param speed 手指速度,范围:1~1000 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_hand_speed(rm_robot_handle *handle, int speed); -/** - * @brief 设置灵巧手力阈值 - * - * @param handle 机械臂控制句柄 - * @param hand_force 手指力,范围:1~1000 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_hand_force(rm_robot_handle *handle, int hand_force); -/** @} */ // 结束组的定义 - -/** - * @defgroup ModbusConfig Modbus 配置 - * - * 睿尔曼机械臂在控制器和末端接口板上各提供一个RS485通讯接口,这些接口可通过接口配置为标准的Modbus RTU模式。 - * 在Modbus RTU模式下,用户可通过提供的接口对连接在端口上的外设进行读写操作。 - * - * @attention - * - 控制器的RS485接口在未配置为Modbus RTU模式时,可用于直接控制机械臂。 - * - Modbus RTU模式与机械臂控制模式不兼容。若需恢复机械臂控制模式,必须关闭该端口的Modbus RTU模式。 - * - 关闭Modbus RTU模式后,系统将自动切换回机械臂控制模式,使用波特率460800BPS,停止位1,数据位8,无校验。 - * - * 此外,I系列控制器还支持modbus-TCP主站配置,允许用户配置使用modbus-TCP主站,以连接外部设备的modbus-TCP从站。 - * - * @{ - */ -/** - * @brief 配置通讯端口ModbusRTU模式 - * @details 配置通讯端口ModbusRTU模式,机械臂启动后,要对通讯端口进行任何操作,必须先启动该指令,否则会返回报错信息。 - * 另外,机械臂会对用户的配置方式进行保存,机械臂重启后会自动恢复到用户断电之前配置的模式。 - * @param handle 机械臂控制句柄 - * @param port 通讯端口,0-控制器RS485端口为RTU主站,1-末端接口板RS485接口为RTU主站,2-控制器RS485端口为RTU从站 - * @param baudrate 波特率,支持 9600,115200,460800 三种常见波特率 - * @param timeout 超时时间,单位百毫秒。。对Modbus设备所有的读写指令,在规定的超时时间内未返回响应数据,则返回超时报错提醒。超时时间不能为0,若设置为0,则机械臂按1进行配置。 - * @note 其他配置默认为:数据位-8,停止位-1,奇偶校验-无 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_set_modbus_mode(rm_robot_handle *handle, int port, int baudrate, int timeout); -/** - * @brief 关闭通讯端口 Modbus RTU 模式 - * - * @param handle 机械臂控制句柄 - * @param port 通讯端口,0-控制器RS485端口为RTU主站,1-末端接口板RS485接口为RTU主站,2-控制器RS485端口为RTU从站 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_close_modbus_mode(rm_robot_handle *handle, int port); -/** - * @brief 配置连接 ModbusTCP 从站 - * - * @attention 如需配置连接ModbusTCP从站,则该接口需要在创建机械臂句柄后调用一次,否则在读写寄存器时无法接收到返回值。 - * @param handle 机械臂控制句柄 - * @param ip 从机IP地址 - * @param port 端口号 - * @param timeout 超时时间,单位毫秒。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_set_modbustcp_mode(rm_robot_handle *handle, const char *ip, int port, int timeout); -/** - * @brief 配置关闭 ModbusTCP 从站 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_close_modbustcp_mode(rm_robot_handle *handle); -/** - * @brief 读线圈 - * - * @param handle 机械臂控制句柄 - * @param params 线圈读取参数结构体,该指令最多一次性支持读 8 个线圈数据,即返回的数据不会超过一个字节 - * @param data 返回线圈状态,数据类型:int8 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_coils(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 读离散量输入 - * - * @param handle 机械臂控制句柄 - * @param params 离散量输入读取参数结构体,该指令最多一次性支持读 8 个离散量数据,即返回的数据不会超过一个字节 - * @param data 返回离散量,数据类型:int8 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_input_status(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 读保持寄存器 - * - * @param handle 机械臂控制句柄 - * @param params 保持寄存器数据读取参数结构体,该指令每次只能读 1 个寄存器,即 2 个字节 - * 的数据,不可一次性读取多个寄存器数据,该结构体成员num无需设置 - * @param data 返回寄存器数据,数据类型:int16 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_holding_registers(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 读输入寄存器 - * - * @param handle 机械臂控制句柄 - * @param params 输入寄存器数据读取参数结构体,该指令每次只能读 1 个寄存器,即 2 个字节 - * 的数据,不可一次性读取多个寄存器数据,该结构体成员num无需设置 - * @param data 返回寄存器数据,数据类型:int16 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_input_registers(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 写单圈数据 - * - * @param handle 机械臂控制句柄 - * @param params 单圈数据写入参数结构体,该结构体成员num无需设置 - * @param data 要写入线圈的数据,数据类型:int16 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 写操作失败,超时时间内未获取到数据,或者指令内容错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_write_single_coil(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int data); -/** - * @brief 写单个寄存器 - * - * @param handle 机械臂控制句柄 - * @param params 单个寄存器数据写入参数结构体,该结构体成员num无需设置 - * @param data 要写入寄存器的数据,类型:int16 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 写操作失败,超时时间内未获取到数据,或者指令内容错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_write_single_register(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int data); -/** - * @brief 写多个寄存器 - * - * @param handle 机械臂控制句柄 - * @param params 多个寄存器数据写入参数结构体。其中寄存器每次写的数量不超过10个,即该结构体成员num<=10。 - * @param data 要写入寄存器的数据数组,类型:byte。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 写操作失败,超时时间内未获取到数据,或者指令内容错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_write_registers(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 写多圈数据 - * - * @param handle 机械臂控制句柄 - * @param params 多圈数据写入参数结构体。每次写的数量不超过 160 个,即该结构体成员num<=160。 - * @param data 要写入线圈的数据数组,类型:byte。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 写操作失败,超时时间内未获取到数据,或者指令内容错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_write_coils(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 读多圈数据 - * - * @param handle 机械臂控制句柄 - * @param params 多圈数据读取参数结构体,要读的线圈的数量 8< num <= 120,该指令最多一次性支持读 120 个线圈数据, 即 15 个 byte - * @param data 返回线圈状态,数据类型:int8 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_multiple_coils(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 读多个保存寄存器 - * - * @param handle 机械臂控制句柄 - * @param params 多个保存寄存器读取参数结构体,要读的寄存器的数量 2 < num < 13,该指令最多一次性支持读 12 个寄存器数据, 即 24 个 byte - * @param data 返回寄存器数据,数据类型:int8 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_multiple_holding_registers(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 读多个输入寄存器 - * - * @param handle 机械臂控制句柄 - * @param params 多个输入寄存器读取参数结构体,要读的寄存器的数量 2 < num < 13,该指令最多一次性支持读 12 个寄存器数据, 即 24 个 byte - * @param data 返回寄存器数据,数据类型:int8 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_multiple_input_registers(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** @} */ // 结束组的定义 - -/** - * @defgroup InstallPos 系统安装方式 - * - * 睿尔曼机械臂可支持不同形式的安装方式,但是安装方式不同,机器人的动力学模型参数和坐标系的方向也有所差别。 - * @{ - */ -/** - * @brief 设置安装方式参数 - * - * @param handle 机械臂控制句柄 - * @param x 旋转角,单位 ° - * @param y 俯仰角,单位 ° - * @param z 方位角,单位 ° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_install_pose(rm_robot_handle *handle, float x, float y, float z); -/** - * @brief 获取安装方式参数 - * - * @param handle 机械臂控制句柄 - * @param x 旋转角(out),单位 ° - * @param y 俯仰角(out),单位 ° - * @param z 方位角(out),单位 ° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_install_pose(rm_robot_handle *handle, float *x, float *y, float *z); -/** @} */ // 结束组的定义 - -/** - * @defgroup ForcePositionControl 透传力位混合控制补偿 - * - * 针对睿尔曼带一维力和六维力版本的机械臂,用户除了可直接使用示教器调用底层的力位混合控制模块外,还可以将 - * 自定义的轨迹以周期性透传的形式结合底层的力位混合控制算法进行补偿。 - * - * @attention 该功能只适用于一维力传感器和六维力传感器机械臂版本 - * - * 透传效果和周期、轨迹是否平滑有关,周期要求稳定,防止出现较大波动,用户使用该指令时请做好轨迹规划,轨迹规划的 - * 平滑程度决定了机械臂的运行状态。基础系列 WIFI 和网口模式透传周期最快 20ms,USB 和 RS485 模式透传周期最快 10ms。 - * 高速网口的透传周期最快也可到 10ms,不过在使用该高速网口前,需要使用指令打开配置。另外 I 系列有线网口周期最快可达 2ms。 - * - * @{ - */ -/** - * @brief 开启透传力位混合控制补偿模式 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_start_force_position_move(rm_robot_handle *handle); -/** - * @brief 停止透传力位混合控制补偿模式 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_stop_force_position_move(rm_robot_handle *handle); -/** - * @brief 透传力位混合补偿-角度方式 - * - * @param handle 机械臂控制句柄 - * @param joint 目标关节角度 - * @param sensor 所使用传感器类型,0-一维力,1-六维力 - * @param mode 模式,0-沿基坐标系,1-沿工具端坐标系 - * @param dir 力控方向,0~5分别代表X/Y/Z/Rx/Ry/Rz,其中一维力类型时默认方向为Z方向 - * @param force 力的大小 单位N - * @param follow 是否高跟随 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_force_position_move_joint(rm_robot_handle *handle,const float *joint,int sensor,int mode,int dir,float force, bool follow); -/** - * @brief 透传力位混合补偿-位姿方式 - * - * @param handle 机械臂控制句柄 - * @param pose 当前坐标系下目标位姿 - * @param sensor 所使用传感器类型,0-一维力,1-六维力 - * @param mode 模式,0-沿基坐标系,1-沿工具端坐标系 - * @param dir 力控方向,0~5分别代表X/Y/Z/Rx/Ry/Rz,其中一维力类型时默认方向为Z方向 - * @param force 力的大小 单位N - * @param follow 是否高跟随 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_force_position_move_pose(rm_robot_handle *handle, rm_pose_t pose,int sensor,int mode,int dir,float force, bool follow); -/** - * @brief 透传力位混合补偿-新参数 - * - * @param handle 机械臂控制句柄 - * @param param 透传力位混合补偿参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_force_position_move(rm_robot_handle *handle, rm_force_position_move_t param); -/** @} */ // 结束组的定义 - -/** - * @defgroup LiftControl 升降机构 - * - * 升降机构速度开环控制、位置闭环控制及状态获取 - * @{ - */ -/** - * @brief 升降机构速度开环控制 - * - * @param handle 机械臂控制句柄 - * @param speed 速度百分比,-100~100。 - - speed<0:升降机构向下运动 - - speed>0:升降机构向上运动 - - speed=0:升降机构停止运动 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_lift_speed(rm_robot_handle *handle, int speed); -/** - * @brief 升降机构位置闭环控制 - * - * @param handle 机械臂控制句柄 - * @param speed 速度百分比,1~100 - * @param height 目标高度,单位 mm,范围:0~2600 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待升降机到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 其他值:阻塞模式并设置超时时间,单位为秒。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为升降机构。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_set_lift_height(rm_robot_handle *handle, int speed, int height, int block); -/** - * @brief 获取升降机构状态 - * - * @param handle 机械臂控制句柄 - * @param state 当前升降机构状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_lift_state(rm_robot_handle *handle, rm_expand_state_t *state); -/** @} */ // 结束组的定义 - -/** - * @defgroup ExpandControl 通用扩展关节 - * - * 扩展关节速度环控制、位置环控制及状态获取 - * @{ - */ -/** - * @brief 扩展关节状态获取 - * - * @param handle 机械臂控制句柄 - * @param state 扩展关节状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_expand_state(rm_robot_handle *handle, rm_expand_state_t *state); -/** - * @brief 扩展关节速度环控制 - * - * @param handle 机械臂控制句柄 - * @param speed 速度百分比,-100~100。 - - speed<0:扩展关节反方向运动 - - speed>0:扩展关节正方向运动 - - speed=0:扩展关节停止运动 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_expand_speed(rm_robot_handle *handle, int speed); -/** - * @brief 扩展关节位置环控制 - * - * @param handle 机械臂控制句柄 - * @param speed 速度百分比,1~100 - * @param pos 扩展关节角度,单位度 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待升降机到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 其他值:阻塞模式并设置超时时间,单位为秒。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为扩展关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_set_expand_pos(rm_robot_handle *handle, int speed, int pos, int block); -/** @} */ // 结束组的定义 - -/** - * @defgroup OnlineProgramming 在线编程 - * - * 包含在线编程文件下发、在线编程文件管理、全局路点管理等相关功能接口。 - * @{ - */ -/** - * @brief 文件下发 - * - * @param handle 机械臂控制句柄 - * @param project 文件下发参数配置结构体 - * @param errline 若运行失败,该参数返回有问题的工程行数,err_line 为 0,则代表校验数据长度不对,err_line 为 -1,则代表无错误 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 文件名称校验失败 - - -5: 文件读取失败 - - -6: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_send_project(rm_robot_handle *handle, rm_send_project_t project, int *errline); -/** - * @brief 轨迹规划中改变速度比例系数 - * - * @param handle 机械臂控制句柄 - * @param speed 当前进度条的速度数据 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_plan_speed(rm_robot_handle *handle, int speed); - -/** - * @brief 获取在线编程列表 - * - * @param handle 机械臂控制句柄 - * @param page_num 页码 - * @param page_size 每页大小 - * @param vague_search 模糊搜索 - * @param trajectorys 在线编程程序列表 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_program_trajectory_list(rm_robot_handle *handle, int page_num, int page_size, const char *vague_search,rm_program_trajectorys_t *trajectorys); - -/** - * @brief 开始运行指定编号轨迹 - * - * @param handle 机械臂控制句柄 - * @param id 运行指定的ID,1-100,存在轨迹可运行 - * @param speed 1-100,需要运行轨迹的速度,若设置为0,则按照存储的速度运行 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 运行状态已停止但未接收到运行成功,是否在外部停止了轨迹。 - */ -RM_INTERFACE_EXPORT int rm_set_program_id_run(rm_robot_handle *handle, int id, int speed, int block); -/** - * @brief 查询在线编程运行状态 - * - * @param handle 机械臂控制句柄 - * @param run_state 在线编程运行状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_program_run_state(rm_robot_handle *handle, rm_program_run_state_t *run_state); -/** - * @brief 查询流程图运行状态 - * - * @param handle 机械臂控制句柄 - * @param run_state 流程图运行状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_flowchart_program_run_state(rm_robot_handle *handle, rm_flowchart_run_state_t *run_state); -/** - * @brief 删除指定编号编程文件 - * - * @param handle 机械臂控制句柄 - * @param id 指定编程轨迹的编号 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_delete_program_trajectory(rm_robot_handle *handle, int id); -/** - * @brief 修改指定编号的编程文件 - * - * @param handle 机械臂控制句柄 - * @param id 指定在线编程轨迹编号 - * @param speed 更新后的规划速度比例 1-100 - * @param name 更新后的文件名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_update_program_trajectory(rm_robot_handle *handle, int id, int speed, const char* name); -/** - * @brief 设置 IO 默认运行编号 - * - * @param handle 机械臂控制句柄 - * @param id 设置 IO 默认运行的在线编程文件编号,支持 0-100,0 代表取消设置 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_default_run_program(rm_robot_handle *handle, int id); -/** - * @brief 获取 IO 默认运行编号 - * - * @param handle 机械臂控制句柄 - * @param id IO 默认运行的在线编程文件编号,支持 0-100,0 代表无默认 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_default_run_program(rm_robot_handle *handle, int *id); -/** - * @brief 新增全局路点 - * - * @param handle 机械臂控制句柄 - * @param waypoint 新增全局路点参数(无需输入新增全局路点时间) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_add_global_waypoint(rm_robot_handle *handle, rm_waypoint_t waypoint); -/** - * @brief 更新全局路点 - * - * @param handle 机械臂控制句柄 - * @param waypoint 更新全局路点参数(无需输入更新全局路点时间) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_update_global_waypoint(rm_robot_handle *handle, rm_waypoint_t waypoint); -/** - * @brief 删除全局路点 - * - * @param handle 机械臂控制句柄 - * @param point_name 全局路点名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_delete_global_waypoint(rm_robot_handle *handle, const char* point_name); -/** - * @brief 查询指定全局路点 - * - * @param handle 机械臂控制句柄 - * @param name 指定全局路点名称 - * @param point 返回指定的全局路点参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_given_global_waypoint(rm_robot_handle *handle, const char* name, rm_waypoint_t *point); -/** - * @brief 查询多个全局路点 - * - * @param handle 机械臂控制句柄 - * @param page_num 页码 - * @param page_size 每页大小 - * @param vague_search 模糊搜索 - * @param point_list 返回的全局路点列表 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_global_waypoints_list(rm_robot_handle *handle, int page_num, int page_size, const char *vague_search,rm_waypoint_list_t *point_list); -/** @} */ // 结束在线编程组的定义 - -/** - * @defgroup UdpConfig UDP主动上报 - * - * 睿尔曼机械臂提供 UDP 机械臂状态主动上报接口,使用时,需要和机械臂处于同一局域网络下,通过设置主动上报配置接口的目标 IP或和机械臂建立 TCP 连接, - * 机械臂即会主动周期性上报机械臂状态数据,数据周期可配置,默认 5ms。配置正确并开启三线程模式后,通过注册回调函数可接收并处理主动上报数据。 - * @{ - */ -/** - * @brief 设置 UDP 机械臂状态主动上报配置 - * - * @param handle 机械臂控制句柄 - * @param config UDP配置结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: rm_realtime_push_config_t config参数配置非法。 - */ -RM_INTERFACE_EXPORT int rm_set_realtime_push(rm_robot_handle *handle, rm_realtime_push_config_t config); -/** - * @brief 查询 UDP 机械臂状态主动上报配置 - * - * @param handle 机械臂控制句柄 - * @param config 获取到的UDP机械臂状态主动上报配置 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_realtime_push(rm_robot_handle *handle, rm_realtime_push_config_t *config); -/** @} */ // 结束组的定义 - -/** - * @defgroup Electronic_Fence 电子围栏和虚拟墙 - * - * I 系列机械臂具备电子围栏与虚拟墙功能,并提供了针对控制器所保存的电子围栏或虚拟墙几何模型参数的操作接口。 - * 用户可以通过这些接口,实现对电子围栏或虚拟墙的新增、查询、更新和删除操作,在使用中,可以灵活地使用保存在 - * 控制器中的参数配置,需要注意的是,目前控制器支持保存的参数要求不超过10 个。 - * - * 电子围栏 - * 电子围栏功能通过精确设置参数,确保机械臂的轨迹规划、示教等运动均在设定的电子围栏范围内进行。当机械臂的运动 - * 轨迹可能超出电子围栏的界限时,系统会立即返回相应的错误码,并自动中止运动,从而有效保障机械臂的安全运行。 - * @attention 电子围栏目前仅支持长方体和点面矢量平面这两种形状,并且其仅在仿真模式下生效,为用户提供一个预演轨迹与进行轨迹优化的安全环境。 - * - * 虚拟墙 - * 虚拟墙功能支持在电流环拖动示教与力控拖动示教两种模式下,对拖动范围进行精确限制。在这两种特定的示教模式下,用户可以借助虚拟墙功能,确保 - * 机械臂的拖动操作不会超出预设的范围。 - * @attention 虚拟墙功能目前支持长方体和球体两种形状,并仅在上述两种示教模式下有效。在其他操作模式下,此功能将自动失效。因此,请确保在正确的操作模式 - * 下使用虚拟墙功能,以充分发挥其限制拖动范围的作用。 - * - * @{ - */ -/** - * @brief 新增几何模型参数 - * - * @param handle 机械臂控制句柄 - * @param config 几何模型参数结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: rm_fence_config_t中form设置有误。 - */ -RM_INTERFACE_EXPORT int rm_add_electronic_fence_config(rm_robot_handle *handle, rm_fence_config_t config); -/** - * @brief 更新几何模型参数 - * - * @param handle 机械臂控制句柄 - * @param config 几何模型参数结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: rm_fence_config_t中form设置有误。 - */ -RM_INTERFACE_EXPORT int rm_update_electronic_fence_config(rm_robot_handle *handle, rm_fence_config_t config); -/** - * @brief 删除指定几何模型 - * - * @param handle 机械臂控制句柄 - * @param form_name 几何模型名称,不超过 10 个字节,支持字母、数字、下划线 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_delete_electronic_fence_config(rm_robot_handle *handle, const char* form_name); -/** - * @brief 查询所有几何模型名称 - * - * @param handle 机械臂控制句柄 - * @param names 几何模型名称列表,长度为实际存在几何模型数量 - * @param len 几何模型名称列表长度 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_electronic_fence_list_names(rm_robot_handle *handle, rm_fence_names_t *names, int *len); -/** - * @brief 查询指定几何模型参数 - * - * @param handle 机械臂控制句柄 - * @param name 指定几何模型名称 - * @param config 返回几何模型参数结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_given_electronic_fence_config(rm_robot_handle *handle, const char* name, rm_fence_config_t *config); -/** - * @brief 查询所有几何模型参数 - * - * @param handle 机械臂控制句柄 - * @param config_list 几何模型信息列表,长度为实际存在几何模型数量 - * @param len 几何模型信息列表长度 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_electronic_fence_list_infos(rm_robot_handle *handle, rm_fence_config_list_t *config_list, int *len); -/** - * @brief 设置电子围栏使能状态 - * - * @param handle 机械臂控制句柄 - * @param state 电子围栏使能状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @note 电子围栏功能通过精确设置参数,确保机械臂的轨迹规划、示教等运动均在设定的电子围栏范围内进行。当机械臂的运动轨迹可能超出电子围栏的界限时, - * 系统会立即返回相应的错误码,并自动中止运动,从而有效保障机械臂的安全运行。需要注意的是,电子围栏目前仅支持长方体和点面矢量平面这两种形状,并 - * 且其仅在仿真模式下生效,为用户提供一个预演轨迹与进行轨迹优化的安全环境 - */ -RM_INTERFACE_EXPORT int rm_set_electronic_fence_enable(rm_robot_handle *handle, rm_electronic_fence_enable_t state); -/** - * @brief 获取电子围栏使能状态 - * - * @param handle 机械臂控制句柄 - * @param state 电子围栏使能状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_electronic_fence_enable(rm_robot_handle *handle,rm_electronic_fence_enable_t *state); -/** - * @brief 设置当前电子围栏参数配置 - * - * @param handle 机械臂控制句柄 - * @param config 当前电子围栏参数结构体(无需设置电子围栏名称) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: rm_fence_config_t中form设置有误。 - */ -RM_INTERFACE_EXPORT int rm_set_electronic_fence_config(rm_robot_handle *handle, rm_fence_config_t config); -/** - * @brief 获取当前电子围栏参数 - * - * @param handle 机械臂控制句柄 - * @param config 返回当前电子围栏参数结构体(返回参数中不包含电子围栏名称) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_electronic_fence_config(rm_robot_handle *handle, rm_fence_config_t *config); -/** - * @brief 设置虚拟墙使能状态 - * - * @param handle 机械臂控制句柄 - * @param state 虚拟墙状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_virtual_wall_enable(rm_robot_handle *handle, rm_electronic_fence_enable_t state); -/** - * @brief 获取虚拟墙使能状态 - * - * @param handle 机械臂控制句柄 - * @param state 虚拟墙状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_virtual_wall_enable(rm_robot_handle *handle,rm_electronic_fence_enable_t *state); -/** - * @brief 设置当前虚拟墙参数 - * - * @param handle 机械臂控制句柄 - * @param config 当前虚拟墙参数(无需设置虚拟墙名称) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_virtual_wall_config(rm_robot_handle *handle, rm_fence_config_t config); -/** - * @brief 获取当前虚拟墙参数 - * - * @param handle 机械臂控制句柄 - * @param config 当前虚拟墙参数(返回参数中不包含虚拟墙名称) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_virtual_wall_config(rm_robot_handle *handle, rm_fence_config_t *config); -/** @} */ // 结束电子围栏组的定义 - -/** - * @defgroup SelfCollision 自碰撞安全检测 - * - * 睿尔曼机械臂支持自碰撞安全检测,自碰撞安全检测使能状态下,可确保在轨迹规划、示教等运动过程中机械臂的各个部分不会相互碰撞。 - * @attention 以上自碰撞安全检测功能目前只在仿真模式下生效,用于进行预演轨迹与轨迹优化。 - * @{ - */ -/** - * @brief 设置自碰撞安全检测使能状态 - * - * @param handle 机械臂控制句柄 - * @param state true代表使能,false代表禁使能 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_self_collision_enable(rm_robot_handle *handle, bool state); -/** - * @brief 获取自碰撞安全检测使能状态 - * - * @param handle 机械臂控制句柄 - * @param state true代表使能,false代表禁使能 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_self_collision_enable(rm_robot_handle *handle,bool *state); -/** @} */ // 结束组的定义 - - -/** - * @brief 设置末端生态协议模式 - * @param handle 机械臂控制句柄 - * @param mode 末端生态协议模式 - * 0:禁用协议 - * 9600:开启协议(波特率9600) - * 115200:开启协议(波特率115200) - * 256000:开启协议(波特率256000) - * 460800:开启协议(波特率460800) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 -*/ -RM_INTERFACE_EXPORT int rm_set_rm_plus_mode(rm_robot_handle *handle, int mode); - -/** - * @brief 查询末端生态协议模式 - * @param handle 机械臂控制句柄 - * @param mode 末端生态协议模式 - * 0:禁用协议 - * 9600:开启协议(波特率9600) - * 115200:开启协议(波特率115200) - * 256000:开启协议(波特率256000) - * 460800:开启协议(波特率460800) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * -*/ -RM_INTERFACE_EXPORT int rm_get_rm_plus_mode(rm_robot_handle *handle, int *mode); - -/** - * @brief 设置触觉传感器模式(末端生态协议支持) - * @param handle 机械臂控制句柄 - * @param mode 触觉传感器开关状态 0:关闭触觉传感器 1:打开触觉传感器(返回处理后数据) 2:打开触觉传感器(返回原始数据) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 -*/ -RM_INTERFACE_EXPORT int rm_set_rm_plus_touch(rm_robot_handle *handle, int mode); - -/** - * @brief 查询触觉传感器模式(末端生态协议支持) - * @param handle 机械臂控制句柄 - * @param mode 触觉传感器开关状态 0:关闭触觉传感器 1:打开触觉传感器(返回处理后数据) 2:打开触觉传感器(返回原始数据) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_rm_plus_touch(rm_robot_handle *handle, int *mode); - -/** - * @brief 读取末端设备基础信息(末端生态协议支持) - * @param handle 机械臂控制句柄 - * @param info 末端设备基础信息 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 -*/ -RM_INTERFACE_EXPORT int rm_get_rm_plus_base_info(rm_robot_handle *handle, rm_plus_base_info_t *info); - -/** - * @brief 读取末端设备实时信息(末端生态协议支持) - * @param handle 机械臂控制句柄 - * @param info 末端设备实时信息 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 -*/ -RM_INTERFACE_EXPORT int rm_get_rm_plus_state_info(rm_robot_handle *handle, rm_plus_state_info_t *info); - -/******************************************算法接口*******************************************************/ -/** - * @defgroup Algo 算法接口 - * - * 针对睿尔曼机械臂,提供正逆解、各种位姿参数转换等工具接口。 - * @{ - */ -/** - * @brief 查询算法库版本号 - * @return char* 返回版本号 - * @code - * char *version = rm_algo_version(); - * printf("algo version: %s\n", version); - * @endcode - */ -RM_INTERFACE_EXPORT char* rm_algo_version(void); -/** - * @brief 初始化算法依赖数据(不连接机械臂时调用) - * - * @param Mode 机械臂型号 - * @param Type 传感器型号 - */ -RM_INTERFACE_EXPORT void rm_algo_init_sys_data(rm_robot_arm_model_e Mode, rm_force_type_e Type); -/** - * @brief 设置安装角度 - * - * @param x X轴安装角度 单位° - * @param y Y轴安装角度 单位° - * @param z z轴安装角度 单位° - */ -RM_INTERFACE_EXPORT void rm_algo_set_angle(float x, float y, float z); -/** - * @brief 获取安装角度 - * - * @param x X轴安装角度 单位° - * @param y Y轴安装角度 单位° - * @param z z轴安装角度 单位° - */ -RM_INTERFACE_EXPORT void rm_algo_get_angle(float* x, float* y, float* z); -/** - * @brief 设置工作坐标系 - * - * @param coord_work 坐标系数据(无需设置名称) - */ -RM_INTERFACE_EXPORT void rm_algo_set_workframe(const rm_frame_t* const coord_work); -/** - * @brief 获取当前工作坐标系 - * - * @param coord_work 当前工作坐标系(获取到的坐标系参数,不包括坐标系名称) - */ -RM_INTERFACE_EXPORT void rm_algo_get_curr_workframe(rm_frame_t* coord_work); -/** - * @brief 设置工具坐标系 - * - * @param coord_tool 坐标系数据(无需设置名称) - */ -RM_INTERFACE_EXPORT void rm_algo_set_toolframe(const rm_frame_t* const coord_tool); -/** - * @brief 获取算法当前工具坐标系 - * - * @param coord_tool 当前工具坐标系(获取到的坐标系参数,不包括坐标系名称) - */ -RM_INTERFACE_EXPORT void rm_algo_get_curr_toolframe(rm_frame_t* coord_tool); -/** - * @brief 设置算法关节最大限位 - * - * @param joint_limit 单位° - */ -RM_INTERFACE_EXPORT void rm_algo_set_joint_max_limit(const float* const joint_limit); -/** - * @brief 获取算法关节最大限位 - * - * @param joint_limit 返回关节最大限位 - */ -RM_INTERFACE_EXPORT void rm_algo_get_joint_max_limit(float* joint_limit); -/** - * @brief 设置算法关节最小限位 - * - * @param joint_limit 单位° - */ -RM_INTERFACE_EXPORT void rm_algo_set_joint_min_limit(const float* const joint_limit); -/** - * @brief 获取算法关节最小限位 - * - * @param joint_limit 返回关节最小限位 - */ -RM_INTERFACE_EXPORT void rm_algo_get_joint_min_limit(float* joint_limit); -/** - * @brief 设置算法关节最大速度 - * - * @param joint_slim_max RPM - */ -RM_INTERFACE_EXPORT void rm_algo_set_joint_max_speed(const float* const joint_slim_max); -/** - * @brief 获取算法关节最大速度 - * - * @param joint_slim_max 返回关节最大速度 - */ -RM_INTERFACE_EXPORT void rm_algo_get_joint_max_speed(float* joint_slim_max); -/** - * @brief 设置算法关节最大加速度 - * - * @param joint_alim_max RPM/s - */ -RM_INTERFACE_EXPORT void rm_algo_set_joint_max_acc(const float* const joint_alim_max); -/** - * @brief 获取算法关节最大加速度 - * - * @param joint_alim_max 返回关节最大加速度 - */ -RM_INTERFACE_EXPORT void rm_algo_get_joint_max_acc(float* joint_alim_max); -/** - * @brief 设置逆解求解模式 - * - * @param mode true:遍历模式,冗余参数遍历的求解策略。适于当前位姿跟要求解的位姿差别特别大的应用场景,如MOVJ_P、位姿编辑等,耗时较长 - false:单步模式,自动调整冗余参数的求解策略。适于当前位姿跟要求解的位姿差别特别小、连续周期控制的场景,如笛卡尔空间规划的位姿求解等,耗时短 - */ -RM_INTERFACE_EXPORT void rm_algo_set_redundant_parameter_traversal_mode(bool mode); -/** - * @brief 逆解函数,默认遍历模式,可使用Algo_Set_Redundant_Parameter_Traversal_Mode接口设置逆解求解模式 - * - * @param handle 机械臂控制句柄 - * @param params 逆解输入参数结构体 - * @param q_out 存放输出的关节角度数组 单位° - * @return int 逆解结果 - * - 0: 逆解成功 - * - 1: 逆解失败 - * - -1: 上一时刻关节角度输入为空或超关节限位 - * - -2: 目标位姿四元数不合法 - * @attention 机械臂已连接时,可直接调用该接口进行计算,计算使用的参数均为机械臂当前的参数; - * 未连接机械臂时,需首先调用初始化算法依赖数据接口,并按照实际需求设置使用的坐标系、安装方式及关节速度位置等限制 - *(不设置则按照出厂默认的参数进行计算),此时机械臂控制句柄设置为NULL即可 - */ -RM_INTERFACE_EXPORT int rm_algo_inverse_kinematics(rm_robot_handle *handle, rm_inverse_kinematics_params_t params, float *q_out); - -/** - * @brief 计算逆运动学全解(当前仅支持六自由度机器人) - * @param handle 机械臂控制句柄,连接机械臂时传入机械臂控制句柄,不连接时传入NULL - * @param params 逆解输入参数结构体 - * @return rm_inverse_kinematics_all_solve_t 逆解的全解结构体 -*/ -RM_INTERFACE_EXPORT rm_inverse_kinematics_all_solve_t rm_algo_inverse_kinematics_all(rm_robot_handle *handle, rm_inverse_kinematics_params_t params); - -/** - * @brief 从多解中选取最优解(当前仅支持六自由度机器人) - * @param weight 权重,建议默认值为{1,1,1,1,1,1} - * @param params 待选解的全解结构体 - * @return int 最优解索引,选解结果为ik_solve.q_solve[i],如果没有合适的解返回-1(比如求出8组解,但是8组都有关节角度超限位,那么就返回-1) -*/ -RM_INTERFACE_EXPORT int rm_algo_ikine_select_ik_solve(float *weight, rm_inverse_kinematics_all_solve_t params); - - -/** - * @brief 检查逆解结果是否超出关节限位(当前仅支持六自由度机器人) - * @param q_solve 选解,单位:° - * @return int 0:未超限位,1~dof: 第i个关节超限位 -1:当前机器人非六自由度,当前仅支持六自由度机器人 -*/ -RM_INTERFACE_EXPORT int rm_algo_ikine_check_joint_position_limit(const float* const q_solve); - -/** - * @brief 检查逆解结果是否超速(当前仅支持六自由度机器人) - * @param dt 两帧数据之间的时间间隔,即控制周期,单位sec - * @param q_ref 参考关节角度或者第一帧数据角度,单位:° - * @param q_solve 求解结果,即下一帧要发送的角度 - * @return int 0:表示未超限 i:表示关节i超限,优先报序号小的关节 -1:当前机器人非六自由度,当前仅支持六自由度机器人 -*/ -RM_INTERFACE_EXPORT int rm_algo_ikine_check_joint_velocity_limit(float dt, const float* const q_ref, const float* const q_solve); - - -/** - * @brief 根据参考位形计算臂角大小(仅支持RM75) - * @param q_ref 当前参考位形的关节角度,单位° - * @param arm_angle 计算结果,当前参考位形对应的臂角大小,单位° - * @return int - * 0: 求解成功 - * -1: 求解失败,或机型非RM75 - * -2: q_ref 输入参数非法 - */ -RM_INTERFACE_EXPORT int rm_algo_calculate_arm_angle_from_config_rm75(float *q_ref, float *arm_angle); - -/** - * @brief 臂角法求解RM75逆运动学 - * @param params rm_inverse_kinematics_params_t,逆解参数结构体 - * @param arm_angle 指定轴角大小,单位:° - * @param q_solve 求解结果,单位:° - * @return int - * 0: 求解成功 - * -1: 求解失败 - * -2: 求解结果超出限位 - * -3: 机型非RM75 - */ -RM_INTERFACE_EXPORT int rm_algo_inverse_kinematics_rm75_for_arm_angle(rm_inverse_kinematics_params_t params, float arm_angle, float *q_solve); - -/** - * @brief 通过分析雅可比矩阵最小奇异值, 判断机器人是否处于奇异状态 - * @param q 要判断的关节角度(机械零位描述),单位:° - * @param 最小奇异值阈值,若传NULL,则使用内部默认值,默认值为0.01(该值在0-1之间) - * @return 0:在当前阈值条件下正常 - * -1:表示在当前阈值条件下判断为奇异区 - * -2:表示计算失败 - */ -RM_INTERFACE_EXPORT int rm_algo_universal_singularity_analyse(const float* const q, float singluar_value_limit); -/** - * @brief 设置自定义阈值(仅适用于解析法分析机器人奇异状态) - * @param limit_qe 肘部奇异区域范围设置(即J3接近0的范围),unit: °,default:about 10deg - * @param limit_qw 腕部奇异区域范围设置(即J5接近0的范围),unit: °,default:about 10deg - * @param limit_d 肩部奇异区域范围设置(即腕部中心点距离奇异平面的距离), unit: m, default: 0.05 -*/ -RM_INTERFACE_EXPORT void rm_algo_kin_set_singularity_thresholds(float limit_qe_algo, float limit_qw_algo, float limit_d_algo); -/** - * @brief 获取自定义阈值(仅适用于解析法分析机器人奇异状态) - * - * @param limit_qe 肘部奇异区域范围获取(即J3接近0的范围), unit: °, default: about 10deg - * @param limit_qw 腕部奇异区域范围获取(即J5接近0的范围), unit: °, default: about 10deg - * @param limit_d 肩部奇异区域范围获取(即腕部中心点距离奇异平面的距离), unit: m, default: 0.05 - */ -RM_INTERFACE_EXPORT void rm_algo_kin_get_singularity_thresholds(float* limit_qe_algo, float* limit_qw_algo, float* limit_d_algo); - -/** - * @brief 恢复初始阈值(仅适用于解析法分析机器人奇异状态),阈值初始化为:limit_qe=10deg,limit_qw=10deg,limit_d = 0.05m -*/ -RM_INTERFACE_EXPORT void rm_algo_kin_singularity_thresholds_init(); -/** - * @brief 解析法判断机器人是否处于奇异位形(仅支持六自由度) - * @param q 要判断的关节角度,单位:° - * @param distance 输出参数,返回腕部中心点到肩部奇异平面的距离,该值越接近0说明越接近肩部奇异,单位m,不需要时可传NULL - * @return 0表正常,-1表肩部奇异,-2表肘部奇异,-3表腕部奇异,-4表仅支持6自由度机械臂 -*/ -RM_INTERFACE_EXPORT int rm_algo_kin_robot_singularity_analyse(const float* const q, float *distance); -/** - * @brief 设置工具包络球参数 - * @param toolSphere_i 工具包络球编号 (0~4) - * @param data 工具包络球参数,注意其参数在末端法兰坐标系下描述 - */ -RM_INTERFACE_EXPORT void rm_algo_set_tool_envelope(const int toolSphere_i, rm_tool_sphere_t data); - -/** - * @brief 获取工具包络球参数 - * @param toolSphere_i 工具rm_get_tool_voltage包络球编号 (0~4) - * @param data 工具包络球参数,注意其参数在末端法兰坐标系下描述 - */ -RM_INTERFACE_EXPORT void rm_algo_get_tool_envelope(const int toolSphere_i, rm_tool_sphere_t *data); -/** - * @brief 自碰撞检测 - * @param joint 要判断的关节角度,单位:° - * @return int - * 0: 无碰撞 - * 1: 发生碰撞,超出关节限位将被认为发生碰撞 - */ -RM_INTERFACE_EXPORT int rm_algo_safety_robot_self_collision_detection(float *joint); -/** - * @brief 正解算法接口 - * - * @param handle 机械臂控制句柄,连接机械臂时传入机械臂控制句柄,不连接时传入NULL - * @param joint 关节角度,单位:° - * - * @return rm_pose_t 目标位姿 - * @attention 机械臂已连接时,可直接调用该接口进行计算,计算使用的参数均为机械臂当前的参数; - * 未连接机械臂时,需首先调用初始化算法依赖数据接口,并按照实际需求设置使用的坐标系、安装方式及关节速度位置等限制 - *(不设置则按照出厂默认的参数进行计算),此时机械臂控制句柄设置为NULL即可 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_forward_kinematics(rm_robot_handle *handle,const float* const joint); -/** - * @brief 欧拉角转四元数 - * - * @param eu 欧拉角,单位:rad - * @return rm_quat_t 四元数 - */ -RM_INTERFACE_EXPORT rm_quat_t rm_algo_euler2quaternion(rm_euler_t eu); -/** - * @brief 四元数转欧拉角 - * - * @param qua 四元数 - * @return rm_euler_t 欧拉角 - */ -RM_INTERFACE_EXPORT rm_euler_t rm_algo_quaternion2euler(rm_quat_t qua); -/** - * @brief 欧拉角转旋转矩阵 - * - * @param state 欧拉角,单位:rad - * @return rm_matrix_t 旋转矩阵 - */ -RM_INTERFACE_EXPORT rm_matrix_t rm_algo_euler2matrix(rm_euler_t state); -/** - * @brief 位姿转旋转矩阵 - * - * @param state 位姿 - * @return rm_matrix_t 旋转矩阵 - */ -RM_INTERFACE_EXPORT rm_matrix_t rm_algo_pos2matrix(rm_pose_t state); -/** - * @brief 旋转矩阵转位姿 - * - * @param matrix 旋转矩阵 - * @return rm_pose_t 位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_matrix2pos(rm_matrix_t matrix); -/** - * @brief 基坐标系转工作坐标系 - * - * @param matrix 工作坐标系在基坐标系下的矩阵 - * @param state 工具端坐标在基坐标系下位姿 - * @return rm_pose_t 基坐标系在工作坐标系下的位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_base2workframe(rm_matrix_t matrix, rm_pose_t state); -/** - * @brief 工作坐标系转基坐标系 - * - * @param matrix 工作坐标系在基坐标系下的矩阵 - * @param state 工具端坐标在工作坐标系下位姿 - * @return rm_pose_t 工作坐标系在基坐标系下的位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_workframe2base(rm_matrix_t matrix, rm_pose_t state); -/** - * @brief 计算环绕运动位姿 - * - * @param handle 机械臂控制句柄,连接机械臂时传入机械臂控制句柄,不连接时传入NULL - * @param curr_joint 当前关节角度 单位° - * @param rotate_axis 旋转轴: 1:x轴, 2:y轴, 3:z轴 - * @param rotate_angle 旋转角度: 旋转角度, 单位(度) - * @param choose_axis 指定计算时使用的坐标系 - * @return rm_pose_t 计算位姿结果 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_rotate_move(rm_robot_handle *handle,const float* const curr_joint, int rotate_axis, float rotate_angle, rm_pose_t choose_axis); -/** - * @brief 计算沿工具坐标系运动位姿 - * - * @param handle 机械臂控制句柄,连接机械臂时传入机械臂控制句柄,不连接时传入NULL - * @param curr_joint 当前关节角度,单位:度 - * @param move_lengthx 沿X轴移动长度,单位:米 - * @param move_lengthy 沿Y轴移动长度,单位:米 - * @param move_lengthz 沿Z轴移动长度,单位:米 - * @return rm_pose_t 工作坐标系下的位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_cartesian_tool(rm_robot_handle *handle,const float* const curr_joint, float move_lengthx, - float move_lengthy, float move_lengthz); -/** - * @brief 计算Pos和Rot沿某坐标系有一定的位移和旋转角度后,所得到的位姿数据 - * - * @param handle 机械臂控制句柄,连接机械臂时传入机械臂控制句柄,不连接时传入NULL - * @param poseCurrent 当前时刻位姿(欧拉角形式) - * @param deltaPosAndRot 移动及旋转数组,位置移动(单位:m),旋转(单位:度) - * @param frameMode 坐标系模式选择 0:Work(work即可任意设置坐标系),1:Tool - * @return rm_pose_t 平移旋转后的位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_pose_move(rm_robot_handle *handle,rm_pose_t poseCurrent, const float *deltaPosAndRot, int frameMode); -/** - * @brief 末端位姿转成工具位姿 - * - * @param handle 机械臂控制句柄 - * @param eu_end 基于世界坐标系和默认工具坐标系的末端位姿 - * @return rm_pose_t 基于工作坐标系和工具坐标系的末端位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_end2tool(rm_robot_handle *handle,rm_pose_t eu_end); -/** - * @brief 工具位姿转末端位姿 - * - * @param handle 机械臂控制句柄 - * @param eu_tool 基于工作坐标系和工具坐标系的末端位姿 - * @return rm_pose_t 基于世界坐标系和默认工具坐标系的末端位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_tool2end(rm_robot_handle *handle,rm_pose_t eu_tool); -/** - * @brief 获取DH参数 - * - * @return rm_DH_t DH参数 - */ -RM_INTERFACE_EXPORT rm_dh_t rm_algo_get_dh(); -/** - * @brief 设置DH参数 - * - * @param dh DH参数 - */ -RM_INTERFACE_EXPORT void rm_algo_set_dh(rm_dh_t dh); - -/** @} */ // 结束算法组的定义 - -/*********************************************四代控制器新增接口*******************************************************/ - -/** - * @brief 查询轨迹列表 - * @param handle 机械臂控制句柄 - * @param page_num 页码 - * @param page_size 每页大小 - * @param vague_search 模糊搜索 - * @param list 轨迹列表 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_trajectory_file_list(rm_robot_handle *handle, int page_num, int page_size, const char *vague_search,rm_trajectory_list_t *trajectory_list); -/** - * @brief 开始运行指定轨迹 - * @param handle 机械臂控制句柄 - * @param trajectory_name 轨迹名称 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_set_run_trajectory(rm_robot_handle *handle, const char *trajectory_name); -/** - * @brief 删除指定轨迹 - * @param handle 机械臂控制句柄 - * @param trajectory_name 轨迹名称 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_delete_trajectory_file(rm_robot_handle *handle, const char *trajectory_name); -/** - * @brief 保存轨迹到控制机器 - * @param handle 机械臂控制句柄 - * @param trajectory_name 轨迹名称 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_save_trajectory_file(rm_robot_handle *handle, const char *trajectory_name); - -/** - * @brief 设置机械臂急停状态 - * @param handle 机械臂控制句柄 - * @param state 急停状态,true:急停,false:恢复 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_set_arm_emergency_stop(rm_robot_handle *handle, bool state); -/** - * @brief 新增Modbus TCP主站 - * @param handle 机械臂控制句柄 - * @param master Modbus TCP主站信息 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_add_modbus_tcp_master(rm_robot_handle *handle, rm_modbus_tcp_master_info_t master); -/** - * @brief 修改Modbus TCP主站 - * @param handle 机械臂控制句柄 - * @param master_name Modbus TCP主站名称 - * @param master 要修改的Modbus TCP主站信息 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_update_modbus_tcp_master(rm_robot_handle *handle, const char *master_name, rm_modbus_tcp_master_info_t master); -/** - * @brief 删除Modbus TCP主站 - * @param handle 机械臂控制句柄 - * @param master_name Modbus TCP主站名称 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_delete_modbus_tcp_master(rm_robot_handle *handle, const char *master_name); -/** - * @brief 查询Modbus TCP主站 - * @param handle 机械臂控制句柄 - * @param master_name Modbus TCP主站名称 - * @param master Modbus TCP主站信息 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_modbus_tcp_master(rm_robot_handle *handle, const char *master_name, rm_modbus_tcp_master_info_t *master); -/** - * @brief 查询TCP主站列表 - * @param handle 机械臂控制句柄 - * @param page_num 页码 - * @param page_size 每页大小 - * @param vague_search 模糊搜索 - * @param list TCP主站列表 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_modbus_tcp_master_list(rm_robot_handle *handle, int page_num, int page_size, const char *vague_search,rm_modbus_tcp_master_list_t *list); -/** - * @brief 设置控制器RS485模式(四代控制器支持) - * @param handle 机械臂控制句柄 - * @param mode 0代表默认RS485串行通讯,1代表modbus-RTU主站模式,2-代表modbus-RTU从站模式。 - * @param baudrate 波特率(当前支持9600 19200 38400 57600 115200 230400 460800) - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_set_controller_rs485_mode(rm_robot_handle *handle, int mode, int baudrate); -/** - * @brief 查询控制器RS485模式(四代控制器支持) - * @param handle 机械臂控制句柄 - * @param controller_rs485_mode 0代表默认RS485串行通讯,1代表modbus-RTU主站模式,2-代表modbus-RTU从站模式。 - * @param baudrate 波特率(当前支持9600 19200 38400 57600 115200 230400 460800) - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_controller_rs485_mode_v4(rm_robot_handle *handle, int *controller_rs485_mode, int *baudrate); -/** - * @brief 设置工具端RS485模式(四代控制器支持) - * @param handle 机械臂控制句柄 - * @param mode 通讯端口,0-设置工具端RS485端口为RTU主站,1-设置工具端RS485端口为灵巧手模式,2-设置工具端RS485端口为夹爪模式。 - * @param baudrate 波特率(当前支持9600,115200,460800) - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_set_tool_rs485_mode(rm_robot_handle *handle, int mode, int baudrate); -/** - * @brief 查询工具端RS485模式(四代控制器支持) - * @param handle 机械臂控制句柄 - * @param tool_rs485_mode 0-代表modbus-RTU主站模式,1-代表灵巧手模式,2-代表夹爪模式。 - * @param baudrate 波特率(当前支持9600,115200,460800) - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_tool_rs485_mode_v4(rm_robot_handle *handle, int *tool_rs485_mode, int *baudrate); -/** - * @brief Modbus RTU协议读线圈 - * @param handle 机械臂控制句柄 - * @param param 读线圈参数 - * @param data 读线圈数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_rtu_coils(rm_robot_handle *handle, rm_modbus_rtu_read_params_t param, int *data); -/** - * @brief Modbus RTU协议写线圈 - * @param handle 机械臂控制句柄 - * @param param 写线圈参数 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_write_modbus_rtu_coils(rm_robot_handle *handle, rm_modbus_rtu_write_params_t param); -/** - * @brief Modbus RTU协议读离散量输入 - * @param handle 机械臂控制句柄 - * @param param 读离散输入参数 - * @param data 读离散输入数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_rtu_input_status(rm_robot_handle *handle, rm_modbus_rtu_read_params_t param, int *data); -/** - * @brief Modbus RTU协议读保持寄存器 - * @param handle 机械臂控制句柄 - * @param param 读保持寄存器参数 - * @param data 读保持寄存器数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_rtu_holding_registers(rm_robot_handle *handle, rm_modbus_rtu_read_params_t param, int *data); -/** - * @brief Modbus RTU协议写保持寄存器 - * @param handle 机械臂控制句柄 - * @param param 写保持寄存器参数 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_write_modbus_rtu_registers(rm_robot_handle *handle, rm_modbus_rtu_write_params_t param); -/** - * @brief Modbus RTU协议读输入寄存器 - * @param handle 机械臂控制句柄 - * @param param 读输入寄存器参数 - * @param data 读输入寄存器数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_rtu_input_registers(rm_robot_handle *handle, rm_modbus_rtu_read_params_t param, int *data); -/** - * @brief Modbus TCP协议读线圈 - * @param handle 机械臂控制句柄 - * @param param 读线圈参数 - * @param data 读线圈数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口。 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_tcp_coils(rm_robot_handle *handle, rm_modbus_tcp_read_params_t param, int *data); -/** - * @brief Modbus TCP协议写线圈 - * @param handle 机械臂控制句柄 - * @param param 写线圈参数 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口。 - */ -RM_INTERFACE_EXPORT int rm_write_modbus_tcp_coils(rm_robot_handle *handle, rm_modbus_tcp_write_params_t param); -/** - * @brief Modbus TCP协议读离散量输入 - * @param handle 机械臂控制句柄 - * @param param 读离散输入参数 - * @param data 读离散输入数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口。 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_tcp_input_status(rm_robot_handle *handle, rm_modbus_tcp_read_params_t param, int *data); -/** - * @brief Modbus TCP协议读保持寄存器 - * @param handle 机械臂控制句柄 - * @param param 读保持寄存器参数 - * @param data 读保持寄存器数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口。 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_tcp_holding_registers(rm_robot_handle *handle, rm_modbus_tcp_read_params_t param, int *data); -/** - * @brief Modbus TCP协议写保持寄存器 - * @param handle 机械臂控制句柄 - * @param param 写保持寄存器参数 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口。 - */ -RM_INTERFACE_EXPORT int rm_write_modbus_tcp_registers(rm_robot_handle *handle, rm_modbus_tcp_write_params_t param); -/** - * @brief Modbus TCP协议读输入寄存器 - * @param handle 机械臂控制句柄 - * @param param 读输入寄存器参数 - * @param data 读输入寄存器数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口。 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_tcp_input_registers(rm_robot_handle *handle, rm_modbus_tcp_read_params_t param, int *data); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/third_party/Robotic_Arm/include/rm_interface_global.h b/third_party/Robotic_Arm/include/rm_interface_global.h deleted file mode 100644 index f771b85..0000000 --- a/third_party/Robotic_Arm/include/rm_interface_global.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef RM_INTERFACE_GLOBAL_H -#define RM_INTERFACE_GLOBAL_H - -#ifdef __linux -#define RM_INTERFACE_EXPORT -#endif - -#if _WIN32 -#if defined(RM_INTERFACE_LIBRARY) -# define RM_INTERFACE_EXPORT __declspec(dllexport) -#else -# define RM_INTERFACE_EXPORT __declspec(dllexport) -#endif -#endif - -#endif // RM_INTERFACE_GLOBAL_H diff --git a/third_party/Robotic_Arm/include/rm_service.h b/third_party/Robotic_Arm/include/rm_service.h deleted file mode 100644 index 6050a3b..0000000 --- a/third_party/Robotic_Arm/include/rm_service.h +++ /dev/null @@ -1,4536 +0,0 @@ -#ifndef RM_SERVICE_H -#define RM_SERVICE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "rm_interface.h" -#include "rm_interface_global.h" - -#ifdef __cplusplus -} - -class RM_Service { -public: -/** - * @defgroup Init_Class 初始化及连接 - * - * 此模块为API及机械臂初始化相关接口,包含API版本号查询、API初始化、连接/断开机械臂、日志设置、 - * 机械臂仿真/真实模式设置、机械臂信息获取、运动到位信息及机械臂实时状态信息回调函数注册等 - * @{ - */ -/** - * @brief 查询sdk版本号 - * - * @code - * char *version = rm_api_version(); - * printf("api version: %s\n", version); - * @endcode - * @return char* 返回版本号 - */ -RM_INTERFACE_EXPORT char* rm_api_version(void); -/** - * @brief 初始化线程模式 - * - * @param mode RM_SINGLE_MODE_E:单线程模式,单线程非阻塞等待数据返回; - * RM_DUAL_MODE_E:双线程模式,增加接收线程监测队列中的数据; - * RM_TRIPLE_MODE_E:三线程模式,在双线程模式基础上增加线程监测UDP接口数据; - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 创建线程失败。查看日志以获取具体错误 - * @see rm_create_robot_arm - */ -RM_INTERFACE_EXPORT int rm_init(rm_thread_mode_e mode); - -/** - * @brief 关闭所有连接,销毁所有线程 - * - * @return int 函数执行的状态码。 - - 0: 成功。 - */ -RM_INTERFACE_EXPORT int rm_destory(void); - -/** - * @brief 日志打印配置 - * - * @param LogCallback 日志打印回调函数 - * @param level 日志打印等级,0:debug级别,1:info级别,2:warn:级别,3:error级别 - */ - RM_INTERFACE_EXPORT void rm_set_log_call_back(void (*LogCallback)(const char* message, va_list args),int level); - -/** - * @brief 保存日志到文件 - * - * @param path 日志保存文件路径 - */ -RM_INTERFACE_EXPORT void rm_set_log_save(const char* path); - -/** - * @brief 设置全局超时时间 - * - * @param timeout 接收控制器返回指令超时时间,多数接口默认超时时间为500ms,单位ms - */ -RM_INTERFACE_EXPORT void rm_set_timeout(int timeout); - -/** - * @brief 创建一个机械臂,用于实现对该机械臂的控制 - * - * @param ip 机械臂的ip地址 - * @param port 机械臂的端口号 - * @return rm_robot_handle* 创建成功后,返回机械臂控制句柄,达到最大连接数5或者连接失败返回空 - * @see rm_init - */ -RM_INTERFACE_EXPORT rm_robot_handle *rm_create_robot_arm(const char *ip,int port); - -/** - * @brief 手动设置机械臂自由度 - * - * @param handle 机械臂控制句柄 - * @param dof 机械臂自由度 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 未找到对应句柄,句柄为空或已被删除。 - - -2: 设置失败,自由度设置不合理(负数或者大于10)。 - */ -RM_INTERFACE_EXPORT int rm_set_robot_dof(rm_robot_handle *handle, int dof); -/** - * @brief 根据句柄删除机械臂 - * - * @param handle 需要删除的机械臂句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 未找到对应句柄,句柄为空或已被删除。 - */ -RM_INTERFACE_EXPORT int rm_delete_robot_arm(rm_robot_handle *handle); -/** - * @brief 机械臂仿真/真实模式设置 - * - * @param handle 机械臂控制句柄 - * @param mode 模式 0:仿真 1:真实 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_run_mode(rm_robot_handle *handle, int mode); -/** - * @brief 机械臂仿真/真实模式获取 - * - * @param handle 机械臂控制句柄 - * @param mode 模式 0:仿真 1:真实 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_run_mode(rm_robot_handle *handle,int *mode); -/** - * @brief 获取机械臂基本信息 - * - * @param handle 机械臂控制句柄 - * @param robot_info 机械臂基本信息结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 未找到对应句柄,句柄为空或已被删除。 - - -2: 获取到的机械臂基本信息非法,检查句柄是否已被删除。 - */ -RM_INTERFACE_EXPORT int rm_get_robot_info(rm_robot_handle *handle, rm_robot_info_t *robot_info); -/** - * @brief 机械臂事件回调注册 - * - * @param handle 机械臂控制句柄 - * @param event_callback 机械臂事件回调函数 - */ -RM_INTERFACE_EXPORT void rm_get_arm_event_call_back(rm_event_callback_ptr event_callback); -/** - * @brief UDP机械臂状态主动上报信息回调注册 - * - * @param handle 机械臂控制句柄 - * @param realtime_callback 机械臂状态信息回调函数 - */ -RM_INTERFACE_EXPORT void rm_realtime_arm_state_call_back(rm_realtime_arm_state_callback_ptr realtime_callback); -/** @} */ // 结束初始化组的定义 -/** - * @defgroup Joint_Config 关节配置 - * - * 对机械臂的关节参数进行设置,如果关节发生错误,则无法修改关节参数,必须先清除关节错误代码。另外设置关节之前, - * 必须先将关节掉使能,否则会设置不成功。 - * 关节所有参数在修改完成后,会自动保存到关节 Flash,立即生效,之后关节处于掉使能状态,修改完参数后必须 - * 发送指令控制关节上使能。 - * @attention 睿尔曼机械臂在出厂前所有参数都已经配置到最佳状态,一般不建议用户修改关节的底层参数。若用户确需修改,首先 - * 应使机械臂处于非使能状态,然后再发送修改参数指令,参数设置成功后,发送关节恢复使能指令。需要注意的是,关节恢复 - * 使能时,用户需要保证关节处于静止状态,以免上使能过程中关节发生报错。关节正常上使能后,用户方可控制关节运动。 - * @{ - */ -/** - * @brief 设置关节最大速度 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param max_speed 关节最大速度,单位:°/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_max_speed(rm_robot_handle *handle,int joint_num,float max_speed); -/** - * @brief 设置关节最大加速度 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param max_acc 关节最大加速度,单位:°/s² - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_max_acc(rm_robot_handle *handle,int joint_num,float max_acc); -/** - * @brief 设置关节最小限位 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param min_pos 关节最小位置,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_min_pos(rm_robot_handle *handle,int joint_num,float min_pos); -/** - * @brief 设置关节最大限位 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param max_pos 关节最大位置,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_max_pos(rm_robot_handle *handle,int joint_num,float max_pos); -/** - * @brief 设置关节最大速度(驱动器) - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param max_speed 关节最大速度,单位:°/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_drive_max_speed(rm_robot_handle *handle,int joint_num,float max_speed); -/** - * @brief 设置关节最大加速度(驱动器) - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param max_acc 关节最大加速度,单位:°/s² - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_drive_max_acc(rm_robot_handle *handle,int joint_num,float max_acc); -/** - * @brief 设置关节最小限位(驱动器) - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param min_pos 关节最小位置 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_drive_min_pos(rm_robot_handle *handle,int joint_num,float min_pos); -/** - * @brief 设置关节最大限位(驱动器) - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param max_pos 关节最大位置 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_drive_max_pos(rm_robot_handle *handle,int joint_num,float max_pos); -/** - * @brief 设置关节使能状态 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @param en_state 1:上使能 0:掉使能 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_en_state(rm_robot_handle *handle,int joint_num,int en_state); -/** - * @brief 设置关节零位 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_zero_pos(rm_robot_handle *handle,int joint_num); -/** - * @brief 清除关节错误代码 - * - * @param handle 机械臂句柄 - * @param joint_num 关节序号 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_clear_err(rm_robot_handle *handle,int joint_num); -/** - * @brief 一键设置关节限位 - * - * @param handle 机械臂句柄 - * @param limit_mode 1-正式模式,各关节限位为规格参数中的软限位和硬件限位 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_auto_set_joint_limit(rm_robot_handle *handle,int limit_mode); -/** - * @brief 查询关节最大速度 - * - * @param handle 机械臂句柄 - * @param max_speed 关节1~7转速数组,单位:°/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_max_speed(rm_robot_handle *handle,float *max_speed); -/** - * @brief 查询关节最大加速度 - * - * @param handle 机械臂句柄 - * @param max_acc 关节1~7加速度数组,单位:°/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_max_acc(rm_robot_handle *handle,float *max_acc); -/** - * @brief 查询关节最小限位 - * - * @param handle 机械臂句柄 - * @param min_pos 关节1~7最小位置数组,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_min_pos(rm_robot_handle *handle,float *min_pos); -/** - * @brief 查询关节最大限位 - * - * @param handle 机械臂句柄 - * @param max_pos 关节1~7最大位置数组,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_max_pos(rm_robot_handle *handle,float *max_pos); -/** - * @brief 查询关节(驱动器)最大速度 - * - * @param handle 机械臂句柄 - * @param max_speed 关节1~7转速数组,单位:°/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_drive_max_speed(rm_robot_handle *handle,float *max_speed); -/** - * @brief 查询关节(驱动器)最大加速度 - * - * @param handle 机械臂句柄 - * @param max_acc 关节1~7加速度数组,单位:°/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_drive_max_acc(rm_robot_handle *handle,float *max_acc); -/** - * @brief 查询关节(驱动器)最小限位 - * - * @param handle 机械臂句柄 - * @param min_pos 关节1~7最小位置数组,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_drive_min_pos(rm_robot_handle *handle,float *min_pos); -/** - * @brief 查询关节(驱动器)最大限位 - * - * @param handle 机械臂句柄 - * @param max_pos 关节1~7最大位置数组,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_drive_max_pos(rm_robot_handle *handle,float *max_pos); -/** - * @brief 查询关节使能状态 - * - * @param handle 机械臂句柄 - * @param en_state 关节1~7使能状态数组,1-使能状态,0-掉使能状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_en_state(rm_robot_handle *handle,uint8_t *en_state); -/** - * @brief 查询关节错误代码 - * - * @param handle 机械臂句柄 - * @param err_flag 反馈关节错误代码,错误码请参见 \ref robotic_error - * @param brake_state 反馈关节抱闸状态,1 代表抱闸未打开,0 代表抱闸已打开 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_err_flag(rm_robot_handle *handle,uint16_t *err_flag,uint16_t *brake_state); -/** @} */ // 结束关节配置组的定义 - -/** - * @defgroup ArmTipVelocityParameters 机械臂末端参数配置 - * - * 机械臂末端运动参数设置及获取 - * @{ - */ -/** - * @brief 设置机械臂末端最大线速度 - * - * @param handle 机械臂句柄 - * @param speed 末端最大线速度,单位m/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_max_line_speed(rm_robot_handle *handle,float speed); -/** - * @brief 设置机械臂末端最大线加速度 - * - * @param handle 机械臂句柄 - * @param acc 末端最大线加速度,单位m/s^2 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_max_line_acc(rm_robot_handle *handle,float acc); -/** - * @brief 设置机械臂末端最大角速度 - * - * @param handle 机械臂句柄 - * @param speed 末端最大角速度,单位rad/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_max_angular_speed(rm_robot_handle *handle,float speed); -/** - * @brief 设置机械臂末端最大角加速度 - * - * @param handle 机械臂句柄 - * @param acc 末端最大角加速度,单位rad/s^2 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_max_angular_acc(rm_robot_handle *handle,float acc); -/** - * @brief 设置机械臂末端参数为默认值 - * - * @param handle 机械臂句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_tcp_init(rm_robot_handle *handle); -/** - * @brief 设置机械臂动力学碰撞检测等级 - * - * @param handle 机械臂句柄 - * @param collision_stage 等级:0~8,0-无碰撞,8-碰撞最灵敏 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_collision_state(rm_robot_handle *handle,int collision_stage); -/** - * @brief 查询碰撞防护等级 - * - * @param handle 机械臂句柄 - * @param collision_stage 等级,范围:0~8 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_collision_stage(rm_robot_handle *handle,int *collision_stage); -/** - * @brief 获取机械臂末端最大线速度 - * - * @param handle 机械臂句柄 - * @param speed 末端最大线速度,单位m/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_max_line_speed(rm_robot_handle *handle, float *speed); -/** - * @brief 获取机械臂末端最大线加速度 - * - * @param handle 机械臂句柄 - * @param acc 末端最大线加速度,单位m/s^2 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_max_line_acc(rm_robot_handle *handle, float *acc); -/** - * @brief 获取机械臂末端最大角速度 - * - * @param handle 机械臂句柄 - * @param speed 末端最大角速度,单位rad/s - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_max_angular_speed(rm_robot_handle *handle, float *speed); -/** - * @brief 获取机械臂末端最大角加速度 - * - * @param handle 机械臂句柄 - * @param acc 末端最大角加速度,单位rad/s^2 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_max_angular_acc(rm_robot_handle *handle, float *acc); -/** - * @brief 设置DH参数 - * - * @param handle 机械臂控制句柄 - * @param dh DH参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_DH_data(rm_robot_handle *handle, rm_dh_t dh); -/** - * @brief 获取DH参数 - * - * @param handle 机械臂控制句柄 - * @param dh DH参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_DH_data(rm_robot_handle *handle, rm_dh_t *dh); -/** - * @brief 恢复机械臂默认 DH 参数 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_DH_data_default(rm_robot_handle *handle); -/** @} */ // 结束组的定义 -/** - * @defgroup ToolCoordinateConfig 工具坐标系配置 - * - * 工具坐标系标定、切换、删除、修改、查询及工具包络参数等管理 - * @{ - */ -/** - * @brief 六点法自动设置工具坐标系 标记点位 - * - * @param handle 机械臂控制句柄 - * @param point_num 1~6代表6个标定点 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_auto_tool_frame(rm_robot_handle *handle,int point_num); -/** - * @brief 六点法自动设置工具坐标系 提交 - * - * @param handle 机械臂控制句柄 - * @param name 工具坐标系名称,不能超过十个字节。 - * @param payload 新工具执行末端负载重量 单位kg - * @param x 新工具执行末端负载位置 位置x 单位m - * @param y 新工具执行末端负载位置 位置y 单位m - * @param z 新工具执行末端负载位置 位置z 单位m - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_generate_auto_tool_frame(rm_robot_handle *handle, const char *name,float payload,float x,float y,float z); -/** - * @brief 手动设置工具坐标系 - * - * @param handle 机械臂句柄 - * @param frame 新工具坐标系参数结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_manual_tool_frame(rm_robot_handle *handle, rm_frame_t frame); -/** - * @brief 切换当前工具坐标系 - * - * @param handle 机械臂句柄 - * @param tool_name 目标工具坐标系名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_change_tool_frame(rm_robot_handle *handle, const char* tool_name); -/** - * @brief 删除指定工具坐标系 - * - * @param handle 机械臂句柄 - * @param tool_name 要删除的工具坐标系名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_delete_tool_frame(rm_robot_handle *handle, const char* tool_name); -/** - * @brief 修改指定工具坐标系 - * - * @param handle 机械臂控制句柄 - * @param frame 要修改的工具坐标系名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_update_tool_frame(rm_robot_handle *handle, rm_frame_t frame); -/** - * @brief 获取所有工作坐标系名称 - * - * @param handle 机械臂控制句柄 - * @param frame_names 返回的工作坐标系名称字符数组 - * @param len 返回的工作坐标系名称长度 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_total_tool_frame(rm_robot_handle *handle, rm_frame_name_t *frame_names, int *len); -/** - * @brief 获取指定工具坐标系 - * - * @param handle 机械臂控制句柄 - * @param name 指定的工具坐标系名称 - * @param frame 返回的工具参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_given_tool_frame(rm_robot_handle *handle, const char *name, rm_frame_t *frame); -/** - * @brief 获取当前工具坐标系 - * - * @param handle 机械臂控制句柄 - * @param tool_frame 返回的坐标系 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_current_tool_frame(rm_robot_handle *handle, rm_frame_t *tool_frame); -/** - * @brief 设置工具坐标系的包络参数 - * - * @param handle 机械臂控制句柄 - * @param envelope 包络参数列表,每个工具最多支持 5 个包络球,可以没有包络 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_tool_envelope(rm_robot_handle *handle, rm_envelope_balls_list_t envelope); -/** - * @brief 获取工具坐标系的包络参数 - * - * @param handle 机械臂控制句柄 - * @param tool_name 控制器中已存在的工具坐标系名称 - * @param envelope 包络参数列表,每个工具最多支持 5 个包络球,可以没有包络 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回获取失败,检查工具坐标系是否存在。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_tool_envelope(rm_robot_handle *handle, const char* tool_name, rm_envelope_balls_list_t *envelope); -/** @} */ // 结束组的定义 - -/** - * @defgroup WorkCoordinateConfig 工作坐标系配置 - * - * 工作坐标系标定、切换、删除、修改、查询等管理 - * @{ - */ -/** - * @brief 三点法自动设置工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param workname 工作坐标系名称,不能超过十个字节。 - * @param point_num 1~3代表3个标定点,依次为原点、X轴一点、Y轴一点,4代表生成坐标系。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_auto_work_frame(rm_robot_handle *handle,const char *workname, int point_num); -/** - * @brief 手动设置工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param work_name 工作坐标系名称,不能超过十个字节。 - * @param pose 新工作坐标系相对于基坐标系的位姿 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_manual_work_frame(rm_robot_handle *handle, const char* work_name, rm_pose_t pose); -/** - * @brief 切换当前工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param work_name 目标工作坐标系名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_change_work_frame(rm_robot_handle *handle, const char* work_name); -/** - * @brief 删除指定工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param work_name 要删除的工具坐标系名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_delete_work_frame(rm_robot_handle *handle, const char* work_name); -/** - * @brief 修改指定工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param work_name 指定工具坐标系名称 - * @param pose 更新工作坐标系相对于基坐标系的位姿 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_update_work_frame(rm_robot_handle *handle, const char* work_name, rm_pose_t pose); -/** - * @brief 获取所有工作坐标系名称 - * - * @param handle 机械臂控制句柄 - * @param frame_names 返回的工作坐标系名称字符数组 - * @param len 返回的工作坐标系名称长度 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_total_work_frame(rm_robot_handle *handle, rm_frame_name_t *frame_names, int *len); -/** - * @brief 获取指定工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param name 指定的工作坐标系名称 - * @param pose 获取到的位姿 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_given_work_frame(rm_robot_handle *handle, const char *name, rm_pose_t *pose); -/** - * @brief 获取当前工作坐标系 - * - * @param handle 机械臂控制句柄 - * @param work_frame 返回的坐标系 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_current_work_frame(rm_robot_handle *handle, rm_frame_t *work_frame); -/** @} */ // 结束组的定义 - -/** - * @defgroup ArmState 机械臂状态查询 - * - * 机械臂当前状态、关节温度、电流、电压查询 - * @{ - */ -/** - * @brief 获取机械臂当前状态 - * - * @param handle 机械臂控制句柄 - * @param state 机械臂当前状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_current_arm_state(rm_robot_handle *handle,rm_current_arm_state_t *state); -/** - * @brief 获取关节当前温度 - * - * @param handle 机械臂控制句柄 - * @param temperature 关节1~7温度数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_current_joint_temperature(rm_robot_handle *handle, float *temperature); -/** - * @brief 获取关节当前电流 - * - * @param handle 机械臂控制句柄 - * @param current 关节1~7电流数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_current_joint_current(rm_robot_handle *handle, float *current); -/** - * @brief 获取关节当前电压 - * - * @param handle 机械臂控制句柄 - * @param voltage 关节1~7电压数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_current_joint_voltage(rm_robot_handle *handle, float *voltage); -/** - * @brief 获取当前关节角度 - * - * @param handle 机械臂控制句柄 - * @param joint 当前7个关节的角度数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_degree(rm_robot_handle *handle, float *joint); -/** - * @brief 获取机械臂所有状态信息 - * - * @param handle 机械臂控制句柄 - * @param state 存储机械臂信息的结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_all_state(rm_robot_handle *handle, rm_arm_all_state_t *state); -/** @} */ // 结束组的定义 - -/** - * @defgroup InitPose 初始位置设置 - * - * 记录机械臂初始位置 - * @{ - */ -/** - * @brief 设置机械臂的初始位置角度 - * - * @param handle 机械臂控制句柄 - * @param joint 机械臂初始位置关节角度数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_init_pose(rm_robot_handle *handle, float *joint); -/** - * @brief 获取机械臂初始位置角度 - * - * @param handle 机械臂控制句柄 - * @param joint 机械臂初始位置关节角度数组 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_init_pose(rm_robot_handle *handle, float *joint); -/** @} */ // 结束组的定义 - -/** - * @defgroup MovePlan 机械臂轨迹指令类 - * - * 关节运动、笛卡尔空间运动以及角度及位姿透传 - * @{ - */ -/** - * @brief 关节空间运动 - * - * @param handle 机械臂控制句柄 - * @param joint 目标关节1~7角度数组 - * @param v 速度比例1~100,即规划速度和加速度占关节最大线转速和加速度的百分比 - * @param r 轨迹交融半径,目前默认0。 - * @param trajectory_connect 轨迹连接标志 - * - 0:立即规划并执行轨迹,不与后续轨迹连接。 - * - 1:将当前轨迹与下一条轨迹一起规划,但不立即执行。阻塞模式下,即使发送成功也会立即返回。 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,单位为秒。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_movej(rm_robot_handle *handle, const float *joint, int v, int r,int trajectory_connect,int block); -/** - * @brief 笛卡尔空间直线运动 - * - * @param handle 机械臂控制句柄 - * @param pose 目标位姿,位置单位:米,姿态单位:弧度 - * @param v 速度比例1~100,即规划速度和加速度占机械臂末端最大线速度和线加速度的百分比 - * @param r 轨迹交融半径,目前默认0。 - * @param trajectory_connect 轨迹连接标志 - * - 0:立即规划并执行轨迹,不与后续轨迹连接。 - * - 1:将当前轨迹与下一条轨迹一起规划,但不立即执行。阻塞模式下,即使发送成功也会立即返回。 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 其他值:阻塞模式并设置超时时间,单位为秒。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_movel(rm_robot_handle *handle,rm_pose_t pose, int v, int r, int trajectory_connect, int block); -/** - * @brief 笛卡尔空间直线偏移运动 - * @details 该函数用于机械臂末端在当前位姿的基础上沿某坐标系(工具或工作)进行位移或旋转运动。 - * @param handle 机械臂控制句柄 - * @param offset 位置姿态偏移,位置单位:米,姿态单位:弧度 - * @param v 速度百分比系数,1~100 - * @param r 交融半径百分比系数,0~100。 - * @param trajectory_connect 轨迹连接标志 - * - 0:立即规划并执行轨迹,不与后续轨迹连接。 - * - 1:将当前轨迹与下一条轨迹一起规划,但不立即执行。阻塞模式下,即使发送成功也会立即返回。 - * @param frame_type 参考坐标系类型:0-工作,1-工具 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后才返回。 - * - 单线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_movel_offset(rm_robot_handle *handle,rm_pose_t offset, int v, int r, int trajectory_connect, int frame_type, int block); -/** - * @brief 样条曲线运动 - * - * @param handle 机械臂控制句柄 - * @param pose 目标位姿,位置单位:米,姿态单位:弧度 - * @param v 速度比例1~100,即规划速度和加速度占机械臂末端最大线速度和线加速度的百分比 - * @param r 轨迹交融半径,目前默认0。 - * @param trajectory_connect 轨迹连接标志 - * - 0:立即规划并执行轨迹,不与后续轨迹连接。 - * - 1:将当前轨迹与下一条轨迹一起规划,但不立即执行。阻塞模式下,即使发送成功也会立即返回。 - * @note 样条曲线运动需至少连续下发三个点位(trajectory_connect设置为1),否则运动轨迹为直线 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_moves(rm_robot_handle *handle,rm_pose_t pose, int v, int r, int trajectory_connect, int block); -/** - * @brief 笛卡尔空间圆弧运动 - * - * @param handle 机械臂控制句柄 - * @param pose_via 中间点位姿,位置单位:米,姿态单位:弧度 - * @param pose_to 终点位姿 - * @param v 速度比例1~100,即规划速度和加速度占机械臂末端最大角速度和角加速度的百分比 - * @param r 轨迹交融半径,目前默认0。 - * @param loop 规划圈数,目前默认0. - * @param trajectory_connect 轨迹连接标志 - * - 0:立即规划并执行轨迹,不与后续轨迹连接。 - * - 1:将当前轨迹与下一条轨迹一起规划,但不立即执行。阻塞模式下,即使发送成功也会立即返回。 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_movec(rm_robot_handle *handle,rm_pose_t pose_via, rm_pose_t pose_to, int v, int r, int loop, int trajectory_connect, int block); -/** - * @brief 该函数用于关节空间运动到目标位姿 - * - * @param handle 机械臂控制句柄 - * @param pose 目标位姿,位置单位:米,姿态单位:弧度。 - * @param v 速度比例1~100,即规划速度和加速度占机械臂末端最大线速度和线加速度的百分比 - * @param r 轨迹交融半径,目前默认0。 - * @param trajectory_connect 轨迹连接标志 - * - 0:立即规划并执行轨迹,不与后续轨迹连接。 - * - 1:将当前轨迹与下一条轨迹一起规划,但不立即执行。阻塞模式下,即使发送成功也会立即返回。 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_movej_p(rm_robot_handle *handle,rm_pose_t pose, int v, int r, int trajectory_connect, int block); -/** - * @brief 角度不经规划,直接通过CANFD透传给机械臂 - * @details 角度透传到 CANFD,若指令正确,机械臂立即执行 - * 备注: - * 透传效果受通信周期和轨迹平滑度影响,因此要求通信周期稳定,避免大幅波动。 - * 用户在使用此功能时,建议进行良好的轨迹规划,以确保机械臂的稳定运行。 - * I系列有线网口周期最快可达2ms,提供了更高的实时性。 - * @param handle 机械臂控制句柄 - * @param joint 关节1~7目标角度数组,单位:° - * @param follow true-高跟随,false-低跟随。若使用高跟随,透传周期要求不超过 10ms。 - * @param expand 如果存在通用扩展轴,并需要进行透传,可使用该参数进行透传发送。 - * @param trajectory_mode 高跟随模式下,0-完全透传模式、1-曲线拟合模式、2-滤波模式 - * @param radio 曲线拟合模式和滤波模式下的平滑系数(数值越大效果越好),滤波模式下取值范围0~100,曲线拟合模式下取值范围0~1000 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - */ -RM_INTERFACE_EXPORT int rm_movej_canfd(rm_robot_handle *handle, float *joint, bool follow, int expand, int trajectory_mode=0, int radio=0); -/** - * @brief 位姿不经规划,直接通过CANFD透传给机械臂 - * @details 当目标位姿被透传到机械臂控制器时,控制器首先尝试进行逆解计算。 - * 若逆解成功且计算出的各关节角度与当前角度差异不大,则直接下发至关节执行,跳过额外的轨迹规划步骤。 - * 这一特性适用于需要周期性调整位姿的场景,如视觉伺服等应用。 - * 备注: - * 透传效果受通信周期和轨迹平滑度影响,因此要求通信周期稳定,避免大幅波动。 - * 用户在使用此功能时,建议进行良好的轨迹规划,以确保机械臂的稳定运行。 - * I系列有线网口周期最快可达2ms,提供了更高的实时性。 - * @param handle 机械臂控制句柄 - * @param pose 位姿 (优先采用四元数表达) - * @param follow true-高跟随,false-低跟随。若使用高跟随,透传周期要求不超过 10ms。 - * @param trajectory_mode 高跟随模式下,0-完全透传模式、1-曲线拟合模式、2-滤波模式 - * @param radio 曲线拟合模式和滤波模式下的平滑系数(数值越大效果越好),滤波模式下取值范围0~100,曲线拟合模式下取值范围0~1000 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - */ -RM_INTERFACE_EXPORT int rm_movep_canfd(rm_robot_handle *handle, rm_pose_t pose, bool follow, int trajectory_mode=0, int radio=0); -/** - * @brief 关节空间跟随运动 - * @param handle 机械臂控制句柄 - * @param joint 关节1~7目标角度数组,单位:° - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - */ -RM_INTERFACE_EXPORT int rm_movej_follow(rm_robot_handle *handle,float *joint); -/** - * @brief 笛卡尔空间跟随运动 - * @param handle 机械臂控制句柄 - * @param pose 位姿 (优先采用四元数表达) - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - */ -RM_INTERFACE_EXPORT int rm_movep_follow(rm_robot_handle *handle, rm_pose_t pose); -/** @} */ // 结束组的定义 - -/** - * @defgroup ArmMotionControl 机械臂运动控制指令类 - * - * 控制运动的急停、缓停、暂停、继续、清除轨迹以及查询当前规划类型 - * @{ - */ -/** - * @brief 轨迹缓停,在当前正在运行的轨迹上停止 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_slow_stop(rm_robot_handle *handle); -/** - * @brief 轨迹急停,关节最快速度停止,轨迹不可恢复 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_stop(rm_robot_handle *handle); -/** - * @brief 轨迹暂停,暂停在规划轨迹上,轨迹可恢复 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_pause(rm_robot_handle *handle); -/** - * @brief 轨迹暂停后,继续当前轨迹运动 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_continue(rm_robot_handle *handle); -/** - * @brief 清除当前轨迹 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 必须在暂停后使用,否则机械臂会发生意外!!!! - */ -RM_INTERFACE_EXPORT int rm_set_delete_current_trajectory(rm_robot_handle *handle); -/** - * @brief 清除所有轨迹 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 必须在暂停后使用,否则机械臂会发生意外!!!! - */ -RM_INTERFACE_EXPORT int rm_set_arm_delete_trajectory(rm_robot_handle *handle); -/** - * @brief 获取当前正在规划的轨迹信息 - * - * @param handle 机械臂控制句柄 - * @param type 返回的规划类型 - * @param data 无规划和关节空间规划为当前关节1~7角度数组;笛卡尔空间规划则为当前末端位姿 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_current_trajectory(rm_robot_handle *handle,rm_arm_current_trajectory_e *type,float *data); -/** @} */ // 结束组的定义 - -/** - * @defgroup ArmTeachMove 机械臂示教指令类 - * - * 关节、位置、姿态的示教及步进控制 - * @{ - */ -/** - * @brief 关节步进 - * - * @param handle 机械臂控制句柄 - * @param joint_num 关节序号,1~7 - * @param step 步进的角度, - * @param v 速度比例1~100,即规划速度和加速度占机械臂末端最大线速度和线加速度的百分比 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_step(rm_robot_handle *handle,int joint_num, float step, int v, int block); -/** - * @brief 当前工作坐标系下,位置步进 - * - * @param handle 机械臂控制句柄 - * @param type 示教类型 - * @param step 步进的距离,单位m,精确到0.001mm - * @param v 速度比例1~100,即规划速度和加速度占机械臂末端最大线速度和线加速度的百分比 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - * @attention 参考坐标系默认为当前工作坐标系,可调用rm_set_teach_frame修改为工具坐标系, - */ -RM_INTERFACE_EXPORT int rm_set_pos_step(rm_robot_handle *handle, rm_pos_teach_type_e type, float step, int v, int block); -/** - * @brief 当前工作坐标系下,姿态步进 - * - * @param handle 机械臂控制句柄 - * @param type 示教类型 - * @param step 步进的弧度,单位rad,精确到0.001rad - * @param v 速度比例1~100,即规划速度和加速度占机械臂末端最大线速度和线加速度的百分比 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - * @attention 参考坐标系默认为当前工作坐标系,可调用rm_set_teach_frame修改为工具坐标系, - */ -RM_INTERFACE_EXPORT int rm_set_ort_step(rm_robot_handle *handle, rm_ort_teach_type_e type, float step, int v, int block); -/** - * @brief 切换示教运动坐标系 - * - * @param handle 机械臂控制句柄 - * @param frame_type 0: 工作坐标系运动, 1: 工具坐标系运动 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_teach_frame(rm_robot_handle *handle, int frame_type); -/** - * @brief 获取示教参考坐标系 - * - * @param handle 机械臂控制句柄 - * @param frame_type 0: 工作坐标系运动, 1: 工具坐标系运动 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_teach_frame(rm_robot_handle *handle,int *frame_type); -/** - * @brief 关节示教 - * - * @param handle 机械臂控制句柄 - * @param joint_num 示教关节的序号,1~7 - * @param direction 示教方向,0-负方向,1-正方向 - * @param v 速度比例1~100,即规划速度和加速度占关节最大线转速和加速度的百分比 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_joint_teach(rm_robot_handle *handle,int joint_num, int direction, int v); -/** - * @brief 当前工作坐标系下,笛卡尔空间位置示教 - * - * @param handle 机械臂控制句柄 - * @param type 示教类型 - * @param direction 示教方向,0-负方向,1-正方向 - * @param v 即规划速度和加速度占机械臂末端最大线速度和线加速度的百分比 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 参考坐标系默认为当前工作坐标系,可调用rm_set_teach_frame修改为工具坐标系, - */ -RM_INTERFACE_EXPORT int rm_set_pos_teach(rm_robot_handle *handle,rm_pos_teach_type_e type, int direction, int v); -/** - * @brief 当前工作坐标系下,笛卡尔空间姿态示教 - * - * @param handle 机械臂控制句柄 - * @param type 示教类型 - * @param direction 示教方向,0-负方向,1-正方向 - * @param v 速度比例1~100,即规划速度和加速度占机械臂末端最大角速度和角加速度的百分比 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 参考坐标系默认为当前工作坐标系,可调用rm_set_teach_frame修改为工具坐标系, - */ -RM_INTERFACE_EXPORT int rm_set_ort_teach(rm_robot_handle *handle,rm_ort_teach_type_e type, int direction, int v); -/** - * @brief 示教停止 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_stop_teach(rm_robot_handle *handle); -/** @} */ // 结束组的定义 - -/** - * @defgroup ControllerConfig 系统配置 - * - * 控制器状态获取、电源控制、错误清除、有线网口IP地址配置、软件信息获取 - * @{ - */ -/** - * @brief 获取控制器状态 - * - * @param handle 机械臂控制句柄 - * @param voltage 返回的电压 - * @param current 返回的电流 - * @param temperature 返回的温度 - * @param err_flag 控制器运行错误代码 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_controller_state(rm_robot_handle *handle, float *voltage, float *current, float *temperature, int *err_flag); -/** - * @brief 设置机械臂电源 - * - * @param handle 机械臂控制句柄 - * @param arm_power 1-上电状态,0 断电状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_arm_power(rm_robot_handle *handle, int arm_power); -/** - * @brief 读取机械臂电源状态 - * - * @param handle 机械臂控制句柄 - * @param power_state 获取到的机械臂电源状态,1-上电状态,0 断电状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_power_state(rm_robot_handle *handle, int *power_state); -/** - * @brief 读取控制器的累计运行时间 - * - * @param handle 机械臂控制句柄 - * @param day 读取到的时间 - * @param hour 读取到的时间 - * @param min 读取到的时间 - * @param sec 读取到的时间 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_system_runtime(rm_robot_handle *handle, int *day, int *hour, int *min, int *sec); -/** - * @brief 清零控制器的累计运行时间 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_clear_system_runtime(rm_robot_handle *handle); -/** - * @brief 读取关节的累计转动角度 - * - * @param handle 机械臂控制句柄 - * @param joint_odom 各关节累计的转动角度,单位° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_odom(rm_robot_handle *handle, float *joint_odom); -/** - * @brief 清零关节累计转动的角度 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_clear_joint_odom(rm_robot_handle *handle); -/** - * @brief 配置有线网口 IP 地址 - * - * @param handle 机械臂控制句柄 - * @param ip 有线网口 IP 地址 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_NetIP(rm_robot_handle *handle, const char* ip); -/** - * @brief 清除系统错误 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_clear_system_err(rm_robot_handle *handle); -/** - * @brief 读取机械臂软件信息 - * - * @param handle 机械臂控制句柄 - * @param software_info 机械臂软件信息结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_arm_software_info(rm_robot_handle *handle,rm_arm_software_version_t *software_info); -/** - * @brief 查询控制器RS485模式 - * - * @param handle 机械臂控制句柄 - * @param mode 0-代表默认 RS485 串行通讯,1-代表 modbus-RTU 主站模式,2-代表 modbus-RTU 从站模式; - * @param baudrate 波特率 - * @param timeout modbus 协议超时时间,单位 100ms,仅在 modbus-RTU 模式下提供此字段 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持此接口 - */ -RM_INTERFACE_EXPORT int rm_get_controller_RS485_mode(rm_robot_handle *handle, int* mode, int* baudrate, int* timeout); -/** - * @brief 查询工具端 RS485 模式 - * - * @param handle 机械臂控制句柄 - * @param mode 0-代表默认 RS485 串行通讯 1-代表 modbus-RTU 主站模式 - * @param baudrate 波特率 - * @param timeout modbus 协议超时时间,单位 100ms,仅在 modbus-RTU 模式下提供此字段 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持此接口 - */ -RM_INTERFACE_EXPORT int rm_get_tool_RS485_mode(rm_robot_handle *handle, int* mode, int* baudrate, int* timeout); -/** - * @brief 查询关节软件版本号 - * - * @param handle 机械臂控制句柄 - * @param version 获取到的各关节软件版本号数组,需转换为十六进制,例如获取某关节版本为54536,转换为十六进制为D508,则当前关节的版本号为 Vd5.0.8(三代控制器) - * @param joint_v 获取到的各关节软件版本号字符串数组(四代控制器) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_joint_software_version(rm_robot_handle *handle,int *version, rm_version_t *joint_v); -RM_INTERFACE_EXPORT int rm_get_joint_software_version(rm_robot_handle *handle,int *version); -/** - * @brief 查询末端接口板软件版本号 - * - * @param handle 机械臂控制句柄 - * @param version (三代控制器)获取到的末端接口板软件版本号,需转换为十六进制,例如获取到版本号393,转换为十六进制为189,则当前关节的版本号为 V1.8.9 - * @param end_v (四代控制器)获取到的末端接口板软件版本号字符串 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_tool_software_version(rm_robot_handle *handle, int *version, rm_version_t *end_v); -RM_INTERFACE_EXPORT int rm_get_tool_software_version(rm_robot_handle *handle, int *version); -/** @} */ // 结束组的定义 - -/** - * @defgroup CommunicationConfig 配置通讯内容 - * - * 机械臂控制器可通过网口、WIFI、RS232-USB 接口和 RS485 接口与用户通信,用户使用时无需切换,可使用上述任一接口, - * 控制器收到指令后,若指令格式正确,则会通过相同的接口反馈数据。 - * @{ - */ -/** - * @brief 配置 wifiAP 模式 - * - * @param handle 机械臂控制句柄 - * @param wifi_name wifi名称 - * @param password wifi密码 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - * @attention 设置成功后蜂鸣器响,手动重启控制器进入 WIFIAP 模式。 - */ -RM_INTERFACE_EXPORT int rm_set_wifi_ap(rm_robot_handle *handle, const char* wifi_name, const char* password); -/** - * @brief 配置WiFi STA模式 - * - * @param handle 机械臂控制句柄 - * @param router_name 路由器名称 - * @param password 路由器Wifi密码 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - * @attention 设置成功后蜂鸣器响,手动重启控制器进入 WIFISTA 模式。 - */ -RM_INTERFACE_EXPORT int rm_set_wifi_sta(rm_robot_handle *handle, const char* router_name, const char* password); - -/** - * @brief 控制器RS485接口波特率设置,设置成功后蜂鸣器响 - * - * @param handle 机械臂控制句柄 - * @param baudrate 波特率:9600,19200,38400,115200和460800,若用户设置其他数据,控制器会默认按照460800处理。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 四代控制器不支持该接口 - * @attention 该指令下发后控制器会记录当前波特率,断电重启后仍会使用该波特率对外通信。 - */ -RM_INTERFACE_EXPORT int rm_set_RS485(rm_robot_handle *handle, int baudrate); -/** - * @brief 获取有线网卡信息,未连接有线网卡则会返回无效数据 - * - * @param handle 机械臂控制句柄 - * @param ip 网络地址 - * @param mask 子网掩码 - * @param mac MAC地址 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_wired_net(rm_robot_handle *handle, char * ip, char * mask, char * mac); -/** - * @brief 查询无线网卡网络信息 - * - * @param handle 机械臂控制句柄 - * @param wifi_net 无线网卡网络信息结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 结构体中的channel值只有在AP模式时才可获取到,标识 wifi 热点的物理信道号 - */ -RM_INTERFACE_EXPORT int rm_get_wifi_net(rm_robot_handle *handle, rm_wifi_net_t *wifi_net); -/** - * @brief 恢复网络出厂设置 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_net_default(rm_robot_handle *handle); -/** - * @brief 配置关闭 wifi 功能,需要重启后生效 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_wifi_close(rm_robot_handle *handle); -/** @} */ // 结束组的定义 - -/** - * @defgroup ControllerIOConfig 控制器IO配置及获取 - * - * 机械臂控制器提供IO端口,用于与外部设备交互。以下是具体的IO端口配置和特性: - * - * - 数字IO: - * - 数量: 4路 - * - 功能: DO/DI复用(数字输出/数字输入) - * - 电压范围: 可配置为0~24V - * @{ - */ -/** - * @brief 设置数字IO模式 - * - * @param handle 机械臂控制句柄 - * @param io_num IO 端口号,范围:1~4 - * @param io_mode 模式: - * 0-通用输入模式,1-通用输出模式、2-输入开始功能复用模式、3-输入暂停功能复用模式、 - * 4-输入继续功能复用模式、5-输入急停功能复用模式、6-输入进入电流环拖动复用模式、7-输入进入力只动位置拖动模式(六维力版本可配置)、 - * 8-输入进入力只动姿态拖动模式(六维力版本可配置)、9-输入进入力位姿结合拖动复用模式(六维力版本可配置)、 - * 10-输入外部轴最大软限位复用模式(外部轴模式可配置)、11-输入外部轴最小软限位复用模式(外部轴模式可配置)、 - * 12-输入初始位姿功能复用模式、13-输出碰撞功能复用模式、14-实时调速功能复用模式 - * @param io_speed_mode 模式取值1或2(只有io_mode为14时生效): - * 1表示单次触发模式,单次触发模式下当IO拉低速度设置为speed参数值,IO恢复高电平速度设置为初始值。 - * 2表示连续触发模式,连续触发模式下IO拉低速度设置为speed参数值,IO恢复高电平速度维持当前值 - * @param io_speed 速度取值范围0-100(只有io_mode为14时生效) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_IO_mode(rm_robot_handle *handle, int io_num, int io_mode, int io_speed_mode=0, int io_speed=0); -/** - * @brief 设置数字IO输出 - * - * @param handle 机械臂控制句柄 - * @param io_num IO 端口号,范围:1~4 - * @param state IO 状态,1-输出高,0-输出低 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_DO_state(rm_robot_handle *handle, int io_num, int state); -/** - * @brief - * - * @param handle 机械臂控制句柄 - * @param io_num IO 端口号,范围:1~4 - * @param state IO 状态 - * @param io_mode 模式: - * 0-通用输入模式,1-通用输出模式、2-输入开始功能复用模式、3-输入暂停功能复用模式、 - * 4-输入继续功能复用模式、5-输入急停功能复用模式、6-输入进入电流环拖动复用模式、7-输入进入力只动位置拖动模式(六维力版本可配置)、 - * 8-输入进入力只动姿态拖动模式(六维力版本可配置)、9-输入进入力位姿结合拖动复用模式(六维力版本可配置)、 - * 10-输入外部轴最大软限位复用模式(外部轴模式可配置)、11-输入外部轴最小软限位复用模式(外部轴模式可配置)、 - * 12-输入初始位姿功能复用模式13-输出碰撞功能复用模式、14-实时调速功能复用模式 - * @param io_speed_mode 模式取值1或2(只有io_mode为14时生效): - * 1表示单次触发模式,单次触发模式下当IO拉低速度设置为speed参数值,IO恢复高电平速度设置为初始值。 - * 2表示连续触发模式,连续触发模式下IO拉低速度设置为speed参数值,IO恢复高电平速度维持当前值 - * @param io_speed 速度取值范围0-100(只有io_mode为14时生效) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_IO_state(rm_robot_handle *handle, int io_num, int* state, int* mode, int* io_speed_mode=nullptr, int* io_speed=nullptr); -/** - * @brief 获取所有 IO 输入状态 - * - * @param handle 机械臂控制句柄 - * @param DI_state 数字输入状态,1:高,0:低,-1:该端口不是输入模式 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_IO_input(rm_robot_handle *handle, int *DI_state); -/** - * @brief 获取所有 IO 输出状态 - * - * @param handle 机械臂控制句柄 - * @param DO_state 数字输出状态,1:高,0:低,-1:该端口不是输出模式 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_IO_output(rm_robot_handle *handle, int *DO_state); -/** - * @brief 设置控制器电源输出 - * - * @param handle 机械臂控制句柄 - * @param voltage_type 电源输出类型,0:0V,2:12V,3:24V - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_voltage(rm_robot_handle *handle, int voltage_type); -/** - * @brief 获取控制器电源输出类 - * - * @param handle 机械臂控制句柄 - * @param voltage_type 电源输出类型,0:0V,2:12V,3:24V - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_voltage(rm_robot_handle *handle, int *voltage_type); -/** @} */ // 结束组的定义 - -/** - * @defgroup ToolIOConfig 末端工具 IO 控制 - * - * 机械臂末端工具端提供多种IO端口,用于与外部设备交互。以下是端口的具体配置和特性: - * - 电源输出: - * - 数量: 1路 - * - 可配置电压: 0V, 5V, 12V, 24V - * - * - 数字IO: - * - 数量: 2路 - * - 可配置性: 输入/输出均可配置 - * - 输入特性: - * - 参考电平: 12V~24V - * - 输出特性: - * - 电压范围: 5~24V(与输出电压一致) - * - * - 通讯接口: - * - 数量: 1路 - * - 可配置协议: RS485 - * @{ - */ -/** - * @brief 设置工具端数字 IO 输出 - * - * @param handle 机械臂控制句柄 - * @param io_num IO 端口号,范围:1~2 - * @param state IO 状态,1-输出高,0-输出低 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_tool_DO_state(rm_robot_handle *handle, int io_num, int state); -/** - * @brief 设置工具端数字 IO 模式 - * - * @param handle 机械臂控制句柄 - * @param io_num IO 端口号,范围:1~2 - * @param io_mode 模式,0-输入状态,1-输出状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_tool_IO_mode(rm_robot_handle *handle, int io_num, int io_mode); -/** - * @brief 获取数字 IO 状态 - * - * @param handle 机械臂控制句柄 - * @param state 0-输入模式,1-输出模式 - * @param mode 0-低,1-高 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_tool_IO_state(rm_robot_handle *handle, int* state, int* mode); -/** - * @brief 设置工具端电源输出 - * - * @param handle 机械臂控制句柄 - * @param voltage_type 电源输出类型,0:0V,1:5V,2:12V,3:24V, - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 电源输出设置为 5V 时,工具端的IO 暂不支持输入输出功能 - */ -RM_INTERFACE_EXPORT int rm_set_tool_voltage(rm_robot_handle *handle, int voltage_type); -/** - * @brief 获取工具端电源输出 - * - * @param handle 机械臂控制句柄 - * @param voltage_type 电源输出类型,0:0V,1:5V,2:12V,3:24V, - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_tool_voltage(rm_robot_handle *handle, int *voltage_type); -/** @} */ // 结束组的定义 - -/** - * @defgroup GripperControl 末端工具—手爪控制 - * - * 睿尔曼机械臂末端配备了因时机器人公司的 EG2-4C2 手爪,为了便于用户操作手爪,机械臂控制器 - * 对用户开放了手爪的控制协议(手爪控制协议与末端modbus 功能互斥) - * @{ - */ -/** - * @brief 设置手爪行程,即手爪开口的最大值和最小值,设置成功后会自动保存,手爪断电不丢失 - * - * @param handle 机械臂控制句柄 - * @param min_limit 手爪开口最小值,范围:0~1000,无单位量纲 - * @param max_limit 手爪开口最大值,范围:0~1000,无单位量纲 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_gripper_route(rm_robot_handle *handle, int min_limit, int max_limit); -/** - * @brief 松开手爪,即手爪以指定的速度运动到开口最大处 - * - * @param handle 机械臂控制句柄 - * @param speed 手爪松开速度,范围 1~1000,无单位量纲 - * @param block true 表示阻塞模式,等待控制器返回夹爪到位指令;false 表示非阻塞模式,不接收夹爪到位指令; - * @param timeout 阻塞模式:设置等待夹爪到位超时时间,单位:秒 - * 非阻塞模式:0-发送后立即返回;其他值-接收设置成功指令后返回; - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4:超时 - */ -RM_INTERFACE_EXPORT int rm_set_gripper_release(rm_robot_handle *handle, int speed, bool block, int timeout); -/** - * @brief 手爪力控夹取,手爪以设定的速度和力夹取,当夹持力超过设定的力阈值后,停止夹取 - * - * @param handle 机械臂控制句柄 - * @param speed 手爪夹取速度,范围 1~1000,无单位量纲 - * @param force 力控阈值,范围:50~1000,无单位量纲 - * @param block true 表示阻塞模式,等待控制器返回夹爪到位指令;false 表示非阻塞模式,不接收夹爪到位指令; - * @param timeout 阻塞模式:设置等待夹爪到位超时时间,单位:秒 - * 非阻塞模式:0-发送后立即返回;其他值-接收设置成功指令后返回; - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4:超时 - */ -RM_INTERFACE_EXPORT int rm_set_gripper_pick(rm_robot_handle *handle, int speed, int force, bool block, int timeout); -/** - * @brief - * - * @param handle 机械臂控制句柄 - * @param speed 手爪夹取速度,范围 1~1000,无单位量纲 - * @param force 力控阈值,范围:50~1000,无单位量纲 - * @param block true 表示阻塞模式,等待控制器返回夹爪到位指令;false 表示非阻塞模式,不接收夹爪到位指令; - * @param timeout 阻塞模式:设置等待夹爪到位超时时间,单位:秒 - * 非阻塞模式:0-发送后立即返回;其他值-接收设置成功指令后返回; - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4:超时 - */ -RM_INTERFACE_EXPORT int rm_set_gripper_pick_on(rm_robot_handle *handle, int speed, int force, bool block, int timeout); -/** - * @brief 设置手爪达到指定位置 - * @details 手爪到达指定位置,当当前开口小于指定开口时,手爪以指定速度松开到指定开口位置;当当前开口大于指定开口时, - * 手爪以指定速度和力矩闭合往指定开口处闭合,当夹持力超过力矩阈值或者达到指定位置后,手爪停止。 - * @param handle 机械臂控制句柄 - * @param position 手爪开口位置,范围:1~1000,无单位量纲 - * @param block true 表示阻塞模式,等待控制器返回夹爪到位指令;false 表示非阻塞模式,不接收夹爪到位指令; - * @param timeout 阻塞模式:设置等待夹爪到位超时时间,单位:秒 - * 非阻塞模式:0-发送后立即返回;其他值-接收设置成功指令后返回; - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4:超时 - */ -RM_INTERFACE_EXPORT int rm_set_gripper_position(rm_robot_handle *handle, int position, bool block, int timeout); -/** - * @brief 查询夹爪状态 - * - * @param handle 机械臂控制句柄 - * @param state 夹爪状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @attention 此接口默认不更新数据,从首次控制夹爪开始后,使能更新状态,如果此时控制灵巧手或打开末端modbus功能,将不再更新数据。另外夹爪需要支持最新的固件,方可支持此功能 - */ -RM_INTERFACE_EXPORT int rm_get_gripper_state(rm_robot_handle *handle, rm_gripper_state_t *state); -/** @} */ // 结束组的定义 - -/** - * @defgroup ForceSensor 末端传感器六维力 - * - * 睿尔曼机械臂六维力版末端配备集成式六维力传感器,无需外部走线,用户可直接通过协议对六维力进行操作, - * 获取六维力数据。如下图所示,正上方为六维力的 Z 轴,航插反方向为六维力的 Y 轴,坐标系符合右手定则。 - * 机械臂位于零位姿态时,工具坐标系与六维力的坐标系方向一致。 - * 另外,六维力额定力 200N,额定力矩 8Nm,过载水平 300%FS,工作温度 5~80℃,准度 0.5%FS。使用过程中 - * 注意使用要求,防止损坏六维力传感器。 - * @{ - */ -/** - * @brief 查询当前六维力传感器得到的力和力矩信息:Fx,Fy,Fz,Mx,My,Mz - * - * @param handle 机械臂控制句柄 - * @param data 力传感器数据结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_force_data(rm_robot_handle *handle, rm_force_data_t *data); -/** - * @brief 将六维力数据清零,标定当前状态下的零位 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_clear_force_data(rm_robot_handle *handle); -/** - * @brief 自动设置六维力重心参数 - * @details 设置六维力重心参数,六维力重新安装后,必须重新计算六维力所受到的初始力和重心。分别在不同姿态下,获取六维力的数据, - * 用于计算重心位置。该指令下发后,机械臂以固定的速度运动到各标定点。 - * 以RM65机械臂为例,四个标定点的关节角度分别为: - * 位置1关节角度:{0,0,-60,0,60,0} - * 位置2关节角度:{0,0,-60,0,-30,0} - * 位置3关节角度:{0,0,-60,0,-30,180} - * 位置4关节角度:{0,0,-60,0,-120,0} - * @attention 必须保证在机械臂静止状态下标定; - * 该过程不可中断,中断后必须重新标定。 - * @param handle 机械臂控制句柄 - * @param block true 表示阻塞模式,等待标定完成后返回;false 表示非阻塞模式,发送后立即返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_force_sensor(rm_robot_handle *handle, bool block); -/** - * @brief 手动标定六维力数据 - * @details 六维力重新安装后,必须重新计算六维力所受到的初始力和重心。该手动标定流程,适用于空间狭窄工作区域,以防自动标定过程中 - * 机械臂发生碰撞,用户可以手动选取四个位置下发,当下发完四个点后,机械臂开始自动沿用户设置的目标运动,并在此过程中计算六维力重心。 - * @attention 上述4个位置必须按照顺序依次下发,当下发完位置4后,机械臂开始自动运行计算重心。 - * @param handle 机械臂控制句柄 - * @param count 点位;1~4 - * @param joint 关节角度,单位:° - * @param block true 表示阻塞模式,等待标定完成后返回;false 表示非阻塞模式,发送后立即返回 - * @return int 函数执行的状态码。 - - 0: 计算成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_manual_set_force(rm_robot_handle *handle, int count, float *joint, bool block); -/** - * @brief 停止标定力传感器重心 - * @details 在标定力传感器过程中,如果发生意外,发送该指令,停止机械臂运动,退出标定流程 - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_stop_set_force_sensor(rm_robot_handle *handle); -/** @} */ // 结束组的定义 - -/** - * @defgroup ForceSensor 末端传感器一维力 - * - * 睿尔曼机械臂末端接口板集成了一维力传感器,可获取 Z 方向的力,量程200N,准度 0.5%FS。 - * @{ - */ -/** - * @brief 查询末端一维力数据 - * - * @param handle 机械臂控制句柄 - * @param data 一维力数据结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 非力控版本机械臂,不支持此功能。 - */ -RM_INTERFACE_EXPORT int rm_get_Fz(rm_robot_handle *handle, rm_fz_data_t *data); -/** - * @brief 清零末端一维力数据,清空一维力数据后,后续所有获取到的数据都是基于当前的偏置。 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_clear_Fz(rm_robot_handle *handle); -/** - * @brief 自动标定一维力数据 - * @details 设置一维力重心参数,一维力重新安装后,必须重新计算一维力所受到的初始力和重心。 - * 分别在不同姿态下,获取一维力的数据,用于计算重心位置,该步骤对于基于一维力的力位混合控制操作具有重要意义。 - * @param handle 机械臂控制句柄 - * @param block true 表示阻塞模式,等待标定完成后返回;false 表示非阻塞模式,发送后立即返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_auto_set_Fz(rm_robot_handle *handle, bool block); -/** - * @brief 手动标定一维力数据 - * @details 设置一维力重心参数,一维力重新安装后,必须重新计算一维力所受到的初始力和重心。该手动标定流程, - * 适用于空间狭窄工作区域,以防自动标定过程中机械臂发生碰撞,用户可以手动选取2个位置下发,当下发完后, - * 机械臂开始自动沿用户设置的目标运动,并在此过程中计算一维力重心。 - * @param handle 机械臂控制句柄 - * @param joint1 位置1关节角度数组,单位:度 - * @param joint2 位置2关节角度数组,单位:度 - * @param block true 表示阻塞模式,等待标定完成后返回;false 表示非阻塞模式,发送后立即返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_manual_set_Fz(rm_robot_handle *handle, float *joint1, float *joint2, bool block); -/** @} */ // 结束组的定义 - -/** - * @defgroup DragTeach 拖动示教 - * - * 睿尔曼机械臂在拖动示教过程中,可记录拖动的轨迹点,并根据用户的指令对轨迹进行复现。 - * @{ - */ -/** - * @brief 拖动示教开始 - * - * @param handle 机械臂控制句柄 - * @param trajectory_record 拖动示教时记录轨迹,0-不记录,1-记录轨迹 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_start_drag_teach(rm_robot_handle *handle, int trajectory_record); -/** - * @brief 拖动示教结束 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_stop_drag_teach(rm_robot_handle *handle); -/** - * @brief 开始复合模式拖动示教 - * @attention 仅支持三代控制器,四代控制器使用rm_start_multi_drag_teach_new - * @param handle 机械臂控制句柄 - * @param mode 拖动示教模式 0-电流环模式,1-使用末端六维力,只动位置,2-使用末端六维力,只动姿态,3-使用末端六维力,位置和姿态同时动 - * @param singular_wall 仅在六维力模式拖动示教中生效,用于指定是否开启拖动奇异墙,0表示关闭拖动奇异墙,1表示开启拖动奇异墙 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口。 - * @note 失败的可能原因: - - 当前机械臂非六维力版本(六维力拖动示教)。 - - 机械臂当前处于 IO 急停状态 - - 机械臂当前处于仿真模式 - - 输入参数有误 - - 使用六维力模式拖动示教时,当前已处于奇异区 - */ -RM_INTERFACE_EXPORT int rm_start_multi_drag_teach(rm_robot_handle *handle, int mode, int singular_wall); -/** - * @brief 开始复合模式拖动示教-新参数 - * - * @param handle 机械臂控制句柄 - * @param teach_state 复合拖动示教参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @note 失败的可能原因: - - 当前机械臂非六维力版本(六维力拖动示教)。 - - 机械臂当前处于 IO 急停状态 - - 机械臂当前处于仿真模式 - - 输入参数有误 - - 使用六维力模式拖动示教时,当前已处于奇异区 - */ -RM_INTERFACE_EXPORT int rm_start_multi_drag_teach(rm_robot_handle *handle, rm_multi_drag_teach_t teach_state); -/** - * @brief 设置电流环拖动示教灵敏度 - * - * @param handle 机械臂控制句柄 - * @param grade 等级,0到100,表示0~100%,当设置为100时保持初始状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_drag_teach_sensitivity(rm_robot_handle *handle, int grade); -/** - * @brief 获取电流环拖动示教灵敏度 - * - * @param handle 机械臂控制句柄 - * @param grade 等级,0到100,表示0~100%,当设置为100时保持初始状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_drag_teach_sensitivity(rm_robot_handle *handle, int *grade); -/** - * @brief 运动到轨迹起点 - * @details 轨迹复现前,必须控制机械臂运动到轨迹起点,如果设置正确,机械臂将以20%的速度运动到轨迹起点 - * @param handle 机械臂控制句柄 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - * @see rm_run_drag_trajectory - */ -RM_INTERFACE_EXPORT int rm_drag_trajectory_origin(rm_robot_handle *handle, int block); -/** - * @brief 轨迹复现开始 - * - * @param handle 机械臂控制句柄 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,根据运动时间设置,单位为秒。 - * @attention 使用单线程阻塞模式时,请设置超时时间确保轨迹在超时时间内运行结束返回 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误,请确保机械臂当前位置为拖动示教起点。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - * @attention 必须在拖动示教结束后才能使用,同时保证机械臂位于拖动示教的起点位置,可调用rm_drag_trajectory_origin接口运动至起点位置 - * @see rm_drag_trajectory_origin - */ -RM_INTERFACE_EXPORT int rm_run_drag_trajectory(rm_robot_handle *handle, int block); -/** - * @brief 控制机械臂在轨迹复现过程中的暂停 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_pause_drag_trajectory(rm_robot_handle *handle); -/** - * @brief 控制机械臂在轨迹复现过程中暂停之后的继续, - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_continue_drag_trajectory(rm_robot_handle *handle); -/** - * @brief 控制机械臂在轨迹复现过程中的停止 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_stop_drag_trajectory(rm_robot_handle *handle); -/** - * @brief 保存拖动示教轨迹 - * - * @param handle 机械臂控制句柄 - * @param name 轨迹要保存的文件路径及名称,长度不超过300个字符,例: c:/rm_test.txt - * @param num 轨迹点数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_save_trajectory(rm_robot_handle *handle, const char* name, int *num); -/** - * @brief 力位混合控制 - * @details 在笛卡尔空间轨迹规划时,使用该功能可保证机械臂末端接触力恒定,使用时力的方向与机械臂运动方向不能在同一方向。 - * 开启力位混合控制,执行笛卡尔空间运动,接收到运动完成反馈后,需要等待2S后继续下发下一条运动指令。 - * @param handle 机械臂控制句柄 - * @param sensor 0-一维力;1-六维力 - * @param mode 0-基坐标系力控;1-工具坐标系力控; - * @param direction 力控方向;0-沿X轴;1-沿Y轴;2-沿Z轴;3-沿RX姿态方向;4-沿RY姿态方向;5-沿RZ姿态方向 - * @param N 力的大小,单位N - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_force_position(rm_robot_handle *handle, int sensor, int mode, int direction, float N); -/** - * @brief 力位混合控制-新参数 - * @details 在笛卡尔空间轨迹规划时,使用该功能可保证机械臂末端接触力恒定,使用时力的方向与机械臂运动方向不能在同一方向。 - * 开启力位混合控制,执行笛卡尔空间运动,接收到运动完成反馈后,需要等待2S后继续下发下一条运动指令。 - * @param handle 机械臂控制句柄 - * @param param 力位混合控制参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_force_position(rm_robot_handle *handle, rm_force_position_t param); -/** - * @brief 结束力位混合控制 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_stop_force_position(rm_robot_handle *handle); -/** - * @brief 设置六维力拖动示教模式 - * - * @param handle 机械臂控制句柄 - * @param mode 0表示快速拖动模式 1表示精准拖动模式 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 非六维力版本机械臂,不支持此功能。 - */ -RM_INTERFACE_EXPORT int rm_set_force_drag_mode(rm_robot_handle *handle, int mode); -/** - * @brief 获取六维力拖动示教模式 - * - * @param handle 机械臂控制句柄 - * @param mode 0表示快速拖动模式 1表示精准拖动模式 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。处理建议:1、联系睿尔曼公司技术支持确认控制器版本是否支持此功能; - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 非六维力版本机械臂,不支持此功能。 - */ -RM_INTERFACE_EXPORT int rm_get_force_drag_mode(rm_robot_handle *handle, int *mode); -/** @} */ // 结束组的定义 - -/** - * @defgroup HandControl 五指灵巧手 - * - * 睿尔曼机械臂末端配置因时的五指灵巧手,可通过协议对灵巧手进行设置。 - * @{ - */ -/** - * @brief 设置灵巧手目标手势序列号 - * - * @param handle 机械臂控制句柄 - * @param posture_num 预先保存在灵巧手内的手势序号,范围:1~40 - * @param block true 表示阻塞模式,等待灵巧手运动结束后返回;false 表示非阻塞模式,发送后立即返回 - * @param timeout 阻塞模式下超时时间设置,单位:秒 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 超时未返回 - */ -RM_INTERFACE_EXPORT int rm_set_hand_posture(rm_robot_handle *handle, int posture_num, bool block, int timeout); -/** - * @brief 设置灵巧手目标手势序列号 - * - * @param handle 机械臂控制句柄 - * @param seq_num 预先保存在灵巧手内的手势序号,范围:1~40 - * @param block true 表示阻塞模式,等待灵巧手运动结束后返回;false 表示非阻塞模式,发送后立即返回 - * @param timeout 阻塞模式下超时时间设置,单位:秒 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 超时未返回 - */ -RM_INTERFACE_EXPORT int rm_set_hand_seq(rm_robot_handle *handle, int seq_num, bool block, int timeout); -/** - * @brief 设置灵巧手各自由度角度 - * @details 设置灵巧手角度,灵巧手有6个自由度,从1~6分别为小拇指,无名指,中指,食指,大拇指弯曲,大拇指旋转 - * @param handle 机械臂控制句柄 - * @param hand_angle 手指角度数组,范围:0~1000. 另外,-1代表该自由度不执行任何操作,保持当前状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_hand_angle(rm_robot_handle *handle, const int *hand_angle); -/** - * @brief 设置灵巧手各自由度跟随角度 - * @details 设置灵巧手跟随角度,灵巧手有6个自由度,从1~6分别为小拇指,无名指,中指,食指,大拇指弯曲,大拇指旋转 - * @param handle 机械臂控制句柄 - * @param hand_angle 手指角度数组,最大表示范围为-32768到+32767,按照灵巧手厂商定义的角度做控制,例如因时的范围为0-2000 - * @param block 设置等待机械臂返回状态超时时间,设置0时为非阻塞模式。单位为毫秒。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_hand_follow_angle(rm_robot_handle *handle, const int *hand_angle, int block); -/** - * @brief 灵巧手位置跟随控制 - * @details 设置灵巧手跟随位置,灵巧手有6个自由度,从1~6分别为小拇指,无名指,中指,食指,大拇指弯曲,大拇指旋转,最高50Hz的控制频率 - * @param handle 机械臂控制句柄 - * @param hand_pos 手指位置数组,最大范围为0-65535,按照灵巧手厂商定义的角度做控制,例如因时的范围为0-1000 - * @param block 设置等待机械臂返回状态超时时间,设置0时为非阻塞模式。单位为毫秒。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_hand_follow_pos(rm_robot_handle *handle, const int *hand_pos, int block); -/** - * @brief 设置灵巧手速度 - * - * @param handle 机械臂控制句柄 - * @param speed 手指速度,范围:1~1000 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_hand_speed(rm_robot_handle *handle, int speed); -/** - * @brief 设置灵巧手力阈值 - * - * @param handle 机械臂控制句柄 - * @param hand_force 手指力,范围:1~1000 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_hand_force(rm_robot_handle *handle, int hand_force); -/** @} */ // 结束组的定义 - -/** - * @defgroup ModbusConfig Modbus 配置 - * - * 睿尔曼机械臂在控制器和末端接口板上各提供一个RS485通讯接口,这些接口可通过JSON协议配置为标准的Modbus RTU模式。 - * 在Modbus RTU模式下,用户可通过JSON协议对连接在端口上的外设进行读写操作。 - * - * @attention - * - 控制器的RS485接口在未配置为Modbus RTU模式时,可用于直接控制机械臂。 - * - Modbus RTU模式与机械臂控制模式不兼容。若需恢复机械臂控制模式,必须关闭该端口的Modbus RTU模式。 - * - 关闭Modbus RTU模式后,系统将自动切换回机械臂控制模式,使用波特率460800BPS,停止位1,数据位8,无校验。 - * - * 此外,I系列控制器还支持modbus-TCP主站配置,允许用户配置使用modbus-TCP主站,以连接外部设备的modbus-TCP从站。 - * - * @{ - */ -/** - * @brief 配置通讯端口ModbusRTU模式 - * @details 配置通讯端口ModbusRTU模式,机械臂启动后,要对通讯端口进行任何操作,必须先启动该指令,否则会返回报错信息。 - * 另外,机械臂会对用户的配置方式进行保存,机械臂重启后会自动恢复到用户断电之前配置的模式。 - * @param handle 机械臂控制句柄 - * @param port 通讯端口,0-控制器RS485端口为RTU主站,1-末端接口板RS485接口为RTU主站,2-控制器RS485端口为RTU从站 - * @param baudrate 波特率,支持 9600,115200,460800 三种常见波特率 - * @param timeout 超时时间,单位百毫秒。。对Modbus设备所有的读写指令,在规定的超时时间内未返回响应数据,则返回超时报错提醒。超时时间不能为0,若设置为0,则机械臂按1进行配置。 - * @note 其他配置默认为:数据位-8,停止位-1,奇偶校验-无 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_set_modbus_mode(rm_robot_handle *handle, int port, int baudrate, int timeout); -/** - * @brief 关闭通讯端口 Modbus RTU 模式 - * - * @param handle 机械臂控制句柄 - * @param port 通讯端口,0-控制器RS485端口为RTU主站,1-末端接口板RS485接口为RTU主站,2-控制器RS485端口为RTU从站 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_close_modbus_mode(rm_robot_handle *handle, int port); -/** - * @brief 配置连接 ModbusTCP 从站 - * - * @param handle 机械臂控制句柄 - * @param ip 从机IP地址 - * @param port 端口号 - * @param timeout 超时时间,单位毫秒。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_set_modbustcp_mode(rm_robot_handle *handle, const char *ip, int port, int timeout); -/** - * @brief 关闭通讯端口ModbusRTU模式 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_close_modbustcp_mode(rm_robot_handle *handle); -/** - * @brief 读线圈 - * - * @param handle 机械臂控制句柄 - * @param params 线圈读取参数结构体,该指令最多一次性支持读 8 个线圈数据,即返回的数据不会超过一个字节 - * @param data 返回线圈状态,数据类型:int8 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_coils(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 读离散量输入 - * - * @param handle 机械臂控制句柄 - * @param params 离散量输入读取参数结构体,该指令最多一次性支持读 8 个离散量数据,即返回的数据不会超过一个字节 - * @param data 返回离散量,数据类型:int8 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_input_status(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 读保持寄存器 - * - * @param handle 机械臂控制句柄 - * @param params 保持寄存器数据读取参数结构体,该指令每次只能读 1 个寄存器,即 2 个字节 - * 的数据,不可一次性读取多个寄存器数据,该结构体成员num无需设置 - * @param data 返回寄存器数据,数据类型:int16 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_holding_registers(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 读输入寄存器 - * - * @param handle 机械臂控制句柄 - * @param params 输入寄存器数据读取参数结构体,该指令每次只能读 1 个寄存器,即 2 个字节 - * 的数据,不可一次性读取多个寄存器数据,该结构体成员num无需设置 - * @param data 返回寄存器数据,数据类型:int16 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_input_registers(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 写单圈数据 - * - * @param handle 机械臂控制句柄 - * @param params 单圈数据写入参数结构体,该结构体成员num无需设置 - * @param data 要写入线圈的数据,数据类型:int16 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 写操作失败,超时时间内未获取到数据,或者指令内容错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_write_single_coil(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int data); -/** - * @brief 写单个寄存器 - * - * @param handle 机械臂控制句柄 - * @param params 单个寄存器数据写入参数结构体,该结构体成员num无需设置 - * @param data 要写入寄存器的数据,类型:int16 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 写操作失败,超时时间内未获取到数据,或者指令内容错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_write_single_register(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int data); -/** - * @brief 写多个寄存器 - * - * @param handle 机械臂控制句柄 - * @param params 多个寄存器数据写入参数结构体。其中寄存器每次写的数量不超过10个,即该结构体成员num<=10。 - * @param data 要写入寄存器的数据数组,类型:byte。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 写操作失败,超时时间内未获取到数据,或者指令内容错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_write_registers(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 写多圈数据 - * - * @param handle 机械臂控制句柄 - * @param params 多圈数据写入参数结构体。每次写的数量不超过 160 个,即该结构体成员num<=160。 - * @param data 要写入线圈的数据数组,类型:byte。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 写操作失败,超时时间内未获取到数据,或者指令内容错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_write_coils(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 读多圈数据 - * - * @param handle 机械臂控制句柄 - * @param params 多圈数据读取参数结构体,要读的线圈的数量 8< num <= 120,该指令最多一次性支持读 120 个线圈数据, 即 15 个 byte - * @param data 返回线圈状态,数据类型:int8 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_multiple_coils(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 读多个保存寄存器 - * - * @param handle 机械臂控制句柄 - * @param params 多个保存寄存器读取参数结构体,要读的寄存器的数量 2 < num < 13,该指令最多一次性支持读 12 个寄存器数据, 即 24 个 byte - * @param data 返回寄存器数据,数据类型:int8 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_multiple_holding_registers(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** - * @brief 读多个输入寄存器 - * - * @param handle 机械臂控制句柄 - * @param params 多个输入寄存器读取参数结构体,要读的寄存器的数量 2 < num < 13,该指令最多一次性支持读 12 个寄存器数据, 即 24 个 byte - * @param data 返回寄存器数据,数据类型:int8 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 读取失败,超时时间内未获取到数据。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_multiple_input_registers(rm_robot_handle *handle, rm_peripheral_read_write_params_t params, int *data); -/** @} */ // 结束组的定义 - -/** - * @defgroup InstallPos 系统安装方式 - * - * 睿尔曼机械臂可支持不同形式的安装方式,但是安装方式不同,机器人的动力学模型参数和坐标系的方向也有所差别。 - * @{ - */ -/** - * @brief 设置安装方式参数 - * - * @param handle 机械臂控制句柄 - * @param x 旋转角,单位 ° - * @param y 俯仰角,单位 ° - * @param z 方位角,单位 ° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_install_pose(rm_robot_handle *handle, float x, float y, float z); -/** - * @brief 获取安装方式参数 - * - * @param handle 机械臂控制句柄 - * @param x 旋转角(out),单位 ° - * @param y 俯仰角(out),单位 ° - * @param z 方位角(out),单位 ° - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_install_pose(rm_robot_handle *handle, float *x, float *y, float *z); -/** @} */ // 结束组的定义 - -/** - * @defgroup ForcePositionControl 透传力位混合控制补偿 - * - * 针对睿尔曼带一维力和六维力版本的机械臂,用户除了可直接使用示教器调用底层的力位混合控制模块外,还可以将 - * 自定义的轨迹以周期性透传的形式结合底层的力位混合控制算法进行补偿。 - * - * @attention 该功能只适用于一维力传感器和六维力传感器机械臂版本 - * - * 透传效果和周期、轨迹是否平滑有关,周期要求稳定,防止出现较大波动,用户使用该指令时请做好轨迹规划,轨迹规划的 - * 平滑程度决定了机械臂的运行状态。基础系列 WIFI 和网口模式透传周期最快 20ms,USB 和 RS485 模式透传周期最快 10ms。 - * 高速网口的透传周期最快也可到 10ms,不过在使用该高速网口前,需要使用指令打开配置。另外 I 系列有线网口周期最快可达 2ms。 - * @{ - */ -/** - * @brief 开启透传力位混合控制补偿模式 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_start_force_position_move(rm_robot_handle *handle); -/** - * @brief 停止透传力位混合控制补偿模式 - * - * @param handle 机械臂控制句柄 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_stop_force_position_move(rm_robot_handle *handle); -/** - * @brief 透传力位混合补偿-角度方式 - * - * @param handle 机械臂控制句柄 - * @param joint 目标关节角度 - * @param sensor 所使用传感器类型,0-一维力,1-六维力 - * @param mode 模式,0-沿基坐标系,1-沿工具端坐标系 - * @param dir 力控方向,0~5分别代表X/Y/Z/Rx/Ry/Rz,其中一维力类型时默认方向为Z方向 - * @param force 力的大小 单位N - * @param follow 是否高跟随 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_force_position_move_joint(rm_robot_handle *handle,const float *joint,int sensor,int mode,int dir,float force, bool follow); -/** - * @brief 透传力位混合补偿-位姿方式 - * - * @param handle 机械臂控制句柄 - * @param pose 当前坐标系下目标位姿 - * @param sensor 所使用传感器类型,0-一维力,1-六维力 - * @param mode 模式,0-沿基坐标系,1-沿工具端坐标系 - * @param dir 力控方向,0~5分别代表X/Y/Z/Rx/Ry/Rz,其中一维力类型时默认方向为Z方向 - * @param force 力的大小 单位N - * @param follow 是否高跟随 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_force_position_move_pose(rm_robot_handle *handle, rm_pose_t pose,int sensor,int mode,int dir,float force, bool follow); -/** - * @brief 透传力位混合补偿-新参数 - * - * @param handle 机械臂控制句柄 - * @param param 透传力位混合补偿参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_force_position_move(rm_robot_handle *handle, rm_force_position_move_t param); -/** @} */ // 结束组的定义 - -/** - * @defgroup LiftControl 升降机构 - * - * 升降机构速度开环控制、位置闭环控制及状态获取 - * @{ - */ -/** - * @brief 升降机构速度开环控制 - * - * @param handle 机械臂控制句柄 - * @param speed 速度百分比,-100~100。 - - speed<0:升降机构向下运动 - - speed>0:升降机构向上运动 - - speed=0:升降机构停止运动 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_lift_speed(rm_robot_handle *handle, int speed); -/** - * @brief 升降机构位置闭环控制 - * - * @param handle 机械臂控制句柄 - * @param speed 速度百分比,1~100 - * @param height 目标高度,单位 mm,范围:0~2600 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待升降机到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 其他值:阻塞模式并设置超时时间,单位为秒。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为升降机构。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_set_lift_height(rm_robot_handle *handle, int speed, int height, int block); -/** - * @brief 获取升降机构状态 - * - * @param handle 机械臂控制句柄 - * @param state 当前升降机构状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_lift_state(rm_robot_handle *handle, rm_expand_state_t *state); -/** @} */ // 结束组的定义 - -/** - * @defgroup ExpandControl 通用扩展关节 - * - * 扩展关节速度环控制、位置环控制及状态获取 - * @{ - */ -/** - * @brief 扩展关节状态获取 - * - * @param handle 机械臂控制句柄 - * @param state 扩展关节状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_expand_state(rm_robot_handle *handle, rm_expand_state_t *state); -/** - * @brief 扩展关节速度环控制 - * - * @param handle 机械臂控制句柄 - * @param speed 速度百分比,-100~100。 - - speed<0:扩展关节反方向运动 - - speed>0:扩展关节正方向运动 - - speed=0:扩展关节停止运动 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_expand_speed(rm_robot_handle *handle, int speed); -/** - * @brief 扩展关节位置环控制 - * - * @param handle 机械臂控制句柄 - * @param speed 速度百分比,1~100 - * @param pos 扩展关节角度,单位度 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待升降机到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 其他值:阻塞模式并设置超时时间,单位为秒。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 当前到位设备校验失败,即当前到位设备不为扩展关节。 - - -5: 单线程模式超时未接收到返回,请确保超时时间设置合理。 - */ -RM_INTERFACE_EXPORT int rm_set_expand_pos(rm_robot_handle *handle, int speed, int pos, int block); -/** @} */ // 结束组的定义 - -/** - * @defgroup OnlineProgramming 在线编程 - * - * 包含在线编程文件下发、在线编程文件管理、全局路点管理等相关功能接口。 - * @{ - */ -/** - * @brief 文件下发 - * - * @param handle 机械臂控制句柄 - * @param project 文件下发参数配置结构体 - * @param errline 若运行失败,该参数返回有问题的工程行数,err_line 为 0,则代表校验数据长度不对 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 文件名称校验失败 - - -5: 文件读取失败 - - -6: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_send_project(rm_robot_handle *handle, rm_send_project_t project, int *errline); -/** - * @brief 轨迹规划中改变速度比例系数 - * - * @param handle 机械臂控制句柄 - * @param speed 当前进度条的速度数据 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_plan_speed(rm_robot_handle *handle, int speed); - -/** - * @brief 获取在线编程列表 - * - * @param handle 机械臂控制句柄 - * @param page_num 页码 - * @param page_size 每页大小 - * @param vague_search 模糊搜索 - * @param trajectorys 在线编程程序列表 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_program_trajectory_list(rm_robot_handle *handle, int page_num, int page_size, const char *vague_search,rm_program_trajectorys_t *trajectorys); - -/** - * @brief 开始运行指定编号轨迹 - * - * @param handle 机械臂控制句柄 - * @param id 运行指定的ID,1-100,存在轨迹可运行 - * @param speed 1-100,需要运行轨迹的速度,若设置为0,则按照存储的速度运行 - * @param block 阻塞设置 - * - 多线程模式: - * - 0:非阻塞模式,发送指令后立即返回。 - * - 1:阻塞模式,等待机械臂到达目标位置或规划失败后返回。 - * - 单线程模式: - * - 0:非阻塞模式。 - * - 其他值:阻塞模式并设置超时时间,单位为秒。 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 运行状态已停止但未接收到运行成功,是否在外部停止了轨迹。 - */ -RM_INTERFACE_EXPORT int rm_set_program_id_run(rm_robot_handle *handle, int id, int speed, int block); -/** - * @brief 查询在线编程运行状态 - * - * @param handle 机械臂控制句柄 - * @param run_state 在线编程运行状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 四代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_program_run_state(rm_robot_handle *handle, rm_program_run_state_t *run_state); -/** - * @brief 查询流程图运行状态 - * - * @param handle 机械臂控制句柄 - * @param run_state 流程图运行状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_flowchart_program_run_state(rm_robot_handle *handle, rm_flowchart_run_state_t *run_state); -/** - * @brief 删除指定编号编程文件 - * - * @param handle 机械臂控制句柄 - * @param id 指定编程轨迹的编号 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_delete_program_trajectory(rm_robot_handle *handle, int id); -/** - * @brief 修改指定编号的编程文件 - * - * @param handle 机械臂控制句柄 - * @param id 指定在线编程轨迹编号 - * @param speed 更新后的规划速度比例 1-100 - * @param name 更新后的文件名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_update_program_trajectory(rm_robot_handle *handle, int id, int speed, const char* name); -/** - * @brief 设置 IO 默认运行编号 - * - * @param handle 机械臂控制句柄 - * @param id 设置 IO 默认运行的在线编程文件编号,支持 0-100,0 代表取消设置 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_default_run_program(rm_robot_handle *handle, int id); -/** - * @brief 获取 IO 默认运行编号 - * - * @param handle 机械臂控制句柄 - * @param id IO 默认运行的在线编程文件编号,支持 0-100,0 代表无默认 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_default_run_program(rm_robot_handle *handle, int *id); -/** - * @brief 新增全局路点 - * - * @param handle 机械臂控制句柄 - * @param waypoint 新增全局路点参数(无需输入新增全局路点时间) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_add_global_waypoint(rm_robot_handle *handle, rm_waypoint_t waypoint); -/** - * @brief 更新全局路点 - * - * @param handle 机械臂控制句柄 - * @param waypoint 更新全局路点参数(无需输入更新全局路点时间) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_update_global_waypoint(rm_robot_handle *handle, rm_waypoint_t waypoint); -/** - * @brief 删除全局路点 - * - * @param handle 机械臂控制句柄 - * @param point_name 全局路点名称 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_delete_global_waypoint(rm_robot_handle *handle, const char* point_name); -/** - * @brief 查询指定全局路点 - * - * @param handle 机械臂控制句柄 - * @param name 指定全局路点名称 - * @param point 返回指定的全局路点参数 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_given_global_waypoint(rm_robot_handle *handle, const char* name, rm_waypoint_t *point); -/** - * @brief 查询多个全局路点 - * - * @param handle 机械臂控制句柄 - * @param page_num 页码 - * @param page_size 每页大小 - * @param vague_search 模糊搜索 - * @param point_list 返回的全局路点列表 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_global_waypoints_list(rm_robot_handle *handle, int page_num, int page_size, const char *vague_search,rm_waypoint_list_t *point_list); -/** @} */ // 结束在线编程组的定义 - -/** - * @defgroup UdpConfig UDP主动上报 - * - * 睿尔曼机械臂提供 UDP 机械臂状态主动上报接口,使用时,需要和机械臂处于同一局域网络下,通过设置主动上报配置接口的目标 IP或和机械臂建立 TCP 连接, - * 机械臂即会主动周期性上报机械臂状态数据,数据周期可配置,默认 5ms。配置正确并开启三线程模式后,通过注册回调函数可接收并处理主动上报数据。 - * @{ - */ -/** - * @brief 设置 UDP 机械臂状态主动上报配置 - * - * @param handle 机械臂控制句柄 - * @param config UDP配置结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_realtime_push(rm_robot_handle *handle, rm_realtime_push_config_t config); -/** - * @brief 查询 UDP 机械臂状态主动上报配置 - * - * @param handle 机械臂控制句柄 - * @param config 获取到的UDP机械臂状态主动上报配置 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_realtime_push(rm_robot_handle *handle, rm_realtime_push_config_t *config); -/** @} */ // 结束组的定义 - -/** - * @defgroup Electronic_Fence 电子围栏和虚拟墙 - * - * I 系列机械臂具备电子围栏与虚拟墙功能,并提供了针对控制器所保存的电子围栏或虚拟墙几何模型参数的操作接口。 - * 用户可以通过这些接口,实现对电子围栏或虚拟墙的新增、查询、更新和删除操作,在使用中,可以灵活地使用保存在 - * 控制器中的参数配置,需要注意的是,目前控制器支持保存的参数要求不超过10 个。 - * - * 电子围栏 - * 电子围栏功能通过精确设置参数,确保机械臂的轨迹规划、示教等运动均在设定的电子围栏范围内进行。当机械臂的运动 - * 轨迹可能超出电子围栏的界限时,系统会立即返回相应的错误码,并自动中止运动,从而有效保障机械臂的安全运行。 - * @attention 电子围栏目前仅支持长方体和点面矢量平面这两种形状,并且其仅在仿真模式下生效,为用户提供一个预演轨迹与进行轨迹优化的安全环境。 - * - * 虚拟墙 - * 虚拟墙功能支持在电流环拖动示教与力控拖动示教两种模式下,对拖动范围进行精确限制。在这两种特定的示教模式下,用户可以借助虚拟墙功能,确保 - * 机械臂的拖动操作不会超出预设的范围。 - * @attention 虚拟墙功能目前支持长方体和球体两种形状,并仅在上述两种示教模式下有效。在其他操作模式下,此功能将自动失效。因此,请确保在正确的操作模式 - * 下使用虚拟墙功能,以充分发挥其限制拖动范围的作用。 - * - * @{ - */ -/** - * @brief 新增几何模型参数 - * - * @param handle 机械臂控制句柄 - * @param config 几何模型参数结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 -4:form设置有误 - */ -RM_INTERFACE_EXPORT int rm_add_electronic_fence_config(rm_robot_handle *handle, rm_fence_config_t config); -/** - * @brief 更新几何模型参数 - * - * @param handle 机械臂控制句柄 - * @param config 几何模型参数结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_update_electronic_fence_config(rm_robot_handle *handle, rm_fence_config_t config); -/** - * @brief 删除指定几何模型 - * - * @param handle 机械臂控制句柄 - * @param form_name 几何模型名称,不超过 10 个字节,支持字母、数字、下划线 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_delete_electronic_fence_config(rm_robot_handle *handle, const char* form_name); -/** - * @brief 查询所有几何模型名称 - * - * @param handle 机械臂控制句柄 - * @param names 几何模型名称列表,长度为实际存在几何模型数量 - * @param len 几何模型名称列表长度 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_electronic_fence_list_names(rm_robot_handle *handle, rm_fence_names_t *names, int *len); -/** - * @brief 查询指定几何模型参数 - * - * @param handle 机械臂控制句柄 - * @param name 指定几何模型名称 - * @param config 返回几何模型参数结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_given_electronic_fence_config(rm_robot_handle *handle, const char* name, rm_fence_config_t *config); -/** - * @brief 查询所有几何模型参数 - * - * @param handle 机械臂控制句柄 - * @param config_list 几何模型信息列表,长度为实际存在几何模型数量 - * @param len 几何模型信息列表长度 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_electronic_fence_list_infos(rm_robot_handle *handle, rm_fence_config_list_t *config_list, int *len); -/** - * @brief 设置电子围栏使能状态 - * - * @param handle 机械臂控制句柄 - * @param state 电子围栏使能状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * @note 电子围栏功能通过精确设置参数,确保机械臂的轨迹规划、示教等运动均在设定的电子围栏范围内进行。当机械臂的运动轨迹可能超出电子围栏的界限时, - * 系统会立即返回相应的错误码,并自动中止运动,从而有效保障机械臂的安全运行。需要注意的是,电子围栏目前仅支持长方体和点面矢量平面这两种形状,并 - * 且其仅在仿真模式下生效,为用户提供一个预演轨迹与进行轨迹优化的安全环境 - */ -RM_INTERFACE_EXPORT int rm_set_electronic_fence_enable(rm_robot_handle *handle, rm_electronic_fence_enable_t state); -/** - * @brief 获取电子围栏使能状态 - * - * @param handle 机械臂控制句柄 - * @param state 电子围栏使能状态 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_electronic_fence_enable(rm_robot_handle *handle,rm_electronic_fence_enable_t *state); -/** - * @brief 设置当前电子围栏参数配置 - * - * @param handle 机械臂控制句柄 - * @param config 当前电子围栏参数结构体(无需设置电子围栏名称) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_electronic_fence_config(rm_robot_handle *handle, rm_fence_config_t config); -/** - * @brief 获取当前电子围栏参数 - * - * @param handle 机械臂控制句柄 - * @param config 返回当前电子围栏参数结构体(返回参数中不包含电子围栏名称) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_electronic_fence_config(rm_robot_handle *handle, rm_fence_config_t *config); -/** - * @brief 设置虚拟墙使能状态 - * - * @param handle 机械臂控制句柄 - * @param state 虚拟墙状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_virtual_wall_enable(rm_robot_handle *handle, rm_electronic_fence_enable_t state); -/** - * @brief 获取虚拟墙使能状态 - * - * @param handle 机械臂控制句柄 - * @param state 虚拟墙状态结构体 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_virtual_wall_enable(rm_robot_handle *handle,rm_electronic_fence_enable_t *state); -/** - * @brief 设置当前虚拟墙参数 - * - * @param handle 机械臂控制句柄 - * @param config 当前虚拟墙参数(无需设置虚拟墙名称) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_virtual_wall_config(rm_robot_handle *handle, rm_fence_config_t config); -/** - * @brief 获取当前虚拟墙参数 - * - * @param handle 机械臂控制句柄 - * @param config 当前虚拟墙参数(返回参数中不包含虚拟墙名称) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_virtual_wall_config(rm_robot_handle *handle, rm_fence_config_t *config); -/** @} */ // 结束电子围栏组的定义 - -/** - * @defgroup SelfCollision 自碰撞安全检测 - * - * 睿尔曼机械臂支持自碰撞安全检测,自碰撞安全检测使能状态下,可确保在轨迹规划、示教等运动过程中机械臂的各个部分不会相互碰撞。 - * @attention 以上自碰撞安全检测功能目前只在仿真模式下生效,用于进行预演轨迹与轨迹优化。 - * @{ - */ -/** - * @brief 设置自碰撞安全检测使能状态 - * - * @param handle 机械臂控制句柄 - * @param state true代表使能,false代表禁使能 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_set_self_collision_enable(rm_robot_handle *handle, bool state); -/** - * @brief 获取自碰撞安全检测使能状态 - * - * @param handle 机械臂控制句柄 - * @param state true代表使能,false代表禁使能 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - */ -RM_INTERFACE_EXPORT int rm_get_self_collision_enable(rm_robot_handle *handle,bool *state); -/** @} */ // 结束组的定义 - -/** - * @brief 设置末端生态协议模式 - * @param handle 机械臂控制句柄 - * @param mode 末端生态协议模式 - * 0:禁用协议 - * 9600:开启协议(波特率9600) - * 115200:开启协议(波特率115200) - * 256000:开启协议(波特率256000) - * 460800:开启协议(波特率460800) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 -*/ -RM_INTERFACE_EXPORT int rm_set_rm_plus_mode(rm_robot_handle *handle, int mode); - -/** - * @brief 查询末端生态协议模式 - * @param handle 机械臂控制句柄 - * @param mode 末端生态协议模式 - * 0:禁用协议 - * 9600:开启协议(波特率9600) - * 115200:开启协议(波特率115200) - * 256000:开启协议(波特率256000) - * 460800:开启协议(波特率460800) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * -*/ -RM_INTERFACE_EXPORT int rm_get_rm_plus_mode(rm_robot_handle *handle, int *mode); - -/** - * @brief 设置触觉传感器模式(末端生态协议支持) - * @param handle 机械臂控制句柄 - * @param mode 触觉传感器开关状态 0:关闭触觉传感器 1:打开触觉传感器(返回处理后数据) 2:打开触觉传感器(返回原始数据) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 -*/ -RM_INTERFACE_EXPORT int rm_set_rm_plus_touch(rm_robot_handle *handle, int mode); - -/** - * @brief 查询触觉传感器模式(末端生态协议支持) - * @param handle 机械臂控制句柄 - * @param mode 触觉传感器开关状态 0:关闭触觉传感器 1:打开触觉传感器(返回处理后数据) 2:打开触觉传感器(返回原始数据) - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 -*/ -RM_INTERFACE_EXPORT int rm_get_rm_plus_touch(rm_robot_handle *handle, int *mode); - -/** - * @brief 读取末端设备基础信息(末端生态协议支持) - * @param handle 机械臂控制句柄 - * @param info 末端设备基础信息 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 -*/ -RM_INTERFACE_EXPORT int rm_get_rm_plus_base_info(rm_robot_handle *handle, rm_plus_base_info_t *info); - -/** - * @brief 读取末端设备实时信息(末端生态协议支持) - * @param handle 机械臂控制句柄 - * @param info 末端设备实时信息 - * @return int 函数执行的状态码。 - - 0: 成功。 - - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - - -1: 数据发送失败,通信过程中出现问题。 - - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 -*/ -RM_INTERFACE_EXPORT int rm_get_rm_plus_state_info(rm_robot_handle *handle, rm_plus_state_info_t *info); - - - -/******************************************算法接口*******************************************************/ -/** - * @defgroup Algo 算法接口 - * - * 针对睿尔曼机械臂,提供正逆解、各种位姿参数转换等工具接口。 - * @{ - */ -/** - * @brief 查询算法库版本号 - * @return char* 返回版本号 - */ -RM_INTERFACE_EXPORT char* rm_algo_version(void); -/** - * @brief 初始化算法依赖数据(不连接机械臂时调用) - * - * @param Mode 机械臂型号 - * @param Type 传感器型号 - */ -RM_INTERFACE_EXPORT void rm_algo_init_sys_data(rm_robot_arm_model_e Mode, rm_force_type_e Type); -/** - * @brief 设置安装角度 - * - * @param x X轴安装角度 单位° - * @param y Y轴安装角度 单位° - * @param z z轴安装角度 单位° - */ -RM_INTERFACE_EXPORT void rm_algo_set_angle(float x, float y, float z); -/** - * @brief 获取安装角度 - * - * @param x X轴安装角度 单位° - * @param y Y轴安装角度 单位° - * @param z z轴安装角度 单位° - */ -RM_INTERFACE_EXPORT void rm_algo_get_angle(float* x, float* y, float* z); -/** - * @brief 设置工作坐标系 - * - * @param coord_work 坐标系数据 - */ -RM_INTERFACE_EXPORT void rm_algo_set_workframe(const rm_frame_t* const coord_work); -/** - * @brief 获取当前工作坐标系 - * - * @param coord_work 当前工作坐标系 - */ -RM_INTERFACE_EXPORT void rm_algo_get_curr_workframe(rm_frame_t* coord_work); -/** - * @brief 设置工具坐标系 - * - * @param coord_tool 坐标系数据 - */ -RM_INTERFACE_EXPORT void rm_algo_set_toolframe(const rm_frame_t* const coord_tool); -/** - * @brief 获取当前工具坐标系 - * - * @param coord_tool 当前工具坐标系 - */ -RM_INTERFACE_EXPORT void rm_algo_get_curr_toolframe(rm_frame_t* coord_tool); -/** - * @brief 设置关节最大限位 - * - * @param joint_limit 单位° - */ -RM_INTERFACE_EXPORT void rm_algo_set_joint_max_limit(const float* const joint_limit); -/** - * @brief 获取关节最大限位 - * - * @param joint_limit 返回关节最大限位 - */ -RM_INTERFACE_EXPORT void rm_algo_get_joint_max_limit(float* joint_limit); -/** - * @brief 设置关节最小限位 - * - * @param joint_limit 单位° - */ -RM_INTERFACE_EXPORT void rm_algo_set_joint_min_limit(const float* const joint_limit); -/** - * @brief 获取关节最小限位 - * - * @param joint_limit 返回关节最小限位 - */ -RM_INTERFACE_EXPORT void rm_algo_get_joint_min_limit(float* joint_limit); -/** - * @brief 设置关节最大速度 - * - * @param joint_slim_max RPM - */ -RM_INTERFACE_EXPORT void rm_algo_set_joint_max_speed(const float* const joint_slim_max); -/** - * @brief 获取关节最大速度 - * - * @param joint_slim_max 返回关节最大速度 - */ -RM_INTERFACE_EXPORT void rm_algo_get_joint_max_speed(float* joint_slim_max); -/** - * @brief 设置关节最大加速度 - * - * @param joint_alim_max RPM/s - */ -RM_INTERFACE_EXPORT void rm_algo_set_joint_max_acc(const float* const joint_alim_max); -/** - * @brief 获取关节最大加速度 - * - * @param joint_alim_max 返回关节最大加速度 - */ -RM_INTERFACE_EXPORT void rm_algo_get_joint_max_acc(float* joint_alim_max); -/** - * @brief 设置逆解求解模式 - * - * @param mode true:遍历模式,冗余参数遍历的求解策略。适于当前位姿跟要求解的位姿差别特别大的应用场景,如MOVJ_P、位姿编辑等,耗时较长 - false:单步模式,自动调整冗余参数的求解策略。适于当前位姿跟要求解的位姿差别特别小、连续周期控制的场景,如笛卡尔空间规划的位姿求解等,耗时短 - */ -RM_INTERFACE_EXPORT void rm_algo_set_redundant_parameter_traversal_mode(bool mode); -/** - * @brief 逆解函数,默认遍历模式,可使用Algo_Set_Redundant_Parameter_Traversal_Mode接口设置逆解求解模式 - * - * @param handle 机械臂控制句柄 - * @param params 逆解输入参数结构体 - * @param q_out 输出的关节角度 单位° - * @return int 逆解结果 - * - 0: 逆解成功 - * - 1: 逆解失败 - * - -1: 上一时刻关节角度输入为空 - * - -2: 目标位姿四元数不合法 - * @attention 机械臂已连接时,可直接调用该接口进行计算,计算使用的参数均为机械臂当前的参数; - * 未连接机械臂时,需首先调用初始化算法依赖数据接口,并按照实际需求设置使用的坐标系及关节速度位置等限制 - *(不设置则按照出厂默认的参数进行计算),此时机械臂控制句柄设置为NULL即可 - */ -RM_INTERFACE_EXPORT int rm_algo_inverse_kinematics(rm_robot_handle *handle, rm_inverse_kinematics_params_t params, float *q_out); - -/** - * @brief 计算逆运动学全解(当前仅支持六自由度机器人) - * @param handle 机械臂控制句柄,连接机械臂时传入机械臂控制句柄,不连接时传入NULL - * @param params 逆解输入参数结构体 - * @return rm_inverse_kinematics_all_solve_t 逆解的全解结构体 -*/ -RM_INTERFACE_EXPORT rm_inverse_kinematics_all_solve_t rm_algo_inverse_kinematics_all(rm_robot_handle *handle, rm_inverse_kinematics_params_t params); - -/** - * @brief 从多解中选取最优解(当前仅支持六自由度机器人) - * @param weight 权重,建议默认值为{1,1,1,1,1,1} - * @param params 待选解的全解结构体 - * @return int 最优解索引,选解结果为ik_solve.q_solve[i],如果没有合适的解返回-1(比如求出8组解,但是8组都有关节角度超限位,那么就返回-1) -*/ -RM_INTERFACE_EXPORT int rm_algo_ikine_select_ik_solve(float *weight, rm_inverse_kinematics_all_solve_t params); - - -/** - * @brief 检查逆解结果是否超出关节限位(当前仅支持六自由度机器人) - * @param q_solve 选解,单位:° - * @return int 0:未超限位,1~dof: 第i个关节超限位,-1:当前机器人非六自由度,当前仅支持六自由度机器人 -*/ -RM_INTERFACE_EXPORT int rm_algo_ikine_check_joint_position_limit(const float* const q_solve); - -/** - * @brief 检查逆解结果是否超速(当前仅支持六自由度机器人) - * @param dt 两帧数据之间的时间间隔,即控制周期,单位sec - * @param q_ref 参考关节角度或者第一帧数据角度,单位:° - * @param q_solve 求解结果,即下一帧要发送的角度 - * @return int 0:表示未超限 i:表示关节i超限,优先报序号小的关节 -1:当前机器人非六自由度,当前仅支持六自由度机器人 -*/ -RM_INTERFACE_EXPORT int rm_algo_ikine_check_joint_velocity_limit(float dt, const float* const q_ref, const float* const q_solve); - -/** - * @brief 根据参考位形计算臂角大小(仅支持RM75) - * @param q_ref 当前参考位形的关节角度,单位° - * @param arm_angle 计算结果,当前参考位形对应的臂角大小,单位° - * @return int - * 0: 求解成功 - * -1: 求解失败,或机型非RM75 - * -2: q_ref 输入参数非法 - */ -RM_INTERFACE_EXPORT int rm_algo_calculate_arm_angle_from_config_rm75(float *q_ref, float *arm_angle); - -/** - * @brief 臂角法求解RM75逆运动学 - * @param params rm_inverse_kinematics_params_t,逆解参数结构体 - * @param arm_angle 指定轴角大小,单位:° - * @param q_solve 求解结果,单位:° - * @return int - * 0: 求解成功 - * -1: 求解失败 - * -2: 求解结果超出限位 - * -3: 机型非RM75 - */ -RM_INTERFACE_EXPORT int rm_algo_inverse_kinematics_rm75_for_arm_angle(rm_inverse_kinematics_params_t params, float arm_angle, float *q_solve); - - - -/** - * @brief 通过分析雅可比矩阵最小奇异值, 判断机器人是否处于奇异状态 - * @param q 要判断的关节角度(机械零位描述),单位:° - * @param 最小奇异值阈值,若传NULL,则使用内部默认值,默认值为0.01(该值在0-1之间) - * @return 0:在当前阈值条件下正常 - * -1:表示在当前阈值条件下判断为奇异区 - * -2:表示计算失败 -*/ -RM_INTERFACE_EXPORT int rm_algo_universal_singularity_analyse(const float* const q, float singluar_value_limit); -/** - * @brief 恢复初始阈值(仅适用于解析法分析机器人奇异状态),阈值初始化为:limit_qe=10deg,limit_qw=10deg,limit_d = 0.05m -*/ -RM_INTERFACE_EXPORT void rm_algo_kin_singularity_thresholds_init(); - -/** - * @brief 设置自定义阈值(仅适用于解析法分析机器人奇异状态) - * @param limit_qe 肘部奇异区域范围设置(即J3接近0的范围),unit:°,default: about 10deg - * @param limit_qw 腕部奇异区域范围设置(即J5接近0的范围),unit:°,default: about 10deg - * @param limit_d 肩部奇异区域范围设置(即腕部中心点距离奇异平面的距离), unit: m, default: 0.05 -*/ -RM_INTERFACE_EXPORT void rm_algo_kin_set_singularity_thresholds(float limit_qe_algo, float limit_qw_algo, float limit_d_algo); - -/** - * @brief 获取自定义阈值(仅适用于解析法分析机器人奇异状态) - * - * @param limit_qe 肘部奇异区域范围获取(即J3接近0的范围), unit: °, default: about 10deg - * @param limit_qw 腕部奇异区域范围获取(即J5接近0的范围), unit: °, default: about 10deg - * @param limit_d 肩部奇异区域范围获取(即腕部中心点距离奇异平面的距离), unit: m, default: 0.05 - */ -RM_INTERFACE_EXPORT void rm_algo_kin_get_singularity_thresholds(float* limit_qe_algo, float* limit_qw_algo, float* limit_d_algo); - -/** - * @brief 解析法判断机器人是否处于奇异位形(仅支持六自由度) - * @param q 要判断的关节角度,单位:° - * @param distance 输出参数,返回腕部中心点到肩部奇异平面的距离,该值越接近0说明越接近肩部奇异,单位m,不需要时可传NULL - * @return 0表正常,-1表肩部奇异,-2表肘部奇异,-3表腕部奇异,-4仅支持6自由度机械臂 -*/ -RM_INTERFACE_EXPORT int rm_algo_kin_robot_singularity_analyse(const float* const q, float *distance); -/** - * @brief 设置工具包络球参数 - * @param toolSphere_i 工具包络球编号 (0~4) - * @param data 工具包络球参数,注意其参数在末端法兰坐标系下描述 - */ -RM_INTERFACE_EXPORT void rm_algo_set_tool_envelope(const int toolSphere_i, rm_tool_sphere_t data); - -/** - * @brief 获取工具包络球参数 - * @param toolSphere_i 工具rm_get_tool_voltage包络球编号 (0~4) - * @param data 工具包络球参数,注意其参数在末端法兰坐标系下描述 - */ -RM_INTERFACE_EXPORT void rm_algo_get_tool_envelope(const int toolSphere_i, rm_tool_sphere_t *data); -/** - * @brief 自碰撞检测 - * @param joint 要判断的关节角度,单位:° - * @return int - * 0: 无碰撞 - * 1: 发生碰撞,超出关节限位将被认为发生碰撞 - */ -RM_INTERFACE_EXPORT int rm_algo_safety_robot_self_collision_detection(float *joint); -/** - * @brief 机械臂正解函数 - * - * @param handle 机械臂控制句柄 - * @param joint - * - * @return rm_pose_t 目标位姿 - * @attention 机械臂已连接时,可直接调用该接口进行计算,计算使用的参数均为机械臂当前的参数; - * 未连接机械臂时,需首先调用初始化算法依赖数据接口,并按照实际需求设置使用的坐标系及关节速度位置等限制 - *(不设置则按照出厂默认的参数进行计算),此时机械臂控制句柄设置为NULL即可 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_forward_kinematics(rm_robot_handle *handle,const float* const joint); -/** - * @brief 欧拉角转四元数 - * - * @param eu 欧拉角 - * @return rm_quat_t 四元数 - */ -RM_INTERFACE_EXPORT rm_quat_t rm_algo_euler2quaternion(rm_euler_t eu); -/** - * @brief 四元数转欧拉角 - * - * @param qua 四元数 - * @return rm_euler_t 欧拉角 - */ -RM_INTERFACE_EXPORT rm_euler_t rm_algo_quaternion2euler(rm_quat_t qua); -/** - * @brief 欧拉角转旋转矩阵 - * - * @param state 欧拉角 - * @return rm_matrix_t 旋转矩阵 - */ -RM_INTERFACE_EXPORT rm_matrix_t rm_algo_euler2matrix(rm_euler_t state); -/** - * @brief 位姿转旋转矩阵 - * - * @param state 位姿 - * @return rm_matrix_t 旋转矩阵 - */ -RM_INTERFACE_EXPORT rm_matrix_t rm_algo_pos2matrix(rm_pose_t state); -/** - * @brief 旋转矩阵转位姿 - * - * @param matrix 旋转矩阵 - * @return rm_pose_t 位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_matrix2pos(rm_matrix_t matrix); -/** - * @brief 基坐标系转工作坐标系 - * - * @param matrix 工作坐标系在基坐标系下的矩阵 - * @param state 工具端坐标在基坐标系下位姿 - * @return rm_pose_t 基坐标系在工作坐标系下的位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_base2workframe(rm_matrix_t matrix, rm_pose_t state); -/** - * @brief 工作坐标系转基坐标系 - * - * @param matrix 工作坐标系在基坐标系下的矩阵 - * @param state 工具端坐标在工作坐标系下位姿 - * @return rm_pose_t 工作坐标系在基坐标系下的位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_workframe2base(rm_matrix_t matrix, rm_pose_t state); -/** - * @brief 计算环绕运动位姿 - * - * @param handle 机械臂控制句柄 - * @param curr_joint 当前关节角度 单位° - * @param rotate_axis 旋转轴: 1:x轴, 2:y轴, 3:z轴 - * @param rotate_angle 旋转角度: 旋转角度, 单位(度) - * @param choose_axis 指定计算时使用的坐标系 - * @return rm_pose_t 计算位姿结果 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_rotate_move(rm_robot_handle *handle,const float* const curr_joint, int rotate_axis, float rotate_angle, rm_pose_t choose_axis); -/** - * @brief 计算沿工具坐标系运动位姿 - * - * @param handle 机械臂控制句柄 - * @param curr_joint 当前关节角度,单位:度 - * @param move_lengthx 沿X轴移动长度,单位:米 - * @param move_lengthy 沿Y轴移动长度,单位:米 - * @param move_lengthz 沿Z轴移动长度,单位:米 - * @return rm_pose_t 工作坐标系下的位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_cartesian_tool(rm_robot_handle *handle,const float* const curr_joint, float move_lengthx, - float move_lengthy, float move_lengthz); - /** - * @brief 计算Pos和Rot沿某坐标系有一定的位移和旋转角度后,所得到的位姿数据 - * - * @param handle 机械臂控制句柄,连接机械臂时传入机械臂控制句柄,不连接时传入NULL - * @param poseCurrent 当前时刻位姿(欧拉角形式) - * @param deltaPosAndRot 移动及旋转数组,位置移动(单位:m),旋转(单位:度) - * @param frameMode 坐标系模式选择 0:Work(work即可任意设置坐标系),1:Tool - * @return rm_pose_t 平移旋转后的位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_pose_move(rm_robot_handle *handle,rm_pose_t poseCurrent, const float *deltaPosAndRot, int frameMode); -/** - * @brief 末端位姿转成工具位姿 - * - * @param handle 机械臂控制句柄 - * @param eu_end 基于世界坐标系和默认工具坐标系的末端位姿 - * @return rm_pose_t 基于工作坐标系和工具坐标系的末端位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_end2tool(rm_robot_handle *handle,rm_pose_t eu_end); -/** - * @brief 工具位姿转末端位姿 - * - * @param handle 机械臂控制句柄 - * @param eu_tool 基于工作坐标系和工具坐标系的末端位姿 - * @return rm_pose_t 基于世界坐标系和默认工具坐标系的末端位姿 - */ -RM_INTERFACE_EXPORT rm_pose_t rm_algo_tool2end(rm_robot_handle *handle,rm_pose_t eu_tool); -/** - * @brief 获取DH参数 - * - * @return rm_DH_t DH参数 - */ -RM_INTERFACE_EXPORT rm_dh_t rm_algo_get_dh(); -/** - * @brief 设置DH参数 - * - * @param dh DH参数 - */ -RM_INTERFACE_EXPORT void rm_algo_set_dh(rm_dh_t dh); -/** @} */ // 结束算法组的定义 - -/*********************************************四代控制器新增接口*******************************************************/ - -/** - * @brief 查询轨迹列表 - * @param handle 机械臂控制句柄 - * @param page_num 页码 - * @param page_size 每页大小 - * @param vague_search 模糊搜索 - * @param list 轨迹列表 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_trajectory_file_list(rm_robot_handle *handle, int page_num, int page_size, const char *vague_search,rm_trajectory_list_t *trajectory_list); -/** - * @brief 开始运行指定轨迹 - * @param handle 机械臂控制句柄 - * @param trajectory_name 轨迹名称 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_set_run_trajectory(rm_robot_handle *handle, const char *trajectory_name); -/** - * @brief 删除指定轨迹 - * @param handle 机械臂控制句柄 - * @param trajectory_name 轨迹名称 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_delete_trajectory_file(rm_robot_handle *handle, const char *trajectory_name); -/** - * @brief 保存轨迹到控制机器 - * @param handle 机械臂控制句柄 - * @param trajectory_name 轨迹名称 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_save_trajectory_file(rm_robot_handle *handle, const char *trajectory_name); - -/** - * @brief 设置机械臂急停状态 - * @param handle 机械臂控制句柄 - * @param state 急停状态,true:急停,false:恢复 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_set_arm_emergency_stop(rm_robot_handle *handle, bool state); -/** - * @brief 新增Modbus TCP主站 - * @param handle 机械臂控制句柄 - * @param master Modbus TCP主站信息 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_add_modbus_tcp_master(rm_robot_handle *handle, rm_modbus_tcp_master_info_t master); -/** - * @brief 修改Modbus TCP主站 - * @param handle 机械臂控制句柄 - * @param master_name Modbus TCP主站名称 - * @param master 要修改的Modbus TCP主站信息 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_update_modbus_tcp_master(rm_robot_handle *handle, const char *master_name, rm_modbus_tcp_master_info_t master); -/** - * @brief 删除Modbus TCP主站 - * @param handle 机械臂控制句柄 - * @param master_name Modbus TCP主站名称 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_delete_modbus_tcp_master(rm_robot_handle *handle, const char *master_name); -/** - * @brief 查询Modbus TCP主站 - * @param handle 机械臂控制句柄 - * @param master_name Modbus TCP主站名称 - * @param master Modbus TCP主站信息 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_modbus_tcp_master(rm_robot_handle *handle, const char *master_name, rm_modbus_tcp_master_info_t *master); -/** - * @brief 查询TCP主站列表 - * @param handle 机械臂控制句柄 - * @param page_num 页码 - * @param page_size 每页大小 - * @param vague_search 模糊搜索 - * @param list TCP主站列表 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_modbus_tcp_master_list(rm_robot_handle *handle, int page_num, int page_size, const char *vague_search,rm_modbus_tcp_master_list_t *list); -/** - * @brief 设置控制器RS485模式(四代控制器支持) - * @param handle 机械臂控制句柄 - * @param controller_rs485_mode 0代表默认RS485串行通讯,1代表modbus-RTU主站模式,2-代表modbus-RTU从站模式。 - * @param baudrate 波特率(当前支持9600 19200 38400 57600 115200 230400 460800) - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_set_controller_rs485_mode(rm_robot_handle *handle, int controller_rs485_mode, int baudrate); -/** - * @brief 查询控制器RS485模式(四代控制器支持) - * @param handle 机械臂控制句柄 - * @param controller_rs485_mode 0代表默认RS485串行通讯,1代表modbus-RTU主站模式,2-代表modbus-RTU从站模式。 - * @param baudrate 波特率(当前支持9600 19200 38400 57600 115200 230400 460800) - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_controller_rs485_mode_v4(rm_robot_handle *handle, int *controller_rs485_mode, int *baudrate); -/** - * @brief 设置工具端RS485模式(四代控制器支持) - * @param handle 机械臂控制句柄 - * @param mode 通讯端口,0-设置工具端RS485端口为RTU主站,1-设置工具端RS485端口为灵巧手模式,2-设置工具端RS485端口为夹爪模式。 - * @param baudrate 波特率(当前支持9600,115200,460800) - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_set_tool_rs485_mode(rm_robot_handle *handle, int mode, int baudrate); -/** - * @brief 查询工具端RS485模式(四代控制器支持) - * @param handle 机械臂控制句柄 - * @param tool_rs485_mode 0-代表modbus-RTU主站模式,1-代表灵巧手模式,2-代表夹爪模式。 - * @param baudrate 波特率(当前支持9600,115200,460800) - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_get_tool_rs485_mode_v4(rm_robot_handle *handle, int *tool_rs485_mode, int *baudrate); -/** - * @brief Modbus RTU协议读线圈 - * @param handle 机械臂控制句柄 - * @param param 读线圈参数 - * @param data 读线圈数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_rtu_coils(rm_robot_handle *handle, rm_modbus_rtu_read_params_t param, int *data); -/** - * @brief Modbus RTU协议写线圈 - * @param handle 机械臂控制句柄 - * @param param 写线圈参数 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_write_modbus_rtu_coils(rm_robot_handle *handle, rm_modbus_rtu_write_params_t param); -/** - * @brief Modbus RTU协议读离散量输入 - * @param handle 机械臂控制句柄 - * @param param 读离散输入参数 - * @param data 读离散输入数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_rtu_input_status(rm_robot_handle *handle, rm_modbus_rtu_read_params_t param, int *data); -/** - * @brief Modbus RTU协议读保持寄存器 - * @param handle 机械臂控制句柄 - * @param param 读保持寄存器参数 - * @param data 读保持寄存器数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_rtu_holding_registers(rm_robot_handle *handle, rm_modbus_rtu_read_params_t param, int *data); -/** - * @brief Modbus RTU协议写保持寄存器 - * @param handle 机械臂控制句柄 - * @param param 写保持寄存器参数 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_write_modbus_rtu_registers(rm_robot_handle *handle, rm_modbus_rtu_write_params_t param); -/** - * @brief Modbus RTU协议读输入寄存器 - * @param handle 机械臂控制句柄 - * @param param 读输入寄存器参数 - * @param data 读输入寄存器数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_rtu_input_registers(rm_robot_handle *handle, rm_modbus_rtu_read_params_t param, int *data); -/** - * @brief Modbus TCP协议读线圈 - * @param handle 机械臂控制句柄 - * @param param 读线圈参数 - * @param data 读线圈数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口。 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_tcp_coils(rm_robot_handle *handle, rm_modbus_tcp_read_params_t param, int *data); -/** - * @brief Modbus TCP协议写线圈 - * @param handle 机械臂控制句柄 - * @param param 写线圈参数 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口。 - */ -RM_INTERFACE_EXPORT int rm_write_modbus_tcp_coils(rm_robot_handle *handle, rm_modbus_tcp_write_params_t param); -/** - * @brief Modbus TCP协议读离散量输入 - * @param handle 机械臂控制句柄 - * @param param 读离散输入参数 - * @param data 读离散输入数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口。 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_tcp_input_status(rm_robot_handle *handle, rm_modbus_tcp_read_params_t param, int *data); -/** - * @brief Modbus TCP协议读保持寄存器 - * @param handle 机械臂控制句柄 - * @param param 读保持寄存器参数 - * @param data 读保持寄存器数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口。 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_tcp_holding_registers(rm_robot_handle *handle, rm_modbus_tcp_read_params_t param, int *data); -/** - * @brief Modbus TCP协议写保持寄存器 - * @param handle 机械臂控制句柄 - * @param param 写保持寄存器参数 - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口。 - */ -RM_INTERFACE_EXPORT int rm_write_modbus_tcp_registers(rm_robot_handle *handle, rm_modbus_tcp_write_params_t param); -/** - * @brief Modbus TCP协议读输入寄存器 - * @param handle 机械臂控制句柄 - * @param param 读输入寄存器参数 - * @param data 读输入寄存器数据,数组大小为param.num - * @return int 函数执行的状态码。 - * - 0: 成功。 - * - 1: 控制器返回false,传递参数错误或机械臂状态发生错误。 - * - -1: 数据发送失败,通信过程中出现问题。 - * - -2: 数据接收失败,通信过程中出现问题或者控制器超时没有返回。 - * - -3: 返回值解析失败,接收到的数据格式不正确或不完整。 - * - -4: 三代控制器不支持该接口。 - */ -RM_INTERFACE_EXPORT int rm_read_modbus_tcp_input_registers(rm_robot_handle *handle, rm_modbus_tcp_read_params_t param, int *data); - - -}; - -#endif // __cplusplus - -#endif // MY_CPP_WRAPPER_H \ No newline at end of file diff --git a/third_party/Robotic_Arm/include/rm_version.h b/third_party/Robotic_Arm/include/rm_version.h deleted file mode 100644 index 8ce72a1..0000000 --- a/third_party/Robotic_Arm/include/rm_version.h +++ /dev/null @@ -1,16 +0,0 @@ - -#ifndef RM_VERSION_H -#define RM_VERSION_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define SDK_VERSION ("1.1.0") - -#ifdef __cplusplus -} -#endif - -#endif - \ No newline at end of file diff --git a/third_party/Robotic_Arm/linux/lib/api_cpp.dll b/third_party/Robotic_Arm/linux/lib/api_cpp.dll deleted file mode 100644 index 9c0f307..0000000 Binary files a/third_party/Robotic_Arm/linux/lib/api_cpp.dll and /dev/null differ diff --git a/third_party/Robotic_Arm/linux/lib/api_cpp.lib b/third_party/Robotic_Arm/linux/lib/api_cpp.lib deleted file mode 100644 index c4caa6e..0000000 Binary files a/third_party/Robotic_Arm/linux/lib/api_cpp.lib and /dev/null differ diff --git a/third_party/Robotic_Arm/linux/lib/libapi_cpp.so b/third_party/Robotic_Arm/linux/lib/libapi_cpp.so deleted file mode 100644 index 0c46375..0000000 Binary files a/third_party/Robotic_Arm/linux/lib/libapi_cpp.so and /dev/null differ diff --git a/third_party/Robotic_Arm/windows/win_mingw64_c++_v1.1.0/libapi_cpp.dll b/third_party/Robotic_Arm/windows/win_mingw64_c++_v1.1.0/libapi_cpp.dll deleted file mode 100644 index 1324ec7..0000000 Binary files a/third_party/Robotic_Arm/windows/win_mingw64_c++_v1.1.0/libapi_cpp.dll and /dev/null differ diff --git a/third_party/Robotic_Arm/windows/win_mingw64_c++_v1.1.0/libapi_cpp.dll.a b/third_party/Robotic_Arm/windows/win_mingw64_c++_v1.1.0/libapi_cpp.dll.a deleted file mode 100644 index 3465e6e..0000000 Binary files a/third_party/Robotic_Arm/windows/win_mingw64_c++_v1.1.0/libapi_cpp.dll.a and /dev/null differ diff --git "a/third_party/libcanbus/docs/libcanbus\344\275\277\347\224\250\350\257\264\346\230\216.txt" "b/third_party/libcanbus/docs/libcanbus\344\275\277\347\224\250\350\257\264\346\230\216.txt" new file mode 100644 index 0000000..9da90c5 --- /dev/null +++ "b/third_party/libcanbus/docs/libcanbus\344\275\277\347\224\250\350\257\264\346\230\216.txt" @@ -0,0 +1,31 @@ + +将libcanbus用命令解压到/usr/local/lib/目录下面 + +tar -xvf libcanbus.tar -C /usr/local/lib/ + +配置环境变量: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib + +libcanbus.a为静态库,libcanbus.so为共享库 + +libcanbus_arm 编译器为 arm-linux-gnueabihf-gcc +libcanbus_arm64 编译器为 aarch64-linux-gnu-gcc +libcanbus(ubuntu20) 编译器为 gcc version 9.4.0 +libcanbus(ubuntu22) 编译器为 gcc version 11.3.0 + + +编译时先加载libcanbus库,再加载libusb库(源码注释里面有编译方法)。 + +如果编译提示pthread相关错误,说明libcanbus.tar +自带的libusb库不匹配, 请安装libusb库 sudo apt-get install libusb-1.0-0-dev 并删掉/usr/local/lib目录下的libusb相关库文件 + +如果提示ludev错误,请安装libudev-dev: sudo apt-get install libudev-dev + +如果编译过程中找不到cc1plus 请安装 sudo apt-get install --reinstall build-essential + + +注意:root用户可直接读写usbcan设备,非root用户,需要修改usbcan模块的操作权限,可百度搜索修改方法。 +或者尝试将hcanbus.rules文件放到 /etc/udev/rules.d/, 然后重启系统。 + +各函数使用方法与windows版本的动态库使用一致,只是一些函数,多了一个通道参数。 +(linux下面不能识别为独立双通道,一个双通道设备,有两个通道0和1,0对应can1,1对应can2) + diff --git "a/third_party/libcanbus/docs/linux\345\212\250\346\200\201\345\272\223\344\270\216windows\345\267\256\345\274\202\350\257\264\346\230\216.txt" "b/third_party/libcanbus/docs/linux\345\212\250\346\200\201\345\272\223\344\270\216windows\345\267\256\345\274\202\350\257\264\346\230\216.txt" new file mode 100644 index 0000000..df5ddda --- /dev/null +++ "b/third_party/libcanbus/docs/linux\345\212\250\346\200\201\345\272\223\344\270\216windows\345\267\256\345\274\202\350\257\264\346\230\216.txt" @@ -0,0 +1,8 @@ +linux动态库与windows动态库差异 + +1 linux动态库是libcanbus.so,配合libusb.so使用;windows动态库是Hcanbus.dll。 + +2 linux下一个双通道can只能扫描出一个设备,有0和1两个通道,可分别打开;windows是独立双通道,可扫描出2个设备,每个设备一个通道。 + +3 linux动态库使用方法与windows的动态库基本一致,只是一些函数多了一个通道参数。可用参考windows版本动态库使用说明书来使用这些函数。使用 + 方法也可用参考linux测试源码。 diff --git "a/third_party/libcanbus/docs/\345\212\250\346\200\201\345\272\223\346\216\245\345\217\243\345\207\275\346\225\260\344\275\277\347\224\250\350\257\264\346\230\216(windows\347\211\210\346\234\254).pdf" "b/third_party/libcanbus/docs/\345\212\250\346\200\201\345\272\223\346\216\245\345\217\243\345\207\275\346\225\260\344\275\277\347\224\250\350\257\264\346\230\216(windows\347\211\210\346\234\254).pdf" new file mode 100644 index 0000000..1f6685d Binary files /dev/null and "b/third_party/libcanbus/docs/\345\212\250\346\200\201\345\272\223\346\216\245\345\217\243\345\207\275\346\225\260\344\275\277\347\224\250\350\257\264\346\230\216(windows\347\211\210\346\234\254).pdf" differ diff --git "a/third_party/libcanbus/docs/\346\263\242\347\211\271\347\216\207\350\256\241\347\256\227\345\231\250\344\275\277\347\224\250\350\257\264\346\230\216.pdf" "b/third_party/libcanbus/docs/\346\263\242\347\211\271\347\216\207\350\256\241\347\256\227\345\231\250\344\275\277\347\224\250\350\257\264\346\230\216.pdf" new file mode 100644 index 0000000..608984b Binary files /dev/null and "b/third_party/libcanbus/docs/\346\263\242\347\211\271\347\216\207\350\256\241\347\256\227\345\231\250\344\275\277\347\224\250\350\257\264\346\230\216.pdf" differ diff --git a/third_party/libcanbus/include/linux/Hcanbus.h b/third_party/libcanbus/include/linux/Hcanbus.h new file mode 100644 index 0000000..c9adfdf --- /dev/null +++ b/third_party/libcanbus/include/linux/Hcanbus.h @@ -0,0 +1,120 @@ +#ifndef CANBUS_H +#define CANBUS_H + +#include + +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +#define LIBUSB_CALL __stdcall +#else +#define LIBUSB_CALL +#endif + +typedef unsigned int u32; +typedef unsigned char u8; + +typedef struct _Dev_Info { + char HW_Type[32]; + char HW_Ser[32]; + char HW_Ver[32]; + char FW_Ver[32]; + char MF_Date[32]; +} Dev_Info, *PDev_Info; + +typedef struct _Can_Config { + unsigned int Baudrate; + unsigned short Pres; + unsigned char Tseg1; + unsigned char Tseg2; + unsigned char SJW; + unsigned char Config; + unsigned char Model; + unsigned char Reserved; +} Can_Config, *P_Can_Config; + +typedef struct _CanFD_Config { + unsigned int NomBaud; + unsigned int DatBaud; + unsigned short NomPre; + unsigned char NomTseg1; + unsigned char NomTseg2; + unsigned char NomSJW; + unsigned char DatPre; + unsigned char DatTseg1; + unsigned char DatTseg2; + unsigned char DatSJW; + unsigned char Config; + unsigned char Model; + unsigned char Cantype; +} CanFD_Config, *P_CanFD_Config; + +typedef struct _Can_Msg { + unsigned int ID; + unsigned int TimeStamp; + unsigned char FrameType; + unsigned char DataLen; + unsigned char ExternFlag; + unsigned char RemoteFlag; + unsigned char BusSatus; + unsigned char ErrSatus; + unsigned char TECounter; + unsigned char RECounter; + unsigned char Data[8]; +} Can_Msg, *P_Can_Msg; + +typedef struct _CanFD_Msg { + unsigned int ID; + unsigned int TimeStamp; + unsigned char FrameType; + unsigned char DLC; + unsigned char ExternFlag; + unsigned char RemoteFlag; + unsigned char BusSatus; + unsigned char ErrSatus; + unsigned char TECounter; + unsigned char RECounter; + unsigned char Data[64]; +} CanFD_Msg, *P_CanFD_Msg; + +typedef struct _Can_Status { + unsigned char BusSatus; + unsigned char ErrSatus; + unsigned char TECounter; + unsigned char RECounter; + unsigned int TimeStamp; +} Can_Status, *P_Can_Status; + +#ifdef __cplusplus +extern "C" { +#endif + +int LIBUSB_CALL CAN_ScanDevice(void); +int LIBUSB_CALL CAN_OpenDevice(u32 devNum, u32 chNum); +int LIBUSB_CALL CAN_CloseDevice(u32 devNum, u32 chNum); + +int LIBUSB_CALL CAN_GetDevType(u32 devNum); +int LIBUSB_CALL CAN_GetDevPlck(u32 devNum); +int LIBUSB_CALL CAN_ReadDevInfo(u32 devNum, PDev_Info devinfo); + +int LIBUSB_CALL CAN_GetTimeStamp(u32 devNum, u32 chNum, u32 *timestamp); +int LIBUSB_CALL CAN_SetTimeStamp(u32 devNum, u32 chNum, u32 timestamp, char mode); + +int LIBUSB_CALL CAN_SetFilter(u32 devNum, u32 chNum, char namber, char type, u32 ftID, u32 ftMask, char enable); +int LIBUSB_CALL CAN_Reset(u32 devNum, u32 chNum); +int LIBUSB_CALL CAN_GetStatus(u32 devNum, u32 chNum, P_Can_Status status); +int LIBUSB_CALL CAN_Init(u32 devNum, u32 chNum, P_Can_Config pInitConfig); +int LIBUSB_CALL CAN_Transmit(u32 devNum, u32 chNum, P_Can_Msg canmsg, u32 items, int timeou); +int LIBUSB_CALL CAN_TransmitRt(u32 devNum, u32 chNum, P_Can_Msg canmsg, u32 items, u32 *txitems, int timeou); +int LIBUSB_CALL CAN_GetReceiveNum(u32 devNum, u32 chNum); +int LIBUSB_CALL CAN_Receive(u32 devNum, u32 chNum, P_Can_Msg canmsg, int Len, int timeou); + +int LIBUSB_CALL CANFD_Init(u32 devNum, u32 chNum, P_CanFD_Config pInitConfig); +int LIBUSB_CALL CANFD_Transmit(u32 devNum, u32 chNum, P_CanFD_Msg canmsg, u32 items, int timeout); +int LIBUSB_CALL CANFD_TransmitRt(u32 devNum, u32 chNum, P_CanFD_Msg canmsg, u32 items, u32 *txitems, int timeou); +int LIBUSB_CALL CANFD_GetReceiveNum(u32 devNum, u32 chNum); +int LIBUSB_CALL CANFD_Receive(u32 devNum, u32 chNum, P_CanFD_Msg canmsg, int Len, int timeout); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/third_party/libcanbus/include/windows/Hcanbus.h b/third_party/libcanbus/include/windows/Hcanbus.h new file mode 100644 index 0000000..a946572 --- /dev/null +++ b/third_party/libcanbus/include/windows/Hcanbus.h @@ -0,0 +1,121 @@ + +#ifndef HCANBUS_H +#define HCANBUS_H + +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +#define LIBUSB_CALL WINAPI +#else +#define LIBUSB_CALL +#endif + +typedef struct _Dev_Info { + char HW_Type[32]; //设备型号 字符串 + char HW_Ser[32]; //设备序列号 字符串 + char HW_Ver[32]; //硬件版本 字符串 + char FW_Ver[32]; //软件版本 字符串 + char MF_Date[32]; //生产日期 字符串 +} Dev_Info, *PDev_Info; + +typedef struct _Can_Config { + unsigned int Baudrate; + unsigned short Pres; // Pres,Tseg1,Tseg2如果与Baudrate不匹配,动态库会自动按 + unsigned char Tseg1; // Baudrate重新计算Pres,Tseg1,Tseg2,SJW并且采样点设置为 + unsigned char Tseg2; // 75%左右。一般情况可以只设置波特率,Pres,Tseg1,Tseg2填0 + unsigned char SJW; + unsigned char Config; //配置信息:0x01接通内部电阻 0x02离线唤醒 0x04自动重传 + unsigned char Model; //工作模式:0 正常模式,1 环回模式,2 静默模式,3 静默环回模式 + unsigned char Reserved; //保留 +}Can_Config, *P_Can_Config; + +typedef struct _CanFD_Config { + unsigned int NomBaud; //常规波特率 + unsigned int DatBaud; //数据波特率 + unsigned short NomPre; // NomPre,NomTseg1,NomTseg2如果与NomBaud不匹配,动态库会自动按 + unsigned char NomTseg1; // NomBaud重新计算NomPre,NomTseg1,NomTseg2,NomSJW并且采样点设置为 + unsigned char NomTseg2; // 75%左右。这些值可借助波特率计算器计算后设置 + unsigned char NomSJW; + unsigned char DatPre; // DatPre,DatTseg1,DatTseg2如果与DatBaud不匹配,动态库会自动按 + unsigned char DatTseg1; // DatBaud重新计算DatPre,DatTseg1,DatTseg2,DatSJW并且采样点设置为 + unsigned char DatTseg2; // 75%左右。这些值可借助波特率计算器计算后设置 + unsigned char DatSJW; + unsigned char Config; //配置信息:0x01接通内部电阻 0x02离线唤醒 0x04自动重传 + unsigned char Model; //工作模式:0 正常模式,1 环回模式,2 静默模式,3 静默环回模式 + unsigned char Cantype; //CAN模式: 0 CAN,1 IOS CANFD,2 Non-ISO CANFD +}CanFD_Config, *P_CanFD_Config; + +typedef struct _Can_Msg { + unsigned int ID; //报文ID + unsigned int TimeStamp; //微秒级时间戳 + unsigned char FrameType; //帧类型 + unsigned char DataLen; //有效字节数 + unsigned char ExternFlag; //扩展帧标识:0标准帧,1扩展帧 + unsigned char RemoteFlag; //远程帧标识:0数据帧,1远程帧 + unsigned char BusSatus; //总线状态 + unsigned char ErrSatus; //错误状态 + unsigned char TECounter; //发送错误计数 + unsigned char RECounter; //接收错误计数 + unsigned char Data[8]; //报文数据 +}Can_Msg, *P_Can_Msg; + +typedef struct _CanFD_Msg { + unsigned int ID; //报文ID + unsigned int TimeStamp; //微秒级时间戳 + unsigned char FrameType; //帧类型 + unsigned char DLC; //DLC不等于数据长度。最大值15,对于数据长度64 + unsigned char ExternFlag; //扩展帧标识:0标准帧,1扩展帧 + unsigned char RemoteFlag; //远程帧标识:0数据帧,1远程帧 + unsigned char BusSatus; //总线状态 + unsigned char ErrSatus; //错误状态 + unsigned char TECounter; //发送错误计数 + unsigned char RECounter; //接收错误计数 + unsigned char Data[64]; //报文数据 +}CanFD_Msg, *P_CanFD_Msg; + +typedef struct _Can_Status { + unsigned char BusSatus; //总线状态 + unsigned char ErrSatus; //错误状态 + unsigned char TECounter; //发送错误计数 + unsigned char RECounter; //接收错误计数 + unsigned int TimeStamp; //产生状态时的时间戳 +}Can_Status, *P_Can_Status; + +#ifdef __cplusplus +extern "C" { +#endif + +int __stdcall Reg_HotPlug_Func(void(*pfunc)(void)); //热拔插函数 +int __stdcall CAN_ScanDevice(void); //扫描CAN,CANFD设备 + +int __stdcall CAN_OpenDevice(unsigned int devNum); //打开CAN,CANFD设备 +int __stdcall CAN_CloseDevice(unsigned int devNum); //关闭CAN,CANFD设备 + +int __stdcall CAN_GetDevType(unsigned int devNum); //获取CAN,CANFD类型 0:常规CAN,1:CANFD +int __stdcall CAN_GetDevPlck(unsigned int devNum); //获取CAN,CANFD主频 +int __stdcall CAN_ReadDevInfo(unsigned int devNum, PDev_Info devinfo); //读取CAN,CANFD设备信息 + +int __stdcall CAN_GetTimeStamp(unsigned int devNum,unsigned int *timestamp); //获取CAN,CANFD时间戳 +int __stdcall CAN_SetTimeStamp(unsigned int devNum,unsigned int timestamp,char mode);//设置CAN,CANFD时间戳 mode 0:设置当前通道,1设置同硬件所有通道 + +int __stdcall CAN_SetFilter(unsigned int devNum,char namber, char type, unsigned int ftID, unsigned int ftMask, char enable); //设置CAN,CANFD硬件屏蔽 +int __stdcall CAN_Reset(unsigned int devNum); //复位CAN,CANFD设备 +int __stdcall CAN_GetStatus(unsigned int devNum,P_Can_Status status); //获取CAN,CANFD设备状态 + +int __stdcall CAN_Init(unsigned int devNum,P_Can_Config pInitConfig); //初始化CAN设备 +int __stdcall CAN_Transmit(unsigned int devNum, P_Can_Msg canmsg, unsigned int items, int timeou); //发送CAN报文 +int __stdcall CAN_TransmitRt(unsigned int devNum, P_Can_Msg canmsg, unsigned int items, unsigned int *txitems, int timeou); //定时发送CAN报文 +int __stdcall CAN_GetReceiveNum(unsigned int devNum); //获取接收缓冲区中接收到但尚未被读取的帧数量 +int __stdcall CAN_Receive(unsigned int devNum,P_Can_Msg canmsg, int Len, int timeou); //接收CAN报文 + +int __stdcall CANFD_Init(unsigned int devNum, P_CanFD_Config pInitConfig); +int __stdcall CANFD_Transmit(unsigned int devNum, P_CanFD_Msg canmsg, unsigned int items, int timeout); +int __stdcall CANFD_TransmitRt(unsigned int devNum, P_CanFD_Msg canmsg, unsigned int items, unsigned int *txitems, int timeou); //定时发送CAN报文 +int __stdcall CANFD_GetReceiveNum(unsigned int devNum);//获取接收缓冲区中接收到但尚未被读取的帧数量 +int __stdcall CANFD_Receive(unsigned int devNum, P_CanFD_Msg canmsg, unsigned int Len, int timeout); //接收CANFD报文 +#ifdef __cplusplus +} +#endif + +#endif + + + diff --git a/third_party/libcanbus/linux/arm/libcanbus.a b/third_party/libcanbus/linux/arm/libcanbus.a new file mode 100755 index 0000000..064ccbf Binary files /dev/null and b/third_party/libcanbus/linux/arm/libcanbus.a differ diff --git a/third_party/libcanbus/linux/arm/libcanbus.so b/third_party/libcanbus/linux/arm/libcanbus.so new file mode 100755 index 0000000..0815d60 Binary files /dev/null and b/third_party/libcanbus/linux/arm/libcanbus.so differ diff --git a/third_party/libcanbus/linux/arm/libusb-1.0.a b/third_party/libcanbus/linux/arm/libusb-1.0.a new file mode 100644 index 0000000..c712d7b Binary files /dev/null and b/third_party/libcanbus/linux/arm/libusb-1.0.a differ diff --git a/third_party/libcanbus/linux/arm/libusb-1.0.la b/third_party/libcanbus/linux/arm/libusb-1.0.la new file mode 100755 index 0000000..56bdbe1 --- /dev/null +++ b/third_party/libcanbus/linux/arm/libusb-1.0.la @@ -0,0 +1,41 @@ +# libusb-1.0.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-14 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libusb-1.0.so.0' + +# Names of this library. +library_names='libusb-1.0.so.0.3.0 libusb-1.0.so.0 libusb-1.0.so' + +# The name of the static archive. +old_library='libusb-1.0.a' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags=' -pthread' + +# Libraries that this one depends upon. +dependency_libs=' -latomic' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libusb-1.0. +current=3 +age=3 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/bcwu/libusb_arm/lib' diff --git a/third_party/libcanbus/linux/arm/libusb-1.0.so b/third_party/libcanbus/linux/arm/libusb-1.0.so new file mode 120000 index 0000000..fe95f18 --- /dev/null +++ b/third_party/libcanbus/linux/arm/libusb-1.0.so @@ -0,0 +1 @@ +libusb-1.0.so.0.3.0 \ No newline at end of file diff --git a/third_party/libcanbus/linux/arm/libusb-1.0.so.0 b/third_party/libcanbus/linux/arm/libusb-1.0.so.0 new file mode 120000 index 0000000..fe95f18 --- /dev/null +++ b/third_party/libcanbus/linux/arm/libusb-1.0.so.0 @@ -0,0 +1 @@ +libusb-1.0.so.0.3.0 \ No newline at end of file diff --git a/third_party/libcanbus/linux/arm/libusb-1.0.so.0.3.0 b/third_party/libcanbus/linux/arm/libusb-1.0.so.0.3.0 new file mode 100755 index 0000000..c9ea91d Binary files /dev/null and b/third_party/libcanbus/linux/arm/libusb-1.0.so.0.3.0 differ diff --git a/third_party/libcanbus/linux/arm64/libcanbus.a b/third_party/libcanbus/linux/arm64/libcanbus.a new file mode 100755 index 0000000..43965c6 Binary files /dev/null and b/third_party/libcanbus/linux/arm64/libcanbus.a differ diff --git a/third_party/libcanbus/linux/arm64/libcanbus.so b/third_party/libcanbus/linux/arm64/libcanbus.so new file mode 100755 index 0000000..68022a4 Binary files /dev/null and b/third_party/libcanbus/linux/arm64/libcanbus.so differ diff --git a/third_party/libcanbus/linux/arm64/libusb-1.0.a b/third_party/libcanbus/linux/arm64/libusb-1.0.a new file mode 100644 index 0000000..c8be42c Binary files /dev/null and b/third_party/libcanbus/linux/arm64/libusb-1.0.a differ diff --git a/third_party/libcanbus/linux/arm64/libusb-1.0.la b/third_party/libcanbus/linux/arm64/libusb-1.0.la new file mode 100755 index 0000000..d0a7e1c --- /dev/null +++ b/third_party/libcanbus/linux/arm64/libusb-1.0.la @@ -0,0 +1,41 @@ +# libusb-1.0.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-14 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libusb-1.0.so.0' + +# Names of this library. +library_names='libusb-1.0.so.0.3.0 libusb-1.0.so.0 libusb-1.0.so' + +# The name of the static archive. +old_library='libusb-1.0.a' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags=' -pthread' + +# Libraries that this one depends upon. +dependency_libs=' -latomic' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libusb-1.0. +current=3 +age=3 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/bcwu/libusb_arm64/lib' diff --git a/third_party/libcanbus/linux/arm64/libusb-1.0.so b/third_party/libcanbus/linux/arm64/libusb-1.0.so new file mode 120000 index 0000000..fe95f18 --- /dev/null +++ b/third_party/libcanbus/linux/arm64/libusb-1.0.so @@ -0,0 +1 @@ +libusb-1.0.so.0.3.0 \ No newline at end of file diff --git a/third_party/libcanbus/linux/arm64/libusb-1.0.so.0 b/third_party/libcanbus/linux/arm64/libusb-1.0.so.0 new file mode 120000 index 0000000..fe95f18 --- /dev/null +++ b/third_party/libcanbus/linux/arm64/libusb-1.0.so.0 @@ -0,0 +1 @@ +libusb-1.0.so.0.3.0 \ No newline at end of file diff --git a/third_party/libcanbus/linux/arm64/libusb-1.0.so.0.3.0 b/third_party/libcanbus/linux/arm64/libusb-1.0.so.0.3.0 new file mode 100755 index 0000000..59cb530 Binary files /dev/null and b/third_party/libcanbus/linux/arm64/libusb-1.0.so.0.3.0 differ diff --git a/third_party/libcanbus/linux/ubuntu20/libcanbus.a b/third_party/libcanbus/linux/ubuntu20/libcanbus.a new file mode 100755 index 0000000..9fe59df Binary files /dev/null and b/third_party/libcanbus/linux/ubuntu20/libcanbus.a differ diff --git a/third_party/libcanbus/linux/ubuntu20/libcanbus.so b/third_party/libcanbus/linux/ubuntu20/libcanbus.so new file mode 100755 index 0000000..de3c047 Binary files /dev/null and b/third_party/libcanbus/linux/ubuntu20/libcanbus.so differ diff --git a/third_party/libcanbus/linux/ubuntu20/libusb-1.0.a b/third_party/libcanbus/linux/ubuntu20/libusb-1.0.a new file mode 100755 index 0000000..2d42e8f Binary files /dev/null and b/third_party/libcanbus/linux/ubuntu20/libusb-1.0.a differ diff --git a/third_party/libcanbus/linux/ubuntu20/libusb-1.0.la b/third_party/libcanbus/linux/ubuntu20/libusb-1.0.la new file mode 100755 index 0000000..96e977d --- /dev/null +++ b/third_party/libcanbus/linux/ubuntu20/libusb-1.0.la @@ -0,0 +1,41 @@ +# libusb-1.0.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-14 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libusb-1.0.so.0' + +# Names of this library. +library_names='libusb-1.0.so.0.3.0 libusb-1.0.so.0 libusb-1.0.so' + +# The name of the static archive. +old_library='libusb-1.0.a' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags=' -pthread' + +# Libraries that this one depends upon. +dependency_libs=' -ludev -latomic -lpthread' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libusb-1.0. +current=3 +age=3 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/usr/local/lib' diff --git a/third_party/libcanbus/linux/ubuntu20/libusb-1.0.so b/third_party/libcanbus/linux/ubuntu20/libusb-1.0.so new file mode 120000 index 0000000..fe95f18 --- /dev/null +++ b/third_party/libcanbus/linux/ubuntu20/libusb-1.0.so @@ -0,0 +1 @@ +libusb-1.0.so.0.3.0 \ No newline at end of file diff --git a/third_party/libcanbus/linux/ubuntu20/libusb-1.0.so.0 b/third_party/libcanbus/linux/ubuntu20/libusb-1.0.so.0 new file mode 120000 index 0000000..fe95f18 --- /dev/null +++ b/third_party/libcanbus/linux/ubuntu20/libusb-1.0.so.0 @@ -0,0 +1 @@ +libusb-1.0.so.0.3.0 \ No newline at end of file diff --git a/third_party/libcanbus/linux/ubuntu20/libusb-1.0.so.0.3.0 b/third_party/libcanbus/linux/ubuntu20/libusb-1.0.so.0.3.0 new file mode 100755 index 0000000..c47a270 Binary files /dev/null and b/third_party/libcanbus/linux/ubuntu20/libusb-1.0.so.0.3.0 differ diff --git a/third_party/libcanbus/linux/ubuntu22/libcanbus.a b/third_party/libcanbus/linux/ubuntu22/libcanbus.a new file mode 100644 index 0000000..f4fae9c Binary files /dev/null and b/third_party/libcanbus/linux/ubuntu22/libcanbus.a differ diff --git a/third_party/libcanbus/linux/ubuntu22/libcanbus.so b/third_party/libcanbus/linux/ubuntu22/libcanbus.so new file mode 100755 index 0000000..c5c97a3 Binary files /dev/null and b/third_party/libcanbus/linux/ubuntu22/libcanbus.so differ diff --git a/third_party/libcanbus/linux/ubuntu22/libusb-1.0.a b/third_party/libcanbus/linux/ubuntu22/libusb-1.0.a new file mode 100644 index 0000000..aa27bb7 Binary files /dev/null and b/third_party/libcanbus/linux/ubuntu22/libusb-1.0.a differ diff --git a/third_party/libcanbus/linux/ubuntu22/libusb-1.0.la b/third_party/libcanbus/linux/ubuntu22/libusb-1.0.la new file mode 100755 index 0000000..a8841cd --- /dev/null +++ b/third_party/libcanbus/linux/ubuntu22/libusb-1.0.la @@ -0,0 +1,41 @@ +# libusb-1.0.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-14 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libusb-1.0.so.0' + +# Names of this library. +library_names='libusb-1.0.so.0.3.0 libusb-1.0.so.0 libusb-1.0.so' + +# The name of the static archive. +old_library='libusb-1.0.a' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags=' -pthread' + +# Libraries that this one depends upon. +dependency_libs=' -ludev -latomic' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libusb-1.0. +current=3 +age=3 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/usr/local/lib/lib' diff --git a/third_party/libcanbus/linux/ubuntu22/libusb-1.0.so b/third_party/libcanbus/linux/ubuntu22/libusb-1.0.so new file mode 100755 index 0000000..8d65c5d Binary files /dev/null and b/third_party/libcanbus/linux/ubuntu22/libusb-1.0.so differ diff --git a/third_party/libcanbus/linux/ubuntu22/libusb-1.0.so.0 b/third_party/libcanbus/linux/ubuntu22/libusb-1.0.so.0 new file mode 100755 index 0000000..8d65c5d Binary files /dev/null and b/third_party/libcanbus/linux/ubuntu22/libusb-1.0.so.0 differ diff --git a/third_party/libcanbus/linux/ubuntu22/libusb-1.0.so.0.3.0 b/third_party/libcanbus/linux/ubuntu22/libusb-1.0.so.0.3.0 new file mode 100755 index 0000000..8d65c5d Binary files /dev/null and b/third_party/libcanbus/linux/ubuntu22/libusb-1.0.so.0.3.0 differ diff --git a/third_party/libcanbus/rules/hcanbus.rules b/third_party/libcanbus/rules/hcanbus.rules new file mode 100644 index 0000000..b3327fe --- /dev/null +++ b/third_party/libcanbus/rules/hcanbus.rules @@ -0,0 +1,9 @@ + + +# 将文件放到 /etc/udev/rules.d/ +# 然后重启系统 + +SUBSYSTEMS=="usb", ATTRS{idVendor}=="a8fa", ATTRS{idProduct}=="8598", GROUP="plugdev", MODE="0666" + + + diff --git "a/third_party/libcanbus/tools/windows/\346\263\242\347\211\271\347\216\207\350\256\241\347\256\227\345\231\250.exe" "b/third_party/libcanbus/tools/windows/\346\263\242\347\211\271\347\216\207\350\256\241\347\256\227\345\231\250.exe" new file mode 100644 index 0000000..709de46 Binary files /dev/null and "b/third_party/libcanbus/tools/windows/\346\263\242\347\211\271\347\216\207\350\256\241\347\256\227\345\231\250.exe" differ diff --git a/third_party/libcanbus/windows/x64/HCanbus.dll b/third_party/libcanbus/windows/x64/HCanbus.dll new file mode 100644 index 0000000..adf0381 Binary files /dev/null and b/third_party/libcanbus/windows/x64/HCanbus.dll differ diff --git a/third_party/libcanbus/windows/x64/HCanbus.lib b/third_party/libcanbus/windows/x64/HCanbus.lib new file mode 100644 index 0000000..6373795 Binary files /dev/null and b/third_party/libcanbus/windows/x64/HCanbus.lib differ diff --git a/third_party/libcanbus/windows/x86/HCanbus.dll b/third_party/libcanbus/windows/x86/HCanbus.dll new file mode 100644 index 0000000..f5fe956 Binary files /dev/null and b/third_party/libcanbus/windows/x86/HCanbus.dll differ diff --git a/third_party/libcanbus/windows/x86/HCanbus.lib b/third_party/libcanbus/windows/x86/HCanbus.lib new file mode 100644 index 0000000..7aec8d3 Binary files /dev/null and b/third_party/libcanbus/windows/x86/HCanbus.lib differ