跳转到主要内容

概述

订阅 Wuji Hand 2 的 joint_states 广播流,拿到每个在线关节的位置、速度与力矩代理值。回调在 SDK 的后台工作线程上触发,主线程不阻塞。 这是读取灵巧手实时状态的最短路径。做状态监控、数据记录、或给上层控制器喂反馈,都从这里开始。 对应的 Python 示例为 0.subscribe_callback.py,C 示例为 0_subscribe_joint_states.c。 关节状态与各字段定义见 SDK 接口,本页只讲怎么跑起来与实测结果。

前置条件

硬件

本示例只读取,不使能电机,手指不会动。

软件

前序步骤

无。设备上电、网络连通即可。

数据流

每帧是一个自描述的变长聚合体:header 带 seq、timestamp_us 与 frame_id,joints 只包含固件本周期上报的关节。

帧结构实测

在 20 关节全在线的设备上,单帧实测如下: nid 不连续,而且与数组索引是两套编号。 实测 20 个在线关节的 nid 依次是 1 2 3 4、6 7 8 9、11 12 13 14、16 17 18 19、21 22 23 24,跳过 5、10、15、20。每根手指占用 5 个 nid 号段但只用前 4 个。 两者的换算关系实测吻合全部 20 个关节:
索引 0 是 thumb_S1(nid 1),索引 4 是 index_S1(nid 6),索引 19 是 pinky_S4(nid 24)。拿 nid 直接当数组下标会整体错位,关节标签与完整对照见设备信息。

运行时分支

C 侧回调在专用工作线程上触发,frame 指针只在回调期间有效,其堆上的 joints 数组在回调返回后立即释放,不能留存指针。

调用顺序

关订阅必须早于断设备。反过来做,工作线程可能仍在访问已释放的设备。

运行与输出

Python 侧每帧一行,默认只打印拇指的 4 个关节:
C 侧把整帧铺开成表,并把打印限流到约 1 Hz,避免刷屏:
以上为实机运行结果,设备是 20 关节全在线的右手 Wuji Hand 2。静置不动时 position 稳定,velocity 在零附近抖动。 输出率约 1 kHz。 实测 5 秒收到 5555 帧,按设备端 seq 差计算为每秒约 1000 帧。回调里做打印之外的重活会导致积压。

调整与适配

多设备环境必须指定设备

这是本示例最容易踩的坑,两侧行为还不一样: Python 侧的示例没有 --sn 参数(Glove 的同类示例有)。共用网络里跑之前,把连接那段改成指定 SN:
实测过一次反例:网络上有三台 Hand 2,其中一台被别的客户端占用,示例连到它时抛 Session already exists,此前已连的设备订阅随之终止,整轮只收到 1 帧数据。

订阅更多数据流

joint_states 之外,设备还提供 joint_diagnostics 与 imu。订阅方式相同,换成对应的资源方法即可。

降低输出率

约 1 kHz 对多数应用偏高。用订阅句柄的 set_rate() 降频,见输出率调节。

回调里不要做重活

回调在 SDK 工作线程上按帧触发。写文件、跑算法、加锁等待都会挤占这条线程,导致积压。正确做法是回调里只做最小拷贝,把数据丢进队列,另起线程消费。

相关内容