Device discovery & connection
Discover or fix a glove, select one or many, and use a Receiver.
Device discovery & connection
The default configuration discovers the single supported serial glove. To fix a port or serial number, or to run multiple gloves, configure GloveConfig in the matching section below.
Device discovery
To list devices before creating the Sdk, call qnbot::discover_gloves(). The returned
std::vector<qnbot::DiscoveredGlove> contains the serial port, left/right hand, device SN, and
an optional per-device error:
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};
}When the port is occupied by another process, the device is still kept in the result, port is
usable, and the condition is identified by qnbot::GloveDiscoveryErrorCode::port_busy (stable
error code PORT_BUSY). Program logic should test the enum and must not parse the diagnostic
message. The discovery result is a snapshot of the moment of the call; rediscover after
devices are plugged or unplugged. For a complete example, see
discover_gloves.cpp.
Single glove
The single-glove scenario automatically discovers the only connected supported glove:
qnbot::SdkConfig config;
config.devices = {qnbot::GloveConfig{}};
qnbot::Sdk sdk(std::move(config));A single-glove declaration without a configured side still requires exactly one unoccupied candidate. Fixed selection is only needed when automatic discovery cannot work, see Connecting the device.
Two gloves
When connecting one left glove and one right glove at the same time, you only need to declare the
side; there is no need to set connection explicitly:
qnbot::GloveConfig left;
left.side = qnbot::Side::left;
qnbot::GloveConfig right;
right.side = qnbot::Side::right;
qnbot::SdkConfig config;
config.devices = {left, right};The SDK assigns devices uniquely by side; the serial enumeration order does not determine the
left/right data streams. Each directly wired glove is assigned at most once; a supported Receiver
can carry two sources, left and right. SDK creation fails when the directly wired candidates are
missing one side, when multiple candidates exist on the same side, or when the device information
and the discovery result disagree during SDK creation. The behavior when a glove on a Receiver
goes offline during SDK creation is described below. Two gloves on the same side must each
explicitly configure port or serial_number.
When no device locating information is provided, SerialConnection{} uses the automatic
discovery and side assignment described above.
Multiple gloves
When connecting three or more gloves, at least two are on the same side. To select each glove
individually, set a unique name for each entry and use different port or serial_number
values to pin down same-side gloves. name is only used by the application to select a glove and
does not replace device locating information; if the other conditions are already unique, the SDK
does not reject creation merely because name is omitted.
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");No physical glove, or integrating your own device? Both cases can feed external hand frames frame by frame, and they are read through the same paths as a physical glove. See External input for the configuration and frame constraints.
Connecting the device
Sdk construction completes device discovery and identity verification before returning; start() establishes the continuously running connection and data streams, see Lifecycle. Use the connection options below when you need to pin a specific device.
A fixed port or serial number
A fixed deployment can specify the serial port:
qnbot::SerialConnection connection;
connection.port = "/dev/ttyUSB0";
qnbot::GloveConfig device_config{qnbot::Side::right, connection};
device_config.name = "primary";When the SDK can recognize the port as a supported directly wired glove and both port and
side are explicitly provided, the SDK still verifies the device identity first. For older
directly wired gloves that cannot report a device identity, the SDK continues to connect using
the configured serial port and left/right hand, and emits an "identity not verified" warning.
Reconnection after a drop retries only that port and cannot confirm whether the recovered
device is still the same physical glove. Automatic discovery, providing only port, providing
only side, selecting by serial_number, wireless Receivers, and unrecognized port types still
require device identity verification and cannot use this compatibility behavior.
You can also select by USB serial number. An empty SerialConnection{} uses automatic discovery:
qnbot::SerialConnection by_serial;
by_serial.serial_number = "YOUR-SERIAL-NUMBER";When device locating information is set explicitly, auto_discover=true, port and serial_number
are mutually exclusive; baudrate is optional.
Wireless Receiver (experimental)
The Receiver is currently an experimental feature; its stability, support scope, and public behavior may change later, and the current behavior should not be treated as a long-term compatibility commitment.
A supported wireless Receiver uses the same qnbot::GloveConfig and serial port selection
method as a directly wired glove; no Receiver-specific configuration type is needed. One
declaration still represents only one glove source; to connect the left and right hands
automatically, declare qnbot::Side::left and qnbot::Side::right separately, and the SDK can
resolve the gloves on both sides through the same Receiver.
For fixed deployments, the left and right declarations can explicitly select the same Receiver serial port. If the port is actually connected to a directly wired glove, duplicate binding is rejected. A glove on the Receiver that is configured but offline during SDK creation is not added: other online gloves and SDK capabilities that do not depend on that glove can continue to be used, and the offline source and its associated outputs are not added to the current SDK instance. After turning that glove on, the SDK must be recreated; it is not added dynamically to a running instance.
An identity-confirmed Receiver source supports pose, status, Capture, Calibration, Skeleton, and Retargeting. Wireless haptics and undocumented device control capabilities are not currently provided; when these capabilities are needed, use a connection method that the product explicitly supports.
Select and inspect a device
Sdk construction completes device discovery and identity verification before returning. Once
creation succeeds, you can select devices and prepare data reads; continuous callbacks are best
registered before start(). When relying on serial auto-discovery, Sdk construction accesses
the devices; a discovery failure or unmet identity constraints directly makes construction fail.
Direct gloves are allocated when the Sdk is created, as shown below:
Select a device
When only one glove is enabled in the configuration, you can select it directly:
auto glove = sdk.glove();
auto device = glove.device();In multi-glove scenarios, you can select by side:
auto glove = sdk.glove();
auto left = glove.device(qnbot::Side::left);
auto right = glove.device(qnbot::Side::right);- When no device matches,
NotFoundSelectionErroris thrown. - When multiple devices match,
AmbiguousSelectionErroris thrown. candidates()provides the selectable devices, andselector_kind()andselector_value()describe this selection.
Inspect the device
device.get_device_info() returns the verified GloveDeviceInfo snapshot saved during SDK
construction, including canonical_sn, device type, model, firmware version, hand, and hand
source; it does not resend the identity command each time.
Device identifiers serve different purposes:
| Identifier | Source | Purpose |
|---|---|---|
name | GloveConfig::name, optional | The application's own logical name; it can be left empty when the device is unique or can already be distinguished by side; it is recommended for multiple devices on the same side or complex topologies, and is used to select with glove.device(name) |
source_id | GloveDevice::source_id() | A stable routing identifier provided by the SDK for the current source |
canonical_sn | get_device_info().canonical_sn | The canonical SN verified through device identity; the application should not derive it from the port or name |
For legacy firmware connected with an explicit port + side that cannot provide an identity, the SDK does not fabricate these fields;
the call throws UnavailableFeatureError, and capabilities that depend on a verified identity
are unavailable.
GloveDevice's start() and stop() act only on that device. The same-named operations on
Glove act on all configured gloves.