SDK 数据参考

标定

Wuji Glove 用 EMF 解算手部关节角度时,需要先做一次 IK 标定,生成与穿戴者手型匹配的 URDF 模型。SDK 提供 Python 标定 API、运行时手型切换、用户自定义 URDF 覆盖,并按 SDK 用户与设备序列号隔离标定文件。

何时需要标定

  • 首次使用一台手套
  • 更换穿戴者
  • 上层应用需要切换 Wuji Hand / Wuji Hand 2 模型

设备序列号已包含左右手信息,左手套和右手套各自独立标定,互不影响。启用 SDK 用户隔离时,每位用户独立持有自己的标定 URDF,见 SDK 用户管理

标定流程

标定要求穿戴者按提示完成一组规定动作,SDK 采集 EMF 数据并解算出适配的 URDF。

标定开始 SDK 自动把 EMF 降频因数临时强制为 1,采集结束恢复原值(含错误与取消路径)。预先调用 glove.emf_poses_rate_divider().set(N>1) 不会让标定时间被放大。详见 输出率调节

同步阻塞调用

适合脚本与命令行工具:

from wuji_sdk import SdkManager, Handedness

manager = SdkManager.instance()
glove = manager.connect(handedness=Handedness.Left, device_name="glove")

result = glove.calibrate_blocking(timeout_s=900.0)

print("device_sn:", result["device_sn"])
print("active hand profile:", result["active_hand_profile"])
print("generated profiles:", result["generated_hand_profiles"])
print("URDFs:", result["calibrated_urdfs"])
print("poses collected:", result["poses_collected"])
print("sdk user:", result["sdk_user"]["display_name"])

calibrate_blocking() 在标定结束或超时前不返回,Ctrl+C 延迟到方法返回后才响应。

异步调用

asyncio 程序使用异步 API,支持标准 cancellation:

result = await glove.calibrate(timeout_s=900.0)

参数

参数类型默认说明
skip_constraintsboolFalse跳过稳定性和约束检查(仅调试用)
timeout_sfloat900.0整体超时(秒),必须为有限正数
hand_profileWujiHandProfilestrNoneNone指定要生成的手型 profile(见下)
on_feedbackCallableNoneNone实时反馈回调

实时反馈

通过 on_feedback 回调获取标定过程中的状态:

def on_feedback(fb):
    if fb.get("state") == "collecting":
        progress = fb.get("progress", 0.0)
        step = fb.get("step_index", 0)
        total = fb.get("step_total", 0)
        print(f"step {step}/{total}: {progress*100:.0f}%")
    for hint in fb.get("hints", []):
        print(f"hint: {hint}")

result = glove.calibrate_blocking(on_feedback=on_feedback)

fb 字典包含当前姿势序号、状态、进度、采集帧数、姿势偏差诊断指标 (metrics) 与提示文本 (hints) 等字段。

回调内抛出的异常会被 SDK 记录到日志,不会中断标定。

手型选择

Wuji Glove 支持两代手型的实时 IK 模型:

手型字符串值枚举
Wuji Hand"wujihand"WujiHandProfile.WUJI_HAND
Wuji Hand 2"wujihand2"WujiHandProfile.WUJI_HAND_2

标定时指定手型

from wuji_sdk import WujiHandProfile

result = glove.calibrate_blocking(
    hand_profile=WujiHandProfile.WUJI_HAND_2,
)
# result["generated_hand_profiles"] == ["wujihand2"]
# result["calibrated_urdfs"] == {"wujihand2": "/path/to/...urdf"}

不指定 hand_profile 时,SDK 用同一批采集数据同时生成两代 URDF,写入:

  • calibration.hand_model_paths.wujihand
  • calibration.hand_model_paths.wujihand2

实时 IK 默认使用 "wujihand",运行时可直接切换。

运行时切换手型

calibration.hand_profile 参数通过 SET 在线切换实时 IK 模型:

# 切到 Wuji Hand 2
glove.set("calibration.hand_profile", "wujihand2")

# 切回 Wuji Hand
glove.set("calibration.hand_profile", "wujihand")

切换在下一帧生效。未设置 calibration.hand_profile 时默认为 "wujihand"

自定义 URDF 覆盖

calibration.hand_model_path 可指定用户提供的 URDF 文件,优先级最高

glove.set("calibration.hand_model_path", "/path/to/custom_hand.urdf")

清空该值后,SDK 按 calibration.hand_profile 回退到标定生成的 URDF。

URDF 查找顺序

实时 IK、tf_staticoffline_pipeline 加载手部 URDF 的优先级:

  1. 用户自定义路径calibration.hand_model_path 指向 SDK 托管目录之外的文件
  2. 当前 profile 的标定 URDFcalibration.hand_model_paths.<profile>wujihandwujihand2
  3. legacy 兼容路径:旧版本写入的 calibration.hand_model_paths.hand_1/hand_2calibration.hand_model_path
  4. 内置默认 URDF:按左右手返回 SDK 自带模型

找不到目标 profile 的标定 URDF 时,SDK 会静默回退到内置默认模型并打印一条 warn 日志。手部追踪不会中断,但解算精度会下降。生产环境应根据日志确认 IK 在用预期的 URDF。

返回字段

calibrate() / calibrate_blocking() 返回的标定汇总:

字段类型说明
device_snstr设备序列号(已编码左右手)
hand_profilestrNone调用时传入的 profile,未传则为 None
active_hand_profilestrNone实时 IK 标定后将使用的 profile
generated_hand_profileslist[str]本次实际生成的所有 profile(["wujihand"]["wujihand","wujihand2"]
calibrated_urdfsdict[str, str]profile → URDF 文件路径
calibrated_urdfstrNone单 profile 标定时为该路径,多 profile 时为 None
poses_collectedint采集到的姿势数
frames_per_posedict[str, int]姿势名 → 该姿势采集帧数
sdk_userdict标定当时的 SDK 用户信息(user_id / display_name / description / is_default

标定结果路径

标定 URDF 按 <sn>_hand_<profile>_<calibration_id>.urdf 命名。落盘根目录按 SDK 用户区分:

SDK 用户URDF 目录参数表
默认用户~/.wuji/sdk/models/~/.wuji/sdk/params/<sn>.toml
具名用户~/.wuji/sdk/users/<user_id>/models/~/.wuji/sdk/users/<user_id>/params/<sn>.toml

唯一性由 (user_id, device_sn, hand_profile) 三元组保证。切换 SDK 用户时,已连接设备会自动重新加载该用户名下对应的 URDF,无需重连。

错误处理

场景行为
hand_profile 传入非 "wujihand" / "wujihand2" 的字符串或枚举立即抛 ValueError / WujiException,标定不会启动
timeout_s 非有限正数立即抛 ValueError
标定超时TimeoutError,本轮采集结果不持久化
标定中途切换 SDK 用户WujiException(错误信息含 SDK user changed during calibration),本轮采集结果丢弃,旧 URDF 不动
URDF 写入失败WujiException自动回滚本轮新文件,旧 URDF 与 hand_model_paths 参数保持原值
标定算法收敛失败WujiException,错误信息标注失败的 hand_profile,旧 URDF 不动

所有失败路径都保留上一次成功的标定结果,失败的本轮不会污染已有 URDF,可直接重试。

资源路径速查

资源路径访问说明
calibration.hand_profileGET / SET实时 IK 当前使用的手型("wujihand" / "wujihand2"
calibration.hand_model_paths.wujihandGET / SETWuji Hand 标定 URDF 路径,由 SDK 写入
calibration.hand_model_paths.wujihand2GET / SETWuji Hand 2 标定 URDF 路径,由 SDK 写入
calibration.hand_model_pathGET / SET用户自定义 URDF 覆盖(优先级最高)