> ## 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 接口约定](/docs/wuji-sdk/data-reference)。

## 快速开始

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

<Tabs>
  <Tab title="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>

  <Tab title="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);
    ```
  </Tab>
</Tabs>

切换数据源（重新对齐时序、丢弃旧帧）时清空 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()`。切换数据源或长时间停顿后再开始时调用。

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

## 输入格式

`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 用户管理与标定](/docs/wuji-sdk/device-params#sdk-用户管理)。

## 平台与限制

* 仅支持 **Linux x86\_64** 与 **Linux aarch64**。macOS / Windows / 其它架构暂不分发预编译 wheel。
* 算法原生内置于 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.