Skip to content

prim_base

BasePrim

Bases: Serializable, UniquelyNamed, Recreatable, ABC

Provides high level functions to deal with a basic prim and its attributes/ properties. If there is an Xform prim present at the path, it will use it. Otherwise, a new XForm prim at the specified prim path will be created.

the prim will have "xformOp:orient", "xformOp:translate" and "xformOp:scale" only post init,

unless it is a non-root articulation link.

Parameters:

Name Type Description Default
prim_path str

prim path of the Prim to encapsulate or create.

required
name str

Name for the object. Names need to be unique per scene.

required
load_config None or dict

If specified, should contain keyword-mapped values that are relevant for loading this prim at runtime. Note that this is only needed if the prim does not already exist at @prim_path -- it will be ignored if it already exists. Subclasses should define the exact keys expected for their class.

None
Source code in prims/prim_base.py
class BasePrim(Serializable, UniquelyNamed, Recreatable, ABC):
    """
    Provides high level functions to deal with a basic prim and its attributes/ properties.
    If there is an Xform prim present at the path, it will use it. Otherwise, a new XForm prim at
    the specified prim path will be created.

    Note: the prim will have "xformOp:orient", "xformOp:translate" and "xformOp:scale" only post init,
        unless it is a non-root articulation link.

    Args:
        prim_path (str): prim path of the Prim to encapsulate or create.
        name (str): Name for the object. Names need to be unique per scene.
        load_config (None or dict): If specified, should contain keyword-mapped values that are relevant for
            loading this prim at runtime. Note that this is only needed if the prim does not already exist at
            @prim_path -- it will be ignored if it already exists. Subclasses should define the exact keys expected
            for their class.
    """

    def __init__(
        self,
        prim_path,
        name,
        load_config=None,
    ):
        self._prim_path = prim_path
        self._name = name
        self._load_config = {} if load_config is None else load_config

        # Other values that will be filled in at runtime
        self._applied_visual_material = None
        self._loaded = False                                # Whether this prim exists in the stage or not
        self._initialized = False                           # Whether this prim has its internal handles / info initialized or not (occurs AFTER and INDEPENDENTLY from loading!)
        self._prim = None
        self._state_size = None
        self._n_duplicates = 0                              # Simple counter for keeping track of duplicates for unique name indexing

        # Run some post-loading steps if this prim has already been loaded
        if is_prim_path_valid(prim_path=self._prim_path):
            logging.debug(f"prim {name} already exists, skipping load")
            self._prim = get_prim_at_path(prim_path=self._prim_path)
            self._loaded = True
            # Run post load.
            self._post_load()

        # Run super init
        super().__init__()

    def _initialize(self):
        """
        Initializes state of this object and sets up any references necessary post-loading. Should be implemented by
        sub-class for extended utility
        """
        pass

    def initialize(self):
        """
        Initializes state of this object and sets up any references necessary post-loading. Subclasses should
        implement / extend the _initialize() method.
        """
        assert not self._initialized, \
            f"Prim {self.name} at prim_path {self._prim_path} can only be initialized once! (It is already initialized)"
        self._initialize()

        # Cache state size
        self._state_size = len(self.dump_state(serialized=True))

        self._initialized = True

    def load(self, simulator=None):
        """
        Load this prim into omniverse, optionally integrating this prim with simulator context @simulator, and return
        loaded prim reference.

        Args:
            simulator (None or SimulationContext): If specified, should be simulator into which this prim will be
                loaded. Otherwise, it will be loaded into the default stage

        Returns:
            Usd.Prim: Prim object loaded into the simulator
        """
        if self._loaded:
            raise ValueError("Cannot load a single prim multiple times.")

        # Load prim
        self._prim = self._load(simulator=simulator)
        self._loaded = True

        # Run any post-loading logic
        self._post_load()

        return self._prim

    def _post_load(self):
        """
        Any actions that should be taken (e.g.: modifying the object's properties such as scale, visibility, additional
        joints, etc.) that should be taken after loading the raw object into omniverse but BEFORE we initialize the
        object and grab its handles and internal references. By default, this is a no-op.
        """
        pass

    def remove(self, simulator=None):
        """
        Removes this prim from omniverse stage

        Args:
            simulator (None or SimulationContext): If specified, should be simulator into which this prim will be
                removed. Otherwise, it will be removed from the default stage
        """
        if not self._loaded:
            raise ValueError("Cannot remove a prim that was never loaded.")

        # Remove prim
        delete_prim(self.prim_path)
        if simulator:
            # Also clear the name so we can reuse this later
            self.remove_names(include_all_owned=True, skip_ids={id(simulator)})

    @abstractmethod
    def _load(self, simulator=None):
        """
        Loads the raw prim into the simulator. Any post-processing should be done in @self._post_load()

        Args:
            simulator (Simulator): Active simulation context
        """
        raise NotImplementedError()

    @property
    def loaded(self):
        return self._loaded

    @property
    def initialized(self):
        return self._initialized

    @property
    def state_size(self):
        # This is the cached value
        return self._state_size

    @property
    def prim_path(self):
        """
        Returns:
            str: prim path in the stage.
        """
        return self._prim_path

    @property
    def name(self):
        """
        Returns:
            str: unique name assigned to this prim
        """
        return self._name

    @property
    def prim(self):
        """
        Returns:
            Usd.Prim: USD Prim object that this object holds.
        """
        return self._prim

    @property
    def property_names(self):
        """
        Returns:
            set of str: Set of property names that this prim has (e.g.: visibility, proxyPrim, etc.)
        """
        return set(self._prim.GetPropertyNames())

    @property
    def visible(self):
        """
        Returns:
            bool: true if the prim is visible in stage. false otherwise.
        """
        return UsdGeom.Imageable(self.prim).ComputeVisibility(Usd.TimeCode.Default()) != UsdGeom.Tokens.invisible

    @visible.setter
    def visible(self, visible):
        """
        Sets the visibility of the prim in stage.

        Args:
            visible (bool): flag to set the visibility of the usd prim in stage.
        """
        imageable = UsdGeom.Imageable(self.prim)
        if visible:
            imageable.MakeVisible()
        else:
            imageable.MakeInvisible()
        return

    def is_valid(self):
        """
        Returns:
            bool: True is the current prim path corresponds to a valid prim in stage. False otherwise.
        """
        return is_prim_path_valid(self.prim_path)

    def change_prim_path(self, new_prim_path):
        """
        Moves prim from the old path to a new one.

        Args:
            new_prim_path (str): new path of the prim to be moved to.
        """
        move_prim(path_from=self.prim_path, path_to=new_prim_path)
        self._prim_path = new_prim_path
        self._prim = get_prim_at_path(self._prim_path)
        return

    def get_attribute(self, attr):
        """
        Get this prim's attribute. Should be a valid attribute under self._prim.GetAttributes()

        Returns:
            any: value of the requested @attribute
        """
        return self._prim.GetAttribute(attr).Get()

    def set_attribute(self, attr, val):
        """
        Set this prim's attribute. Should be a valid attribute under self._prim.GetAttributes()

        Args:
            attr (str): Attribute to set
            val (any): Value to set for the attribute. This should be the valid type for that attribute.
        """
        self._prim.GetAttribute(attr).Set(val)

    def get_property(self, prop):
        """
        Sets property @prop with value @val

        Args:
            prop (str): Name of the property to get. See Raw USD Properties in the GUI for examples of property names

        Returns:
            any: Property value
        """
        self._prim.GetProperty(prop).Get()

    def set_property(self, prop, val):
        """
        Sets property @prop with value @val

        Args:
            prop (str): Name of the property to set. See Raw USD Properties in the GUI for examples of property names
            val (any): Value to set for the property. Should be valid for that property
        """
        self._prim.GetProperty(prop).Set(val)

    def get_custom_data(self):
        """
        Get custom data associated with this prim

        Returns:
            dict: Dictionary of any custom information
        """
        return self._prim.GetCustomData()

    def _create_prim_with_same_kwargs(self, prim_path, name, load_config):
        """
        Generates a new instance of this prim's class with specified @prim_path, @name, and @load_config, but otherwise
        all other kwargs should be identical to this instance's values.

        Args:
            prim_path (str): Absolute path to the newly generated prim
            name (str): Name for the newly created prim
            load_config (dict): Keyword-mapped kwargs to use to set specific attributes for the created prim's instance

        Returns:
            BasePrim: Generated prim object (not loaded, and not initialized!)
        """
        return self.__class__(
            prim_path=prim_path,
            name=name,
            load_config=load_config,
        )

    def duplicate(self, simulator, prim_path):
        """
        Duplicates this object, and generates a new instance at @prim_path.
        Note that the created object is automatically loaded into the simulator, but is NOT initialized
        until a sim step occurs!

        Args:
            simulator (Simulator): simulation instance to load this object
            prim_path (str): Absolute path to the newly generated prim

        Returns:
            BasePrim: Generated prim object
        """
        new_prim = self._create_prim_with_same_kwargs(
            prim_path=prim_path,
            name=f"{self.name}_copy{self._n_duplicates}",
            load_config=self._load_config,
        )
        simulator.import_object(new_prim, register=False, auto_initialize=True)

        # Increment duplicate count
        self._n_duplicates += 1

        # Set visibility
        new_prim.visible = self.visible

        return new_prim

name property

Returns:

Name Type Description
str

unique name assigned to this prim

prim property

Returns:

Type Description

Usd.Prim: USD Prim object that this object holds.

prim_path property

Returns:

Name Type Description
str

prim path in the stage.

property_names property

Returns:

Type Description

set of str: Set of property names that this prim has (e.g.: visibility, proxyPrim, etc.)

visible property writable

Returns:

Name Type Description
bool

true if the prim is visible in stage. false otherwise.

change_prim_path(new_prim_path)

Moves prim from the old path to a new one.

Parameters:

Name Type Description Default
new_prim_path str

new path of the prim to be moved to.

required
Source code in prims/prim_base.py
def change_prim_path(self, new_prim_path):
    """
    Moves prim from the old path to a new one.

    Args:
        new_prim_path (str): new path of the prim to be moved to.
    """
    move_prim(path_from=self.prim_path, path_to=new_prim_path)
    self._prim_path = new_prim_path
    self._prim = get_prim_at_path(self._prim_path)
    return

duplicate(simulator, prim_path)

Duplicates this object, and generates a new instance at @prim_path. Note that the created object is automatically loaded into the simulator, but is NOT initialized until a sim step occurs!

Parameters:

Name Type Description Default
simulator Simulator

simulation instance to load this object

required
prim_path str

Absolute path to the newly generated prim

required

Returns:

Name Type Description
BasePrim

Generated prim object

Source code in prims/prim_base.py
def duplicate(self, simulator, prim_path):
    """
    Duplicates this object, and generates a new instance at @prim_path.
    Note that the created object is automatically loaded into the simulator, but is NOT initialized
    until a sim step occurs!

    Args:
        simulator (Simulator): simulation instance to load this object
        prim_path (str): Absolute path to the newly generated prim

    Returns:
        BasePrim: Generated prim object
    """
    new_prim = self._create_prim_with_same_kwargs(
        prim_path=prim_path,
        name=f"{self.name}_copy{self._n_duplicates}",
        load_config=self._load_config,
    )
    simulator.import_object(new_prim, register=False, auto_initialize=True)

    # Increment duplicate count
    self._n_duplicates += 1

    # Set visibility
    new_prim.visible = self.visible

    return new_prim

get_attribute(attr)

Get this prim's attribute. Should be a valid attribute under self._prim.GetAttributes()

Returns:

Name Type Description
any

value of the requested @attribute

Source code in prims/prim_base.py
def get_attribute(self, attr):
    """
    Get this prim's attribute. Should be a valid attribute under self._prim.GetAttributes()

    Returns:
        any: value of the requested @attribute
    """
    return self._prim.GetAttribute(attr).Get()

get_custom_data()

Get custom data associated with this prim

Returns:

Name Type Description
dict

Dictionary of any custom information

Source code in prims/prim_base.py
def get_custom_data(self):
    """
    Get custom data associated with this prim

    Returns:
        dict: Dictionary of any custom information
    """
    return self._prim.GetCustomData()

get_property(prop)

Sets property @prop with value @val

Parameters:

Name Type Description Default
prop str

Name of the property to get. See Raw USD Properties in the GUI for examples of property names

required

Returns:

Name Type Description
any

Property value

Source code in prims/prim_base.py
def get_property(self, prop):
    """
    Sets property @prop with value @val

    Args:
        prop (str): Name of the property to get. See Raw USD Properties in the GUI for examples of property names

    Returns:
        any: Property value
    """
    self._prim.GetProperty(prop).Get()

initialize()

Initializes state of this object and sets up any references necessary post-loading. Subclasses should implement / extend the _initialize() method.

Source code in prims/prim_base.py
def initialize(self):
    """
    Initializes state of this object and sets up any references necessary post-loading. Subclasses should
    implement / extend the _initialize() method.
    """
    assert not self._initialized, \
        f"Prim {self.name} at prim_path {self._prim_path} can only be initialized once! (It is already initialized)"
    self._initialize()

    # Cache state size
    self._state_size = len(self.dump_state(serialized=True))

    self._initialized = True

is_valid()

Returns:

Name Type Description
bool

True is the current prim path corresponds to a valid prim in stage. False otherwise.

Source code in prims/prim_base.py
def is_valid(self):
    """
    Returns:
        bool: True is the current prim path corresponds to a valid prim in stage. False otherwise.
    """
    return is_prim_path_valid(self.prim_path)

load(simulator=None)

Load this prim into omniverse, optionally integrating this prim with simulator context @simulator, and return loaded prim reference.

Parameters:

Name Type Description Default
simulator None or SimulationContext

If specified, should be simulator into which this prim will be loaded. Otherwise, it will be loaded into the default stage

None

Returns:

Type Description

Usd.Prim: Prim object loaded into the simulator

Source code in prims/prim_base.py
def load(self, simulator=None):
    """
    Load this prim into omniverse, optionally integrating this prim with simulator context @simulator, and return
    loaded prim reference.

    Args:
        simulator (None or SimulationContext): If specified, should be simulator into which this prim will be
            loaded. Otherwise, it will be loaded into the default stage

    Returns:
        Usd.Prim: Prim object loaded into the simulator
    """
    if self._loaded:
        raise ValueError("Cannot load a single prim multiple times.")

    # Load prim
    self._prim = self._load(simulator=simulator)
    self._loaded = True

    # Run any post-loading logic
    self._post_load()

    return self._prim

remove(simulator=None)

Removes this prim from omniverse stage

Parameters:

Name Type Description Default
simulator None or SimulationContext

If specified, should be simulator into which this prim will be removed. Otherwise, it will be removed from the default stage

None
Source code in prims/prim_base.py
def remove(self, simulator=None):
    """
    Removes this prim from omniverse stage

    Args:
        simulator (None or SimulationContext): If specified, should be simulator into which this prim will be
            removed. Otherwise, it will be removed from the default stage
    """
    if not self._loaded:
        raise ValueError("Cannot remove a prim that was never loaded.")

    # Remove prim
    delete_prim(self.prim_path)
    if simulator:
        # Also clear the name so we can reuse this later
        self.remove_names(include_all_owned=True, skip_ids={id(simulator)})

set_attribute(attr, val)

Set this prim's attribute. Should be a valid attribute under self._prim.GetAttributes()

Parameters:

Name Type Description Default
attr str

Attribute to set

required
val any

Value to set for the attribute. This should be the valid type for that attribute.

required
Source code in prims/prim_base.py
def set_attribute(self, attr, val):
    """
    Set this prim's attribute. Should be a valid attribute under self._prim.GetAttributes()

    Args:
        attr (str): Attribute to set
        val (any): Value to set for the attribute. This should be the valid type for that attribute.
    """
    self._prim.GetAttribute(attr).Set(val)

set_property(prop, val)

Sets property @prop with value @val

Parameters:

Name Type Description Default
prop str

Name of the property to set. See Raw USD Properties in the GUI for examples of property names

required
val any

Value to set for the property. Should be valid for that property

required
Source code in prims/prim_base.py
def set_property(self, prop, val):
    """
    Sets property @prop with value @val

    Args:
        prop (str): Name of the property to set. See Raw USD Properties in the GUI for examples of property names
        val (any): Value to set for the property. Should be valid for that property
    """
    self._prim.GetProperty(prop).Set(val)