General Hand Retargeting Documentation release
Commands
General Hand Retargeting

Dexteritythatacross glove,across human,across robot.

GHR maps multiple glove sources and people into one 21-point human-hand representation, then retargets that motion across dexterous robot hands. The same interface accepts VR tracking and video-derived hand keypoints.

01 · source Glove · VR · video Source adapters normalize hand observations.
02 · human Shared 21-point hand A person-aware representation separates input devices from robots.
03 · robot Robot-hand targets Robot profiles produce joint targets for replay or teleoperation.
Capabilities

One representation across sources, people, and robots


Input

Cross-glove

Manus, Wuji, and Qineng gloves share one normalized EMF interface.

Calibration

Cross-human

Person- and hand-specific calibration maps each wearer into the same 21-point hand representation.

Output

Cross-robot

Robot profiles retarget the shared hand motion to multiple dexterous-hand kinematics.

External sources

VR and video-to-robot

VR tracking and video-derived 21-point keypoints can enter Retargeter through the same human-hand boundary.

Current Supported Devices

Device classCurrently supported devicesSelection
Data gloveManus · Wuji · QinengGLOVE_SOURCE=manus|wuji|qineng
VRMeta Quest through XRoboToolkit/OpenXRuv run teleoperater quest
Video / keypointsMediaPipe-compatible metric 21-point hand motionuv run retargeter --hdf5 <file_path> for HDF5
Robot handWuji · Wuji 2 · SharpaSet ROBOT to a supported code
Release roadmap

Three core components, one hand-motion pipeline


The public interface is organized around three focused tools. Each stage has one job and a stable output for the next stage.

01 Available

Caliber

Single-stage calibration identifies wearer- and glove-specific hand geometry once, then saves a reusable profile.

Outputcalibration artifact
uv run caliber
02 Available

Tracker

Tracker maps normalized glove observations into metric, person-aware 21-point human-hand motion.

Output21 × 3 human-hand motion
uv run tracker
03 Available

Retargeter

Retargeter converts shared human motion from Tracker, VR, or video into targets for supported robot hands.

Outputrobot joint targets
uv run retargeter
End-to-end · online

Teleoper combines Tracker and Retargeter

Tracker produces live 21-point human-hand motion; Retargeter immediately converts it into robot joint targets in the same process.

uv run teleoperater --rt
Live glove Tracker Retargeter Robot Joint Angles
Getting Started

From clone to your first replay


Run all commands from the repository root.

Prerequisites

Linux, Git, uv, Python 3.11 or 3.12, and a desktop session for visualization. A supported glove and Dora are required only for collection and live --rt modes.

Installation

terminal
$ git clone <repository-url>
$ cd GHR
$ uv sync

Use uv run for the commands below; activating the environment is optional.

Configure one active tuple

Edit the repository-root ghr.env to select the source, person, hand model, optimizer, side, and robot:

ghr.env
GLOVE_SOURCE=manus
GLOVE_PERSON=<person-id>
GLOVE_MODELING=3-2-1-thumbCMCUp
OPTIMIZER=autodiff
HAND_SIDE=right
ROBOT=wuji2

For a one-off run, override a value inline: HAND_SIDE=left uv run caliber.

Fetch the active demo data

Download the captures, calibration results, and robot assets selected by ghr.env. The command also handles datasets published under the legacy calibration directory name.

terminal
$ uv run demo-data fetch

Run the first pipeline

With a fetched or collected calibration session:

terminal
# Calibrate and inspect.
$ uv run caliber
$ uv run viz

# Replay, export, and retarget.
$ uv run tracker
$ uv run tracker --save
$ uv run retargeter
Tutorial

Calibrate a glove to a human hand


Caliber turns static EMF pose captures into a verified, person-specific 21-point skeleton used by runtime Tracker IK.

Calibration input

Each glove adapter provides raw_device_data with shape (2, 6, 7): five fingertip EMF RX poses and one independent EMF TX/palm reference row for each side, stored as xyz + wxyz.

1. Collect the static pose set

Set GLOVE_SOURCE, GLOVE_PERSON, and HAND_SIDE first, then launch the collection UI:

terminal · launches physical hardware
$ uv run collect

# Optional one-run overrides:
$ uv run collect <person-id> --source manus --hand left
#Pose keyHow to hold the hand
1flatFlat on a desk, fingers together.
2–5pinch_indexpinch_pinkyTouch the thumb tip to each fingertip in turn.
6halfbentCurl fingers II–V halfway between flat and fist.
7fistCurl tightly, keeping fingertips on the palm surface rather than tucked beneath the fingers.
8thumb_pinch_mcpPress the thumb tip onto the finger MCP knuckles.
9flat_openKeep the hand flat and spread all five fingers as wide as possible.
10mcp_90Bend II–V about 90° at the MCP only; keep PIP/DIP straight and thumb up.
11–14pinch_*_extendRepeat each thumb-to-finger pinch with the target finger extended.

Match HAND_SIDE to the powered glove. After the static set, record one continuous motion for runtime validation.

2. Tune the fingertip sensor offset

If a pinch remains open, adjust the affected finger’s local sensor x offset, save it, and rerun Caliber. Offsets are specific to the source, person, hand, and glove fit.

terminal
$ uv run define_tip2rx
$ uv run caliber
Pinch before fingertip sensor offset tuning
Before: visible pinch gap.
Pinch after fingertip sensor offset tuning
After: improved fingertip closure.

3. Run the single-stage solve

Caliber runs one full-hand joint solve with analytic thumb-CMC coupling.

terminal
$ uv run caliber

4. Verify before runtime use

Inspect every pose and confirm that predicted RX poses align with the measurements. Then replay continuous motion to check pinch closure and joint stability.

terminal
$ uv run viz
$ uv run tracker

5. Use the result

terminal
# Replay and export the human hand.
$ uv run tracker
$ uv run tracker --save

# Retarget a recording or run the composed pipeline.
$ uv run retargeter
$ uv run teleoperater

# Live glove.
$ uv run tracker --rt
$ uv run teleoperater --rt
! Hardware is opt-in

Live commands visualize by default. Only uv run teleoperater --rt --hardware sends commands to a physical robot. Calibrate each glove side independently.

Tutorial

Add a New Robot


Add left/right kinematic assets, declare a robot profile, register its code, and validate a saved hand motion.

1. Add self-contained URDF and MJCF assets

The pipeline uses Pinocchio FK from URDF and Mink/MuJoCo from MJCF, so both representations are required for every supported side.

AssetLocationUsed by
MJCF and meshesdata/motion_retargeting/assets/<name>_hand/Mink solver and MuJoCo visualization
URDF and meshesdata/motion_retargeting/assets/<name>_hand_description/Pinocchio forward kinematics
Per-side YAMLretarget/config/retargeter/robot/<name>/Structural profile and robot geometry
Shared defaultsretarget/config/retargeter/common.yamlLoss and solver defaults for every robot

2. Declare the per-side hand profile

Create left/right YAML files under retarget/config/retargeter/robot/<name>/. Define the robot code, finger frames, fingertip sites, coupled joints, palm origin, and hand anchors. Shared solver settings remain in retarget/config/retargeter/common.yaml.

  • Declare fingers in anatomical order: thumb, index, middle, ring, pinky.
  • Use model frame and joint names, not qpos indices.
  • Register the robot in ROBOT_CONFIGS and VALID_ROBOT.

3. Define origin, fingertips, and anchors

Run the geometry editor once per side and save the palm origin, fingertip sites, and hand anchors.

terminal
$ uv run define_robot example left
$ uv run define_robot example right

4. Validate with a saved human-hand motion

terminal · simulation only
$ uv run retargeter path/to/recording.pkl --robot example --hand left
$ uv run retargeter path/to/recording.pkl --robot example --hand right

Verify model loading, joint limits, anchor alignment, stable motion, and pinch closure on both sides before adding a hardware driver.

Tutorial

Add a New Glove


A new glove is a producer for one normalized EMF pose format. Once the adapter satisfies that contract, collection, Caliber, visualization, and runtime Tracker IK remain source-agnostic.

1. Implement the one input contract

Every source emits raw_device_data with shape (2, 6, 7).

Dimension / rowContract
Axis 0Two hand slots: left and right.
Rows 0–4Thumb, index, middle, ring, and pinky EMF RX poses.
Row 5EMF TX IMU/reference pose; it remains separate from the five RX orientations.
Last axisposition xyz in metres plus unit quaternion wxyz.
FrameRX positions in the shared TX-local axes: x forward, y left, z up.
Missing sensorZero quaternion, allowing downstream IK to freeze that finger safely.

2. Separate hardware I/O from axis conversion

integration files
hardware/glove/collect/<source>_node.py
hardware/glove/dataflows/collect_<source>.yml
hardware/glove/dataflows/realtime_<source>.yml
calib/caliber/utils/<source>_adapt.py
  • Keep SDK connections and Dora output in hardware/.
  • Normalize metres, axes, sensor order, and wxyz quaternions in the adapter.
  • Register the source in calib/caliber/utils/glove_sources.py.

Measure the fingertip-to-RX offsets for the new source before calibration:

terminal
$ GLOVE_SOURCE=<source> HAND_SIDE=left uv run define_tip2rx

3. Validate end to end

terminal · collection/live commands require hardware
# Capture the complete static set from the new adapter.
$ GLOVE_SOURCE=<source> uv run collect --source <source> --hand left

# Calibration and inspection use the saved capture.
$ GLOVE_SOURCE=<source> uv run caliber
$ GLOVE_SOURCE=<source> uv run viz

# Only after offline validation: stream the live glove.
$ GLOVE_SOURCE=<source> uv run tracker --rt

Check shape, units, handedness, sensor loss, flat/pinch poses, and continuous motion before enabling live use.

Tutorial

VR and video-to-robot


Retargeter accepts metric 21-point human-hand motion from gloves, VR tracking, video, or another pose producer.

Input paths

VR

Meta Quest

uv run teleoperater quest converts OpenXR tracking to the shared 21-point hand and drives one or both robot hands.

Video

Video-to-robot

Retarget saved 21-point .pkl recordings with uv run retargeter, or play MediaPipe-21 HDF5 directly with uv run retargeter --hdf5 <file_path>.

MediaPipe-21 HDF5 replay

terminal · MediaPipe-21 HDF5 replay
$ uv run retargeter --hdf5 path/to/recording.h5

The HDF5 adapter selects the active HAND_SIDE, uses the active ROBOT, opens the online MuJoCo UI at 30 FPS, loops until the window closes, holds the latest valid pose across invalid detections, and does not save a trajectory.

Live Meta Quest → robot retargeting

Start the XRoboToolkit PC Service and Quest client, then run one hand or both hands:

terminal · live Meta Quest tracking
# One hand: ROBOT and HAND_SIDE come from ghr.env.
$ uv run teleoperater quest

# Override the robot and side for one run.
$ uv run teleoperater quest --robot wuji2 --hand right

# Track left and right together.
$ uv run teleoperater quest --bimanual

Use --robot, --hand, --bimanual, and --filter-alpha as needed. Quest mode renders robot targets but does not command physical hardware.

21-point input contract

Each frame is a finite (21, 3) array in metres using MediaPipe landmark order. Producers may provide world-oriented raw points or wrist-centred points in the project frame: x forward, y left, z up. Source adapters own scale, handedness, coordinate conversion, confidence filtering, and timing.

Examples

Dexterous manipulation demos


Recorded examples of GHR teleoperation across bimanual grasping, assembly, stacking, and in-hand manipulation.

Recorded demo
Task RW-01

Light Bulb Assembly

One hand stabilizes the tabletop fixture while the other aligns and twists the light bulb into place.

BimanualAlignmentTorque application31.6 s
Teleop
Task RW-02

Cup Stacking

A teleoperated demonstration of grasping, separating, aligning, and stacking nested paper cups.

GraspSeparateAlignStack60.3 s
Recorded demo
Task RW-05

Bimanual Cup Extraction

Two hands establish a stable cooperative interaction and extract the target cup from its surrounding setup.

BimanualCooperative21.8 s
Teleop
Task RW-06

Rubik’s Cube Teleoperation

Two teleoperated robot hands stabilize, regrasp, and rotate the cube through coordinated in-hand manipulation.

BimanualIn-hand manipulationRegrasp40.1 s

Policy

Real-robot policy evidence is presented separately from teleoperated references so execution and demonstration remain unambiguous.

i Evidence status

RW-01 and RW-05 are recorded demonstrations. RW-02 has separate teleoperation and policy-rollout footage. RW-06 is a recorded Rubik’s Cube teleoperation. RW-07 is a real-robot card-extraction policy rollout. Success protocols, policy provenance, and ranking metadata remain pending.

Reference

Command map


Primary workflow commands use uv run.

uv run collectCapture and average the complete static calibration pose set.hardware
uv run caliberRun the single-stage full-hand calibration with analytic thumb-CMC coupling.offline
uv run vizVerify the active calibration in the browser.offline · GUI
uv run trackerReplay EMF motion through calibrated human-hand IK.offline by default
uv run retargeterRetarget a saved glove- or video-derived 21-point .pkl recording.no glove required
uv run retargeter --hdf5 <file_path>Continuously replay a MediaPipe-21 HDF5 recording in the online MuJoCo UI.loops · no save
uv run teleoperaterCompose Tracker and Retargeter in one viewer.replay by default
uv run teleoperater quest [--bimanual]Stream one or both Meta Quest tracked hands into Retargeter.live VR
Reference

Artifacts and paths


The centralized helpers derive every path from the active tuple. Do not reconstruct a result path by guessing a nearby person or model.

directory layout
data/caliber/data/
└── <source>/<person>/<hand>/
    ├── all_poses.npz
    ├── <pose>.npz
    └── motion_<timestamp>.npz

data/caliber/results/
└── <source>/<modeling>/<optimizer>/<person>/<hand>/
    ├── params.json
    ├── calibration_result.json
    ├── loss_history.json
    ├── bone_roll_correction.json
    └── viz_data.json
ArtifactRole
all_poses.npzNamespaced, averaged static-pose measurements for one source/person/hand session.
params.jsonCalibrated parameters consumed by runtime Tracker IK.
calibration_result.jsonSingle-stage fit, parameter tables, metrics, configuration, and input provenance.
loss_history.jsonOptimizer convergence history for inspection and comparison.
viz_data.jsonTuple-specific geometry consumed by the browser visualization index.
Help

Troubleshooting


SymptomLikely causeAction
Session not foundThe active source, person, or hand does not own all_poses.npz.Recheck the six knobs and the exact data directory; do not substitute another profile.
Collector buttons stay disabledHAND_SIDE does not match the powered glove, so the selected row is empty.Correct the hand side and relaunch collection.
One finger fits badlyA pose was held incorrectly, or the wearing-specific tip-to-RX profile is wrong.Recollect the affected pose and inspect uv run define_tip2rx.
Calibration viewer is blankNo matching tuple is indexed, or the browser has no WebGL context.Read the terminal output, verify the tuple, and use the viewer’s software-WebGL launch path.
Replay selects the wrong motionAn implicit assumption was made about the session.Confirm the active tuple or pass the exact motion_*.npz path explicitly.
Robot motion is implausibleThe issue may be in retargeter rather than calibration.First validate tracker alone, then inspect the selected robot profile and retarget YAML.
teleoperater quest cannot find the SDKNo discovered Python interpreter can import both numpy and xrobotoolkit_sdk.Pass the SDK environment explicitly with --xrt-python or set QUEST_XRT_PYTHON.
Only one bimanual Quest viewer movesThe other Quest hand is not actively tracked.Make both hands visible to the headset; each side begins independently and holds its last pose while tracking is absent.
Support

Contact Wei Pan


@ Questions and support

For any questions, contact Wei Pan at weisonweileen@gmail.com.