Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds configuration classes for spawning different assets at prim paths #1164

Merged
merged 31 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b540a5f
adds demo on multi-object
Mayankm96 Oct 4, 2024
106b267
moves randomization to its own function
Mayankm96 Oct 4, 2024
86e0946
adds wrapper for multi asset spawn
Mayankm96 Oct 4, 2024
ad15267
adds multi asset py
Mayankm96 Oct 4, 2024
f19cb63
removes version addded notice
Mayankm96 Oct 5, 2024
ab9f892
allows overriding global settings in cfg
Mayankm96 Oct 5, 2024
d919efe
adds spawning of multi usd files
Mayankm96 Oct 5, 2024
2ec63fb
combines multi usd file into multi-asset
Mayankm96 Oct 6, 2024
18ef1fd
reduces solver count
Mayankm96 Oct 6, 2024
ea64b87
renames function
Mayankm96 Oct 6, 2024
93daf30
fixes documentation
Mayankm96 Oct 6, 2024
1c2f234
adds version log
Mayankm96 Oct 6, 2024
0c9b63c
runs formatter
Mayankm96 Oct 6, 2024
33247a5
Added docs
Dhoeller19 Oct 8, 2024
07710f8
Merge branch 'main' into feature/multi-object
Dhoeller19 Oct 8, 2024
d7a8551
Update docs
Dhoeller19 Oct 8, 2024
7be898d
adds more points to note to how-to
Mayankm96 Oct 9, 2024
f8050e2
runs formatter
Mayankm96 Oct 9, 2024
0dc3691
fixes tab ordering
Mayankm96 Oct 9, 2024
798b5cd
fix tab
Mayankm96 Oct 9, 2024
9f6f0c1
fixes doc
Mayankm96 Oct 9, 2024
845ac59
Apply suggestions from code review
Mayankm96 Oct 9, 2024
6375eb8
Apply suggestions from code review
Mayankm96 Oct 9, 2024
144f15d
Apply suggestions from code review
Mayankm96 Oct 9, 2024
df63363
make function safer
Mayankm96 Oct 9, 2024
2e6c299
adds test
Mayankm96 Oct 9, 2024
df51fb2
adds test for files as well
Mayankm96 Oct 9, 2024
1378991
adds check for multi-asset spawning
Mayankm96 Oct 9, 2024
49353c3
moves the check up
Mayankm96 Oct 9, 2024
fefda69
checks
Mayankm96 Oct 9, 2024
90300a7
Merge branch 'main' into feature/multi-object
Mayankm96 Oct 9, 2024
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
Binary file added docs/source/_static/demos/multi_asset.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions docs/source/api/lab/omni.isaac.lab.sim.spawners.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
sensors
from_files
materials
wrappers

.. rubric:: Classes

Expand Down Expand Up @@ -302,3 +303,27 @@ Physical Materials
.. autoclass:: DeformableBodyMaterialCfg
:members:
:exclude-members: __init__, func

Wrappers
--------

.. automodule:: omni.isaac.lab.sim.spawners.wrappers

.. rubric:: Classes

.. autosummary::

MultiAssetSpawnerCfg
MultiUsdFileCfg

.. autofunction:: spawn_multi_asset

.. autoclass:: MultiAssetSpawnerCfg
:members:
:exclude-members: __init__, func

.. autofunction:: spawn_multi_usd_file

.. autoclass:: MultiUsdFileCfg
:members:
:exclude-members: __init__, func
11 changes: 11 additions & 0 deletions docs/source/how-to/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ a fixed base robot. This guide goes over the various considerations and steps to

make_fixed_prim

Multi-Asset Spawning
--------------------

This guide explains how to import and configure different assets in each environment. This is
useful when you want to create diverse environments with different objects.

.. toctree::
:maxdepth: 1

multi_asset_spawning

Saving Camera Output
--------------------

Expand Down
72 changes: 72 additions & 0 deletions docs/source/how-to/multi_asset_spawning.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
Spawning Multiple Assets
========================

.. currentmodule:: omni.isaac.lab

This guide describes how to create different assets within each environment using spawning functions that allow for random selection of assets.
The approach is useful to create diversity in your simulations. The sample script ``multi_asset.py`` is used as a reference, located in the ``IsaacLab/source/standalone/demos`` directory.

.. dropdown:: Code for multi_asset.py
:icon: code

.. literalinclude:: ../../../source/standalone/demos/multi_asset.py
:language: python
:linenos:

This script creates multiple environments, where each environment has a rigid object that is either a cone, a cube, or a sphere,
and an articulation that is either the ANYmal-C or ANYmal-D robot.

.. image:: ../_static/demos/multi_asset.jpg
:width: 100%
:alt: result of multi_asset.py

Using Multi-Asset Spawning Functions
------------------------------------

It is possible to spawn different assets and USDs in each environment using the spawners :class:`~sim.spawners.wrappers.MultiAssetSpawnerCfg` and :class:`~sim_utils.MultiUsdFileCfg`:

* We set the spawn configuration in :class:`~RigidObjectCfg` to be :class:`~sim.spawners.wrappers.MultiAssetSpawnerCfg`:

.. literalinclude:: ../../../source/standalone/demos/multi_asset.py
:language: python
:lines: 99-125
:dedent:

This function allows you to define a list of different assets that can be spawned as rigid objects.
When ``random_choice=True`` is set, one asset from the list is randomly selected each time an object is spawned.

* We set the spawn configuration in :class:`~ArticulationCfg` to be :class:`~sim_utils.MultiUsdFileCfg`:

.. literalinclude:: ../../../source/standalone/demos/multi_asset.py
:language: python
:lines: 128-161
:dedent:

This configuration allows the selection of different USD files representing articulated assets.
With ``random_choice=True``, the spawning process picks one of the specified assets at random. In the following scenario,
it is important to note that the articulation must have the same structure (same links, joints, names, etc.) across all USD files.
The purpose is to enable the user to create randomized versions of the same asset, for example with different link lengths.



Executing the Simulation
------------------------

To execute the script with multiple environments and randomized assets, use the following command:

.. code-block:: bash

./isaaclab.sh -p source/standalone/demos/multi_asset.py --num_envs 2048

This command runs the simulation with 2048 environments, each with randomly selected assets.

Stopping the Simulation
-----------------------

To stop the simulation, use the following command in the terminal:

.. code-block:: bash

Ctrl+C

This safely terminates the simulation.
2 changes: 1 addition & 1 deletion source/extensions/omni.isaac.lab/config/extension.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

# Note: Semantic Versioning is used: https://semver.org/
version = "0.24.19"
version = "0.24.20"

# Description
title = "Isaac Lab framework for Robot Learning"
Expand Down
10 changes: 10 additions & 0 deletions source/extensions/omni.isaac.lab/docs/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
Changelog
---------

0.24.20 (2024-10-06)
~~~~~~~~~~~~~~~~~~~~

Added
^^^^^

* Added configuration classes for spawning assets from a list of individual asset configurations randomly
at the specified prim paths.


0.24.19 (2024-10-05)
~~~~~~~~~~~~~~~~~~~~

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,4 @@ class and the function call in a single line of code.
from .sensors import * # noqa: F401, F403
from .shapes import * # noqa: F401, F403
from .spawner_cfg import * # noqa: F401, F403
from .wrappers import * # noqa: F401, F403
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,6 @@ class SpawnerCfg:
This parameter is only used when cloning prims. If False, then the asset will be inherited from
the source prim, i.e. all USD changes to the source prim will be reflected in the cloned prims.
.. versionadded:: 2023.1
This parameter is only supported from Isaac Sim 2023.1 onwards. If you are using an older
version of Isaac Sim, this parameter will be ignored.
"""


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (c) 2022-2024, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

"""Sub-module for wrapping spawner configurations.

Unlike the other spawner modules, this module provides a way to wrap multiple spawner configurations
into a single configuration. This is useful when the user wants to spawn multiple assets based on
different configurations.
"""

from .wrappers import spawn_multi_asset, spawn_multi_usd_file
from .wrappers_cfg import MultiAssetSpawnerCfg, MultiUsdFileCfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# Copyright (c) 2022-2024, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

from __future__ import annotations

import random
import re
from typing import TYPE_CHECKING

import omni.isaac.core.utils.prims as prim_utils
import omni.usd
from pxr import Sdf, Usd

import omni.isaac.lab.sim as sim_utils
from omni.isaac.lab.sim.spawners.from_files import UsdFileCfg

if TYPE_CHECKING:
from . import wrappers_cfg


def spawn_multi_asset(
prim_path: str,
cfg: wrappers_cfg.MultiAssetSpawnerCfg,
translation: tuple[float, float, float] | None = None,
orientation: tuple[float, float, float, float] | None = None,
) -> Usd.Prim:
"""Spawn multiple assets based on the provided configurations.

This function spawns multiple assets based on the provided configurations. The assets are spawned
in the order they are provided in the list. If the `random_choice` parameter is set to True, a random
Mayankm96 marked this conversation as resolved.
Show resolved Hide resolved
asset configuration is selected for each spawn.

Args:
prim_path: The prim path to spawn the assets.
cfg: The configuration for spawning the assets.
translation: The translation of the spawned assets. Default is None.
orientation: The orientation of the spawned assets. Default is None.
Mayankm96 marked this conversation as resolved.
Show resolved Hide resolved

Returns:
The created prim at the first prim path.
"""
# resolve: {SPAWN_NS}/AssetName
# note: this assumes that the spawn namespace already exists in the stage
root_path, asset_path = prim_path.rsplit("/", 1)
# check if input is a regex expression
# note: a valid prim path can only contain alphanumeric characters, underscores, and forward slashes
is_regex_expression = re.match(r"^[a-zA-Z0-9/_]+$", root_path) is None

# resolve matching prims for source prim path expression
if is_regex_expression and root_path != "":
source_prim_paths = sim_utils.find_matching_prim_paths(root_path)
# if no matching prims are found, raise an error
if len(source_prim_paths) == 0:
raise RuntimeError(
f"Unable to find source prim path: '{root_path}'. Please create the prim before spawning."
)
else:
source_prim_paths = [root_path]

# spawn everything first in a "Dataset" prim
prim_utils.create_prim("/World/Dataset", "Scope")
Mayankm96 marked this conversation as resolved.
Show resolved Hide resolved
proto_prim_paths = list()
for index, asset_cfg in enumerate(cfg.assets_cfg):
# append semantic tags if specified
if cfg.semantic_tags is not None:
if asset_cfg.semantic_tags is None:
asset_cfg.semantic_tags = cfg.semantic_tags
else:
asset_cfg.semantic_tags += cfg.semantic_tags
# override settings for properties
attr_names = ["mass_props", "rigid_props", "collision_props", "activate_contact_sensors", "deformable_props"]
for attr_name in attr_names:
attr_value = getattr(cfg, attr_name)
if hasattr(asset_cfg, attr_name) and attr_value is not None:
setattr(asset_cfg, attr_name, attr_value)
# spawn single instance
proto_prim_path = f"/World/Dataset/Asset_{index:04d}"
asset_cfg.func(proto_prim_path, asset_cfg, translation=translation, orientation=orientation)
# append to proto prim paths
proto_prim_paths.append(proto_prim_path)

# resolve prim paths for spawning and cloning
prim_paths = [f"{source_prim_path}/{asset_path}" for source_prim_path in source_prim_paths]
# acquire stage
stage = omni.usd.get_context().get_stage()

# manually clone prims if the source prim path is a regex expression
# note: unlike in the cloner API from Isaac Sim, we do not "reset" xforms on the copied prims.
# This is because the "spawn" calls during the creation of the proto prims already handles this operation.
with Sdf.ChangeBlock():
for index, prim_path in enumerate(prim_paths):
# spawn single instance
env_spec = Sdf.CreatePrimInLayer(stage.GetRootLayer(), prim_path)
# randomly select an asset configuration
if cfg.random_choice:
proto_path = random.choice(proto_prim_paths)
else:
proto_path = proto_prim_paths[index % len(proto_prim_paths)]
# copy the proto prim
Sdf.CopySpec(env_spec.layer, Sdf.Path(proto_path), env_spec.layer, Sdf.Path(prim_path))

# delete the dataset prim after spawning
prim_utils.delete_prim("/World/Dataset")

# return the prim
return prim_utils.get_prim_at_path(prim_paths[0])


def spawn_multi_usd_file(
prim_path: str,
cfg: wrappers_cfg.MultiUsdFileCfg,
translation: tuple[float, float, float] | None = None,
orientation: tuple[float, float, float, float] | None = None,
) -> Usd.Prim:
"""Spawn multiple USD files based on the provided configurations.

This function creates configuration instances corresponding the individual USD files and
calls the :meth:`spawn_multi_asset` method to spawn them into the scene.

Args:
prim_path: The prim path to spawn the assets.
cfg: The configuration for spawning the assets.
translation: The translation of the spawned assets. Default is None.
orientation: The orientation of the spawned assets. Default is None.
Mayankm96 marked this conversation as resolved.
Show resolved Hide resolved

Returns:
The created prim at the first prim path.
"""
# needed here to avoid circular imports
from .wrappers_cfg import MultiAssetSpawnerCfg

# parse all the usd files
if isinstance(cfg.usd_path, str):
usd_paths = [cfg.usd_path]
else:
usd_paths = cfg.usd_path

# make a template usd config
usd_template_cfg = UsdFileCfg()
for attr_name, attr_value in cfg.__dict__.items():
# skip names we know are not present
if attr_name in ["func", "usd_path", "random_choice"]:
continue
# set the attribute into the template
setattr(usd_template_cfg, attr_name, attr_value)

# create multi asset configuration of USD files
multi_asset_cfg = MultiAssetSpawnerCfg(assets_cfg=[])
for usd_path in usd_paths:
usd_cfg = usd_template_cfg.replace(usd_path=usd_path)
multi_asset_cfg.assets_cfg.append(usd_cfg)
# set random choice
multi_asset_cfg.random_choice = cfg.random_choice

# call the original function
return spawn_multi_asset(prim_path, multi_asset_cfg, translation, orientation)
Loading
Loading