- Python
- C
接触检测与接触残差数据流(TactileBinary、TactileResidual)依赖训练好的接触模型。首次使用前,先运行
wuji calib tactile 完成触觉标定,模型按 SDK 用户与手套序列号自动加载。触觉矩阵布局
触觉数据来自压阻阵列的 24×31 压力矩阵,共 744 个位置,其中 526 个为有效触点。TactileFrame、TactileBinary、TactileResidual 均采用该布局,按 24×31 row-major 排列。访问第 row 行第 col 列:data[row * 31 + col](row 为 0–23,col 为 0–30)。
下图标注了行、列索引在手套上对应的物理触点位置(左:列索引,右:行索引),可据此把矩阵索引(或导出点云中的点顺序)对应到手套的具体部位。

布局变更
固件 v0.11.0 起,触觉矩阵从 24×32(768 值)调整为 24×31(744 值),移除 24×32 布局中的无效列 26。其余列相对顺序不变:列 0–25 索引保持原样,列 27–31 左移为列 26–30。
TactileFrame
标定后的触觉矩阵数据。帧率:120 FPS。data 为 744 个值的数组,按 24×31 row-major 排列。访问第 row 行第 col 列:data[row * 31 + col]。无效位置固定为 -1.0,可据此与有效触点的零压力 0.0 区分。
TactileZones
按手指区域聚合的触觉数据。每个区域是一块矩形,按 row-major 排列。矩形内属于该区域的位置给出压力值,其余位置固定为-1.0。
六个区域的有效触点合计 526,与 TactileFrame 同掩码。数组长度是矩形的格数,按上表取值即可避免越界。
PointField
点云字段描述。PointCloud
触觉点云数据:每帧给出手套 526 个有效触点的 3D 位置和压力。位置通过线性混合蒙皮(LBS)从手部骨架解出,坐标系l_wrist / r_wrist。每点除 x / y / z 还带 pressure(0.0–1.0 归一化压力),可按压力着色做 3D 可视化。
glove.tactile_point_cloud() 的空间位置依赖 EMF 链路解算的手部姿态,输出率跟随 emf_poses 的实际输出率同步变化,见 输出率调节。sensor_msgs/PointCloud2 的自描述格式:data 是扁平字节流,point_stride 是每点字节数,fields 描述每点内部的字段(名字、字节偏移、类型)。当前实现 4 个字段,每点 16 字节,data 共 point_count × 16 字节,按点顺序排布。新增字段时只需在 fields 追加一项,PointCloud 自身的消息定义不变。
TactileBinary
二值接触检测结果,基于触觉数据推断,帧率:120 FPS,与glove.tactile() 同频发布。
data 按 24×31 row-major 排列,与 TactileFrame 同形、同掩码(526 个有效触点)。访问第 row 行第 col 列:data[row * 31 + col]。现有触觉网格可视化无需改动即可复用。
训练接触模型
接触模型训练一次,按当前 SDK 用户与手套序列号保存(目录规则见 触觉数据路径),订阅时 SDK 自动加载,无需配置路径。训练入口有两个:- Wuji CLI:运行
wuji calib tactile,按终端提示完成 4 个动作的采集,CLI 随后自动训练、验证并安装模型。用法见 触觉标定。 - SDK 标定接口:
await glove.calibrate_tactile()(或阻塞版glove.calibrate_tactile_blocking())按提示录制几组动作,SDK 自动完成训练与安装。每组录制结束可以保留、重录或停止,传入on_pose_prompt回调即可交互控制,不传则全程自动执行。完整用法见示例7.tactile_calibration.py(Python)与4_tactile_calibration.c(C,接口说明见触觉接触标定)。
跨机器迁移模型
推荐用wuji user export 与 wuji user import 整体迁移。手动迁移时必须满足两点:
- 拷贝全部 3 个模型文件:
contact.safetensors、contact.npz与contact.json(位置见 触觉数据路径)。contact.json是模型的提交标记,缺少该文件时模型不会被加载。 - 放入
manager.tactile_model_paths(user_id, sn)返回的paths["dir"]目录。
TactileResidual
每像素有符号接触残差,基于触觉数据推断,帧率:120 FPS,与glove.tactile() 同频发布。
data 按 24×31 row-major 排列,与 TactileFrame 同形、同掩码(526 个有效触点)。访问第 row 行第 col 列:data[row * 31 + col]。
残差信号不平滑、不归一化、不二值化,业务侧自行定阈值与后处理。和 TactileBinary 共享同一接触模型,同时订阅两者只运行一次模型推断。
tactile_residual 与 tactile_binary 共享同一个模型目录,同样按当前 SDK 用户与手套序列号自动加载,模型的训练入口与迁移方式见 TactileBinary。切换 SDK 用户或重新训练模型后,SDK 会自动热重载。
wuji_glove_。初始化约定、内存管理、错误码与工程构建见 C 接口参考。
触觉接触灵敏度
wuji_glove_set_tactile_binary_sensitivity 设置当前 SDK 用户的 tactile_binary 灵敏度倍率。SDK 在本地保存该倍率。设置立即生效,重新连接后仍然保留。传入有限正数,值高于 1.0 时接触检测更灵敏。
wuji_glove_get_tactile_binary_sensitivity 返回当前生效的倍率。返回值限制在 0.5–3.0。没有有效值时,getter 返回 1.0。
dev 与 out_sensitivity 都不能为 NULL。任一指针为 NULL 时,getter 返回 WUJI_STATUS_ERR_INVALID_ARG。out_sensitivity 有效时,调用失败不修改 *out_sensitivity。用 wuji_last_error() 获取详情。
触觉接触标定
wuji_glove_calibrate_tactile_blocking 一次调用完成引导式触觉接触标定:按提示录制几组动作,SDK 依次完成采集、数据校验与训练。
调用前先决定 install:
install = true:训练后执行加载校验并安装,模型按当前 SDK 用户与手套序列号保存,订阅tactile_binary/tactile_residual时自动加载。可选灵敏度参数(has_sensitivity置 true 并填sensitivity)仅此模式接受,否则调用直接报错。install = false:只训练不安装,跳过加载校验与安装,产物保存在本次运行目录,不会自动加载。适合先离线评估训练效果、再决定是否安装的场景。
on_pose_prompt 让流程可交互:每组动作开始前与录制结束后各回调一次,参数为 WujiTactilePromptRequest,返回 0 继续、1 重录、2 停止,其他取值一律按停止处理。on_feedback 上报采集与训练进度,返回 0 继续、1 中止,其他取值一律按中止处理。两个回调都可不设置,此时全程自动执行。回调收到的事件指针仅在回调期间有效。timeout_s 是协作式超时:超时触发取消,但函数会先等在途的采集或训练与正在执行的回调返回,因此函数返回后不再有任何回调触发。若 on_pose_prompt 内部无限阻塞(如等待控制台输入),超时无法强制它返回。
成功返回后从 summary 读取结果,model_dir 两种取值按 installed 区分:
installed = true:model_dir指向已安装的模型目录,订阅时自动加载。installed = false:model_dir指向本次运行保存的模型,不会被自动加载。
verified_alive_taxels 仅在 has_verified_alive_taxels 为 true 时有效。读完调用 wuji_tactile_calibration_summary_free 释放堆字段。
失败原因通过 wuji_last_error() 获取。库构建时未启用 model-export 特性会返回 WUJI_STATUS_ERR_UNSUPPORTED。Python 对应接口为 glove.calibrate_tactile_blocking()(阻塞)。异步版 glove.calibrate_tactile() 仅 Python 提供,C 侧无异步入口。
实时观察接触与残差的操作见 SDK 使用实践的触觉接触网格视图与触觉残差网格视图。