SDK 数据参考

触觉数据

# 触觉矩阵
sub = glove.tactile().subscribe()
frame = await sub.recv_async()
print(f"最大压力值: {max(frame.data):.2f}")

# 分区数据
sub = glove.tactile_zones().subscribe()
zones = await sub.recv_async()
print(f"手掌: {zones.palm}, 拇指: {zones.thumb}")

TactileFrame

校准后的触觉矩阵数据。帧率:120 FPS

字段类型说明
headerFrameHeader帧头
dataList[float]768 个值,其中 526 个为有效触点(压力值 0.0~1.0),其余为无效触点,固定为 -1.0

data 为 768 个值的数组,按 24×32 row-major 排列。访问第 row 行第 col 列:data[row * 32 + col]。无效位置固定为 -1.0,可据此与有效触点的零压力 0.0 区分。

{
  "header": {
    "seq": 42,
    "timestamp_us": 1709876543210,
    "frame_id": ""
  },
  "data": [-1.0, 0.12, 0.45, 0.78, -1.0, 0.33, ...] // 共 768 个值,526 个有效,无效点为 -1.0
}

TactileZones

按手指区域聚合的触觉数据。

字段类型最大点数说明
headerFrameHeader帧头
palmList[float]290手掌区域
thumbList[float]52拇指区域
indexList[float]52食指区域
middleList[float]58中指区域
ringList[float]52无名指区域
pinkyList[float]45小指区域
{
  "header": {
    "seq": 42,
    "timestamp_us": 1709876543210,
    "frame_id": ""
  },
  "palm": [0.0, 0.12, 0.45, ...],  // 最多 290 个值
  // 以下各指点数见上表
  "thumb": [0.0, 0.85, 0.92, ...],
  "index": [0.0, 0.67, 0.23, ...],
  "middle": [0.0, 0.34, ...],
  "ring": [0.0, 0.11, ...],
  "pinky": [0.0, 0.05, ...]
}

PointField

点云字段描述。

字段类型说明
namestr字段名称
offsetint字节偏移
typeint数据的数值类型编码,固定为 7(float32)

PointCloud

触觉点云数据。

glove.tactile_point_cloud() 的空间位置依赖 EMF 链路解算的手部姿态,输出率随 EMF 链路的 降频因数 同步变化。

字段类型说明
headerFrameHeader帧头
frame_idstr坐标系
point_strideint每点字节数
fieldsList[PointField]字段描述列表
dataList[int]原始二进制数据
方法返回说明
point_count()int获取点数量
{
  "header": {
    "seq": 42,
    "timestamp_us": 1709876543210,
    "frame_id": "l_wrist"
  },
  "frame_id": "l_wrist",
  "point_stride": 12,
  "fields": [
    {
      "name": "x",
      "offset": 0,
      "type": 7
    },
    {
      "name": "y",
      "offset": 4,
      "type": 7
    },
    {
      "name": "z",
      "offset": 8,
      "type": 7
    }
  ],
  "data": [0, 0, 128, 63, ...] // 原始二进制,每点 12 字节
}

TactileBinary

二值接触检测结果,基于触觉数据推断,帧率:120 FPS,与 glove.tactile() 同频发布。

字段类型说明
headerFrameHeader帧头
dataList[float]768 个接触状态值:1.0 接触,0.0 未接触,-1.0 无效触点

data 按 24×32 row-major 排列,与 TactileFrame 同形、同掩码(526 个有效触点)。访问第 row 行第 col 列:data[row * 32 + col]。现有触觉网格可视化无需改动即可复用。

接触判定依赖一个训练好的接触模型,模型在 Wuji Studio 中训练并按设备自动加载。未加载模型时,数据流仍以 120 FPS 发布,但所有有效触点恒为 0.0(无接触),无效触点为 -1.0,不会出现 1.0

直接通过 SDK 使用(不经 Wuji Studio)时,先把训练好的模型目录配置给 tactile_binary 再订阅。目录需包含 contact.safetensorscontact.npz 两个文件。模型目录变更或重新训练后,SDK 会自动热重载。

# 配置训练好的接触模型目录(经 Wuji Studio 使用时由 Studio 自动配置)
glove.set("algorithms.tactile_binary.model_dir", "/path/to/contact_model")

sub = glove.tactile_binary().subscribe()
frame = await sub.recv_async()
contacts = sum(1 for v in frame.data if v == 1.0)
print(f"接触触点数: {contacts}")
{
  "header": {
    "seq": 42,
    "timestamp_us": 1709876543210,
    "frame_id": ""
  },
  "data": [-1.0, 0.0, 1.0, 1.0, -1.0, 0.0, ...] // 共 768 个值,526 个有效
}

TactileResidual

每像素有符号接触残差,基于触觉数据推断,帧率:120 FPS,与 glove.tactile() 同频发布。

字段类型说明
headerFrameHeader帧头
dataList[float]768 个残差值。正值 = 比基线压得重(接触),约 0 = 无接触,负值 = 比基线更轻,-1.0 表示无效触点

data 按 24×32 row-major 排列,与 TactileFrame 同形、同掩码(526 个有效触点)。访问第 row 行第 col 列:data[row * 32 + col]

残差信号不平滑、不归一化、不二值化,业务侧自行定阈值与后处理。和 TactileBinary 共享同一接触模型,同时订阅两者只跑一次模型推断。

残差解算依赖一个训练好的接触模型,模型在 Wuji Studio 中训练并按设备自动加载。未加载模型时,数据流仍以 120 FPS 发布,但所有有效触点恒接近静止零点,无法反映真实压力变化。

直接通过 SDK 使用(不经 Wuji Studio)时,配置 algorithms.tactile_binary.model_dir 即可(tactile_residualtactile_binary 共享该模型目录设置)。目录需包含 contact.safetensorscontact.npz 两个文件。模型目录变更或重新训练后,SDK 会自动热重载。

# 配置训练好的接触模型目录(经 Wuji Studio 使用时由 Studio 自动配置)
glove.set("algorithms.tactile_binary.model_dir", "/path/to/contact_model")

sub = glove.tactile_residual().subscribe()
frame = await sub.recv_async()
valid = [v for v in frame.data if v != -1.0]
print(f"残差范围: [{min(valid):.2f}, {max(valid):.2f}]")
{
  "header": {
    "seq": 42,
    "timestamp_us": 1709876543210,
    "frame_id": ""
  },
  "data": [-1.0, 0.05, 1.23, 0.87, -1.0, -0.02, ...] // 共 768 个值,526 个有效
}