原始数据转换

Wuji SDK 的原始数据转换让你在采集时只保存轻量的原始数据,事后再把它们复算成完整的后处理产物——指尖位姿、关节角度、手骨架、IMU 融合姿态。离线复算结果与在线实时计算完全一致。

何时使用

实时逆向运动学解算对 CPU 消耗较高。如果采集时只想录数据、之后再分析,全程跑解算是浪费。原始数据转换适合:

  • 采集时只订阅轻量的 emf_poses 和原始 IMU,降低 CPU 占用
  • 事后再决定需要哪些后处理产物
  • 用任意自选格式保存原始数据,不绑定特定文件格式

工作流

  1. 在线采集:只订阅 emf_poses 和原始 IMU 数据
  2. 保存:用任意格式保存原始数据帧
  3. 离线复算:用 WujiGlove.offline_pipeline() 把保存的帧复算成后处理产物

离线复算与在线实时计算结果一致:相同的输入加相同的标定,得到相同的输出。

创建离线 pipeline

WujiGlove.offline_pipeline() 创建一条不依赖真实设备连接的 pipeline。

from wuji_sdk import WujiGlove

pipeline = WujiGlove.offline_pipeline(
    sn="WujiGlove-12345",   # 必填,按序列号加载该设备的标定
    hand_side="right",       # 必填,"left" 或 "right"
    urdf_path=None,          # 可选,指定标定手部模型文件
)
参数说明
sn设备序列号,用于加载对应设备的标定模型
hand_side手别,"left""right";非法值抛 ValueError
urdf_path可选,显式指定 URDF 手部模型路径

pipeline 创建后可查询实际使用的标定来源:

print(pipeline.sn)               # "WujiGlove-12345"
print(pipeline.hand_side)        # "right"
print(pipeline.urdf_source)      # "override" | "calibration_file" | "builtin_default"
print(pipeline.urdf_source_path) # 实际 URDF 路径,或 None

标定查找顺序

手部产物依赖标定的手部模型。pipeline 按以下顺序查找 URDF:

  1. urdf_path:显式传入则直接使用该文件
  2. 标定文件:未传 urdf_path 时,按 sn~/.wuji/sdk/params/ 中查找该设备的标定
  3. 内置默认模型:以上都没有时回退到内置默认 URDF,并打印 warning

回退到内置默认模型(urdf_sourcebuiltin_default)时,手部产物可能不准确。请确认使用的是采集该数据的手套的标定模型。IMU 融合产物不依赖 URDF,不受影响。

复算手部产物

手部链以 emf_poses 帧为输入,复算出三种产物。三者共享同一次解算,结果与在线一致。

for emf_poses in my_recording_reader():   # 自定义读取器,逐帧返回 EmfPoseArray
    angles   = pipeline.hand_joint_angles().compute(emf_poses)
    tips     = pipeline.tip_poses().compute(emf_poses)
    skeleton = pipeline.hand_skeleton().compute(emf_poses)
    save(angles, tips, skeleton)   # 自定义写入器
资源返回类型内容
pipeline.hand_joint_angles()HandJointAngles21 DoF 手部关节角
pipeline.tip_poses()FingertipPoses5 指指尖位姿
pipeline.hand_skeleton()HandSkeleton21 个 MediaPipe 关键点骨架

产物的完整字段定义见 SDK 数据参考

复算 IMU 融合

IMU 链以原始 IMU 帧为输入,复算出融合姿态。手套手背 IMU 用 imu_data_palm()

for raw_frame in my_imu_reader():   # 逐帧返回原始 ImuData
    fused = pipeline.imu_data_palm().compute(raw_frame)
    save(fused)   # 自定义写入器

原始 IMU 帧用 ImuData.raw() 构造,orientation_covariance[0] 自动标记为 -1(未融合)。IMU 融合产物不依赖标定 URDF。

构造输入帧

用 schema 构造器在内存中构造输入帧:

from wuji_sdk import (
    EmfPose, EmfPoseArray, FrameHeader, ImuData,
    Pose, Quaternion, Vector3F64,
)

emf = EmfPoseArray(
    header=FrameHeader(seq=1, timestamp_us=0, frame_id="r_hand_emf_tx"),
    poses=[
        EmfPose(
            pose=Pose(position=[0.05, 0.0, 0.0],
                      orientation=Quaternion(0.0, 0.0, 0.0, 1.0)),
            confidence=1.0,
        )
        for _ in range(5)
    ],
)

raw_imu = ImuData.raw(
    header=FrameHeader(seq=1, timestamp_us=0, frame_id="imu_raw/palm"),
    angular_velocity=Vector3F64(0.0, 0.0, 0.0),
    linear_acceleration=Vector3F64(0.0, 0.0, 9.8),
)

完整可运行示例见 SDK 安装包中的 examples/3.offline_pipeline.py