数据来源与读取方式
姿态、IMU、Skeleton 与输出的共同读取方式,以及外部输入来源。
数据来源与读取方式
两类数据
SDK 发布两类数据:设备直接产出的原始数据,和 SDK 计算出的数据。读取方式相同,区别只在数据怎么产生:
| 原始数据 | SDK 处理后的数据 | |
|---|---|---|
| 典型 API | pose()、imu()、status() | skeleton()、output() |
| 需要算法包 | 不需要 | 灵巧手输出需要,见 算法包配置;Skeleton 由 SDK 提供,不需要 |
| 需要运行方式 | 不需要 | 需要,见 运行方式 |
原始数据见 读取原始数据,SDK 处理后的数据(Retargeting)见 读取 Retargeting 数据。
数据读取方式
几种读取方式拿到的是同一批 Sample<T>。推荐 callback 订阅:数据在产生时立即处理,不需要轮询;只需要当前值时用 latest(),阻塞等待与 coroutine 见 运行方式。
姿态、IMU、Skeleton、灵巧手输出、状态和标定进度都使用相同的读取方式:启动前注册 callback
持续接收,启动后用 latest() 取最新值,或用 next() 阻塞等待、用 coro::next 异步等待。阻塞等待与 coroutine 的 executor、stop token 和取消规则见 运行方式
与 C++20 coroutine。
每次读取返回 Sample<T>;字段、类型和两个时间的取值约束见 Sample<T>。
callback 订阅
subscribe() 在每次有新数据时调用 callback:
auto subscription = device.status().subscribe(
[](const qnbot::Sample<qnbot::GloveStatus>& sample) {
std::cout << sample.value.connected << '\n';
});同一订阅的 callback 按顺序执行且不会并发。callback 应保持短小;其中抛出的异常不会终止订阅。应用必须保存返回的 Subscription;需要提前停止该 callback 时调用
subscription.unsubscribe()。不要在 callback 内同步取消或销毁它自己的订阅。
阻塞等待下一条数据和 C++20 coroutine 用法见运行方式。
获取最新值
latest() 立即返回当前保存的最新数据;尚无数据时返回 std::nullopt:
if (const auto sample = device.pose().latest()) {
std::cout << sample->sequence << '\n';
}外部输入
没有实体手套,或要把自研设备、仿真手部的数据接进来时,用 ExternalConnection + push_frame() 把外部手部帧作为输入源。外部手部帧与实体手套进入同一条数据链路:原始姿态直接读取,Retargeting 结果由 SDK 计算。
配置与使用
外部输入没有设备身份握手,因此必须在 GloveConfig 中显式配置 side:
qnbot::GloveConfig glove_config{
qnbot::Side::right, qnbot::ExternalConnection{}};配置 target 后,先订阅输出并启动 SDK,再由应用持续提交帧:
auto device = glove.device();
auto output = device.output("hand");
auto subscription = output.subscribe(
[](const qnbot::Sample<qnbot::HandJointCommand>& sample) {
std::cout << sample.value.joints.size() << '\n';
});
device.start();
glove.run_background();
qnbot::GlovePose pose = device.push_frame(frame);push_frame() 同步返回当前帧的原始 GlovePose;Retargeting 结果通过 output() 读取。上例使用后台模式。
外部输入沿用运行方式中的后台或手动模式:后台模式持续提交 push_frame(frame);手动模式每轮先提交帧,再调用 update()。首次需要标定时,完成采集与标定后才会产生 target 输出。完整示例见后台运行和手动 update。
帧约束
- 五个指尖姿态(
thumb、index、middle、ring、pinky)必填,每个值都是GloveNodePose。 position是 3 个有限浮点数,单位为米。quaternion_xyzw是 4 个有限的 XYZW 分量,整体范数非零;SDK 会在使用前归一化。timestamp_ms可省略;填写时必须是有限毫秒数,并对同一设备严格递增;省略时沿用当前共享时间基准。时间单位、默认基准和授时方式见时间戳与外部授时。timestamp_sec仅用于兼容旧代码,SDK 会将其乘以1000转为毫秒;不得与timestamp_ms同时设置。
公共合同统一单位和 quaternion 分量顺序,但坐标原点、轴方向和旋转参考系仍须与所选算法包的产品说明一致。side 不随帧传入;设备标识与 sequence 由所选设备和 SDK 决定。完整字段见 GloveNodePose 与 ExternalGloveFrame。