迁移
从 SDK 1.3.0 升级到 1.4.0,以及更早版本升级时的 API 替换与流程调整。
迁移
从 1.3.0 升级到 1.4.0
1.4.0 的主要迁移动作是统一时间单位。现有单手套应用不需要改成组合设备,也不要求调用
sync_time();只有使用外部时间源、读取时间字段或准备接入 Exo + Glove 时,才需要完成对应步骤。
同时更新 Core 与 Glove
安装 qnbot-sdk-glove 1.4.0,让 pip 解析匹配的 Core 依赖;不要让已打包程序继续携带
1.3.0 的 native 库:
python -m pip install --upgrade "qnbot-sdk-glove==1.4.0"如果应用会打包 wheel、native 库或虚拟环境,应清理旧产物后重新构建并部署。
将公开数值时间改为毫秒
1.4.0 的 Glove 帧、运行状态、采集、标定和派生数据统一使用毫秒。新输出只提供
timestamp_ms;所有把时间当秒读取、存储、相减或传给下游协议的代码都需要同步修改。
外部帧的新写法:
frame = ExternalGloveFrame(
thumb=thumb,
index=index,
middle=middle,
ring=ring,
pinky=pinky,
timestamp_ms=1_700_000_000_123.0,
)旧的 timestamp_sec 仍可作为兼容输入,SDK 会明确执行
timestamp_ms = timestamp_sec * 1000。不要根据数值大小猜测单位,也不要同时传入两个字段;
timestamp_ms 与 timestamp_sec 同时存在时会抛出参数错误。
按需设置外部时间基准
如果应用需要让所有 Glove source 使用同一个外部绝对时间基准,在 Glove 域调用公开入口
Glove.sync_time()。参数是绝对 Unix 毫秒,不是秒或纳秒:
import time
sdk = Sdk(devices=(GloveConfig(),))
glove = sdk.glove()
glove.sync_time(time.time() * 1_000.0)
glove.start()可以在运行中再次调用 sync_time();后续未显式携带时间的 Glove 帧会从新基准继续推进,已有订阅和生命周期不会重置。显式提供的 timestamp_ms 优先,不会被共享时钟覆盖。不调用时,SDK 使用主机 Unix 毫秒时间。该操作只调整 Glove 域,不会修改 Exo 时间。
按需接入 Exo + Glove 组合设备
组合设备是 1.4.0 的新增能力,不影响原有 GloveConfig。需要共享串口时,改用
CompositeExoGloveConfig,并从同一个 Sdk 取得 sdk.glove() 与 sdk.exo();完整配置和能力边界见手套 + 外骨骼融合方案。
迁移检查清单
- 安装匹配的 Core 与 Glove 1.4.0,清理打包产物中的 1.3.0 native 库
- 将输出字段和下游协议中的秒值改为毫秒,优先使用
timestamp_ms - 如暂时保留
timestamp_sec输入,确认代码没有同时传入timestamp_ms - 对外部时间源使用绝对 Unix 毫秒,并在需要时调用
glove.sync_time() - 只有使用融合硬件时才改用
CompositeExoGloveConfig - 用真实设备复测采集记录、时间对齐、断线恢复和关闭流程
从 1.2.x 升级到 1.3.0
本文只列出 Glove SDK 从 1.2.0 升级到 1.3.0 时必须修改的内容。SerialConnection、后台运行方式和算法包 package_id 语义没有变化,因此不列入本次不兼容变更。
采集接口从 Glove 移到 GloveDevice
1.2.0 中,应用通过 Glove 调用采集接口,同时传入设备选择参数:
capture = glove.start_capture(
package_ids=["qnbot-dexhand"],
operator_id="operator-001",
source=None,
side=Side.LEFT,
force=False,
)其中 source 用于按设备名称选择设备,side 用于按左右手选择设备;source 为空时根据 side 选择设备。
1.3.0 中,需要先获取目标设备,再执行采集:
device = glove.device(side=Side.LEFT)
capture = device.start_capture(
package_ids=["qnbot-dexhand"],
operator_id="operator-001",
force=False,
)也可以按名称选择:
device = glove.device("my-glove")设备选择从采集请求中独立出来,由应用先明确选择 GloveDevice。
capture_status() 移到 GloveDevice
1.2.0:
readiness = glove.capture_status(
package_ids=["qnbot-dexhand"],
operator_id="operator-001",
source=None,
side=Side.LEFT,
)1.3.0:
device = glove.device(side=Side.LEFT)
readiness = device.capture_status(
package_ids=["qnbot-dexhand"],
operator_id="operator-001",
)start_calibration() 移到 GloveDevice
1.2.0:
calibration = glove.start_calibration(
completed_capture_session=capture,
targets=targets,
)1.3.0:
calibration = device.start_calibration(
completed_capture_session=capture,
targets=targets,
)采集会话和标定会话由同一个 GloveDevice 管理:
device = glove.device(side=Side.LEFT)
capture = device.start_capture(
package_ids=["qnbot-dexhand"],
operator_id="operator-001",
)
calibration = device.start_calibration(
completed_capture_session=capture,
targets=targets,
)CalibrationInteractionMode 更名
1.2.0 的 CalibrationInteractionMode 在 1.3.0 更名为 CaptureInteractionMode,取值不变(AUTO_TERMINAL、EXTERNAL):
from qnbot_sdk import CaptureInteractionMode项目代码、配置文件映射和自定义封装中使用旧枚举名称的地方都需要修改。
采集交互配置从 CalibrationConfig 移到 CaptureConfig
1.3.0 把采集阶段配置和标定阶段配置分开:interaction 和 operator_id 属于采集阶段,已从 CalibrationConfig 移到 CaptureConfig;CalibrationConfig 只保留 force。
如果 1.2.0 项目把这两个字段写在 CalibrationConfig 中:
algorithms = AlgorithmsConfig(
calibration=CalibrationConfig(
interaction=CalibrationInteractionMode.EXTERNAL,
operator_id="operator-001",
force=False,
),
)1.3.0 应改为:
algorithms = AlgorithmsConfig(
capture=CaptureConfig(
interaction=CaptureInteractionMode.EXTERNAL,
operator_id="operator-001",
),
calibration=CalibrationConfig(force=False),
)两个 force 的含义和归属没有变化,字段定义见 CaptureConfig 与 CalibrationConfig。
迁移检查清单
- 将
glove.start_capture()改为device.start_capture() - 将
glove.capture_status()改为device.capture_status() - 将
glove.start_calibration()改为device.start_calibration() - 将
CalibrationInteractionMode改为CaptureInteractionMode - 将
interaction和operator_id从CalibrationConfig移到CaptureConfig - 确保采集和标定使用同一个
GloveDevice
从 1.1.x 升级到 1.2.0
以下仅列出升级时需要修改现有代码或重新构建的不兼容变化。完整的新增功能、修复和版本变化请查看 Python SDK 更新日志。
| 不兼容项 | 原有用法 | 当前行为 | 迁移动作 |
|---|---|---|---|
| Core 与 Glove 安装包 | 可以分别替换 wheel,或让已打包程序继续携带旧版 native 库 | Core 与 Glove 属于同一套公开 API 和 native ABI,混用不同发布版本不受支持 | 删除旧版 wheel,同时安装同一发布版本的 Core 和 Glove;不要混用。若程序将 SDK 打包进可执行文件、镜像或其他交付产物,应清理旧构建内容并重新构建 |
connect() / start() / stop() 生命周期 | connect() 建立设备连接,start() 再启动数据流;停止后可另外调用 disconnect() | connect() 已弃用并保留为成功的空操作;start() 负责连接并启动,stop() 同时停止并断开;disconnect() 委托给 stop() | 不再依赖 connect() 判断连接成功;准备好数据读取和订阅后直接调用 start(),结束时调用 stop(),最后调用 close() |
| SDK 创建阶段 | 可以先创建未完成设备解析的 SDK,再到 connect() 时发现设备、读取身份和补全配置 | 创建 Sdk 时会完成设备发现与身份探测,并解析 source、target 和算法包;无设备、端口占用、身份不匹配或算法包缺失可能在构造函数中抛错 | 在创建 SDK 前准备好设备和算法包,把构造和 start() 都放入异常处理;设备、配置或已安装算法包变化后重新创建 SDK |
get_device_info() | 每次调用都会向已连接设备发起新的 id 身份事务 | 返回 SDK 创建阶段保存的已验证身份快照,可在 start() 前调用;显式端口回退但身份未验证时抛出 UnavailableFeatureError | 不要依赖该调用刷新设备身份;需要展示身份时读取快照,并在允许未验证设备的部署中处理 UnavailableFeatureError |
| Capture 请求参数 | capture_status() 和 start_capture() 使用 candidate_ids | 参数改为非空 package_ids,每项必须是非空算法包 ID | 将所有 candidate_ids= 改为 package_ids=,并确保序列非空 |
| Capture 结果与 Session 所有权 | CaptureSession.result() 返回 CaptureSet;后续标定接收该 CaptureSet | result() 返回只读摘要 CaptureResult;后续标定直接接收仍打开且已完成的 CaptureSession | 删除 CaptureSet / CaptureSetSnapshot 逻辑;在标定完成前保持原 CaptureSession 打开,并把它传给 start_calibration() |
| Calibration 会话 API | start_calibration(capture_set=..., package_id=..., target=...) 为一个 target 返回一个 CalibrationJob | start_calibration(completed_capture_session=..., targets=(...)) 返回一个 CalibrationSession,按顺序处理非空且不重复的 target 序列;result() 返回结果 tuple,wait() 可阻塞等待完成 | 删除独立 CalibrationJob 流程和 package_id 参数,改为一次创建 CalibrationSession,通过 snapshot()、result()、wait()、cancel() 和 close() 管理 |
| Capture 控制与进度 | device.calibration_control(name) 按 target 提交确认;calibration_progress(name) 同时包含动作提示、样本数和保存状态 | source 级动作改由 device.capture_progress() 与 device.capture_control() 处理;target 级 device.calibration_progress(name) 只报告 Calibration 计算状态 | 将 calibration_control() 改为 capture_control();从 CaptureProgress.stage 读取动作和样本进度,从 CalibrationProgress.job 读取各 target 状态;confirm()、skip()、cancel() 使用 request_id,retry() 使用 stage_id |
| Capture 状态与字段 | CaptureSessionState 包含 CREATED、AWAITING_CONFIRMATION、COLLECTING;CaptureStageState 包含 REUSED、CAPTURED、FAILED;快照使用 stage_runs 和字符串 failure,CapturePlan 含 resolved_packages | Session 的进行中状态统一为 RUNNING;动作状态进入 CaptureStageProgress,完成使用 COMPLETED,复用由 origin=REUSED 表示;快照使用 stage_progress 和结构化 CaptureFailure,resolved_packages 已删除 | 更新状态分支和界面字段:CAPTURED 改为 COMPLETED,从 origin 判断复用,从 Session 的结构化 failure 判断失败,并将 stage_runs 改为 stage_progress;不要再读取 resolved_packages |
| Calibration 状态与结果字段 | CalibrationJobState 使用 RUNNING、SAVING、COMPLETED、FAILED;CalibrationJobSnapshot 和 CalibrationResult 含 package_id、package_version | CalibrationSessionState 与 CalibrationJobState 支持取消,job 还包含 PENDING;保存过程归入 RUNNING;进度使用 CalibrationJobProgress / CalibrationSessionSnapshot,CalibrationResult 仅保留 record_id、source_id、target_id、created_at | 删除 SAVING 和 CalibrationJobSnapshot 分支,改用 Session/job 两级状态;如需算法包 ID 或版本,从自身 target 配置维护,不再从 CalibrationResult 读取 |
| 标定存储配置 | 通过 CalibrationStoreConfig 或 CalibrationConfig.store 指定目录 | 这两个公开入口已删除,标定记录统一保存在 <QNBOT_HOME>/glove/calibrations | 删除旧存储配置;如需更改数据根目录,在创建 Sdk 前设置 QNBOT_HOME,并确保 CLI 与 SDK 使用相同值 |
| Debug 日志目录 | 通过 DebugConfig.log_dir 指定目录 | DebugConfig.log_dir 已删除;QNBOT_HOME 决定日志根目录,日志位于 <QNBOT_HOME>/logs,每次诊断运行使用独立 session 目录 | 删除 DebugConfig.log_dir;如需更改日志根目录,在创建 Sdk 前设置 QNBOT_HOME |
| Debug detail 与 module | 使用 DebugDetail.RAW 和任意 module 字符串,例如 serial、glove、buffer | RAW 已删除;详细记录使用 FULL。可选模块改为 DebugModule.TRANSPORT、DEVICE、CAPTURE、CALIBRATION、RETARGETING、OUTPUT | 将 DebugDetail.RAW 改为 FULL 或 SUMMARY;把旧 module 名替换为对应 DebugModule 枚举值 |
| Skeleton 关节角与标定 | skeleton().joint_angles() 使用 24 个 active joints,索引 1 是原有第二个关节;已有标定对应旧 Skeleton 版本 | 关节角增加为 25 个,索引 1 新增 <side>_thumb_cmc_flexion,原索引 1–23 后移一位;Skeleton pose 仍为 25 个节点,旧版本标定不会作为当前兼容记录复用 | 将固定长度、索引映射和下游协议更新为 25 个关节,优先按关节名读取;升级后允许 Skeleton 重新标定 |