Source code for omni.isaac.lab.sim.spawners.shapes.shapes

# Copyright (c) 2022-2024, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

from __future__ import annotations

from typing import TYPE_CHECKING

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

from omni.isaac.lab.sim import schemas
from omni.isaac.lab.sim.utils import bind_physics_material, bind_visual_material, clone

if TYPE_CHECKING:
    from . import shapes_cfg


[docs]@clone def spawn_sphere( prim_path: str, cfg: shapes_cfg.SphereCfg, translation: tuple[float, float, float] | None = None, orientation: tuple[float, float, float, float] | None = None, ) -> Usd.Prim: """Create a USDGeom-based sphere prim with the given attributes. For more information, see `USDGeomSphere <https://openusd.org/dev/api/class_usd_geom_sphere.html>`_. .. note:: This function is decorated with :func:`clone` that resolves prim path into list of paths if the input prim path is a regex pattern. This is done to support spawning multiple assets from a single and cloning the USD prim at the given path expression. Args: 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. cfg: The configuration instance. translation: The translation to apply to the prim w.r.t. its parent prim. Defaults to None, in which case this is set to the origin. orientation: The orientation in (w, x, y, z) to apply to the prim w.r.t. its parent prim. Defaults to None, in which case this is set to identity. Returns: The created prim. Raises: ValueError: If a prim already exists at the given path. """ # spawn sphere if it doesn't exist. attributes = {"radius": cfg.radius} _spawn_geom_from_prim_type(prim_path, cfg, "Sphere", attributes, translation, orientation) # return the prim return prim_utils.get_prim_at_path(prim_path)
[docs]@clone def spawn_cuboid( prim_path: str, cfg: shapes_cfg.CuboidCfg, translation: tuple[float, float, float] | None = None, orientation: tuple[float, float, float, float] | None = None, ) -> Usd.Prim: """Create a USDGeom-based cuboid prim with the given attributes. For more information, see `USDGeomCube <https://openusd.org/dev/api/class_usd_geom_cube.html>`_. Note: Since USD only supports cubes, we set the size of the cube to the minimum of the given size and scale the cube accordingly. .. note:: This function is decorated with :func:`clone` that resolves prim path into list of paths if the input prim path is a regex pattern. This is done to support spawning multiple assets from a single and cloning the USD prim at the given path expression. Args: 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. cfg: The configuration instance. translation: The translation to apply to the prim w.r.t. its parent prim. Defaults to None, in which case this is set to the origin. orientation: The orientation in (w, x, y, z) to apply to the prim w.r.t. its parent prim. Defaults to None, in which case this is set to identity. Returns: The created prim. Raises: If a prim already exists at the given path. """ # resolve the scale size = min(cfg.size) scale = [dim / size for dim in cfg.size] # spawn cuboid if it doesn't exist. attributes = {"size": size} _spawn_geom_from_prim_type(prim_path, cfg, "Cube", attributes, translation, orientation, scale) # return the prim return prim_utils.get_prim_at_path(prim_path)
[docs]@clone def spawn_cylinder( prim_path: str, cfg: shapes_cfg.CylinderCfg, translation: tuple[float, float, float] | None = None, orientation: tuple[float, float, float, float] | None = None, ) -> Usd.Prim: """Create a USDGeom-based cylinder prim with the given attributes. For more information, see `USDGeomCylinder <https://openusd.org/dev/api/class_usd_geom_cylinder.html>`_. .. note:: This function is decorated with :func:`clone` that resolves prim path into list of paths if the input prim path is a regex pattern. This is done to support spawning multiple assets from a single and cloning the USD prim at the given path expression. Args: 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. cfg: The configuration instance. translation: The translation to apply to the prim w.r.t. its parent prim. Defaults to None, in which case this is set to the origin. orientation: The orientation in (w, x, y, z) to apply to the prim w.r.t. its parent prim. Defaults to None, in which case this is set to identity. Returns: The created prim. Raises: ValueError: If a prim already exists at the given path. """ # spawn cylinder if it doesn't exist. attributes = {"radius": cfg.radius, "height": cfg.height, "axis": cfg.axis.upper()} _spawn_geom_from_prim_type(prim_path, cfg, "Cylinder", attributes, translation, orientation) # return the prim return prim_utils.get_prim_at_path(prim_path)
[docs]@clone def spawn_capsule( prim_path: str, cfg: shapes_cfg.CapsuleCfg, translation: tuple[float, float, float] | None = None, orientation: tuple[float, float, float, float] | None = None, ) -> Usd.Prim: """Create a USDGeom-based capsule prim with the given attributes. For more information, see `USDGeomCapsule <https://openusd.org/dev/api/class_usd_geom_capsule.html>`_. .. note:: This function is decorated with :func:`clone` that resolves prim path into list of paths if the input prim path is a regex pattern. This is done to support spawning multiple assets from a single and cloning the USD prim at the given path expression. Args: 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. cfg: The configuration instance. translation: The translation to apply to the prim w.r.t. its parent prim. Defaults to None, in which case this is set to the origin. orientation: The orientation in (w, x, y, z) to apply to the prim w.r.t. its parent prim. Defaults to None, in which case this is set to identity. Returns: The created prim. Raises: ValueError: If a prim already exists at the given path. """ # spawn capsule if it doesn't exist. attributes = {"radius": cfg.radius, "height": cfg.height, "axis": cfg.axis.upper()} _spawn_geom_from_prim_type(prim_path, cfg, "Capsule", attributes, translation, orientation) # return the prim return prim_utils.get_prim_at_path(prim_path)
[docs]@clone def spawn_cone( prim_path: str, cfg: shapes_cfg.ConeCfg, translation: tuple[float, float, float] | None = None, orientation: tuple[float, float, float, float] | None = None, ) -> Usd.Prim: """Create a USDGeom-based cone prim with the given attributes. For more information, see `USDGeomCone <https://openusd.org/dev/api/class_usd_geom_cone.html>`_. .. note:: This function is decorated with :func:`clone` that resolves prim path into list of paths if the input prim path is a regex pattern. This is done to support spawning multiple assets from a single and cloning the USD prim at the given path expression. Args: 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. cfg: The configuration instance. translation: The translation to apply to the prim w.r.t. its parent prim. Defaults to None, in which case this is set to the origin. orientation: The orientation in (w, x, y, z) to apply to the prim w.r.t. its parent prim. Defaults to None, in which case this is set to identity. Returns: The created prim. Raises: ValueError: If a prim already exists at the given path. """ # spawn cone if it doesn't exist. attributes = {"radius": cfg.radius, "height": cfg.height, "axis": cfg.axis.upper()} _spawn_geom_from_prim_type(prim_path, cfg, "Cone", attributes, translation, orientation) # return the prim return prim_utils.get_prim_at_path(prim_path)
""" Helper functions. """ def _spawn_geom_from_prim_type( prim_path: str, cfg: shapes_cfg.ShapeCfg, prim_type: str, attributes: dict, translation: tuple[float, float, float] | None = None, orientation: tuple[float, float, float, float] | None = None, scale: tuple[float, float, float] | None = None, ): """Create a USDGeom-based prim with the given attributes. To make the asset instanceable, we must follow a certain structure dictated by how USD scene-graph instancing and physics work. The rigid body component must be added to each instance and not the referenced asset (i.e. the prototype prim itself). This is because the rigid body component defines properties that are specific to each instance and cannot be shared under the referenced asset. For more information, please check the `documentation <https://docs.omniverse.nvidia.com/extensions/latest/ext_physics/rigid-bodies.html#instancing-rigid-bodies>`_. Due to the above, we follow the following structure: * ``{prim_path}`` - The root prim that is an Xform with the rigid body and mass APIs if configured. * ``{prim_path}/geometry`` - The prim that contains the mesh and optionally the materials if configured. If instancing is enabled, this prim will be an instanceable reference to the prototype prim. Args: prim_path: The prim path to spawn the asset at. cfg: The config containing the properties to apply. prim_type: The type of prim to create. attributes: The attributes to apply to the prim. translation: The translation to apply to the prim w.r.t. its parent prim. Defaults to None, in which case this is set to the origin. orientation: The orientation in (w, x, y, z) to apply to the prim w.r.t. its parent prim. Defaults to None, in which case this is set to identity. scale: The scale to apply to the prim. Defaults to None, in which case this is set to identity. Raises: ValueError: If a prim already exists at the given path. """ # spawn geometry if it doesn't exist. if not prim_utils.is_prim_path_valid(prim_path): prim_utils.create_prim(prim_path, prim_type="Xform", translation=translation, orientation=orientation) else: raise ValueError(f"A prim already exists at path: '{prim_path}'.") # create all the paths we need for clarity geom_prim_path = prim_path + "/geometry" mesh_prim_path = geom_prim_path + "/mesh" # create the geometry prim prim_utils.create_prim(mesh_prim_path, prim_type, scale=scale, attributes=attributes) # apply collision properties if cfg.collision_props is not None: schemas.define_collision_properties(mesh_prim_path, cfg.collision_props) # apply visual material if cfg.visual_material is not None: if not cfg.visual_material_path.startswith("/"): material_path = f"{geom_prim_path}/{cfg.visual_material_path}" else: material_path = cfg.visual_material_path # create material cfg.visual_material.func(material_path, cfg.visual_material) # apply material bind_visual_material(mesh_prim_path, material_path) # apply physics material if cfg.physics_material is not None: if not cfg.physics_material_path.startswith("/"): material_path = f"{geom_prim_path}/{cfg.physics_material_path}" else: material_path = cfg.physics_material_path # create material cfg.physics_material.func(material_path, cfg.physics_material) # apply material bind_physics_material(mesh_prim_path, material_path) # note: we apply rigid properties in the end to later make the instanceable prim # apply mass properties if cfg.mass_props is not None: schemas.define_mass_properties(prim_path, cfg.mass_props) # apply rigid body properties if cfg.rigid_props is not None: schemas.define_rigid_body_properties(prim_path, cfg.rigid_props)