Skip to main content

概述

本篇实践介绍如何订阅 Wuji Hand 2 的 joint_states 实时状态流,并在回调中读取在线关节的位置(position)、速度(velocity)和力矩代理值(effort)。应用场景包括实时监控关节状态、记录和分析运动数据,以及为上层控制器提供位置、速度和力矩反馈。 对应的 Python 示例为 0.subscribe_callback.py,C 示例为 0_subscribe_joint_states.c。字段定义见 joint_states 字段定义。

前置条件

硬件

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

软件

前序步骤

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

数据流

每帧是一个自描述的变长聚合体: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、指尖触觉等。订阅方式相同,换成对应的资源方法即可。指尖触觉的解码方式见 Wuji Hand 2 指尖触觉。

降低输出率

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

避免在回调中执行阻塞操作

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

相关内容