Unverified Commit 87618028 authored by Mayank Mittal's avatar Mayank Mittal Committed by GitHub

Uses stage identifier for faster file checks in the `from_files` spawners (#502)

# Description

The function `check_file_exists` is slow since it tries to access the
Nucleus server for the file, which can take time. This function uses the
stage resolver to see if the file exists instead.

## Type of change

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

## Checklist

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./orbit.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 run all the tests with `./orbit.sh --test` and they pass
- [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
parent 13146109
[package] [package]
# Note: Semantic Versioning is used: https://semver.org/ # Note: Semantic Versioning is used: https://semver.org/
version = "0.15.11" version = "0.15.12"
# Description # Description
title = "ORBIT framework for Robot Learning" title = "ORBIT framework for Robot Learning"
......
Changelog Changelog
--------- ---------
0.15.12 (2024-04-16)
~~~~~~~~~~~~~~~~~~~~
Changed
^^^^^^^
* Replaced calls to the ``check_file_path`` function in the :mod:`omni.isaac.orbit.sim.spawners.from_files`
with the USD stage resolve identifier function. This helps speed up the loading of assets from file paths
by avoiding Nucleus server calls.
0.15.11 (2024-04-15) 0.15.11 (2024-04-15)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
......
...@@ -9,12 +9,12 @@ from typing import TYPE_CHECKING ...@@ -9,12 +9,12 @@ from typing import TYPE_CHECKING
import carb import carb
import omni.isaac.core.utils.prims as prim_utils import omni.isaac.core.utils.prims as prim_utils
import omni.isaac.core.utils.stage as stage_utils
import omni.kit.commands import omni.kit.commands
from pxr import Gf, Sdf, Usd from pxr import Gf, Sdf, Usd
from omni.isaac.orbit.sim import converters, schemas from omni.isaac.orbit.sim import converters, schemas
from omni.isaac.orbit.sim.utils import bind_physics_material, bind_visual_material, clone from omni.isaac.orbit.sim.utils import bind_physics_material, bind_visual_material, clone
from omni.isaac.orbit.utils.assets import check_file_path
if TYPE_CHECKING: if TYPE_CHECKING:
from . import from_files_cfg from . import from_files_cfg
...@@ -203,6 +203,7 @@ def _spawn_from_usd_file( ...@@ -203,6 +203,7 @@ def _spawn_from_usd_file(
Args: Args:
prim_path: The prim path or pattern to spawn the asset at. If the prim path is a regex pattern, prim_path: The prim path or pattern to spawn the asset at. If the prim path is a regex pattern,
then the asset is spawned at all the matching prim paths. then the asset is spawned at all the matching prim paths.
usd_path: The path to the USD file to spawn the asset from.
cfg: The configuration instance. cfg: The configuration instance.
translation: The translation to apply to the prim w.r.t. its parent prim. Defaults to None, in which translation: The translation to apply to the prim w.r.t. its parent prim. Defaults to None, in which
case the translation specified in the generated USD file is used. case the translation specified in the generated USD file is used.
...@@ -216,7 +217,8 @@ def _spawn_from_usd_file( ...@@ -216,7 +217,8 @@ def _spawn_from_usd_file(
FileNotFoundError: If the USD file does not exist at the given path. FileNotFoundError: If the USD file does not exist at the given path.
""" """
# check file path exists # check file path exists
if not check_file_path(usd_path): stage: Usd.Stage = stage_utils.get_current_stage()
if not stage.ResolveIdentifierToEditTarget(usd_path):
raise FileNotFoundError(f"USD file not found at path: '{usd_path}'.") raise FileNotFoundError(f"USD file not found at path: '{usd_path}'.")
# spawn asset if it doesn't exist. # spawn asset if it doesn't exist.
if not prim_utils.is_prim_path_valid(prim_path): if not prim_utils.is_prim_path_valid(prim_path):
......
...@@ -8,8 +8,9 @@ ...@@ -8,8 +8,9 @@
By default, we use the Isaac Sim Nucleus Server for hosting assets and resources. This makes By default, we use the Isaac Sim Nucleus Server for hosting assets and resources. This makes
distribution of the assets easier and makes the repository smaller in size code-wise. distribution of the assets easier and makes the repository smaller in size code-wise.
For more information on Omniverse Nucleus: For more information, please check information on `Omniverse Nucleus`_.
https://docs.omniverse.nvidia.com/app_isaacsim/app_isaacsim/overview.html#omniverse-nucleus
.. _Omniverse Nucleus: https://docs.omniverse.nvidia.com/nucleus/latest/overview/overview.html
""" """
import io import io
...@@ -21,8 +22,22 @@ import carb ...@@ -21,8 +22,22 @@ import carb
import omni.client import omni.client
import omni.isaac.core.utils.nucleus as nucleus_utils import omni.isaac.core.utils.nucleus as nucleus_utils
# get assets root path
# note: we check only once at the start of the module to prevent multiple checks on the Nucleus Server
NUCLEUS_ASSET_ROOT_DIR = nucleus_utils.get_assets_root_path()
"""Path to the root directory on the Nucleus Server.
This is resolved using Isaac Sim's Nucleus API. If the Nucleus Server is not running, then this
will be set to None. The path is resolved using the following steps:
1. Based on simulation parameter: ``/persistent/isaac/asset_root/default``.
2. Iterating over all the connected Nucleus Servers and checking for the first server that has the
the connected status.
3. Based on simulation parameter: ``/persistent/isaac/asset_root/cloud``.
"""
# check nucleus connection # check nucleus connection
if nucleus_utils.get_assets_root_path() is None: if NUCLEUS_ASSET_ROOT_DIR is None:
msg = ( msg = (
"Unable to perform Nucleus login on Omniverse. Assets root path is not set.\n" "Unable to perform Nucleus login on Omniverse. Assets root path is not set.\n"
"\tPlease check: https://docs.omniverse.nvidia.com/app_isaacsim/app_isaacsim/overview.html#omniverse-nucleus" "\tPlease check: https://docs.omniverse.nvidia.com/app_isaacsim/app_isaacsim/overview.html#omniverse-nucleus"
...@@ -30,14 +45,14 @@ if nucleus_utils.get_assets_root_path() is None: ...@@ -30,14 +45,14 @@ if nucleus_utils.get_assets_root_path() is None:
carb.log_error(msg) carb.log_error(msg)
raise RuntimeError(msg) raise RuntimeError(msg)
NVIDIA_NUCLEUS_DIR = f"{nucleus_utils.get_assets_root_path()}/NVIDIA" NVIDIA_NUCLEUS_DIR = f"{NUCLEUS_ASSET_ROOT_DIR}/NVIDIA"
"""Path to the root directory on the NVIDIA Nucleus Server.""" """Path to the root directory on the NVIDIA Nucleus Server."""
ISAAC_NUCLEUS_DIR = f"{nucleus_utils.get_assets_root_path()}/Isaac" ISAAC_NUCLEUS_DIR = f"{NUCLEUS_ASSET_ROOT_DIR}/Isaac"
"""Path to the `Isaac` directory on the NVIDIA Nucleus Server.""" """Path to the ``Isaac`` directory on the NVIDIA Nucleus Server."""
ISAAC_ORBIT_NUCLEUS_DIR = f"{ISAAC_NUCLEUS_DIR}/Samples/Orbit" ISAAC_ORBIT_NUCLEUS_DIR = f"{ISAAC_NUCLEUS_DIR}/Samples/Orbit"
"""Path to the `Isaac/Samples/Orbit` directory on the NVIDIA Nucleus Server.""" """Path to the ``Isaac/Samples/Orbit`` directory on the NVIDIA Nucleus Server."""
def check_file_path(path: str) -> Literal[0, 1, 2]: def check_file_path(path: str) -> Literal[0, 1, 2]:
...@@ -47,11 +62,11 @@ def check_file_path(path: str) -> Literal[0, 1, 2]: ...@@ -47,11 +62,11 @@ def check_file_path(path: str) -> Literal[0, 1, 2]:
path: The path to the file. path: The path to the file.
Returns: Returns:
The status of the file. Possible values are: The status of the file. Possible values are listed below.
* :obj:`0` if the file does not exist * :obj:`0` if the file does not exist
* :obj:`1` if the file exists locally * :obj:`1` if the file exists locally
* :obj:`2` if the file exists on the Nucleus Server * :obj:`2` if the file exists on the Nucleus Server
""" """
if os.path.isfile(path): if os.path.isfile(path):
return 1 return 1
......
...@@ -59,6 +59,14 @@ class TestSpawningFromFiles(unittest.TestCase): ...@@ -59,6 +59,14 @@ class TestSpawningFromFiles(unittest.TestCase):
self.assertTrue(prim_utils.is_prim_path_valid("/World/Franka")) self.assertTrue(prim_utils.is_prim_path_valid("/World/Franka"))
self.assertEqual(prim.GetPrimTypeInfo().GetTypeName(), "Xform") self.assertEqual(prim.GetPrimTypeInfo().GetTypeName(), "Xform")
def test_spawn_usd_fails(self):
"""Test loading prim from Usd file fails when asset usd path is invalid."""
# Spawn cone
cfg = sim_utils.UsdFileCfg(usd_path=f"{ISAAC_ORBIT_NUCLEUS_DIR}/Robots/FrankaEmika/panda2_instanceable.usd")
with self.assertRaises(FileNotFoundError):
cfg.func("/World/Franka", cfg)
def test_spawn_urdf(self): def test_spawn_urdf(self):
"""Test loading prim from URDF file.""" """Test loading prim from URDF file."""
# retrieve path to urdf importer extension # retrieve path to urdf importer extension
......
# Copyright (c) 2022-2024, The ORBIT Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
"""Launch Isaac Sim Simulator first."""
from omni.isaac.orbit.app import AppLauncher, run_tests
# launch omniverse app
app_launcher = AppLauncher(headless=True)
simulation_app = app_launcher.app
"""Rest everything follows."""
import unittest
import omni.isaac.orbit.utils.assets as assets_utils
class TestAssetsUtils(unittest.TestCase):
"""Test cases for the assets utility functions."""
def test_nucleus_connection(self):
"""Test checking the Nucleus connection."""
# check nucleus connection
self.assertIsNotNone(assets_utils.NUCLEUS_ASSET_ROOT_DIR)
def test_check_file_path_nucleus(self):
"""Test checking a file path on the Nucleus server."""
# robot file path
usd_path = f"{assets_utils.ISAAC_ORBIT_NUCLEUS_DIR}/Robots/FrankaEmika/panda_instanceable.usd"
# check file path
self.assertEqual(assets_utils.check_file_path(usd_path), 2)
def test_check_file_path_invalid(self):
"""Test checking an invalid file path."""
# robot file path
usd_path = f"{assets_utils.ISAAC_ORBIT_NUCLEUS_DIR}/Robots/FrankaEmika/panda_xyz.usd"
# check file path
self.assertEqual(assets_utils.check_file_path(usd_path), 0)
if __name__ == "__main__":
run_tests()
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