For device-specific data structures, see the product-specific documentation listed below.
Common Types
FrameHeader
Header information for each data frame.Vector3 / Vector3F64
Three-dimensional vector.Vector3 uses f32 precision, Vector3F64 uses f64 precision (used for IMU data, ROS compatible).
Quaternion
Quaternion representing 3D rotation. Python has a singleQuaternion, while C splits it into WujiQuaternionF32 and WujiQuaternionF64 to match the precision each stream carries.
Pose
Position and orientation.Handedness
Device handedness enum, used for connecting by handedness. The C constants areWUJI_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.
ImuData
IMU sensor data, following the ROSsensor_msgs/Imu convention.
Coordinate Transforms
FrameTransform
Single coordinate transform.FrameTransforms
Collection of coordinate transforms.Recording Types
For complete usage and code examples, see Data Recording and Offline Processing.TopicRecorder
MCAP recording session configurator. Register channels, then callstart() to begin recording.
RecordingHandle
Recording control handle returned byTopicRecorder.start().
RecordingSummary
Recording statistics returned byhandle.stop().
QualityMetrics
Real-time quality metrics (5-second sliding window).ChannelHealth
Per-channel health details (elements ofchannels on QualityMetrics).
QualitySummary
Aggregate recording quality statistics.RecordingAlert
Quality alert.RecordingStatus
Recording runtime status.Device-Specific Types
Error Code Categories
The SDK has three unrelated categories of error codes. A value from one category means nothing in another:
Code
0 means no active error and isn’t included in the catalog. describe_error(0) returns None, so no action is needed. If describe_error() returns None for a nonzero code, keep the numeric value in logs and bug reports. This can happen when the firmware contains an error code that the SDK catalog doesn’t yet include.
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:WujiStatus— most operations (wuji_init/wuji_scan/wuji_connect/ opening subscriptions, etc.).WUJI_STATUS_OKmeans success. On failure, retrieve the per-thread error string viawuji_last_error().int32_t— metadata readers (wuji_dev_serial_number/wuji_dev_device_name) return the number of bytes written.uint8_t— status querywuji_dev_is_connected.void—wuji_shutdownand resource cleanup functions.
wuji_discovered_free— release the device list returned bywuji_scanwuji_dev_release— paired withwuji_connect, release the device handle after disconnectingwuji_sub_close— close the subscription handle
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.
Error Code Description
wuji_hand_2_describe_error is a static function (no device connection needed) that decodes a device fault code (from joint_diagnostics’s error_code_current — the same values carried by the error history and calibration results in the Python SDK) into WujiErrorInfo. It accepts device fault codes only. Calibration in the Python SDK also reports a separate encoder-only error byte — that one is a different, unrelated enum and must not be passed in. The WujiHandJointDiagnostics.error_code bitfield from Wuji Hand joint diagnostics (returned by wuji_hand_get_all_diagnostics) must not be passed in either:
WUJI_STATUS_ERR_NOT_FOUND. severity values: Warning / DeferredStop / ImmediateStop / Fatal. clear_policy values: AutoClear / ManualClear / NonClearable.
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
framepointer 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_closefrom inside that subscription’s own callback.closejoins 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 nextwuji_*call on the same thread. Copy the message immediately if you need to retain it. ENDandERRORare terminal frames — no further data will arrive after them, but you still need to callwuji_sub_closeto release the subscription handle.- String getters use a two-call query: first call with
buf=NULL, buf_len=0to read*needed(required bytes including NUL), then allocate and call again to fill. Passing an undersized buffer returnsWUJI_STATUS_ERR_BUFFER_TOO_SMALLand never truncates. - Whole-hand batch reads (
get_all_effort_limit/get_all_mit_params) return a flat-20 array plus an online bitmap. Use theWUJI_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
feedbackpointer is valid only during the callback. The SDK guards the session calls made from inside it rather than deadlocking:wuji_glove_calibration_waitandwuji_glove_calibration_try_finishreturnWUJI_STATUS_ERR_INVALID_ARG, andwuji_glove_calibration_session_freerecords the reason inwuji_last_error()and skips the release — so the session stays alive and you must free it again after the callback returns.wuji_glove_calibration_cancelis safe to call from the callback. Free the session withwuji_glove_calibration_session_freeand the result withwuji_glove_calibration_result_free. WujiUserInfoholds heap strings: free a single struct withwuji_user_info_free, and free an array returned bywuji_list_userswithwuji_user_info_array_free.
Python equivalents
The table below maps each C API to its Python counterpart by capability. For full usage of the cross-device capabilities, see the capability chapters listed at the top of this page. For per-device APIs, see the matching section on this page.| Capability | C | Python |
|---|---|---|
| Init | wuji_init(NULL) | SdkManager.instance() |
| Scan | wuji_scan(&devs, &count) | manager.scan() |
| Connect | wuji_connect(&target, alias, &opts, &dev) | manager.connect(…) / manager.auto_connect(…) |
| Default connect options | wuji_connect_options_default() | ConnectOptions() |
| Device subscribe | wuji_glove_subscribe_tactile(dev, cb, user, &sub) | glove.tactile().subscribe_with_callback(…) |
| Global subscribe | wuji_subscribe_tf(cb, user, &sub) | manager.tf().subscribe() |
| Stream output rate | wuji_sub_set_rate(sub, hz, &actual) | sub.set_rate(hz) |
| Hand 2 control action | wuji_hand_2_enable(dev, mask) | hand.enable(joints=mask) |
| Hand 2 realtime command | wuji_hand_2_joint_command_publish + wuji_joint_command_publisher_send | hand.joint_command().publish().send([…]) |
| Hand 2 joint state subscribe | wuji_hand_2_subscribe_joint_states | hand.joint_states().subscribe() |
| Hand 2 joint diagnostics subscribe | wuji_hand_2_subscribe_joint_diagnostics | hand.joint_diagnostics().subscribe() |
| Hand 2 IMU subscribe | wuji_hand_2_subscribe_imu | hand.imu().subscribe() |
| Hand 2 nid and joint index conversion | wuji_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 description | wuji_hand_2_describe_error(code, &info) | WujiHand2.describe_error(code) |
| Hand 2 flash log export | wuji_hand_2_export_flash_logs + wuji_hand_2_flash_log_export_free | hand.export_flash_logs() |
| Hand connect (USB SN) | wuji_hand_connect_sn(sn, alias, &dev) | WujiHand.connect_sn(sn, alias) |
| Hand joint state subscribe | wuji_hand_subscribe_joint_states | hand.joint_states().subscribe() |
| Hand realtime command | wuji_hand_joint_command_publish + wuji_hand_joint_command_publisher_send | hand.joint_command().publish().send([…]) |
| Hand realtime controller | wuji_hand_realtime_controller_open / _set_target_position / get_actual* | hand.realtime_controller(LowPass(…)) |
| Glove time sync | wuji_glove_sync_time(dev, &tsr) | glove.sync_time() |
| Glove hand model path | wuji_glove_get_hand_model_path / wuji_glove_set_hand_model_path | glove.hand_model_path().get() / .set(path) |
| SDK user management | wuji_create_user / wuji_switch_user / wuji_list_users | manager.create_user() / switch_user() / list_users() |
| User data export and import | wuji_user_data_export / wuji_user_data_preview / wuji_user_data_import | manager.export_user_data() / preview_user_data() / import_user_data() |
| Glove hand model calibration (async) | wuji_glove_calibration_start + wuji_glove_calibration_try_finish | glove.calibrate() |
| Glove hand model calibration (sync) | wuji_glove_calibrate | glove.calibrate_blocking() |
| Glove tactile contact calibration (sync) | wuji_glove_calibrate_tactile_blocking | glove.calibrate_tactile_blocking() |
| Disconnect | wuji_dev_disconnect + wuji_dev_release | device.disconnect() |
CMake project example
A complete runnable C project (withCMakeLists.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:
${SDK} is the extracted tarball root. The CMake project uses -DWUJI_SDK_INCLUDE_DIR and -DWUJI_SDK_LIB to point at the same paths.
Interface List
Python and C types map one to one with the same field semantics. Naming and memory layout follow each language’s conventions:
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.