Physics Schemas
A robot model needs more than geometry to simulate. Its links need mass, its shapes need collision properties, and its joints need physical constraints. USD stores these properties in schemas: named groups of attributes attached to objects in the scene. An object in a USD scene is called a prim; a robot link, collision mesh, or joint can each be a prim.
Isaac Lab’s schema configurations let you set these properties from Python when an asset is spawned. Use them to tune an existing asset or give a new shape its physical properties, without editing the source USD file by hand. An imported asset may already contain everything you need; override only the properties you want to change.
These are asset settings. Choose the simulation backend and its scene-wide solver settings separately through backends_and_presets.
What is a fragment?
A schema fragment is a small Python configuration object that sets properties
from one USD schema or attribute namespace. For example, MassCfg(mass=0.5)
sets a mass property, while UsdPhysicsCollisionCfg(collision_enabled=True)
sets a collision property.
It is called a fragment because it describes just one part of an asset’s physics configuration. Combine fragments to describe the properties you need, then pass them to the appropriate spawner fields. A fragment is configuration data, not a separate USD file or a piece of geometry.
The distinction is:
- The schema defines the available properties and how they are stored in USD.
- The fragment supplies the values you want to set from Python.
- The spawner applies those values to the asset’s prims when it creates the asset.
Give an object physical properties
This configuration creates a small box with a mass of 0.5 kg and enabled collisions:
Pass this configuration to an asset’s spawn field, such as
RigidObjectCfg(spawn=cuboid, ...). The spawner creates the geometry and applies
the schema configurations; the physics backend then reads the resulting properties.
Each spawner field controls a different part of the asset:
For joints controlled by Isaac Lab actuators, also read actuators: actuator configuration can override drive settings after spawning.
A field set to None leaves the existing attribute unchanged. An empty fragment,
such as UsdPhysicsRigidBodyCfg(), still requests the corresponding schema; it
does not replace every attribute with a Python default.
Add backend-specific settings
A spawner field can accept a list of fragments for the same property family. Use a list to combine shared USD properties with settings for a particular backend:
Here, UsdPhysicsCollisionCfg enables collisions and NewtonCollisionCfg sets
a Newton contact margin of 1 mm. They describe the same collision shape, so they
belong together in collision_props.
Import shared fragments from isaaclab.sim.schemas, PhysX fragments from
isaaclab_physx.sim.schemas, and Newton or MuJoCo fragments from
isaaclab_newton.sim.schemas. Material fragments live in the corresponding
sim.spawners.materials modules.
You can store settings for several backends on one asset. This does not activate those backends or make their parameters interchangeable: a solver must support a property for it to affect the simulation. For example, MuJoCo gravity compensation settings apply to Newton’s MuJoCo solver, not to PhysX.
Configure an existing robot
UsdFileCfg accepts the same property fields. Pass a fragment or list directly
to update existing matching bodies, collisions, or joints throughout the imported
asset. Use a dictionary when different parts need different settings:
Dictionary keys are regular-expression suffixes appended to the spawn prim’s path.
For example, if the robot is spawned at /World/Robot, "/.*" searches beneath
/World/Robot. Rules apply in order, so a later rule can override an earlier one.
In this example, the hand subtree receives a smaller PhysX depenetration limit.
For USD, URDF, and MJCF imports, the anchor is the spawn prim. Shape and mesh spawners use the geometry prim for collisions and the container prim for rigid-body and mass properties. Deformable settings use the spawn prim for every spawner type.
The search includes inactive and undefined prims as well as instance proxies. Patterns select candidate prims; the property family then filters them. For example, rigid-body settings apply to rigid bodies, and joint-drive settings apply to revolute or prismatic joints. A broad pattern does not normally turn every mesh into a body.
When a setting does not apply
First check that the selected backend supports the property and that the pattern
matches the intended prim. Matching uses the whole path: .* can cross /
boundaries, while [^/]+ matches just one path segment.
Most fragment writers modify prims that already have the relevant USD API, meaning
the schema that identifies them as a body, collision shape, or other physics object.
For mass, articulation, and joint-drive settings, the spawner flags
mass_props_create_if_missing, articulation_props_create_if_missing, and
joint_drive_props_create_if_missing can create missing APIs on matched targets.
Keep patterns narrow when enabling API creation. A broad mass pattern can give each matching mesh its own mass, rather than setting one mass for the body.
Shape and mesh spawners create the APIs needed by their new geometry. With a bare fragment or list, file spawners search for existing schema carriers; if none exist for the family, they apply it at the spawn prim, treating the asset as a single body. Explicit dictionaries give you control over the target selection.
The writers warn when no valid targets are found or when a target is an instance proxy that cannot be edited. An empty fragment list makes no changes. Joint-drive patterns silently skip non-joint prims, since a subtree can contain both joints and meshes.
Gravity compensation with MuJoCo
Set body-level gravcomp to compute gravity compensation. Set joint-level
actuatorgravcomp to route that force through the actuator channel, where actuator
force limits apply; otherwise it goes through the passive-force channel.
gravcomp=1.0 provides full compensation. The joint fragment also enables full
compensation on its child body if that body’s value is unset or zero; an existing
nonzero value is kept. To disable compensation, turn off actuatorgravcomp as
well as setting the body’s gravcomp to zero.
The older MujocoJointDrivePropertiesCfg also auto-enables body compensation
when requested, unless an explicit body gravcomp value is supplied. Prefer the
fragment example above for new configurations.
Deformable bodies
Choose volume_deformable_props for a solid deformable or
surface_deformable_props for a cloth-like surface. Set only one of these fields
on a spawner. Both accept OmniPhysicsDeformableBodyCfg for shared properties such
as mass and kinematic behavior; PhysX also provides tuning fragments.
Unlike most rigid-body writers, deformable writers create the deformable setup if
it is missing. Set deformable mass with OmniPhysicsDeformableBodyCfg.mass;
UsdPhysics.MassAPI does not control it.
This example creates a volume deformable with PhysX tuning, a collision offset on its simulation mesh, and material settings for both PhysX and Newton:
The simulation mesh is a child named sim_mesh by default. Target it through
collision_props to set collision offsets. Deformable and simulation-mesh collision
patterns are relative to the spawn prim.
physics_material accepts deformable material fragments and lists that mix rigid
and deformable material settings. Each fragment applies its own material schema;
a material used only by deformables does not need the rigid-body material API.
Using the property configuration classes
You will also see classes such as RigidBodyBaseCfg and
PhysxRigidBodyPropertiesCfg in existing tasks. These combine a property group’s
shared and backend-specific fields in one object. They are deprecated compatibility
classes. Existing configurations still work in the same spawner fields, but use
fragments for new code. Pass a compatibility object directly, rather than placing
it in a fragment list.
- Base classes in
isaaclab.sim.schemascontain shared fields and do not import a backend package. - PhysX subclasses add fields such as damping and solver iterations.
- Newton subclasses add Newton settings; MuJoCo subclasses add solver-specific fields such as gravity compensation.
When updating an existing task, split its compatibility object into fragments for the shared and backend-specific fields. See the fragment migration examples for examples.
This example writes both PhysX and MuJoCo settings into the asset. Each backend uses the fields it supports. For a full list of classes and fields, expand the reference sections below.
Schema reference and implementation
The sections below explain how configuration fields become USD attributes. You do not need these details for the examples above.
Property configuration class hierarchy
For each property group (rigid body, joint drive, collision, articulation root,
material, mesh collision), Isaac Lab defines a single base class in core
isaaclab.sim.schemas and one subclass per backend in the corresponding
extension package:
NewtonMeshCollisionPropertiesCfg uses
multiple inheritance: it extends both
NewtonCollisionPropertiesCfg (for
contact_margin / contact_gap) and
MeshCollisionBaseCfg (for
mesh_approximation_name). Each inherited field is written to the namespace of its declaring class;
see field-to-namespace mapping.
NewtonSDFCollisionPropertiesCfg is
collision-rooted, so it authors NewtonSDFCollisionAPI without also applying
UsdPhysics.MeshCollisionAPI or setting physics:approximation.
Each spawner has one field per property group, such as rigid_props or
joint_drive_props. Each field accepts the base class or any of its subclasses.
Fragment writers and target families
Every fragment subclasses SchemaFragment and declares
which USD namespace its fields write to and which applied schema, if any, it owns. A
fragment’s func names the callable that
applies it to a prim; the default applier
(apply_namespaced) writes each non-None field as
<namespace>:<camelCase(field)> and leaves None fields untouched (partial
update). Irregular APIs override func — for example
UsdPhysicsDriveCfg dispatches through
apply_drive to handle the multi-instance
UsdPhysics.DriveAPI.
Fragments are grouped into families, one per spawner slot. Each family has a writer
that resolves target prims from an expression and dispatches every fragment via its
func. Backend fragments carry backend-specific appliers, so the core package never
imports a backend:
The tendon families are tune-not-apply: the tendon topology is authored in the source
asset, so their writers only tune existing instances and never create them. The deformable
families sit at the other end of that spectrum: see Deformable bodies.
PhysX tendon
fragments use instance_names to select one or more instances on each matching prim;
None (the default) broadcasts to all existing instances.
A fixed tendon is split at the same boundary as the PhysX schemas: the root fragment owns
whole-tendon dynamics and limits, while the axis fragment owns each joint’s contribution.
Prim-path matching chooses the joints and instance_names chooses the tendon on those
joints:
How the deformable setup is created
Creating the deformable setup on a matched prim without the anchor happens in three steps:
- Simulation mesh. A
sim_meshchild prim is authored under the target (the name is configurable via the writer’ssim_mesh_nameargument). For surface deformables this is a triangle-mesh copy of the visual mesh; for volume deformables it is a tetrahedralizedUsdGeom.TetMesh— reused in place, without re-tetrahedralizing, when the source asset already ships a pre-tetrahedralizedUsdGeom.TetMeshchild. - Backend anchor. The active physics backend applies its own anchor schemas through
PhysicsManager.setup_deformable_body: PhysX applies the realOmniPhysicsDeformableBodyAPIto the body prim (the same single schema for both deformable types) and the type-dependentOmniPhysicsVolumeDeformableSimAPI/OmniPhysicsSurfaceDeformableSimAPIto the simulation-mesh prim, while Newton applies its own (currently token-only)Physics*schemas. Core fragments own no applied schema of their own — OmniPhysicsDeformableBodyCfg only writes into theomniphysics:*namespace once the anchor exists. - Fragment dispatch. Every fragment in the matched slot is applied to the target, in list order, exactly like the other families.
How fields map to USD namespaces
Because each cfg field is routed to its declaring class’s namespace (not the instance’s class), a subclass instance can author attributes across multiple namespaces on the same prim. For example:
The writer applies each field to the namespace of the class where the field is
declared. The applied schemas (PhysxRigidBodyAPI for disable_gravity,
none for the Mjc raw attribute) are added only when the corresponding
fields are non-None.
Field names and compatibility aliases
Python fields use snake_case; USD attributes generally use camelCase
(for example, contact_margin becomes newton:contactMargin). Single-word
MuJoCo fields such as gravcomp keep their spelling.
JointDriveBaseCfg still accepts max_velocity as an alias for
max_joint_velocity and max_effort as an alias for max_force. Prefer the
new names: the aliases are scheduled for removal in 4.0. Using an old name emits a
deprecation warning and copies its value if the new field is unset. If both are
provided, the new field wins without a warning. The old dataclass fields are then
reset to None.
Where to go next
- /source/how-to/write_articulation_cfg — configure a complete robot asset.
- actuators — understand how actuators resolve joint drive properties.
- |
set_joint_velocity_target|actuators.target_command.set_velocity_index| — migrate older schema configurations to 3.0. - /source/api/lab/isaaclab.sim.schemas — shared configurations and writers.
- /source/api/lab_physx/isaaclab_physx.sim.schemas — PhysX configurations.
- /source/api/lab_newton/isaaclab_newton.sim.schemas — Newton and MuJoCo configurations.