> ## 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.

# 手部重定向

手部重定向把人手关键点（21 个 MediaPipe 格式 landmark）映射为 Wuji Hand 2 与 Wuji Hand 的 20 维关节角度命令，可直接送入设备。算法原生内置于 SDK，安装 `pip install wuji-sdk numpy` 即可使用——`numpy` 用于关键点/qpos 数组，无其他依赖。C SDK 提供对等接口，函数名见下方接口清单，内存归属与状态码约定见 [C 接口约定](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/data-reference.md)。

## 快速开始

`RetargetSession.for_hand(model, side)` 按设备型号绑定内置 IK 配置。`session.step(keypoints)` 接受 `(21, 3)` float32 数组，返回 `(20,)` float32 关节角度，可直接发送到设备：

> [tab] Python
>
> ```python theme={null}
> import numpy as np
> from wuji_sdk import Handedness, HandModel, RetargetSession
>
> session = RetargetSession.for_hand(HandModel.WujiHand2, side=Handedness.Right)
>
> # keypoints：21 个 MediaPipe landmark，单位米
> keypoints = np.zeros((21, 3), dtype=np.float32)
> # ... 用相机 / MediaPipe / VR 采集填入 keypoints
>
> joint_angles = session.step(keypoints)   # numpy.ndarray (20,)
> ```

> [tab] C
>
> ```c theme={null}
> WujiRetargetSession *session = NULL;
> if (wuji_retarget_session_create(WUJI_HAND_MODEL_WUJI_HAND2,
>                                  WUJI_HANDEDNESS_RIGHT, &session) != WUJI_STATUS_OK) {
>     fprintf(stderr, "create failed: %s\n", wuji_last_error());
>     return 1;
> }
>
> float keypoints[63] = {0};   // 21×3 行主序 xyz，单位米
> float joint_angles[20];      // 固件顺序关节角（rad）
> // ... 用相机 / MediaPipe / VR 采集填入 keypoints
>
> if (wuji_retarget_session_step(session, keypoints, joint_angles) != WUJI_STATUS_OK) {
>     // 退化或非法的关键点帧返回 WUJI_STATUS_ERR_ALGORITHM，丢弃本帧即可
>     fprintf(stderr, "step failed: %s\n", wuji_last_error());
> }
>
> wuji_retarget_session_free(session);
> ```

切换数据源（重新对齐时序、丢弃旧帧）时清空 warm-start 与低通滤波内部状态：Python 调 `session.reset()`，C 调 `wuji_retarget_session_reset()`。

## API 参考

### 创建 session

类方法 `RetargetSession.for_hand(hand_model, side)`，按设备型号绑定内置配置。

| 参数 | 类型 | 说明 |
| - | - | - |
| `hand_model` | `HandModel` | 目标手型：`HandModel.WujiHand` 或 `HandModel.WujiHand2` |
| `side` | `Handedness` | 手性：`Handedness.Left` 或 `Handedness.Right` |

### 单帧重定向

`session.step(keypoints)` 对单帧关键点执行一次重定向。

| 参数 | 类型 | 说明 |
| - | - | - |
| `keypoints` | `np.ndarray` | 形状 `(21, 3)` 的 float32 数组（或 63 元素行主序展平），按 MediaPipe landmark 顺序，单位米 |

返回 `np.ndarray` 形状 `(20,)` float32，可直接发设备。

### 重置状态

`session.reset()` 清空 warm-start 与低通滤波器状态，C 的等价接口是 `wuji_retarget_session_reset()`。切换数据源或长时间停顿后再开始时调用。

单帧求解的实跑记录、退化输入与断续追踪的处理见[重定向会话：关键点到关节角](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/sdk-practice/retarget-session.md)。

## 输入格式

`step` 入参遵循 [MediaPipe Hands](https://ai.google.dev/edge/api/mediapipe/python/mp/tasks/vision/HandLandmarker) landmark 约定，21 个点按固定顺序（wrist / 五指 × 4 关节），坐标系单位为米。任何能产出该格式的来源都可接入：摄像头 + MediaPipe、Wuji Glove 的 `hand_skeleton` 订阅、VR 手部追踪等。

## 实时遥操作示例

`RetargetSession` 是纯重定向接口，遥操作（从实时关键点流驱动手部）是基于该接口的应用层模式。完整示例见 `wuji-sdk` 仓的 [`examples/python/retargeting/`](https://github.com/wuji-technology/wuji-sdk/tree/main/examples/python/retargeting) 与 [`examples/c/retargeting/`](https://github.com/wuji-technology/wuji-sdk/tree/main/examples/c/retargeting)（Wuji Glove 输入 → 重定向 → 驱动 Wuji Hand 2 / Wuji Hand）。

队列式订阅的 `recv()` 返回最旧的未读帧，每轮只读取一帧会持续落后。用队列式订阅时，每轮先 drain 到最新一帧再传入 `step`。回调式订阅（如 C 示例）在回调中直接覆盖共享缓冲，主循环读取的始终是最新帧。

### 选择 teleop 的 SDK 用户

手部模型取决于当前选中的 SDK 用户。连接前切换、连接后切换都可以——切换后已连接的 glove 会自动改用新用户的模型，无需断开重连：

* **默认用户**：始终使用 SDK 内置默认 hand URDF。在默认用户下执行标定不生效
* **具名用户**：使用该用户标定的手部模型。该用户尚未标定时，同样回退到内置默认 URDF

Python 与 C 的 teleop 示例（`1.teleop_real.py` 与 `1_teleop_real.c`）行为一致：连接 glove 前列出全部 SDK 用户并提示选择，直接回车保持当前用户，退出时还原切换前的用户。菜单不显示用户是否已标定，SDK 未提供连接前解析用户手部模型的公开接口。

内置默认 URDF 目前比按用户标定的手部模型更稳定，建议先选默认用户。若内置 URDF 对实际手型跟踪效果不佳，创建一个具名 SDK 用户，切换到该用户后执行 glove 标定，标定后即可在示例菜单中选中该用户。详见 [SDK 用户管理与标定](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/device-params.md#sdk-用户管理)。

## 平台与限制

* 预编译 wheel 支持 **Linux x86\_64**、**Linux aarch64** 和 **macOS arm64（Apple 芯片，11.0 及以上）**。Windows 和 Intel Mac 不在发行范围内。
* 算法原生内置于 SDK，无需额外下载。运行时依赖仅 `numpy`（用于关键点/qpos 数组）。

## 接口清单

| 操作 | Python | C |
| - | - | - |
| 创建 session | `RetargetSession.for_hand(hand_model, side)` | `wuji_retarget_session_create()` |
| 单帧重定向 | `session.step(keypoints)` | `wuji_retarget_session_step()` |
| 重置内部状态 | `session.reset()` | `wuji_retarget_session_reset()` |
| 释放 session | 随对象回收自动释放 | `wuji_retarget_session_free()`，传 `NULL` 为空操作 |
| 目标手型取值 | `HandModel.WujiHand`、`HandModel.WujiHand2` | `WUJI_HAND_MODEL_WUJI_HAND`、`WUJI_HAND_MODEL_WUJI_HAND2` |
| 手性取值 | `Handedness.Left`、`Handedness.Right` | `WUJI_HANDEDNESS_LEFT`、`WUJI_HANDEDNESS_RIGHT` |

两侧算法与内置 IK 配置相同。Python 收发 `(21, 3)` 与 `(20,)` 的 numpy 数组，C 收发 63 与 20 个 float 的行主序裸数组，由调用方分配。退化或非法的关键点帧在 Python 抛 `WujiException`，在 C 返回 `WUJI_STATUS_ERR_ALGORITHM`，两种情况都丢弃本帧即可。


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