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

# ROS 2 集成

`wuji_glove_driver` 将 Wuji Glove 的关节角、追踪位姿、掌部 IMU 和触觉数据发布为 ROS 2 Topic。驱动不加载模型、发布 TF，也不提供控制或标定服务。开始前完成[穿戴与连接](https://docs.wuji.tech/docs/zh/wuji-glove/latest/getting-started.md)及所需的[标定](https://docs.wuji.tech/docs/zh/wuji-glove/latest/calibration.md)。

## 安装

使用已安装 ROS 2 Lyrical 的 Ubuntu 26.04（resolute），支持 x86\_64 和 aarch64。以下命令获取源码、加载 ROS 环境、安装依赖及 Hand 2 模型，并构建工作区。构建时会自动下载并校验适配当前架构的 Wuji SDK C 包。

```bash theme={null}
# 获取源码并加载 ROS 2 环境
git clone https://github.com/wuji-technology/wuji-ros2.git "$HOME/wuji-ros2"
cd "$HOME/wuji-ros2"
source /opt/ros/lyrical/setup.bash
# 安装构建工具和依赖
sudo apt-get update
sudo apt-get install -y ros-dev-tools
rosdep update
# 安装 Hand 2 模型与工作区依赖
scripts/install_hand2_descriptions.sh
rosdep install --from-paths . --ignore-src -r -y
# 构建工作区。SDK C 包会自动下载并校验
colcon build --cmake-args -DBUILD_TESTING=OFF
# 加载构建结果
source install/setup.bash
```

> [!NOTE]
>
> * 模型安装脚本要求 `/etc/apt/sources.list.d/ros2.sources` 存在。若文件缺失，先按 ROS 2 官方安装流程配置 Lyrical 软件源，再重新运行脚本。
> * 若电脑从未初始化 rosdep，在 `rosdep update` 前执行一次 `sudo rosdep init`。`sudo` 命令需要管理员权限。
> * 若 SDK 下载失败，从 [Wuji SDK v2026.10.12](https://github.com/wuji-technology/wuji-sdk/releases/tag/v2026.10.12) 下载 `wuji-sdk-c-2026.10.12-x86_64-linux-gnu.tar.gz` 或 `wuji-sdk-c-2026.10.12-aarch64-linux-gnu.tar.gz`，按主机架构选择并解压，确认目录包含 `include/wuji_sdk.h`、`lib/libwuji_sdk_c.so` 和 `LICENSE`。将 `/path/to/sdk` 替换为解压目录的绝对路径，在 `wuji-ros2` 目录运行以下命令代替默认构建命令：
>
>   ```bash theme={null}
>   colcon build --cmake-args -DBUILD_TESTING=OFF -DWUJI_SDK_ROOT=/path/to/sdk
>   ```
> * 使用 `WUJI_SDK_ROOT` 时，CMake 不校验 SDK 版本，请使用上述指定发行包。

后续每个新终端均需进入工作区并加载 ROS 环境与构建结果：

```bash theme={null}
cd "$HOME/wuji-ros2"
source /opt/ros/lyrical/setup.bash
source install/setup.bash
```

## 选择设备

完成穿戴与网络连接后，扫描设备：

```bash theme={null}
ros2 run wuji_tools wuji_list
```

记录目标手套的序列号。启动驱动时可使用以下参数选择设备：

| 参数 | 作用 |
| - | - |
| `serial_number` | 按扫描到的序列号选择手套。指定 `endpoint` 时用于校验设备身份 |
| `hand_side` | 单独使用时选择唯一的左手套或右手套。与 `serial_number` 或 `endpoint` 同时使用时校验手别，取值为 `left` 或 `right` |
| `endpoint` | 按扫描到的 `IP:端口` 地址直接连接手套，可选 |

未指定选择条件时，驱动仅在发现唯一一只 Wuji Glove 时连接。发现多只手套时立即报错退出。未发现手套时等待至 `connect_timeout` 后退出。驱动连接期间独占手套，其他 SDK 程序或 `wuji viz` 无法同时连接。同时连接多只手套时，为每个驱动进程指定不同序列号和命名空间。

## 读取手套数据

### 运行验证

**1. 启动驱动**

将 `GLOVE_SERIAL_NUMBER` 替换为[选择设备](#选择设备)中记录的序列号，启动驱动：

```bash theme={null}
ros2 launch wuji_bringup glove.launch.py \
  serial_number:=GLOVE_SERIAL_NUMBER namespace:=glove
```

按网络地址连接时，将 `GLOVE_ENDPOINT` 替换为扫描结果中的 `IP:端口` 地址，改用以下命令：

```bash theme={null}
ros2 launch wuji_bringup glove.launch.py \
  serial_number:=GLOVE_SERIAL_NUMBER endpoint:=GLOVE_ENDPOINT namespace:=glove
```

需要校验手别时，在启动命令末尾添加 `hand_side:=left` 或 `hand_side:=right`。

> [!NOTE]
>
> 驱动等待设备连接的超时时间默认 10 秒。在启动命令末尾添加 `connect_timeout:=20.0`，可将连接等待时间延长至 20 秒。设为 `0.0` 时持续等待设备连接。启动参数仅在启动时读取。

**2. 检查数据**

保持驱动运行。新开终端，加载 ROS 环境与构建结果，再运行状态示例：

```bash theme={null}
cd "$HOME/wuji-ros2"
source /opt/ros/lyrical/setup.bash
source install/setup.bash
ros2 run wuji_bringup glove_status_demo --ros-args -r __ns:=/glove
```

示例逐帧输出五指关节角与 confidence，默认运行 10 秒，再汇总各 Topic 的帧数和平均接收率。收到至少 1 帧 `joint_angles` 表示验证通过。未收到可选流的数据时，示例输出警告。

只统计接收率并延长到 30 秒时，运行：

```bash theme={null}
ros2 run wuji_bringup glove_status_demo \
  --duration 30 --rate-only --ros-args -r __ns:=/glove
```

`--duration` 和 `--rate-only` 放在 `--ros-args` 前。接收率使用首次到末次回调之间的帧数和时间计算，表示示例处理 ROS 消息的速率，不代表设备原始输出率。

> [!NOTE]
>
> 驱动已连接但状态示例收不到数据时，先核对两个终端的 namespace、`ROS_DOMAIN_ID` 和 QoS 是否一致。仍有问题时，再尝试切换 ROS 2 中间件。安装 Cyclone DDS：
>
> ```bash theme={null}
> sudo apt-get install ros-lyrical-rmw-cyclonedds-cpp
> ```
>
> 停止当前 launch。在驱动终端和状态示例终端分别执行：
>
> ```bash theme={null}
> export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
> ```
>
> 重新运行步骤 1 和步骤 2。后续新开的终端也要设置相同的 ROS 2 中间件。

**3. 停止驱动**

在驱动终端按 `Ctrl+C`。驱动关闭订阅并断开设备连接。

### 数据 Topic

全部 10 个 Topic 使用 SensorDataQoS：best-effort、volatile、keep-last 5。订阅端应使用 best-effort，reliable 订阅者无法接收这些发布者的数据。

驱动通过下表的 Topic 发布手套数据。订阅时使用表中消息类型。Topic 名称均为相对名称，例如 `namespace:=glove` 下的 `joint_angles` 对应 `/glove/joint_angles`。

| Topic | 消息类型 | 内容 | 启动开关 |
| - | - | - | - |
| `joint_angles` | `wuji_msgs/msg/HandJointAngles` | 五指关节角数组及各指 confidence | 始终启用 |
| `emf_poses` | `wuji_msgs/msg/TrackedPoseArray` | 带名称、位姿和 confidence 的 EMF 追踪结果 | `publish_emf_poses` |
| `tip_poses` | `wuji_msgs/msg/TrackedPoseArray` | 带名称、位姿和 confidence 的指尖追踪结果 | `publish_tip_poses` |
| `hand_skeleton` | `wuji_msgs/msg/TrackedPoseArray` | 带名称、位姿和 confidence 的手部骨骼追踪结果 | `publish_skeleton` |
| `imu/palm` | `sensor_msgs/msg/Imu` | SDK `imu_raw/palm` 的掌部原始 IMU | `publish_imu` |
| `tactile` | `wuji_msgs/msg/TactileGrid` | 网格尺寸与触觉数据数组 | `publish_tactile` |
| `tactile/residual` | `wuji_msgs/msg/TactileGrid` | 网格尺寸与触觉残差数组 | `publish_tactile_residual` |
| `tactile/binary` | `wuji_msgs/msg/TactileGrid` | 网格尺寸与触觉二值数组 | `publish_tactile_binary` |
| `tactile/zones` | `wuji_msgs/msg/TactileZoneArray` | 触觉区域名称与数值 | `publish_tactile_zones` |
| `tactile/points` | `sensor_msgs/msg/PointCloud2` | 触觉点云 | `publish_tactile_points` |

> [!NOTE]
>
> Wuji 自定义消息的字段定义见 `wuji-ros2` 仓库的 `wuji_msgs/msg/` 目录，文件名与表中消息类型对应，嵌套消息也在该目录。标准消息见 ROS 2 的 [Imu.msg](https://github.com/ros2/common_interfaces/blob/lyrical/sensor_msgs/msg/Imu.msg) 和 [PointCloud2.msg](https://github.com/ros2/common_interfaces/blob/lyrical/sensor_msgs/msg/PointCloud2.msg)。

加载工作区后，运行以下命令查看当前安装版本的消息字段：

```bash theme={null}
ros2 interface show wuji_msgs/msg/HandJointAngles
ros2 interface show wuji_msgs/msg/TrackedPoseArray
ros2 interface show wuji_msgs/msg/TactileGrid
ros2 interface show wuji_msgs/msg/TactileZoneArray
```

### 数据解读

* 关节角使用 rad，位姿位置使用 m。按各指 `angles` 数组的实际长度读取角度，拇指为 5 项，其余手指各 4 项，也不把 confidence 解释为已归一化的概率。
* 消息保留 SDK 时间戳、坐标系标识和数据值。ROS 命名空间不会改写消息中的 `frame_id`。坐标系含义见[坐标系说明](https://docs.wuji.tech/docs/zh/wuji-glove/latest/coordinate-frames.md)。
* 驱动将 SDK 原始 IMU 字段及其协方差复制到 `imu/palm`，不另行计算姿态，也不发布 SDK 派生的 `imu_data/palm`。
* 触觉网格按 `rows × columns` 的行优先顺序排列。网格值含义由 Topic 决定，残差与二值网格不能当作力值。
* 触觉点云按消息自身的 `fields`、`point_step` 和 `row_step` 解析，不假设固定为仅含 xyz 的布局。

## Topic 发布设置

除必需的 `joint_angles` 外，表中的 9 个数据流均可通过启动参数控制，默认启用。例如，关闭触觉点云时使用：

```bash theme={null}
ros2 launch wuji_bringup glove.launch.py \
  serial_number:=GLOVE_SERIAL_NUMBER namespace:=glove \
  publish_tactile_points:=false
```

布尔启动参数仅接受小写 `true` / `false`。其他可选流使用表中对应的 `publish_*` 参数。`joint_angles` 没有关闭开关。

### 断流处理

必需的 `joint_angles` 无法启动，或运行中报告结束或错误时，驱动以非零状态退出，launch 随之结束。可选流失败时，仅停止该流并记录日志，其他流继续运行。

驱动不自动重连。恢复设备和网络后重新启动 launch。流报告结束或错误才会触发相应处理。应用若需检查数据是否持续更新，应监测消息时间戳。


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