Skip to content
2 changes: 1 addition & 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 = "0.47.11"
version = "0.49.0"

# Description
title = "Isaac Lab framework for Robot Learning"
Expand Down
17 changes: 17 additions & 0 deletions source/isaaclab/docs/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
Changelog
---------

0.49.0 (2025-11-07)
~~~~~~~~~~~~~~~~~~~

Added
^^^^^

* Added two new PhysX configuration parameters to :class:`~isaaclab.sim.PhysxCfg`:

- :attr:`~isaaclab.sim.PhysxCfg.disable_sleeping`: Disables sleeping for all objects in the physics scene on a global level.
This flag is set to ``True`` by default and overrides any sleeping settings on individual bodies. If sleeping is required
on any individual body, this flag must be set to ``False``. Note that if ``disable_sleeping`` is set to ``False`` and the
directGPU pipeline is enabled, PhysX will issue an error and fail scene creation.
- :attr:`~isaaclab.sim.PhysxCfg.enable_external_forces_every_iteration`: Enables external forces to be applied every iteration.
This flag is set to ``False`` by default (standard PhysX behavior). Setting this to ``True`` can reduce noisy joint velocity
data from PhysX at a slight performance cost.


0.47.11 (2025-11-03)
~~~~~~~~~~~~~~~~~~~~

Expand Down
20 changes: 20 additions & 0 deletions source/isaaclab/isaaclab/sim/simulation_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,26 @@ class PhysxCfg:

"""

disable_sleeping: bool = True
"""Disable sleeping for all objects in the physics scene on a global level. Default is True.

This flag disables sleeping for all objects in the scene, overriding any sleeping settings on individual bodies.
If sleeping is required on any individual body, this flag must be set to False.

.. warning::

If :attr:`disable_sleeping` is set to False and the GPU pipeline is enabled, PhysX will issue an error
message and fail scene creation as this is not supported.
"""

enable_external_forces_every_iteration: bool = False
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this flag only work when TGS is used? Also if this flag is enabled, then within the asset classes, I wonder if we still need to set forces at simulation steps. Previously those were getting cleared which wasn't a desired effect.

By iteration: do you mean solver iteration or sim.step? The document is clear about it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"""Enable external forces to be applied every iteration. Default is False.

When set to False (default), external forces are applied using the standard PhysX behavior, which may lead
to noisy joint velocity data from PhysX. Setting this to True will apply external forces at every iteration,
which can reduce the noise in joint velocity data at a slight performance cost.
"""


@configclass
class RenderCfg:
Expand Down
20 changes: 20 additions & 0 deletions source/isaaclab/isaaclab/sim/simulation_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,26 @@ def _set_additional_physx_params(self):
physx_prim.CreateAttribute("physxScene:solveArticulationContactLast", Sdf.ValueTypeNames.Bool).Set(
self.cfg.physx.solve_articulation_contact_last
)
# -- Disable sleeping globally
# This overrides any sleeping settings on individual bodies
physx_prim.CreateAttribute("physxSceneAPI:disableSleeping", Sdf.ValueTypeNames.Bool).Set(
self.cfg.physx.disable_sleeping
)
# Check if disable_sleeping is False with GPU pipeline enabled
if not self.cfg.physx.disable_sleeping:
# Check if GPU pipeline is enabled via the suppressReadback flag
suppress_readback = self.carb_settings.get_as_bool("/physics/suppressReadback")
if suppress_readback:
raise RuntimeError(
"PhysX configuration error: 'disable_sleeping' is set to False while GPU pipeline is enabled "
"(/physics/suppressReadback=True). This combination will cause PhysX to fail scene creation. "
"Please set 'cfg.physx.disable_sleeping = True' or disable GPU pipeline."
)
# -- Enable external forces every iteration
# This can help reduce noisy joint velocity data from PhysX at a slight performance cost
physx_scene_api.CreateEnableExternalForcesEveryIterationAttr(
self.cfg.physx.enable_external_forces_every_iteration
)

# -- Gravity
# note: Isaac sim only takes the "up-axis" as the gravity direction. But physics allows any direction so we
Expand Down
106 changes: 106 additions & 0 deletions source/isaaclab/test/sim/test_simulation_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,109 @@ def test_zero_gravity():
gravity_dir, gravity_mag = sim.get_physics_context().get_gravity()
gravity = np.array(gravity_dir) * gravity_mag
np.testing.assert_almost_equal(gravity, cfg.gravity)


@pytest.mark.isaacsim_ci
def test_disable_sleeping_setting():
"""Test that the disable_sleeping PhysX setting is applied correctly."""
from pxr import PhysxSchema

# Test with disable_sleeping set to True (default)
cfg = SimulationCfg()
assert cfg.physx.disable_sleeping is True

sim = SimulationContext(cfg)

# Get the physics scene prim and check the attribute
stage = sim.stage
physics_scene_prim = stage.GetPrimAtPath(cfg.physics_prim_path)
assert physics_scene_prim.IsValid()

# Check that the attribute exists and is set to True
disable_sleeping_attr = physics_scene_prim.GetAttribute("physxSceneAPI:disableSleeping")
assert disable_sleeping_attr.IsValid()
assert disable_sleeping_attr.Get() is True


@pytest.mark.isaacsim_ci
def test_disable_sleeping_false_with_cpu():
"""Test that disable_sleeping can be set to False when using CPU simulation."""
from pxr import PhysxSchema

# Test with disable_sleeping set to False and CPU device
cfg = SimulationCfg(device="cpu")
cfg.physx.disable_sleeping = False

sim = SimulationContext(cfg)

# Get the physics scene prim and check the attribute
stage = sim.stage
physics_scene_prim = stage.GetPrimAtPath(cfg.physics_prim_path)
assert physics_scene_prim.IsValid()

# Check that the attribute exists and is set to False
disable_sleeping_attr = physics_scene_prim.GetAttribute("physxSceneAPI:disableSleeping")
assert disable_sleeping_attr.IsValid()
assert disable_sleeping_attr.Get() is False


@pytest.mark.isaacsim_ci
def test_disable_sleeping_false_with_gpu_raises_error():
"""Test that disable_sleeping=False with GPU simulation raises an error."""
# Test with disable_sleeping set to False and GPU device
cfg = SimulationCfg(device="cuda:0")
cfg.physx.disable_sleeping = False

# This should raise a RuntimeError because GPU pipeline + disable_sleeping=False is not supported
with pytest.raises(RuntimeError, match="disable_sleeping.*GPU pipeline"):
SimulationContext(cfg)


@pytest.mark.isaacsim_ci
def test_enable_external_forces_every_iteration_setting():
"""Test that the enable_external_forces_every_iteration PhysX setting is applied correctly."""
from pxr import PhysxSchema

# Test with enable_external_forces_every_iteration set to False (default)
cfg = SimulationCfg()
assert cfg.physx.enable_external_forces_every_iteration is False

sim = SimulationContext(cfg)

# Get the physics scene API and check the attribute
stage = sim.stage
physics_scene_prim = stage.GetPrimAtPath(cfg.physics_prim_path)
assert physics_scene_prim.IsValid()

physx_scene_api = PhysxSchema.PhysxSceneAPI(physics_scene_prim)
assert physx_scene_api

# Check that the attribute exists and is set to False
enable_external_forces_attr = physx_scene_api.GetEnableExternalForcesEveryIterationAttr()
assert enable_external_forces_attr.IsValid()
assert enable_external_forces_attr.Get() is False


@pytest.mark.isaacsim_ci
def test_enable_external_forces_every_iteration_true():
"""Test that enable_external_forces_every_iteration can be set to True."""
from pxr import PhysxSchema

# Test with enable_external_forces_every_iteration set to True
cfg = SimulationCfg()
cfg.physx.enable_external_forces_every_iteration = True

sim = SimulationContext(cfg)

# Get the physics scene API and check the attribute
stage = sim.stage
physics_scene_prim = stage.GetPrimAtPath(cfg.physics_prim_path)
assert physics_scene_prim.IsValid()

physx_scene_api = PhysxSchema.PhysxSceneAPI(physics_scene_prim)
assert physx_scene_api

# Check that the attribute exists and is set to True
enable_external_forces_attr = physx_scene_api.GetEnableExternalForcesEveryIterationAttr()
assert enable_external_forces_attr.IsValid()
assert enable_external_forces_attr.Get() is True
Loading