HumansXDocumentation Center 日本語Website ↗
Knowledge Base › Software › Wuji SDK

Common Data Types

Developer Guide

This page lists all common data type field definitions in the Wuji SDK.

For device-specific data structures, see the product-specific documentation listed below.

Common Types

FrameHeader

Header information for each data frame.

FieldTypeDescription
seqintIncrementing sequence number
timestamp_usintDevice timestamp (microseconds). For the semantics, see Data frame timestamps
frame_idstrCoordinate frame ID (e.g., "l_wrist"), max 32 characters

Vector3 / Vector3F64

Three-dimensional vector. Vector3 uses f32 precision, Vector3F64 uses f64 precision (used for IMU data, ROS compatible).

FieldTypeDescription
xfloatX component
yfloatY component
zfloatZ component

Quaternion

Quaternion representing 3D rotation. Python has a single Quaternion, while C splits it into WujiQuaternionF32 and WujiQuaternionF64 to match the precision each stream carries.

FieldTypeDescription
xfloatX component
yfloatY component
zfloatZ component
wfloatW component

Pose

Position and orientation.

FieldTypeDescription
positionList[float]Position [x, y, z] (meters)
orientationQuaternionRotation quaternion

Handedness

Device handedness enum, used for connecting by handedness. The C constants are WUJI_HANDEDNESS_LEFT (0) and WUJI_HANDEDNESS_RIGHT (1). The two Wuji Hand handedness getters return a raw uint8_t rather than this enum, and their encodings are opposites — see Wuji Hand Data Subscription for the convention.

ValueDescription
Handedness.LeftLeft hand (fourth character of serial number is J)
Handedness.RightRight hand (fourth character of serial number is K)

ImuData

IMU sensor data, following the ROS sensor_msgs/Imu convention.

FieldTypeDescription
headerFrameHeaderFrame header
orientationQuaternionOrientation quaternion
orientation_covariancelist[float]Orientation covariance (length 9). A first element of -1 marks the orientation as unavailable
angular_velocityVector3F64Angular velocity (rad/s)
angular_velocity_covariancelist[float]Angular velocity covariance (length 9)
linear_accelerationVector3F64Linear acceleration (m/s²)
linear_acceleration_covariancelist[float]Linear acceleration covariance (length 9)

Coordinate Transforms

FrameTransform

Single coordinate transform.

FieldTypeDescription
timestamp_usintTimestamp (microseconds)
parent_frame_idstrParent frame
child_frame_idstrChild frame
translationList[float]Translation [x, y, z] (meters)
rotationQuaternionRotation quaternion

FrameTransforms

Collection of coordinate transforms.

FieldTypeDescription
transformsList[FrameTransform]Transform list

Recording Types

For complete usage and code examples, see Data Recording.

TopicRecorder

MCAP recording session configurator. Register channels, then call start() to begin recording.

MethodParametersDescription
__init__()compression: str = "lz4", chunk_size: int = NoneCreate a recorder. Supports "lz4", "zstd", "none"
record()sub: SubscriptionRegister a subscription channel
start()output_path: strStart recording, returns RecordingHandle

RecordingHandle

Recording control handle returned by TopicRecorder.start().

MethodReturnsDescription
pause()—Pause recording
resume()—Resume recording
stop()RecordingSummaryStop recording and return summary
subscribe_metrics()MetricsStreamSubscribe to real-time quality metrics
subscribe_status()StatusStreamSubscribe to recording status updates
subscribe_alerts()AlertStreamSubscribe to quality alerts

RecordingSummary

Recording statistics returned by handle.stop().

FieldTypeDescription
total_framesintTotal frames recorded
file_sizeintMCAP file size in bytes
duration_sfloatRecording duration in seconds
channelslist[ChannelRecordingSummary]Written frame counts by channel
qualityQualitySummaryQuality statistics summary

channels is ordered by channel ID and includes registered channels with no messages. Each ChannelRecordingSummary contains channel_id, channel_name, and frame_count. duration_s includes pauses and buffer draining during stop. It excludes MCAP file finalization, flushing, and waiting for monitor callbacks to exit.

QualityMetrics

Real-time quality metrics (5-second sliding window).

FieldTypeDescription
frame_drop_ratefloatFrame drop rate (0.0–1.0)
frame_jitter_usfloatInter-frame jitter in microseconds
sync_offset_msfloatCross-channel sync offset in milliseconds
sync_ratefloatSync success rate (0.0–1.0)
timestamp_nsintNanosecond timestamp
channelslist[ChannelHealth]Per-channel health details, see ChannelHealth

ChannelHealth

Per-channel health details (elements of channels on QualityMetrics).

FieldTypeDescription
channel_namestrChannel name
channel_idintChannel ID
actual_hzfloatMeasured frame rate (Hz)
drop_ratefloatFrame drop rate for this channel (0.0–1.0)
last_frame_age_msint | NoneTime since the last frame in milliseconds, None if no frame received yet
jitter_usfloatInter-frame jitter in microseconds
is_onlineboolWhether the channel is currently receiving data
last_downtime_msint | NoneDuration of the last downtime in milliseconds, None if never dropped

QualitySummary

Aggregate recording quality statistics.

FieldTypeDescription
total_framesintTotal frames received
dropped_framesintTotal frames dropped
frame_drop_ratefloatDrop rate (0.0–1.0)
avg_sync_offset_msfloatAverage sync offset in milliseconds
max_sync_offset_msfloatMaximum sync offset in milliseconds
sync_ratefloatSync success rate (0.0–1.0)
spc_alert_countintTotal SPC alerts triggered
duration_sfloatRecording duration in seconds

RecordingAlert

Quality alert.

FieldTypeDescription
metricstrName of the metric that triggered the alert
current_valuefloatCurrent measured value
thresholdfloatAlert threshold
messagestrHuman-readable alert message

RecordingStatus

Recording runtime status.

FieldTypeDescription
statestrCurrent state ("recording" or "paused")
frame_countintFrames recorded so far
duration_sfloatElapsed duration in seconds

Device-Specific Types

ProductType definitions
Wuji Hand 2.2 (Beta)Wuji Hand SDK Reference
Wuji Hand 2.1 (Beta)Wuji Hand SDK Reference
Wuji GloveWuji Glove data streams overview

Error Code Categories

The following three categories of error codes are unrelated. A value from one category means nothing in another:

CategoryCarried byHow to decode
Device fault code (u16)error_code_current in Wuji Hand 2 joint diagnostics, the warning / deferred_stop / immediate_stop / fatal fields in ErrorStatus, error_code in the error history, and system_error_code in encoder calibration resultsWujiHand2.describe_error(). See Wuji Hand 2 Joint Diagnostics — Device Fault Codes
Encoder calibration code (u8)enc1_error_code / enc2_error_code in the encoder calibration resultsA calibration-only code that reports why the calibration step failed (enc1 is a small 0–9 enum, enc2 is segmented by calibration stage). Don’t pass it to describe_error(). Read the human-readable name from the enc1_error_name / enc2_error_name read-only properties on the calibration result objects
First-generation Wuji Hand diagnostic bitfield (u32)WujiHandJointDiagnostics.error_code, returned by wuji_hand_get_all_diagnostics()Each bit represents a fault condition. This encoding is independent of Wuji Hand 2 device fault codes. Don’t pass it to WujiHand2.describe_error() or wuji_hand_2_describe_error()

Use Code Values

Device fault codes use the 0xSCNN layout. Don’t decode the hexadecimal digits yourself. Treat each complete code as an opaque identifier for logs, user displays, and bug reports.

Read Decoded Results

In Python, describe_error() returns a dict. Read values by key, such as info["severity"] and info["clear_policy"].

The following fields contain text from the firmware’s error catalog:

FieldMeaning
descError description
causeCause
resolutionSuggested action

Handle None Results

When describe_error(code) returns None, check the original error code:

Error CodeMeaningAction
0No active error. The catalog doesn’t include this valueNo action needed
Nonzero valueThe firmware may contain an error code that the SDK catalog doesn’t yet includeKeep the original value for logs and bug reports

For the differences between SDK exceptions, C return codes, and device fault codes, see the Error Code Index. For device fault-code lookup, see Fault Logs and Error Codes.

C SDK conventions

This section covers C SDK initialization, error handling, memory lifetime, callback constraints, and CMake setup. Device-specific capabilities remain documented on the corresponding product pages.

Initialization and conventions

Initialization

Call once at process start and release at shutdown:

#include "wuji_sdk.h"

if (wuji_init(NULL) != WUJI_STATUS_OK) {
    fprintf(stderr, "init failed: %s\n", wuji_last_error());
    return 1;
}

// ... your code

wuji_shutdown();

Return value taxonomy

  • WujiStatus — most operations (wuji_init / wuji_scan / wuji_connect / opening subscriptions, etc.). WUJI_STATUS_OK means success. On failure, retrieve the per-thread error string via wuji_last_error().
  • int32_t — metadata readers (wuji_dev_serial_number / wuji_dev_device_name) return the number of bytes written.
  • uint8_t — status query wuji_dev_is_connected.
  • void — wuji_shutdown and resource cleanup functions.

Resource cleanup functions

  • wuji_discovered_free — release the device list returned by wuji_scan
  • wuji_dev_release — paired with wuji_connect, release the device handle after disconnecting
  • wuji_sub_close — close the subscription handle

User Info Struct

WujiUserInfo holds seven fields: user_id, display_name, description, external_id, is_default, created_at, and updated_at. wuji_update_user takes a WujiUserUpdate carrying only the fields to change, and setting clear_description / clear_external_id clears the matching value. For the full user management API list, see SDK Users and Calibration Data.

Usage constraints

C SDK users must observe the following constraints to avoid use-after-free, deadlocks, and reading stale error strings.

  • A typed callback’s frame pointer is valid only for the duration of the callback. Heap fields are released after the callback returns. Copy whatever you need to retain inside the callback. Do not store the pointer.
  • Never call wuji_sub_close from inside that subscription’s own callback. close joins the worker thread and will deadlock if called from the callback itself. Close from a different thread.
  • The return value of wuji_last_error() is only valid until the next wuji_* call on the same thread. Copy the message immediately if you need to retain it.
  • END and ERROR are terminal frames — no further data will arrive after them, but you still need to call wuji_sub_close to release the subscription handle.
  • String getters use a two-call query: first call with buf=NULL, buf_len=0 to read *needed (required bytes including NUL), then allocate and call again to fill. Passing an undersized buffer returns WUJI_STATUS_ERR_BUFFER_TOO_SMALL and never truncates.
  • Whole-hand batch reads (get_all_effort_limit / get_all_mit_params) return a flat-20 array plus an online bitmap. Use the WUJI_JOINT_ONLINE(mask, i) macro to check slot validity, otherwise you will read offline-joint placeholders (0 or NaN).
  • The calibration feedback callback runs on the calibration worker thread, and the feedback pointer is valid only during the callback. The SDK guards the session calls made from inside it rather than deadlocking: wuji_glove_calibration_wait and wuji_glove_calibration_try_finish return WUJI_STATUS_ERR_INVALID_ARG, and wuji_glove_calibration_session_free records the reason in wuji_last_error() and skips the release — so the session stays alive and you must free it again after the callback returns. wuji_glove_calibration_cancel is safe to call from the callback. Free the session with wuji_glove_calibration_session_free and the result with wuji_glove_calibration_result_free.
  • WujiUserInfo holds heap strings: free a single struct with wuji_user_info_free, and free an array returned by wuji_list_users with wuji_user_info_array_free.

Python equivalents

The table below maps each C API to its Python counterpart by capability. For full usage of cross-device capabilities and per-device APIs, see the C API Reference.

CapabilityCPython
Initwuji_init(NULL)SdkManager.instance()
Scanwuji_scan(&devs, &count)manager.scan()
Connectwuji_connect(&target, alias, &opts, &dev)manager.connect(…) / manager.auto_connect(…)
Default connect optionswuji_connect_options_default()ConnectOptions()
Device subscribewuji_glove_subscribe_tactile(dev, cb, user, &sub)glove.tactile().subscribe_with_callback(…)
Global subscribewuji_subscribe_tf(cb, user, &sub)manager.tf().subscribe()
Stream output ratewuji_sub_set_rate(sub, hz, &actual)sub.set_rate(hz)
Hand 2 control actionwuji_hand_2_enable(dev, mask)hand.enable(joints=mask)
Hand 2 realtime commandwuji_hand_2_joint_command_publish + wuji_joint_command_publisher_sendhand.joint_command().publish().send([…])
Hand 2 joint state subscribewuji_hand_2_subscribe_joint_stateshand.joint_states().subscribe()
Hand 2 joint diagnostics subscribewuji_hand_2_subscribe_joint_diagnosticshand.joint_diagnostics().subscribe()
Hand 2 IMU subscribewuji_hand_2_subscribe_imuhand.imu().subscribe()
Hand 2 nid and joint index conversionwuji_hand_2_nid_to_joint_index(nid, &index) / wuji_hand_2_joint_index_to_nid(joint_index, &nid)WujiHand2.nid_to_joint_index(nid) / WujiHand2.joint_index_to_nid(joint_index)
Hand 2 error descriptionwuji_hand_2_describe_error(code, &info)WujiHand2.describe_error(code)
Hand 2 flash log exportwuji_hand_2_export_flash_logs + wuji_hand_2_flash_log_export_freehand.export_flash_logs()
Hand connect (USB SN)wuji_hand_connect_sn(sn, alias, &dev)WujiHand.connect_sn(sn, alias)
Hand joint state subscribewuji_hand_subscribe_joint_stateshand.joint_states().subscribe()
Hand realtime commandwuji_hand_joint_command_publish + wuji_hand_joint_command_publisher_sendhand.joint_command().publish().send([…])
Hand realtime controllerwuji_hand_realtime_controller_open / _set_target_position / get_actual*hand.realtime_controller(LowPass(…))
Glove time syncwuji_glove_sync_time(dev, &tsr)glove.sync_time()
Glove hand model pathwuji_glove_get_hand_model_path / wuji_glove_set_hand_model_pathglove.hand_model_path().get() / .set(path)
SDK user managementwuji_create_user / wuji_switch_user / wuji_list_usersmanager.create_user() / switch_user() / list_users()
User data export and importwuji_user_data_export / wuji_user_data_preview / wuji_user_data_importmanager.export_user_data() / preview_user_data() / import_user_data()
Glove hand model calibration (async)wuji_glove_calibration_start + wuji_glove_calibration_try_finishglove.calibrate()
Glove hand model calibration (sync)wuji_glove_calibrateglove.calibrate_blocking()
Glove tactile contact calibration (sync)wuji_glove_calibrate_tactile_blockingglove.calibrate_tactile_blocking()
Disconnectwuji_dev_disconnect + wuji_dev_releasedevice.disconnect()

CMake project example

A complete runnable C project (with CMakeLists.txt plus a subscription callback demo) lives in the examples/c/ directory of the wuji-sdk repo, organized into examples/c/wuji_glove/ (stream output rate control, custom hand model for online IK, SDK user management, and hand model calibration), examples/c/wuji_hand_2/ (joint-state subscriptions, control actions, device info, fingertip tactile data, stream output rate control, flash-log export, opposition replay, and MIT sweep), and examples/c/wuji_hand/ (subscriptions, publishing, grasp loops, and tactile status) subdirectories. See that directory’s README for build instructions. Minimal link:

  • Linux

  • macOS arm64

cc my_app.c -I "${SDK}/include" -L "${SDK}/lib" -lwuji_sdk_c -o my_app
LD_LIBRARY_PATH="${SDK}/lib" ./my_app
cc my_app.c -I "${SDK}/include" -L "${SDK}/lib" \
  -lwuji_sdk_c -Wl,-rpath,"${SDK}/lib" -o my_app
./my_app

Use an absolute path for ${SDK}, the extracted package directory. In CMake, set WUJI_SDK_INCLUDE_DIR to ${SDK}/include, and set WUJI_SDK_LIB to ${SDK}/lib/libwuji_sdk_c.so on Linux or ${SDK}/lib/libwuji_sdk_c.dylib on macOS.

Interface List

Python and C types map one to one with the same field semantics. Naming and memory layout follow each language’s conventions:

TypePythonC
Frame headerFrameHeaderWujiFrameHeader
3D vector (f32)Vector3No standalone struct — f32 triples are inlined as float[3], such as WujiPose.position
3D vector (f64)Vector3F64WujiVector3F64
Rotation quaternionQuaternionWujiQuaternionF32, WujiQuaternionF64
PosePoseWujiPose
Device handednessHandedness.Left, Handedness.RightWUJI_HANDEDNESS_LEFT, WUJI_HANDEDNESS_RIGHT
IMU dataImuDataWujiImuData
Single transformFrameTransformWujiFrameTransform
Transform collectionFrameTransformsWujiFrameTransforms
Recorder and control handleTopicRecorder, RecordingHandleWujiTopicRecorder, WujiRecordingHandle
Recording summary and quality metricsRecordingSummary, QualitySummary, QualityMetrics, ChannelHealth, RecordingAlert, RecordingStatusWujiRecordingSummary, WujiRecordingQualitySummary, WujiRecordingMetrics, WujiRecordingChannelHealth, WujiRecordingAlert, WujiRecordingStatus
Per-channel recording countsChannelRecordingSummaryWujiRecordingChannelSummary
Wuji Hand joint stateHandJointStatesWujiHandJointStates
Wuji Hand joint commandHandJointCommandNo frame struct — send an array of 20 WujiJointCommand entries
Wuji Hand tactile pressure frameTactileGloveFrameWujiTactileGloveFrame
Decoded device fault codeThe dict returned by WujiHand2.describe_error()WujiErrorInfo

Three representation differences stand out. A Python str field is a fixed-length char array in C, such as frame_id[32] and parent_frame_id[32]. A Python list field is a pointer plus a length in C, such as transforms and transforms_len on WujiFrameTransforms. Python has a single Quaternion, while C splits it into WujiQuaternionF32 and WujiQuaternionF64 to match the precision each stream carries. C frame pointers stay valid only for the duration of a subscription callback, so copy anything you need to keep. See the C Interface Reference for the full constraints.