SDKPython SDK

运行方式

当前线程、后台线程与手动 update 三种运行方式。

当前版本 · 1.4.0

运行方式

本章只适用于需要持续计算 SDK 处理后的数据或使用自动重连等后台功能的程序。只读取原始 pose/IMU 时不需要选择运行方式,见 数据来源与读取方式;需要上述功能时再往下读。

需要上述功能时,通过 Glove 选择一种运行方式。同一次运行中不要混用:

  • 命令行程序通常调用 glove.run_forever(),在当前线程持续运行;
  • GUI、异步程序或当前线程还要处理其他工作时,可以调用 glove.run_background() 在后台运行;
  • 已有同步主循环时,可以持续调用 glove.update(),由程序控制调度。

当前线程持续运行

glove.run_forever()

run_forever() 阻塞当前线程,直到收到停止请求或 SDK 因错误停止。公开命令行示例按 Ctrl+C 结束进程;需要主动停止时,使用后台模式。

后台线程运行

glove.run_background()
try:
    ...
finally:
    glove.request_stop()
    glove.join()

join() 不只是等待线程结束,也负责把后台运行错误报告给调用方,因此不能只调用 request_stop() 而省略 join()。后台模式适用于 GUI 主线程、宿主事件循环或其他不能阻塞当前线程的场景。

普通 asyncio 程序读取 SDK 处理后的数据时,通常在 start() 后调用 glove.run_background(),再通过 await output.next() 或 async for 读取输出。asyncio event loop 本身不会推进 SDK 调度,SDK 后台运行和 event loop 都需要保持运行。close() 可能等待数据处理与 callback 清理,异步程序中建议通过 asyncio.to_thread() 调用。

如果外部帧来自 async iterator,应创建一个独立的 asyncio task 持续调用 push_frame(),同时通过 await output.next() 或 async for 读取输出。只等待输出而不继续提交输入帧,不会产生新的 SDK 处理后的数据。

手动 update

手动模式适合已有同步主循环并希望主动控制 SDK 调度的程序。先订阅 SDK 处理后的数据,再启动设备;每次调用 glove.update() 都会计算到期的任务,也可以通过 latest() 立即读取当前输出:

output = glove.device().output()
output.subscribe(on_output)
glove.start()

for _ in range(100):
    update = glove.update()
    latest = output.latest()
    if latest is not None:
        print(latest.sequence, latest.value)
    if update.has_next_task:
        update.sleep()

按用途选择字段:

想做什么读取字段
记录已推进的调度次数tick
观察本次执行了多少任务ran_task_count
决定是否继续等待下一项任务has_next_task
等下一项任务到期再继续sleep()

完整字段、类型和返回值见 UpdateResult。sleep() 返回 SleepResult.READY、STOPPED 或 NO_TASKS。每个 UpdateResult 只能等待一次;重复使用或在下一次更新后再使用会抛出 StaleUpdateError。

手动模式只改变 SDK 调度由谁推进,不改变数据读取方式。能够自行协调 SDK 调度与 asyncio event loop 的宿主也可以采用手动 update(),但必须保证持续调用 glove.update();只等待输出而不继续推进调度,不会产生新的 SDK 处理后的数据。普通异步程序优先使用 glove.run_background();异步读取方式见 异步读取。

完整异步流程见 async_runtime.py。