From 8bfc876f974f41bcd66979f55b88358558566bbf Mon Sep 17 00:00:00 2001 From: Ivan Yang Date: Tue, 27 Oct 2026 22:23:17 -0700 Subject: [PATCH 1/6] docs(examples): install the local isaaccapture build the canonical way The converted examples installed the local build with an unpinned --find-links command and no --reinstall-package, and none said to activate a venv. A local build is always X.Y+local, so uv kept the old wheel after a rebuild, and an unpinned resolve could pick another wheel from install/wheels. examples/README.md now states the rule once and points at step 4 of Build from source. Each example README, its docs-site page and the plugin READMEs that install an example link to it; noitom and oglo_tactile inline the step 4 command with the cloudxr extra. The pip form in references/build.rst gains --force-reinstall to match step 4. Part of #985. Signed-off-by: Ivan Yang --- .../source/development/build_from_source/index.rst | 2 ++ docs/source/device/body_tracking/soma.rst | 3 ++- docs/source/device/hand_tracking/sharpa_avatar.rst | 3 ++- .../device/trackers/vive_ultimate_tracker.rst | 3 ++- docs/source/references/build.rst | 6 +++--- docs/source/references/haptic_feedback.rst | 5 ++--- docs/source/references/mcap_record_replay.rst | 6 +++--- docs/source/references/retargeting/sharpa.rst | 3 ++- docs/source/references/retargeting/wuji.rst | 3 ++- examples/README.md | 14 +++++++++++++- examples/cloudxr_mujoco_teleop/README.md | 5 ++--- examples/deviceio_live_view/README.md | 1 + examples/haptic_feedback/README.md | 5 ++--- examples/mcap_record_replay/README.md | 3 ++- examples/noitom/README.md | 11 ++++++++--- examples/oglo_tactile/README.md | 11 ++++++++++- examples/retargeting/README.md | 5 +++-- examples/robot_viz/README.md | 4 +++- examples/robot_viz/pyproject.toml | 3 ++- examples/sharpa_avatar/README.md | 2 ++ examples/soma_body_publisher/README.md | 3 ++- examples/soma_hand_publisher/README.md | 3 ++- examples/tactile/README.md | 3 ++- examples/teleop_session_manager/README.md | 3 ++- src/plugins/noitom_mocap/README.md | 2 +- src/plugins/vive_se3_tracker/README.md | 3 ++- 26 files changed, 79 insertions(+), 36 deletions(-) diff --git a/docs/source/development/build_from_source/index.rst b/docs/source/development/build_from_source/index.rst index b8d373f6f0..469332ac30 100644 --- a/docs/source/development/build_from_source/index.rst +++ b/docs/source/development/build_from_source/index.rst @@ -332,6 +332,8 @@ When ``BUILD_TESTING`` is ``ON``, CTest is enabled at the top level. Run all tes The CI uses ``ctest`` (see :code-file:`build-ubuntu.yml <.github/workflows/build-ubuntu.yml>`). +.. _build-from-source-install-package: + 4. Install the ``isaaccapture`` pip package ------------------------------------------- diff --git a/docs/source/device/body_tracking/soma.rst b/docs/source/device/body_tracking/soma.rst index b0349a181b..25ee69caa1 100644 --- a/docs/source/device/body_tracking/soma.rst +++ b/docs/source/device/body_tracking/soma.rst @@ -87,7 +87,8 @@ Build the examples Start with a configured Isaac Capture checkout. See :doc:`../../development/build_from_source/index` for the complete build -prerequisites. Install the live viewer and both deterministic publishers: +prerequisites. Install the live viewer and both deterministic publishers into a venv +set up as in :ref:`step 4 of Build from source `: .. code-block:: bash diff --git a/docs/source/device/hand_tracking/sharpa_avatar.rst b/docs/source/device/hand_tracking/sharpa_avatar.rst index a7cde9d791..3d9326812b 100644 --- a/docs/source/device/hand_tracking/sharpa_avatar.rst +++ b/docs/source/device/hand_tracking/sharpa_avatar.rst @@ -118,7 +118,8 @@ See :ref:`dedicated-cloudxr-runtime` and ``TeleopSession`` can launch the same binary through ``plugin.yaml``. The visualization example does that for you (CloudXR and the plugin start unless -you opt out): +you opt out). Run it from the repository root, in a venv set up as in +:ref:`step 4 of Build from source `: .. code-block:: bash diff --git a/docs/source/device/trackers/vive_ultimate_tracker.rst b/docs/source/device/trackers/vive_ultimate_tracker.rst index 8c86c0b15f..4f20b5d4e6 100644 --- a/docs/source/device/trackers/vive_ultimate_tracker.rst +++ b/docs/source/device/trackers/vive_ultimate_tracker.rst @@ -214,7 +214,8 @@ printer. Use a collection id printed by the plugin in Step 7: Step 9 (optional): Record and replay ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Install the examples package once, from the Isaac Capture root: +Install the examples package once, from the Isaac Capture root, in a venv set up as in +:ref:`step 4 of Build from source `: .. code-block:: bash diff --git a/docs/source/references/build.rst b/docs/source/references/build.rst index f9b281c7dd..9938c3501f 100644 --- a/docs/source/references/build.rst +++ b/docs/source/references/build.rst @@ -57,8 +57,8 @@ The project uses a modern CMake target-based approach. Libraries export namespac Using the Python wheel ---------------------- -After building, activate a virtual environment with the build's Python version (step 4 of -:doc:`/development/build_from_source/index` shows how), then install the wheels with ``uv`` or +After building, activate a virtual environment with the build's Python version +(:ref:`step 4 of Build from source ` shows how), then install the wheels with ``uv`` or ``pip``, pinning the local build's version ``X.Y+local`` (``X.Y`` from the repository's ``VERSION`` file): @@ -69,7 +69,7 @@ file): uv pip install "isaaccapture==X.Y+local" --find-links=./install/wheels/ --reinstall-package isaaccapture # or - pip install "isaaccapture==X.Y+local" --find-links=./install/wheels/ + pip install "isaaccapture==X.Y+local" --find-links=./install/wheels/ --force-reinstall The wheel carries the ``isaacteleop`` compatibility alias, which will be removed in 1.9, so diff --git a/docs/source/references/haptic_feedback.rst b/docs/source/references/haptic_feedback.rst index 9c06fa3dbf..80ebc30a28 100644 --- a/docs/source/references/haptic_feedback.rst +++ b/docs/source/references/haptic_feedback.rst @@ -67,9 +67,8 @@ Running The example connects through the CloudXR / OpenXR runtime, which it starts itself if nothing is serving (see :ref:`dedicated-cloudxr-runtime` to manage -that service yourself). Install ``isaaccapture`` built from this tree into the -active environment first, for example -``uv pip install "isaaccapture[cloudxr]" --find-links=./install/wheels/``. +that service yourself). From the repository root, set up a venv and install +``isaaccapture`` into it as in :ref:`step 4 of Build from source `. Then install the example and run it: .. code-block:: bash diff --git a/docs/source/references/mcap_record_replay.rst b/docs/source/references/mcap_record_replay.rst index 76cd1c68d6..0743407959 100644 --- a/docs/source/references/mcap_record_replay.rst +++ b/docs/source/references/mcap_record_replay.rst @@ -156,7 +156,7 @@ additional source nodes (``HeadSource``, ``ControllersSource``, …) in For a live browser view of **all** human DeviceIO trackers at once (hands, head, controllers, and full body), see ``examples/deviceio_live_view/`` and its -``README.md``: +``README.md``. From the repo root, in a venv set up as in :ref:`step 4 of Build from source `: .. code-block:: bash @@ -173,7 +173,7 @@ A C++ recorder lives at ``examples/mcap_record_replay/cpp/``: Live preview ^^^^^^^^^^^^ -From the repo root: +From the repo root, in a venv set up as in :ref:`step 4 of Build from source `: .. code-block:: bash @@ -188,7 +188,7 @@ opened from another machine; pass ``--host 127.0.0.1`` to keep one local. Recording ^^^^^^^^^ -From the repo root: +From the repo root, in the same venv: .. code-block:: bash diff --git a/docs/source/references/retargeting/sharpa.rst b/docs/source/references/retargeting/sharpa.rst index 8ae0368b38..247673038c 100644 --- a/docs/source/references/retargeting/sharpa.rst +++ b/docs/source/references/retargeting/sharpa.rst @@ -125,7 +125,8 @@ produced in your target joint order. Run the example --------------- -The repo ships a bimanual demo in ``examples/retargeting``: +The repo ships a bimanual demo in ``examples/retargeting``. Install it from the +repository root, in a venv set up as in :ref:`step 4 of Build from source `: .. code-block:: console diff --git a/docs/source/references/retargeting/wuji.rst b/docs/source/references/retargeting/wuji.rst index da45c7535c..bfb00bc082 100644 --- a/docs/source/references/retargeting/wuji.rst +++ b/docs/source/references/retargeting/wuji.rst @@ -65,7 +65,8 @@ Run the example --------------- The example supports a device-free synthetic pose, recorded keypoints, and a -real Wuji hand: +real Wuji hand. Install it from the repository root, in a venv set up as in +:ref:`step 4 of Build from source `: .. code-block:: console diff --git a/examples/README.md b/examples/README.md index f3d5245ce2..5078e3886c 100644 --- a/examples/README.md +++ b/examples/README.md @@ -10,12 +10,24 @@ your own project — the last of those is the reason for the layout below. ## Running an example +Build Isaac Capture from source, then set up a venv from the repository root +exactly as in [step 4 of Build from source][install-step]: create it on the +build's Python, activate it, and install `isaaccapture` pinned to `X.Y+local` +with `--reinstall-package isaaccapture`, so a rebuild replaces the installed +wheel. `uv pip install` finds a repo-root `.venv` even when it is inactive and +`python` does not, so activate it in every terminal you run an example from. + ```bash uv pip install -e ./examples/ python -m isaaccapture_examples. ``` -Every example runs this way, and its `README.md` gives the exact command. +Every example runs this way, and its `README.md` gives the exact command. An +example whose `pyproject.toml` points `[tool.uv.sources]` at this checkout +replaces that wheel with an editable build of the checkout, and its first +install compiles the extensions. + +[install-step]: https://nvidia.github.io/IsaacCapture/main/development/build_from_source/index.html#install-the-isaaccapture-pip-package An example with one obvious entry point puts it in `__main__.py`, so `python -m isaaccapture_examples.` runs it. An example that is several diff --git a/examples/cloudxr_mujoco_teleop/README.md b/examples/cloudxr_mujoco_teleop/README.md index 58de8b31b2..dc5bd35380 100644 --- a/examples/cloudxr_mujoco_teleop/README.md +++ b/examples/cloudxr_mujoco_teleop/README.md @@ -24,9 +24,8 @@ Assumes IsaacTeleop is already built and installed in this tree. ```bash curl -LsSf https://astral.sh/uv/install.sh | sh ``` - With `isaaccapture` built from this tree already installed in the active - environment (for example - `uv pip install "isaaccapture[cloudxr]" --find-links=./install/wheels/`), + With the venv set up and `isaaccapture` installed as in + [Running an example](../README.md#running-an-example), install the example once; this pulls its Python dependencies (`mujoco`, `numpy`, `scipy` — see `pyproject.toml`): ```bash diff --git a/examples/deviceio_live_view/README.md b/examples/deviceio_live_view/README.md index 949f86aaa0..dde0997a24 100644 --- a/examples/deviceio_live_view/README.md +++ b/examples/deviceio_live_view/README.md @@ -9,6 +9,7 @@ Draws live DeviceIO human tracking — hands, head, controllers, full body — i browser with [viser](https://viser.studio). Trackers that are inactive or absent are hidden rather than drawn in an error color. `CloudXRLauncher` starts the CloudXR runtime and WSS proxy itself, so there is nothing to launch separately. +In a venv set up as in [Running an example](../README.md#running-an-example): ```bash uv pip install -e ./examples/deviceio_live_view diff --git a/examples/haptic_feedback/README.md b/examples/haptic_feedback/README.md index 52d427e98b..2fa49c95bf 100644 --- a/examples/haptic_feedback/README.md +++ b/examples/haptic_feedback/README.md @@ -14,9 +14,8 @@ flushes to an `IHapticDevice` adapter each frame. | `controller_haptic_example` | Pull a controller trigger to rumble that same controller — the minimal in-process `HapticSink` → `ControllerHapticDevice` wiring. | | `hand_pinch_haptic_example` | Pinch a fingertip toward the thumb to vibrate a haptic glove — the cross-process path (`HapticSink` → `PushTensorHapticDevice`, pushing a `HapticCommand` to a glove plugin such as Manus). | -Install `isaaccapture` built from this tree into the active environment -first, for example -`uv pip install "isaaccapture[cloudxr]" --find-links=./install/wheels/`. +Set up the venv and install `isaaccapture` as in +[Running an example](../README.md#running-an-example), then: ```bash uv pip install -e ./examples/haptic_feedback diff --git a/examples/mcap_record_replay/README.md b/examples/mcap_record_replay/README.md index 33d1cc9d4a..0d636f8604 100644 --- a/examples/mcap_record_replay/README.md +++ b/examples/mcap_record_replay/README.md @@ -6,7 +6,8 @@ SPDX-License-Identifier: Apache-2.0 # MCAP record / replay Record DeviceIO tracking to an MCAP file and replay it into a viser 3D view. -Live viewers are included for watching without recording. +Live viewers are included for watching without recording. In a venv set up +as in [Running an example](../README.md#running-an-example): ```bash uv pip install -e ./examples/mcap_record_replay diff --git a/examples/noitom/README.md b/examples/noitom/README.md index 5399cc6c2d..aaf0e2b25c 100644 --- a/examples/noitom/README.md +++ b/examples/noitom/README.md @@ -28,11 +28,17 @@ optional plugin when you need Noitom support: cmake -B build -DBUILD_PLUGIN_NOITOM_MOCAP=ON -DISAAC_TELEOP_PYTHON_VERSION=3.12 cmake --build build --target python_package python_wheel noitom_mocap_plugin --parallel cmake --install build -uv pip install --find-links=install/wheels "isaaccapture[cloudxr]" +uv venv --python 3.12 --seed .venv +source .venv/bin/activate +uv pip install "isaaccapture[cloudxr]==X.Y+local" --find-links=./install/wheels/ --reinstall-package isaaccapture ``` Python 3.12 matches Isaac Lab 3.0, which Example 2 needs. The wheel installs only on the Python it was built for, so use a 3.12 venv for Example 1 too. +`X.Y` is your build's version, the first two numbers of the repository's +`VERSION` file. The venv and install lines follow +[Running an example](../README.md#running-an-example); activate the venv in +every terminal you run Example 1 from. Run `cmake --install build` again whenever `plugin.yaml` changes so the updated configuration is copied to `install/plugins/noitom_mocap/plugin.yaml`. @@ -81,8 +87,7 @@ The callback runs inside Isaac Lab's own interpreter, so install isaaccapture and this example into *that* environment rather than a venv of your own. Build with `-DISAAC_TELEOP_PYTHON_VERSION=3.12` as above: Isaac Lab 3.0 runs Python 3.12, and pip skips a wheel built for another version. Deactivate any venv -first, because `isaaclab.sh -p` uses `$VIRTUAL_ENV` when it is set. `X.Y` is -your build's version, the first two numbers of the repository's `VERSION` file. +first, because `isaaclab.sh -p` uses `$VIRTUAL_ENV` when it is set. ```bash deactivate # only if a venv is active diff --git a/examples/oglo_tactile/README.md b/examples/oglo_tactile/README.md index 0639f4c8b7..b349b5e8be 100644 --- a/examples/oglo_tactile/README.md +++ b/examples/oglo_tactile/README.md @@ -43,10 +43,17 @@ session, records, and draws the overlay). `oglo_heatmap.py` is the renderer. cmake -B build -DBUILD_PLUGIN_OGLO=ON -DBUILD_VIZ=ON cmake --build build --parallel cmake --install build # builds the isaaccapture python wheel/package - uv pip install --find-links=install/wheels "isaaccapture[cloudxr]" + uv venv --python 3.11 --seed .venv + source .venv/bin/activate + uv pip install "isaaccapture[cloudxr]==X.Y+local" --find-links=./install/wheels/ --reinstall-package isaaccapture uv pip install -e ./examples/oglo_tactile ctest --test-dir build -R oglo_packet_parser --output-on-failure # parser sanity ``` + The venv and install lines follow + [Running an example](../README.md#running-an-example): `3.11` is the default + `ISAAC_TELEOP_PYTHON_VERSION` and `X.Y` the first two numbers of the + repository's `VERSION` file. + The BLE backend (BlueZ via libdbus, permissive) connects out of the box. CuPy for the in-headset overlay comes with `isaaccapture[cloudxr]`. @@ -67,6 +74,7 @@ session, records, and draws the overlay). `oglo_heatmap.py` is the renderer. **Start the CloudXR runtime** — a background service, so this shell stays free ```bash cd +source .venv/bin/activate source scripts/setup_cloudxr_env.sh python -m isaaccapture.cloudxr.service start --accept-eula # flag needed on first run only # Note the printed web-client URL, e.g. https://:48322/ @@ -82,6 +90,7 @@ python -m isaaccapture.cloudxr.service start --accept-eula # flag needed on fi **Gloves + recording + overlay** ```bash cd +source .venv/bin/activate source scripts/setup_cloudxr_env.sh source ~/.cloudxr/run/cloudxr.env # path printed by step above python -m isaaccapture_examples.oglo_tactile.oglo_teleop_record diff --git a/examples/retargeting/README.md b/examples/retargeting/README.md index aef93878a8..7d2ecaa887 100644 --- a/examples/retargeting/README.md +++ b/examples/retargeting/README.md @@ -5,8 +5,9 @@ SPDX-License-Identifier: Apache-2.0 # Retargeting engine examples -Standalone demos of the retargeting engine. Install once, then run whichever -one you want: +Standalone demos of the retargeting engine. In a venv set up as in +[Running an example](../README.md#running-an-example), install once, then run +whichever one you want: ```bash uv pip install -e ./examples/retargeting diff --git a/examples/robot_viz/README.md b/examples/robot_viz/README.md index f1960bcb68..b0d8e91717 100644 --- a/examples/robot_viz/README.md +++ b/examples/robot_viz/README.md @@ -49,6 +49,8 @@ cmake --build build --parallel There is no flag for the twin: a Linux `BUILD_VIZ` build has it. The first configure fetches MuJoCo and its six vendored dependencies from GitHub and compiles them (~40 s on 12 cores). +Then run `cmake --install build`, and install the wheel and this example as in [Running an example](../README.md#running-an-example). + To just run it, `uv pip install .` drives the same CMake and skips the `build/` tree: ```bash @@ -57,7 +59,7 @@ uv pip install -e ./examples/robot_viz # same environment python -m isaaccapture_examples.robot_viz ``` -Both must land in one environment. Beware `uv pip install isaaccapture` without a path or `--find-links`: it does not resolve at all until `isaaccapture` is published, and once it is, it resolves to a release with no robot twin in it. +Both must land in one environment. Beware `uv pip install isaaccapture` without a path or the `==X.Y+local` pin: it does not resolve at all until `isaaccapture` is published, and once it is, it resolves to a release with no robot twin in it. Running additionally needs a GPU with EGL + CUDA, and a headset. On a multi-GPU host, pass the GPU: `SceneTwin` takes a `gl_device_index`, which indexes EGL devices and need not agree with CUDA's ordering. The renderer checks at construction and names both device numbers. diff --git a/examples/robot_viz/pyproject.toml b/examples/robot_viz/pyproject.toml index 35819fc507..a495e1f3d3 100644 --- a/examples/robot_viz/pyproject.toml +++ b/examples/robot_viz/pyproject.toml @@ -4,7 +4,8 @@ # Pure Python -- nothing here is compiled. The scene backend lives in # isaaccapture.viz.robot, which ships with Televiz on Linux. # -# uv pip install "isaaccapture[cloudxr]" --find-links=./install/wheels/ +# Install isaaccapture as in examples/README.md, "Running an example", then: +# # uv pip install -e ./examples/robot_viz # python -m isaaccapture_examples.robot_viz # needs a headset; fetches its # # scene on the first run diff --git a/examples/sharpa_avatar/README.md b/examples/sharpa_avatar/README.md index 1806a04b04..b01217b39c 100644 --- a/examples/sharpa_avatar/README.md +++ b/examples/sharpa_avatar/README.md @@ -18,6 +18,8 @@ Install them first, then run this example against the installed plugin. ## Run +Run the last two commands in a venv set up as in [Running an example](../README.md#running-an-example). + ```bash ./src/plugins/sharpa_avatar/install_avatar_sdk.sh cmake -B build \ diff --git a/examples/soma_body_publisher/README.md b/examples/soma_body_publisher/README.md index ee5652ee70..99f715520c 100644 --- a/examples/soma_body_publisher/README.md +++ b/examples/soma_body_publisher/README.md @@ -24,7 +24,8 @@ SOMA-X example_animation.npy -> SchemaPusher collection soma_body_demo ``` -Install the example: +Install the example into a venv set up as in +[Running an example](../README.md#running-an-example): ```bash uv pip install -e ./examples/soma_body_publisher diff --git a/examples/soma_hand_publisher/README.md b/examples/soma_hand_publisher/README.md index 115994afed..cd4e29a92d 100644 --- a/examples/soma_hand_publisher/README.md +++ b/examples/soma_hand_publisher/README.md @@ -24,7 +24,8 @@ SOMA-X example_animation.npy -> left/right SchemaPusher collections ``` -Install the example: +Install the example into a venv set up as in +[Running an example](../README.md#running-an-example): ```bash uv pip install -e ./examples/soma_hand_publisher diff --git a/examples/tactile/README.md b/examples/tactile/README.md index 8dc7486fe6..3b7266b2fd 100644 --- a/examples/tactile/README.md +++ b/examples/tactile/README.md @@ -20,7 +20,8 @@ feeder -> "tactile" (TactileDataArray, every frame) -> TactileTracker -> printer, and tactile/* MCAP channels ``` -Install the example: +Install the example into a venv set up as in +[Running an example](../README.md#running-an-example): ```bash uv pip install -e ./examples/tactile diff --git a/examples/teleop_session_manager/README.md b/examples/teleop_session_manager/README.md index 9b54d90d02..5d5a777aa8 100644 --- a/examples/teleop_session_manager/README.md +++ b/examples/teleop_session_manager/README.md @@ -5,7 +5,8 @@ SPDX-License-Identifier: Apache-2.0 # TeleopSessionManager examples -Four standalone demos of the `TeleopSession` API. Install once, then run +Four standalone demos of the `TeleopSession` API. In a venv set up as in +[Running an example](../README.md#running-an-example), install once, then run whichever one you want: ```bash diff --git a/src/plugins/noitom_mocap/README.md b/src/plugins/noitom_mocap/README.md index c3fbc35d58..3ad68651e1 100644 --- a/src/plugins/noitom_mocap/README.md +++ b/src/plugins/noitom_mocap/README.md @@ -58,7 +58,7 @@ python src/plugins/noitom_mocap/tools/noitom_mocap_printer.py --duration=10 ``` Record through the Noitom example wrapper and replay with the shared MCAP -script: +script, in a venv set up as in [Running an example](../../../examples/README.md#running-an-example): ```bash uv pip install -e ./examples/noitom diff --git a/src/plugins/vive_se3_tracker/README.md b/src/plugins/vive_se3_tracker/README.md index 5600f5c71d..378b076d68 100644 --- a/src/plugins/vive_se3_tracker/README.md +++ b/src/plugins/vive_se3_tracker/README.md @@ -102,7 +102,8 @@ with no arguments. Stale files from a crashed run are cleared on the next startu ## Recording / replay (Python examples) -Both run with no arguments once the plugin is up: +Both run with no arguments once the plugin is up, in a venv set up as in +[Running an example](../../../examples/README.md#running-an-example): ```bash uv pip install -e ./examples/mcap_record_replay From 4c1c598e9ed5f5128430c8e171b2d9f0f56f733a Mon Sep 17 00:00:00 2001 From: Ivan Yang Date: Tue, 27 Oct 2026 23:03:17 -0700 Subject: [PATCH 2/6] docs(examples): cover rebuilds of editable examples and Isaac Lab Examples that point [tool.uv.sources] at the checkout keep uv's cached editable build, so a C++ rebuild never reached them. examples/README.md and the mcap_record_replay page now say to reinstall such an example with --reinstall-package isaaccapture, and the README says to rerun the step 4 install after each rebuild. noitom's Isaac Lab install gains a rebuild command: pip treats an installed X.Y+local as satisfied, so it needs --force-reinstall, and --no-deps keeps Isaac Lab's other packages in place. Drop the mcap_record_replay note that offered `uv run --python 3.11` instead of the activated venv. No lockfile is tracked, and on a build for another Python it recreates the repo-root .venv. robot_viz no longer claims an unpinned isaaccapture fails to resolve; the package index serves a release that is not the local build. Part of #985. Signed-off-by: Ivan Yang --- docs/source/references/mcap_record_replay.rst | 7 ++----- examples/README.md | 11 +++++++---- examples/mcap_record_replay/README.md | 4 ---- examples/noitom/README.md | 10 ++++++++++ examples/robot_viz/README.md | 2 +- examples/robot_viz/pyproject.toml | 7 +++---- 6 files changed, 23 insertions(+), 18 deletions(-) diff --git a/docs/source/references/mcap_record_replay.rst b/docs/source/references/mcap_record_replay.rst index 0743407959..4d24fe7a7b 100644 --- a/docs/source/references/mcap_record_replay.rst +++ b/docs/source/references/mcap_record_replay.rst @@ -205,7 +205,8 @@ The example never downloads a published wheel — it runs against the ``isaaccapture`` next to it, built from this checkout. The first install compiles the extension modules and takes a few minutes; later ones reuse the cached build, and the install is editable, so edits under ``src/python/`` need -no rebuild. From ``install/examples/mcap_record_replay`` (after ``cmake +no rebuild. After a C++ change, add ``--reinstall-package isaaccapture`` to the +install to rebuild it. From ``install/examples/mcap_record_replay`` (after ``cmake --install``) it picks up the wheel you just built instead — see :doc:`/development/build_from_source/index`. @@ -235,10 +236,6 @@ The ``record_controller`` / ``replay_controller`` and ``record_full_body`` / ``--host``, ``--port``). ``live_full_body`` accepts ``--host``, ``--port``, and the CloudXR launcher flags (including ``--accept-eula``). -``uv run`` (instead of an activated venv) needs an explicit ``--python 3.11`` -— without it, ``uv`` may resolve against the system Python and fail to match -the lockfile. - API Reference ------------- diff --git a/examples/README.md b/examples/README.md index 5078e3886c..57dc1bbd8d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -13,9 +13,10 @@ your own project — the last of those is the reason for the layout below. Build Isaac Capture from source, then set up a venv from the repository root exactly as in [step 4 of Build from source][install-step]: create it on the build's Python, activate it, and install `isaaccapture` pinned to `X.Y+local` -with `--reinstall-package isaaccapture`, so a rebuild replaces the installed -wheel. `uv pip install` finds a repo-root `.venv` even when it is inactive and -`python` does not, so activate it in every terminal you run an example from. +with `--reinstall-package isaaccapture`. Rerun that install after every +rebuild to replace the installed wheel. `uv pip install` finds a repo-root +`.venv` even when it is inactive and `python` does not, so activate it in every +terminal you run an example from. ```bash uv pip install -e ./examples/ @@ -25,7 +26,9 @@ python -m isaaccapture_examples. Every example runs this way, and its `README.md` gives the exact command. An example whose `pyproject.toml` points `[tool.uv.sources]` at this checkout replaces that wheel with an editable build of the checkout, and its first -install compiles the extensions. +install compiles the extensions. uv reuses that build, and rebuilding `build/` +does not reach it, so after a C++ change reinstall such an example with +`uv pip install -e ./examples/ --reinstall-package isaaccapture`. [install-step]: https://nvidia.github.io/IsaacCapture/main/development/build_from_source/index.html#install-the-isaaccapture-pip-package diff --git a/examples/mcap_record_replay/README.md b/examples/mcap_record_replay/README.md index 0d636f8604..7f2b96e73f 100644 --- a/examples/mcap_record_replay/README.md +++ b/examples/mcap_record_replay/README.md @@ -20,10 +20,6 @@ command; a replay given no path picks the newest matching recording there (e.g. `replay_hand` picks the newest `hands_*.mcap`) and exits if none match -- no silent fallback to a wrong-type recording. -`uv run` (instead of an activated venv) needs an explicit `--python 3.11` -- -without it, `uv` may resolve against the system Python and fail to match the -lockfile. - The live and replay viewers bind every interface, so a browser on another machine can reach them at `http://:8080`. Pass `--host 127.0.0.1` to keep a viewer local. Replay repeats until Ctrl+C; no loop flag is needed. diff --git a/examples/noitom/README.md b/examples/noitom/README.md index aaf0e2b25c..cd784ee42b 100644 --- a/examples/noitom/README.md +++ b/examples/noitom/README.md @@ -102,6 +102,16 @@ compatibility shim from your build, which maps `isaacteleop` to `isaaccapture`. Isaac Lab pins `isaacteleop~=1.4.145`, so pip may warn about that conflict. +pip treats an installed `X.Y+local` as already satisfied, so after a rebuild +replace it explicitly. `--no-deps` keeps pip from reinstalling Isaac Lab's +other packages: + +```bash +cd +./isaaclab.sh -p -m pip install "isaaccapture==X.Y+local" \ + --find-links /install/wheels --force-reinstall --no-deps +``` + ```bash cd ./isaaclab.sh -p scripts/environments/teleoperation/teleop_se3_agent.py \ diff --git a/examples/robot_viz/README.md b/examples/robot_viz/README.md index b0d8e91717..dbec59fc08 100644 --- a/examples/robot_viz/README.md +++ b/examples/robot_viz/README.md @@ -59,7 +59,7 @@ uv pip install -e ./examples/robot_viz # same environment python -m isaaccapture_examples.robot_viz ``` -Both must land in one environment. Beware `uv pip install isaaccapture` without a path or the `==X.Y+local` pin: it does not resolve at all until `isaaccapture` is published, and once it is, it resolves to a release with no robot twin in it. +Both must land in one environment. Install `isaaccapture` from a path, or with both `--find-links=./install/wheels/` and the `==X.Y+local` pin: otherwise uv can resolve it to a release from the package index, which is not your build and may have no robot twin in it. Running additionally needs a GPU with EGL + CUDA, and a headset. On a multi-GPU host, pass the GPU: `SceneTwin` takes a `gl_device_index`, which indexes EGL devices and need not agree with CUDA's ordering. The renderer checks at construction and names both device numbers. diff --git a/examples/robot_viz/pyproject.toml b/examples/robot_viz/pyproject.toml index a495e1f3d3..add4024725 100644 --- a/examples/robot_viz/pyproject.toml +++ b/examples/robot_viz/pyproject.toml @@ -24,10 +24,9 @@ description = "A robot's digital twin rendered into an Isaac Teleop Televiz XR s requires-python = ">=3.11,<3.14" dependencies = [ - # Unversioned, and a live hazard in both directions: until isaaccapture is - # published this does not resolve from an index at all, and once it is, it - # resolves happily against a release that is not this checkout's viz -- and - # against one with no robot twin at all. Install the locally built wheel first. + # Unversioned, and a live hazard: from a package index this resolves to a + # release that is not this checkout's viz, possibly one with no robot twin + # at all. Install the locally built wheel first. "isaaccapture[cloudxr]", # app.py imports numpy directly. "numpy", From 496bd0745ba6472be597da1149d265b1d4ca196f Mon Sep 17 00:00:00 2001 From: Ivan Yang Date: Tue, 27 Oct 2026 23:46:10 -0700 Subject: [PATCH 3/6] docs(examples): add demo extras, venv reuse and drop soma's cmake step The Sharpa and Wuji demos import their retargeters at startup, and step 4's extras include neither pink nor wuji_sdk, so both failed in the step 4 venv. Their run sections now say to add grounding or wuji to the extras step 4 installs, and the retargeting README table names them. uv refuses to recreate an existing venv without --clear, even on the same Python, so rerunning the step 4, noitom or oglo_tactile lines failed. Step 4 now says to reuse a .venv on the build's Python and to pass --clear only to switch Python. soma's build block ran .venv/bin/cmake, which a step 4 venv lacks, to stage isaacteleop_python into build/. The step 2 build already does that, and the editable soma examples never read build/, so drop it. Part of #985. Signed-off-by: Ivan Yang --- docs/source/development/build_from_source/index.rst | 3 +++ docs/source/device/body_tracking/soma.rst | 5 ----- docs/source/references/retargeting/sharpa.rst | 3 ++- docs/source/references/retargeting/wuji.rst | 3 ++- examples/retargeting/README.md | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/source/development/build_from_source/index.rst b/docs/source/development/build_from_source/index.rst index 469332ac30..7b270632ab 100644 --- a/docs/source/development/build_from_source/index.rst +++ b/docs/source/development/build_from_source/index.rst @@ -350,6 +350,9 @@ From the repository root: uv venv --python 3.11 --seed .venv source .venv/bin/activate +If ``.venv`` already exists on the build's Python, activate it and skip ``uv venv``. To switch it +to another Python, rerun ``uv venv`` with ``--clear``, which deletes everything installed in it. + Install it by version. A local build is always ``X.Y+local``, where ``X.Y`` is the first two numbers of the repository's ``VERSION`` file; they also appear in the wheel's file name. The pin selects your build for the venv's Python, so a newer published ``isaaccapture`` cannot replace it. diff --git a/docs/source/device/body_tracking/soma.rst b/docs/source/device/body_tracking/soma.rst index 25ee69caa1..8024e6f107 100644 --- a/docs/source/device/body_tracking/soma.rst +++ b/docs/source/device/body_tracking/soma.rst @@ -96,11 +96,6 @@ set up as in :ref:`step 4 of Build from source `: +repository root, in a venv set up as in :ref:`step 4 of Build from source `, +with ``grounding`` added to the extras that step installs: .. code-block:: console diff --git a/docs/source/references/retargeting/wuji.rst b/docs/source/references/retargeting/wuji.rst index bfb00bc082..27e274a0bd 100644 --- a/docs/source/references/retargeting/wuji.rst +++ b/docs/source/references/retargeting/wuji.rst @@ -66,7 +66,8 @@ Run the example The example supports a device-free synthetic pose, recorded keypoints, and a real Wuji hand. Install it from the repository root, in a venv set up as in -:ref:`step 4 of Build from source `: +:ref:`step 4 of Build from source `, with +``wuji`` added to the extras that step installs: .. code-block:: console diff --git a/examples/retargeting/README.md b/examples/retargeting/README.md index 7d2ecaa887..b6cac9cc8b 100644 --- a/examples/retargeting/README.md +++ b/examples/retargeting/README.md @@ -20,7 +20,7 @@ python -m isaaccapture_examples.retargeting.sources_example | `dual_source_teleop_example` | Two input sources driving one session | | `example_retargeters` | `GainOffsetRetargeter`, a minimal custom retargeter | | `multi_retargeter_tuning_demo_imgui` | Tuning several retargeters live, with an ImGui panel | -| `sharpa_hand_retargeter_demo` | Bimanual Sharpa hands; `--synthetic` needs no headset | -| `wuji_hand_retargeter_demo` | Wuji hand, in `synthetic` / `replay` / `drive` modes | +| `sharpa_hand_retargeter_demo` | Bimanual Sharpa hands; `--synthetic` needs no headset. Needs `isaaccapture[grounding]` | +| `wuji_hand_retargeter_demo` | Wuji hand, in `synthetic` / `replay` / `drive` modes. Needs `isaaccapture[wuji]` | Docs: `docs/source/references/retargeting/`. From f50e67b0bbd672b64914a4a4e11dfbe89896d251 Mon Sep 17 00:00:00 2001 From: Ivan Yang Date: Wed, 28 Oct 2026 12:03:54 -0700 Subject: [PATCH 4/6] fix(camera_viz): let setup --wheel find the isaacteleop transition wheel The isaaccapture wheel depends on isaacteleop>=1!1.6.dev0, which only the build's own wheel directory provides; the index serves isaacteleop up to 1.5. setup installed the wheel by path with no --find-links, so `camera_viz.sh setup --wheel` could not resolve any local build. Pass the wheel's directory as --find-links. Part of #985. Signed-off-by: Ivan Yang --- examples/camera_viz/scripts/_install_deps.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/camera_viz/scripts/_install_deps.sh b/examples/camera_viz/scripts/_install_deps.sh index da1fac0fcd..087558dacb 100755 --- a/examples/camera_viz/scripts/_install_deps.sh +++ b/examples/camera_viz/scripts/_install_deps.sh @@ -553,6 +553,9 @@ $WITH_RTP && PKGS+=("pybind11>=2.11" "PyGObject>=3.42,<3.52") # Local wheels keep version ``1.3+local`` across rebuilds; uv's --upgrade # no-ops on them. mtime probe forces a reinstall when the wheel's newer. EXTRA_UV=() +# The wheel depends on the isaacteleop transition wheel built beside it, which +# no index serves. +[[ "$MODE" == full && -n "$WHEEL" ]] && EXTRA_UV+=(--find-links "$(dirname "$WHEEL")") if [[ "$MODE" == full && -f "$WHEEL" ]]; then wheel_mtime=$(stat -c %Y "$WHEEL" 2>/dev/null || echo 0) # Empty on a fresh venv; `|| true` keeps the no-match from aborting under pipefail+set -e. From 29cc5fad755572ee86a537d51e4f73b798e25994 Mon Sep 17 00:00:00 2001 From: Ivan Yang Date: Wed, 28 Oct 2026 12:04:04 -0700 Subject: [PATCH 5/6] docs(examples): reuse an existing venv, state editable rebuilds once uv refuses to recreate an existing .venv without --clear, even on the same Python, so the inline uv venv lines in noitom and oglo_tactile now say to skip them on a matching venv and that --clear deletes its packages. Step 4 of Build from source now holds the one statement about examples whose [tool.uv.sources] point at the checkout: they replace the wheel with an editable build, and a C++ change needs --reinstall-package isaaccapture. examples/README.md and the mcap_record_replay page link to it instead of restating it, and the README names camera_viz and vehicle_teleop as the examples that keep their own .venv. camera_streaming's --wheel example named a glob, which expands to every wheel in the directory, and relied on setup's default Python 3.12 while a default build is cp311. It now names one install/wheels wheel with --python 3.11, and the flag table lists --python. noitom's Isaac Lab rebuild command moves after the launch block. Part of #985. Signed-off-by: Ivan Yang --- .../development/build_from_source/index.rst | 7 ++++++ docs/source/references/camera_streaming.rst | 12 ++++++++-- docs/source/references/mcap_record_replay.rst | 9 ++++---- examples/README.md | 12 +++++----- examples/noitom/README.md | 22 ++++++++++--------- examples/oglo_tactile/README.md | 2 +- 6 files changed, 40 insertions(+), 24 deletions(-) diff --git a/docs/source/development/build_from_source/index.rst b/docs/source/development/build_from_source/index.rst index 7b270632ab..69f7fc2c40 100644 --- a/docs/source/development/build_from_source/index.rst +++ b/docs/source/development/build_from_source/index.rst @@ -370,6 +370,13 @@ differently: # --reinstall-package replaces an already-installed isaaccapture, e.g. after a rebuild. uv pip install "isaaccapture[retargeters,cloudxr,ui]==X.Y+local" --find-links=./install/wheels/ --reinstall-package isaaccapture +.. _build-from-source-editable-examples: + +An example whose ``pyproject.toml`` points ``[tool.uv.sources]`` at this checkout replaces this +wheel with an editable build of the checkout when you install it. Its first install compiles the +extensions, and uv reuses that build afterwards, so after a C++ change reinstall the example with +``uv pip install -e ./examples/ --reinstall-package isaaccapture``. + The wheel carries the ``isaacteleop`` compatibility alias, which will be removed in 1.9, so ``import isaacteleop`` resolves without installing anything else. See diff --git a/docs/source/references/camera_streaming.rst b/docs/source/references/camera_streaming.rst index 293dc41119..3c84fe4660 100644 --- a/docs/source/references/camera_streaming.rst +++ b/docs/source/references/camera_streaming.rst @@ -123,16 +123,24 @@ needs. Flags trim or extend that: * - ``--wheel PATH`` - Install a locally built ``isaaccapture`` wheel instead of resolving one from the index — for developing Isaac Capture itself. + * - ``--python VERSION`` + - Python for the venv that ``setup`` creates (default 3.12). An existing ``.venv`` keeps its + Python. * - ``--build-from-source`` - Skip the package index and build ``isaaccapture`` from the surrounding checkout without prompting — a full C++ / CUDA / Vulkan build (see :doc:`/development/build_from_source/index`). -For example, to use a wheel built from this checkout, run from the repository root: +For example, to use a wheel built from this checkout, run from the repository root. Name one +wheel: ``install/wheels/`` keeps earlier builds, and ``--wheel`` takes a single path. ``X.Y`` is as +in :ref:`step 4 of Build from source `, and both the wheel's +``cp`` tag and ``--python`` must match the build's ``ISAAC_TELEOP_PYTHON_VERSION`` (3.11 by +default): .. code-block:: bash - examples/camera_viz/camera_viz.sh setup --wheel build/wheels/isaaccapture-*.whl + examples/camera_viz/camera_viz.sh setup --python 3.11 \ + --wheel install/wheels/isaaccapture-X.Y+local-cp311-cp311-linux_x86_64.whl .. _camera-streaming-external-venv: diff --git a/docs/source/references/mcap_record_replay.rst b/docs/source/references/mcap_record_replay.rst index 4d24fe7a7b..ab14c577d0 100644 --- a/docs/source/references/mcap_record_replay.rst +++ b/docs/source/references/mcap_record_replay.rst @@ -202,11 +202,10 @@ Recordings are written to ``./recordings/`` relative to where you run the command, and the replay scripts look there when given no path. The example never downloads a published wheel — it runs against the -``isaaccapture`` next to it, built from this checkout. The first install -compiles the extension modules and takes a few minutes; later ones reuse the -cached build, and the install is editable, so edits under ``src/python/`` need -no rebuild. After a C++ change, add ``--reinstall-package isaaccapture`` to the -install to rebuild it. From ``install/examples/mcap_record_replay`` (after ``cmake +``isaaccapture`` next to it, built from this checkout. The install is editable, +so edits under ``src/python/`` need no rebuild; for C++ changes see +:ref:`step 4 of Build from source `. From +``install/examples/mcap_record_replay`` (after ``cmake --install``) it picks up the wheel you just built instead — see :doc:`/development/build_from_source/index`. diff --git a/examples/README.md b/examples/README.md index 57dc1bbd8d..a9b62f168a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -23,14 +23,14 @@ uv pip install -e ./examples/ python -m isaaccapture_examples. ``` -Every example runs this way, and its `README.md` gives the exact command. An -example whose `pyproject.toml` points `[tool.uv.sources]` at this checkout -replaces that wheel with an editable build of the checkout, and its first -install compiles the extensions. uv reuses that build, and rebuilding `build/` -does not reach it, so after a C++ change reinstall such an example with -`uv pip install -e ./examples/ --reinstall-package isaaccapture`. +Every example runs this way except camera_viz and vehicle_teleop, whose +wrapper scripts call `.venv/bin/python` inside the example directory; their +READMEs set up that venv. An example whose `pyproject.toml` points +`[tool.uv.sources]` at this checkout installs an editable build instead of the +wheel; [step 4][editable-examples] says how to rebuild it. [install-step]: https://nvidia.github.io/IsaacCapture/main/development/build_from_source/index.html#install-the-isaaccapture-pip-package +[editable-examples]: https://nvidia.github.io/IsaacCapture/main/development/build_from_source/index.html#build-from-source-editable-examples An example with one obvious entry point puts it in `__main__.py`, so `python -m isaaccapture_examples.` runs it. An example that is several diff --git a/examples/noitom/README.md b/examples/noitom/README.md index cd784ee42b..5bb6eec897 100644 --- a/examples/noitom/README.md +++ b/examples/noitom/README.md @@ -28,7 +28,7 @@ optional plugin when you need Noitom support: cmake -B build -DBUILD_PLUGIN_NOITOM_MOCAP=ON -DISAAC_TELEOP_PYTHON_VERSION=3.12 cmake --build build --target python_package python_wheel noitom_mocap_plugin --parallel cmake --install build -uv venv --python 3.12 --seed .venv +uv venv --python 3.12 --seed .venv # skip if .venv already runs 3.12; --clear switches it (deletes its packages) source .venv/bin/activate uv pip install "isaaccapture[cloudxr]==X.Y+local" --find-links=./install/wheels/ --reinstall-package isaaccapture ``` @@ -102,15 +102,7 @@ compatibility shim from your build, which maps `isaacteleop` to `isaaccapture`. Isaac Lab pins `isaacteleop~=1.4.145`, so pip may warn about that conflict. -pip treats an installed `X.Y+local` as already satisfied, so after a rebuild -replace it explicitly. `--no-deps` keeps pip from reinstalling Isaac Lab's -other packages: - -```bash -cd -./isaaclab.sh -p -m pip install "isaaccapture==X.Y+local" \ - --find-links /install/wheels --force-reinstall --no-deps -``` +Then launch the task: ```bash cd @@ -121,6 +113,16 @@ cd --external_callback isaaccapture_examples.noitom.noitom_tasks.register_tasks ``` +pip treats an installed `X.Y+local` as already satisfied, so after a rebuild +replace it explicitly. `--no-deps` keeps pip from reinstalling Isaac Lab's +other packages: + +```bash +cd +./isaaclab.sh -p -m pip install "isaaccapture==X.Y+local" \ + --find-links /install/wheels --force-reinstall --no-deps +``` + For advanced manual plugin control, start the plugin yourself and disable auto-launch in the Isaac Lab terminal: diff --git a/examples/oglo_tactile/README.md b/examples/oglo_tactile/README.md index b349b5e8be..f7334b78ba 100644 --- a/examples/oglo_tactile/README.md +++ b/examples/oglo_tactile/README.md @@ -43,7 +43,7 @@ session, records, and draws the overlay). `oglo_heatmap.py` is the renderer. cmake -B build -DBUILD_PLUGIN_OGLO=ON -DBUILD_VIZ=ON cmake --build build --parallel cmake --install build # builds the isaaccapture python wheel/package - uv venv --python 3.11 --seed .venv + uv venv --python 3.11 --seed .venv # skip if .venv already runs 3.11; --clear switches it (deletes its packages) source .venv/bin/activate uv pip install "isaaccapture[cloudxr]==X.Y+local" --find-links=./install/wheels/ --reinstall-package isaaccapture uv pip install -e ./examples/oglo_tactile From ea766649cb0ff3eac1dff8798b8d0bf4c239fe29 Mon Sep 17 00:00:00 2001 From: Ivan Yang Date: Wed, 28 Oct 2026 13:37:39 -0700 Subject: [PATCH 6/6] docs(examples): note when to skip uv venv in oxr and vehicle_teleop Both READMEs gained an inline `uv venv` line in #1372 and #1375. uv refuses an existing .venv without --clear, so say to skip the line when .venv already runs that Python, as noitom and oglo_tactile do. Signed-off-by: Ivan Yang --- examples/oxr/README.md | 2 +- examples/vehicle_teleop/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/oxr/README.md b/examples/oxr/README.md index 835d8bc6fd..1bec540489 100644 --- a/examples/oxr/README.md +++ b/examples/oxr/README.md @@ -119,7 +119,7 @@ cmake --install build # Run Python example. Replace 3.11 with your ISAAC_TELEOP_PYTHON_VERSION and # X.Y with the first two numbers of VERSION. -uv venv --python 3.11 --seed .venv +uv venv --python 3.11 --seed .venv # skip if .venv already runs 3.11; --clear switches it (deletes its packages) source .venv/bin/activate uv pip install "isaaccapture[cloudxr]==X.Y+local" --find-links=./install/wheels/ --reinstall-package isaaccapture uv pip install -e ./examples/oxr diff --git a/examples/vehicle_teleop/README.md b/examples/vehicle_teleop/README.md index ca440fdc9e..7963d74a0f 100644 --- a/examples/vehicle_teleop/README.md +++ b/examples/vehicle_teleop/README.md @@ -32,7 +32,7 @@ Create the example virtual environment in this directory, install the ```bash cd examples/vehicle_teleop # Replace 3.11 with your ISAAC_TELEOP_PYTHON_VERSION and X.Y with the first two numbers of VERSION. -uv venv --python 3.11 --seed .venv +uv venv --python 3.11 --seed .venv # skip if .venv already runs 3.11; --clear switches it (deletes its packages) source .venv/bin/activate uv pip install "isaaccapture[cloudxr]==X.Y+local" --find-links=../../install/wheels/ --reinstall-package isaaccapture uv pip install -e .