Retargeter: Manus to Sharpa#
SharpaHandRetargeter maps live hand-tracking poses from a Manus glove (or any other source feeding the OpenXR
hand-tracking layer) onto Sharpa hand joint angles, frame by frame, via
optimization-based inverse kinematics. SharpaBiManualRetargeter is a
thin combiner that interleaves left and right outputs into a single
target-ordered vector for downstream control.
At a glance#
Stage |
What happens |
|---|---|
Input |
26-joint OpenXR |
Repack |
Drop OpenXR palm + non-thumb metacarpals to land on the canonical MANO 21-joint layout, and convert quaternions to wxyz. |
IK |
|
Warm-start |
Previous-frame qpos is kept and reused (with the wrist re-pinned to the new tracker reading) to keep the IK locally smooth. A frame with any invalid input joint zeros the output and resets the warm-start. |
Output |
Sharpa finger DOFs (everything Pinocchio reports past the
FreeFlyer), optionally reordered by |
The retargeter intentionally contains no IK math itself: joint orderings,
frame mappings, rotation corrections, and Pink/Pinocchio configuration all
live in robotic_grounding (V2D). This module is the OpenXR-shaped
adapter on top of it.
See also
Manus Gloves – installing the Manus plugin so its tracking shows up on the OpenXR hand layer that this retargeter consumes.
Retargeting Interface – the broader retargeting interface and pipeline-builder pattern.
Why the [grounding] extra exists#
The Sharpa kinematics model, MJCFs, meshes, and the IK setup that this
retargeter calls all live in the robotic_grounding package (part of
V2D). V2D is on track to be fully open sourced; until then its source
isn’t public, so the wheel has two build modes:
Default — wheel ships without
robotic_grounding. Sharpa retargeter imports skip cleanly, so forks and OSS contributors can build and use the rest of Teleop unaffected.With
-DBUNDLE_ROBOTIC_GROUNDING=TRUE— the build pullsrobotic_groundingfrom the pinned SHA indeps/v2d/version.txtand bundles it into the wheel. Installingisaacteleop[grounding]then resolves all imports, and the Sharpa MJCFs ship with the wheel.
Note
-DBUNDLE_ROBOTIC_GROUNDING=TRUE is a temporary bridge. Once V2D is
fully open sourced, robotic_grounding will be a normal public
dependency of the [grounding] extra and the bundling flag (along
with scripts/setup_v2d_src.sh and the V2D_RETARGETER_TOKEN
gating in CI) will go away.
The next two sections cover that opt-in build, how to use the retargeter once the extra is in place, and how to verify the install.
Build the [grounding] extra#
Prerequisites:
gh CLI installed and
gh auth login‘d with read access tojiwenc-nv/v2d.A configured Teleop build tree.
$ scripts/setup_v2d_src.sh
$ cmake -B build -DBUNDLE_ROBOTIC_GROUNDING=TRUE <other flags...>
$ cmake --build build --target python_wheel
$ uv pip install -e .[grounding]
The first command populates deps/v2d/src/robotic_grounding/ from the
SHA pinned in deps/v2d/version.txt. The CMake flag tells the wheel
build to bundle that subtree alongside isaacteleop.
If the wheel was built without -DBUNDLE_ROBOTIC_GROUNDING=TRUE, the
import raises ModuleNotFoundError with a pointer back to
scripts/setup_v2d_src.sh.
Use it from Python#
from isaacteleop.retargeters import (
SharpaHandRetargeter,
SharpaHandRetargeterConfig,
)
The Sharpa MJCFs and meshes ship inside the bundled robotic_grounding
package – resolve them with importlib.resources:
from importlib.resources import files
xml_dir = files("robotic_grounding") / "assets" / "xmls" / "sharpawave"
right_mjcf = str(xml_dir / "right_sharpawave_nomesh.xml") # mesh-free, fast
# or "right_sharpawave.xml" if you also have the STL meshes
cfg = SharpaHandRetargeterConfig(hand_side="right", robot_asset_path=right_mjcf)
retargeter = SharpaHandRetargeter(cfg, name="sharpa_right")
Key SharpaHandRetargeterConfig fields:
robot_asset_path— the Sharpa MJCF path (..._nomesh.xmlis the mesh-free variant used in tests and on machines without the STLs).hand_side—"left"or"right".hand_joint_names— optional output ordering override; defaults to whatever finger joints Pinocchio discovers in the MJCF, in model order.source_to_robot_scale— MANO-to-robot length scale.solver/max_iter/frequency/frame_tasks_converged_threshold— Pink IK knobs forwarded toSharpaHandKinematics.
For bimanual control, instantiate two SharpaHandRetargeters and
wrap them with SharpaBiManualRetargeter so a single output vector is
produced in your target joint order.
Run the example#
The repo ships a bimanual demo at
examples/retargeting/python/sharpa_hand_retargeter_demo.py:
# Synthetic curl animation (no headset, no GUI required):
$ python examples/retargeting/python/sharpa_hand_retargeter_demo.py --synthetic
# Live bimanual from a connected Quest headset:
$ python examples/retargeting/python/sharpa_hand_retargeter_demo.py
# Custom MJCFs (e.g. the mesh-bearing variants):
$ python examples/retargeting/python/sharpa_hand_retargeter_demo.py \
--left-mjcf /path/to/left_sharpawave.xml \
--right-mjcf /path/to/right_sharpawave.xml
The synthetic mode is the smoke test: if it animates a curl trajectory and prints non-zero finger qpos each frame, the install is good.
Validate#
Two checks; either by itself is sufficient.
End-to-end pytest – exercises the full Pinocchio + Pink IK pipeline through the Teleop wrapper (init, warm-start persistence, open vs. curled hand, absent-hand zeros, etc.):
$ ctest --test-dir build -R retargeting_test_sharpa_hand_retargeter --output-on-failure
...
100% tests passed, 0 tests failed out of 1
The Test command line printed by ctest -V should include
--extra grounding. If it doesn’t, the wheel build skipped bundling –
re-check that cmake -B build was invoked with
-DBUNDLE_ROBOTIC_GROUNDING=TRUE after running setup_v2d_src.sh.
Full retargeting suite – regression coverage in case the wrapper introduced a typing or import regression elsewhere:
$ ctest --test-dir build -R '^retargeting_' --output-on-failure
...
100% tests passed, 0 tests failed out of 16
CI#
The workflow at .github/workflows/build-ubuntu.yml runs the same flow
via the setup-v2d-src composite action, gated on the
V2D_RETARGETER_TOKEN repo secret (a PAT scoped read-only to
jiwenc-nv/v2d). The action sets -DBUNDLE_ROBOTIC_GROUNDING from
its own bundled output; on forks without the secret the action no-ops
and the flag is false.
Public artifact safety: a Release-only step strips robotic_grounding/
out of every wheel before actions/upload-artifact runs, so V2D source
never reaches the public artifact channel.
Bumping the bundled robotic_grounding#
Edit the SHA in deps/v2d/version.txt and rerun
scripts/setup_v2d_src.sh.