设备发现与连接
发现与固定手套、单只或多只选择与 Receiver。
设备发现与连接
默认配置可以自动发现唯一支持的串口手套;需要固定端口、序列号或多只手套时,按下面对应的小节配置 GloveConfig。
发现设备
需要在创建 Sdk 前列出设备时,可调用 qnbot::discover_gloves()。返回的
std::vector<qnbot::DiscoveredGlove> 包含串口、左右手、设备 SN 和可选逐设备错误:
const auto devices = qnbot::discover_gloves();
const auto selected = std::find_if(
devices.begin(), devices.end(),
[](const auto& device) { return !device.error; });
if (selected != devices.end() && selected->hand) {
qnbot::SerialConnection connection;
connection.port = selected->port;
qnbot::GloveConfig config{*selected->hand, connection};
}端口被其他进程占用时,该设备仍保留在结果中,port 可用,并通过
qnbot::GloveDiscoveryErrorCode::port_busy(稳定错误码 PORT_BUSY)标识。程序逻辑应判断枚举,不要解析诊断 message。发现结果是调用时刻的快照;设备插拔后应重新发现。完整示例见
discover_gloves.cpp。
单只手套
单手套场景会自动发现唯一连接的受支持手套:
qnbot::SdkConfig config;
config.devices = {qnbot::GloveConfig{}};
qnbot::Sdk sdk(std::move(config));未配置 side 的单手套声明仍要求只有一个未占用候选。只有自动发现不成立时才需要固定选择,见 连接设备。
两只手套
同时连接一只左手套和一只右手套时,只需要声明 side,无需显式设置 connection:
qnbot::GloveConfig left;
left.side = qnbot::Side::left;
qnbot::GloveConfig right;
right.side = qnbot::Side::right;
qnbot::SdkConfig config;
config.devices = {left, right};SDK 按 side 唯一分配设备,串口枚举顺序不会决定左右数据流。每只直连手套最多分配一次;受支持的 Receiver 可以承载左右两个 source。直连候选缺少某一侧、同一侧存在多个候选,或 SDK 创建期间设备信息与发现结果不一致时,SDK 创建失败。Receiver 中手套在 SDK 创建期间离线的行为见下文。两只同侧手套必须分别显式配置 port 或 serial_number。
未提供设备定位信息时,SerialConnection{} 使用上述自动发现和 side 分配。
多只手套
连接三只及以上手套时,至少有两只位于同一侧。如需分别选择每只手套,应为每项配置设置唯一的 name,并使用不同的 port 或 serial_number 固定同侧手套。name 只用于应用选择手套,不替代设备定位信息;如果其他条件已经唯一,SDK 不会仅因省略 name 而拒绝创建。
qnbot::SerialConnection left_primary_connection;
left_primary_connection.port = "/dev/ttyUSB0";
qnbot::GloveConfig left_primary{qnbot::Side::left, left_primary_connection};
left_primary.name = "left-primary";
qnbot::SerialConnection left_backup_connection;
left_backup_connection.port = "/dev/ttyUSB1";
qnbot::GloveConfig left_backup{qnbot::Side::left, left_backup_connection};
left_backup.name = "left-backup";
qnbot::GloveConfig right;
right.side = qnbot::Side::right;
right.name = "right";
qnbot::SdkConfig config;
config.devices = {left_primary, left_backup, right};
qnbot::Sdk sdk(std::move(config));
auto selected = sdk.glove().device("left-primary");没有实体手套,或要接入自研设备? 这两种情况都可以用外部输入逐帧提供手部帧,读取路径与实体手套相同。配置方式与帧约束见 外部输入。
连接设备
Sdk 构造返回前完成设备发现与身份校验,start() 才建立持续运行的连接与数据流,见 生命周期。需要指定具体设备时,用下面的连接方式。
指定端口或序列号
固定部署可以指定串口:
qnbot::SerialConnection connection;
connection.port = "/dev/ttyUSB0";
qnbot::GloveConfig device_config{qnbot::Side::right, connection};
device_config.name = "primary";当 SDK 能将该端口识别为受支持的有线直连手套,且同时显式提供 port 和 side 时,
SDK 仍会优先验证设备身份。对于无法报告设备身份的旧版有线直连手套,SDK 会使用配置的串口和左右手继续连接,并发出“身份未验证”告警。断线恢复只重试该 port,无法确认恢复后是否仍是同一只实体手套。自动发现、只提供 port、只提供 side、按
serial_number 选择、无线 Receiver 以及无法识别端口类型时仍要求设备身份校验,不能使用这一兼容行为。
也可以通过 USB 序列号选择。空的 SerialConnection{} 使用自动发现:
qnbot::SerialConnection by_serial;
by_serial.serial_number = "YOUR-SERIAL-NUMBER";显式设置设备定位信息时,auto_discover=true、port 和 serial_number 互斥;baudrate 可选。
无线 Receiver(实验性功能)
Receiver 当前是实验性功能,稳定性、支持范围和公开行为后续可能变化,不建议把当前行为作为长期兼容承诺。
受支持的无线 Receiver 与直连有线手套使用同一个 qnbot::GloveConfig 和串口选择方式,不需要 Receiver 专用配置类型。一条声明仍只表示一只手套 source;自动连接左右手时,分别声明 qnbot::Side::left 和 qnbot::Side::right,SDK 可以通过同一个 Receiver 解析两侧手套。
固定部署时,左右两条声明可以显式选择同一个 Receiver 串口。若端口实际连接的是直连有线手套,重复绑定会被拒绝。Receiver 中已配置但在 SDK 创建期间离线的手套不会加入:其他在线手套和不依赖该手套的 SDK 功能可以继续使用,离线 source 及其关联输出不会加入当前 SDK 实例。打开该手套后需要重新创建 SDK,不会在运行中的实例里动态加入。
经过身份确认的 Receiver source 支持 pose、status、Capture、Calibration、Skeleton 和 Retargeting。当前不提供无线 haptics 或未公开的设备控制能力;需要这些能力时请使用产品明确支持的连接方式。
选择和查看设备
Sdk 构造在返回前完成设备发现和身份校验。创建成功后即可选择设备和准备数据读取;持续 callback 建议在 start() 前注册。依赖串口自动发现时,Sdk 构造会访问设备;发现失败或身份约束不满足会直接导致构造失败。
直连手套在 Sdk 创建时按下图分配:
选择设备
配置中只有一只启用手套时,可直接选择:
auto glove = sdk.glove();
auto device = glove.device();多手套场景可按 side 选择:
auto glove = sdk.glove();
auto left = glove.device(qnbot::Side::left);
auto right = glove.device(qnbot::Side::right);- 没有匹配设备时抛出
NotFoundSelectionError。 - 匹配多个设备时抛出
AmbiguousSelectionError。 candidates()提供可选设备,selector_kind()和selector_value()描述本次选择。
选中的设备的 start()、stop() 与 health() 作用范围见 核心对象与生命周期。
查看设备
device.get_device_info() 返回 SDK 构造期间保存的已验证 GloveDeviceInfo 快照,包括
canonical_sn、设备类型、型号、固件版本、hand 和 hand 来源,不会每次重新发送身份命令。
设备标识的用途不同:
| 标识 | 来源 | 用途 |
|---|---|---|
name | GloveConfig::name,可选 | 应用自己的逻辑名称;唯一设备或按 side 已能区分时可以不填,同侧多设备或复杂拓扑建议填写,并用 glove.device(name) 选择 |
source_id | GloveDevice::source_id() | SDK 为当前 source 提供的稳定路由标识 |
canonical_sn | get_device_info().canonical_sn | 经过设备身份验证的规范 SN,不应由应用根据端口或 name 推导 |
对显式 port + side 连接且无法提供身份的旧固件,SDK 不会伪造这些字段,调用会抛出
UnavailableFeatureError,依赖已验证身份的能力不可用。