SDK 怎么用
Linux 有两套 1.2.1 压缩包(Ubuntu 22.04 及以上),按机器选:
| 机器 | 文件 | 大小 |
|---|---|---|
| PC / x86 工控机 | Humanhand_G7_sdk_1.2.1_linux_x86_64.tar.gz | 4.09 MB |
| ARM64 板 | Humanhand_G7_sdk_1.2.1_linux_aarch64.tar.gz | 3.46 MB |
Windows 有一套 1.2.1 压缩包,按机器选:
| 机器 | 文件 | 大小 |
|---|---|---|
| Windows x86_64 SDK | Humanhand_G7_sdk_1.2.1_windows_x86_64.zip | 86.45 MB |
- 先不写代码,用包里的
run.sh看手能不能动、做一次标定。 - 确认没问题后,再把库接到你自己的程序里,循环读取 21 个关节位置(接了小臂模块可以再要 22 个点)。
Windows 上请用 HumanHand 上位机 发关节,接收格式见 UDP接收-关节位姿。本页只讲这个 Linux 压缩包。
先选你现在要做的事
| 你现在的情况 | 往下看 |
|---|---|
| 刚解压,不知道这些文件是干什么的 | 包里每个文件 |
| 想先看手套好不好用,还不写程序 | 第一次:用 run.sh |
| 菜单里已经在「发送关节」,想在电脑上看到手 | 看手的画面 |
| 要把手套编进自己的软件 | 接到自己的程序 |
| 想知道读出来的数是什么意思 | 读到的数据 |
下载
从上表或软件包下载 Humanhand G7 SDK 1.2.1。以下以 x86_64 版为例;ARM64 板请选择对应的 aarch64 压缩包。
tar -xzf Humanhand_G7_sdk_1.2.1_linux_x86_64.tar.gz
cd Humanhand_G7_sdk_1.2.1_linux_x86_64后面的路径都相对这个目录。
包里每个文件
解压后大致是这样。第一次用只需要 demo/examples/run.sh。 其它文件先不用打开。
Humanhand_G7_sdk_1.2.1_linux_x86_64/
├── README.md 包内说明书(和本页同一条路)
├── CHANGELOG.md SDK 各版本更新说明
├── LICENSE NOTICE 许可,发布产品时保留
├── include/hand_sdk.h 写自己程序时 #include 这一个头
├── lib/linux/x86_64/
│ ├── libhand_runtime.so 真正干活的库(链接它)
│ ├── libtensorflowlite_c.so.2.17.1 库的依赖,必须和上一行放在同一目录
│ └── param/ 手套出厂参数缓存,程序自己写入,不用改
└── demo/
├── examples/
│ ├── run.sh 开箱脚本:第一次就跑这个
│ ├── hand_mocap 已经编好的演示程序(run.sh 会启动它)
│ ├── udp_receiver.py 终端打印 UDP 数字,不存盘
│ ├── udp_receiver.md 上面脚本的包格式
│ ├── recv_hand_udp.py 收关节 UDP,画点线图
│ ├── hand_example.cpp 示例源码,接到自己工程时抄它
│ └── compile.sh 编译上面那份示例
└── docs/
├── Integration.md 怎么链进自己的工程
├── API.md 每个函数做什么
└── DataFormat.md 21 / 22 个点怎么排、单位| 文件 | 你怎么用 |
|---|---|
run.sh | 开箱入口。 设好运行环境,并启动 hand_mocap。不要先去点 hand_mocap。 |
hand_mocap | 预编译好的演示:选串口、标定、发关节。由 run.sh 拉起。 |
recv_hand_udp.py | 演示开始发关节之后,另开一个终端跑它,才能看见手。需要本机已装 python3 和 python3-tk。 |
hand_example.cpp + compile.sh | 要自己编译一份和演示相同流程的程序时用。 |
hand_sdk.h + libhand_runtime.so | 接到你自己软件时,只要这两个(外加与运行库同目录的 libtensorflowlite_c.so*)。 |
param/ | 第一次连这只手套时,程序会从硬件把参数存到这里。不要手工改。 |
demo/docs/ | 写代码时再打开;先跑 run.sh 不必看。 |
第一次用之前
手套走 USB 串口。当前用户要能读写串口,做一次后重新登录:
sudo usermod -aG dialout $USER插上手套,看系统给了哪个口:
ls /dev/ttyACM* /dev/ttyUSB*记下名字(常见 /dev/ttyACM0)。口被上位机或其它程序占用时,这里会打不开。
第一次:用 run.sh
run.sh 做三件事:设好库需要的环境、找到旁边的 hand_mocap、把它启动起来。你只要进到 demo/examples 再执行它。
cd demo/examples
chmod +x run.sh
./run.sh它会问:单手还是双手、波特率(直接回车即可,默认 921600)、串口。然后出现菜单:
======== 手部动捕 ========
1) 标定手型
2) 手套数据读取
3) 发送关节位姿(相对手腕)
4) 发送关节位姿(相对小臂)
5) 发送传感器原始数据(线圈位姿 + 线圈IMU + 磁源IMU)
6) 对指优化-开启
7) 抗磁干扰-弱
8) 退出
b) 上一步新手套或新佩戴者建议先选择 1) 标定手型。标定文件生成在当前目录:右手 hand_profile_right.bin,左手 hand_profile_left.bin。
菜单 2 读取手套信息,不发送关节位姿;菜单 5 发送线圈位姿和惯性数据,不用于关节画面。菜单 6 切换对指优化(默认开启):拇指尖靠近某指尖时,求解会把这两点再收近一点;标定结束后开关状态保持不变,不要每帧反复开关。菜单 7 在弱、强、关之间切换抗磁干扰(默认弱),菜单 8 退出,b 返回上一步。
已经知道串口时,可以跳过提问:
./run.sh --port /dev/ttyACM0
./run.sh --port /dev/ttyACM0 --port2 /dev/ttyACM1双手必须在同一个 run.sh 进程里打开两只手套,不要开两个窗口各跑一次。
标定怎么做(菜单 1)
共 8 段。每段先倒计时 3 秒,再自动采集,不是按回车才开始采;采完按回车进下一段,输入 r 重录本段,输入 b 回到上一步。八段都完会自动计算。
| 序号 | 手势 | 时长 | 怎么摆 |
|---|---|---|---|
| 1 | 平放静止 | 2 s | 手掌贴紧水平桌面,四指伸直并尽量并拢,保持平稳,拇指自然放松 |
| 2 | 握拳静止 | 2 s | 保持握拳并静止 |
| 3 | 重复握拳 | 5 s | 持续握拳与张开交替,四指尽量并拢,拇指自然放松 |
| 4 | 拇指伸展 | 5 s | 反复屈伸大拇指 |
| 5 | 食指对指 | 2 s | 拇指与食指指尖相对,不要压紧指腹 |
| 6 | 中指对指 | 2 s | 拇指与中指指尖相对,不要压紧指腹 |
| 7 | 无名指对指 | 2 s | 拇指与无名指指尖相对,不要压紧指腹 |
| 8 | 小拇指对指 | 2 s | 拇指与小指指尖相对,不要压紧指腹 |
发出关节(菜单 3 / 4)
标定完成后选 3)。程序按求解节拍往本机 127.0.0.1:15001 发关节 UDP(双手也是这个端口,左右各一包)。
4) 要手套接了小臂模块。没接小臂时用 3)。
字节格式见 UDP接收-关节位姿。自己的程序也可以不经过 UDP,直接读 SDK 数组,见下一节。
看手的画面
菜单已经在发送关节之后,另开一个终端(仍在 demo/examples):
python3 recv_hand_udp.py和演示一样提问:1 单手一个窗口,2 双手两个窗口,回车默认双手。再选监听地址和端口,回车=0.0.0.0:15001(双手共用)。刷新选 1–6 对应 20/40/60/80/100/120 Hz,回车默认 120。左键拖转动,右键平移,滚轮缩放。

没有画面时:确认演示还在菜单 3 或 4 发送关节、本机装了 python3-tk(Ubuntu:sudo apt install python3-tk)、没改默认端口。
接到自己的程序
确认 run.sh 已经能标定、能看见手,再改你的工程。
你要带上的只有:
include/hand_sdk.hlib/linux/x86_64/libhand_runtime.so- 同目录的
libtensorflowlite_c.so.2.17.1
可抄的完整流程:demo/examples/hand_example.cpp。在 demo/examples 里执行 ./compile.sh 就能编出一份和演示相同菜单的程序。
关节计算在 libhand_runtime.so 内完成,并使用 1 个线程。演示程序直接运行 ./run.sh;自己写程序时包含 include/hand_sdk.h、链接 libhand_runtime.so,./compile.sh 已按此配置。不需要设置 OMP_NUM_THREADS 或 OPENBLAS_NUM_THREADS。libtensorflowlite_c.so.2.17.1 必须与 libhand_runtime.so 放在同一目录。
一只手套 = 一次 hh_sdk_create。取数只用一个线程调用 hh_sdk_poll。两只手套在同一个程序里 create 两次,同一个循环里轮流 poll。
#include "hand_sdk.h"
HhSdkConfig cfg = {
.serial_port = "/dev/ttyACM0",
.baud = 0, /* 0 = 921600 */
.hand = HH_SDK_HAND_RIGHT, /* 1 左 / 2 右,和 UDP 包头 hand 相同 */
.profile_path = "hand_profile_right.bin",
.cache_dir = NULL, /* NULL = 用库旁边的 param/ */
};
HhSdkHandle* h = hh_sdk_create(&cfg); /* 失败为 NULL */
HhSdkFrame frame;
int rc = hh_sdk_poll(h, &frame); /* 调用成功为 HH_SDK_OK;好不好用看 frame.status */
hh_sdk_destroy(h);hand 也可以填 HH_SDK_HAND_AUTO(0),让库读手套上的左右标记。
frame.status:
| status | 含义 |
|---|---|
HH_SDK_STATUS_OK | 这一拍有新姿态,可以用 |
HH_SDK_STATUS_NO_UPDATE | 手套还没送来新的一帧,稍后再 poll |
HH_SDK_STATUS_NO_SIGNAL | 手套在线,手指没跟上 |
HH_SDK_STATUS_UNSTABLE | 这一拍没有得到可用的解。正常动作不应出现。字段里仍有数字,请沿用上一拍可用的结果 |
抗磁干扰与磁场可信度
抗磁干扰用 hh_sdk_set_mag_guard(h, mode) 设置。mode 只能是 2、1 或 0。请与 hh_sdk_poll 放在同一线程,不要每一帧都修改。
打开后,附近磁场受到干扰时,受影响手指的输出会保持平稳。关闭后,输出继续按传感器数据更新。三种设置下都可以读取磁场可信度。
1(默认,菜单“弱”):按通常灵敏度启用。2(“强”):更早启用;启用之后的效果与“弱”相同。0(“关”):关闭;输出继续按传感器数据更新,可信度仍按上一次的“弱”或“强”计算。
当前设置用 hh_sdk_get_mag_guard 读回。头文件中的 HH_SDK_MAG_GUARD_STRONG、HH_SDK_MAG_GUARD_WEAK、HH_SDK_MAG_GUARD_OFF 分别对应 2、1、0。
磁场可信度每路为 0 到 1,越接近 1 越正常。它不在 UDP 包里,包长也不变。hh_sdk_poll 或 hh_sdk_poll_coils 读到新数据后,调用 hh_sdk_coil_confidence;还没有新数据时返回 HH_SDK_ERR_NOT_READY。下标 0 到 4 是拇指到小指,5 是小臂。演示在发送关节时大约每 2 秒打印一行,其中包含五根手指的可信度。
磁定位算法版本用 hh_sdk_magpose_version() 读取(当前 1.1.4),SDK 版本用 hh_sdk_version() 读取(1.2.1);这两个函数不需要打开手套。
接了小臂模块、要相对小臂的 22 点:同一次 poll 成功后再调 hh_sdk_forearm_root。
在自己程序里做标定时,采集那段时间必须继续 hh_sdk_poll,这段才会有数据。步骤见包内 demo/docs/API.md。
从 SDK 根目录编译示例:
g++ -O2 -std=c++17 -Iinclude demo/examples/hand_example.cpp \
-Llib/linux/x86_64 -lhand_runtime -ldl -o hand_example
export LD_LIBRARY_PATH="lib/linux/x86_64"
./hand_example函数表:demo/docs/API.md。链接细节:demo/docs/Integration.md。点的排列:demo/docs/DataFormat.md。
读到的数据
位置单位是米。朝向是四个数,顺序 w, x, y, z。都相对手掌(菜单 3 的输出;SDK 可用 hh_sdk_poll 读取)。左右手编号:1 左、2 右(和 UDP 包头相同)。
前后、左右、上下以手的解剖方向为准:

| 手 | +X | +Y | +Z |
|---|---|---|---|
| 左手 | 右 | 前(沿手指) | 上 |
| 右手 | 左 | 后 | 上 |
21 个点(相对手掌):0 掌根;每指四个点(掌指、近节、远节、指尖),顺序拇指 → 食指 → 中指 → 无名指 → 小指。
22 个点(相对小臂,需小臂模块):0 小臂(位置为 0),1 手腕(即上面的掌根),2–21 对应上面的 1–20。
网上收这些点的包格式:UDP接收-关节位姿。轴的图解也可以看坐标系定义。
run.sh 参数(可选)
一般跟着提问走即可。需要写进脚本时:
| 参数 | 默认 | 含义 |
|---|---|---|
--port | (提问) | 手套串口 |
--port2 | (无) | 第二只手套串口 |
--hand | right | left 或 right |
--baud | 921600 | 0 也表示 921600 |
--profile | hand_profile_{hand}.bin | 标定写入、跟踪读取的手型档案 |
--cache-dir | 库旁 param/ | 出厂参数缓存目录 |
这些参数同样适用于直接启动 hand_mocap(日常仍建议用 run.sh,以免漏设环境变量)。
常见问题
| 现象 | 处理 |
|---|---|
| 打不开手套 | 口是否存在;是否已加入 dialout 并重新登录;串口是否被其它程序占用 |
version query timeout | 串口选错,换同一个设备上的另一个 /dev/ttyACM* |
| 第一次连上提示参数下载失败 | 手套已上电,串口空闲,再试一次 |
| 手指几乎不动 / 位置不准 | 指套戴好;用菜单做完 8 段标定 |
recv_hand_udp.py 没有画面 | 演示是否已在菜单 3 或 4;是否装了 python3-tk |
| 自己的程序一跑 CPU 打满 | 关节计算已在库内使用 1 个线程;两只手套请在同一个线程里轮流调用 hh_sdk_poll,不要每只手各开一个计算线程 |
libtensorflowlite_c.so 找不到 | 必须和 libhand_runtime.so 放在同一目录 |
hh_sdk_create 返回空 | 串口、左右手、profile_path 非空 |
