跳转到主要内容
离线解算以 Wuji Glove 的 emf_poses 生成关节角、指尖位姿和骨架,以原始 IMU 帧生成融合姿态。数据录制将输入帧保存为 MCAP 文件,重放代码从该文件读取并还原帧。还原后的帧可直接传给离线解算接口,无需连接设备。

解算步骤

创建离线处理管线

创建离线处理管线时,指定采集设备的序列号与手别。序列号支持 1–64 字节的 ASCII 字母、数字、.、_ 和 -,不能仅为 . 或 ..。urdf_path 可选,用于固定手部模型,便于重复处理同一批数据。 以下示例使用右手,实际处理时替换为录制数据对应的值。
hand_side 使用 "left" 或 "right",非法值抛出 WujiException。urdf_path=None 使用下方的模型查找规则。

复算关节角、指尖位姿和骨架

处理录制数据时,从 MCAP 文件的 /<序列号>/emf_poses 通道读取输入帧。解算接口使用的输入类型在 Python 中为 EmfPoseArray,在 C 中为 WujiEmfPoseArray。Python 的帧读取与还原方法见重放代码。 每帧包含 5 个 EMF 位姿。对同一帧依次请求关节角、指尖位姿与骨架,共享一次解算。下面的函数接收 1 帧并输出结果数量。

复算 IMU 姿态

处理录制数据时,从 MCAP 文件的 /<序列号>/imu_raw/palm 通道读取输入帧。解算接口使用的输入类型在 Python 中为原始 ImuData,在 C 中为原始 WujiImuData。Python 的帧读取与还原方法见重放代码。 将原始 IMU 帧传给对应的融合入口,获得姿态。6 路入口分别对应 palm、thumb、index、middle、ring 和 pinky,各自保持融合状态,均不依赖标定 URDF。Python 方法名使用 imu_data_<部位>(),C 函数名使用 wuji_glove_offline_compute_imu_data_<部位>。
ImuData.raw() 将 orientation_covariance[0] 设为 -1.0,表示未融合输入。
输入和输出使用同一数据类型。融合后的 orientation_covariance[0] 为 0.0。

示例

以下程序使用合成的右手 EMF 帧和手背 IMU 样本,依次创建管线、计算手部结果与 IMU 姿态,最后释放资源。运行时无需连接设备。 真实数据可使用 Wuji Glove 录制的 MCAP 文件,文件中需包含 emf_poses 和 imu_raw/palm 两条通道。按重放代码从文件还原原始帧并逐帧传入管线。序列号可从通道名核对,手别和采集时使用的 URDF 需在录制时另行记录。
保存为 offline_pipeline.py,运行 python offline_pipeline.py。
两种程序均应输出 Fingers: 5, tips: 5, skeleton joints: 21,以及包含 4 个分量的 Orientation。姿态数值随 IMU 输入变化,手部结果数值还受手部模型影响。默认 SDK 用户使用内置模型时,日志中出现相应警告是预期行为。这一步确认解算接口可运行,真实录制数据的读取、逐帧重放和在线结果对比见 SDK 使用实践 · 离线数据处理。

注意事项

选择并核对手部模型

手部结果依赖标定模型。两种语言按相同规则选择 URDF:
  1. 显式路径:传入 urdf_path 时直接使用该文件,读取失败时报错,不回退
  2. 托管模型:未指定路径时,优先使用当前 SDK 用户的 calibration.hand_model_path 指向的自定义文件,前提是它位于 SDK 托管目录之外。否则使用该用户对应手别的 left_hand.urdf 或 right_hand.urdf。两者二选一,不互为回退
  3. 内置模型:选中的托管模型文件缺失、无法读取,或路径指向另一手别时,使用内置默认 URDF 并记录警告
默认 SDK 用户跳过托管模型,未显式指定路径时使用内置模型。要匹配采集时的手部模型,先切换到采集时所用的具名用户,或指定对应 URDF。详见标定。内置模型可能降低手部结果的准确性,IMU 融合不受 URDF 影响。
创建管线后即可解算,无需再查询。托管模型不可用时可能回退到内置 URDF。需要确认实际使用的模型时,读取 urdf_source 和 urdf_source_path。序列号和手别也可从管线读回。
urdf_source 为 "override"、"calibration_file" 或 "builtin_default"。内置模型的 urdf_source_path 为 None。

按采集顺序处理帧

按采集顺序逐帧调用。同一管线保留解算状态,手部解算只缓存最近 1 帧。连续提交相同的手部帧不会再次求解,依次提交帧 A、帧 B、帧 A 时则会重新计算。 每个独立数据流使用独立管线,同一管线串行处理。从头重播或更换标定模型时创建新管线。 离线与在线流程复用相同解算器。对比结果时,保持输入帧、标定模型和处理顺序一致。

检查错误并释放资源

调用失败时抛出异常。结果对象由 Python 管理,无需手动释放。管线及其资源对象应在创建它们的线程中使用。重新处理一段录制时创建新的 pipeline。非法 hand_side 抛出 WujiException。显式 URDF 不可读或解算失败时,通过异常获取原因。