> This page is for version Release 2.3.
> For other versions, use one of these documentation indexes:
> - Release 3.0 (default): https://docs.nvidia.com/isaaclab/3.0/llms.txt
> - Release 2.3: https://docs.nvidia.com/isaaclab/2.3/llms.txt
> - Release 2.2: https://docs.nvidia.com/isaaclab/2.2/llms.txt
> - Release 2.1: https://docs.nvidia.com/isaaclab/2.1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/isaaclab/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/isaaclab/_mcp/server.

# Writing an Asset Configuration

This guide walks through the process of creating an `~assets.ArticulationCfg`.
The `~assets.ArticulationCfg` is a configuration object that defines the
properties of an `~assets.Articulation` in Isaac Lab.

> **Note**
>
> While we only cover the creation of an `~assets.ArticulationCfg` in this guide,
> the process is similar for creating any other asset configuration object.

We will use the Cartpole example to demonstrate how to create an `~assets.ArticulationCfg`.
The Cartpole is a simple robot that consists of a cart with a pole attached to it. The cart
is free to move along a rail, and the pole is free to rotate about the cart. The file for this configuration example is
`source/isaaclab_assets/isaaclab_assets/robots/cartpole.py`.

```python
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

"""Configuration for a simple Cartpole robot."""

import isaaclab.sim as sim_utils
from isaaclab.actuators import ImplicitActuatorCfg
from isaaclab.assets import ArticulationCfg
from isaaclab.utils.assets import ISAACLAB_NUCLEUS_DIR

##
# Configuration
##

CARTPOLE_CFG = ArticulationCfg(
    spawn=sim_utils.UsdFileCfg(
        usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/Classic/Cartpole/cartpole.usd",
        rigid_props=sim_utils.RigidBodyPropertiesCfg(
            rigid_body_enabled=True,
            max_linear_velocity=1000.0,
            max_angular_velocity=1000.0,
            max_depenetration_velocity=100.0,
            enable_gyroscopic_forces=True,
        ),
        articulation_props=sim_utils.ArticulationRootPropertiesCfg(
            enabled_self_collisions=False,
            solver_position_iteration_count=4,
            solver_velocity_iteration_count=0,
            sleep_threshold=0.005,
            stabilization_threshold=0.001,
        ),
    ),
    init_state=ArticulationCfg.InitialStateCfg(
        pos=(0.0, 0.0, 2.0), joint_pos={"slider_to_cart": 0.0, "cart_to_pole": 0.0}
    ),
    actuators={
        "cart_actuator": ImplicitActuatorCfg(
            joint_names_expr=["slider_to_cart"],
            effort_limit_sim=400.0,
            stiffness=0.0,
            damping=10.0,
        ),
        "pole_actuator": ImplicitActuatorCfg(
            joint_names_expr=["cart_to_pole"], effort_limit_sim=400.0, stiffness=0.0, damping=0.0
        ),
    },
)
"""Configuration for a simple Cartpole robot."""
```

## Defining the spawn configuration

As explained in [Spawning prims into the scene](/source/tutorials/00_sim/spawn_prims) tutorials, the spawn configuration defines
the properties of the assets to be spawned. This spawning may happen procedurally, or
through an existing asset file (e.g. USD or URDF). In this example, we will spawn the
Cartpole from a USD file.

When spawning an asset from a USD file, we define its `~sim.spawners.from_files.UsdFileCfg`.
This configuration object takes in the following parameters:

* `~sim.spawners.from_files.UsdFileCfg.usd_path`: The USD file path to spawn from
* `~sim.spawners.from_files.UsdFileCfg.rigid_props`: The properties of the articulation's root
* `~sim.spawners.from_files.UsdFileCfg.articulation_props`: The properties of all the articulation's links

The last two parameters are optional. If not specified, they are kept at their default values in the USD file.

```python
spawn=sim_utils.UsdFileCfg(
    usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/Classic/Cartpole/cartpole.usd",
    rigid_props=sim_utils.RigidBodyPropertiesCfg(
        rigid_body_enabled=True,
        max_linear_velocity=1000.0,
        max_angular_velocity=1000.0,
        max_depenetration_velocity=100.0,
        enable_gyroscopic_forces=True,
    ),
    articulation_props=sim_utils.ArticulationRootPropertiesCfg(
        enabled_self_collisions=False,
        solver_position_iteration_count=4,
        solver_velocity_iteration_count=0,
        sleep_threshold=0.005,
        stabilization_threshold=0.001,
    ),
),
```

To import articulation from a URDF file instead of a USD file, you can replace the
`~sim.spawners.from_files.UsdFileCfg` with a `~sim.spawners.from_files.UrdfFileCfg`.
For more details, please check the API documentation.

## Defining the initial state

Every asset requires defining their initial or *default* state in the simulation through its configuration.
This configuration is stored into the asset's default state buffers that can be accessed when the asset's
state needs to be reset.

> **Note**
>
> The initial state of an asset is defined w\.r.t. its local environment frame. This then needs to
> be transformed into the global simulation frame when resetting the asset's state. For more
> details, please check the [Interacting with an articulation](/source/tutorials/01_assets/run_articulation) tutorial.

For an articulation, the `~assets.ArticulationCfg.InitialStateCfg` object defines the
initial state of the root of the articulation and the initial state of all its joints. In this
example, we will spawn the Cartpole at the origin of the XY plane at a Z height of 2.0 meters.
Meanwhile, the joint positions and velocities are set to 0.0.

```python
init_state=ArticulationCfg.InitialStateCfg(
    pos=(0.0, 0.0, 2.0), joint_pos={"slider_to_cart": 0.0, "cart_to_pole": 0.0}
),
```

## Defining the actuator configuration

Actuators are a crucial component of an articulation. Through this configuration, it is possible
to define the type of actuator model to use. We can use the internal actuator model provided by
the physics engine (i.e. the implicit actuator model), or use a custom actuator model which is
governed by a user-defined system of equations (i.e. the explicit actuator model).
For more details on actuators, see [Actuators](/source/overview/core-concepts/actuators).

The cartpole's articulation has two actuators, one corresponding to its each joint:
`cart_to_pole` and `slider_to_cart`. We use two different actuator models for these actuators as
an example. However, since they are both using the same actuator model, it is possible
to combine them into a single actuator model.

```python
actuators={
    "cart_actuator": ImplicitActuatorCfg(
        joint_names_expr=["slider_to_cart"],
        effort_limit_sim=400.0,
        stiffness=0.0,
        damping=10.0,
    ),
    "pole_actuator": ImplicitActuatorCfg(
        joint_names_expr=["cart_to_pole"], effort_limit_sim=400.0, stiffness=0.0, damping=0.0
    ),
},
```

```python
actuators={
   "all_joints": ImplicitActuatorCfg(
      joint_names_expr=[".*"],
      effort_limit=400.0,
      velocity_limit=100.0,
      stiffness={"slider_to_cart": 0.0, "cart_to_pole": 0.0},
      damping={"slider_to_cart": 10.0, "cart_to_pole": 0.0},
   ),
},
```

## ActuatorCfg velocity/effort limits considerations

In IsaacLab v1.4.0, the plain `velocity_limit` and `effort_limit` attributes were **not** consistently
pushed into the physics solver:

* **Implicit actuators**
  * velocity_limit was ignored (never set in simulation)
  * effort_limit was set into simulation

* **Explicit actuators**
  * both velocity_limit and effort_limit were used only by the drive model, not by the solver

In v2.0.1 we accidentally changed this: all velocity_limit & effort_limit, implicit or
explicit, were being applied to the solver. That caused many training under the old default uncaped solver
limits to break.

To restore the original behavior while still giving users full control over solver limits, we introduced two new flags:

* **velocity_limit_sim**
  Sets the physics-solver's maximum joint-velocity cap in simulation.

* **effort_limit_sim**
  Sets the physics-solver's maximum joint-effort cap in simulation.

These explicitly set the solver's joint-velocity and joint-effort caps at simulation level.

On the other hand, velocity_limit and effort_limit model the motor's hardware-level constraints in torque
computation for all explicit actuators rather than limiting simulation-level constraint.
For implicit actuators, since they do not model motor hardware limitations, `velocity_limit` were removed in v2.1.1
and marked as deprecated. This preserves same behavior as they did in v1.4.0. Eventually, `velocity_limit` and
`effort_limit` will be deprecated for implicit actuators, preserving only `velocity_limit_sim` and
`effort_limit_sim`

* * **Attribute**
  * **Implicit Actuator**
  * **Explicit Actuator**
* * `velocity_limit`
  * Deprecated (alias for `velocity_limit_sim`)
  * Used by the model (e.g. DC motor), not set into simulation
* * `effort_limit`
  * Deprecated (alias for `effort_limit_sim`)
  * Used by the model, not set into simulation
* * `velocity_limit_sim`
  * Set into simulation
  * Set into simulation
* * `effort_limit_sim`
  * Set into simulation
  * Set into simulation

Users who want to tune the underlying physics-solver limits should set the `_sim` flags.

## USD vs. ActuatorCfg discrepancy resolution

USD having default value and the fact that ActuatorCfg can be specified with None, or a overriding value can sometime be
confusing what exactly gets written into simulation. The resolution follows these simple rules,per joint and per
property:

| **Condition**        | **ActuatorCfg Value** | **Applied**         |
| -------------------- | --------------------- | ------------------- |
| No override provided | Not Specified         | USD Value           |
| Override provided    | User's ActuatorCfg    | Same as ActuatorCfg |

Digging into USD can sometime be unconvinent, to help clarify what exact value is written, we designed a flag
`isaaclab.assets.ArticulationCfg.actuator_value_resolution_debug_print`,
to help user figure out what exact value gets used in simulation.

Whenever an actuator parameter is overridden in the user's ActuatorCfg (or left unspecified),
we compare it to the value read from the USD definition and record any differences.  For each joint and each property,
if unmatching value is found, we log the resolution:

1. **USD Value**
   The default limit or gain parsed from the USD asset.

2. **ActuatorCfg Value**
   The user-provided override (or “Not Specified” if none was given).

3. **Applied**
   The final value actually used for simulation: if the user didn't override it, this matches the USD value;
   otherwise it reflects the user's setting.

This resolution info is emitted as a warning table only when discrepancies exist.
Here's an example of what you'll see:

| Group                                                                | Property                                                                                                                                                                     | Name                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | ID                                                                            | USD Value                                                                                                                                                                                                                                                                                                                                                      | ActuatorCfg Value                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | Applied                                                                                                                                                                                                                                                                                                                                                        |
| -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| panda_shoulder                panda_forearm               panda_hand | velocity_limit_sim    stiffness    damping    armature    velocity_limit_sim   stiffness   damping   armature   friction   velocity_limit_sim  stiffness  armature  friction | panda_joint1 panda_joint2 panda_joint3 panda_joint4 panda_joint1 panda_joint2 panda_joint3 panda_joint4 panda_joint1 panda_joint2 panda_joint3 panda_joint4 panda_joint1 panda_joint2 panda_joint3 panda_joint4 panda_joint5 panda_joint6 panda_joint7 panda_joint5 panda_joint6 panda_joint7 panda_joint5 panda_joint6 panda_joint7 panda_joint5 panda_joint6 panda_joint7 panda_joint5 panda_joint6 panda_joint7 panda_finger_joint1 panda_finger_joint2 panda_finger_joint1 panda_finger_joint2 panda_finger_joint1 panda_finger_joint2 panda_finger_joint1 panda_finger_joint2 | 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 4 5 6 4 5 6 4 5 6 4 5 6 4 5 6 7 8 7 8 7 8 7 8 | 2.17e+00 2.17e+00 2.17e+00 2.17e+00 2.29e+04 2.29e+04 2.29e+04 2.29e+04 4.58e+03 4.58e+03 4.58e+03 4.58e+03 0.00e+00 0.00e+00 0.00e+00 0.00e+00 2.61e+00 2.61e+00 2.61e+00 2.29e+04 2.29e+04 2.29e+04 4.58e+03 4.58e+03 4.58e+03 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.00e+00 2.00e-01 2.00e-01 1.00e+06 1.00e+06 0.00e+00 0.00e+00 0.00e+00 0.00e+00 | Not Specified Not Specified Not Specified Not Specified 8.00e+01 8.00e+01 8.00e+01 8.00e+01 4.00e+00 4.00e+00 4.00e+00 4.00e+00 Not Specified Not Specified Not Specified Not Specified Not Specified Not Specified Not Specified 8.00e+01 8.00e+01 8.00e+01 4.00e+00 4.00e+00 4.00e+00 Not Specified Not Specified Not Specified Not Specified Not Specified Not Specified Not Specified Not Specified 2.00e+03 2.00e+03 Not Specified Not Specified Not Specified Not Specified | 2.17e+00 2.17e+00 2.17e+00 2.17e+00 8.00e+01 8.00e+01 8.00e+01 8.00e+01 4.00e+00 4.00e+00 4.00e+00 4.00e+00 0.00e+00 0.00e+00 0.00e+00 0.00e+00 2.61e+00 2.61e+00 2.61e+00 8.00e+01 8.00e+01 8.00e+01 4.00e+00 4.00e+00 4.00e+00 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.00e+00 2.00e-01 2.00e-01 2.00e+03 2.00e+03 0.00e+00 0.00e+00 0.00e+00 0.00e+00 |

To keep the cleaniness of logging, `isaaclab.assets.ArticulationCfg.actuator_value_resolution_debug_print`
default to False, remember to turn it on when wishes.