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
1 change: 1 addition & 0 deletions apps/isaaclab.python.headless.kit
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ log.outputStreamLevel = "Warn"
"omni.physx.fabric" = {}
"usdrt.scenegraph" = {}
"omni.kit.telemetry" = {}
"omni.kit.async_engine" = {}
"omni.kit.loop" = {}
# this is needed to create physics material through CreatePreviewSurfaceMaterialPrim
"omni.kit.usd.mdl" = {}
Expand Down
1 change: 1 addition & 0 deletions apps/isaaclab.python.headless.rendering.kit
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ version = "3.0.0"
keywords = ["experience", "app", "isaaclab", "python", "camera", "minimal"]

[dependencies]
"omni.kit.async_engine" = {}
# Isaac Lab minimal app
"isaaclab.python.headless" = {}
"isaacsim.core.rendering_manager" = {}
Expand Down
1 change: 1 addition & 0 deletions apps/isaaclab.python.kit
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ keywords = ["experience", "app", "usd"]
"omni.hydra.engine.stats" = {}
"omni.hydra.rtx" = {}
"omni.kit.mainwindow" = {}
"omni.kit.async_engine" = {}
"omni.kit.manipulator.camera" = {}
"omni.kit.manipulator.prim" = {}
"omni.kit.manipulator.selection" = {}
Expand Down
1 change: 1 addition & 0 deletions apps/isaaclab.python.rendering.kit
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ version = "3.0.0"
keywords = ["experience", "app", "isaaclab", "python", "camera", "minimal"]

[dependencies]
"omni.kit.async_engine" = {}
# Isaac Lab minimal app
"isaaclab.python" = {}

Expand Down
1 change: 1 addition & 0 deletions apps/isaaclab.python.xr.openxr.headless.kit
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ xr.skipInputDeviceUSDWrites = true
cameras_enabled = true

[dependencies]
"omni.kit.async_engine" = {}
"isaaclab.python.xr.openxr" = {}

# NOTE: xr.profile.ar.enabled is intentionally NOT set here.
Expand Down
1 change: 1 addition & 0 deletions apps/isaaclab.python.xr.openxr.kit
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ xr.skipInputDeviceUSDWrites = true
'rtx-transient'.resourcemanager.enableTextureStreaming = false

[dependencies]
"omni.kit.async_engine" = {}
"isaaclab.python" = {}

# Required for XR instruction widget (CopyFabricPrim)
Expand Down
46 changes: 42 additions & 4 deletions source/isaaclab/isaaclab/utils/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,39 @@ def _parse_kit_asset_root() -> str:
"""Path to the ``Isaac/IsaacLab`` directory on the NVIDIA Nucleus Server."""


def _kit_app():
"""Return the running Kit app or ``None`` if Kit is not running."""
try:
import omni.kit.app # noqa: PLC0415

return omni.kit.app.get_app()
except Exception:
return None


def _drive_kit_async(coro):
"""Run an ``omni.client`` ``_async`` coroutine without blocking Kit's main thread.

Schedules the coroutine on Kit's asyncio loop and ticks ``app.update()`` until
it resolves; falls back to a private event loop when Kit isn't running.
"""
import asyncio # noqa: PLC0415
import time # noqa: PLC0415

app = _kit_app()
if app is None:
return asyncio.run(coro)
# omni.kit.async_engine's observer pumps asyncio on each Kit frame -- scheduling on any
# other loop would deadlock the spin below. Fail loudly if a custom kit config drops it.
import omni.kit.async_engine # noqa: PLC0415

task = omni.kit.async_engine.run_coroutine(coro)
while not task.done():
app.update()
time.sleep(0)
return task.result()


def check_file_path(path: str) -> Literal[0, 1, 2]:
"""Checks if a file exists on the Nucleus Server or locally.

Expand All @@ -70,7 +103,7 @@ def check_file_path(path: str) -> Literal[0, 1, 2]:

import omni.client # noqa: PLC0415

if omni.client.stat(path.replace(os.sep, "/"))[0] == omni.client.Result.OK:
if _drive_kit_async(omni.client.stat_async(path.replace(os.sep, "/")))[0] == omni.client.Result.OK:
return 2
else:
return 0
Expand Down Expand Up @@ -131,7 +164,10 @@ def retrieve_file_path(path: str, download_dir: str | None = None, force_downloa
if _UDIM_RE.search(cur_url):
for tile in range(1001, 1101):
tile_url = _UDIM_RE.sub(str(tile), cur_url)
if omni.client.stat(tile_url.replace(os.sep, "/"))[0] == omni.client.Result.OK:
if (
_drive_kit_async(omni.client.stat_async(tile_url.replace(os.sep, "/")))[0]
== omni.client.Result.OK
):
if tile_url not in visited:
to_visit.append(tile_url)
else:
Expand All @@ -143,7 +179,9 @@ def retrieve_file_path(path: str, download_dir: str | None = None, force_downloa
os.makedirs(os.path.dirname(target_path), exist_ok=True)

if not os.path.isfile(target_path) or force_download:
result = omni.client.copy(cur_url, target_path, omni.client.CopyBehavior.OVERWRITE)
result = _drive_kit_async(
omni.client.copy_async(cur_url, target_path, omni.client.CopyBehavior.OVERWRITE)
)
if result != omni.client.Result.OK and force_download:
raise RuntimeError(f"Unable to copy file: '{cur_url}'. Is the Nucleus Server running?")

Expand Down Expand Up @@ -183,7 +221,7 @@ def read_file(path: str) -> io.BytesIO:
elif file_status == 2:
import omni.client # noqa: PLC0415

file_content = omni.client.read_file(path.replace(os.sep, "/"))[2]
file_content = _drive_kit_async(omni.client.read_file_async(path.replace(os.sep, "/")))[2]
return io.BytesIO(memoryview(file_content).tobytes())
else:
raise FileNotFoundError(f"Unable to find the file: {path}")
Expand Down
Loading