Commit 799a4f7f authored by nv-mhaselton's avatar nv-mhaselton Committed by Kelly Guo

Adds Headless XR support and Centralize XR-specific Settings (#278)

Adds headless XR support to Isaac Lab and refactors the AppLauncher:
* Fixed headless XR rendering with Kit XR's OpenXR extension
* Automatically enables AR mode when running headless
* Centralized XR-specific settings from code to Kit app configuration
files
* Added new `isaaclab.python.xr.openxr.headless.kit` configuration file
* Introduced `--xr` flag in AppLauncher for explicit XR mode control
(also supports `XR=1` environment variable)
* Device resolution for XR should default to CPU unless overridden
* In a separate commit, the AppLauncher configuration resolution is
broken down to resolve the flake8 C901 complexity violation

<!-- As you go through the list, delete the ones that are not
applicable. -->

- New feature (non-breaking change which adds functionality)

Please attach before and after screenshots of the change if applicable.

<!--
Example:

| Before | After |
| ------ | ----- |
| _gif/png before_ | _gif/png after_ |

To upload images to a PR -- simply drag and drop an image while in edit
mode and it should upload the image directly. You can then paste that
source into the above before/after sections.
-->

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.sh --format`
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there

<!--
As you go through the checklist above, you can mark something as done by
putting an x character in it

For example,
- [x] I have done this task
- [ ] I have not done this task
-->
parent 1c88446c
##
# Adapted from: apps/isaaclab.python.xr.openxr.kit
##
[package]
title = "Isaac Lab Python OpenXR Headless"
description = "An app for running Isaac Lab with OpenXR in headless mode"
version = "2.0.0"
# That makes it browsable in UI with "experience" filter
keywords = ["experience", "app", "usd", "headless"]
[settings]
# Note: This path was adapted to be respective to the kit-exe file location
app.versionFile = "${exe-path}/VERSION"
app.folder = "${exe-path}/"
app.name = "Isaac-Sim"
app.version = "4.5.0"
[dependencies]
"isaaclab.python.xr.openxr" = {}
[settings]
xr.profile.ar.enabled = true
# Register extension folder from this repo in kit
[settings.app.exts]
folders = [
"${exe-path}/exts", # kit extensions
"${exe-path}/extscore", # kit core extensions
"${exe-path}/../exts", # isaac extensions
"${exe-path}/../extsDeprecated", # deprecated isaac extensions
"${exe-path}/../extscache", # isaac cache extensions
"${exe-path}/../extsPhysics", # isaac physics extensions
"${exe-path}/../isaacsim/exts", # isaac extensions for pip
"${exe-path}/../isaacsim/extsDeprecated", # deprecated isaac extensions
"${exe-path}/../isaacsim/extscache", # isaac cache extensions for pip
"${exe-path}/../isaacsim/extsPhysics", # isaac physics extensions for pip
"${app}", # needed to find other app files
"${app}/../source", # needed to find extensions in Isaac Lab
]
......@@ -24,6 +24,7 @@ app.asyncRenderingLowLatency = true
# For XR, set this back to default "#define OMNI_MAX_DEVICE_GROUP_DEVICE_COUNT 16"
renderer.multiGpu.maxGpuCount = 16
renderer.gpuEnumeration.glInterop.enabled = true # Allow Kit XR OpenXR to render headless
[dependencies]
"isaaclab.python.rendering" = {}
......@@ -34,11 +35,14 @@ renderer.multiGpu.maxGpuCount = 16
"omni.kit.xr.profile.ar" = {}
[settings]
app.xr.enabled = true
# xr settings
xr.ui.enabled = false
xrstage.profile.ar.anchorMode = "active camera"
xr.depth.aov = "GBufferDepth"
defaults.xr.profile.ar.renderQuality = "off"
rtx.rendermode = "RaytracedLighting"
# Register extension folder from this repo in kit
[settings.app.exts]
......
......@@ -8,15 +8,11 @@
"""Launch Isaac Sim Simulator first."""
import argparse
import os
from isaaclab.app import AppLauncher
# add argparse arguments
parser = argparse.ArgumentParser(description="Keyboard teleoperation for Isaac Lab environments.")
parser.add_argument(
"--disable_fabric", action="store_true", default=False, help="Disable fabric and use USD I/O operations."
)
parser.add_argument("--num_envs", type=int, default=1, help="Number of environments to simulate.")
parser.add_argument("--teleop_device", type=str, default="keyboard", help="Device for interacting with environment")
parser.add_argument("--task", type=str, default=None, help="Name of the task.")
......@@ -28,7 +24,7 @@ args_cli = parser.parse_args()
app_launcher_args = vars(args_cli)
if args_cli.teleop_device.lower() == "handtracking":
app_launcher_args["experience"] = f'{os.environ["ISAACLAB_PATH"]}/apps/isaaclab.python.xr.openxr.kit'
app_launcher_args["xr"] = True
# launch omniverse app
app_launcher = AppLauncher(app_launcher_args)
simulation_app = app_launcher.app
......@@ -69,9 +65,7 @@ def pre_process_actions(delta_pose: torch.Tensor, gripper_command: bool) -> torc
def main():
"""Running keyboard teleoperation with Isaac Lab manipulation environment."""
# parse configuration
env_cfg = parse_env_cfg(
args_cli.task, device=args_cli.device, num_envs=args_cli.num_envs, use_fabric=not args_cli.disable_fabric
)
env_cfg = parse_env_cfg(args_cli.task, device=args_cli.device, num_envs=args_cli.num_envs)
# modify configuration
env_cfg.terminations.time_out = None
if "Lift" in args_cli.task:
......
......@@ -51,11 +51,12 @@ AppLauncher.add_app_launcher_args(parser)
# parse the arguments
args_cli = parser.parse_args()
app_launcher_args = vars(args_cli)
if args_cli.teleop_device.lower() == "handtracking":
vars(args_cli)["experience"] = f'{os.environ["ISAACLAB_PATH"]}/apps/isaaclab.python.xr.openxr.kit'
app_launcher_args["xr"] = True
# launch the simulator
app_launcher = AppLauncher(args_cli)
app_launcher = AppLauncher(app_launcher_args)
simulation_app = app_launcher.app
"""Rest everything follows."""
......
......@@ -11,7 +11,6 @@ from scipy.spatial.transform import Rotation, Slerp
from typing import Final
import carb
from omni.kit.viewport.utility import get_active_viewport
from ..device_base import DeviceBase
......@@ -83,11 +82,6 @@ class Se3HandTracking(DeviceBase):
self._alpha_rot = 0.5
self._smoothed_delta_pos = np.zeros(3)
self._smoothed_delta_rot = np.zeros(3)
# Set the XR anchormode to active camera
carb.settings.get_settings().set_string("/xrstage/profile/ar/anchorMode", "active camera")
# Select RTX - RealTime for Renderer
viewport_api = get_active_viewport()
viewport_api.set_hd_engine("rtx", "RaytracedLighting")
self._delta_pos_scale_factor = delta_pos_scale_factor
self._delta_rot_scale_factor = delta_rot_scale_factor
self._frame_marker_cfg = FRAME_MARKER_CFG.copy()
......
......@@ -154,6 +154,8 @@ class SimulationContext(_SimulationContext):
self._local_gui = carb_settings_iface.get("/app/window/enabled")
# read flag for whether livestreaming GUI is enabled
self._livestream_gui = carb_settings_iface.get("/app/livestream/enabled")
# read flag for whether XR GUI is enabled
self._xr_gui = carb_settings_iface.get("/app/xr/enabled")
# read flag for whether the Isaac Lab viewport capture pipeline will be used,
# casting None to False if the flag doesn't exist
......@@ -162,7 +164,7 @@ class SimulationContext(_SimulationContext):
# read flag for whether the default viewport should be enabled
self._render_viewport = bool(carb_settings_iface.get("/isaaclab/render/active_viewport"))
# flag for whether any GUI will be rendered (local, livestreamed or viewport)
self._has_gui = self._local_gui or self._livestream_gui
self._has_gui = self._local_gui or self._livestream_gui or self._xr_gui
# apply render settings from render config
if self.cfg.render.enable_translucency is not None:
......@@ -193,6 +195,8 @@ class SimulationContext(_SimulationContext):
import omni.replicator.core as rep
rep.settings.set_render_rtx_realtime(antialiasing=self.cfg.render.antialiasing_mode)
# WAR: The omni.replicator.core extension sets /rtx/renderMode=RayTracedLighting with incorrect casing.
carb_settings_iface.set("/rtx/rendermode", "RaytracedLighting")
except Exception:
pass
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment