Skip to content

Fixes stale sensor data after environment reset#5782

Merged
kellyguo11 merged 4 commits into
isaac-sim:developfrom
AntoineRichard:antoiner/fix/contact-sensor-stale-reset
May 27, 2026
Merged

Fixes stale sensor data after environment reset#5782
kellyguo11 merged 4 commits into
isaac-sim:developfrom
AntoineRichard:antoiner/fix/contact-sensor-stale-reset

Conversation

@AntoineRichard

@AntoineRichard AntoineRichard commented May 26, 2026

Copy link
Copy Markdown
Collaborator

Description

ContactSensor (and other lazy-eval sensors — IMU, PVA, JointWrenchSensor) surfaced pre-reset values when scene.reset(env_ids) ran inside ManagerBasedRLEnv._reset_idx. The reset call zeroed each sensor's _data buffers correctly, but the shared reset_envs_kernel then marked the env as outdated — so the next sensor.data access (during observation_manager.compute()) triggered a lazy refetch from a physics buffer that had not been stepped since the reset, overwriting the zeros with stale data (contact forces, joint wrenches, velocities → spurious finite-diff accelerations).

The fix clears the outdated flag in reset_envs_kernel instead of setting it. The next InteractiveScene.update(dt) re-arms the flag at the sensor's configured update period, so:

  • The first data read after scene.reset(env_ids) returns the freshly-zeroed buffers.
  • The next step's read pulls fresh post-reset physics data as before.

This is a single-point fix in the shared sensor layer — it covers both Newton and PhysX backends for every sensor that follows the "reset() zeros _data + data is lazy" pattern.

Fixes #4970

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Screenshots

N/A — behavior change is observable in the sensor data values, covered by the regression tests below.

Checklist

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • I have added a changelog fragment under source/<pkg>/changelog.d/ for every touched package (do not edit CHANGELOG.rst or bump extension.toml — CI handles that)
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

Tests added

Per-backend, per-sensor regression tests that mirror the manager-based env path (write new asset state, then scene.reset(env_ids), then read sensor.data). Each was verified RED with the kernel change temporarily reverted and GREEN with it restored:

Backend Sensor Test
PhysX ContactSensor test_contact_sensor.py::test_contact_sensor_no_stale_data_after_reset (cuda + cpu)
PhysX JointWrenchSensor test_joint_wrench_sensor.py::test_no_stale_data_after_scene_reset
PhysX PVA test_pva.py::test_no_stale_data_after_scene_reset
PhysX IMU test_imu.py::test_no_stale_data_after_scene_reset
Newton ContactSensor test_contact_sensor.py::test_no_stale_data_after_scene_reset (cuda + cpu)
Newton JointWrenchSensor test_joint_wrench_sensor.py::test_no_stale_data_after_scene_reset
Newton PVA test_pva.py::test_no_stale_data_after_scene_reset
Newton IMU test_imu.py::test_no_stale_data_after_scene_reset

Existing ContactSensor (PhysX, 20 tests) and IMU (PhysX, 8 tests) suites continue to pass.

Note

The Newton IMU's native SensorIMU (accelerometer / gyroscope) does not carry data between physics steps the way PhysX's get_velocities() does, so its test passes both before and after the fix. The test stays in as a guard against future regressions in Newton IMU's design.

Notes for reviewers

  • Behavior change is intentional: sensors that override reset() to zero their _data (contact, IMU, PVA, joint wrench, both backends) now keep those zeros until the next physics step. Sensors that don't zero data (e.g. ray-caster, frame transformer) still see refetches at the next update-period boundary, which preserves current behavior for them.
  • No public API change. No deprecation needed.

The shared sensor lazy-eval kernel was marking envs as outdated on reset,
which caused the next data access to refetch from a physics buffer that
had not been stepped since the reset and overwrite the zeros that each
sensor's reset() override had just written. Inside
ManagerBasedRLEnv._reset_idx this surfaced as observations reflecting the
pre-reset state (contact force on a cube that had been teleported back
up, joint wrench on a freshly reset articulation, spurious finite-diff
acceleration on IMU/PVA, etc.).

Clear the outdated flag in reset_envs_kernel instead of setting it. The
next InteractiveScene.update re-arms the flag at the configured update
period, so post-reset reads return the freshly-zeroed buffers and the
following step's read pulls fresh physics data as before.

Adds per-backend, per-sensor regression tests (PhysX: ContactSensor,
JointWrenchSensor, PVA, IMU; Newton: same set) that exercise the
scene.reset(env_ids) path through the public data accessor.

Fixes isaac-sim#4970
@github-actions github-actions Bot added bug Something isn't working documentation Improvements or additions to documentation asset New asset feature or request isaac-sim Related to Isaac Sim team isaac-mimic Related to Isaac Mimic team infrastructure labels May 26, 2026
@AntoineRichard AntoineRichard changed the base branch from main to develop May 26, 2026 15:26
@AntoineRichard AntoineRichard changed the title Fix stale sensor data after environment reset Fixes stale sensor data after environment reset May 26, 2026

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review Summary

This is a well-targeted fix for #4970 — the stale sensor data issue after environment reset. The approach is minimal and correct.

The Bug (Recap)

When scene.reset(env_ids) runs inside ManagerBasedRLEnv._reset_idx:

  1. Each sensor's reset() zeros its _data buffers ✓
  2. reset_envs_kernel then marked the env as outdated → ❌ Problem
  3. Next sensor.data access triggered a lazy refetch from a physics buffer that hadn't been stepped
  4. The zeros got overwritten with stale pre-reset values

The Fix

# Before: is_outdated[env] = True  (triggering unwanted refetch)
# After:  is_outdated[env] = False (preserving the zeroed data)

This is the correct single-point fix. The flag is re-armed by InteractiveScene.update after the next physics step, restoring normal lazy-fetch behavior.


✅ Strengths

  1. Minimal diff: One line change in reset_envs_kernel covers all affected sensors (ContactSensor, IMU, PVA, JointWrenchSensor) across both PhysX and Newton backends.

  2. Comprehensive test coverage: 8 new regression tests (4 sensors × 2 backends) that specifically reproduce the manager-based RL flow. Each test was verified RED→GREEN.

  3. Well-documented: The changelog fragment and updated docstring in reset_envs_kernel clearly explain the rationale.

  4. No API changes: Purely internal behavior fix — no breaking changes for downstream users.


⚠️ Considerations

1. Sensors Without Zeroing reset() Override

The PR description notes:

Sensors that don't zero data (e.g. ray-caster, frame transformer) still see refetches at the next update-period boundary.

This is correct because those sensors don't override reset() to zero their data — they rely on the fetch. But it's worth confirming this behavior is still exercised by existing tests.

Question for author: Were the existing ray-caster and frame-transformer tests confirmed to still pass with this change? The PR description mentions existing ContactSensor (20) and IMU (8) tests passed, but doesn't explicitly mention ray-caster/frame-transformer.

2. Partial Reset Edge Case

With scene.reset(env_ids) where env_ids is a subset:

  • Only the specified envs get is_outdated[env] = False
  • Other envs retain their is_outdated state

This looks correct, but the new tests only cover single-env scenarios. It would strengthen confidence to see test_reset_with_env_ids_only_zeros_selected_envs patterns also check that non-reset envs retain their normal lazy-fetch behavior (i.e., their is_outdated flag isn't accidentally cleared).

3. Missing Import in Newton IMU Test

Looking at test_imu.py (Newton), the test uses RigidObject but I see it's correctly imported:

from isaaclab.assets import RigidObject, RigidObjectCfg

Good — this was updated.


🔍 Regression Test Robustness

The tests correctly mirror the _reset_idx flow:

  1. Run simulation until sensor has non-zero data
  2. Write new asset state
  3. Call scene.reset(env_ids) without a subsequent physics step
  4. Assert sensor.data returns zeros, not stale values

This is the exact scenario from issue #4970. The assertion style is clear:

assert post_reset_force_mag == 0.0, (
    "Contact sensor returned stale pre-reset data after scene.reset(): "
    f"got {post_reset_force_mag}, expected 0.0"
)

Verdict

Looks good to merge pending:

  1. Confirmation that ray-caster/frame-transformer tests still pass (should be covered by CI)
  2. (Optional) Consider adding a multi-env partial-reset test to verify non-reset envs retain outdated flag

The fix is correct, minimal, and well-tested. Nice work @AntoineRichard!


📋 Update (2026-05-27)

New commits pushed: 153a1e5cce490ebe

Reviewed the diff between previously-reviewed commit and new head. The changes appear to be unrelated to this PR's fix (stale sensor data after reset). They include:

  • CI: Added ovphysx pip package to rendering workflow
  • Docs: LEAPP export updates, Windows tab-sets, ecosystem link fixes
  • New: PPISP camera QA demos (ppisp_camera.py, ppisp_camera_ovrtx.py)
  • Cleanup: Removed legacy OVRTX 0.2.x code paths
  • Fix: Tutorial CPU tensor device mismatch (add_new_robot.py)
  • Test: Docstring updates, golden images for ovphysx rendering

These look like upstream base-branch changes that merged in, not modifications to the sensor reset fix itself. The core fix in reset_envs_kernel (flipping is_outdated[env] = False) remains unchanged.

Original review assessment stands: ✅ Ready to merge.

@github-actions github-actions Bot added the isaac-lab Related to Isaac Lab team label May 27, 2026
The kernel-level fix (reset_envs_kernel setting is_outdated=False) broke
FrameTransformer's refetch-on-reset behavior that PR isaac-sim#1276 relies on,
causing test_outdated_sensor.py to fail in CI. Move the fix into each
step-dependent sensor's reset() so it only affects the four sensors that
genuinely have a staleness problem (contact / IMU / PVA / joint-wrench
across PhysX and Newton); FrameTransformer / RayCaster / Camera keep
their original refetch-on-reset semantics.

* Revert reset_envs_kernel back to is_outdated=True (PR isaac-sim#1276 contract).
* Add clear_outdated_envs_kernel + SensorBase._mark_envs_up_to_date()
  helper for sensors to opt out of the refetch.
* Each affected sensor's reset() now calls _mark_envs_up_to_date(mask)
  after zeroing _data, so subsequent data access returns those zeros
  rather than refetching the unstepped physics buffer.
* Simplify Newton ContactSensor.reset() to use the shared
  _resolve_indices_and_mask helper instead of its custom resolution.
* Add per-package changelog fragments (isaaclab / isaaclab_physx /
  isaaclab_newton).
Replace the SensorBase opt-out scaffolding from the previous attempt with
a kernel-level check: each step-dependent sensor's update kernel now
takes the sensor timestamp and early-returns for envs where it is still
0 (the existing reset_envs_kernel signal that no physics step has
occurred since the last reset). Reading the physics buffer for those
envs would inject pre-reset values; the kernel skip keeps the data that
the sensor's reset() populated.

This is a single added argument and a single conditional per affected
kernel — no shared kernel, helper method, or class attribute. Touches:

  PhysX:  update_net_forces_kernel, imu_update_kernel,
          pva_update_kernel, joint_wrench_split_kernel.
  Newton: copy_from_newton_kernel, imu_copy_kernel,
          pva_update_kernel, joint_wrench_to_incoming_joint_frame_kernel.

FrameTransformer / RayCaster / Camera kernels are untouched so they
continue to refetch right after reset (the path PR isaac-sim#1276 set up).
@kellyguo11 kellyguo11 merged commit b58d9e0 into isaac-sim:develop May 27, 2026
39 of 40 checks passed
kellyguo11 added a commit that referenced this pull request May 28, 2026
… locomanip quaternion, deformable demo, IK, benchmark scripts (#5816)

# Description

Cherry pick following PRs from develop:

- #5779 
- #5760
- #5791
- #5810 
- #5811
- #5812 
- #5754 
- #5802 
- #5803 
- #5782
- #5804 
- #5744 
- #5775 
- #5784

---------

Signed-off-by: Kelly Guo <kellyg@nvidia.com>
Co-authored-by: John <jaybdub@users.noreply.github.com>
Co-authored-by: myurasov-nv <168484206+myurasov-nv@users.noreply.github.com>
Co-authored-by: Antoine RICHARD <antoiner@nvidia.com>
Co-authored-by: Mike Yan Michelis <46975745+mmichelis@users.noreply.github.com>
Co-authored-by: hujc <jichuanh@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

asset New asset feature or request bug Something isn't working documentation Improvements or additions to documentation infrastructure isaac-lab Related to Isaac Lab team isaac-mimic Related to Isaac Mimic team isaac-sim Related to Isaac Sim team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug Report] Stale contact sensor data after reset

2 participants