Asset Transformer API#
This page covers programmatic usage of the Asset Transformer, including API classes, custom rule development, and integration patterns.
For UI-based usage, refer to Asset Transformer. For available rules, review Asset Transformer Rules Reference.
Rule Interface#
All transformation rules implement the RuleInterface abstract base class. This interface defines the contract for rule implementations:
from abc import ABC, abstractmethod
from typing import Any
from pxr import Usd
class RuleInterface(ABC):
def __init__(
self,
source_stage: Usd.Stage,
package_root: str,
destination_path: str,
args: dict[str, Any],
) -> None: ...
@abstractmethod
def process_rule(self) -> str | None:
"""Execute the rule logic. Return a stage path to switch stages, or None."""
...
@abstractmethod
def get_configuration_parameters(self) -> list:
"""Return the configuration parameters for this rule."""
...
def log_operation(self, message: str) -> None:
"""Append a message to the operation log."""
...
def add_affected_stage(self, stage_identifier: str) -> None:
"""Record an identifier for a stage affected by this rule."""
...
Key Methods:
Method |
Description |
|---|---|
|
Execute the rule logic. Return |
|
Return a list of |
|
Record human-readable log messages for the execution report. |
|
Record identifiers for stages or layers modified by the rule. |
Rule Logging#
Every rule implementation must provide adequate logging through the log_operation() method. This creates a detailed audit trail of transformations:
def process_rule(self) -> str | None:
self.log_operation("SchemaRoutingRule start destination=payloads/physics.usda")
self.log_operation("Schema patterns: Physics*, Physx*")
# ... processing ...
self.log_operation("Moved 5 schema(s) from /World/Robot: PhysicsRigidBodyAPI, PhysicsMassAPI, ...")
self.log_operation("Processed 12 prim(s), moved 24 schema instance(s)")
self.log_operation("SchemaRoutingRule completed")
Logging Best Practices:
Log the rule start with key configuration parameters
Log pattern matches and filter criteria
Log each significant operation (schema moves, property copies, prim transfers)
Log summary statistics (counts of processed items)
Log affected stages using
add_affected_stage()Log completion status
Rule Registration#
The RuleRegistry is a singleton class that maintains a mapping of rule type names to their implementation classes. When the AssetTransformerManager executes a profile, it looks up each rule’s type string in the registry to find the corresponding implementation class.
The RuleRegistry uses a singleton pattern, meaning there is only one global instance shared across all code. This allows rules registered by any extension or module to be available to all transformation profiles.
Registry Methods:
Method |
Description |
|---|---|
|
Register a rule class. The key is computed as |
|
Look up a rule class by its fully qualified type name. Returns |
|
Return a dictionary mapping all registered type names to their implementation classes. |
|
Return a sorted list of all registered rule type names. |
|
Remove all registered rules. Primarily used for testing. |
Creating Custom Rules#
To create a custom transformation rule, implement the RuleInterface abstract base class and register it with the RuleRegistry.
Complete Custom Rule Example
from isaacsim.asset.transformer import RuleConfigurationParam, RuleInterface, RuleRegistry
from pxr import Usd
class MyCustomRule(RuleInterface):
"""A custom transformation rule."""
def get_configuration_parameters(self) -> list:
return [
RuleConfigurationParam(
name="my_param",
display_name="My Parameter",
param_type=str,
description="Description of the parameter",
default_value="default_value",
),
RuleConfigurationParam(
name="scope",
display_name="Scope",
param_type=str,
description="Root prim path to process",
default_value="/",
),
]
def process_rule(self) -> str | None:
params = self.args.get("params", {}) or {}
my_param = params.get("my_param", "default_value")
scope = params.get("scope", "/")
self.log_operation(f"MyCustomRule start my_param={my_param} scope={scope}")
stage = self.source_stage
scope_prim = stage.GetPrimAtPath(scope)
if not scope_prim.IsValid():
self.log_operation(f"Scope prim not found: {scope}")
return None
processed_count = 0
for prim in Usd.PrimRange(scope_prim):
processed_count += 1
self.log_operation(f"Processed {processed_count} prim(s)")
self.log_operation("MyCustomRule completed")
self.add_affected_stage("my_output.usda")
return None
registry = RuleRegistry()
registry.register(MyCustomRule)
Referencing a Custom Rule in a Profile:
The rule is registered using its fully qualified class name ({module}.{class_name}), which becomes the type string in rule specifications:
from isaacsim.asset.transformer import RuleSpec
# type = fully qualified class name used when registering the rule
rule_spec = RuleSpec(
name="My Custom Transformation",
type="my_extension.rules.MyCustomRule",
destination="payloads",
params={"my_param": "custom_value", "scope": "/World/Robot"},
enabled=True,
)
Extension-Based Registration#
For Isaac Sim extensions, register rules when the extension loads:
import omni.ext
from isaacsim.asset.transformer import RuleRegistry
from .rules import AnotherRule, MyCustomRule
class MyExtension(omni.ext.IExt):
def on_startup(self, ext_id):
registry = RuleRegistry()
registry.register(MyCustomRule)
registry.register(AnotherRule)
def on_shutdown(self):
pass
Programmatic API Usage#
The Asset Transformer can be invoked programmatically using the Python API. This enables integration into automated pipelines, batch processing, and custom tooling.
Basic Usage#
from isaacsim.asset.transformer import (
AssetTransformerManager,
RuleProfile,
RuleSpec,
)
# input_stage_path = "/path/to/robot.usd"
# package_root = "/output/robot_package"
profile = RuleProfile(
profile_name="My Transform Profile",
version="1.0",
rules=[
RuleSpec(
name="Route Physics Schemas",
type="isaacsim.asset.transformer.rules.core.schemas.SchemaRoutingRule",
destination="payloads/Physics",
params={
"schemas": ["Physics*", "Physx*"],
"stage_name": "physics.usda",
},
enabled=True,
),
RuleSpec(
name="Route Materials",
type="isaacsim.asset.transformer.rules.perf.materials.MaterialsRoutingRule",
destination="payloads",
params={
"materials_layer": "materials.usda",
"deduplicate": True,
},
enabled=True,
),
],
)
manager = AssetTransformerManager()
report = manager.run(
input_stage_path=input_stage_path,
profile=profile,
package_root=package_root,
)
print(f"Transform completed: {report.output_stage_path}")
for result in report.results:
status = "SUCCESS" if result.success else "FAILED"
print(f" {result.rule.name}: {status}")
if result.error:
print(f" Error: {result.error}")
Loading a Profile from JSON#
import json
from isaacsim.asset.transformer import AssetTransformerManager, RuleProfile
# profile_path = "/path/to/profile.json"
# input_stage_path = "/path/to/robot.usd"
# package_root = "/output/robot_package"
with open(profile_path, "r") as f:
profile_data = json.load(f)
profile = RuleProfile.from_dict(profile_data)
manager = AssetTransformerManager()
report = manager.run(
input_stage_path=input_stage_path,
profile=profile,
package_root=package_root,
)
Saving the Execution Report#
import json
# report = manager.run(input_stage_path, profile, package_root)
report_path = f"{report.package_root}/transform_report.json"
with open(report_path, "w") as f:
json.dump(report.to_dict(), f, indent=2)
Accessing Rule Logs#
# Iterate through rule results
for result in report.results:
print(f"\n=== {result.rule.name} ===")
print(f"Type: {result.rule.type}")
print(f"Success: {result.success}")
print(f"Duration: {result.started_at} to {result.finished_at}")
print(f"Affected stages: {result.affected_stages}")
print("Log:")
for entry in result.log:
print(f" {entry['message']}")
Querying Registered Rules#
from isaacsim.asset.transformer import RuleRegistry
registry = RuleRegistry()
rule_types = registry.list_rule_types()
for rule_type in rule_types:
print(rule_type)
rule_cls = registry.get("isaacsim.asset.transformer.rules.core.schemas.SchemaRoutingRule")
if rule_cls:
temp_rule = rule_cls.__new__(rule_cls)
temp_rule._log = []
params = temp_rule.get_configuration_parameters()
for param in params:
print(f" {param.name}: {param.param_type.__name__} = {param.default_value}")
API Classes Reference#
Class |
Description |
|---|---|
|
Coordinates execution of rule profiles over USD stages. Call |
|
Defines a complete transformation pipeline with profile metadata and ordered rule specifications. |
|
Specification for a single rule including name, type, destination, parameters, and enabled state. |
|
Contains the results of a transformation run including per-rule logs, timestamps, and the output stage path. |
|
Result of executing a single rule including success status, log entries, affected stages, and error information. |
|
Singleton registry mapping rule type names to implementation classes. Rules are registered automatically when their extensions load. |
|
Abstract base class for all transformation rules. Implement this to create custom rules. |
|
Describes a configurable parameter for a rule, including name, type, default value, and description. |
Error Handling#
from isaacsim.asset.transformer import AssetTransformerManager, RuleProfile
# input_stage_path, profile, package_root from your context
manager = AssetTransformerManager()
try:
report = manager.run(input_stage_path, profile, package_root)
except RuntimeError as e:
print(f"Transformation failed to start: {e}")
raise
for result in report.results:
if not result.success:
print(f"Rule '{result.rule.name}' failed: {result.error}")
Common Errors:
Error |
Cause |
|---|---|
|
The input USD file does not exist or is corrupted |
|
Cannot write to the output directory (permissions, disk full) |
|
Attempting to register a class that does not inherit from |
Rule |
Exception raised during |