API reference
Object and method summary, plus the data and result models.
API reference
An explicit close() is the primary cleanup method; destruction only provides a non-throwing
last resort.
Glove::close() reclaims subscriptions that are still valid. The application only needs to keep
the corresponding Subscription objects alive; there is no need to unsubscribe them one by one
before the final close. Call subscription.unsubscribe() explicitly only when the owning object
keeps running but a single callback needs to be stopped early.
Do not synchronously call unsubscribe() on, or destroy, that subscription from inside its own
callback.
Finite tasks call Glove::close() when the normal path ends; background mode calls
request_stop() and join() first. Glove::close() stops and closes all configured gloves, and
Sdk::close() closes the remaining capabilities and releases the entire SDK. After a successful
close, repeated calls are a no-op.
The destructors of Subscription, Glove, and Sdk still provide an RAII fallback, but they
cannot replace an explicit close(), because destruction cannot reliably report cleanup
failures. Also do not destroy the last Sdk object inside a callback; leave cleanup to the
application control path outside the callback.
For the full field definitions, see Configuration reference.
Object and method summary
For methods without parameters, the "Parameters, type, and default" column says "None".
Top-level functions
| API | Purpose | Parameters, type, and default | Return value | When to call | Main errors |
|---|---|---|---|---|---|
qnbot::discover_gloves() | View the currently discoverable gloves | None | std::vector<DiscoveredGlove> | Before creating the SDK | Top-level discovery errors; per-port errors are in the result |
Sdk
| API | Purpose | Parameters, type, and default | Return value | When to call | Main errors |
|---|---|---|---|---|---|
Sdk::glove() | Enter the glove capability | None | Glove | SDK not closed | ClosedHandleError, capability unavailable |
Sdk::start() | Start configured capabilities and device data streams | None | void | After preparing to read data | Connection, identity, data stream, or lifecycle errors |
Sdk::update() | Perform one SDK task scheduling pass | None | UpdateResult | Started and no other run mode in use | LifecycleError |
Sdk::run_forever() | Keep advancing SDK scheduling on the current thread | None | void | Started and no other run mode in use | LifecycleError |
Sdk::run_background() | Advance SDK scheduling in the background | None | void | Started and no other run mode in use | LifecycleError, background runtime errors |
Sdk::request_stop() / join() | Request stop and wait for the background run to finish | None | void | During a foreground or background run | LifecycleError, background errors |
Sdk::stop() | Stop running and disconnect devices | None | void | SDK started | Errors during stopping |
Sdk::close() | Finally close the SDK | None | void | When the SDK is no longer used | Errors during closing; the object is invalid after closing |
Sdk::health() | View the health status of the entire SDK | None | Health | SDK not closed | ClosedHandleError |
Glove
| API | Purpose | Parameters, type, and default | Return value | When to call | Main errors |
|---|---|---|---|---|---|
Glove::device() / device(name) / device(side) | Select a configured glove | None, const std::string&, or Side | GloveDevice | After SDK creation | NotFoundSelectionError, AmbiguousSelectionError |
Glove::sync_time(reference_time_ms) | Set one external absolute time reference for every Glove source | double reference_time_ms, a finite Unix-millisecond value | void | Prefer before start(); may be called again while running to resynchronize | InvalidArgumentError, ClosedHandleError, or native synchronization errors |
start() / stop() / close() | Start, stop, or finally close all gloves | None | void | The corresponding lifecycle stage | Connection, lifecycle, or close errors |
update() / run_forever() / run_background() | Advance SDK scheduling | None | UpdateResult / void | Started; choose one of the three methods | LifecycleError, background runtime errors |
request_stop() / join() | Request stop and wait for the background run to finish | None | void | During a foreground or background run | LifecycleError, background errors |
health() | View the health status of all gloves | None | Health | Glove not closed | ClosedHandleError |
GloveDevice
| API | Purpose | Parameters, type, and default | Return value | When to call | Main errors |
|---|---|---|---|---|---|
source_id() | Read the runtime source identifier | None | std::string | SDK not closed | ClosedHandleError |
get_device_info() | Read the verified device information snapshot | None | GloveDeviceInfo | After SDK creation, may be before start | UnavailableFeatureError (identity not verified) |
start() / stop() | Start or stop only the current glove | None | void | When the device needs separate control | Connection, identity, data stream, or lifecycle errors |
pose() / imu() / status() | Read the raw pose, experimental IMU, or device status | None | The corresponding ReadChannel<T> | After SDK creation | Lifecycle, close, or unsupported errors |
skeleton() | Enable and access Skeleton data | None | Skeleton | Must be called before start | LifecycleError, capability unavailable |
Skeleton::joint_angles() / pose() | Read Skeleton joint angles or skeleton nodes | None | The corresponding ReadChannel<T> | After Skeleton is enabled | Owning object closed or capability unavailable |
output() / output(name) | Read the dexterous hand output of the specified target | None or const std::string& | ReadChannel<HandJointCommand> | After SDK creation | Target not found or ambiguous |
haptics() | Obtain the fingertip haptics control entry point | None | StateChannel<Haptics> | After a serial device is selected | Unsupported or rejected for external, wireless, or disconnected |
push_frame(frame) | Submit one frame of data to an external source | const ExternalGloveFrame&, required | GlovePose | External device already started | Parameter, timestamp, or lifecycle errors |
capture_status(package_ids, operator_id) | Check whether manual capture on this device can start | package_ids: const std::vector<std::string>&; operator_id: const std::string&, both required | CaptureReadiness | Before creating a Capture Session | InvalidArgumentError, WorkflowError |
start_capture(package_ids, operator_id, force) | Start manual capture on this device | package_ids and operator_id required; force: bool defaults to false, and true re-completes the capture motions in the current plan | CaptureSession | When ready to start capturing | InvalidArgumentError, WorkflowError |
start_calibration(session, targets) | Start calibration using a completed capture on this device | session: const CaptureSession&, must be completed; targets: non-empty target sequence, both required | CalibrationSession | Capture completed and the Session is still open | Session or target validation errors |
calibration_status(...) | View the calibration status of the specified target | None, name, or TargetName | CalibrationReadiness | After SDK creation | Target not found or ambiguous |
capture_progress() / capture_control() | Read progress or control Capture | None | ReadChannel<CaptureProgress> / CaptureControl | External interaction flow | Lifecycle or control request errors |
calibration_progress(...) | Read the calibration progress of the specified target | None, name, or TargetName | ReadChannel<CalibrationProgress> | During calibration observation | Target not found or ambiguous |
Sdk, Glove, and GloveDevice still provide connect() and disconnect(). connect() is
kept only for compatibility with old code and does not open devices; disconnect() is equivalent
to stop(). New code should use start() and stop() directly.
Lifecycle and scope
| Object | Method | Scope and behavior |
|---|---|---|
Sdk | start() | Connects and starts all enabled devices and capabilities that are not yet closed, in configuration order; states that are already satisfied can be called again |
Sdk | update() | Performs one manual update of the entire SDK and returns a one-shot wait result |
Sdk | run_forever() / run_background() | Runs the entire SDK in foreground or background mode; both modes are mutually exclusive with manual update |
Sdk | request_stop() / join() | Requests the current run loop to stop; join() waits for the background run to finish and reports background errors |
Sdk | stop() | Stops all started capabilities and data streams, then disconnects all connected devices; start() can be called again afterwards |
Sdk | health() | Returns the aggregated health status of all devices and capabilities that are not closed |
Sdk | close() | Requests stop, waits for the run to finish, cleans up subscriptions, and releases all SDK resources; after complete cleanup, repeated calls are a no-op |
Glove | start() / stop() | Acts only on all enabled gloves that are not yet closed |
Glove | update() / run_forever() / run_background() | Handles glove data only; the run mode rules are the same as for Sdk |
Glove | request_stop() / join() / health() | Stops or observes the glove run state without affecting other SDK capabilities |
Glove | close() | Stops and closes all configured gloves; the Sdk itself can still be used for other capabilities that are not closed |
GloveDevice | start() / stop() | Acts only on the selected physical glove; does not change the state of other devices |
GloveDevice | push_frame() | Only allows an external connection to submit one input frame while connected and started |
Data reading and subscriptions
| API | Purpose | Parameters, type, and default | Return value | When to call | Main errors |
|---|---|---|---|---|---|
ReadChannel<T>::latest() | Immediately read the most recent data item | None | std::optional<Sample<T>> | Owning object not closed | Close errors |
ReadChannel<T>::subscribe(callback) | Invoke the callback each time new data arrives | std::function<void(const Sample<T>&)>, required | Subscription | Recommended before start | Parameter or close errors |
ReadChannel<T>::next() | Create a one-shot wait for the next data item | None | NextOperation<T> | While the owning object is running | Cancellation, close, or data stream errors |
StateChannel<T>::set(value) / clear() | Update or clear the haptic setting | const T& / None | void | Device connected and haptics supported | Parameter, rejection, or disconnection errors |
Subscription::unsubscribe() | Stop one callback early | None | void | When the SDK keeps running but the callback is no longer needed | Synchronous cancellation inside the callback is unsafe |
NextOperation<T>::get() / cancel() | Block for data or cancel the wait | None | Sample<T> / void | During a single wait | Cancellation, close, or repeated consumption errors |
Capture/Calibration sessions
| API | Purpose | Parameters, type, and default | Return value | When to call | Main errors |
|---|---|---|---|---|---|
CaptureControl::confirm() / skip() / cancel() | Confirm, skip, or cancel the current Capture request | const std::string& request_id, required | void | After external interaction receives the current request | Empty, expired, or state mismatch |
CaptureControl::retry() | Re-execute one Capture stage | const std::string& stage_id, required | void | When external interaction needs a retry | Empty, unknown, or not currently retryable |
CaptureSession | Control manual capture and read status or results | snapshot(), confirm(), skip(), retry(), cancel(), result(), close() | Snapshot, std::optional<CaptureResult>, or void | While the Session is open | Expired request, invalid stage, close errors |
CalibrationSession | Control calibration and read or wait for results | snapshot(), result(), wait(), cancel(), close() | Snapshot, optional result, or result vector | While the Session is open | Workflow, cancellation, or close errors |
Data and result models
The tables below describe the public fields that public APIs accept or return
directly; std::optional means the field may be absent.
TelemetryMeta
| Field | Type | Description |
|---|---|---|
source | std::string | Source ID that produced the data |
timestamp | double | Data timestamp |
sequence | std::optional<std::uint64_t> | Sequence number provided by the device or data source |
frame_id | std::optional<std::string> | Frame identifier provided by the device or data source |
Sample<T>
| Field | Type | Description |
|---|---|---|
value | T | Current business data |
sequence | std::uint64_t | SDK sequence number, monotonically increasing within the same data category |
source_time | std::optional<double> | Data source time |
observed_at | double | Monotonic time at which the SDK received the data |
Neither source_time nor observed_at is a system calendar time.
DiscoveredGlove and GloveDiscoveryIssue
| Type | Field | Description |
|---|---|---|
DiscoveredGlove | port, hand, sn, error | Candidate port, left/right hand, device SN, and per-port discovery error |
GloveDiscoveryIssue | code, message | Stable error classification and a display description; programs should test code |
GloveDeviceInfo
| Field | Type | Description |
|---|---|---|
canonical_sn | std::string | Canonical SN verified through device identity |
device_type | std::string | Device type |
model | std::string | Device model |
firmware_version | std::string | Firmware version |
hand | Side | Device left/right hand |
hand_source | std::string | Source of the left/right hand information |
GloveNodePose and ExternalGloveFrame
| Type | Field | Type and description |
|---|---|---|
GloveNodePose | position | std::array<double, 3>, 3D position |
GloveNodePose | quaternion_xyzw | std::array<double, 4>, XYZW quaternion |
ExternalGloveFrame | thumb, index, middle, ring, pinky | GloveNodePose, fingertip poses of the five fingers |
ExternalGloveFrame | timestamp_ms | std::optional<double>, preferred optional millisecond input; when omitted, the current shared time reference is used; see Timestamps & external time sync for the time semantics |
ExternalGloveFrame | timestamp_sec | std::optional<double>, deprecated compatibility input; multiplied by 1000 and mutually exclusive with timestamp_ms |
GloveFeaturePayload
| Field | Type | Description |
|---|---|---|
glove_id | std::string | Glove data identifier |
timestamp_ms | double | Device data time, in milliseconds |
root_pose | GloveNodePose | Hand root node pose |
fingertip_world / fingertip_local | std::map<GloveFinger, GloveNodePose> | World poses of the five fingers and local poses relative to the root node |
hand_side | Side | Left/right hand reported in the frame |
finger_names | std::vector<GloveFinger> | Order of the fingers included in the current frame |
raw_valid_mask / held_mask | std::map<GloveFinger, bool> | Raw data validity and whether the previous valid value is held |
quality_flags | std::vector<std::string> | Quality markers of the current frame |
GlovePose
| Field | Type | Description |
|---|---|---|
meta | TelemetryMeta | Source, time, and frame identifier |
payload | GloveFeaturePayload | Root node, five-finger poses, and validity information |
quality | std::map<std::string, Value> | Extensible quality information |
GloveImuPayload
| Field | Type | Description |
|---|---|---|
valid | bool | Whether the current raw counts are valid |
gyroscope_raw | std::array<std::int16_t, 3> | Three-axis gyroscope raw counts |
accelerometer_raw | std::array<std::int16_t, 3> | Three-axis accelerometer raw counts |
GloveImu
| Field | Type | Description |
|---|---|---|
meta | TelemetryMeta | Source, time, and frame identifier |
payload | GloveImuPayload | valid, three-axis gyroscope_raw, and three-axis accelerometer_raw |
quality | std::map<std::string, Value> | Extensible quality information |
HandJointCommand
| Field | Type | Description |
|---|---|---|
target | std::string | Target identifier |
joints | std::map<std::string, double> | Mapping from joint names to target positions |
timestamp | double | Output timestamp |
source | std::optional<std::string> | Source ID that produced the output |
metadata | std::map<std::string, Value> | Additional algorithm information |
Skeleton fixed joints
When coming from skeleton().joint_angles(), joints always contains the following 25 active
joints. The <side> in the names is replaced with left or right; read by joint name and do
not treat the ordering of the std::map as the native index.
| Index | Joint name |
|---|---|
| 0 | <side>_thumb_cmc_abduction |
| 1 | <side>_thumb_cmc_flexion |
| 2 | <side>_thumb_cmc_opposition |
| 3 | <side>_thumb_mcp_abduction |
| 4 | <side>_thumb_mcp_flexion |
| 5 | <side>_thumb_ip_flexion |
| 6 | <side>_index_mcp_abduction |
| 7 | <side>_index_mcp_flexion |
| 8 | <side>_index_pip_flexion |
| 9 | <side>_index_dip_flexion |
| 10 | <side>_middle_mcp_abduction |
| 11 | <side>_middle_mcp_flexion |
| 12 | <side>_middle_pip_flexion |
| 13 | <side>_middle_dip_flexion |
| 14 | <side>_ring_cmc_cup |
| 15 | <side>_ring_mcp_abduction |
| 16 | <side>_ring_mcp_flexion |
| 17 | <side>_ring_pip_flexion |
| 18 | <side>_ring_dip_flexion |
| 19 | <side>_little_cmc_opposition |
| 20 | <side>_little_cmc_cup |
| 21 | <side>_little_mcp_abduction |
| 22 | <side>_little_mcp_flexion |
| 23 | <side>_little_pip_flexion |
| 24 | <side>_little_dip_flexion |
HandSkeletonPose
| Field | Type | Description |
|---|---|---|
timestamp_ms | double | Skeleton output time, in milliseconds |
hand_side | Side | Left/right hand |
coordinate_frame | std::string | Currently wrist_local |
names | std::vector<std::string> | 25 node names |
positions_local | std::vector<std::array<double, 3>> | 25 local positions |
orientations_local_xyzw | std::vector<std::array<double, 4>> | 25 local XYZW quaternions |
Haptics
| Field | Type | Description |
|---|---|---|
strengths | std::map<GloveFinger, std::int32_t> | Mapping from fingers to 0..100 haptic strength; may be empty; fingers can be thumb, index, middle, ring, pinky |
GloveStatus
| Field | Type | Description |
|---|---|---|
device_type | std::string | Device type |
connected / stale | bool | Whether connected and whether the data is stale |
timestamp | double | Status timestamp |
last_error | std::optional<std::string> | Most recent device error |
reconnect_count | std::uint64_t | Number of successful recoveries |
fields | std::map<std::string, Value> | Additional status related to the device type |
Health
| Field | Type | Description |
|---|---|---|
ok | bool | Whether the current aggregate status is healthy |
warning_count / error_count | std::uint64_t | Cumulative warning and error counts |
devices | std::map<std::string, DeviceHealth> | Mapping from source ID to device health summary |
last_error | std::optional<std::string> | Most recent SDK error |
runtime_overrun | bool | Whether SDK scheduling has ever overrun |
topic_callback_error | bool | Whether an unhandled exception has ever occurred in an SDK data processing callback |
DeviceHealth contains connected: bool, stale: bool, and
last_error: std::optional<std::string>.
CalibrationReadiness and UpdateResult
| Type | Field or method | Type and description |
|---|---|---|
CalibrationReadiness | state | CalibrationReadinessState: not_required, ready, or needs_calibration |
CalibrationReadiness | operator_id | std::string, the wearer identifier used for this determination |
UpdateResult | tick() | std::uint64_t, the current scheduling sequence number |
UpdateResult | ran_task_count() | std::uint64_t, the number of tasks executed this time |
UpdateResult | has_next_task() | bool, whether more tasks remain |
UpdateResult | sleep() | SleepResult, waits for the next task to become due; each result can be called only once |
Capture models
| Type | Field | Type and description |
|---|---|---|
CapturePlanStage | stage_id, prompt | std::string, stage identifier and action prompt |
required_sample_count, optional | std::uint64_t, bool, required sample count and whether it can be skipped | |
CapturePlan | package_ids, stages | std::vector<std::string>, std::vector<CapturePlanStage>, algorithm packages and stage order |
CaptureStageReadiness | stage_id, required_sample_count, state | Stage identifier, required sample count, and reusable / needs_capture state |
CaptureReadiness | state, plan, stages | Overall readiness state, plan, and per-stage readiness |
CaptureStageProgress | stage_id, prompt, optional | Current stage identifier, action prompt, and whether it can be skipped |
state, origin | CaptureStageState, CaptureStageOrigin, stage state and data origin | |
collected_sample_count, required_sample_count | std::uint64_t, collected sample count and required sample count | |
request_id | std::optional<std::string>, current control request identifier | |
CaptureFailure | code, message | std::string, stable failure code and display description |
CaptureProgress | session_id, session_state, failure | Session identifier, state, and optional failure information |
source_id, side, operator_id, stage | Source, left/right hand, wearer, and current stage progress | |
CaptureSessionSnapshot | side, plan, state | Left/right hand, plan, and Session state |
current_stage, request_id | Current stage and request identifier, both std::optional<std::string> | |
collected_sample_count, required_sample_count | std::uint64_t, sampling progress of the current stage | |
remaining_stages, stage_progress, allowed_operations | Remaining stages, complete stage progress, and the currently allowed control operations | |
next_action, failure | Next-step prompt and optional failure information | |
CaptureStageSamples | stage_id, frame_count | Stage identifier and final frame count |
CaptureResult | operator_id, side, created_at, stage_samples | Wearer, left/right hand, creation time, and per-stage capture summary |
CaptureReadiness
capture_status(package_ids, operator_id) returns the overall readiness, the capture plan, and the per-stage readiness before a Capture Session is created.
| Field | Type | Description |
|---|---|---|
state | CaptureReadinessState | not_required, ready, or needs_capture |
plan | CapturePlan | The resolved capture plan |
stages | std::vector<CaptureStageReadiness> | Per-stage readiness |
Calibration models
| Type | Field | Type and description |
|---|---|---|
CalibrationJobFailure | code, message | std::string, stable failure code and display description |
CalibrationJobProgress | target_id | std::string, target identifier |
state | CalibrationJobState: pending, running, completed, failed, or cancelled | |
failure | std::optional<CalibrationJobFailure>, current failure information | |
CalibrationProgress | session_id, source_id, job | Session identifier, source ID, and current target progress |
CalibrationSessionSnapshot | state, jobs | Session state and progress ordered by target |
CalibrationResult | record_id, source_id, target_id, created_at | Record ID, source, target, and result creation time |