Skip to content

[Tests] Consolidate overlapping isaaclab_newton tests - #7603

Open
StafaH wants to merge 2 commits into
isaac-sim:developfrom
StafaH:test/optimize-isaaclab-newton-tests-2
Open

[Tests] Consolidate overlapping isaaclab_newton tests#7603
StafaH wants to merge 2 commits into
isaac-sim:developfrom
StafaH:test/optimize-isaaclab-newton-tests-2

Conversation

@StafaH

@StafaH StafaH commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Description

Second pass over the isaaclab_newton test suite after #7306. The goal is the same: cut CI runtime by removing tests that produce no verdict and by collapsing groups of tests that rebuild the same simulation to check one accessor each, while keeping every distinct behavioral check.

Removed (no verdict produced)

  • test_articulation.py: test_initialization_hand_with_tendons and test_spatial_tendons always skipped (shadow hand / spatial tendons are unsupported on Newton); the shadow_hand fixture branch and its sim config go with them. test_setting_gains_from_cfg_dict was byte-for-byte the same check as test_setting_gains_from_cfg.
  • test_rigid_object.py: four permanently skipped tests (kinematic bodies, no-friction, static friction, restitution) and the material helper only they used. test_rigid_object_collection.py: the permanently skipped kinematic test.
  • test_contact_sensor.py: the newton_contacts cases of the force-matrix, contact-point and finger-isolation tests were non-strict xfails. They ran the full 240-step settle (and the Allegro drop with flaky reruns) and could neither fail nor pass the build. They are now skip with the same reason, so the known gap stays visible in the report.

Consolidated (same assertions, fewer simulations)

  • Dynamics accessor shape contracts: six tests (J/M/g × fixed/floating base) each spun up their own sim per batch size. One test_dynamics_accessor_shapes reads all three accessors per (asset, batch) and keeps the positive-diagonal mass-matrix check. 12 sims → 4.
  • FK-refresh after a manual joint write: three tests → one test_dynamics_accessors_refresh_after_manual_joint_write that checks J, M and g on both assets. Gravity stays on so the g(q) assertion is not vacuous.
  • Config-validation failures (out-of-range default joint pos/vel, valid/invalid explicit articulation root) are device independent; each pair is now one parametrized CPU test.
  • External-force tests reran an identical reset+force cycle five times; two cycles still cover the alternating local/global variants and the re-application after reset.
  • PVA/IMU: initialization + shape checks merged; the at-rest gravity and velocity checks shared the same 200/500-step settle and are now read from one scene. Free-fall acceleration and growing-speed checks share one scene.
  • Joint wrench: partial and full reset checks run on the same 4-env scene.
  • Frame view (test_views_xform_prim_newton.py): body/shape-path rejection, world-attached read/write, and clone-plan vs post-reset resolution each collapsed into one scene.
  • Newton schemas: each authored/unset pair now authors both prims in one stage instead of two SimulationContexts.
  • Ray-cast sensor: the two FK-refresh-after-carrier-write checks run on one scene.
  • Frame transformer: 100 steps with a reset every 25 → 50 steps (two reset cycles); the per-step assertions are unchanged.
  • test_site_injection.py: two tests made the identical call and split the assertions.

Before and after measurement

Per-file wall time from the CI-style per-file runner on the same workstation (RTX PRO 6000), warm Warp cache, changed files only:

File Cases before Cases after Before After
assets/test_articulation.py 194 + 4 skipped 177 298.6 s 232.8 s
sensors/test_contact_sensor.py 67 + 8 xpassed 67 + 8 skipped 87.8 s 64.9 s
assets/test_rigid_object_collection.py 54 + 8 skipped 53 52.4 s 48.8 s
assets/test_rigid_object.py 58 + 16 skipped 52 48.8 s 47.1 s
sim/test_views_xform_prim_newton.py 60 54 44.6 s 42.2 s
sensors/test_frame_transformer.py 9 9 23.5 s 21.3 s
sensors/test_newton_raycast_sensor.py 18 16 20.6 s 18.9 s
sensors/test_joint_wrench_sensor.py 10 9 19.1 s 16.9 s
sensors/test_pva.py 10 6 17.0 s 14.1 s
sensors/test_imu.py 7 5 14.7 s 13.1 s
sim/test_newton_schemas.py 20 14 7.7 s 6.7 s
sensors/test_site_injection.py 27 26 5.3 s 5.4 s
Total (changed files) 640 s 532 s

The whole isaaclab_newton suite measured 16 min 20 s before the change on this machine; the changed files account for the full 108 s saved (about 11%). The largest single win is test_articulation.py, which is 30% of the suite.

Type of change

  • Test and CI performance improvement (non-breaking)

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

Merge the dynamics accessor shape and FK-refresh checks into one sim per
asset, fold paired sensor and schema checks that rebuilt the same scene,
remove permanently skipped tests, and skip the non-strict xfail contact
sensor cases that ran to completion without producing a verdict.
@StafaH
StafaH requested a review from a team September 5, 2026 15:05
@github-actions github-actions Bot added the isaac-lab Related to Isaac Lab team label Sep 5, 2026
@greptile-apps

greptile-apps Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR reduces the Newton test-suite runtime by removing permanently skipped cases and consolidating tests that previously created duplicate simulation scenes.

  • Combines articulation dynamics shape and FK-refresh checks.
  • Shares simulation scenes across sensor, schema, and frame-view assertions.
  • Reduces repeated reset/force and frame-transformer cycles.
  • Converts non-strict unsupported contact cases to explicit skips.
  • One consolidation weakens independent FK-refresh regression coverage because the accessors share refresh state.

Confidence Score: 4/5

The PR appears safe to merge, with a non-blocking test-quality issue in the consolidated articulation refresh test.

The runtime optimizations generally preserve the tested behavior, but the first Jacobian read refreshes shared FK state and prevents later assertions from detecting accessor-specific refresh regressions.

Files Needing Attention: source/isaaclab_newton/test/assets/test_articulation.py

Important Files Changed

Filename Overview
source/isaaclab_newton/test/assets/test_articulation.py Consolidates validation, dynamics-shape, force-cycle, and FK-refresh tests; the refresh consolidation masks accessor-specific refresh regressions.
source/isaaclab_newton/test/assets/test_rigid_object.py Removes permanently skipped material and kinematic tests and consolidates device-independent prim validation.
source/isaaclab_newton/test/sensors/test_contact_sensor.py Converts unsupported non-strict Newton-contact xfails into explicit skips.
source/isaaclab_newton/test/sensors/test_pva.py Shares scenes for initialization, settled-state, and free-fall assertions while retaining their behavioral checks.
source/isaaclab_newton/test/sim/test_newton_schemas.py Consolidates authored and unset schema cases onto distinct prims within shared stages.
source/isaaclab_newton/test/sim/test_views_xform_prim_newton.py Consolidates frame-path rejection, resolution, and world-pose round-trip checks into fewer scenes.

Reviews (1): Last reviewed commit: "Consolidate overlapping isaaclab_newton ..." | Re-trigger Greptile

Comment on lines +4003 to +4013
assert not torch.allclose(J_link_0, articulation.data.body_link_jacobian_w.torch, atol=1e-3), (
"body_link_jacobian_w did not change after manual joint write; FK trigger likely missing"
)
assert not torch.allclose(J_com_0, J_com_1, atol=1e-3), (
"body_com_jacobian_w did not change after manual joint writeFK trigger likely missing before eval_jacobian."
assert not torch.allclose(J_com_0, articulation.data.body_com_jacobian_w.torch, atol=1e-3), (
"body_com_jacobian_w did not change after manual joint write; FK trigger likely missing"
)


@pytest.mark.parametrize("num_articulations", [1])
@pytest.mark.parametrize("device", test_devices(DeviceScope.CUDA))
@pytest.mark.parametrize("articulation_type", ["panda", "anymal"])
@pytest.mark.parametrize("gravity_enabled", [False])
@pytest.mark.isaacsim_ci
def test_mass_matrix_refreshes_after_manual_joint_write(
sim, num_articulations, device, articulation_type, gravity_enabled
):
"""After ``write_joint_position_to_sim_index`` (no sim step), the mass matrix read
must reflect the new joint state.

The mass matrix depends on ``q`` (joint positions) through the body-spatial-inertia
transformation in eval_mass_matrix's ``compute_body_spatial_inertia`` step, which
reads ``state.body_q``. Same FK-staleness pattern as the Jacobian.
"""
articulation_cfg = generate_articulation_cfg(articulation_type=articulation_type)
articulation, _ = generate_articulation(articulation_cfg, num_articulations, device=device)
sim.reset()
sim.step()
articulation.update(sim.cfg.dt)

M_0 = articulation.data.mass_matrix.torch.clone()
q_target = articulation.data.joint_pos.torch.clone() + 0.5
env_ids = wp.array([0], dtype=wp.int32, device=device)
articulation.write_joint_position_to_sim_index(position=q_target, env_ids=env_ids)
M_1 = articulation.data.mass_matrix.torch.clone()

assert not torch.allclose(M_0, M_1, atol=1e-3), (
"mass_matrix did not change after manual joint write — "
"FK trigger likely missing before eval_mass_matrix (compute_body_spatial_inertia "
"reads stale state.body_q)."
assert not torch.allclose(M_0, articulation.data.mass_matrix.torch, atol=1e-3), (
"mass_matrix did not change after manual joint write; FK trigger likely missing"
)


@pytest.mark.parametrize("num_articulations", [1])
@pytest.mark.parametrize("device", test_devices(DeviceScope.CUDA))
@pytest.mark.parametrize("articulation_type", ["panda"])
@pytest.mark.isaacsim_ci
def test_gravity_compensation_refreshes_after_manual_joint_write(sim, num_articulations, device, articulation_type):
"""After ``write_joint_position_to_sim_index`` (no sim step), the gravity
compensation read must reflect the new joint state.

``g(q)`` depends on ``q`` through the RNEA pass in ``eval_inverse_dynamics_passive``,
which reads ``state.body_q``. Same FK-staleness pattern as the Jacobian and
the mass matrix. Gravity stays enabled (the default) — with gravity off,
``g(q)`` is identically zero and the assert would be vacuous.
"""
articulation_cfg = generate_articulation_cfg(articulation_type=articulation_type)
articulation, _ = generate_articulation(articulation_cfg, num_articulations, device=device)
sim.reset()
sim.step()
articulation.update(sim.cfg.dt)

g_0 = articulation.data.gravity_compensation_forces.torch.clone()
q_target = articulation.data.joint_pos.torch.clone() + 0.5
env_ids = wp.array([0], dtype=wp.int32, device=device)
articulation.write_joint_position_to_sim_index(position=q_target, env_ids=env_ids)
g_1 = articulation.data.gravity_compensation_forces.torch.clone()

assert not torch.allclose(g_0, g_1, atol=1e-3), (
"gravity_compensation_forces did not change after manual joint write — "
"FK trigger likely missing before eval_inverse_dynamics_passive."
assert not torch.allclose(g_0, articulation.data.gravity_compensation_forces.torch, atol=1e-3), (
"gravity_compensation_forces did not change after manual joint write; FK trigger likely missing"

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.

P2 Shared refresh weakens coverage

The test reads body_link_jacobian_w first, which refreshes the FK state shared by all four accessors. The later body_com_jacobian_w, mass_matrix, and gravity_compensation_forces checks therefore run with FK already refreshed and would still pass if their own refresh calls were removed. Re-invalidate FK before each check or parameterize the test so each accessor is the first read after a joint write.

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

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.

Isaac Lab Review Bot

The test-only consolidation largely preserves existing coverage and reduces repeated simulation setup, but the merged dynamics-accessor refresh test no longer independently verifies FK invalidation for three accessors.

  • Design and architecture: Grouping related checks into shared scenes is appropriate for reducing Newton test runtime. However, FK-refresh behavior is stateful, so sharing one stale-to-fresh transition across multiple accessor assertions weakens the intended regression coverage.
  • API: No production or public API is changed. The test helper cleanup is internally consistent, and the .skip changelog fragment appropriately records a non-user-visible test-only change.
  • Implementation: In test_dynamics_accessors_refresh_after_manual_joint_write, one joint write marks FK stale, but the first body_link_jacobian_w read refreshes the shared FK state. Subsequent reads of body_com_jacobian_w, mass_matrix, and gravity_compensation_forces therefore cannot detect removal of their own FK-refresh triggers. Re-mark FK stale, such as by repeating the joint write, before each accessor assertion.

Minor fixes needed. Posted 1 actionable finding inline.

Automated review; human maintainers own approval decisions.

"mass_matrix did not change after manual joint write — "
"FK trigger likely missing before eval_mass_matrix (compute_body_spatial_inertia "
"reads stale state.body_q)."
assert not torch.allclose(M_0, articulation.data.mass_matrix.torch, atol=1e-3), (

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.

🟡 Warning · Implementation — Chained reads void three FK-refresh assertions

All four accessors are read after one joint write. As the test's own comment states, the write marks FK stale via a single _fk_timestamp, so the first read (body_link_jacobian_w) runs forward() and refreshes body_q. The later COM-Jacobian, mass-matrix and gravity reads then see fresh poses even if their own FK trigger were removed — the exact regressions the docstring claims to catch. Re-write the joint state before each accessor read.

…aaclab-newton-tests-2

# Conflicts:
#	source/isaaclab_newton/test/assets/test_articulation.py
@StafaH

StafaH commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

run-ci

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant