Skip to main content

概述

本篇实践介绍如何使用离线管线将电磁位姿和原始 IMU 数据转换为手部追踪结果。应用场景包括重新处理录制数据、在无设备环境中调试和比较不同手部模型的求解结果。 对应的 Python 示例为 3.offline_pipeline.py。 接口与参数说明见原始数据转换,本页说明集成流程和运行时行为。
C SDK 没有对应的离线管线接口,本页介绍 Python 用法。

前置条件

硬件

无。这是本系列唯一一篇不需要接设备的文章。

软件

前序步骤

想重放真实数据先看数据录制。只跑示例里的合成帧则无需任何准备。

数据流

管线提供的通道

实测 offline_pipeline() 返回对象暴露这些方法: 另有三个只读属性:sn、hand_side、urdf_source 与 urdf_source_path。 手部求解依赖 URDF,IMU 融合不依赖。 换手模只影响前三个方法的输出。

URDF 来源

构造时传的 sn 决定 SDK 去哪里找手部模型。实测未标定的序列号:
urdf_source 有两种取值。builtin_default 表示用的是内置通用手模,path 为 None。标定过的设备会指向 ~/.wuji/sdk/models/<序列号>_hand.urdf。 想强制指定某份手模,传 urdf_path:
路径不存在会立刻抛错,不会静默回落到默认手模:
hand_side 只接受 "left" 和 "right",其他值抛 ValueError: hand_side must be 'left' or 'right'。
重放数据时 sn 要填采集那只手套的序列号,不是本机手上这只。填错会加载到另一份手模,求解结果整体偏移,而且不报错。

与在线结果的一致性实测

方法

  1. 连真实手套,用 TopicRecorder 同时录 emf_poses、hand_joint_angles、hand_skeleton 三条流,4 秒
  2. 从 MCAP 里按 header.seq 把三条流对齐,得到 525 个共同帧
  3. 把录到的 emf_poses 重建成 EmfPoseArray,喂给离线管线
  4. 拿离线算的结果与录到的在线结果逐元素相减

结果

对比前 200 帧: 关节角完全相同。骨骼位置的 7 纳米差异来自 MCAP 的 JSON 序列化把 float 往返了一遍,不是算法差异。 结论是离线重放能无损复现在线求解。拿录好的数据调算法、对比不同手模、复现线上问题,结果都可信。

重放代码

Quaternion 的构造顺序是 (x, y, z, w)。MCAP 里存的方向如果是对象形式,按字段名取,别按顺序解包。

IMU 融合实测

融合器有状态,逐帧推进。示例只喂了一帧,看不出行为,实测连续喂帧的演化。

静止

持续喂 angular_velocity=(0,0,0)、linear_acceleration=(0,0,9.8),共 399 帧: 姿态锁在单位四元数,没有漂移。重力方向与理想 Z 轴一致时融合器不产生修正量。

转动

改喂 angular_velocity=(0, 0, 1.0) rad/s,每帧时间戳递增 5 ms,共 200 帧(1.0 秒): 1 rad/s 转 1 秒理论上是 1 rad = 57.30°,实测 57.0°。差的那 0.3° 是因为首帧没有前一帧可以算时间差,不参与积分,实际只积分了 199 帧:199/200 × 57.30° = 57.01°,与实测吻合。 这决定了两件事:时间戳必须真实递增,融合器完全靠它算积分步长。以及第一帧的输出永远是初始姿态,不要拿它做判断。

集成步骤

完整示例见 Python 示例。以下片段按接入顺序展示关键操作,参数解析、信号处理和完整错误分支见示例。

1. 创建离线管线

序列号使用采集数据的手套序列号,手别与采集设备一致。整段回放复用同一个管线,无需连接设备。

2. 准备电磁位姿帧

Python 示例 用 make_emf_frame() 构造包含 5 指的合成帧。接入录制数据时,将同一时刻的位姿、置信度和帧头还原为 EmfPoseArray,保留采集时间顺序。

3. 逐帧计算所需输出

将一帧传入相应通道。关节角、指尖位姿和骨架可按应用需要选择,无需全部计算。

4. 按需计算 IMU 融合结果

IMU 融合使用独立输入。Python 示例 的 make_raw_imu() 构造原始 IMU 帧,真实回放按采集顺序持续传入。管线无需显式关闭,对象回收即可。

运行与输出

以上为实机运行结果,未连接任何设备。示例用的是一个不存在的演示序列号,所以 urdf_source 是 builtin_default。 三帧的 curl 参数从 0.00 递增到 0.70,模拟手指逐渐弯曲。拇指第 5 个角度随之从 0.629 增到 1.087,方向正确。thumb_conf 恒为 0.475,合成数据的置信度不随弯曲程度变化。

注意事项

扩展用法

对比两套手模

同一批数据跑两条管线,一条用默认手模、一条用标定手模,逐帧比较关节角,就能量化标定带来的差异:

批量重放不要每帧新建管线

hand_joint_angles() 每次调用返回一个通道对象。循环里反复调没有问题,但 IMU 融合的状态挂在管线上,换管线等于重置融合器。整批数据用同一个 pipeline 实例跑完。

合成数据用于回归测试

无需连接设备即可运行,适合用于 CI。示例里手写三帧的做法可扩展为固定输入和固定期望输出的断言。

相关内容