> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wuji.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# 通用数据类型

本页列出 Wuji SDK 中所有通用数据类型的字段定义。

> [!NOTE]
>
> 各设备特定的数据结构请参阅[下方对应的产品文档](#设备专属类型)。

## 通用类型

### FrameHeader

每帧数据的头部信息。

| 字段 | 类型 | 说明 |
| - | - | - |
| `seq` | `int` | 递增序列号 |
| `timestamp_us` | `int` | 设备时间戳（微秒），含义见[数据帧时间戳](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/time-sync.md#数据帧时间戳) |
| `frame_id` | `str` | 坐标系 ID（如 `"l_wrist"`），最大 32 字符 |

### Vector3 / Vector3F64

三维向量。`Vector3` 使用 f32 精度，`Vector3F64` 使用 f64 精度（用于 IMU 数据，ROS 兼容）。

| 字段 | 类型 | 说明 |
| - | - | - |
| `x` | `float` | X 分量 |
| `y` | `float` | Y 分量 |
| `z` | `float` | Z 分量 |

### Quaternion

旋转四元数。Python 统一为 `Quaternion`，C 按数据流的实际精度分为 `WujiQuaternionF32` 与 `WujiQuaternionF64`。

| 字段 | 类型 | 说明 |
| - | - | - |
| `x` | `float` | X 分量 |
| `y` | `float` | Y 分量 |
| `z` | `float` | Z 分量 |
| `w` | `float` | W 分量 |

### Pose

位姿，包含位置和朝向。

| 字段 | 类型 | 说明 |
| - | - | - |
| `position` | `List[float]` | 位置 \[x, y, z]（米） |
| `orientation` | [Quaternion](#quaternion) | 旋转四元数 |

### Handedness

设备手性枚举，用于[按手性连接](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/device-connection.md)。C 侧的等价常量是 `WUJI_HANDEDNESS_LEFT`（`0`）与 `WUJI_HANDEDNESS_RIGHT`（`1`）。Wuji Hand 的两个 handedness 读取接口返回原始 `uint8_t` 而非该枚举，且两者编码彼此相反，取值约定见 [Wuji Hand 数据订阅](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/data-subscription.md)。

| 值 | 说明 |
| - | - |
| `Handedness.Left` | 左手（序列号第 4 位为 `J`） |
| `Handedness.Right` | 右手（序列号第 4 位为 `K`） |

### ImuData

IMU 传感器数据，遵循 ROS `sensor_msgs/Imu` 约定。

| 字段 | 类型 | 说明 |
| - | - | - |
| `header` | [FrameHeader](#frameheader) | 帧头 |
| `orientation` | [Quaternion](#quaternion) | 朝向四元数 |
| `orientation_covariance` | `list[float]` | 朝向协方差（长度 9），首元素为 `-1` 表示朝向不可用 |
| `angular_velocity` | [Vector3F64](#vector3-/-vector3f64) | 角速度（rad/s） |
| `angular_velocity_covariance` | `list[float]` | 角速度协方差（长度 9） |
| `linear_acceleration` | [Vector3F64](#vector3-/-vector3f64) | 线加速度（m/s²） |
| `linear_acceleration_covariance` | `list[float]` | 线加速度协方差（长度 9） |

## 坐标变换

### FrameTransform

单个坐标变换。

| 字段 | 类型 | 说明 |
| - | - | - |
| `timestamp_us` | `int` | 时间戳（微秒） |
| `parent_frame_id` | `str` | 父坐标系 |
| `child_frame_id` | `str` | 子坐标系 |
| `translation` | `List[float]` | 平移 \[x, y, z]（米） |
| `rotation` | [Quaternion](#quaternion) | 旋转四元数 |

### FrameTransforms

坐标变换集合。

| 字段 | 类型 | 说明 |
| - | - | - |
| `transforms` | `List[FrameTransform]` | 变换列表 |

## 录制类型

完整用法和代码示例详见 [数据录制](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/data-recording.md)。

### TopicRecorder

MCAP 录制会话配置器。注册通道后调用 `start()` 开始录制。

| 方法 | 参数 | 说明 |
| - | - | - |
| `__init__()` | `compression: str = "lz4"`, `chunk_size: int = None` | 创建录制器，支持 `"lz4"`、`"zstd"`、`"none"` |
| `record()` | `sub: Subscription` | 注册订阅通道到录制器 |
| `start()` | `output_path: str` | 开始录制，返回 `RecordingHandle` |

### RecordingHandle

录制控制句柄，由 `TopicRecorder.start()` 返回。

| 方法 | 返回值 | 说明 |
| - | - | - |
| `pause()` | — | 暂停录制 |
| `resume()` | — | 恢复录制 |
| `stop()` | `RecordingSummary` | 停止录制，返回统计摘要 |
| `subscribe_metrics()` | `MetricsStream` | 订阅实时质量指标流 |
| `subscribe_status()` | `StatusStream` | 订阅录制状态流 |
| `subscribe_alerts()` | `AlertStream` | 订阅质量告警流 |

### RecordingSummary

录制统计摘要，由 `handle.stop()` 返回。

| 字段 | 类型 | 说明 |
| - | - | - |
| `total_frames` | `int` | 总帧数 |
| `file_size` | `int` | MCAP 文件大小（字节） |
| `duration_s` | `float` | 录制时长（秒） |
| `channels` | `list[ChannelRecordingSummary]` | 各通道写入帧数 |
| `quality` | `QualitySummary` | 质量统计摘要 |

`channels` 按通道 ID 排序，包含已注册但未收到消息的通道。每项 `ChannelRecordingSummary` 包含 `channel_id`、`channel_name` 和 `frame_count`。`duration_s` 包含暂停时间和停止时排空录制缓冲的时间，不包含 MCAP 文件收尾、刷新及等待监控回调退出的时间。

### QualityMetrics

实时质量指标（5 秒滑动窗口）。

| 字段 | 类型 | 说明 |
| - | - | - |
| `frame_drop_rate` | `float` | 丢帧率（0.0\~1.0） |
| `frame_jitter_us` | `float` | 帧间抖动（微秒） |
| `sync_offset_ms` | `float` | 跨通道同步偏差（毫秒） |
| `sync_rate` | `float` | 同步成功率（0.0\~1.0） |
| `timestamp_ns` | `int` | 纳秒时间戳 |
| `channels` | `list[ChannelHealth]` | 每通道健康明细，见 [ChannelHealth](#channelhealth) |

### ChannelHealth

单通道健康明细（[QualityMetrics](#qualitymetrics) 的 `channels` 元素）。

| 字段 | 类型 | 说明 |
| - | - | - |
| `channel_name` | `str` | 通道名 |
| `channel_id` | `int` | 通道 ID |
| `actual_hz` | `float` | 实测帧率（Hz） |
| `drop_rate` | `float` | 该通道丢帧率（0.0\~1.0） |
| `last_frame_age_ms` | `int \| None` | 距最近一帧的毫秒数，尚未收到帧时为 `None` |
| `jitter_us` | `float` | 帧间抖动（微秒） |
| `is_online` | `bool` | 通道当前是否在收数 |
| `last_downtime_ms` | `int \| None` | 最近一次断流时长（毫秒），从未断流为 `None` |

### QualitySummary

录制质量汇总统计。

| 字段 | 类型 | 说明 |
| - | - | - |
| `total_frames` | `int` | 总帧数 |
| `dropped_frames` | `int` | 丢失帧数 |
| `frame_drop_rate` | `float` | 丢帧率（0.0\~1.0） |
| `avg_sync_offset_ms` | `float` | 平均同步偏差（毫秒） |
| `max_sync_offset_ms` | `float` | 最大同步偏差（毫秒） |
| `sync_rate` | `float` | 同步成功率（0.0\~1.0） |
| `spc_alert_count` | `int` | SPC 告警次数 |
| `duration_s` | `float` | 录制时长（秒） |

### RecordingAlert

质量告警。

| 字段 | 类型 | 说明 |
| - | - | - |
| `metric` | `str` | 触发告警的指标名称 |
| `current_value` | `float` | 当前测量值 |
| `threshold` | `float` | 告警阈值 |
| `message` | `str` | 可读的告警信息 |

### RecordingStatus

录制运行状态。

| 字段 | 类型 | 说明 |
| - | - | - |
| `state` | `str` | 当前状态（`"recording"` 或 `"paused"`） |
| `frame_count` | `int` | 已录制帧数 |
| `duration_s` | `float` | 已用时长（秒） |

## 设备专属类型

| 产品 | 类型定义 |
| - | - |
| Wuji Hand 2.2 (Beta) | [Wuji Hand SDK 接口参考](https://docs.wuji.tech/docs/zh/wuji-hand/latest/sdk-reference.md#数据类型) |
| Wuji Hand 2.1 (Beta) | [Wuji Hand SDK 接口参考](https://docs.wuji.tech/docs/zh/wuji-hand/beta1/sdk-reference.md#数据类型) |
| Wuji Glove | [Wuji Glove 数据流概览](https://docs.wuji.tech/docs/zh/wuji-glove/latest/sdk-data-reference/index.md) |

## 错误码分类

以下三类错误码互不相通，数值不能跨类解读：

| 类别 | 出现位置 | 解码方式 |
| - | - | - |
| 设备故障码（`u16`） | Wuji Hand 2 关节诊断的 `error_code_current`、`ErrorStatus` 的 `warning` / `deferred_stop` / `immediate_stop` / `fatal`、错误历史记录的 `error_code`、编码器标定结果的 `system_error_code` | `WujiHand2.describe_error()`，见 [Wuji Hand 2 关节诊断 — 设备故障码](https://docs.wuji.tech/docs/zh/wuji-hand/latest/sdk-reference/diagnostics.md#设备故障码) |
| 编码器标定码（`u8`） | 编码器标定结果的 `enc1_error_code` / `enc2_error_code` | 标定专用错误码，表示该次标定步骤的失败原因（enc1 是 0–9 的小枚举，enc2 按标定阶段分段编码），不可传 `describe_error()`。可读名称用标定结果对象的 `enc1_error_name` / `enc2_error_name` 只读属性获取 |
| 一代 Wuji Hand 诊断位字段（`u32`） | `wuji_hand_get_all_diagnostics()` 返回的 `WujiHandJointDiagnostics.error_code` | 每位表示一种故障，与 Wuji Hand 2 设备故障码采用不同编码。不可传给 `WujiHand2.describe_error()` 或 `wuji_hand_2_describe_error()` |

**码值使用**

设备故障码采用 `0xSCNN` 布局。不要自行拆解十六进制位，应把完整码值作为不透明标识，用于记录日志、展示给用户或写入故障报告。

**读取解码结果**

Python 的 `describe_error()` 返回 `dict`，按 key 读取，例如 `info["severity"]`、`info["clear_policy"]`。

以下字段的文案来自固件码表：

| 字段 | 含义 |
| - | - |
| `desc` | 错误描述 |
| `cause` | 触发原因 |
| `resolution` | 处理方法 |

**处理 `None` 返回值**

当 `describe_error(code)` 返回 `None` 时，按原始错误码判断：

| 错误码 | 含义 | 处理方式 |
| - | - | - |
| `0` | 当前无故障，码表不包含该值 | 无需处理 |
| 非零值 | 可能是固件包含 SDK 码表尚未收录的错误码 | 保留原始数值，用于日志和故障报告 |

SDK 异常、C 返回码与设备侧码值的区别见 [错误码索引](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/appendix.md#错误码索引)。设备故障码的查询见 [故障日志与错误码](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/device-fault-logs.md#查询错误码)。

## C SDK 通用约定

本节补充 C SDK 的初始化、错误处理、内存生命周期、回调约束和 CMake 构建约定。具体设备能力仍在对应产品页面中说明。

## 初始化与约定

**初始化**

进程级初始化一次，结束时释放：

```c theme={null}
#include "wuji_sdk.h"

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

// ... 业务逻辑

wuji_shutdown();
```

**返回值分类**

* `WujiStatus` — 多数操作（`wuji_init` / `wuji_scan` / `wuji_connect` / 订阅打开等），`WUJI_STATUS_OK` 表示成功，失败时通过 `wuji_last_error()` 获取当前线程错误描述。
* `int32_t` — 元信息读取（`wuji_dev_serial_number` / `wuji_dev_device_name`）返回写入字节数。
* `uint8_t` — 状态查询 `wuji_dev_is_connected`。
* `void` — `wuji_shutdown` 与资源释放函数。

**资源释放函数**

* `wuji_discovered_free` — `wuji_scan` 后释放设备列表
* `wuji_dev_release` — 与 `wuji_connect` 配套，断开后释放设备句柄
* `wuji_sub_close` — 关闭订阅句柄

**用户信息结构体**

`WujiUserInfo` 含 7 个字段：`user_id`、`display_name`、`description`、`external_id`、`is_default`、`created_at`、`updated_at`。`wuji_update_user` 通过 `WujiUserUpdate` 只传要改的字段，置位 `clear_description` / `clear_external_id` 可清空对应值。用户管理的完整接口清单见 [SDK 用户与标定数据](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/device-params.md#sdk-用户管理)。

## 使用约束

C SDK 用户必须遵守以下约束，否则会出现 use-after-free、死锁或读到失效错误描述：

* typed 回调的 frame 指针仅在回调期间有效，返回后堆字段即被释放。需要保留的数据必须在回调内拷贝出来，不得保存指针。
* 不要在订阅自身的回调里调 `wuji_sub_close`。`close` 会 join worker 线程，在自身回调中调用必死锁。请在外部线程上 close。
* `wuji_last_error()` 返回值仅在同线程下一次 `wuji_*` 调用前有效。需要保留的错误描述应立即拷贝。
* `END` / `ERROR` 是终止帧，回调收到这两类帧后流不再有新数据，但仍需调用 `wuji_sub_close` 释放订阅句柄。
* 字符串 getter 使用两步查询：先用 `buf=NULL, buf_len=0` 获取 `*needed`（所需字节，含 NUL），再分配缓冲第二次调用填充。直接传不足缓冲会返回 `WUJI_STATUS_ERR_BUFFER_TOO_SMALL`，不做截断。
* 整手批量读（`get_all_effort_limit` / `get_all_mit_params`）返回 flat-20 数组 + 在线 bitmap，用 `WUJI_JOINT_ONLINE(mask, i)` 宏判断槽位是否有效，否则读到离线关节的占位值（0 或 NaN）。
* 标定反馈回调在标定 worker 线程触发，`feedback` 指针仅回调期间有效。回调内调用 session 接口不会死锁，SDK 会拦截：`wuji_glove_calibration_wait` 与 `wuji_glove_calibration_try_finish` 返回 `WUJI_STATUS_ERR_INVALID_ARG`，`wuji_glove_calibration_session_free` 把原因记录到 `wuji_last_error()` 并跳过这次释放——session 仍然存活，必须在回调返回后再释放一次。`wuji_glove_calibration_cancel` 可以在回调内安全调用。session 使用完毕后调用 `wuji_glove_calibration_session_free`，标定结果使用完毕后调用 `wuji_glove_calibration_result_free`。
* `WujiUserInfo` 持堆字符串：单个结构用 `wuji_user_info_free`，`wuji_list_users` 返回的数组用 `wuji_user_info_array_free`。

## Python 接口对照

下表按功能列出 C 与 Python 的对应接口。跨设备能力与设备专属接口的完整用法见 [C 接口参考](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/c-sdk-reference.md)。

<table>
  <thead>
    <tr><th>功能</th><th>C</th><th>Python</th></tr>
  </thead>

  <tbody>
    <tr><td>初始化</td><td>`wuji_init(NULL)`</td><td>`SdkManager.instance()`</td></tr>
    <tr><td>扫描</td><td>`wuji_scan(&devs, &count)`</td><td>`manager.scan()`</td></tr>
    <tr><td>连接</td><td>`wuji_connect(&target, alias, &opts, &dev)`</td><td>`manager.connect(...)` / `manager.auto_connect(...)`</td></tr>
    <tr><td>连接选项默认值</td><td>`wuji_connect_options_default()`</td><td>`ConnectOptions()`</td></tr>
    <tr><td>设备订阅</td><td>`wuji_glove_subscribe_tactile(dev, cb, user, &sub)`</td><td>`glove.tactile().subscribe_with_callback(...)`</td></tr>
    <tr><td>全局订阅</td><td>`wuji_subscribe_tf(cb, user, &sub)`</td><td>`manager.tf().subscribe()`</td></tr>
    <tr><td>订阅流输出率</td><td>`wuji_sub_set_rate(sub, hz, &actual)`</td><td>`sub.set_rate(hz)`</td></tr>
    <tr><td>Hand 2 控制动作</td><td>`wuji_hand_2_enable(dev, mask)`</td><td>`hand.enable(joints=mask)`</td></tr>
    <tr><td>Hand 2 实时指令</td><td>`wuji_hand_2_joint_command_publish` + `wuji_joint_command_publisher_send`</td><td>`hand.joint_command().publish().send([...])`</td></tr>
    <tr><td>Hand 2 关节状态订阅</td><td>`wuji_hand_2_subscribe_joint_states`</td><td>`hand.joint_states().subscribe()`</td></tr>
    <tr><td>Hand 2 关节诊断订阅</td><td>`wuji_hand_2_subscribe_joint_diagnostics`</td><td>`hand.joint_diagnostics().subscribe()`</td></tr>
    <tr><td>Hand 2 IMU 订阅</td><td>`wuji_hand_2_subscribe_imu`</td><td>`hand.imu().subscribe()`</td></tr>
    <tr><td>Hand 2 nid 与关节索引换算</td><td>`wuji_hand_2_nid_to_joint_index(nid, &index)` / `wuji_hand_2_joint_index_to_nid(joint_index, &nid)`</td><td>`WujiHand2.nid_to_joint_index(nid)` / `WujiHand2.joint_index_to_nid(joint_index)`</td></tr>
    <tr><td>Hand 2 错误码描述</td><td>`wuji_hand_2_describe_error(code, &info)`</td><td>`WujiHand2.describe_error(code)`</td></tr>
    <tr><td>Hand 2 Flash 日志导出</td><td>`wuji_hand_2_export_flash_logs` + `wuji_hand_2_flash_log_export_free`</td><td>`hand.export_flash_logs()`</td></tr>
    <tr><td>Hand 连接（USB SN）</td><td>`wuji_hand_connect_sn(sn, alias, &dev)`</td><td>`WujiHand.connect_sn(sn, alias)`</td></tr>
    <tr><td>Hand 关节状态订阅</td><td>`wuji_hand_subscribe_joint_states`</td><td>`hand.joint_states().subscribe()`</td></tr>
    <tr><td>Hand 实时指令</td><td>`wuji_hand_joint_command_publish` + `wuji_hand_joint_command_publisher_send`</td><td>`hand.joint_command().publish().send([...])`</td></tr>
    <tr><td>Hand 实时控制器</td><td>`wuji_hand_realtime_controller_open` / `_set_target_position` / `get_actual*`</td><td>`hand.realtime_controller(LowPass(...))`</td></tr>
    <tr><td>Glove 时间同步</td><td>`wuji_glove_sync_time(dev, &tsr)`</td><td>`glove.sync_time()`</td></tr>
    <tr><td>Glove 手部模型路径</td><td>`wuji_glove_get_hand_model_path` / `wuji_glove_set_hand_model_path`</td><td>`glove.hand_model_path().get()` / `.set(path)`</td></tr>
    <tr><td>SDK 用户管理</td><td>`wuji_create_user` / `wuji_switch_user` / `wuji_list_users`</td><td>`manager.create_user()` / `switch_user()` / `list_users()`</td></tr>
    <tr><td>用户数据导入导出</td><td>`wuji_user_data_export` / `wuji_user_data_preview` / `wuji_user_data_import`</td><td>`manager.export_user_data()` / `preview_user_data()` / `import_user_data()`</td></tr>
    <tr><td>Glove 手部模型标定（异步）</td><td>`wuji_glove_calibration_start` + `wuji_glove_calibration_try_finish`</td><td>`glove.calibrate()`</td></tr>
    <tr><td>Glove 手部模型标定（同步）</td><td>`wuji_glove_calibrate`</td><td>`glove.calibrate_blocking()`</td></tr>
    <tr><td>Glove 触觉接触标定（同步）</td><td>`wuji_glove_calibrate_tactile_blocking`</td><td>`glove.calibrate_tactile_blocking()`</td></tr>
    <tr><td>断开</td><td>`wuji_dev_disconnect` + `wuji_dev_release`</td><td>`device.disconnect()`</td></tr>
  </tbody>
</table>

## CMake 工程示例

完整可运行 C 工程（含 `CMakeLists.txt` + 订阅回调示例）见 [wuji-sdk 仓库的 examples/c/ 目录](https://github.com/wuji-technology/wuji-sdk/blob/main/examples/c/README.md)，按设备分别存放在 `examples/c/wuji_glove/`（设置订阅流输出率、在线 IK 自定义手部模型、SDK 用户管理与手部模型标定）、`examples/c/wuji_hand_2/`（订阅关节状态、控制动作、设备信息、[指尖触觉数据](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/wuji-hand-2-tactile.md)、设置订阅流输出率、Flash 日志导出、对掌回放与 MIT 扫频）与 `examples/c/wuji_hand/`（订阅、发布、抓握循环与触觉状态）子目录，构建步骤参见该目录 README。最小链接方式：

> [tab] Linux
>
> ```bash theme={null}
> cc my_app.c -I "${SDK}/include" -L "${SDK}/lib" -lwuji_sdk_c -o my_app
> LD_LIBRARY_PATH="${SDK}/lib" ./my_app
> ```

> [tab] macOS arm64
>
> ```bash theme={null}
> cc my_app.c -I "${SDK}/include" -L "${SDK}/lib" \
>   -lwuji_sdk_c -Wl,-rpath,"${SDK}/lib" -o my_app
> ./my_app
> ```

`${SDK}` 使用发行包解压目录的绝对路径。CMake 项目将 `WUJI_SDK_INCLUDE_DIR` 设为 `${SDK}/include`，将 `WUJI_SDK_LIB` 设为 `${SDK}/lib/libwuji_sdk_c.so`（Linux）或 `${SDK}/lib/libwuji_sdk_c.dylib`（macOS）。

## 接口清单

Python 与 C 的类型一一对应，字段语义相同，命名与内存表示按各自语言习惯：

| 类型 | Python | C |
| - | - | - |
| 帧头 | `FrameHeader` | `WujiFrameHeader` |
| 三维向量（f32） | `Vector3` | 无独立结构，f32 三分量按 `float[3]` 内联，如 `WujiPose.position` |
| 三维向量（f64） | `Vector3F64` | `WujiVector3F64` |
| 旋转四元数 | `Quaternion` | `WujiQuaternionF32`、`WujiQuaternionF64` |
| 位姿 | `Pose` | `WujiPose` |
| 设备手性 | `Handedness.Left`、`Handedness.Right` | `WUJI_HANDEDNESS_LEFT`、`WUJI_HANDEDNESS_RIGHT` |
| IMU 数据 | `ImuData` | `WujiImuData` |
| 单个坐标变换 | `FrameTransform` | `WujiFrameTransform` |
| 坐标变换集合 | `FrameTransforms` | `WujiFrameTransforms` |
| 录制器与控制句柄 | `TopicRecorder`、`RecordingHandle` | `WujiTopicRecorder`、`WujiRecordingHandle` |
| 录制摘要与质量指标 | `RecordingSummary`、`QualitySummary`、`QualityMetrics`、`ChannelHealth`、`RecordingAlert`、`RecordingStatus` | `WujiRecordingSummary`、`WujiRecordingQualitySummary`、`WujiRecordingMetrics`、`WujiRecordingChannelHealth`、`WujiRecordingAlert`、`WujiRecordingStatus` |
| 逐通道录制统计 | `ChannelRecordingSummary` | `WujiRecordingChannelSummary` |
| Wuji Hand 关节状态 | `HandJointStates` | `WujiHandJointStates` |
| Wuji Hand 关节指令 | `HandJointCommand` | 无对应帧结构，按 20 项 `WujiJointCommand` 数组下发 |
| Wuji Hand 触觉压力帧 | `TactileGloveFrame` | `WujiTactileGloveFrame` |
| 设备故障码解码结果 | `WujiHand2.describe_error()` 返回的 `dict` | `WujiErrorInfo` |

表示方式的差异有三处。Python 的 `str` 字段在 C 是定长 `char` 数组，例如 `frame_id[32]`、`parent_frame_id[32]`。Python 的 `list` 字段在 C 是指针加长度，例如 `WujiFrameTransforms` 的 `transforms` 与 `transforms_len`。Python 只有一个 `Quaternion`，C 按数据流的实际精度分为 `WujiQuaternionF32` 与 `WujiQuaternionF64`。C 的帧指针仅在订阅回调期间有效，需要保留的数据必须在回调内拷贝，约束详见 [C 接口参考](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/data-reference.md)。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.