Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c32b91d
Revert "Promote run_cloudxr_via_wheel.sh to run_cloudxr.sh"
jiwenc-nv Mar 5, 2026
a1b2198
Add Kitmaker integration (#172)
aristarkhovNV Mar 5, 2026
706d746
Revert "Rename run_cloudxr.sh to run_cloudxr_via_docker.sh"
jiwenc-nv Mar 9, 2026
53f40d4
Revert "Revert "Rename run_cloudxr.sh to run_cloudxr_via_docker.sh""
jiwenc-nv Mar 10, 2026
53a543e
Revert "Revert "Promote run_cloudxr_via_wheel.sh to run_cloudxr.sh""
jiwenc-nv Mar 10, 2026
1a3c662
Merge remote-tracking branch 'origin/main' into release/1.0.x
jiwenc-nv Mar 10, 2026
568a8ad
Merge remote-tracking branch 'origin/main' into release/1.0.x
jiwenc-nv Mar 12, 2026
eec658c
Fix CloudXR runtime crash from OpenSSL symbol conflict (#254)
rwiltz Mar 12, 2026
56b62e1
docs: use 1.0.0 as version for pip install
jiwenc-nv Mar 12, 2026
095988f
Whitelist docs from nspect OSS scan
jiwenc-nv Mar 13, 2026
28ce031
Adjust polling timeout for Kitmaker release with exponential backoff …
aristarkhovNV Mar 13, 2026
8b131bf
Download CloudXR from the final public NGC
jiwenc-nv Mar 12, 2026
53cf53a
Use wget to fetch NGC artifacts for public resources (#260)
nv-mhaselton Mar 13, 2026
7df9fb2
Restore NGC workflow for run_cloudxr_via_docker.sh (#261)
aristarkhovNV Mar 13, 2026
70baef4
Update CloudXR to 6.1.0 release
yanziz-nvidia Mar 13, 2026
f65a524
docs: more enhancement for 1.0 release
jiwenc-nv Mar 14, 2026
d6e11f4
docs: add roadmap for future devices
jiwenc-nv Mar 14, 2026
3fa8ca4
docs: add patchelf installation instructions
jiwenc-nv Mar 15, 2026
e0bc5bd
docs: fix docs pointer for Isaac Lab 3.0 beta
jiwenc-nv Mar 18, 2026
a21efc2
Bump version to 1.1
jiwenc-nv Mar 16, 2026
e1e4956
fix: ensure 'isaacteleop' is installed from the local dir (#284)
aristarkhovNV Mar 16, 2026
94f657d
Bypass body tracker if not supported by the runtime
nvddr Mar 17, 2026
b041aa5
fix(retargeting): DLPack copy order and optional transform tests
nvddr Apr 10, 2026
d9647be
ci: automated workflow for release tag
jiwenc-nv May 1, 2026
237c40d
release-tag: use the identity of the requester
jiwenc-nv May 1, 2026
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: 3 additions & 2 deletions .github/workflows/build-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -466,8 +466,8 @@ jobs:
fi

status_url="${KITMAKER_API_ENDPOINT%/}/v0/status/${KITMAKER_RELEASE_UUID}"
# Limit total polling time to at most ~10 minutes (20 * 30s)
max_attempts=20
# Limit total polling time to under an hour with exponential backoff starting at 30s
max_attempts=15
sleep_seconds=30

for ((attempt=1; attempt<=max_attempts; attempt++)); do
Expand Down Expand Up @@ -495,6 +495,7 @@ jobs:
fi

sleep "${sleep_seconds}"
sleep_seconds=$(( sleep_seconds * 125 / 100 ))
done

echo "Timed out waiting for Kitmaker release ${KITMAKER_RELEASE_UUID} to complete"
Expand Down
202 changes: 202 additions & 0 deletions .github/workflows/release-tag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# Manually-triggered release workflow.
#
# Run from a release/X.Y.x branch via the Actions UI. The workflow:
# 1. Validates the branch is release/X.Y.x and that VERSION matches.
# 2. Computes the patch number the same way CMake does (commits since
# the last change to VERSION).
# 3. Verifies no v* tag already exists at HEAD and the computed tag name
# isn't already taken on another commit.
# 4. Verifies the most recent Build Ubuntu run on this commit was green.
# 5. Pushes vX.Y.PATCH (annotated) using a PAT so build-ubuntu.yml fires
# on the tag and runs the release publish chain.
# 6. Creates a draft GitHub release with auto-generated notes.
#
# Access is gated by environment: release (admin reviewers required).

name: Release Tag

on:
workflow_dispatch:
inputs:
skip_ci_check:
description: "Skip the 'latest Build Ubuntu run on this SHA was green' check. Use only if you know what you're doing."
type: boolean
default: false

concurrency:
group: release-tag-${{ github.ref }}
cancel-in-progress: false

permissions:
contents: read

jobs:
release-tag:
runs-on: ubuntu-latest
environment: release
permissions:
contents: read
actions: read

steps:
- name: Validate ref is a release branch
run: |
set -euo pipefail
if [[ ! "${GITHUB_REF}" =~ ^refs/heads/release/([0-9]+)\.([0-9]+)\.x$ ]]; then
echo "::error::This workflow may only run from a release/X.Y.x branch (got: ${GITHUB_REF})."
exit 1
fi
echo "BRANCH_MAJOR=${BASH_REMATCH[1]}" >> "${GITHUB_ENV}"
echo "BRANCH_MINOR=${BASH_REMATCH[2]}" >> "${GITHUB_ENV}"

- name: Checkout (full history)
uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ secrets.RELEASE_SYNC_TOKEN }}

- name: Validate VERSION matches branch
run: |
set -euo pipefail
version_content="$(tr -d '[:space:]' < VERSION)"
if [[ ! "${version_content}" =~ ^([0-9]+)\.([0-9]+)\.x$ ]]; then
echo "::error::VERSION must be MAJOR.MINOR.x format (got: '${version_content}')."
exit 1
fi
if [[ "${BASH_REMATCH[1]}" != "${BRANCH_MAJOR}" || "${BASH_REMATCH[2]}" != "${BRANCH_MINOR}" ]]; then
echo "::error::VERSION (${version_content}) does not match branch release/${BRANCH_MAJOR}.${BRANCH_MINOR}.x."
exit 1
fi

- name: Compute patch number and tag
id: compute
run: |
set -euo pipefail
version_commit="$(git rev-list -n 1 HEAD -- VERSION)"
if [[ -z "${version_commit}" ]]; then
echo "::error::Could not locate the commit that last modified VERSION."
exit 1
fi
patch="$(git rev-list --count "${version_commit}..HEAD")"
if ! [[ "${patch}" =~ ^[0-9]+$ ]]; then
echo "::error::Computed patch is not a number: '${patch}'."
exit 1
fi
tag="v${BRANCH_MAJOR}.${BRANCH_MINOR}.${patch}"
sha="$(git rev-parse HEAD)"
echo "Computed release tag: ${tag} at ${sha}"
echo "tag=${tag}" >> "${GITHUB_OUTPUT}"
echo "patch=${patch}" >> "${GITHUB_OUTPUT}"
echo "sha=${sha}" >> "${GITHUB_OUTPUT}"

- name: Check no existing tag at HEAD (idempotent re-run is allowed)
id: head-tag-check
run: |
set -euo pipefail
tag="${{ steps.compute.outputs.tag }}"
sha="${{ steps.compute.outputs.sha }}"
existing_at_head="$(git tag --points-at "${sha}" | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' || true)"
if [[ -z "${existing_at_head}" ]]; then
echo "head_already_tagged=false" >> "${GITHUB_OUTPUT}"
exit 0
fi
# Allow idempotent re-run when the existing tag matches what we'd compute.
if echo "${existing_at_head}" | grep -qx "${tag}"; then
echo "::notice::HEAD is already tagged ${tag}; skipping tag push, will still ensure draft release exists."
echo "head_already_tagged=true" >> "${GITHUB_OUTPUT}"
exit 0
fi
echo "::error::HEAD already has a release tag (${existing_at_head}) different from the computed tag (${tag}). Refusing to tag the same commit twice."
exit 1

- name: Check computed tag is not taken on a different commit
if: steps.head-tag-check.outputs.head_already_tagged == 'false'
run: |
set -euo pipefail
tag="${{ steps.compute.outputs.tag }}"
if git rev-parse --verify --quiet "refs/tags/${tag}" >/dev/null; then
existing_sha="$(git rev-list -n 1 "refs/tags/${tag}")"
echo "::error::Tag ${tag} already exists on a different commit (${existing_sha}). Resolve manually."
exit 1
fi

- name: Verify latest Build Ubuntu run on this SHA was green
if: ${{ !inputs.skip_ci_check }}
env:
GH_TOKEN: ${{ github.token }}
SHA: ${{ steps.compute.outputs.sha }}
run: |
set -euo pipefail
# Find the most recent completed Build Ubuntu run for this commit.
run_json="$(gh run list \
--workflow build-ubuntu.yml \
--commit "${SHA}" \
--status completed \
--limit 1 \
--json conclusion,databaseId,headSha,event)"
count="$(jq 'length' <<< "${run_json}")"
if [[ "${count}" -eq 0 ]]; then
echo "::error::No completed Build Ubuntu run found for ${SHA}. Push the branch and let CI finish before tagging, or set skip_ci_check=true."
exit 1
fi
conclusion="$(jq -r '.[0].conclusion' <<< "${run_json}")"
run_id="$(jq -r '.[0].databaseId' <<< "${run_json}")"
if [[ "${conclusion}" != "success" ]]; then
echo "::error::Latest Build Ubuntu run on ${SHA} concluded '${conclusion}' (run id ${run_id}). Refusing to tag."
exit 1
fi
echo "Build Ubuntu run ${run_id} on ${SHA} was successful."

- name: Configure git identity
if: steps.head-tag-check.outputs.head_already_tagged == 'false'
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"

- name: Create and push annotated tag
if: steps.head-tag-check.outputs.head_already_tagged == 'false'
run: |
set -euo pipefail
tag="${{ steps.compute.outputs.tag }}"
git tag -a "${tag}" -m "Release ${tag}"
# Pushed via RELEASE_SYNC_TOKEN (set on the actions/checkout step) so the
# tag push triggers build-ubuntu.yml; GITHUB_TOKEN-pushed tags would not.
git push origin "${tag}"
echo "Pushed ${tag}; this will trigger build-ubuntu.yml on the tag ref."

- name: Create or refresh draft GitHub release
env:
GH_TOKEN: ${{ secrets.RELEASE_SYNC_TOKEN }}
run: |
set -euo pipefail
tag="${{ steps.compute.outputs.tag }}"
# Find the previous tag on the same X.Y line for note generation.
prev_tag="$(git tag --list "v${BRANCH_MAJOR}.${BRANCH_MINOR}.*" --sort=-v:refname \
| grep -vx "${tag}" | head -1 || true)"
notes_args=()
if [[ -n "${prev_tag}" ]]; then
notes_args+=(--notes-start-tag "${prev_tag}")
fi
if gh release view "${tag}" >/dev/null 2>&1; then
echo "::notice::Release ${tag} already exists; leaving as-is."
else
gh release create "${tag}" \
--draft \
--title "${tag}" \
--generate-notes "${notes_args[@]}"
echo "Draft release ${tag} created."
fi

- name: Summary
run: |
{
echo "### Release Tag Summary"
echo ""
echo "- Branch: \`${GITHUB_REF#refs/heads/}\`"
echo "- Commit: \`${{ steps.compute.outputs.sha }}\`"
echo "- Computed tag: \`${{ steps.compute.outputs.tag }}\`"
echo "- Already tagged at HEAD: \`${{ steps.head-tag-check.outputs.head_already_tagged }}\`"
} >> "${GITHUB_STEP_SUMMARY}"
10 changes: 10 additions & 0 deletions .nspect-allowlist.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

version = "1.0.0"

[oss.excluded]
[[oss.excluded.directories]]

paths = ['docs']
comment = 'NVIDIA specific documentation'
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ SPDX-License-Identifier: Apache-2.0
**The unified framework for high-fidelity ego-centric and robotics data collection.**

[![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
[![Isaac Lab](https://img.shields.io/badge/Isaac%20Lab-3.0.0-orange.svg)](https://isaac-sim.github.io/IsaacLab/)
[![numpy](https://img.shields.io/badge/numpy-1.22%2B-lightgrey.svg)](https://numpy.org/)
[![Isaac Lab](https://img.shields.io/badge/Isaac%20Lab-3.0.0-orange.svg)](https://isaac-sim.github.io/IsaacLab/develop)
[![numpy](https://img.shields.io/badge/numpy-1.23%2B-lightgrey.svg)](https://numpy.org/)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)


Expand Down Expand Up @@ -60,6 +60,6 @@ Our [documentation page](https://nvidia.github.io/IsaacTeleop) provides everythi

### Install & Run Isaac Lab

Isaac Tepeop Core is design to work side by side with [NVIDIA Isaac Lab](https://github.com/isaac-sim/IsaacLab) starting with Isaac Lab 3.0 EA release.
Isaac Teleop is design to work side by side with [NVIDIA Isaac Lab](https://github.com/isaac-sim/IsaacLab) starting with Isaac Lab [3.0 Beta release](https://github.com/isaac-sim/IsaacLab/releases/tag/v3.0.0-beta).

To get started, please refer to Isaac Lab's [Installation](https://isaac-sim.github.io/IsaacLab/main/source/setup/installation/index.html) guide for more details. Then follow the [CloudXR teleoperation in Isaac Lab](https://isaac-sim.github.io/IsaacLab/main/source/how-to/cloudxr_teleoperation.html) to get started with Teleoperation in Sim.
To get started, please refer to Isaac Lab's [Installation](https://isaac-sim.github.io/IsaacLab/develop/source/setup/installation/index.html) guide for more details. Then follow the [CloudXR teleoperation in Isaac Lab](https://isaac-sim.github.io/IsaacLab/develop/source/how-to/cloudxr_teleoperation.html) to get started with Teleoperation in Sim.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.x
1.1.x
4 changes: 2 additions & 2 deletions deps/cloudxr/.env.default
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
###########################################################
# CloudXR Docker Images and Configs
###########################################################
CXR_RUNTIME_SDK_VERSION=6.1.0-rc2
CXR_WEB_SDK_VERSION=6.1.0-rc6
CXR_RUNTIME_SDK_VERSION=6.1.0
CXR_WEB_SDK_VERSION=6.1.0
CXR_HOST_VOLUME_PATH=$HOME/.cloudxr

###########################################################
Expand Down
68 changes: 68 additions & 0 deletions deps/cloudxr/Dockerfile.runtime-ngc
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Minimal CloudXR runtime image.
# The SDK must be downloaded first (see scripts/download_cloudxr_runtime_sdk.sh).
#
# Build context: deps/cloudxr/ (contains CloudXR-<VERSION>-Linux-<ARCH>-sdk.tar.gz)
#
# Environment overrides:
# NV_DEVICE_PROFILE Device profile (default: auto-webrtc).
# Values: auto-native, auto-webrtc,
# apple-vision-pro, ipad-pro, quest3

# -------------------------------------------------------------------
# Stage 0: Extract the SDK tarball.
# -------------------------------------------------------------------
FROM scratch AS sdk
ARG TARGETARCH
ARG CXR_RUNTIME_SDK_VERSION
ADD CloudXR-${CXR_RUNTIME_SDK_VERSION}-Linux-${TARGETARCH}-sdk.tar.gz /sdk/

# -------------------------------------------------------------------
# Stage 1: Runtime image.
# -------------------------------------------------------------------
FROM ubuntu:24.04

ENV NVIDIA_VISIBLE_DEVICES=all NVIDIA_DRIVER_CAPABILITIES=all
ENV LD_LIBRARY_PATH=/opt/cloudxr

RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
libatomic1 \
libbsd0 \
libegl1 \
libgl1 \
libglx0 \
libvulkan1 \
libx11-6 \
libxext6 \
python3 \
&& rm -rf /var/lib/apt/lists/*

# Vulkan ICD + EGL vendor so the loader can find the NVIDIA driver.
RUN mkdir -p /etc/vulkan/icd.d /usr/share/glvnd/egl_vendor.d
COPY runtime/data/10_nvidia.json /usr/share/glvnd/egl_vendor.d/
COPY runtime/data/nvidia_icd.json /etc/vulkan/icd.d/
ENV VK_DRIVER_FILES=/etc/vulkan/icd.d/nvidia_icd.json

RUN mkdir -p /openxr/run && chmod 777 /openxr /openxr/run && \
touch /var/run/utmp

WORKDIR /opt/cloudxr

COPY runtime/main.py .
COPY --from=sdk /sdk/*.so /sdk/*.so.* ./
COPY --from=sdk /sdk/openxr_cloudxr.json .

# CloudXR / OpenXR runtime configuration.
ENV XR_RUNTIME_JSON=/openxr/openxr_cloudxr.json
ENV NV_CXR_RUNTIME_DIR=/openxr/run
ENV XRT_NO_STDIN=true
ENV NV_CXR_FILE_LOGGING=false
ENV NV_DEVICE_PROFILE=auto-webrtc

COPY --chmod=0755 runtime/eula.sh /eula.sh
COPY --chmod=0755 runtime/entrypoint-ngc.sh /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh", "python3", "/opt/cloudxr/main.py"]
3 changes: 2 additions & 1 deletion deps/cloudxr/Dockerfile.test
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ COPY examples/oxr/python/ /app/tests/
WORKDIR /app/tests
RUN uv venv --python $PYTHON_VERSION /app/venv && \
. /app/venv/bin/activate && \
uv pip install --find-links=/app/install/wheels isaacteleop numpy
uv pip install --find-links=/app/install/wheels --no-index --no-deps --no-cache-dir 'isaacteleop' && \
uv pip install isaacteleop

# Set environment variables
ENV PATH="/app/venv/bin:$PATH"
Expand Down
37 changes: 34 additions & 3 deletions deps/cloudxr/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,33 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# CloudXR compose override for web/proxy services and runtime mode.
# Used together with docker-compose.runtime.yaml.

services:
# CloudXR Runtime
cloudxr-runtime:
build:
context: .
dockerfile: Dockerfile.runtime-ngc
args:
CXR_RUNTIME_SDK_VERSION: ${CXR_RUNTIME_SDK_VERSION}
container_name: cloudxr-runtime-${CXR_RUNTIME_SDK_VERSION}
user: "${CXR_UID:-1000}:${CXR_GID:-1000}"
network_mode: host
healthcheck:
test: ["CMD", "test", "-f", "/openxr/run/runtime_started"]
interval: 1s
timeout: 1s
retries: 10
start_period: 5s
environment:
- ACCEPT_EULA=${ACCEPT_CLOUDXR_EULA:-Y}
- NV_CXR_ENABLE_PUSH_DEVICES=${NV_CXR_ENABLE_PUSH_DEVICES}
- NV_CXR_ENABLE_TENSOR_DATA=${NV_CXR_ENABLE_TENSOR_DATA}
- NV_DEVICE_PROFILE=${NV_DEVICE_PROFILE:-auto-webrtc}
- NV_GPU_INDEX=${NV_GPU_INDEX:-0}
volumes:
- openxr-volume:/openxr/
runtime: nvidia

# WebSocket SSL Proxy Service
wss-proxy:
build:
Expand Down Expand Up @@ -40,3 +63,11 @@ services:
volumes:
- ./webxr_client:/app/webxr_client
restart: unless-stopped

volumes:
openxr-volume:
driver: local
driver_opts:
type: none
o: bind
device: ${CXR_HOST_VOLUME_PATH:-/tmp/cloudxr}
Loading
Loading