Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion source/isaaclab/config/extension.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

# Note: Semantic Versioning is used: https://semver.org/
version = "4.2.1"
version = "4.4.0"

# Description
title = "Isaac Lab framework for Robot Learning"
Expand All @@ -16,6 +16,7 @@ requirements = [
"numpy",
"prettytable==3.3.0",
"toml",
"lazy_loader>=0.4",
"hidapi",
"gymnasium==0.29.0",
"trimesh",
Expand All @@ -26,6 +27,7 @@ modules = [
"numpy",
"prettytable",
"toml",
"lazy_loader",
"hid",
"gymnasium",
"trimesh",
Expand Down
30 changes: 30 additions & 0 deletions source/isaaclab/docs/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,36 @@
Changelog
---------

4.4.0 (2026-02-26)
~~~~~~~~~~~~~~~~~~

Changed
^^^^^^^

* Refined lazy-loading behavior for config-only import paths to keep environment
config construction backend-free. This includes stricter cascading namespace
resolution in :func:`~isaaclab.utils.module.attach_cascading`, avoiding eager
callable resolution during deepcopy of :class:`~isaaclab.utils.string.ResolvableString`,
and updating locomanipulation MDP exports/import boundaries so
``test_env_cfg_no_forbidden_imports.py`` passes without importing runtime modules.


4.3.0 (2026-02-26)
~~~~~~~~~~~~~~~~~~

Changed
^^^^^^^

* Added lazy callable-string resolution for config fields through
:class:`~isaaclab.utils.string.ResolvableString` in :mod:`isaaclab.utils.configclass`.
Config values such as ``class_type``/``func`` can now remain as strings until first
use and then resolve/cached automatically.

* Added ``{DIR}`` callable-string shorthand support in :mod:`isaaclab.utils.configclass`
for config defaults. ``"{DIR}.module:Symbol"`` now expands to the declaring config
module directory before resolution.


4.2.1 (2026-02-25)
~~~~~~~~~~~~~~~~~~

Expand Down
26 changes: 15 additions & 11 deletions source/isaaclab/isaaclab/actuators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,19 @@
and called by the :class:`isaaclab.assets.Articulation` class.
"""

from .actuator_base import ActuatorBase
from .actuator_base_cfg import ActuatorBaseCfg
from .actuator_net import ActuatorNetLSTM, ActuatorNetMLP
from .actuator_net_cfg import ActuatorNetLSTMCfg, ActuatorNetMLPCfg
from .actuator_pd import DCMotor, DelayedPDActuator, IdealPDActuator, ImplicitActuator, RemotizedPDActuator
from .actuator_pd_cfg import (
DCMotorCfg,
DelayedPDActuatorCfg,
IdealPDActuatorCfg,
ImplicitActuatorCfg,
RemotizedPDActuatorCfg,
from isaaclab.utils.lazy_imports import lazy_export

lazy_export(
("actuator_base", "ActuatorBase"),
("actuator_base_cfg", "ActuatorBaseCfg"),
("actuator_net", ["ActuatorNetLSTM", "ActuatorNetMLP"]),
("actuator_net_cfg", ["ActuatorNetLSTMCfg", "ActuatorNetMLPCfg"]),
("actuator_pd", ["DCMotor", "DelayedPDActuator", "IdealPDActuator", "ImplicitActuator", "RemotizedPDActuator"]),
("actuator_pd_cfg", [
"DCMotorCfg",
"DelayedPDActuatorCfg",
"IdealPDActuatorCfg",
"ImplicitActuatorCfg",
"RemotizedPDActuatorCfg",
]),
)
10 changes: 6 additions & 4 deletions source/isaaclab/isaaclab/actuators/actuator_net_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@

from collections.abc import Iterable
from dataclasses import MISSING
from typing import Literal
from typing import TYPE_CHECKING, Literal

from isaaclab.utils import configclass

from . import actuator_net
from .actuator_pd_cfg import DCMotorCfg

if TYPE_CHECKING:
from .actuator_net import ActuatorNetLSTM, ActuatorNetMLP


@configclass
class ActuatorNetLSTMCfg(DCMotorCfg):
"""Configuration for LSTM-based actuator model."""

class_type: type = actuator_net.ActuatorNetLSTM
class_type: type["ActuatorNetLSTM"] | str = "{DIR}.actuator_net:ActuatorNetLSTM"
# we don't use stiffness and damping for actuator net
stiffness = None
damping = None
Expand All @@ -30,7 +32,7 @@ class ActuatorNetLSTMCfg(DCMotorCfg):
class ActuatorNetMLPCfg(DCMotorCfg):
"""Configuration for MLP-based actuator model."""

class_type: type = actuator_net.ActuatorNetMLP
class_type: type["ActuatorNetMLP"] | str = "{DIR}.actuator_net:ActuatorNetMLP"
# we don't use stiffness and damping for actuator net

stiffness = None
Expand Down
15 changes: 9 additions & 6 deletions source/isaaclab/isaaclab/actuators/actuator_pd_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
# SPDX-License-Identifier: BSD-3-Clause

from dataclasses import MISSING
from typing import TYPE_CHECKING

from isaaclab.utils import configclass

from . import actuator_pd
from .actuator_base_cfg import ActuatorBaseCfg

if TYPE_CHECKING:
from .actuator_pd import DCMotor, DelayedPDActuator, IdealPDActuator, ImplicitActuator, RemotizedPDActuator

"""
Implicit Actuator Models.
"""
Expand All @@ -23,7 +26,7 @@ class ImplicitActuatorCfg(ActuatorBaseCfg):
The PD control is handled implicitly by the simulation.
"""

class_type: type = actuator_pd.ImplicitActuator
class_type: type["ImplicitActuator"] | str = "{DIR}.actuator_pd:ImplicitActuator"


"""
Expand All @@ -35,14 +38,14 @@ class ImplicitActuatorCfg(ActuatorBaseCfg):
class IdealPDActuatorCfg(ActuatorBaseCfg):
"""Configuration for an ideal PD actuator."""

class_type: type = actuator_pd.IdealPDActuator
class_type: type["IdealPDActuator"] | str = "{DIR}.actuator_pd:IdealPDActuator"


@configclass
class DCMotorCfg(IdealPDActuatorCfg):
"""Configuration for direct control (DC) motor actuator model."""

class_type: type = actuator_pd.DCMotor
class_type: type["DCMotor"] | str = "{DIR}.actuator_pd:DCMotor"

saturation_effort: float = MISSING
"""Peak motor force/torque of the electric DC motor (in N-m)."""
Expand All @@ -52,7 +55,7 @@ class DCMotorCfg(IdealPDActuatorCfg):
class DelayedPDActuatorCfg(IdealPDActuatorCfg):
"""Configuration for a delayed PD actuator."""

class_type: type = actuator_pd.DelayedPDActuator
class_type: type["DelayedPDActuator"] | str = "{DIR}.actuator_pd:DelayedPDActuator"

min_delay: int = 0
"""Minimum number of physics time-steps with which the actuator command may be delayed. Defaults to 0."""
Expand All @@ -71,7 +74,7 @@ class RemotizedPDActuatorCfg(DelayedPDActuatorCfg):
the output torques.
"""

class_type: type = actuator_pd.RemotizedPDActuator
class_type: type["RemotizedPDActuator"] | str = "{DIR}.actuator_pd:RemotizedPDActuator"

joint_parameter_lookup: list[list[float]] = MISSING
"""Joint parameter lookup table. Shape is (num_lookup_points, 3).
Expand Down
40 changes: 15 additions & 25 deletions source/isaaclab/isaaclab/assets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,18 @@
the corresponding actuator torques.
"""

from .articulation import BaseArticulation, BaseArticulationData, Articulation, ArticulationCfg, ArticulationData
from .asset_base import AssetBase
from .asset_base_cfg import AssetBaseCfg
from .rigid_object import BaseRigidObject, BaseRigidObjectData, RigidObject, RigidObjectCfg, RigidObjectData
from .rigid_object_collection import BaseRigidObjectCollection, BaseRigidObjectCollectionData, RigidObjectCollection, RigidObjectCollectionCfg, RigidObjectCollectionData

__all__ = [
"AssetBase",
"AssetBaseCfg",
"BaseArticulation",
"BaseArticulationData",
"Articulation",
"ArticulationCfg",
"ArticulationData",
"BaseRigidObject",
"BaseRigidObjectData",
"RigidObject",
"RigidObjectCfg",
"RigidObjectData",
"BaseRigidObjectCollection",
"BaseRigidObjectCollectionData",
"RigidObjectCollection",
"RigidObjectCollectionCfg",
"RigidObjectCollectionData",
]
from isaaclab.utils.lazy_imports import lazy_export

lazy_export(
("asset_base", "AssetBase"),
("asset_base_cfg", "AssetBaseCfg"),
("articulation", ["BaseArticulation", "BaseArticulationData", "Articulation", "ArticulationCfg", "ArticulationData"]),
("rigid_object", ["BaseRigidObject", "BaseRigidObjectData", "RigidObject", "RigidObjectCfg", "RigidObjectData"]),
("rigid_object_collection", [
"BaseRigidObjectCollection",
"BaseRigidObjectCollectionData",
"RigidObjectCollection",
"RigidObjectCollectionCfg",
"RigidObjectCollectionData",
]),
)
20 changes: 8 additions & 12 deletions source/isaaclab/isaaclab/assets/articulation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@

"""Sub-module for rigid articulated assets."""

from .base_articulation import BaseArticulation
from .base_articulation_data import BaseArticulationData
from .articulation import Articulation
from .articulation_cfg import ArticulationCfg
from .articulation_data import ArticulationData
from isaaclab.utils.lazy_imports import lazy_export

__all__ = [
"BaseArticulation",
"BaseArticulationData",
"Articulation",
"ArticulationCfg",
"ArticulationData",
]
lazy_export(
("base_articulation", "BaseArticulation"),
("base_articulation_data", "BaseArticulationData"),
("articulation", "Articulation"),
("articulation_cfg", "ArticulationCfg"),
("articulation_data", "ArticulationData"),
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
from __future__ import annotations

from dataclasses import MISSING
from typing import TYPE_CHECKING

from isaaclab.actuators import ActuatorBaseCfg
from isaaclab.utils import configclass

from ..asset_base_cfg import AssetBaseCfg
from .articulation import Articulation

if TYPE_CHECKING:
from .articulation import Articulation


@configclass
Expand All @@ -38,7 +41,7 @@ class InitialStateCfg(AssetBaseCfg.InitialStateCfg):
# Initialize configurations.
##

class_type: type = Articulation
class_type: type[Articulation] | str = "{DIR}.articulation:Articulation"

articulation_root_prim_path: str | None = None
"""Path to the articulation root prim under the :attr:`prim_path`. Defaults to None, in which case the class
Expand Down
6 changes: 3 additions & 3 deletions source/isaaclab/isaaclab/assets/asset_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import torch

import isaaclab.sim as sim_utils
from isaaclab.physics import PhysicsEvent, PhysicsManager
from isaaclab.physics import PhysicsEvent
from isaaclab.sim.simulation_context import SimulationContext
from isaaclab.sim.utils.stage import get_current_stage

Expand Down Expand Up @@ -310,8 +310,8 @@ def _initialize_callback(self, event):
:attr:`PhysicsEvent.PHYSICS_READY` is dispatched by the current backend.
"""
if not self._is_initialized:
self._backend = PhysicsManager.get_backend()
self._device = PhysicsManager.get_device()
self._backend = SimulationContext.instance().physics_manager.get_backend()
self._device = SimulationContext.instance().physics_manager.get_device()
try:
self._initialize_impl()
except Exception as e:
Expand Down
4 changes: 1 addition & 3 deletions source/isaaclab/isaaclab/assets/asset_base_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
from isaaclab.sim import SpawnerCfg
from isaaclab.utils import configclass

from .asset_base import AssetBase


@configclass
class AssetBaseCfg:
Expand Down Expand Up @@ -41,7 +39,7 @@ class InitialStateCfg:
Defaults to (0.0, 0.0, 0.0, 1.0).
"""

class_type: type[AssetBase] = None
class_type: type | str | None = None
"""The associated asset class. Defaults to None, which means that the asset will be spawned
but cannot be interacted with via the asset class.

Expand Down
20 changes: 8 additions & 12 deletions source/isaaclab/isaaclab/assets/rigid_object/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@

"""Sub-module for rigid object assets."""

from .base_rigid_object import BaseRigidObject
from .base_rigid_object_data import BaseRigidObjectData
from .rigid_object import RigidObject
from .rigid_object_cfg import RigidObjectCfg
from .rigid_object_data import RigidObjectData
from isaaclab.utils.lazy_imports import lazy_export

__all__ = [
"BaseRigidObject",
"BaseRigidObjectData",
"RigidObject",
"RigidObjectCfg",
"RigidObjectData",
]
lazy_export(
("base_rigid_object", "BaseRigidObject"),
("base_rigid_object_data", "BaseRigidObjectData"),
("rigid_object", "RigidObject"),
("rigid_object_cfg", "RigidObjectCfg"),
("rigid_object_data", "RigidObjectData"),
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
#
# SPDX-License-Identifier: BSD-3-Clause

from typing import TYPE_CHECKING

from isaaclab.utils import configclass

from ..asset_base_cfg import AssetBaseCfg
from .rigid_object import RigidObject

if TYPE_CHECKING:
from .rigid_object import RigidObject


@configclass
Expand All @@ -26,7 +30,7 @@ class InitialStateCfg(AssetBaseCfg.InitialStateCfg):
# Initialize configurations.
##

class_type: type = RigidObject
class_type: type["RigidObject"] | str = "{DIR}.rigid_object:RigidObject"

init_state: InitialStateCfg = InitialStateCfg()
"""Initial state of the rigid object. Defaults to identity pose with zero velocity."""
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@

"""Sub-module for rigid object collection."""

from .base_rigid_object_collection import BaseRigidObjectCollection
from .base_rigid_object_collection_data import BaseRigidObjectCollectionData
from .rigid_object_collection import RigidObjectCollection
from .rigid_object_collection_cfg import RigidObjectCollectionCfg
from .rigid_object_collection_data import RigidObjectCollectionData
from isaaclab.utils.lazy_imports import lazy_export

__all__ = [
"BaseRigidObjectCollection",
"BaseRigidObjectCollectionData",
"RigidObjectCollection",
"RigidObjectCollectionCfg",
"RigidObjectCollectionData",
]
lazy_export(
("base_rigid_object_collection", "BaseRigidObjectCollection"),
("base_rigid_object_collection_data", "BaseRigidObjectCollectionData"),
("rigid_object_collection", "RigidObjectCollection"),
("rigid_object_collection_cfg", "RigidObjectCollectionCfg"),
("rigid_object_collection_data", "RigidObjectCollectionData"),
)
Loading
Loading