Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,12 @@ cmake --build . -j
### 主要 API 接口

**控制接口**
- `fingerMove()` — 设置关节位置
- `setPosition()` — 设置关节位置
- `setSpeed()` — 设置运动速度
- `setTorque()` — 设置扭矩限制

**状态查询**
- `getState()` — 获取关节状态
- `getPosition()` — 获取关节状态
- `getSpeed()` — 获取当前速度
- `getTorque()` — 获取当前扭矩

Expand Down Expand Up @@ -418,3 +418,4 @@ Copyright (c) 2026 灵心巧手(北京)科技有限公司
---

**注意**:使用前请确保设备已正确连接并配置好通信接口。

4 changes: 2 additions & 2 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ if [ "$INSTALL" = true ]; then
purge_install_artifacts "$SUDO"

# 通过 CMake 的 install 规则安装。对外公共头白名单、库文件、third_party 运行时
# 依赖、cmake config target 等都由 linkerhand/CMakeLists.txt 统一控制,
# 依赖、cmake config target 等都由 CMakeLists.txt 统一控制,
# 不要在这里再手动 cp 头文件——会绕过白名单把全部内部头释放出去。
print_info "执行 cmake --install (受白名单约束)..."
$SUDO cmake --install . --prefix "$INSTALL_PREFIX"
Expand Down Expand Up @@ -288,7 +288,7 @@ if [ "$INSTALL" = true ]; then
echo "使用示例(推荐 find_package):"
echo " find_package(linkerhand-cpp-sdk CONFIG REQUIRED)"
echo " target_link_libraries(<tgt> PRIVATE LinkerHand::linkerhand_cpp_sdk)"
echo " 参考工程: linkerhand/examples/standalone/"
echo " 参考工程: examples/standalone/"
echo ""
INC="$INSTALL_PREFIX/include/linkerhand-cpp-sdk"
echo "或手动指定(头按子目录发布):"
Expand Down
13 changes: 7 additions & 6 deletions docs/API-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ LinkerHandApi 类的构造函数,用于初始化 Linker 机械手 API。

### 设置关节位置
```cpp
void fingerMove(const std::vector<uint8_t> &pose);
void setPosition(const std::vector<uint8_t> &pose);
```
**Description**:
设置关节的目标位置,用于控制手指的运动。
Expand All @@ -66,7 +66,7 @@ void fingerMove(const std::vector<uint8_t> &pose);

### 设置关节位置
```cpp
void fingerMoveArc(const std::vector<double> &pose);
void setPositionArc(const std::vector<double> &pose);
```
**Description**:
设置关节的目标位置,用于控制手指的运动。
Expand Down Expand Up @@ -127,7 +127,7 @@ std::vector<uint8_t> getSpeed();

### 获取当前关节状态
```cpp
std::vector<uint8_t> getState();
std::vector<uint8_t> getPosition();
```
**Description**:
获取当前关节的状态信息。
Expand All @@ -138,7 +138,7 @@ std::vector<uint8_t> getState();

### 获取当前关节状态
```cpp
std::vector<double> getStateArc();
std::vector<double> getPositionArc();
```
**Description**:
获取当前关节的状态信息。
Expand Down Expand Up @@ -269,13 +269,13 @@ int main() {

std::cout << "执行动作:握拳" << std::endl;
std::vector<uint8_t> fist_pose = {120, 60, 0, 0, 0, 0, 255, 255, 255, 51};
hand.fingerMove(fist_pose);
hand.setPosition(fist_pose);
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "-------------------------------------------" << std::endl;

std::cout << "执行动作:张开" << std::endl;
std::vector<uint8_t> open_pose = {255, 104, 255, 255, 255, 255, 255, 255, 255, 71};
hand.fingerMove(open_pose);
hand.setPosition(open_pose);
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "-------------------------------------------" << std::endl;

Expand All @@ -297,3 +297,4 @@ int main() {
- 如果有任何问题或需要进一步支持,请联系 [https://linkerbot.cn/aboutUs](https://linkerbot.cn/aboutUs)。

---

81 changes: 5 additions & 76 deletions docs/FAQ.md
Original file line number Diff line number Diff line change
@@ -1,83 +1,16 @@
# 常见问题解答

本文档面向 `pack.sh` 生成的 `linkerhand-cpp-sdk/` 发布包,以及从 `linkerhand/` 源码构建安装 SDK 的开发者。

## 安装与发布包

### Q1: 发布包和源码仓库是什么关系?

`linkerhand/` 是唯一主开发工作区,`./pack.sh pack` 会基于它生成可直接发布的 `linkerhand-cpp-sdk/`。发布包内包含预编译库、示例、示教器、文档和必要的第三方依赖。

### Q2: 发布包解压后怎么快速验证?

Linux/macOS:

```bash
cd linkerhand-cpp-sdk
mkdir build && cd build
cmake ..
cmake --build . -j$(nproc)
./bin/test_l10_can_0
```

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
```

### Q3: 发布包里的头文件为什么比最小 API 入口多?

发布包不仅面向统一 API,也要支持 `examples/`、`hand_teach_pendant/` 和部分需要直连通信层的客户工程,所以会一起发布 `include/communication/` 下的通信相关头。新项目优先从 `LinkerHandApi.h` 开始接入。

### Q4: 安装后 `find_package` 应该怎么接?

从源码执行 `cmake --install` 或 `./build.sh -i` 后,可直接在下游工程里写:

```cmake
find_package(linkerhand-cpp-sdk CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE LinkerHand::linkerhand_cpp_sdk)
```

这条路径适合系统安装后的二次开发;如果只是消费发布包,直接用发布包根目录的 `CMakeLists.txt` 构建 examples 或参考 `README.md` 手动链接即可。

## 构建与运行

### Q5: 发布包里的 `build.sh` / `build.bat` 能做什么?

它们主要服务于持有源码工程的开发者,用于重建、安装或卸载 SDK。客户从发布包消费预编译库时,通常不需要执行 `-b` / `-i`,直接用 `cmake ..` 构建 examples 即可。

### Q6: `--skip-tests` 为什么没有关闭 examples?

当前 `build.sh` 透传的是 `-DBUILD_TESTS=OFF`,这是 examples 子目录内部开关,不影响顶层 `BUILD_EXAMPLES` / `BUILD_PENDANT`。如果只想构建 SDK,请直接使用:

```bash
cmake -S linkerhand -B linkerhand/build -DBUILD_EXAMPLES=OFF -DBUILD_PENDANT=OFF
cmake --build linkerhand/build -j
```

### Q7: 哪些平台是当前主要验证目标?

- Linux `x86_64`
- Linux `aarch64`
- Windows `x64`(MinGW / MSVC 导入库)

其中 O20 的 CAN-FD 示例目前主要面向 Linux `x86_64`。
本文档面向 `linkerhand-cpp-sdk/` 发布包,以及从 repository root 源码构建安装 SDK 的开发者。

## 通信与接口

### Q8: CAN、Modbus、EtherCAT 怎么选?
### Q1: CAN、Modbus、EtherCAT 怎么选?

- 统一 API 层通过 `COMM_TYPE::CAN`、`COMM_TYPE::MODBUS`、`COMM_TYPE::ETHERCAT` 选择通信方式。
- 不同手型支持范围不同,具体以 `README.md` 型号表和现有 examples 为准。
- 需要自己管理底层总线时,优先参考 `examples/test_*` 和 `hand_teach_pendant/src/HandController.cpp` 的实际用法。

### Q9: Linux 下 CAN 默认怎么配?
### Q2: Linux 下 CAN 默认怎么配?

```bash
sudo modprobe can
Expand All @@ -89,18 +22,14 @@ ip link show can0

如果示例使用了 `can1` 或其他设备名,请按现场总线名替换。

### Q10: Windows 下还需要额外 DLL 吗?
### Q3: Windows 下还需要额外 DLL 吗?

需要。发布包已经带上 `third_party/PCAN_Basic/` 和对应导入库;客户工程除了 SDK 自身 DLL 外,还要确保 `PCANBasic.dll` 与可执行文件同目录,或能被系统搜索路径找到。

## 文档与支持

### Q11: 先看哪个文档最合适?
### Q4: 先看哪个文档最合适?

- 想了解总体接入方式:看 `README.md`
- 想确认接口签名:看 `docs/API-Reference.md`
- 遇到构建或运行问题:看 `docs/TROUBLESHOOTING.md`

### Q12: 旧版参考目录还能直接当文档源吗?

不能。旧版目录只适合做历史对照,内容可能与当前命名空间、打包布局、构建开关不一致。对外发布请以 `linkerhand/` 和 `pack.sh` 产物为准。
10 changes: 5 additions & 5 deletions docs/TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ pkg-config --modversion libusb-1.0
如果构建网页示教器,还要确认 `Boost::system` 可用。只想先验证 SDK 本体时,可显式关闭示例和示教器:

```bash
cmake -S linkerhand -B linkerhand/build -DBUILD_EXAMPLES=OFF -DBUILD_PENDANT=OFF
cmake --build linkerhand/build -j
cmake -S . -B build -DBUILD_EXAMPLES=OFF -DBUILD_PENDANT=OFF
cmake --build build -j
```

### 2. 找不到 `LinkerHandApi.h` 或 `CommFactory.h`(旧名 `CanBusFactory.h`)
Expand Down Expand Up @@ -96,7 +96,7 @@ O20 的 CAN-FD 主要面向 Linux `x86_64`。在 ARM + Ubuntu 18 及以下环境
`USE_ETHERCAT` 默认关闭。只有在现场确实需要时再打开:

```bash
cmake -S linkerhand -B linkerhand/build -DUSE_ETHERCAT=ON
cmake -S . -B build -DUSE_ETHERCAT=ON
```

打开后仍失败,先检查系统是否已安装 `libethercat` 和对应 `pkg-config` 信息,而不是直接修改源码。
Expand All @@ -123,10 +123,10 @@ cmake -S linkerhand -B linkerhand/build -DUSE_ETHERCAT=ON

### 11. 为什么不再从旧版参考目录复制文档?

旧版目录长期手工维护,很多内容与当前仓库状态不再一致。现在的发布文档都应从 `linkerhand/docs/` 输出,由 `pack.sh` 直接复制,避免一边改代码、一边忘记同步旧目录。
旧版目录长期手工维护,很多内容与当前仓库状态不再一致。现在的发布文档都应从 `docs/` 输出,由 `pack.sh` 直接复制,避免一边改代码、一边忘记同步旧目录。

## 排查原则

- 连续编译或运行失败两次以上,先回看日志和环境,不继续盲试。
- 先检查平台、依赖、设备名、库路径,再怀疑源码逻辑。
- 对外发布只以 `linkerhand/` 当前内容和 `pack.sh` 生成物为准。
- 对外发布只以 repository root 当前内容和 `pack.sh` 生成物为准。
15 changes: 14 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ else()
link_directories(${LIBCANBUS_DIR})

# 设置运行时库路径,确保运行时能找到 libcanbus.so 与 SDK .so
set(CMAKE_INSTALL_RPATH "${LIBCANBUS_DIR}")
# $ORIGIN: 让 exe 在自身所在目录(bin/)查找,从而拿到 copy_dependencies 复制过来的 SDK .so
set(CMAKE_INSTALL_RPATH "\$ORIGIN" "${LIBCANBUS_DIR}")
if(LINKERHAND_LIB_DIR)
list(APPEND CMAKE_INSTALL_RPATH "${LINKERHAND_LIB_DIR}")
endif()
Expand Down Expand Up @@ -153,6 +154,18 @@ function(copy_dependencies target)
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
COMMENT "Copying linkerhand_cpp_sdk runtime to output directory"
)
# Unix: 复制只拿到 .so.<VERSION>,exe NEEDED 的是 .so.<SOVERSION>(由 SONAME 决定),
# 必须在 bin/ 里同步建出 SONAME 软链,否则 ld.so 找不到。
if(UNIX AND NOT APPLE)
add_custom_command(TARGET ${target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E remove -f
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<TARGET_SONAME_FILE_NAME:linkerhand_cpp_sdk>"
COMMAND ${CMAKE_COMMAND} -E create_symlink
"$<TARGET_FILE_NAME:linkerhand_cpp_sdk>"
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<TARGET_SONAME_FILE_NAME:linkerhand_cpp_sdk>"
COMMENT "Creating SONAME symlink for linkerhand_cpp_sdk in output directory"
)
endif()
elseif(LINKERHAND_DLL AND EXISTS "${LINKERHAND_DLL}")
add_custom_command(TARGET ${target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
Expand Down
2 changes: 1 addition & 1 deletion examples/L10/action_group_show.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ int main() {

while (running) {
std::vector<uint8_t> action = showLeft();
hand.fingerMove(action);
hand.setPosition(action);
std::this_thread::sleep_for(std::chrono::milliseconds(33));
}

Expand Down
Loading
Loading