[isaacsim.asset.transformer] Isaac Sim Asset Transformer#

Version: 6.2.1

Overview#

The isaacsim.asset.transformer extension provides the core framework for transforming USD assets through configurable rule pipelines. It defines the rule interface, profile model, rule registry, and execution manager that orchestrate ordered sequences of transformation rules over USD stages.

Key Components#

RuleInterface#

Abstract base class that all transformation rules must subclass. A rule receives a source Usd.Stage, a package root directory, a destination path, and a parameter dictionary. Subclasses implement process_rule() to read from the source stage, write opinions to destination layers, and optionally return a new stage path for subsequent rules in the pipeline.

RuleRegistry#

A singleton registry that maps fully qualified rule class names to their implementation classes. Rules register themselves on extension startup (typically in isaacsim.asset.transformer.rules) and are resolved by the manager at execution time.

AssetTransformerManager#

Coordinates the execution of a RuleProfile against a USD stage. The manager:

  1. Opens the input stage and creates a base layer in the output package, flattened when flatten_source is enabled

  2. Collects external asset dependencies into the package directory

  3. Canonicalizes orientation quaternions for deterministic output

  4. Iterates through enabled rules in profile order, instantiating each rule class and calling process_rule()

  5. Supports mid-pipeline stage replacement when a rule returns a new stage path

  6. Produces an ExecutionReport with per-rule logs, affected stages, and success/error status

Data Models#

  • RuleSpec — Specification for a single rule: type, display name, destination path, parameters, and enabled flag

  • RuleProfile — Ordered collection of RuleSpec entries plus global settings (output root, base name, flatten option)

  • RuleConfigurationParam — Descriptor for a rule’s configurable parameter (name, type, default, description)

  • ExecutionReport / RuleExecutionResult — Structured output from a profile run, including timing, logs, and error details

Usage#

from isaacsim.asset.transformer import AssetTransformerManager, RuleProfile

manager = AssetTransformerManager()
profile = RuleProfile.from_json("path/to/profile.json")
report = manager.run("input.usd", profile, package_root="/tmp/output")

for result in report.results:
    print(f"{result.rule.name}: {'OK' if result.success else result.error}")

Enable Extension#

The extension can be enabled (if not already) in one of the following ways:

Define the next entry as an application argument from a terminal.

APP_SCRIPT.(sh|bat) --enable isaacsim.asset.transformer

Define the next entry under [dependencies] in an experience (.kit) file or an extension configuration (extension.toml) file.

[dependencies]
"isaacsim.asset.transformer" = {}

Open the Window > Extensions menu in a running application instance and search for isaacsim.asset.transformer. Then, toggle the enable control button if it is not already active.

Python API#

models

RuleConfigurationParam

Descriptor for a single rule configuration parameter.

RuleSpec

Specification for a single rule in a profile.

RuleProfile

Collection of rules and metadata for a transformation run.

RuleExecutionResult

Outcome of running a single rule.

ExecutionReport

Report for a full transformation run.

rule_interface

RuleInterface

Abstract base class for asset transformation rules.

manager

RuleRegistry

AssetTransformerManager

Coordinates execution of a RuleProfile over USD stages.


Models#

class RuleConfigurationParam(
name: str,
display_name: str,
param_type: type,
description: str | None = None,
default_value: object | None = None,
)#

Bases: object

Descriptor for a single rule configuration parameter.

Parameters:
  • name – Unique parameter name.

  • display_name – Human-readable label.

  • param_type – Expected Python type for the parameter.

  • description – Optional description of the parameter.

  • default_value – Default value for the parameter.

default_value: object | None = None#

Default value for the parameter.

description: str | None = None#

Optional description of the parameter.

display_name: str#
name: str#
param_type: type#
class RuleSpec(
name: str,
type: str,
destination: str | None = None,
params: dict[str,
~typing.Any] = <factory>,
enabled: bool = True,
)#

Bases: object

Specification for a single rule in a profile.

Parameters:
  • name – Rule display name.

  • type – Fully qualified rule class path.

  • destination – Optional output path override.

  • params – Rule parameter overrides.

  • enabled – Whether the rule is active.

static from_dict(
data: dict[str, Any],
) → RuleSpec#

Create a RuleSpec from a dictionary.

Parameters:

data – Mapping with rule fields.

Returns:

Parsed RuleSpec instance.

Raises:

ValueError – If required fields are missing.

Example:

spec = RuleSpec.from_dict(
    {"name": "MoveMeshes", "type": "my.rule.Class", "params": {"scope": "/World"}}
)
to_dict() → dict[str, Any]#

Convert this specification to a plain dictionary.

Returns:

Dictionary suitable for JSON serialization.

Example:

>>> spec = RuleSpec(
...     name="MoveMeshes",
...     type="isaacsim.asset.transformer.rules.perf.geometries.GeometriesRoutingRule",
...     params={"scope": "/World"},
... )
>>> isinstance(spec.to_dict(), dict)
True
destination: str | None = None#

Optional output path override.

enabled: bool = True#

Whether the rule is active.

name: str#
params: dict[str, Any]#
type: str#
class RuleProfile(
profile_name: str,
version: str | None = None,
rules: list[~isaacsim.asset.transformer.models.RuleSpec] = <factory>,
interface_asset_name: str | None = None,
output_package_root: str | None = None,
flatten_source: bool = False,
base_name: str | None = None,
)#

Bases: object

Collection of rules and metadata for a transformation run.

Parameters:
  • profile_name – Display name for the profile.

  • version – Optional profile version string.

  • rules – Rule specifications to execute.

  • interface_asset_name – Optional interface asset identifier.

  • output_package_root – Optional output root for packages.

  • flatten_source – Whether to flatten source stages before rules.

  • base_name – Optional base name for generated outputs.

static from_dict(
data: dict[str, Any],
) → RuleProfile#

Parse a RuleProfile from a dictionary.

Parameters:

data – Mapping with profile fields.

Returns:

Parsed RuleProfile instance.

Raises:

ValueError – If required fields are missing.

Example:

profile = RuleProfile.from_dict({"profile_name": "Default", "rules": []})
static from_json(
json_str: str,
) → RuleProfile#

Parse a RuleProfile from a JSON string.

Parameters:

json_str – JSON payload encoding a profile.

Returns:

Parsed RuleProfile instance.

Example:

profile = RuleProfile.from_json('{"profile_name":"Default","rules":[]}')
to_dict() → dict[str, Any]#

Serialize profile to a dictionary.

Returns:

Dictionary suitable for JSON serialization.

Example:

payload = profile.to_dict()
to_json() → str#

Serialize profile to a deterministic JSON string.

Returns:

JSON string with sorted keys and no trailing spaces.

Example:

json_str = profile.to_json()
base_name: str | None = None#

Optional base name for generated outputs.

flatten_source: bool = False#

Whether to flatten source stages before rules.

interface_asset_name: str | None = None#

Optional interface asset identifier.

output_package_root: str | None = None#

Optional output root for packages.

profile_name: str#
rules: list[RuleSpec]#
version: str | None = None#

Optional profile version string.

class RuleExecutionResult(
rule: ~isaacsim.asset.transformer.models.RuleSpec,
success: bool,
log: list[dict[str,
~typing.Any]] = <factory>,
affected_stages: list[str] = <factory>,
error: str | None = None,
started_at: str = <factory>,
finished_at: str | None = None,
)#

Bases: object

Outcome of running a single rule.

Parameters:
  • rule – Rule specification that was executed.

  • success – Whether the rule completed successfully.

  • log – Log entries recorded during execution.

  • affected_stages – Identifiers of affected stages.

  • error – Error message if the rule failed.

  • started_at – Start timestamp in ISO format.

  • finished_at – Finish timestamp in ISO format.

close() → None#

Mark the result as finished by setting the finished_at timestamp.

Example:

result.close()
affected_stages: list[str]#
error: str | None = None#

Error message if the rule failed.

finished_at: str | None = None#

Finish timestamp in ISO format.

log: list[dict[str, Any]]#
rule: RuleSpec#
started_at: str#
success: bool#
class ExecutionReport(
profile: ~isaacsim.asset.transformer.models.RuleProfile,
input_stage_path: str,
package_root: str,
started_at: str = <factory>,
finished_at: str | None = None,
results: list[~isaacsim.asset.transformer.models.RuleExecutionResult] = <factory>,
output_stage_path: str | None = None,
composition_errors: list[str] = <factory>,
composition_errors_truncated: bool = False,
)#

Bases: object

Report for a full transformation run.

Parameters:
  • profile – Profile used for the run.

  • input_stage_path – Path to the input stage.

  • package_root – Package output root path.

  • started_at – Start timestamp in ISO format.

  • finished_at – Finish timestamp in ISO format.

  • results – Rule execution results.

  • output_stage_path – File path of the final working stage after all rules have executed. Callers can use this to load the transformed asset.

  • composition_errors – Unresolved composition arcs on the final output stage. Non-empty means the output is missing content that the source stage composed, even when every rule succeeded.

  • composition_errors_truncated – True when the search for the above was cut short, so composition_errors is a lower bound rather than the complete set. An empty composition_errors alongside this flag means “not checked”, not “clean”.

close() → None#

Mark the report as finished by setting the finished_at timestamp.

Example:

report.close()
to_dict() → dict[str, Any]#

Serialize the report to a dictionary suitable for JSON.

Returns:

Dictionary with execution details.

Example:

payload = report.to_dict()
to_json() → str#

Serialize the report to a deterministic JSON string.

Returns:

JSON string with sorted keys and compact separators.

Example:

json_str = report.to_json()
composition_errors: list[str]#

Unresolved composition arcs on the final output stage. Non-empty means the output is missing composed content.

composition_errors_truncated: bool = False#

True when the composition-error search was cut short, making composition_errors a lower bound.

finished_at: str | None = None#

Finish timestamp in ISO format.

input_stage_path: str#
output_stage_path: str | None = None#

File path of the final working stage after all rules have executed.

Callers can use this path to load the transformed asset.

package_root: str#
profile: RuleProfile#
results: list[RuleExecutionResult]#
started_at: str#

Rule Interface#

class RuleInterface(
source_stage: pxr.Usd.Stage,
package_root: str,
destination_path: str,
args: dict[str, Any],
)#

Bases: ABC

Abstract base class for asset transformation rules.

Implementations operate on a source pxr.Usd.Stage and may write opinions to a destination pxr.Usd.Stage. Subclasses should record human-readable log messages and any identifiers for stages or layers they affect so the manager can produce comprehensive reports.

Rules may request a stage replacement by returning a stage identifier (file path) from process_rule(). The manager will open the new stage and use it for subsequent rules in the pipeline.

Stage mutation contract:

args["input_stage"] is informational only and must be treated as read-only in every respect, including its session layer. Rules that need to author overrides while reading from the original input must open a private Usd.Stage from args["input_stage_path"] and author into that stage’s session layer; they must not write to either layer of any caller-owned Stage.

Two reasons for this:

  1. args["input_stage"] may be a caller-owned Stage (e.g. the editor’s active Stage). Its session layer commonly carries user-driven overrides such as visibility toggles, purpose settings, and camera opinions; rule authoring or cleanup there would corrupt user state.

  2. The root pxr.Sdf.Layer of an input opened by path is shared via USD’s process-wide layer cache with every Stage observing the same file – including the editor’s active Stage when the user runs the transformer on the open stage. Authoring to that root layer (or calling Reload() on it) fires change notifications on the editor’s Stage that have been observed to invalidate Hydra render product prims mid-frame and crash the renderer.

Parameters:
  • source_stage – Input stage providing opinions to read from.

  • package_root – Root directory for output files.

  • destination_path – Relative path for rule outputs.

  • args – Mapping of parameters including keys such as destination and params.

add_affected_stage(stage_identifier: str) → None#

Record an identifier for a stage or layer affected by this rule.

Parameters:

stage_identifier – Logical label, file path, or layer id that was created, modified, or otherwise affected by the rule.

Example:

rule.add_affected_stage("/tmp/output.usda")
get_affected_stages() → list[str]#

Return identifiers for stages or layers affected by this rule.

Returns:

List of unique identifiers provided via add_affected_stage().

Example:

affected = rule.get_affected_stages()
abstract get_configuration_parameters() → list[RuleConfigurationParam]#

Return the configuration parameters for this rule.

Returns:

List of configuration parameters.

Example:

params = rule.get_configuration_parameters()
get_operation_log() → list[str]#

Return the accumulated operation log messages.

Returns:

List of log message strings in chronological order.

Example:

messages = rule.get_operation_log()
get_pending_deletions() → list[str]#

Return paths the rule deferred to the manager for deletion.

Returns:

List of unique filesystem paths registered via request_deletion(), in registration order.

Example:

for path in rule.get_pending_deletions():
    ...
log_operation(message: str) → None#

Append a human-readable message to the operation log.

Parameters:

message – Message to record in the rule execution log.

Example:

rule.log_operation("Copied prim /World")
abstract process_rule() → str | None#

Execute the rule logic.

This method must be implemented by subclasses. Implementations should emit log messages via log_operation() and record any affected stage or layer identifiers via add_affected_stage().

Returns:

The file path of the stage to be used by subsequent rules. Return None if the current working stage should continue to be used. If a path is returned and differs from the current working stage, the manager will open the new stage for subsequent rules.

Example:

from pxr import Usd
from isaacsim.asset.transformer import RuleInterface

class NoOpRule(RuleInterface):
    def process_rule(self) -> None:
        self.log_operation("noop")

stage = Usd.Stage.CreateInMemory()
NoOpRule(stage, "/tmp", "", {"destination": "out.usda"}).process_rule()
request_deletion(path: str) → None#

Ask the manager to delete path once it releases the working stage.

A rule must use this instead of calling os.remove directly when the file it wants to delete backs the working stage. self.source_stage is the manager-owned working stage; the manager keeps it (and its root pxr.Sdf.Layer) open for the duration of the rule, so the rule cannot free the underlying file. On Windows an open USD layer is an OS-level file lock, so an in-rule os.remove fails with PermissionError: [WinError 5] Access is denied. The manager drains the requests returned by get_pending_deletions() only after it has dropped the working stage, guaranteeing the file handle is gone before the unlink.

The rule should drop its own references to the file (e.g. set self.source_stage = None) before returning so the manager holds the last handle.

Parameters:

path – Filesystem path the manager should delete after releasing the working stage. Duplicate and empty paths are ignored.

Example:

rule.request_deletion("/tmp/pkg/payloads/base.usd")

Manager#

RuleRegistry#

alias of getinstance

class AssetTransformerManager(registry: RuleRegistry | None = None)#

Bases: object

Coordinates execution of a RuleProfile over USD stages.

The manager writes a working copy of the input stage to {package_root}/payloads/{base_name} and runs every rule against it. External assets are copied to {package_root}/source_assets/ with paths rewritten to local references.

RuleProfile.flatten_source decides how composition is handled:

  • True flattens the stage first, baking every sublayer, reference and payload into the exported layer. The result is self-contained.

  • False exports the root layer and keeps its arcs as arcs. Their targets are not copied into the package, so the arcs are re-anchored to the source files they name. Composed content is preserved, but the output keeps referring to the original source tree; use True for a package that stands alone.

Unresolved arcs on the final stage are reported via ExecutionReport.composition_errors rather than passing silently. Each variant set is re-selected one option at a time while collecting them, so an arc broken inside an option nobody selected is still reported. That search is bounded; ExecutionReport.composition_errors_truncated records whether it ran to completion, so a sweep that gave up is never mistaken for a clean result.

Parameters:

registry – Optional registry instance. Currently ignored in favor of the global singleton registry.

run(
input_stage: str | Usd.Stage,
profile: RuleProfile,
package_root: str | None = None,
) → ExecutionReport#

Execute a rule profile against a USD stage and return an execution report.

Parameters:
  • input_stage – Path to the source USD stage or layer, or an already-opened pxr.Usd.Stage. When a stage object is passed it is used directly and its root layer path is used as the internal input_stage.

  • profile – Rule profile specifying ordered rules to run.

  • package_root – Destination root directory for outputs. Generate in an isolated directory and publish only generated files after successful execution, even for new or empty destinations. Unrelated files are preserved and cannot influence folder-based rule discovery.

Returns:

Execution report including per-rule logs and status. A conversion failure leaves the previous package intact and sets output_stage_path to None.

Raises:
  • KeyError – If a rule type is not registered.

  • RuntimeError – If stage loading or export fails.

Example:

manager = AssetTransformerManager()
report = manager.run("input.usd", profile, package_root="/tmp/package")
property registry: getinstance#

Return the singleton rule registry.

Returns:

The manager’s internal RuleRegistry instance.

Example:

registry = manager.registry