MANUS Gloves#
A Linux-only plugin for integrating MANUS gloves
into the Isaac Teleop framework. It provides full hand-joint tracking via the
Manus SDK and injects the resulting poses into the OpenXR hand-tracking layer so
any downstream retargeter can consume them transparently. Optionally it also
publishes Manus flex-sensor (RawDeviceData) tip poses as JointStateOutput
tensors and consumes inbound haptic commands for vibration gloves.
Components#
Core library (
manus_plugin_core) — wraps the Manus SDK (libIsaacTeleopPluginsManus.so) and exposes per-joint tracking data.Plugin executable (
manus_hand_plugin) — the main plugin binary that integrates with the Teleop system via CloudXR / OpenXR.CLI tool (
manus_hand_tracker_printer) — a standalone diagnostic tool that prints tracked joint data to the terminal and opens a real-time MANUS Data Visualizer window showing the hand skeleton from two orthographic views per hand.
Prerequisites#
Linux — x86_64 (tested on Ubuntu 22.04 / 24.04).
Manus SDK for Linux — downloaded automatically by the install script.
System dependencies — the install script installs required packages automatically.
Installation#
MANUS access has two halves: device permissions (kernel/udev, lives on the host) and SDK + plugin build (lives wherever you build, typically a container). The two scripts below split along that line.
Step 1: grant the host access to the Manus dongle (one-time)#
Run this on the host machine, not inside a container. udev rules are
processed by systemd-udevd, which does not run inside Docker — so
installing rules from a container has no effect.
cd src/plugins/manus
./install_udev_rules.sh
# then unplug + replug the Manus dongle
If you’re using the Isaac ROS dev container (isaac_ros run_dev), it
bind-mounts /dev/bus/usb from the host, so once the host has the rules
applied the container will see the dongle with the right permissions.
Step 2: build the SDK and plugin#
Run this inside the build environment (devcontainer or Isaac ROS container):
cd src/plugins/manus
./install_manus.sh
The script will:
Install the required system packages for MANUS Core Integrated.
Download MANUS SDK v3.1.1.
Extract and place the SDK in the correct location.
Build the plugin and the diagnostic tool.
When run inside a container, install_manus.sh skips the udev step and
reminds you to run install_udev_rules.sh on the host.
Manual installation#
If you prefer to install manually:
Download the MANUS Core SDK from MANUS Downloads.
Extract and place the
ManusSDKfolder insidesrc/plugins/manus/, or point CMake at a different path by settingMANUS_SDK_ROOT.Follow the MANUS Getting Started guide for Linux to install the dependencies and configure device permissions.
Expected directory layout after placing the SDK:
src/plugins/manus/
app/
main.cpp
core/
manus_hand_tracking_plugin.cpp
inc/
core/
manus_hand_tracking_plugin.hpp
tools/
manus_hand_tracker_printer.cpp
ManusSDK/ <-- placed here
include/
lib/
Then build from the root:
cd ../../.. # navigate to root
cmake -S . -B build
cmake --build build --target manus_hand_plugin manus_hand_tracker_printer -j
cmake --install build --component manus
Running the Plugin#
1. Start the CloudXR runtime and load its environment#
The MANUS plugin connects to the Teleop session through the CloudXR / OpenXR runtime, so the runtime must be running and its environment sourced in the shell that launches the plugin.
In one terminal, start the CloudXR runtime (keep it running for the duration of the session):
python -m isaacteleop.cloudxr
In the terminal you will use to run the plugin, source the environment file that the runtime writes on startup. This points the OpenXR loader at CloudXR:
source ~/.cloudxr/run/cloudxr.env
See 3. Configure CloudXR (optional) and 4. Whitelist ports for Firewall in the Quick Start for the full CloudXR runtime setup, including EULA acceptance and firewall configuration.
2. Verify with the CLI tool#
Verify that the gloves are working using the CLI tool:
./build/bin/manus_hand_tracker_printer
The tool prints joint positions to the terminal and opens a MANUS Data Visualizer window showing a top-down and side view of each hand.
3. Run the plugin#
The plugin is installed to the install directory. Ensure the CLI tool is
not running when you launch the plugin — only one process can hold the Manus
SDK connection at a time.
./install/plugins/manus/manus_hand_plugin
By default the plugin enables human hand injection, flex-sensor push, and
haptic read. Restrict datasets with --datasets= (comma-separated):
./install/plugins/manus/manus_hand_plugin --datasets=human,sensors,haptic
./install/plugins/manus/manus_hand_plugin --datasets=human # skeleton only
./install/plugins/manus/manus_hand_plugin --datasets=sensors # flex sensors only
Data paths#
Human (OpenXR hand injection)#
The Manus raw skeleton stream is mapped to 26 OpenXR hand joints and pushed
through HandInjector (requires XR_NVX1_device_interface_base). Downstream
hosts consume hands via HandsSource as with any other hand-tracking plugin.
Sensors (flex tips via SchemaPusher)#
When gloves report at least five RawDeviceData flex sensors, the plugin pushes
a JointStateOutput (tensor id joint_state) on:
manus_sensors_leftmanus_sensors_right
Layout: 35 joints named j0..``j34``. For sensor i in thumb→pinky order,
j[7*i : 7*i+7] is [x, y, z, qx, qy, qz, qw] (meters, quaternion xyzw)
in the Manus SDK frame after the plugin’s VUH coordinate setup. Poses are raw
Manus flex transforms; hosts that mask against a re-framed skeleton must apply
their own sensor-pose processing.
This path requires CloudXR tensor push extensions
(XR_NVX1_push_tensor and XR_NVX1_tensor_data). When sensors first become
available the plugin logs sensors=on once per side.
Host-side consumption example:
from isaacteleop.retargeting_engine.deviceio_source_nodes import JointStateSource
SENSOR_JOINTS = [f"j{i}" for i in range(35)]
left = JointStateSource(
name="manus_sensors_left",
collection_id="manus_sensors_left",
joint_names=SENSOR_JOINTS,
)
# Decode thumb tip: joints j0..j6 -> [x, y, z, qx, qy, qz, qw]
Haptic (inbound vibration)#
The plugin reads HapticCommand on collection manus_glove_haptic
(XR_NVX1_tensor_data) and drives five finger motors via the Manus SDK.
See the haptic feedback example and
isaacteleop.haptic_devices.glove.haptic_glove_device.
Wrist Positioning — Controllers vs Optical Hand Tracking#
Two sources are available for positioning the MANUS gloves in 3D space:
Controller adapters — attach Quest 3 controllers to the MANUS Universal Mount on the back of the glove. The controller pose drives wrist placement.
Optical hand tracking — use the HMD’s built-in optical hand tracking to position the hands. No physical controller adapter required.
The plugin selects the source automatically at runtime: optical hand tracking is
preferred when XR_MNDX_xdev_space is supported and the runtime reports an
actively tracked wrist pose; otherwise it falls back to the controller pose.
Note
When using controller adapters it is advisable to disable the HMD’s automatic hand-tracking–to–controller switching to avoid unexpected source changes mid-session.
Troubleshooting#
Symptom |
Resolution |
|---|---|
SDK download fails |
Check your internet connection and re-run the install script. |
Manus SDK not found at build time |
With manual installation, ensure |
Manus SDK not found at runtime |
The build configures RPATH automatically. If you moved the SDK after
building, set |
No data received |
Ensure MANUS Core is running and the gloves are connected and calibrated. |
CloudXR runtime errors |
Make sure the CloudXR runtime is running ( |
Permission denied for USB devices |
udev rules must be installed on the host. Run |
|
You’re inside a container. |
Dongle not visible inside the Isaac ROS container ( |
The container needs |
License#
Source files are covered by their stated licenses (Apache-2.0). The Manus SDK is proprietary to MANUS and is subject to its own license; it is not redistributed by this project.