Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Test-only change: raises the per-channel difference threshold in the visualizer integration
test helper for the Kit RTX pause checks, and restores fresh renders in the paused tiled
capture (NVBUG 6570125 work-around). No user-facing behavior change.
43 changes: 32 additions & 11 deletions source/isaaclab_visualizers/test/visualizer_integration_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,20 @@
_TILED_CAMERA_MOTION_MIN_DIFFERING_PIXELS = 25
"""Minimum differing pixels for tiled camera motion checks."""

# NVBUG 6570125 — Remove these overrides once it ships the fix and paused frames are stable again.
_KIT_PAUSED_VIEWPORT_CHANNEL_DIFF_THRESHOLD = 80
"""Per-channel threshold for paused Kit viewport comparisons (0–255 space)."""

_KIT_PAUSED_TILED_CAMERA_NEWTON_CHANNEL_DIFF_THRESHOLD = 160

@matthewtrepte matthewtrepte Aug 14, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

hm more of a note than a request: 160 out of 256 is a large part of the range; its not rejecting many cases. not sure if there's a cleaner way like loosening also the pixel count threshold so that this threshold doesn't need to be as high

but given that its temporary and well documented that is so and what the bug is, i think its fine.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, I had the same concern. 160 felt high to me too. The measured separation from real motion is what made me comfortable with it as a temporary WAR, and I wouldn't want this to quietly become permanent.

"""Per-channel threshold for paused Kit tiled camera comparisons on Newton (0–255 space)."""

_KIT_PAUSED_TILED_CAMERA_PHYSX_CHANNEL_DIFF_THRESHOLD = 80
"""Per-channel threshold for paused Kit tiled camera comparisons on PhysX (0–255 space).

Matches the viewport value but is kept separate: this cell measures 103 differing pixels at the
default threshold, so it needs its own floor rather than tracking whatever the viewport uses.
"""

_FRAME_MIN_CHANNEL_RANGE = 10
"""Minimum per-frame channel range to reject all-one-color images."""

Expand Down Expand Up @@ -569,12 +583,14 @@ def _assert_frames_remain_stable(
phase: str,
debug_phase: str,
max_differing_pixels: int = 100,
channel_diff_threshold: float = _FRAME_MOTION_CHANNEL_DIFF_THRESHOLD,
) -> None:
"""Assert two viewport frames are effectively unchanged while simulation is paused."""
n_diff = _count_significantly_differing_pixels(frame_a, frame_b)
n_diff = _count_significantly_differing_pixels(frame_a, frame_b, channel_diff_threshold=channel_diff_threshold)
assert n_diff <= max_differing_pixels, (
f"{case_label} failed to pause during {phase}: {n_diff} pixels differed, expected at most "
f"{max_differing_pixels}. Frame shape={_frame_shape_for_message(frame_a)}. "
f"{max_differing_pixels} with per-channel threshold {channel_diff_threshold} in 0-255 space. "
f"Frame shape={_frame_shape_for_message(frame_a)}. "
f"Debug frames: {_current_visualizer_debug_dir()}/*{debug_phase}*.png."
)

Expand Down Expand Up @@ -1259,6 +1275,7 @@ def _attempt_kit_pause():
case_label=case_label,
phase="pausing",
debug_phase="pausing",
channel_diff_threshold=_KIT_PAUSED_VIEWPORT_CHANNEL_DIFF_THRESHOLD,
)

try:
Expand Down Expand Up @@ -1400,16 +1417,13 @@ def _run_visualizer_tiled_camera_motion_test(env, visualizer, *, physics_kind: s

def _attempt_pause():
_set_kit_simulation_paused(env, True)
# Read the sensor's last completed frame while paused. Forcing a new RTX
# render here introduces TAA edge jitter even though physics is frozen.
paused_start_frame = _capture_visualizer_tiled_camera_rgb(
visualizer, label="2a_pausing_frame_20", force_recompute=False
)
# Re-render both paused captures: comparing the sensor's cached frame with itself cannot
# detect a renderer that keeps changing the image after physics stops. The denoiser residue
# that motivated caching is handled by the per-channel threshold below (NVBUG 6570125).
paused_start_frame = _capture_visualizer_tiled_camera_rgb(visualizer, label="2a_pausing_frame_20")
for _ in range(PAUSE_VIZ_N_STEP):
env.sim.render(skip_app_pumping=isinstance(visualizer, KitVisualizer))
paused_end_frame = _capture_visualizer_tiled_camera_rgb(
visualizer, label="2b_pausing_frame_25", force_recompute=False
)
env.sim.render()
paused_end_frame = _capture_visualizer_tiled_camera_rgb(visualizer, label="2b_pausing_frame_25")
_save_visualizer_debug_phase_images(
paused_start_frame,
paused_end_frame,
Expand All @@ -1425,6 +1439,13 @@ def _attempt_pause():
case_label=case_label,
phase="pausing",
debug_phase="pausing_tiled",
channel_diff_threshold=(
_KIT_PAUSED_TILED_CAMERA_NEWTON_CHANNEL_DIFF_THRESHOLD
if isinstance(visualizer, KitVisualizer) and physics_kind == "newton"
else _KIT_PAUSED_TILED_CAMERA_PHYSX_CHANNEL_DIFF_THRESHOLD
if isinstance(visualizer, KitVisualizer)
else _FRAME_MOTION_CHANNEL_DIFF_THRESHOLD
),
)

try:
Expand Down
Loading