Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@
#
# Exceptions for small source SVGs (webpack-inlined; not binary assets).
deps/cloudxr/webxr_client/src/icons/*.svg -filter -diff -merge text

*.usd filter=lfs diff=lfs merge=lfs -text
*.usda filter=lfs diff=lfs merge=lfs -text
*.stl filter=lfs diff=lfs merge=lfs -text
*.STL filter=lfs diff=lfs merge=lfs -text
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ __pycache__/
*.pyd
# Python virtual environments
.venv/
.venv-isaacteleop/
venv/
**/.venv/
**/venv/
Expand Down Expand Up @@ -64,3 +65,17 @@ deps/v2d/wheels/

# Runtime device files injected by MCP server infrastructure
.mcp.json

apv_wuji
avp_ee_hand.md
cmd
AGENTS.md
custom.env
web.env
example_demo
build-local/
deps/cloudxr/webxr_client/helpers/react/CloudXRComponent.tsx
deps/cloudxr/webxr_client/src/App.tsx
deps/cloudxr/webxr_client/src/CloudXRUI.tsx
examples/teleop/CMakeLists.txt
examples/teleop/python/pyproject.toml
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "wuji-retargeting"]
path = third_party/wuji-retargeting
url = https://github.com/wuji-technology/wuji-retargeting.git
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ only point here — edit the rules in the doc, not the shims.
```

- If a hook failure shows **missing or non-obvious repo policy** (not a one-off typo), you **must** add a **short** reminder under **Mandatory learning loop** rules to the right `AGENTS.md` or adjacent **`//` comments** so the next run does not repeat it—unless it is already documented.
- If `pre-commit` is unavailable in the active environment, report the exact blocker and any narrower checks that did run; do not describe the pre-commit gate as passed.

## Mandatory learning loop (AGENTS.md and comments)

Expand All @@ -110,6 +111,8 @@ only point here — edit the rules in the doc, not the shims.

- **High-level** expectations: boundaries between layers, what to avoid, naming or structural conventions, CMake/include policy at a glance, “always / never” rules that stay true across refactors.
- **Style of work**: how minimal to keep diffs, when to ask for clarification, how this subsystem should relate to OpenXR/schema/deviceio, etc.
- For onboarding-oriented shell helpers, keep the flow as a short step-by-step runbook and make separate Python environment responsibilities explicit instead of mixing them into one opaque setup path.
- For shell-script comments meant for humans to follow, prefer short numbered Chinese step comments that mirror repo runbooks (for example the root `cmd` note) over scattered low-level inline commentary.
- For build-only requests, use the documented CMake flags and environment first (for example `-DISAAC_TELEOP_PYTHON_VERSION=...`) rather than patching build files to select options.

**What does *not* belong in `AGENTS.md`**
Expand Down
10 changes: 10 additions & 0 deletions REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,13 @@ path = ".cursor/**"
precedence = "override"
SPDX-FileCopyrightText = "Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved."
SPDX-License-Identifier = "Apache-2.0"

[[annotations]]
path = [
"examples/g1_wuji_teleop/assets/g1_wuji/**",
"examples/g1_wuji_teleop/assets/wuji_hand/**",
"examples/teleop/python/assets/wuji_hand/**",
]
precedence = "override"
SPDX-FileCopyrightText = "Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved."
SPDX-License-Identifier = "Apache-2.0"
173 changes: 173 additions & 0 deletions avp_manus.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#!/usr/bin/env bash
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# IsaacTeleop AVP + MANUS + G1-Wuji demo runbook
#
# Notes:
# 1. This file is a step-by-step command guide. Do not execute it end to end
# with `bash avp_manus.sh`.
# 2. A working team Isaac Lab environment is assumed. Isaac Lab installation
# steps are intentionally omitted here.
# 3. This demo defaults to `examples/g1_wuji_teleop/config/avp_manus.yml`.
# It uses `retargeting.method=official_wuji`, so the
# `third_party/wuji-retargeting` submodule must be initialized first.
# 4. The commands below assume Python 3.12. The Python major/minor version used
# to build `isaacteleop` must match the Python version in your Isaac Lab
# environment. If your Isaac Lab is not using 3.12, update the `3.12`
# references below accordingly.
#
# -----------------------------------------------------------------------------
# 0. Enter the repository root
# -----------------------------------------------------------------------------

cd /path/to/IsaacTeleop

# -----------------------------------------------------------------------------
# 1. Install Ubuntu system dependencies
# -----------------------------------------------------------------------------

sudo apt-get update
sudo apt-get install -y \
build-essential \
cmake \
clang-format-14 \
ccache \
patchelf \
curl \
git \
unzip \
usbutils \
android-tools-adb \
coturn \
libx11-dev \
libssl-dev \
zlib1g-dev \
libc-ares-dev \
libzmq3-dev \
libncurses-dev \
libudev-dev \
libusb-1.0-0-dev \
libvulkan-dev \
glslang-tools \
libxrandr-dev \
libxinerama-dev \
libxcursor-dev \
libxi-dev \
libxext-dev \
libxkbcommon-dev \
libwayland-dev \
wayland-protocols

# -----------------------------------------------------------------------------
# 2. Create and activate the `isaacteleop` conda environment
# -----------------------------------------------------------------------------

conda create -n isaacteleop python=3.12 -y
conda activate isaacteleop
# From PyPI
pip install 'isaacteleop[cloudxr,retargeters]~=1.0.0' --extra-index-url https://pypi.nvidia.com
# python -m pip install --upgrade pip
# python -m pip install uv pre-commit

# -----------------------------------------------------------------------------
# 3. Build IsaacTeleop from source and install the wheel into the `isaacteleop`
# conda environment
# -----------------------------------------------------------------------------

cd /path/to/IsaacTeleop

cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DISAAC_TELEOP_PYTHON_VERSION=3.12 \
-DBUILD_VIZ=OFF \
-DBUILD_PLUGIN_OAK_CAMERA=OFF \
-DENABLE_CLANG_FORMAT_CHECK=OFF

cmake --build build --parallel "$(nproc)"
cmake --install build

python -m pip install -r /path/to/IsaacTeleop/src/core/python/requirements-retargeters.txt
python -m pip install -r /path/to/IsaacTeleop/src/core/python/requirements-cloudxr.txt
python -m pip install --force-reinstall /path/to/IsaacTeleop/install/wheels/isaacteleop-*.whl

python -c "import isaacteleop, isaacteleop.cloudxr, isaacteleop.retargeters; print(isaacteleop.__file__)"

# -----------------------------------------------------------------------------
# 4. Pull the wuji official wuji-retargeting
# -----------------------------------------------------------------------------
cd /path/to/IsaacTeleop
git submodule update --init --recursive third_party/wuji-retargeting

# -----------------------------------------------------------------------------
# 5. Install MANUS host permissions and the SDK / plugin
# -----------------------------------------------------------------------------

cd /path/to/IsaacTeleop/src/plugins/manus

# 5.1 This step must run on the host, not inside a container
./install_udev_rules.sh

# 5.2 Unplug and replug the MANUS dongle

# 5.3 Download the MANUS SDK, then build and install the plugin
./install_manus.sh

cd /path/to/IsaacTeleop
ls -l install/plugins/manus/
ls -l install/bin/manus_hand_tracker_printer

# -----------------------------------------------------------------------------
# 6. Open the ports required for AVP to connect to CloudXR
# -----------------------------------------------------------------------------

sudo ufw allow 48010,48322/tcp
sudo ufw allow 47998:48000,48005,48008,48012/udp

# -----------------------------------------------------------------------------
# 7. Terminal A: start the CloudXR runtime
# -----------------------------------------------------------------------------

cd /path/to/IsaacTeleop
conda activate isaacteleop

echo 'NV_DEVICE_PROFILE=auto-native' > custom.env
python -m isaacteleop.cloudxr --cloudxr-env-config=./custom.env --accept-eula

# Keep terminal A running.

# -----------------------------------------------------------------------------
# 8. Check the local IP address and connect from the AVP device
# -----------------------------------------------------------------------------


# Manual steps on the AVP side:
# 1. Open Isaac XR Teleop Sample Client (version 3.0.0 or newer).
# 2. Enter the Ubuntu LAN IP address found above.
# 3. Connect and keep the session alive.

# -----------------------------------------------------------------------------
# 9. Terminal B: load the CloudXR environment and verify MANUS data first
# -----------------------------------------------------------------------------

cd /path/to/IsaacTeleop
source ~/.cloudxr/run/cloudxr.env

./install/bin/manus_hand_tracker_printer

# Once hand data and the visualization window are updating correctly, close
# `manus_hand_tracker_printer`.
# Note: the MANUS SDK can only be owned by one process at a time, so the
# printer must be closed before starting the main demo.

# -----------------------------------------------------------------------------
# 10. Terminal C: run the final demo
# -----------------------------------------------------------------------------

cd /path/to/IsaacTeleop
source ~/.cloudxr/run/cloudxr.env
conda activate isaacteleop
python examples/g1_wuji_teleop/scripts/g1_wuji_teleop_main.py \
--config /examples/g1_wuji_teleop/config/avp_manus.yml \
--device cuda:0 \
Comment on lines +170 to +172

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fix invalid config path in the final demo command.

Line 171 uses an absolute path (/examples/...) that won’t resolve from the repo checkout and will break the main launch step. Use a repo-relative path or the full /path/to/IsaacTeleop/... path.

Suggested fix
 python examples/g1_wuji_teleop/scripts/g1_wuji_teleop_main.py \
-    --config /examples/g1_wuji_teleop/config/avp_manus.yml \
+    --config examples/g1_wuji_teleop/config/avp_manus.yml \
     --device cuda:0 \
     --viz kit
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
python examples/g1_wuji_teleop/scripts/g1_wuji_teleop_main.py \
--config /examples/g1_wuji_teleop/config/avp_manus.yml \
--device cuda:0 \
python examples/g1_wuji_teleop/scripts/g1_wuji_teleop_main.py \
--config examples/g1_wuji_teleop/config/avp_manus.yml \
--device cuda:0 \
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@avp_manus.sh` around lines 170 - 172, The final demo launch command uses an
invalid config path that will not resolve from a normal repo checkout. Update
the config argument in the main teleop command in avp_man.sh to use a
repo-relative path or the correct full IsaacTeleop path, and make sure the
g1_wuji_teleop_main.py invocation still points to the avp_manus.yml config
correctly.

--viz kit
Loading