Skip to content

Commit fc80c03

Browse files
authored
Merge branch 'develop' into fix/backend-fallback-without-sim-context
2 parents 1d9764b + c4a2759 commit fc80c03

39 files changed

Lines changed: 464 additions & 138 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Docstring-only clarification of the shape-expression convention; behaviour change lives in isaaclab_newton.

source/isaaclab/changelog.d/ooctipus-newton-active-solver-attributes.skip

Whitespace-only changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fixed
2+
^^^^^
3+
4+
* Fixed camera depth display normalization producing ``NaN`` values and suppressing finite depth contrast when
5+
no-hit pixels contain ``inf`` or ``NaN`` values.

source/isaaclab/isaaclab/physics/physics_manager.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class PhysicsManager(ABC):
8686
_sim_time: ClassVar[float] = 0.0
8787
_callbacks: ClassVar[dict[int, tuple[Any, Callable, int, str | None, Any]]] = {}
8888
_callback_id: ClassVar[int] = 0
89+
views: ClassVar[dict[tuple[type, str], Any]] = {}
8990

9091
@classmethod
9192
def _prepare_stage_creation(cls) -> None:
@@ -457,6 +458,7 @@ def close(cls) -> None:
457458
cls.clear_callbacks()
458459
finally:
459460
if is_active_manager:
461+
PhysicsManager.views.clear()
460462
PhysicsManager._sim = None
461463
PhysicsManager._cfg = None
462464
PhysicsManager._sim_time = 0.0

source/isaaclab/isaaclab/sensors/contact_sensor/contact_sensor_cfg.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ class ContactSensorCfg(SensorBaseCfg):
9898
**Newton backend only** (ignored by the PhysX and OvPhysX backends). A shape is an individual
9999
collision geometry attached to a body. If non-empty, :attr:`prim_path` is ignored for the
100100
sensing objects and these shape expressions are used instead.
101+
102+
Full-matched against shape paths, so an expression naming a body selects nothing:
103+
write ``{ENV_REGEX_NS}/Box[^/]*/.*`` to reach the shapes below it.
101104
"""
102105

103106
filter_shape_prim_expr: list[str] = []
@@ -106,6 +109,8 @@ class ContactSensorCfg(SensorBaseCfg):
106109
107110
**Newton backend only** (ignored by the PhysX and OvPhysX backends). If provided, the force
108111
matrix reports per-shape contact forces; mutually exclusive with :attr:`filter_prim_paths_expr`.
112+
113+
Matched against shape paths on the same terms as :attr:`sensor_shape_prim_expr`.
109114
"""
110115

111116
visualizer_cfg: VisualizationMarkersCfg = CONTACT_SENSOR_MARKER_CFG.replace(prim_path="/Visuals/ContactSensor")

source/isaaclab/isaaclab/utils/images.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ def normalize_camera_output_for_display(tensor: torch.Tensor, data_type: str) ->
105105
normalized = tensor.float()
106106

107107
if data_type in ["depth", "distance_to_camera", "distance_to_image_plane"]:
108+
normalized = torch.nan_to_num(normalized, nan=0.0, posinf=0.0, neginf=0.0)
108109
max_val = normalized.max()
109110
if max_val > 0:
110111
normalized = normalized / max_val

source/isaaclab/test/sim/test_physics_manager_lifecycle.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class TestManager(PhysicsManager):
2626
monkeypatch.setattr(PhysicsManager, "_sim", SimpleNamespace(physics_manager=TestManager))
2727
monkeypatch.setattr(PhysicsManager, "_cfg", object())
2828
monkeypatch.setattr(PhysicsManager, "_sim_time", 1.0)
29+
monkeypatch.setattr(PhysicsManager, "views", {(TestManager, "/World/Robot"): object()})
2930

3031
TestManager.register_callback(
3132
lambda _payload: events.append("first"),
@@ -71,6 +72,7 @@ def failing_listener(_payload):
7172
assert PhysicsManager._sim is None
7273
assert PhysicsManager._cfg is None
7374
assert PhysicsManager._sim_time == 0.0
75+
assert PhysicsManager.views == {}
7476

7577

7678
def test_close_surfaces_stop_errors_stored_by_safe_callback_invoke(monkeypatch):
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
2+
# All rights reserved.
3+
#
4+
# SPDX-License-Identifier: BSD-3-Clause
5+
6+
import pytest
7+
import torch
8+
9+
from isaaclab.utils.images import normalize_camera_output_for_display
10+
11+
pytestmark = pytest.mark.unit
12+
13+
14+
@pytest.mark.parametrize("data_type", ["depth", "distance_to_camera", "distance_to_image_plane"])
15+
def test_depth_display_normalization_ignores_nonfinite_values(data_type):
16+
src = torch.tensor([0.0, 2.0, float("inf"), 4.0, float("nan")])
17+
18+
out = normalize_camera_output_for_display(src, data_type)
19+
20+
expected = torch.tensor([0.0, 0.5, 0.0, 1.0, 0.0])
21+
torch.testing.assert_close(out, expected)
22+
assert torch.isfinite(out).all()
23+
24+
25+
def test_depth_display_normalization_handles_all_nonfinite_values():
26+
src = torch.tensor([float("inf"), float("nan")])
27+
28+
out = normalize_camera_output_for_display(src, "depth")
29+
30+
torch.testing.assert_close(out, torch.zeros_like(src))
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fixed
2+
^^^^^
3+
4+
* Registered every configured child solver's builder attributes for coupled Newton models.

source/isaaclab_contrib/isaaclab_contrib/coupling/coupler.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,17 +188,15 @@ def _validate_resolved_entries(
188188
def _register_builder_attributes(cls, builder: ModelBuilder) -> None:
189189
"""Register custom attributes required by nested coupled entries."""
190190
super()._register_builder_attributes(builder)
191-
solver_cfg = getattr(PhysicsManager._cfg, "solver_cfg", None)
192-
if any(isinstance(entry.solver_cfg, MPMSolverCfg) for entry in getattr(solver_cfg, "entries", ())):
193-
NewtonMPMManager._register_builder_attributes(builder)
191+
for entry in PhysicsManager._cfg.solver_cfg.entries:
192+
entry.solver_cfg.class_type._register_builder_attributes(builder)
194193

195194
@classmethod
196195
def _prepare_builder_for_finalize(cls, builder: ModelBuilder) -> None:
197196
"""Normalize kinematic colliders when a coupled entry uses implicit MPM."""
198197
super()._prepare_builder_for_finalize(builder)
199-
solver_cfg = getattr(PhysicsManager._cfg, "solver_cfg", None)
200-
if any(isinstance(entry.solver_cfg, MPMSolverCfg) for entry in getattr(solver_cfg, "entries", ())):
201-
NewtonMPMManager._prepare_builder_for_finalize(builder)
198+
for entry in PhysicsManager._cfg.solver_cfg.entries:
199+
entry.solver_cfg.class_type._prepare_builder_for_finalize(builder)
202200

203201
@classmethod
204202
def _initialize_contacts(cls) -> None:

0 commit comments

Comments
 (0)