diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 345c6fe..7924222 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -68,9 +68,9 @@ jobs:
- name: Setup LinkerHand SDK
run: |
- git clone --branch v1.1.7 https://github.com/linker-bot/linkerhand-cpp-sdk.git /tmp/sdk
+ git clone --depth 1 --branch v2.1.8 https://github.com/linker-bot/linkerhand-cpp-sdk.git /tmp/sdk
cd /tmp/sdk && mkdir build && cd build
- cmake .. && make -j$(nproc) && make install && ldconfig
+ cmake .. -DBUILD_EXAMPLES=OFF && make install && ldconfig
- name: Build Workspace
id: build_step
diff --git a/.gitignore b/.gitignore
index e8b072e..82063c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
build
install
-log
\ No newline at end of file
+log
+.vscode/
+src/linker_hand_cpp_ros2/scripts/_*
+CLAUDE.md
\ No newline at end of file
diff --git a/README.md b/README.md
index 8ab9554..86b23c9 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ LinkerHand-CPP-ROS2 是灵心巧手科技有限公司开发,基于 LinkerHand-
- [环境要求](#-环境要求)
- [快速开始](#-快速开始)
- [话题详情](#-话题详情)
-- [使用示例](#-使用示例)
+- [控制 GUI](#️-控制-gui)
- [许可证](#-许可证)
- [联系我们](#-联系我们)
- [更新日志](#-更新日志)
@@ -24,53 +24,88 @@ LinkerHand-CPP-ROS2 是灵心巧手科技有限公司开发,基于 LinkerHand-
- **操作系统**: Linux (Ubuntu 20.04+ 推荐)
- **架构**: x86_64
-- **编译器**: GCC 7.0+ 或 Clang 5.0+
+- **编译器**: GCC 7.0+ 或 Clang 6.0+(C++17)
- **CMake**: 3.15+
-- **依赖**: ROS2 (推荐 Foxy 或 Humble)、[linkerhand-cpp-sdk](https://github.com/linker-bot/linkerhand-cpp-sdk/releases/tag/v1.1.7)
+- **依赖**: ROS2 (推荐 Foxy 或 Humble)、[linkerhand-cpp-sdk v2.1.8](https://github.com/linker-bot/linkerhand-cpp-sdk/releases/tag/v2.1.8)、`nlohmann_json`
+- **GUI 可选依赖**: `python3-tk`、`rclpy`(用于 `hand_control_gui.py`)
-> 注:本项目仅支持linkerhand-cpp-sdk v1.1.7及以下版本
+> 注:CI 已适配 linkerhand-cpp-sdk v2.1.8;O20 依赖 CAN-FD,当前 ROS2 节点仍以普通 CAN 为主,暂未完成 O20 实机运行适配。Modbus 通信当前仅支持 O6 / L7 / L10。
## 🚀 快速开始
+
#### 下载
+
git clone https://github.com/linker-bot/linkerhand-cpp-ros2.git
+#### 安装 SDK
+
+先安装匹配版本的 [linkerhand-cpp-sdk v2.1.8](https://github.com/linker-bot/linkerhand-cpp-sdk/releases/tag/v2.1.8)(见其 README)。本仓库通过 `find_package(linkerhand-cpp-sdk 2.0 CONFIG REQUIRED)` 引用;节点的 RPATH 会指向 `${linkerhand-cpp-sdk_LIBRARY_DIR}`,SDK 位置变更后需要重新 `colcon build`。
+
#### 编译
+
cd linkerhand-cpp-ros2/
- colcon build
+ colcon build # 全量构建
+ colcon build --packages-select linker_hand_cpp_ros2 # 仅构建核心节点包
-#### 配置XML文件
+#### 启动 CAN 设备
-```bash
+节点通过 SocketCAN 打开 `can0` / `can1` 等接口。使用前需先把 CAN 通道拉起(`CAN_BITRATE` 与 launch 参数保持一致):
+
+ sudo ip link set can0 down 2>/dev/null
+ sudo ip link set can0 up type can bitrate 1000000
+
+> Modbus 通信当前仅支持 O6 / L7 / L10;O20 依赖 CAN-FD,暂未完成 O20 实机运行适配。
+
+#### 配置 XML 文件
+
+`launch/run.xml` 用于双手同时启动,`launch/run_left.xml` 用于仅启动单手。以 `run.xml` 为例(省略部分与实际默认值对齐):
+
+```xml
-
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
+
+
+
......
-
+
```
+> 手动打开CAN设备后,执行launch会自动检测左手或右手CAN通道。
+
#### 运行
+
source install/setup.bash
- ros2 launch linkerhand_cpp_ros2 run.xml
+ # 双手(按 run.xml 默认配置启动)
+ ros2 launch linker_hand_cpp_ros2 run.xml
+ # 仅左手
+ ros2 launch linker_hand_cpp_ros2 run_left.xml
+ # 覆盖某个参数的示例
+ ros2 launch linker_hand_cpp_ros2 run.xml LEFT_JOINTS:=L10 LEFT_CANBUS:=can1
+
+#### 测试与静态检查
+
+ colcon test && colcon test-result --verbose
+
+项目已禁用 cpplint / uncrustify / copyright / xmllint,主要走 `ament_lint_auto` 剩余检查。
## 📚 话题详情
@@ -78,15 +113,15 @@ LinkerHand-CPP-ROS2 是灵心巧手科技有限公司开发,基于 LinkerHand-
| 话题名称 | I/O | 消息类型 | 描述 |
| :--- | :--- | :--- | :--- |
| /left_hand_control | Input | sensor_msgs/msg/JointState | 左手控制指令 |
-| /left_hand_settings | Input | sensor_msgs/msg/String | 左手设置指令 |
+| /left_hand_settings | Input | std_msgs/msg/String | 左手设置指令 |
| /left_hand_touch | Output | std_msgs/msg/Float32MultiArray | 左手触觉传感器数据 |
| /left_hand_state | Output | sensor_msgs/msg/JointState | 左手关节状态 |
| /left_hand_info | Output | std_msgs/msg/String | 左手基本信息 |
-| /right_hand_control | Input | sensor_msgs/msg/JointState | 左手控制指令 |
-| /right_hand_settings | Input | sensor_msgs/msg/String | 右手设置指令 |
-| /right_hand_touch | Output | std_msgs/msg/Float32MultiArray | 左手触觉传感器数据 |
-| /right_hand_state | Output | sensor_msgs/msg/JointState | 左手关节状态 |
-| /right_hand_info | Output | std_msgs/msg/String | 左手基本信息 |
+| /right_hand_control | Input | sensor_msgs/msg/JointState | 右手控制指令 |
+| /right_hand_settings | Input | std_msgs/msg/String | 右手设置指令 |
+| /right_hand_touch | Output | std_msgs/msg/Float32MultiArray | 右手触觉传感器数据 |
+| /right_hand_state | Output | sensor_msgs/msg/JointState | 右手关节状态 |
+| /right_hand_info | Output | std_msgs/msg/String | 右手基本信息 |
针对以上话题的具体字段及其详细描述如下表所示:
@@ -113,11 +148,15 @@ LinkerHand-CPP-ROS2 是灵心巧手科技有限公司开发,基于 LinkerHand-
```bash
L7: ["大拇指弯曲", "大拇指横摆","食指弯曲", "中指弯曲", "无名指弯曲","小拇指弯曲","拇指旋转"]
+L6/O6: ["拇指根部", "拇指侧摆", "食指根部", "中指根部", "无名指根部", "小指根部"]
+
L10: ["拇指根部", "拇指侧摆","食指根部", "中指根部", "无名指根部","小指根部","食指侧摆","无名指侧摆","小指侧摆","拇指旋转"]
L20: ["拇指根部", "食指根部", "中指根部", "无名指根部","小指根部","拇指侧摆","食指侧摆","中指侧摆","无名指侧摆","小指侧摆","拇指横摆","预留","预留","预留","预留","拇指尖部","食指末端","中指末端","无名指末端","小指末端"]
-L21: ["大拇指根部", "食指根部", "中指根部","无名指根部","小拇指根部","大拇指侧摆","食指侧摆","中指侧摆","无名指侧摆","小拇指侧摆","大拇指横滚","预留","预留","预留","预留","大拇指中部","预留","预留","预留","预留","大拇指指尖","食指指尖","中指指尖","无名指指尖","小拇指指尖"]
+G20: ["大拇指根部", "食指根部", "中指根部","无名指根部","小拇指根部","大拇指侧摆","食指侧摆","中指侧摆","无名指侧摆","小拇指侧摆","大拇指横滚","大拇指指尖","食指指尖","中指指尖","无名指指尖","小拇指指尖"]
+
+L21: ["大拇指根部", "食指根部", "中指根部","无名指根部","小拇指根部","大拇指侧摆","食指侧摆","中指侧摆","无名指侧摆","小拇指侧摆","大拇指横滚","预留","预留","预留","预留","大拇指中部","预留","预留","预留","预留","大拇指指尖"]
L25: ["大拇指根部", "食指根部", "中指根部","无名指根部","小拇指根部","大拇指侧摆","食指侧摆","中指侧摆","无名指侧摆","小拇指侧摆","大拇指横滚","预留","预留","预留","预留","大拇指中部","食指中部","中指中部","无名指中部","小拇指中部","大拇指指尖","食指指尖","中指指尖","无名指指尖","小拇指指尖"]
```
@@ -130,17 +169,7 @@ L25: ["大拇指根部", "食指根部", "中指根部","无名指根部","小
```bash
# 清除故障码
- $ ros2 topic pub /left_hand_setting std_msgs/msg/String "data: '{\"setting_cmd\": \"clear_faults\"}'"
-
- # 设置电流
- $ ros2 topic pub /left_hand_setting std_msgs/msg/String "data: '{\"setting_cmd\": \"set_electric_current\", \"params\": {\"electric_current\": 50}}'"
-
- # 使能
- $ ros2 topic pub /left_hand_setting std_msgs/msg/String "data: '{\"setting_cmd\": \"enable\"}'"
-
- # 失能
- $ ros2 topic pub /left_hand_setting std_msgs/msg/String "data: '{\"setting_cmd\": \"disable\"}'"
-
+ $ ros2 topic pub /left_hand_settings std_msgs/msg/String "data: '{\"setting_cmd\": \"clear_faults\"}'"
```
@@ -179,7 +208,11 @@ data: 'Hand direction: Left hand
```
- 压感数据 /left_hand_touch
- 注意:反馈数据为一个一维数组,长度为360,由每个手指的压感数据组成。单个指头压感数据长度是72(6*12矩阵),每个手指压感数据需要单独拆分。(仅适用点阵式传感器)
+ 注意:反馈数据为一个一维数组,长度按型号区分:
+ - 常规型号:长度 360,5 指 × 72(6×12 矩阵)/指;
+ - O6:长度 200,5 指 × 40(4×10 矩阵)/指。
+
+ 每个手指压感数据需要自行按指拆分。仅适用点阵式传感器。
```bash
$ ros2 topic echo /left_hand_touch
@@ -195,20 +228,34 @@ data:
- '...'
```
-## 💡 使用示例
+## 🎛️ 控制 GUI
+
+`hand_control_gui.py` 提供基于 tkinter 的可视化面板:拖动线性滑块直接下发 `JointState`,同时显示 `state` / `touch` / `info` 反馈(含触觉热力图)。它只依赖标准话题,可与任意 `run.xml` 场景配合。
-| 序号 | 文件名称 | 描述 |
-| :--- | :-------- | :--------------------------------------------- |
-| 1 | src/examples/src/action_group_show_l7 | L7型号手指舞示例 |
-| 2 | src/examples/src/action_group_show_l10 | L10型号手指舞示例 |
-| 3 | src/examples/src/action_group_show_l20 | L20型号手指舞示例 |
-| 4 | src/examples/src/loop_l20 | L20型号手势张开握拳示例 |
-| 5 | src/examples/src/show_ok_l20 | L20型号手势ok示例 |
-| 6 | src/examples/src/show_surround_index_finger_l20 | L20型号单指手势示例 |
-| 7 | src/examples/src/show_wave_l20 | L20型号wave手势示例 |
-| 8 | src/examples/src/action_group_show_l25 | L25型号手指舞示例 |
-| 9 | src/examples/src/loop_l25 | L25型号手势张开握拳示例 |
+
+
+
+```bash
+source install/setup.bash
+# 自动从 /linker_hand_{side}_node 读取 HAND_JOINTS 型号参数
+ros2 run linker_hand_cpp_ros2 hand_control_gui.py
+# 或显式指定型号
+ros2 run linker_hand_cpp_ros2 hand_control_gui.py --side right --model L10
+```
+
+功能界面:
+
+- **顶部**:型号 / 侧别 下拉框;「实时」开关(打开后按 `--rate` 周期 (默认60hz) 把当前滑块值发布出去)。
+- **中部左**:反馈面板 —— `位置` / `速度` / `力矩` 三行数值,下方是 5 指触觉热力图;型号切换会自动重建。
+- **中部右**:控制面板 —— 通过顶部 tab 在 `位置` / `速度` / `力矩` 之间切换;点击或拖动线条即可调整(0–255);右侧 Spinbox 支持精确输入。
+- **底部右下**:`复制位置值` 链接,把当前所有关节位置以 `"255, 255, 255, ..."` 的形式写入剪贴板。
+
+常用参数:`--side left|right`、`--model L6|O6|L7|L10|L20|L21|L25|G20|O20`、`--rate `、`--no-live`(禁用自动发布,仅调试用)。
+
+初始位置:`hand_control_gui.py` 中的 `POSITION_DEFAULTS` 按型号定制(默认全 255);`G20` 使用 `[255, 255, 255, 255, 255, 255, 130, 125, 125, 125, 255, 255, 255, 255, 255, 255]` 作为张开手掌的安全初值。
+
+依赖 `python3-tk` 与 `rclpy`。
## 📄 许可证
@@ -224,8 +271,12 @@ Copyright (c) 2026 灵心巧手(北京)科技有限公司
## 📝 更新日志
-详细的版本更新记录请参考 [CHANGELOG.md](CHANGELOG.md)(待创建)。
+详细的版本更新记录请查看 [`git log`](https://github.com/linker-bot/linkerhand-cpp-ros2/commits/main) 或本地执行:
+
+```bash
+git log --oneline --decorate
+```
---
-**注意**: 使用前请确保设备已正确连接并配置好通信接口。
\ No newline at end of file
+**注意**: 使用前请确保设备已正确连接并配置好通信接口。
diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt
deleted file mode 100644
index 57efa31..0000000
--- a/src/examples/CMakeLists.txt
+++ /dev/null
@@ -1,137 +0,0 @@
-cmake_minimum_required(VERSION 3.5)
-project(examples)
-
-# Default to C99
-if(NOT CMAKE_C_STANDARD)
- set(CMAKE_C_STANDARD 99)
-endif()
-
-# Default to C++14
-if(NOT CMAKE_CXX_STANDARD)
- set(CMAKE_CXX_STANDARD 14)
-endif()
-
-# Enable additional compiler warnings
-if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- add_compile_options(-Wall -Wextra -Wpedantic)
-endif()
-
-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 dependencies
-find_package(ament_cmake REQUIRED)
-find_package(rclcpp REQUIRED)
-find_package(std_msgs REQUIRED)
-find_package(sensor_msgs REQUIRED)
-
-# Define common include directories
-set(COMMON_INCLUDE_DIRS
- /usr/local/linker_hand_cpp_sdk/include
- /usr/local/linker_hand_cpp_sdk/third_party/Robotic_Arm/include
- include
-)
-
-#-----------------------------------------------------------------------------
-# 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(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
-)
-
-if(NOT LINKER_HAND_LIB)
- message(FATAL_ERROR "linkerhand_cpp_sdk library not found!")
-endif()
-
-if(NOT LINKER_HAND_INCLUDE_DIR)
- message(FATAL_ERROR "LinkerHand headers not found!")
-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}
-)
-
-# ----------------------------------------------------------------------
-
-# Define common link libraries
-set(COMMON_LIBS ${LINKER_HAND_LIB} pthread)
-
-# Define source files
-set(SOURCE_FILES
- action_group_show_l7
- action_group_show_l10
- action_group_show_l20
- action_group_show_l25
- loop_l20
- loop_l25
- show_surround_index_finger_l20
- show_ok_l20
- show_wave_l20
-)
-
-# Create and name a shared library
-foreach(SOURCE_FILE ${SOURCE_FILES})
- add_executable(${SOURCE_FILE} src/${SOURCE_FILE}.cpp)
- target_include_directories(${SOURCE_FILE} PUBLIC
- $
- $
- )
- ament_target_dependencies(${SOURCE_FILE}
- rclcpp
- std_msgs
- sensor_msgs
- )
- target_link_libraries(${SOURCE_FILE} ${COMMON_LIBS})
- install(TARGETS ${SOURCE_FILE}
- DESTINATION lib/${PROJECT_NAME}
- )
-endforeach()
-
-# Install launch files
-# install(DIRECTORY launch
-# DESTINATION share/${PROJECT_NAME}/
-# )
-
-# Install configuration files
-# install(DIRECTORY config
-# DESTINATION share/${PROJECT_NAME}/
-# )
-
-# Install settings file
-# install(FILES config/setting.yaml
-# DESTINATION config
-# )
-
-# If BUILD_TESTING is enabled, include test-related dependencies
-if(BUILD_TESTING)
- find_package(ament_lint_auto REQUIRED)
- ament_lint_auto_find_test_dependencies()
-endif()
-
-# Package information
-ament_package()
diff --git a/src/examples/package.xml b/src/examples/package.xml
deleted file mode 100644
index 6ff7971..0000000
--- a/src/examples/package.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
- examples
- 0.0.0
- TODO: Package description
- lst
- Apache2.0
-
- ament_cmake
-
- ament_lint_auto
- ament_lint_common
-
-
- ament_cmake
- rclcpp
- std_msgs
- sensor_msgs
-
-
diff --git a/src/examples/src/action_group_show_l10.cpp b/src/examples/src/action_group_show_l10.cpp
deleted file mode 100644
index 3b53fee..0000000
--- a/src/examples/src/action_group_show_l10.cpp
+++ /dev/null
@@ -1,454 +0,0 @@
-// 本demo为适配球形拇指根部关节版本L10灵巧手,默认支持右手,如需左手,请将 HAND_TYPE::RIGHT 改为 HAND_TYPE::LEFT
-
-#include
-#include
-#include
-#include