Skip to content

Add example tests#836

Merged
eric-heiden merged 52 commits into
newton-physics:mainfrom
eric-heiden:test-examples
Oct 2, 2025
Merged

Add example tests#836
eric-heiden merged 52 commits into
newton-physics:mainfrom
eric-heiden:test-examples

Conversation

@eric-heiden

@eric-heiden eric-heiden commented Sep 26, 2025

Copy link
Copy Markdown
Member

Description

  • Implemented a test() function for various examples and added some helper methods to assist with verifying the state of bodies and particles
  • Each example is tested for NaN values in its Model, State, Control, and Contacts structures
  • Each example now executes the test function and above mentioned generic NaN check by passing --test to its CLI args
  • Some examples were fixed, or updated to use some new API functions like builder.replicate()
  • Some examples now only get tested on CUDA to save resources since the CPU version does not add new meaningful test coverage compared to similar examples/sim features we already test on CPU
  • Note that the 2 benchmark failures are due to the slight change in API where newton.examples.run(example, args) now requires an additional args input that wasn't there before

Newton Migration Guide

Please ensure the migration guide for warp.sim users is up-to-date with the changes made in this PR.

  • The migration guide in docs/migration.rst is up-to date

Before your PR is "Ready for review"

  • Necessary tests have been added and new examples are tested (see newton/tests/test_examples.py)
  • Documentation is up-to-date
  • Code passes formatting and linting checks with pre-commit run -a

Summary by CodeRabbit

  • New Features

    • Added public vector helpers for elementwise closeness and in-bounds checks.
    • Examples now include built-in state tests (body/particle), test mode with NaN/non-finite checks, and loss/cost-history & gradient validation in diff‑sim examples.
  • Tests

    • Expanded test utilities, example test registrations, per-device test options, and richer example validations.
  • Chores

    • Runner now accepts CLI args; examples and benchmarks updated to forward args.

Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
@coderabbitai

coderabbitai Bot commented Sep 26, 2025

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds two Warp-agnostic vector helpers (vec_allclose, vec_inside_limits); introduces example-level testing (CLI --test, test_body_state/test_particle_state) with NaN/non-finite checks; updates many examples to forward CLI args into run(example, args) and to include concrete test implementations; extends test helpers and example registrations.

Changes

Cohort / File(s) Summary
Vector utilities API
newton/_src/utils/__init__.py, newton/utils.py
Add vec_allclose(a,b,rtol=...,atol=...) and vec_inside_limits(a,lower,upper); export both via module __all__.
Examples runner & testing utilities
newton/examples/__init__.py
Add --test CLI flag; introduce test_body_state and test_particle_state; run pre-loop NaN/non-finite checks (find_nan_members/find_nonfinite_members); change runner signature/call sites to run(example, args).
Example scripts — tests & args propagation
newton/examples/... (many files, e.g. basic/*, cloth/*, diffsim/*, mpm/*, robot/*, ik/*, selection/*, sensors/*, viewer/*, replay/*)
Update all example entry points to call newton.examples.run(example, args); replace many no-op test() methods with concrete checks using new test helpers; per-example additions (loss_history, gradient checks, solver/init tweaks, per-body keys/quaternions, etc.).
Test helpers & harness
newton/tests/unittest_utils.py, newton/tests/test_examples.py
Add helpers most, find_nan_members, find_nonfinite_members; extend test registration/option building/merging and add_example_test with test_suffix; update many test registrations/options and device-specific merges.
Benchmarks & misc wiring
asv/benchmarks/simulation/bench_cloth.py
Call newton.examples.run with explicit args=None where used.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as CLI
  participant Runner as newton.examples.run
  participant Tests as newton.tests.unittest_utils
  participant Example as Example
  participant Kernel as test_body_state/test_particle_state

  User->>Runner: run(example, args)
  Runner->>Runner: parse args / configure
  alt --test mode
    Runner->>Tests: find_nan_members(state_0,state_1,model,control,contacts)
    Tests-->>Runner: list of offending members
    alt offending members found
      Runner->>User: raise descriptive ValueError (bad members)
    else
      Runner->>Example: Example.test()
      Example->>Kernel: run per-entity tests (test_body_state/test_particle_state)
      Kernel-->>Example: per-entity pass/fail
      alt failures
        Example->>Runner: raise ValueError with failing indices/names
      end
    end
  else normal mode
    Runner->>Example: enter simulation/render loop
  end
  Runner-->>User: exit
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • mmacklin

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. You can run `@coderabbitai generate docstrings` to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit's high-level summary is enabled.
Title Check ✅ Passed The title “Add example tests” succinctly and accurately summarizes the primary purpose of this changeset, which is to introduce testing infrastructure and test implementations for examples across the repository.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Signed-off-by: Eric Heiden <eric-heiden@outlook.com>

@coderabbitai coderabbitai 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.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
newton/tests/test_examples.py (1)

1-1: Disable viewer for cloth.example_cloth_bending test
In newton/tests/test_examples.py, update the add_example_test call for cloth.example_cloth_bending to use_viewer=False (headless CI environments cannot launch the viewer).

🧹 Nitpick comments (14)
newton/examples/basic/example_basic_urdf.py (1)

128-144: Fix unused lambda parameters in test functions.

The lambda functions in your test cases have unused parameters that static analysis tools are flagging. This is a common pattern in callback functions where not all parameters are always used.

Apply this diff to fix the unused parameter warnings:

-            lambda q, qd: max(abs(qd)) < 0.1,
+            lambda q, qd: max(abs(qd)) < 0.1,
-            lambda q, qd: wp.abs(q[2] - 0.48) < 0.01,
+            lambda _, qd: wp.abs(_[2] - 0.48) < 0.01,

Or alternatively, you can prefix unused parameters with underscore:

-            lambda q, qd: max(abs(qd)) < 0.1,
+            lambda _q, qd: max(abs(qd)) < 0.1,
-            lambda q, qd: wp.abs(q[2] - 0.48) < 0.01,
+            lambda q, _qd: wp.abs(q[2] - 0.48) < 0.01,
newton/examples/basic/example_basic_pendulum.py (1)

125-148: Enhance test robustness and fix unused lambda parameter.

The test logic is comprehensive but could be improved for clarity and the unused parameter should be addressed.

Apply this diff to fix the unused parameter and improve readability:

-            lambda q, qd: abs(q[0]) < 1e-5 and abs(q[1]) < 1.0 and q[2] < 5.0 and q[2] > 0.0,
+            lambda q, _qd: abs(q[0]) < 1e-5 and abs(q[1]) < 1.0 and q[2] < 5.0 and q[2] > 0.0,

Consider splitting the position check into more granular tests for better error reporting:

        newton.examples.test_body_state(
            self.model,
            self.state_0,
-            "pendulum links in correct area",
-            lambda q, _qd: abs(q[0]) < 1e-5 and abs(q[1]) < 1.0 and q[2] < 5.0 and q[2] > 0.0,
+            "pendulum links positioned correctly",
+            lambda q, _qd: abs(q[0]) < 1e-5 and abs(q[1]) < 1.0 and 0.0 < q[2] < 5.0,
            [0, 1],
        )
newton/examples/robot/example_robot_cartpole.py (4)

113-120: Use tolerance for comparisons and silence unused arg.

Exact equality on floats (q[2] == 0.0) is brittle in Warp; prefer a small tolerance. Also, rename unused qd to _.

-        newton.examples.test_body_state(
+        newton.examples.test_body_state(
             self.model,
             self.state_0,
             "cart is at ground level and has correct orientation",
-            lambda q, qd: q[2] == 0.0 and newton.utils.vec_allclose(q.q, wp.quat_identity()),
+            lambda q, _: wp.abs(q[2]) <= 1.0e-4 and newton.utils.vec_allclose(q.q, wp.quat_identity()),
             indices=[i * num_bodies_per_env for i in range(self.num_envs)],
         )

Please confirm q[2] is indeed the ground-axis for this example (z). If y is up, adjust accordingly. Based on learnings.


131-142: Apply Warp ops and tolerances to pole1 test.

Same reasons as above; replace Python abs and exact zero.

-            lambda q, qd: qd[0] == 0.0
-            and abs(qd[1]) > 0.05
-            and qd[2] == 0.0
-            and abs(qd[3]) > 0.3
-            and qd[4] == 0.0
-            and qd[5] == 0.0,
+            lambda _, qd: wp.abs(qd[0]) <= 1.0e-6
+            and wp.abs(qd[1]) > 0.05
+            and wp.abs(qd[2]) <= 1.0e-6
+            and wp.abs(qd[3]) > 0.3
+            and wp.abs(qd[4]) <= 1.0e-6
+            and wp.abs(qd[5]) <= 1.0e-6,

Confirm index semantics (linear vs angular ordering) to ensure each constraint targets the intended component.


143-154: Apply Warp ops and tolerances to pole2 test.

Consistent with prior tests; replace Python abs and exact zero.

-            lambda q, qd: qd[0] == 0.0
-            and abs(qd[1]) > 0.05
-            and abs(qd[2]) > 0.05
-            and abs(qd[3]) > 0.2
-            and qd[4] == 0.0
-            and qd[5] == 0.0,
+            lambda _, qd: wp.abs(qd[0]) <= 1.0e-6
+            and wp.abs(qd[1]) > 0.05
+            and wp.abs(qd[2]) > 0.05
+            and wp.abs(qd[3]) > 0.2
+            and wp.abs(qd[4]) <= 1.0e-6
+            and wp.abs(qd[5]) <= 1.0e-6,

Same note about spatial vector ordering applies.


155-179: Silence unused-arg lint in cross-env comparisons.

Rename q to _ in lambdas; no behavior change.

-            lambda q, qd: newton.utils.vec_allclose(qd, env0_cart_vel),
+            lambda _, qd: newton.utils.vec_allclose(qd, env0_cart_vel),
...
-            lambda q, qd: newton.utils.vec_allclose(qd, env0_pole1_vel),
+            lambda _, qd: newton.utils.vec_allclose(qd, env0_pole1_vel),
...
-            lambda q, qd: newton.utils.vec_allclose(qd, env0_pole2_vel),
+            lambda _, qd: newton.utils.vec_allclose(qd, env0_pole2_vel),
newton/examples/cloth/example_cloth_hanging.py (1)

187-201: Silence unused-arg lint and prefer Warp ops in tests.

Rename unused lambda args to _ to satisfy Ruff ARG005. Current comparisons are fine otherwise.

-            newton.examples.test_particle_state(
-                self.state_0,
-                "particles are above the ground",
-                lambda q, qd: q[2] > 0.0,
-            )
+            newton.examples.test_particle_state(
+                self.state_0,
+                "particles are above the ground",
+                lambda q, _: q[2] > 0.0,
+            )
...
-            newton.examples.test_particle_state(
-                self.state_0,
-                "particles are within a reasonable volume",
-                lambda q, qd: newton.utils.vec_inside_limits(q, wp.vec3(min_x, -4.0, -1.8), wp.vec3(0.0, 7.0, 4.0)),
-            )
+            newton.examples.test_particle_state(
+                self.state_0,
+                "particles are within a reasonable volume",
+                lambda q, _: newton.utils.vec_inside_limits(q, wp.vec3(min_x, -4.0, -1.8), wp.vec3(0.0, 7.0, 4.0)),
+            )
newton/_src/utils/__init__.py (1)

199-219: Vector utils are Warp-safe and broadly reusable.

vec_allclose and vec_inside_limits use wp.static(len(a)) and wp.abs, making them suitable within Warp kernels and create_warp_function contexts.

Optional: add a helper for sup-norm to avoid ad hoc patterns like max(abs(v)) in tests:

  • @wp.func def vec_max_abs(a): return leaky_max(leaky_max(wp.abs(a[0]), wp.abs(a[1])), wp.abs(a[2])) (extend to 6D if needed).
newton/examples/cloth/example_cloth_franka.py (1)

42-48: Remove unused local allclose (dead code).

This duplicates newton.utils.vec_allclose and isn’t used.

Apply outside the changed hunk:

-def allclose(a: wp.vec3, b: wp.vec3, rtol=1e-5, atol=1e-8):
-    return (
-        wp.abs(a[0] - b[0]) <= (atol + rtol * wp.abs(b[0]))
-        and wp.abs(a[1] - b[1]) <= (atol + rtol * wp.abs(b[1]))
-        and wp.abs(a[2] - b[2]) <= (atol + rtol * wp.abs(b[2]))
-    )
newton/tests/test_examples.py (2)

27-27: Add import of importlib to the imports section.

The import statement is correctly placed but should be moved to the standard imports section at the top of the file for better organization and consistency with Python conventions.


91-91: Minor: Consider using a custom exception class.

While the current approach works, consider creating a custom exception class for better error categorization and handling.

Based on static analysis hints

newton/examples/basic/example_basic_shapes.py (1)

143-143: Consider using the velocity parameter in test functions.

The lambda functions in the test cases accept a qd parameter (velocity) but don't use it. While this is functionally correct, you might consider either using the velocity in the tests or explicitly ignoring it to improve code clarity.

Based on static analysis hints

If velocity isn't needed, you could make it explicit:

-            lambda q, qd: newton.utils.vec_allclose(q, sphere_q, atol=1e-4),
+            lambda q, _: newton.utils.vec_allclose(q, sphere_q, atol=1e-4),

Also applies to: 151-151, 159-159, 167-167

newton/examples/__init__.py (2)

384-384: Update all export list.

The __all__ list should also include test_particle_state since it's a public utility function that users might want to import directly.

Apply this diff:

-__all__ = ["create_parser", "init", "run", "test_body_state"]
+__all__ = ["create_parser", "init", "run", "test_body_state", "test_particle_state"]

103-103: Consider custom exception classes for better error categorization.

While the current string-based error messages are functional, consider creating custom exception classes for better error handling and categorization in testing frameworks.

Based on static analysis hints

Also applies to: 158-158, 183-183, 187-187, 191-191, 195-195, 199-199

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4949d3c and 90c32bf.

📒 Files selected for processing (40)
  • newton/_src/utils/__init__.py (3 hunks)
  • newton/examples/__init__.py (5 hunks)
  • newton/examples/__main__.py (1 hunks)
  • newton/examples/basic/example_basic_joints.py (5 hunks)
  • newton/examples/basic/example_basic_pendulum.py (3 hunks)
  • newton/examples/basic/example_basic_shapes.py (5 hunks)
  • newton/examples/basic/example_basic_urdf.py (3 hunks)
  • newton/examples/basic/example_basic_viewer.py (1 hunks)
  • newton/examples/cloth/example_cloth_bending.py (2 hunks)
  • newton/examples/cloth/example_cloth_franka.py (3 hunks)
  • newton/examples/cloth/example_cloth_hanging.py (4 hunks)
  • newton/examples/cloth/example_cloth_style3d.py (2 hunks)
  • newton/examples/cloth/example_cloth_twist.py (3 hunks)
  • newton/examples/diffsim/example_diffsim_ball.py (1 hunks)
  • newton/examples/diffsim/example_diffsim_cloth.py (1 hunks)
  • newton/examples/diffsim/example_diffsim_drone.py (1 hunks)
  • newton/examples/diffsim/example_diffsim_soft_body.py (1 hunks)
  • newton/examples/diffsim/example_diffsim_spring_cage.py (1 hunks)
  • newton/examples/example_replay_viewer.py (1 hunks)
  • newton/examples/ik/example_ik_franka.py (1 hunks)
  • newton/examples/ik/example_ik_h1.py (1 hunks)
  • newton/examples/mpm/example_mpm_anymal.py (1 hunks)
  • newton/examples/mpm/example_mpm_grain_rendering.py (1 hunks)
  • newton/examples/mpm/example_mpm_granular.py (1 hunks)
  • newton/examples/mpm/example_mpm_multi_material.py (1 hunks)
  • newton/examples/robot/example_robot_allegro_hand.py (1 hunks)
  • newton/examples/robot/example_robot_anymal_c_walk.py (1 hunks)
  • newton/examples/robot/example_robot_anymal_d.py (2 hunks)
  • newton/examples/robot/example_robot_cartpole.py (2 hunks)
  • newton/examples/robot/example_robot_g1.py (2 hunks)
  • newton/examples/robot/example_robot_h1.py (2 hunks)
  • newton/examples/robot/example_robot_humanoid.py (1 hunks)
  • newton/examples/robot/example_robot_policy.py (1 hunks)
  • newton/examples/robot/example_robot_ur10.py (1 hunks)
  • newton/examples/selection/example_selection_articulations.py (1 hunks)
  • newton/examples/selection/example_selection_cartpole.py (1 hunks)
  • newton/examples/selection/example_selection_materials.py (1 hunks)
  • newton/examples/sensors/example_sensor_contact.py (1 hunks)
  • newton/tests/test_examples.py (9 hunks)
  • newton/utils.py (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-08-25T21:41:45.795Z
Learnt from: dylanturpin
PR: newton-physics/newton#634
File: newton/tests/test_examples.py:329-333
Timestamp: 2025-08-25T21:41:45.795Z
Learning: Newton examples use a centralized CLI argument parsing system in newton/examples/__init__.py. The create_parser() function defines common arguments like --device, --viewer, --output-path, and --num-frames, while init(parser) creates viewers based on parsed arguments. Individual example scripts don't need to define these flags themselves - they inherit them from the centralized system via the example_map and runpy execution.

Applied to files:

  • newton/examples/sensors/example_sensor_contact.py
  • newton/examples/robot/example_robot_policy.py
  • newton/examples/example_replay_viewer.py
  • newton/examples/mpm/example_mpm_granular.py
  • newton/examples/diffsim/example_diffsim_cloth.py
  • newton/examples/selection/example_selection_cartpole.py
  • newton/examples/diffsim/example_diffsim_drone.py
  • newton/examples/selection/example_selection_materials.py
  • newton/examples/mpm/example_mpm_multi_material.py
  • newton/examples/robot/example_robot_allegro_hand.py
  • newton/examples/mpm/example_mpm_anymal.py
  • newton/examples/diffsim/example_diffsim_ball.py
  • newton/examples/robot/example_robot_h1.py
  • newton/examples/robot/example_robot_humanoid.py
  • newton/examples/diffsim/example_diffsim_soft_body.py
  • newton/examples/cloth/example_cloth_style3d.py
  • newton/examples/robot/example_robot_anymal_d.py
  • newton/examples/robot/example_robot_cartpole.py
  • newton/examples/basic/example_basic_joints.py
  • newton/examples/mpm/example_mpm_grain_rendering.py
  • newton/examples/cloth/example_cloth_bending.py
  • newton/examples/ik/example_ik_franka.py
  • newton/examples/selection/example_selection_articulations.py
  • newton/examples/basic/example_basic_viewer.py
  • newton/examples/cloth/example_cloth_twist.py
  • newton/examples/__main__.py
  • newton/examples/robot/example_robot_ur10.py
  • newton/examples/basic/example_basic_pendulum.py
  • newton/examples/robot/example_robot_g1.py
  • newton/examples/ik/example_ik_h1.py
  • newton/examples/basic/example_basic_urdf.py
  • newton/examples/cloth/example_cloth_franka.py
  • newton/examples/__init__.py
  • newton/examples/basic/example_basic_shapes.py
  • newton/examples/diffsim/example_diffsim_spring_cage.py
📚 Learning: 2025-08-27T19:05:44.697Z
Learnt from: Milad-Rakhsha-NV
PR: newton-physics/newton#535
File: newton/tests/test_examples.py:320-414
Timestamp: 2025-08-27T19:05:44.697Z
Learning: In newton/examples/__init__.py, the robot policy example is registered with the key "robot_policy" (not "robot.example_robot_policy"), so tests should reference it as name="robot_policy".

Applied to files:

  • newton/examples/robot/example_robot_policy.py
  • newton/examples/robot/example_robot_h1.py
  • newton/examples/robot/example_robot_anymal_d.py
  • newton/examples/robot/example_robot_ur10.py
  • newton/tests/test_examples.py
  • newton/examples/robot/example_robot_g1.py
📚 Learning: 2025-08-12T18:04:06.577Z
Learnt from: nvlukasz
PR: newton-physics/newton#519
File: newton/_src/solvers/featherstone/kernels.py:75-75
Timestamp: 2025-08-12T18:04:06.577Z
Learning: The Newton physics framework requires nightly Warp builds, which means compatibility concerns with older stable Warp versions (like missing functions such as wp.spatial_adjoint) are not relevant for this project.

Applied to files:

  • newton/examples/basic/example_basic_urdf.py
📚 Learning: 2025-08-12T05:17:34.423Z
Learnt from: shi-eric
PR: newton-physics/newton#521
File: newton/examples/example_cloth_hanging.py:36-36
Timestamp: 2025-08-12T05:17:34.423Z
Learning: The Newton migration guide (docs/migration.rst) is specifically for documenting how to migrate existing warp.sim functionality to Newton equivalents. New Newton-only features that didn't exist in warp.sim do not need migration documentation.

Applied to files:

  • newton/examples/basic/example_basic_urdf.py
🧬 Code graph analysis (36)
newton/examples/sensors/example_sensor_contact.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/robot/example_robot_policy.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/mpm/example_mpm_granular.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/diffsim/example_diffsim_cloth.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/selection/example_selection_cartpole.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/diffsim/example_diffsim_drone.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/selection/example_selection_materials.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/mpm/example_mpm_multi_material.py (1)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/robot/example_robot_allegro_hand.py (1)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/mpm/example_mpm_anymal.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/diffsim/example_diffsim_ball.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/robot/example_robot_h1.py (1)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/examples/robot/example_robot_humanoid.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/diffsim/example_diffsim_soft_body.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/cloth/example_cloth_style3d.py (2)
newton/examples/__init__.py (2)
  • test_particle_state (106-158)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/robot/example_robot_anymal_d.py (1)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/examples/robot/example_robot_cartpole.py (3)
newton/_src/sim/builder.py (1)
  • body_count (515-519)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_allclose (200-207)
newton/examples/basic/example_basic_joints.py (1)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/utils.py (1)
newton/_src/utils/__init__.py (2)
  • vec_allclose (200-207)
  • vec_inside_limits (211-218)
newton/examples/mpm/example_mpm_grain_rendering.py (1)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/cloth/example_cloth_bending.py (2)
newton/examples/__init__.py (2)
  • test_particle_state (106-158)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/ik/example_ik_franka.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/selection/example_selection_articulations.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/basic/example_basic_viewer.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/cloth/example_cloth_twist.py (2)
newton/examples/__init__.py (2)
  • test_particle_state (106-158)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/robot/example_robot_anymal_c_walk.py (2)
newton/examples/__init__.py (3)
  • test_body_state (49-103)
  • init (295-338)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_allclose (200-207)
newton/examples/robot/example_robot_ur10.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/basic/example_basic_pendulum.py (2)
newton/_src/sim/builder.py (1)
  • add_joint_revolute (1366-1448)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/examples/robot/example_robot_g1.py (1)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/examples/cloth/example_cloth_hanging.py (3)
newton/_src/sim/style3d/builder_style3d.py (1)
  • Style3DModelBuilder (38-698)
newton/examples/__init__.py (2)
  • test_particle_state (106-158)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/ik/example_ik_h1.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/basic/example_basic_urdf.py (2)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/_src/sim/builder.py (1)
  • body_count (515-519)
newton/examples/cloth/example_cloth_franka.py (2)
newton/examples/__init__.py (3)
  • test_particle_state (106-158)
  • test_body_state (49-103)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/__init__.py (4)
newton/_src/sim/state.py (1)
  • State (21-112)
newton/_src/sim/contacts.py (1)
  • Contacts (23-93)
newton/_src/sim/control.py (1)
  • Control (21-77)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/basic/example_basic_shapes.py (4)
newton/_src/sim/builder.py (5)
  • add_body (1179-1241)
  • add_shape_sphere (2522-2553)
  • add_shape_capsule (2594-2634)
  • add_shape_box (2555-2592)
  • add_shape_mesh (2721-2754)
newton/_src/solvers/xpbd/solver_xpbd.py (1)
  • SolverXPBD (40-660)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_allclose (200-207)
newton/examples/diffsim/example_diffsim_spring_cage.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
🪛 Ruff (0.13.1)
newton/examples/robot/example_robot_h1.py

129-129: Unused lambda argument: qd

(ARG005)


135-135: Unused lambda argument: q

(ARG005)

newton/examples/cloth/example_cloth_style3d.py

177-177: Unused lambda argument: qd

(ARG005)

newton/examples/robot/example_robot_anymal_d.py

146-146: Unused lambda argument: qd

(ARG005)


152-152: Unused lambda argument: q

(ARG005)

newton/examples/robot/example_robot_cartpole.py

118-118: Unused lambda argument: qd

(ARG005)


125-125: Unused lambda argument: q

(ARG005)


135-135: Unused lambda argument: q

(ARG005)


147-147: Unused lambda argument: q

(ARG005)


163-163: Unused lambda argument: q

(ARG005)


170-170: Unused lambda argument: q

(ARG005)


177-177: Unused lambda argument: q

(ARG005)

newton/examples/basic/example_basic_joints.py

204-204: Unused lambda argument: q

(ARG005)


211-211: Unused lambda argument: q

(ARG005)


218-218: Unused lambda argument: q

(ARG005)


225-225: Unused lambda argument: q

(ARG005)

newton/examples/cloth/example_cloth_bending.py

136-136: Unused lambda argument: q

(ARG005)


142-142: Unused lambda argument: qd

(ARG005)


148-148: Unused lambda argument: qd

(ARG005)

newton/examples/cloth/example_cloth_twist.py

296-296: Unused lambda argument: qd

(ARG005)


301-301: Unused lambda argument: q

(ARG005)

newton/examples/robot/example_robot_anymal_c_walk.py

236-236: Unused lambda argument: qd

(ARG005)


242-242: Unused lambda argument: q

(ARG005)

newton/examples/basic/example_basic_pendulum.py

131-131: Unused lambda argument: qd

(ARG005)

newton/tests/test_examples.py

91-91: Avoid specifying long messages outside the exception class

(TRY003)

newton/examples/robot/example_robot_g1.py

136-136: Unused lambda argument: qd

(ARG005)


142-142: Unused lambda argument: q

(ARG005)

newton/examples/cloth/example_cloth_hanging.py

193-193: Unused lambda argument: qd

(ARG005)


199-199: Unused lambda argument: qd

(ARG005)

newton/examples/basic/example_basic_urdf.py

133-133: Unused lambda argument: q

(ARG005)


141-141: Unused lambda argument: qd

(ARG005)

newton/examples/cloth/example_cloth_franka.py

559-559: Unused lambda argument: qd

(ARG005)


564-564: Unused lambda argument: q

(ARG005)


570-570: Unused lambda argument: q

(ARG005)

newton/examples/__init__.py

103-103: Avoid specifying long messages outside the exception class

(TRY003)


158-158: Avoid specifying long messages outside the exception class

(TRY003)


183-183: Avoid specifying long messages outside the exception class

(TRY003)


187-187: Avoid specifying long messages outside the exception class

(TRY003)


191-191: Avoid specifying long messages outside the exception class

(TRY003)


195-195: Avoid specifying long messages outside the exception class

(TRY003)


199-199: Avoid specifying long messages outside the exception class

(TRY003)

newton/examples/basic/example_basic_shapes.py

143-143: Unused lambda argument: qd

(ARG005)


151-151: Unused lambda argument: qd

(ARG005)


159-159: Unused lambda argument: qd

(ARG005)


167-167: Unused lambda argument: qd

(ARG005)

🪛 GitHub Actions: GPU Unit Tests on AWS EC2
newton/examples/cloth/example_cloth_bending.py

[error] 139-139: SyntaxError: '(' was never closed in warp lambda source while creating Warp function during test_particle_state execution.

newton/tests/test_examples.py

[error] 193-193: Test failed: assertion 1 != 0. Coverage run for 'newton.examples.cloth.example_cloth_bending' exited with code 1.

🪛 GitHub Actions: Pull Request
newton/examples/robot/example_robot_anymal_c_walk.py

[error] 26-26: ModuleNotFoundError: No module named 'torch' while importing example_robot_anymal_c_walk in tests/test_examples.py. This caused the test module 'robot.example_robot_anymal_c_walk' not found during test_examples execution.

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run GPU Benchmarks (Pull Request)
🔇 Additional comments (59)
newton/examples/diffsim/example_diffsim_spring_cage.py (1)

253-253: Pass args to runner: LGTM

Matches the updated run(example, args) API in newton.examples.

newton/examples/robot/example_robot_ur10.py (1)

218-218: Args forwarding: LGTM

Correctly updates to run(example, args).

newton/examples/diffsim/example_diffsim_cloth.py (1)

227-227: Args forwarding: LGTM

Consistent with the new runner signature.

newton/examples/robot/example_robot_anymal_d.py (1)

164-164: Args forwarding: LGTM

Runner call now matches run(example, args).

newton/examples/selection/example_selection_articulations.py (1)

301-301: Args forwarding: LGTM

Correctly updates to run(example, args).

newton/examples/basic/example_basic_viewer.py (1)

194-194: Args forwarding: LGTM

Consistent with newton.examples.run(example, args).

newton/examples/example_replay_viewer.py (1)

252-252: Args forwarding: LGTM

Matches the updated run API.

newton/examples/robot/example_robot_h1.py (1)

147-147: Args forwarding: LGTM

Updated to run(example, args).

newton/examples/robot/example_robot_g1.py (1)

132-143: Fix Warp test function so it actually runs.
The test callbacks get JIT-compiled into Warp kernels. Indexing a wp.transform (q[2]) and calling Python’s max(abs(qd)) are not Warp-compatible, so the kernel compilation will raise at runtime when args.test triggers example.test(). Use Warp utilities to read the translation and velocity norm.

         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "all bodies are above the ground",
-            lambda q, qd: q[2] > 0.0,
+            lambda q, qd: wp.transform_get_translation(q).z > 0.0,
         )
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "all body velocities are small",
-            lambda q, qd: max(abs(qd)) < 0.001,
+            lambda q, qd: wp.length(qd) < 0.001,
         )
⛔ Skipped due to learnings
Learnt from: nvlukasz
PR: newton-physics/newton#519
File: newton/_src/solvers/featherstone/kernels.py:75-75
Timestamp: 2025-08-12T18:04:06.577Z
Learning: The Newton physics framework requires nightly Warp builds, which means compatibility concerns with older stable Warp versions (like missing functions such as wp.spatial_adjoint) are not relevant for this project.
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/_src/sim/ik/ik_objectives.py:0-0
Timestamp: 2025-09-25T16:14:22.002Z
Learning: In NVIDIA Warp's Newton physics library, wp.transform supports direct numerical indexing (e.g., body_tf[0], body_tf[1], body_tf[2] for position and body_tf[3], body_tf[4], body_tf[5], body_tf[6] for quaternion components) to access its elements. This is the standard API used throughout the codebase.
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/_src/sim/ik/ik_objectives.py:0-0
Timestamp: 2025-09-25T16:14:22.002Z
Learning: wp.transform in NVIDIA Warp supports indexing using numerical indices (e.g., body_tf[0], body_tf[3], etc.) to access translation and rotation components. The indexing approach used in the Newton codebase is valid and compiles correctly.
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering, despite the general warp documentation suggesting copies are made by default.
newton/examples/diffsim/example_diffsim_drone.py (1)

821-821: LGTM! API update correctly implemented.

The invocation has been properly updated to pass the parsed arguments to the run function, aligning with the new run(example, args) signature.

newton/utils.py (1)

91-92: LGTM! New utility functions correctly exposed.

The vec_allclose and vec_inside_limits functions are properly imported and exported through the public API. These utilities provide essential vector comparison capabilities for state validation in testing.

Also applies to: 106-107

newton/examples/robot/example_robot_policy.py (1)

472-472: LGTM! API update correctly implemented.

The invocation has been properly updated to pass the parsed arguments to the run function, aligning with the new run(example, args) signature. Based on learnings from previous reviews, this robot policy example is correctly registered as "robot_policy" in the system.

newton/examples/basic/example_basic_urdf.py (2)

30-30: LGTM! Import addition is appropriate.

The import of warp as wp is correctly added to support the test functions that use wp module functionality.


164-164: LGTM! API update correctly implemented.

The invocation has been properly updated to pass the parsed arguments to the run function, aligning with the new run(example, args) signature.

newton/examples/diffsim/example_diffsim_soft_body.py (1)

377-377: LGTM! API update correctly implemented.

The invocation has been properly updated to pass the parsed arguments to the run function, aligning with the new run(example, args) signature.

newton/examples/basic/example_basic_joints.py (3)

87-88: LGTM! Initial joint angle configuration is correct.

Setting the revolute joint to π/2 radians provides a meaningful initial configuration for the joint demonstration.


137-151: LGTM! Ball joint configuration is properly implemented.

The addition of rigid body configuration with zero density for the kinematic sphere parent and the RPY quaternion initialization for the ball joint provide good demonstration of the ball joint capabilities.


243-243: LGTM! API update correctly implemented.

The invocation has been properly updated to pass the parsed arguments to the run function, aligning with the new run(example, args) signature.

newton/examples/basic/example_basic_pendulum.py (2)

59-65: LGTM! Pendulum orientation enhancement improves visualization.

The addition of the rotation quaternion to orient the pendulum sideways provides better visual presentation for viewers, making the pendulum motion more apparent.


164-164: LGTM! API update correctly implemented.

The invocation has been properly updated to pass the parsed arguments to the run function, aligning with the new run(example, args) signature.

newton/examples/robot/example_robot_anymal_c_walk.py (1)

231-246: Fix unused lambda parameters

-            lambda q, qd: q[2] > 0.2,
+            lambda q, _qd: q[2] > 0.2,
-            lambda q, qd: newton.utils.vec_allclose(
+            lambda _q, qd: newton.utils.vec_allclose(

Verify that the height threshold (0.2 m) and forward‐velocity expectation (≈1 m/s) align with the simulated gait before merging.

newton/examples/cloth/example_cloth_twist.py (1)

315-315: Run signature update looks good.

Forwarding args to run() matches the updated runner API.

newton/examples/robot/example_robot_cartpole.py (1)

189-189: Run signature update looks good.

Using run(example, args) aligns with the new runner API.

newton/examples/cloth/example_cloth_hanging.py (2)

62-64: Correct builder class for Style3D.

Switch to newton.Style3DModelBuilder() is appropriate for the style3d path.


235-235: Run signature update looks good.

Passing args to run() is consistent with the new API.

newton/_src/utils/__init__.py (1)

246-247: Export additions look correct.

Including vec_allclose and vec_inside_limits in __all__ is consistent with their use in examples.

newton/examples/cloth/example_cloth_franka.py (2)

24-24: Command comment update looks fine.

No issues.


583-583: Run signature update looks good.

Consistent with the new run(example, args) API.

newton/tests/test_examples.py (5)

87-91: LGTM: Module existence verification.

The runtime verification to ensure the test module exists is a good defensive programming practice. The ImportError handling provides clear error messages when a referenced example module is missing.


147-147: Add --test flag to example execution.

The command construction properly appends the --test flag, which aligns with the PR's objective to enable test mode for examples. This ensures examples can be invoked in test mode to run their validation routines.


234-240: LGTM: New basic shapes test added.

The addition of basic.example_basic_shapes test with appropriate frame count is well-structured and consistent with the existing pattern.


261-271: LGTM: Multiple test configurations for cloth hanging.

The addition of two test variants for cloth.example_cloth_hanging with different test suffixes ("vbd" and "style3d") and corresponding solver options provides good coverage of different solver backends.


314-314: Device assignment optimization for GPU-intensive examples.

Moving specific robot examples (anymal_c_walk, g1, h1) from test_devices to cuda_test_devices is a sensible optimization, as these examples likely require GPU acceleration for reasonable performance and may have PyTorch dependencies that benefit from CUDA.

Also applies to: 329-329, 336-336

newton/examples/basic/example_basic_shapes.py (5)

54-56: LGTM: Consistent body key assignments.

The addition of key parameters to add_body() calls provides meaningful identifiers for each body (sphere, capsule, box, mesh), which will be useful for debugging and the new test functionality. The implementation is consistent and follows a clear naming pattern.

Also applies to: 60-62, 70-70, 87-87


94-94: LGTM: XPBD solver configuration with explicit iterations.

The explicit iterations=10 parameter for the SolverXPBD constructor improves clarity and aligns with the updated API. This provides better control over solver convergence behavior.


103-103: LGTM: Updated documentation comment.

The comment correctly reflects that the forward kinematics step is required for maximal-coordinate solvers like XPBD, providing better context than the previous generic note.


138-169: LGTM: Comprehensive rest pose testing.

The test implementation effectively validates that bodies settle into expected rest positions after simulation. The tests cover all major shapes and use appropriate tolerance values. The bunny test reasonably checks for basic physics constraints (staying above ground, minimal drift) rather than exact positioning due to its complex geometry.


185-185: LGTM: Updated run signature.

The change to newton.examples.run(example, args) correctly passes the parsed arguments, enabling the new test functionality and other argument-driven behavior.

newton/examples/__init__.py (8)

17-17: LGTM: Import for Callable type annotation.

The import of Callable from collections.abc is appropriate for the new type annotations in the test functions.


37-46: LGTM: Non-finite value detection helper.

The _find_nonfinite function provides a robust way to detect problematic numerical values in Newton objects. The implementation correctly handles None objects and uses numpy's isfinite function for reliable detection.


49-103: LGTM: Comprehensive body state testing utility.

The test_body_state function provides a well-designed testing framework that:

  • Supports both Warp functions and Python callables via wp.utils.create_warp_function
  • Uses GPU kernels for efficient batch testing
  • Provides detailed error reporting with body keys
  • Handles optional indices for selective testing

The implementation is robust and will be valuable for example validation.


106-158: LGTM: Particle state testing utility.

The test_particle_state function mirrors the design of test_body_state but for particle systems. The implementation is consistent and provides appropriate error reporting, though it could benefit from particle identifiers similar to how body keys are used.


161-161: LGTM: Updated run function signature.

The change to accept both example and args parameters enables the new testing functionality and argument-driven behavior across examples.


173-174: LGTM: Example-specific test execution.

The conditional execution of example.test() when both args.test is enabled and the method exists provides a clean way for examples to implement custom validation logic.


178-199: LGTM: Generic finiteness validation.

The comprehensive validation of Newton objects (state_0, state_1, contacts, model, control) for non-finite values provides excellent runtime verification. This will help catch numerical issues early in the testing process.


285-290: LGTM: Test mode argument addition.

The addition of the --test flag with BooleanOptionalAction follows argparse best practices and integrates cleanly with the existing argument parser.

newton/examples/__main__.py (1)

3-14: License header matches our standard.
Template aligns with the rest of the repo’s Apache-2.0 headers.

newton/examples/robot/example_robot_humanoid.py (1)

127-127: Passing args into run keeps this example compatible.
This forwards the parsed CLI/test options so the updated runner can perform its validations.

newton/examples/mpm/example_mpm_anymal.py (1)

433-433: Runner invocation now matches the updated API.
args is propagated, so test-mode hooks and nonfinite checks will run as intended.

newton/examples/mpm/example_mpm_grain_rendering.py (1)

160-160: Args forwarding confirmed.
Keeps this grain-rendering example in sync with the new run(example, args) signature.

newton/examples/diffsim/example_diffsim_ball.py (1)

261-261: run call updated appropriately.
Ensures the diffsim example participates in the shared args/test flow.

newton/examples/selection/example_selection_cartpole.py (1)

199-199: Cartpole example now conforms to the new runner signature.
CLI/test arguments will flow into the shared runner just like the other examples.

newton/examples/mpm/example_mpm_multi_material.py (1)

219-219: Updated runner call looks good.
Multi-material example also passes args, enabling the shared validation logic.

newton/examples/selection/example_selection_materials.py (1)

277-277: Args now forwarded to the runner.
Keeps the selection materials example compatible with the enhanced run flow.

newton/examples/mpm/example_mpm_granular.py (1)

229-229: Forward args into run.

Good catch updating this call to satisfy the new run(example, args) signature so tests get the CLI context they expect.

newton/examples/ik/example_ik_franka.py (1)

177-177: run invocation matches updated signature.

Passing args through keeps the IK example wired into the shared test/CLI pipeline after the API change.

newton/examples/robot/example_robot_allegro_hand.py (1)

210-210: Propagate parsed args to the runner.

Thanks for updating the Allegro example to pass args; this keeps its test path consistent with the revised harness.

newton/examples/sensors/example_sensor_contact.py (1)

354-354: Runner call now forwards CLI args.

This change ensures the sensor example benefits from the new test hooks and arg-driven behaviors.

newton/examples/ik/example_ik_h1.py (1)

193-193: Align run call with new API.

Forwarding args here keeps the H1 IK example compatible with the shared runner logic.

Comment thread newton/examples/__init__.py Outdated
Comment thread newton/examples/basic/example_basic_joints.py
Comment thread newton/examples/cloth/example_cloth_bending.py
Comment thread newton/examples/cloth/example_cloth_franka.py
Comment thread newton/examples/cloth/example_cloth_style3d.py
Comment thread newton/examples/robot/example_robot_anymal_c_walk.py
Comment thread newton/examples/robot/example_robot_anymal_d.py
Comment thread newton/examples/robot/example_robot_cartpole.py
Comment thread newton/examples/robot/example_robot_h1.py
Comment thread newton/tests/test_examples.py

@coderabbitai coderabbitai 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.

Actionable comments posted: 13

🧹 Nitpick comments (7)
newton/examples/robot/example_robot_h1.py (1)

125-136: Silence lint and prefer Warp-safe velocity norm check.

Avoid unused lambda args and Python max/abs on Warp types; use wp.length.

Apply:

         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "all bodies are above the ground",
-            lambda q, qd: q[2] > 0.0,
+            lambda q, _qd: q[2] > 0.0,
         )
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "all body velocities are small",
-            lambda q, qd: max(abs(qd)) < 0.001,
+            lambda _q, qd: wp.length(qd) < 1.0e-3,
         )

Ruff ARG005 warnings resolved; wp.length(qd) is robust in Warp kernels. Please verify wp.length supports wp.spatial_vector on your current Warp version. Based on static analysis hints

newton/examples/robot/example_robot_anymal_d.py (1)

142-153: Same cleanups: unused args + Warp-friendly velocity check.

Use underscore for unused parameters and wp.length for norms.

Apply:

         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "all bodies are above the ground",
-            lambda q, qd: q[2] > -0.006,
+            lambda q, _qd: q[2] > -0.006,
         )
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "body velocities are small",
-            lambda q, qd: max(abs(qd)) < 0.1,
+            lambda _q, qd: wp.length(qd) < 0.1,
         )

Resolves Ruff ARG005 and avoids Python builtins inside generated Warp code. Based on static analysis hints

newton/examples/cloth/example_cloth_style3d.py (1)

174-178: Silence unused-arg warning in lambda

Rename the unused qd parameter to _qd to satisfy Ruff ARG005 without changing behavior.

-        newton.examples.test_particle_state(
-            self.state_0,
-            "particles are within a reasonable volume",
-            lambda q, qd: newton.utils.vec_inside_limits(q, wp.vec3(-0.5, -0.2, 0.9), wp.vec3(0.5, 0.2, 1.6)),
-        )
+        newton.examples.test_particle_state(
+            self.state_0,
+            "particles are within a reasonable volume",
+            lambda q, _qd: newton.utils.vec_inside_limits(q, wp.vec3(-0.5, -0.2, 0.9), wp.vec3(0.5, 0.2, 1.6)),
+        )
newton/examples/robot/example_robot_anymal_c_walk.py (1)

231-247: Silence unused-arg warnings in lambdas

Rename unused parameters to underscores to satisfy Ruff ARG005.

-        newton.examples.test_body_state(
+        newton.examples.test_body_state(
             self.model,
             self.state_0,
             "all bodies are above the ground",
-            lambda q, qd: q[2] > 0.2,
+            lambda q, _qd: q[2] > 0.2,
         )
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "the robot is moving forward and not falling",
-            lambda q, qd: newton.utils.vec_allclose(
+            lambda _q, qd: newton.utils.vec_allclose(
                 qd, wp.spatial_vector(0.0, 1.0, 0.0, 0.0, 0.0, 0.0), rtol=0.1, atol=0.15
             ),
             indices=[0],
         )
newton/examples/basic/example_basic_joints.py (1)

210-227: Silence unused-arg warnings in lambdas

Rename unused q to _q to satisfy Ruff ARG005.

-            lambda q, qd: max(abs(qd)) < 1e-2,
+            lambda _q, qd: max(abs(qd)) < 1e-2,
@@
-            lambda q, qd: max(abs(qd)) < 1e-5,
+            lambda _q, qd: max(abs(qd)) < 1e-5,
@@
-            lambda q, qd: max(abs(qd)) < 3.0,
+            lambda _q, qd: max(abs(qd)) < 3.0,
newton/examples/cloth/example_cloth_franka.py (1)

555-572: Silence unused-arg warnings in lambdas

Rename unused parameters to underscores to satisfy Ruff ARG005.

-        newton.examples.test_particle_state(
+        newton.examples.test_particle_state(
             self.state_0,
             "particles are within a reasonable volume",
-            lambda q, qd: newton.utils.vec_inside_limits(q, wp.vec3(-0.34, -0.85, 0.03), wp.vec3(0.34, -0.13, 0.36)),
+            lambda q, _qd: newton.utils.vec_inside_limits(q, wp.vec3(-0.34, -0.85, 0.03), wp.vec3(0.34, -0.13, 0.36)),
         )
         newton.examples.test_particle_state(
             self.state_0,
             "particle velocities are within a reasonable range",
-            lambda q, qd: max(abs(qd)) < 2.0,
+            lambda _q, qd: max(abs(qd)) < 2.0,
         )
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "body velocities are within a reasonable range",
-            lambda q, qd: max(abs(qd)) < 0.7,
+            lambda _q, qd: max(abs(qd)) < 0.7,
         )
newton/examples/cloth/example_cloth_bending.py (1)

132-137: Silence unused-arg warnings in lambdas

Rename unused parameters to underscores to satisfy Ruff ARG005.

-            lambda q, qd: max(abs(qd)) < 0.1,
+            lambda _q, qd: max(abs(qd)) < 0.1,
@@
-            lambda q, qd: q[2] < 0.15,
+            lambda q, _qd: q[2] < 0.15,

Also applies to: 145-151

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4949d3c and 90c32bf.

📒 Files selected for processing (40)
  • newton/_src/utils/__init__.py (3 hunks)
  • newton/examples/__init__.py (5 hunks)
  • newton/examples/__main__.py (1 hunks)
  • newton/examples/basic/example_basic_joints.py (5 hunks)
  • newton/examples/basic/example_basic_pendulum.py (3 hunks)
  • newton/examples/basic/example_basic_shapes.py (5 hunks)
  • newton/examples/basic/example_basic_urdf.py (3 hunks)
  • newton/examples/basic/example_basic_viewer.py (1 hunks)
  • newton/examples/cloth/example_cloth_bending.py (2 hunks)
  • newton/examples/cloth/example_cloth_franka.py (3 hunks)
  • newton/examples/cloth/example_cloth_hanging.py (4 hunks)
  • newton/examples/cloth/example_cloth_style3d.py (2 hunks)
  • newton/examples/cloth/example_cloth_twist.py (3 hunks)
  • newton/examples/diffsim/example_diffsim_ball.py (1 hunks)
  • newton/examples/diffsim/example_diffsim_cloth.py (1 hunks)
  • newton/examples/diffsim/example_diffsim_drone.py (1 hunks)
  • newton/examples/diffsim/example_diffsim_soft_body.py (1 hunks)
  • newton/examples/diffsim/example_diffsim_spring_cage.py (1 hunks)
  • newton/examples/example_replay_viewer.py (1 hunks)
  • newton/examples/ik/example_ik_franka.py (1 hunks)
  • newton/examples/ik/example_ik_h1.py (1 hunks)
  • newton/examples/mpm/example_mpm_anymal.py (1 hunks)
  • newton/examples/mpm/example_mpm_grain_rendering.py (1 hunks)
  • newton/examples/mpm/example_mpm_granular.py (1 hunks)
  • newton/examples/mpm/example_mpm_multi_material.py (1 hunks)
  • newton/examples/robot/example_robot_allegro_hand.py (1 hunks)
  • newton/examples/robot/example_robot_anymal_c_walk.py (1 hunks)
  • newton/examples/robot/example_robot_anymal_d.py (2 hunks)
  • newton/examples/robot/example_robot_cartpole.py (2 hunks)
  • newton/examples/robot/example_robot_g1.py (2 hunks)
  • newton/examples/robot/example_robot_h1.py (2 hunks)
  • newton/examples/robot/example_robot_humanoid.py (1 hunks)
  • newton/examples/robot/example_robot_policy.py (1 hunks)
  • newton/examples/robot/example_robot_ur10.py (1 hunks)
  • newton/examples/selection/example_selection_articulations.py (1 hunks)
  • newton/examples/selection/example_selection_cartpole.py (1 hunks)
  • newton/examples/selection/example_selection_materials.py (1 hunks)
  • newton/examples/sensors/example_sensor_contact.py (1 hunks)
  • newton/tests/test_examples.py (9 hunks)
  • newton/utils.py (2 hunks)
👮 Files not reviewed due to content moderation or server errors (7)
  • newton/examples/mpm/example_mpm_anymal.py
  • newton/examples/ik/example_ik_franka.py
  • newton/examples/diffsim/example_diffsim_soft_body.py
  • newton/examples/sensors/example_sensor_contact.py
  • newton/examples/diffsim/example_diffsim_cloth.py
  • newton/examples/diffsim/example_diffsim_ball.py
  • newton/examples/mpm/example_mpm_grain_rendering.py
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2025-08-25T21:41:45.795Z
Learnt from: dylanturpin
PR: newton-physics/newton#634
File: newton/tests/test_examples.py:329-333
Timestamp: 2025-08-25T21:41:45.795Z
Learning: Newton examples use a centralized CLI argument parsing system in newton/examples/__init__.py. The create_parser() function defines common arguments like --device, --viewer, --output-path, and --num-frames, while init(parser) creates viewers based on parsed arguments. Individual example scripts don't need to define these flags themselves - they inherit them from the centralized system via the example_map and runpy execution.

Applied to files:

  • newton/examples/ik/example_ik_franka.py
  • newton/examples/mpm/example_mpm_granular.py
  • newton/examples/basic/example_basic_viewer.py
  • newton/examples/mpm/example_mpm_grain_rendering.py
  • newton/examples/ik/example_ik_h1.py
  • newton/examples/diffsim/example_diffsim_soft_body.py
  • newton/examples/basic/example_basic_pendulum.py
  • newton/examples/diffsim/example_diffsim_spring_cage.py
  • newton/examples/robot/example_robot_ur10.py
  • newton/examples/sensors/example_sensor_contact.py
  • newton/examples/robot/example_robot_g1.py
  • newton/examples/robot/example_robot_humanoid.py
  • newton/examples/robot/example_robot_anymal_d.py
  • newton/examples/basic/example_basic_joints.py
  • newton/examples/robot/example_robot_cartpole.py
  • newton/examples/diffsim/example_diffsim_cloth.py
  • newton/examples/diffsim/example_diffsim_drone.py
  • newton/examples/selection/example_selection_cartpole.py
  • newton/examples/basic/example_basic_urdf.py
  • newton/examples/__init__.py
  • newton/examples/mpm/example_mpm_multi_material.py
  • newton/examples/__main__.py
  • newton/examples/selection/example_selection_articulations.py
  • newton/examples/cloth/example_cloth_style3d.py
  • newton/examples/example_replay_viewer.py
  • newton/examples/selection/example_selection_materials.py
  • newton/examples/cloth/example_cloth_twist.py
  • newton/examples/robot/example_robot_allegro_hand.py
  • newton/examples/cloth/example_cloth_franka.py
  • newton/examples/cloth/example_cloth_bending.py
  • newton/examples/robot/example_robot_h1.py
  • newton/examples/basic/example_basic_shapes.py
  • newton/examples/mpm/example_mpm_anymal.py
📚 Learning: 2025-08-12T18:04:06.577Z
Learnt from: nvlukasz
PR: newton-physics/newton#519
File: newton/_src/solvers/featherstone/kernels.py:75-75
Timestamp: 2025-08-12T18:04:06.577Z
Learning: The Newton physics framework requires nightly Warp builds, which means compatibility concerns with older stable Warp versions (like missing functions such as wp.spatial_adjoint) are not relevant for this project.

Applied to files:

  • newton/examples/basic/example_basic_urdf.py
📚 Learning: 2025-08-12T05:17:34.423Z
Learnt from: shi-eric
PR: newton-physics/newton#521
File: newton/examples/example_cloth_hanging.py:36-36
Timestamp: 2025-08-12T05:17:34.423Z
Learning: The Newton migration guide (docs/migration.rst) is specifically for documenting how to migrate existing warp.sim functionality to Newton equivalents. New Newton-only features that didn't exist in warp.sim do not need migration documentation.

Applied to files:

  • newton/examples/basic/example_basic_urdf.py
📚 Learning: 2025-08-27T19:05:44.697Z
Learnt from: Milad-Rakhsha-NV
PR: newton-physics/newton#535
File: newton/tests/test_examples.py:320-414
Timestamp: 2025-08-27T19:05:44.697Z
Learning: In newton/examples/__init__.py, the robot policy example is registered with the key "robot_policy" (not "robot.example_robot_policy"), so tests should reference it as name="robot_policy".

Applied to files:

  • newton/examples/robot/example_robot_policy.py
  • newton/examples/robot/example_robot_allegro_hand.py
  • newton/examples/robot/example_robot_h1.py
📚 Learning: 2025-08-14T17:38:36.106Z
Learnt from: nvlukasz
PR: newton-physics/newton#519
File: newton/__init__.py:25-29
Timestamp: 2025-08-14T17:38:36.106Z
Learning: The Newton project prefers incremental __all__ building using __all__ += [...] pattern to group exports with their related imports, rather than a single consolidated __all__ at the end of the file.

Applied to files:

  • newton/utils.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
PR: newton-physics/newton#579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, there's a distinction between solver parameters and Example class attributes. The Example class can have its own use_mujoco attribute for controlling example-level behavior (like CUDA graphs, rendering logic), while the solver uses use_mujoco_cpu for backend selection. These serve different purposes and should not be conflated during API renames.

Applied to files:

  • newton/examples/basic/example_basic_shapes.py
🧬 Code graph analysis (36)
newton/examples/ik/example_ik_franka.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/mpm/example_mpm_granular.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/basic/example_basic_viewer.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/mpm/example_mpm_grain_rendering.py (1)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/ik/example_ik_h1.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/diffsim/example_diffsim_soft_body.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/basic/example_basic_pendulum.py (2)
newton/_src/sim/builder.py (1)
  • add_joint_revolute (1366-1448)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/examples/diffsim/example_diffsim_spring_cage.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/robot/example_robot_ur10.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/robot/example_robot_anymal_c_walk.py (2)
newton/examples/__init__.py (3)
  • test_body_state (49-103)
  • init (295-338)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_allclose (200-207)
newton/examples/sensors/example_sensor_contact.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/robot/example_robot_g1.py (1)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/examples/robot/example_robot_humanoid.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/robot/example_robot_anymal_d.py (1)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/examples/basic/example_basic_joints.py (1)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/examples/diffsim/example_diffsim_ball.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/robot/example_robot_cartpole.py (3)
newton/_src/sim/builder.py (1)
  • body_count (515-519)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_allclose (200-207)
newton/examples/diffsim/example_diffsim_cloth.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/diffsim/example_diffsim_drone.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/selection/example_selection_cartpole.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/basic/example_basic_urdf.py (2)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/_src/sim/builder.py (1)
  • body_count (515-519)
newton/examples/__init__.py (6)
newton/_src/sim/state.py (1)
  • State (21-112)
newton/_src/sim/contacts.py (1)
  • Contacts (23-93)
newton/_src/sim/control.py (1)
  • Control (21-77)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/cloth/example_cloth_hanging.py (1)
  • test (187-200)
newton/examples/robot/example_robot_cartpole.py (1)
  • test (112-179)
newton/examples/cloth/example_cloth_hanging.py (3)
newton/_src/sim/style3d/builder_style3d.py (1)
  • Style3DModelBuilder (38-698)
newton/examples/__init__.py (2)
  • test_particle_state (106-158)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/robot/example_robot_policy.py (1)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/mpm/example_mpm_multi_material.py (1)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/selection/example_selection_articulations.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/utils.py (1)
newton/_src/utils/__init__.py (2)
  • vec_allclose (200-207)
  • vec_inside_limits (211-218)
newton/examples/cloth/example_cloth_style3d.py (2)
newton/examples/__init__.py (2)
  • test_particle_state (106-158)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/selection/example_selection_materials.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
newton/examples/cloth/example_cloth_twist.py (2)
newton/examples/__init__.py (2)
  • test_particle_state (106-158)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/robot/example_robot_allegro_hand.py (1)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/cloth/example_cloth_franka.py (2)
newton/examples/__init__.py (3)
  • test_particle_state (106-158)
  • test_body_state (49-103)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/cloth/example_cloth_bending.py (2)
newton/examples/__init__.py (2)
  • test_particle_state (106-158)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/robot/example_robot_h1.py (2)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/basic/example_basic_shapes.py (4)
newton/_src/sim/builder.py (6)
  • add_body (1179-1241)
  • add_shape_sphere (2522-2553)
  • add_shape_capsule (2594-2634)
  • add_shape_box (2555-2592)
  • add_shape_mesh (2721-2754)
  • finalize (4058-4416)
newton/_src/solvers/xpbd/solver_xpbd.py (1)
  • SolverXPBD (40-660)
newton/examples/__init__.py (2)
  • test_body_state (49-103)
  • run (161-199)
newton/_src/utils/__init__.py (1)
  • vec_allclose (200-207)
newton/examples/mpm/example_mpm_anymal.py (2)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (1)
  • run (161-199)
🪛 Ruff (0.13.1)
newton/examples/basic/example_basic_pendulum.py

131-131: Unused lambda argument: qd

(ARG005)

newton/examples/robot/example_robot_anymal_c_walk.py

236-236: Unused lambda argument: qd

(ARG005)


242-242: Unused lambda argument: q

(ARG005)

newton/examples/robot/example_robot_g1.py

136-136: Unused lambda argument: qd

(ARG005)


142-142: Unused lambda argument: q

(ARG005)

newton/examples/robot/example_robot_anymal_d.py

146-146: Unused lambda argument: qd

(ARG005)


152-152: Unused lambda argument: q

(ARG005)

newton/examples/basic/example_basic_joints.py

204-204: Unused lambda argument: q

(ARG005)


211-211: Unused lambda argument: q

(ARG005)


218-218: Unused lambda argument: q

(ARG005)


225-225: Unused lambda argument: q

(ARG005)

newton/examples/robot/example_robot_cartpole.py

118-118: Unused lambda argument: qd

(ARG005)


125-125: Unused lambda argument: q

(ARG005)


135-135: Unused lambda argument: q

(ARG005)


147-147: Unused lambda argument: q

(ARG005)


163-163: Unused lambda argument: q

(ARG005)


170-170: Unused lambda argument: q

(ARG005)


177-177: Unused lambda argument: q

(ARG005)

newton/examples/basic/example_basic_urdf.py

133-133: Unused lambda argument: q

(ARG005)


141-141: Unused lambda argument: qd

(ARG005)

newton/examples/__init__.py

103-103: Avoid specifying long messages outside the exception class

(TRY003)


158-158: Avoid specifying long messages outside the exception class

(TRY003)


183-183: Avoid specifying long messages outside the exception class

(TRY003)


187-187: Avoid specifying long messages outside the exception class

(TRY003)


191-191: Avoid specifying long messages outside the exception class

(TRY003)


195-195: Avoid specifying long messages outside the exception class

(TRY003)


199-199: Avoid specifying long messages outside the exception class

(TRY003)

newton/examples/cloth/example_cloth_hanging.py

193-193: Unused lambda argument: qd

(ARG005)


199-199: Unused lambda argument: qd

(ARG005)

newton/examples/cloth/example_cloth_style3d.py

177-177: Unused lambda argument: qd

(ARG005)

newton/examples/cloth/example_cloth_twist.py

296-296: Unused lambda argument: qd

(ARG005)


301-301: Unused lambda argument: q

(ARG005)

newton/examples/cloth/example_cloth_franka.py

559-559: Unused lambda argument: qd

(ARG005)


564-564: Unused lambda argument: q

(ARG005)


570-570: Unused lambda argument: q

(ARG005)

newton/tests/test_examples.py

91-91: Avoid specifying long messages outside the exception class

(TRY003)

newton/examples/cloth/example_cloth_bending.py

136-136: Unused lambda argument: q

(ARG005)


142-142: Unused lambda argument: qd

(ARG005)


148-148: Unused lambda argument: qd

(ARG005)

newton/examples/robot/example_robot_h1.py

129-129: Unused lambda argument: qd

(ARG005)


135-135: Unused lambda argument: q

(ARG005)

newton/examples/basic/example_basic_shapes.py

143-143: Unused lambda argument: qd

(ARG005)


151-151: Unused lambda argument: qd

(ARG005)


159-159: Unused lambda argument: qd

(ARG005)


167-167: Unused lambda argument: qd

(ARG005)

🪛 GitHub Actions: Pull Request
newton/examples/robot/example_robot_anymal_c_walk.py

[error] 26-26: ModuleNotFoundError: No module named 'torch' while importing example_robot_anymal_c_walk during test_examples.

newton/tests/test_examples.py

[error] 311-311: Test module robot.example_robot_anymal_c_walk not found. ImportError raised while loading example tests.

🪛 GitHub Actions: GPU Unit Tests on AWS EC2
newton/tests/test_examples.py

[error] 193-193: Assertion failed in test_examples.py: 1 != 0. The covered cloth example test failed; Command 'coverage run --data-file=/tmp/tmp8tlsy0yw/tmp9pv1lj2_ -m newton.examples.cloth.example_cloth_bending --device cpu --test --viewer usd --output-path /var/snap/amazon-ssm-agent/12322/newton/newton/tests/outputs/cloth.example_cloth_bending_cpu.usd --num-frames 200' exited with code 1.

newton/examples/cloth/example_cloth_bending.py

[error] 160-160: SyntaxError: '(' was never closed while extracting warp lambda source (lambda q, qd: newton.utils.vec_inside_limits(...)).

🔇 Additional comments (31)
newton/examples/basic/example_basic_urdf.py (3)

29-31: Import of warp is correct and necessary.

Required for device functions used in tests below.


164-164: Passing args into run() is correct.

Matches newton.examples.run(example, args) behavior where args.test triggers example.test() and finiteness checks.

Ensure the tests invoke this example with --test to exercise the new checks.


136-144: Transform indexing bug and unused arg in lambda.

q is a wp.transform; use q.p[2] for height. Also avoid Python lambda; pass a wp.func. This also resolves Ruff ARG005 for the unused qd.

Apply this diff:

-        bodies_per_env = self.model.body_count // self.num_envs
+        bodies_per_env = self.model.body_count // self.num_envs
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "quadrupeds have reached the terminal height",
-            lambda q, qd: wp.abs(q[2] - 0.48) < 0.01,
+            at_terminal_height,
             # only select the root body of each environment
             indices=[i * bodies_per_env for i in range(self.num_envs)],
         )

Add this device function near the imports:

@wp.func
def at_terminal_height(q: wp.transform, _qd: wp.spatial_vector) -> bool:
    return wp.abs(q.p[2] - 0.48) < 0.01

Please verify body_count % num_envs == 0 at runtime; if not, root-body indexing will be off. Based on relevant_code_snippets

newton/examples/__main__.py (1)

3-14: License header addition: LGTM.

Matches Apache 2.0 template; no functional impact.

newton/_src/utils/__init__.py (3)

199-207: vec_allclose: Correct tolerance semantics; LGTM.

Matches numpy’s abs(a-b) <= atol + rtol*abs(b); works with fixed-size Warp vectors.


210-218: vec_inside_limits: Straightforward and clear; LGTM.

Loop unrolled via wp.static(len(a)) for fixed-size vectors.


246-248: Verify public re-export is wired up.

Ensure newton/utils.py re-exports these for public access as documented.

Run:

newton/examples/example_replay_viewer.py (1)

252-252: API alignment: passing args into run() is correct.

Keeps this entry point consistent with the updated runner signature.

newton/examples/selection/example_selection_materials.py (1)

277-277: API alignment: LGTM.

Forwarding args to run() matches the new examples runner.

newton/examples/mpm/example_mpm_granular.py (1)

229-229: API alignment: LGTM.

Args are now forwarded to the runner as expected.

newton/examples/robot/example_robot_ur10.py (1)

218-218: API alignment: LGTM. Also check for any remaining legacy call sites.

This adopts run(example, args). Verify no other examples still call run(example) without args.

Run:

newton/examples/diffsim/example_diffsim_drone.py (1)

821-821: Forwarding args keeps the example aligned with the updated runner API.

Looks good—this ensures the CLI/test flags propagate into newton.examples.run.

newton/examples/robot/example_robot_allegro_hand.py (1)

210-210: Run invocation now matches the new run(example, args) contract.

No issues spotted; the example will honor --test and other parsed flags.

newton/examples/diffsim/example_diffsim_spring_cage.py (1)

253-253: Args passthrough to run looks correct.

This keeps the diff-sim example compatible with the updated runner.

newton/examples/robot/example_robot_policy.py (1)

472-472: Runner call updated appropriately.

Passing args here ensures policy selection honors CLI/test flags.

newton/examples/robot/example_robot_humanoid.py (1)

127-127: args forwarding confirmed.

The humanoid example now complies with the revised newton.examples.run signature.

newton/examples/mpm/example_mpm_multi_material.py (1)

219-219: Runner call aligns with new signature.

No problems here—args reaches the test harness as expected.

newton/examples/selection/example_selection_articulations.py (1)

301-301: Updated runner invocation is correct.

args is now propagated to handle --test and related options.

newton/examples/selection/example_selection_cartpole.py (1)

199-199: Args propagation LGTM.

This keeps the cartpole selection example compatible with the shared runner.

newton/examples/basic/example_basic_viewer.py (1)

194-194: Run signature update looks good

Passing args into run aligns with newton.examples.run(example, args).

newton/examples/cloth/example_cloth_style3d.py (1)

194-194: Run signature update looks good

Consistent with updated run(example, args).

newton/examples/ik/example_ik_h1.py (1)

193-193: Run signature update looks good

Switch to run(example, args) is correct.

newton/examples/robot/example_robot_anymal_c_walk.py (2)

255-255: Run signature update looks good

run(example, args) matches the new API.


26-57: Fix: guard optional torch dependency to prevent import-time failure

Tests fail importing this module when torch isn’t installed. Guard the import and the JIT-decorated function so the module can be imported, and short-circuit in main if torch is unavailable.

-import torch
+try:
+    import torch
+    TORCH_AVAILABLE = True
+except Exception:
+    TORCH_AVAILABLE = False
-@torch.jit.script
-def quat_rotate_inverse(q: torch.Tensor, v: torch.Tensor) -> torch.Tensor:
+if TORCH_AVAILABLE:
+    @torch.jit.script
+    def quat_rotate_inverse(q: torch.Tensor, v: torch.Tensor) -> torch.Tensor:
+        # ... (body unchanged)
+        q_w = q[..., 3]
+        q_vec = q[..., :3]
+        a = v * (2.0 * q_w**2 - 1.0).unsqueeze(-1)
+        b = torch.cross(q_vec, v, dim=-1) * q_w.unsqueeze(-1) * 2.0
+        if q_vec.dim() == 2:
+            c = q_vec * torch.bmm(q_vec.view(q.shape[0], 1, 3), v.view(q.shape[0], 3, 1)).squeeze(-1) * 2.0
+        else:
+            c = q_vec * torch.einsum("...i,...i->...", q_vec, v).unsqueeze(-1) * 2.0
+        return a - b + c
+else:
+    def quat_rotate_inverse(q, v):
+        raise RuntimeError("Torch not available")

Additionally, exit early in main if torch is missing to make the subprocess return 0 cleanly when the dependency isn’t present:

 if __name__ == "__main__":
-    # Parse arguments and initialize viewer
-    viewer, args = newton.examples.init()
+    # Parse arguments and initialize viewer
+    import sys
+    if not TORCH_AVAILABLE:
+        print("Torch not available; skipping example_robot_anymal_c_walk")
+        sys.exit(0)
+    viewer, args = newton.examples.init()

To ensure CI skips this example when torch is missing, please also verify test_examples marks it torch_required.

Run to confirm mapping:

newton/utils.py (1)

91-93: Re-exporting vec_allclose and vec_inside_limits is correct

Public surface now matches usage across examples/tests. Incremental all style is consistent.

Also applies to: 106-108

newton/examples/basic/example_basic_joints.py (3)

87-89: Initializing joint angle is fine

Setting builder.joint_q[-1] to pi/2 is reasonable for a visible hinge pose.


151-152: Quaternion init for BALL joint looks good

Using quat_rpy to seed initial orientation is appropriate.


243-244: Run signature update looks good

Correctly updated to run(example, args).

newton/examples/cloth/example_cloth_franka.py (1)

583-584: Run signature update looks good

Switch to run(example, args) is correct.

newton/examples/cloth/example_cloth_bending.py (1)

160-160: Run signature update looks good

run(example, args) matches the new API.

newton/examples/basic/example_basic_shapes.py (1)

138-169: Fix transform handling in example tests

test_body_state passes each body's wp.transform into your lambda. newton.utils.vec_allclose expects vector-like inputs, and the lambdas use direct indexing (q[2], etc.). Running the example with --test will make Warp compile this kernel and it aborts because wp.transform isn’t subscriptable and vec_allclose can’t iterate it. Compare the transform’s translation and rotation explicitly instead.

         sphere_q = wp.transform(0.0, -2.0, 0.5, 0.0, 0.0, 0.0, 1.0)
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "sphere at rest pose",
-            lambda q, qd: newton.utils.vec_allclose(q, sphere_q, atol=1e-4),
+            lambda q, qd: newton.utils.vec_allclose(q.p, sphere_q.p, atol=1e-4)
+            and newton.utils.vec_allclose(q.q, sphere_q.q, atol=1e-4),
             [0],
         )
         capsule_q = wp.transform(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "capsule at rest pose",
-            lambda q, qd: newton.utils.vec_allclose(q, capsule_q, atol=1e-4),
+            lambda q, qd: newton.utils.vec_allclose(q.p, capsule_q.p, atol=1e-4)
+            and newton.utils.vec_allclose(q.q, capsule_q.q, atol=1e-4),
             [1],
         )
         box_q = wp.transform(0.0, 2.0, 0.25, 0.0, 0.0, 0.0, 1.0)
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "box at rest pose",
-            lambda q, qd: newton.utils.vec_allclose(q, box_q, atol=0.1),
+            lambda q, qd: newton.utils.vec_allclose(q.p, box_q.p, atol=0.1)
+            and newton.utils.vec_allclose(q.q, box_q.q, atol=0.1),
             [2],
         )
         # we only test that the bunny didn't fall through the ground and didn't slide too far
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "bunny at rest pose",
-            lambda q, qd: q[2] > 0.01 and abs(q[0]) < 0.1 and abs(q[1] - 4.0) < 0.1,
+            lambda q, qd: q.p[2] > 0.01 and abs(q.p[0]) < 0.1 and abs(q.p[1] - 4.0) < 0.1,
             [3],
         )
⛔ Skipped due to learnings
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/_src/sim/ik/ik_objectives.py:0-0
Timestamp: 2025-09-25T16:14:22.002Z
Learning: wp.transform in NVIDIA Warp supports indexing using numerical indices (e.g., body_tf[0], body_tf[3], etc.) to access translation and rotation components. The indexing approach used in the Newton codebase is valid and compiles correctly.
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/_src/sim/ik/ik_objectives.py:0-0
Timestamp: 2025-09-25T16:14:22.002Z
Learning: In NVIDIA Warp's Newton physics library, wp.transform supports direct numerical indexing (e.g., body_tf[0], body_tf[1], body_tf[2] for position and body_tf[3], body_tf[4], body_tf[5], body_tf[6] for quaternion components) to access its elements. This is the standard API used throughout the codebase.
Learnt from: adenzler-nvidia
PR: newton-physics/newton#552
File: newton/_src/solvers/mujoco/solver_mujoco.py:0-0
Timestamp: 2025-08-18T15:56:26.587Z
Learning: In Newton's MuJoCo solver, when transforming joint axes from Newton's internal frame to MuJoCo's expected frame, use wp.quat_rotate(joint_rot, axis) not wp.quat_rotate_inv(joint_rot, axis). The joint_rot represents rotation from joint-local to body frame, so forward rotation is correct.

Comment thread newton/examples/__init__.py Outdated
Comment thread newton/examples/__init__.py
Comment thread newton/examples/__init__.py
Comment thread newton/examples/basic/example_basic_joints.py
Comment thread newton/examples/basic/example_basic_pendulum.py
Comment thread newton/examples/cloth/example_cloth_twist.py
Comment thread newton/examples/robot/example_robot_cartpole.py
Comment thread newton/examples/robot/example_robot_g1.py
Comment thread newton/tests/test_examples.py
Comment thread newton/tests/test_examples.py
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🧹 Nitpick comments (5)
newton/examples/robot/example_robot_anymal_c_walk.py (1)

231-246: Optional: silence Ruff ARG005 in lambdas

If you keep the lambdas, rename unused parameters to _ to quiet ARG005.

-            lambda q, qd: q[2] > 0.2,
+            lambda q, _qd: q[2] > 0.2,
@@
-            lambda q, qd: newton.utils.vec_allclose(qd, forward_vel, rtol=0.1, atol=0.15),
+            lambda _q, qd: newton.utils.vec_allclose(qd, forward_vel, rtol=0.1, atol=0.15),
newton/examples/selection/example_selection_materials.py (1)

255-261: Optional: silence Ruff ARG005 and prefer explicit underscore for unused args

Rename the unused qd parameter to _ for clarity and to satisfy linters.

-            lambda q, qd: q[2] > 0.01,
+            lambda q, _qd: q[2] > 0.01,
newton/examples/selection/example_selection_articulations.py (1)

287-293: Optional: silence Ruff ARG005 and prefer explicit underscore for unused args

Rename the unused qd parameter to _ for clarity and to satisfy linters.

-            lambda q, qd: q[2] > 0.01,
+            lambda q, _qd: q[2] > 0.01,
newton/examples/cloth/example_cloth_bending.py (1)

147-152: Optional: silence Ruff ARG005 for unused arg

Rename the unused qd parameter to _.

-            lambda q, qd: q[2] < 0.15,
+            lambda q, _qd: q[2] < 0.15,
newton/examples/mpm/example_mpm_anymal.py (1)

34-34: Defer optional cross-example import to avoid hard import-time failures.

Importing robot example utilities at module import time can break this example if that module isn’t available. Lazily import where used and provide a clear skip/fallback.

Apply this diff to remove the hard import:

-from newton.examples.robot.example_robot_anymal_c_walk import compute_obs, lab_to_mujoco, mujoco_to_lab

Add this inside Example.init (near where you first use these symbols):

# Lazy import to avoid module-level failures if the example pack isn’t present
try:
    from newton.examples.robot.example_robot_anymal_c_walk import compute_obs, lab_to_mujoco, mujoco_to_lab
except ImportError as e:
    raise ImportError("Missing dependency: newton.examples.robot.example_robot_anymal_c_walk") from e

If preferred, I can wire this to gracefully skip tests when the module is absent instead of raising.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90c32bf and caee6c5.

📒 Files selected for processing (16)
  • newton/examples/__init__.py (5 hunks)
  • newton/examples/basic/example_basic_joints.py (5 hunks)
  • newton/examples/cloth/example_cloth_bending.py (2 hunks)
  • newton/examples/cloth/example_cloth_franka.py (3 hunks)
  • newton/examples/cloth/example_cloth_hanging.py (4 hunks)
  • newton/examples/cloth/example_cloth_style3d.py (2 hunks)
  • newton/examples/cloth/example_cloth_twist.py (3 hunks)
  • newton/examples/mpm/example_mpm_anymal.py (5 hunks)
  • newton/examples/robot/example_robot_allegro_hand.py (2 hunks)
  • newton/examples/robot/example_robot_anymal_c_walk.py (1 hunks)
  • newton/examples/robot/example_robot_humanoid.py (3 hunks)
  • newton/examples/robot/example_robot_policy.py (2 hunks)
  • newton/examples/selection/example_selection_articulations.py (2 hunks)
  • newton/examples/selection/example_selection_cartpole.py (2 hunks)
  • newton/examples/selection/example_selection_materials.py (2 hunks)
  • newton/tests/test_examples.py (15 hunks)
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2025-08-25T21:41:45.795Z
Learnt from: dylanturpin
PR: newton-physics/newton#634
File: newton/tests/test_examples.py:329-333
Timestamp: 2025-08-25T21:41:45.795Z
Learning: Newton examples use a centralized CLI argument parsing system in newton/examples/__init__.py. The create_parser() function defines common arguments like --device, --viewer, --output-path, and --num-frames, while init(parser) creates viewers based on parsed arguments. Individual example scripts don't need to define these flags themselves - they inherit them from the centralized system via the example_map and runpy execution.

Applied to files:

  • newton/examples/cloth/example_cloth_style3d.py
  • newton/examples/selection/example_selection_articulations.py
  • newton/examples/selection/example_selection_materials.py
  • newton/examples/robot/example_robot_allegro_hand.py
  • newton/examples/__init__.py
  • newton/examples/robot/example_robot_humanoid.py
  • newton/examples/selection/example_selection_cartpole.py
  • newton/examples/mpm/example_mpm_anymal.py
  • newton/examples/basic/example_basic_joints.py
  • newton/examples/cloth/example_cloth_franka.py
  • newton/examples/cloth/example_cloth_twist.py
  • newton/examples/cloth/example_cloth_bending.py
📚 Learning: 2025-08-27T19:05:44.697Z
Learnt from: Milad-Rakhsha-NV
PR: newton-physics/newton#535
File: newton/tests/test_examples.py:320-414
Timestamp: 2025-08-27T19:05:44.697Z
Learning: In newton/examples/__init__.py, the robot policy example is registered with the key "robot_policy" (not "robot.example_robot_policy"), so tests should reference it as name="robot_policy".

Applied to files:

  • newton/examples/robot/example_robot_allegro_hand.py
  • newton/tests/test_examples.py
  • newton/examples/robot/example_robot_policy.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
PR: newton-physics/newton#579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, there's a distinction between solver parameters and Example class attributes. The Example class can have its own use_mujoco attribute for controlling example-level behavior (like CUDA graphs, rendering logic), while the solver uses use_mujoco_cpu for backend selection. These serve different purposes and should not be conflated during API renames.

Applied to files:

  • newton/examples/mpm/example_mpm_anymal.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
PR: newton-physics/newton#579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, Example.use_mujoco is a high-level attribute that controls whether to use MuJoCo solver vs other solvers (like XPBD), while SolverMuJoCo.use_mujoco_cpu controls the backend within MuJoCo (CPU vs Warp). These are separate concepts serving different purposes - the PR rename only applies to the solver parameter, not the Example class attributes.

Applied to files:

  • newton/examples/mpm/example_mpm_anymal.py
📚 Learning: 2025-08-18T15:56:26.587Z
Learnt from: adenzler-nvidia
PR: newton-physics/newton#552
File: newton/_src/solvers/mujoco/solver_mujoco.py:0-0
Timestamp: 2025-08-18T15:56:26.587Z
Learning: In Newton's MuJoCo solver, when transforming joint axes from Newton's internal frame to MuJoCo's expected frame, use wp.quat_rotate(joint_rot, axis) not wp.quat_rotate_inv(joint_rot, axis). The joint_rot represents rotation from joint-local to body frame, so forward rotation is correct.

Applied to files:

  • newton/examples/mpm/example_mpm_anymal.py
📚 Learning: 2025-08-12T18:04:06.577Z
Learnt from: nvlukasz
PR: newton-physics/newton#519
File: newton/_src/solvers/featherstone/kernels.py:75-75
Timestamp: 2025-08-12T18:04:06.577Z
Learning: The Newton physics framework requires nightly Warp builds, which means compatibility concerns with older stable Warp versions (like missing functions such as wp.spatial_adjoint) are not relevant for this project.

Applied to files:

  • newton/examples/cloth/example_cloth_twist.py
  • newton/examples/cloth/example_cloth_bending.py
🧬 Code graph analysis (15)
newton/examples/cloth/example_cloth_style3d.py (2)
newton/examples/__init__.py (2)
  • test_particle_state (108-161)
  • run (164-202)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/selection/example_selection_articulations.py (1)
newton/examples/__init__.py (2)
  • test_body_state (49-105)
  • run (164-202)
newton/examples/selection/example_selection_materials.py (1)
newton/examples/__init__.py (2)
  • test_body_state (49-105)
  • run (164-202)
newton/examples/robot/example_robot_allegro_hand.py (2)
newton/examples/__init__.py (1)
  • test_body_state (49-105)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (4)
newton/_src/sim/state.py (1)
  • State (21-112)
newton/_src/sim/contacts.py (1)
  • Contacts (23-93)
newton/_src/sim/control.py (1)
  • Control (21-77)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/robot/example_robot_humanoid.py (2)
newton/examples/__init__.py (2)
  • test_body_state (49-105)
  • run (164-202)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/robot/example_robot_anymal_c_walk.py (2)
newton/examples/__init__.py (3)
  • test_body_state (49-105)
  • init (298-341)
  • run (164-202)
newton/_src/utils/__init__.py (1)
  • vec_allclose (200-207)
newton/examples/selection/example_selection_cartpole.py (3)
newton/_src/sim/builder.py (1)
  • body_count (515-519)
newton/examples/__init__.py (2)
  • test_body_state (49-105)
  • run (164-202)
newton/_src/utils/__init__.py (1)
  • vec_allclose (200-207)
newton/examples/cloth/example_cloth_hanging.py (3)
newton/_src/sim/style3d/builder_style3d.py (1)
  • Style3DModelBuilder (38-698)
newton/examples/__init__.py (2)
  • test_particle_state (108-161)
  • run (164-202)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/mpm/example_mpm_anymal.py (4)
newton/examples/robot/example_robot_anymal_c_walk.py (1)
  • compute_obs (60-74)
newton/examples/robot/example_robot_policy.py (1)
  • compute_obs (113-155)
newton/_src/solvers/mujoco/solver_mujoco.py (1)
  • SolverMuJoCo (1136-2844)
newton/examples/__init__.py (3)
  • test_body_state (49-105)
  • test_particle_state (108-161)
  • run (164-202)
newton/examples/basic/example_basic_joints.py (1)
newton/examples/__init__.py (2)
  • test_body_state (49-105)
  • run (164-202)
newton/examples/cloth/example_cloth_franka.py (2)
newton/examples/__init__.py (2)
  • test_particle_state (108-161)
  • test_body_state (49-105)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/cloth/example_cloth_twist.py (2)
newton/examples/__init__.py (2)
  • test_particle_state (108-161)
  • run (164-202)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/cloth/example_cloth_bending.py (2)
newton/examples/__init__.py (2)
  • test_particle_state (108-161)
  • run (164-202)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/robot/example_robot_policy.py (1)
newton/examples/__init__.py (2)
  • test_body_state (49-105)
  • run (164-202)
🪛 Ruff (0.13.1)
newton/examples/cloth/example_cloth_style3d.py

180-180: Unused lambda argument: qd

(ARG005)

newton/examples/selection/example_selection_articulations.py

292-292: Unused lambda argument: qd

(ARG005)

newton/examples/selection/example_selection_materials.py

260-260: Unused lambda argument: qd

(ARG005)

newton/examples/robot/example_robot_allegro_hand.py

203-203: Unused lambda argument: qd

(ARG005)

newton/examples/__init__.py

91-91: Avoid specifying long messages outside the exception class

(TRY003)


105-105: Avoid specifying long messages outside the exception class

(TRY003)


148-148: Avoid specifying long messages outside the exception class

(TRY003)


161-161: Avoid specifying long messages outside the exception class

(TRY003)


186-186: Avoid specifying long messages outside the exception class

(TRY003)


190-190: Avoid specifying long messages outside the exception class

(TRY003)


194-194: Avoid specifying long messages outside the exception class

(TRY003)


198-198: Avoid specifying long messages outside the exception class

(TRY003)


202-202: Avoid specifying long messages outside the exception class

(TRY003)

newton/examples/robot/example_robot_humanoid.py

122-122: Unused lambda argument: qd

(ARG005)


128-128: Unused lambda argument: q

(ARG005)

newton/examples/robot/example_robot_anymal_c_walk.py

236-236: Unused lambda argument: qd

(ARG005)


243-243: Unused lambda argument: q

(ARG005)

newton/examples/selection/example_selection_cartpole.py

182-182: Unused lambda argument: qd

(ARG005)


189-189: Unused lambda argument: q

(ARG005)


199-199: Unused lambda argument: q

(ARG005)


211-211: Unused lambda argument: q

(ARG005)

newton/examples/cloth/example_cloth_hanging.py

193-193: Unused lambda argument: qd

(ARG005)


202-202: Unused lambda argument: qd

(ARG005)

newton/examples/mpm/example_mpm_anymal.py

297-297: Unused lambda argument: qd

(ARG005)


304-304: Unused lambda argument: q

(ARG005)


310-310: Unused lambda argument: qd

(ARG005)

newton/tests/test_examples.py

91-91: Avoid specifying long messages outside the exception class

(TRY003)

newton/examples/basic/example_basic_joints.py

204-204: Unused lambda argument: q

(ARG005)


211-211: Unused lambda argument: q

(ARG005)


218-218: Unused lambda argument: q

(ARG005)


225-225: Unused lambda argument: q

(ARG005)

newton/examples/cloth/example_cloth_franka.py

561-561: Unused lambda argument: qd

(ARG005)


566-566: Unused lambda argument: q

(ARG005)


572-572: Unused lambda argument: q

(ARG005)

newton/examples/cloth/example_cloth_twist.py

298-298: Unused lambda argument: qd

(ARG005)


303-303: Unused lambda argument: q

(ARG005)

newton/examples/cloth/example_cloth_bending.py

136-136: Unused lambda argument: q

(ARG005)


144-144: Unused lambda argument: qd

(ARG005)


150-150: Unused lambda argument: qd

(ARG005)

newton/examples/robot/example_robot_policy.py

417-417: Unused lambda argument: qd

(ARG005)

🪛 GitHub Actions: Pull Request
newton/examples/robot/example_robot_anymal_c_walk.py

[error] 26-26: ModuleNotFoundError: No module named 'torch'. Importing example_robot_anymal_c_walk requires PyTorch to be installed.

newton/tests/test_examples.py

[error] 311-311: ImportError: Test module robot.example_robot_anymal_c_walk not found. This followed a ModuleNotFoundError for torch during dynamic test discovery.

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run GPU Benchmarks (Pull Request)
  • GitHub Check: Run GPU Unit Tests on AWS EC2 (Pull Request)
🔇 Additional comments (19)
newton/examples/basic/example_basic_joints.py (1)

199-226: Rename unused lambda parameters to satisfy lint

Ruff is still flagging the unused q parameters (ARG005), so CI will keep failing. Please rename the unused arguments to _q across these lambdas; this is the same lint issue that was called out earlier.

             newton.examples.test_body_state(
                 self.model,
                 self.state_0,
                 "static bodies are not moving",
-                lambda q, qd: max(abs(qd)) == 0.0,
+                lambda _q, qd: max(abs(qd)) == 0.0,
                 indices=[2, 4],
             )
             newton.examples.test_body_state(
                 self.model,
                 self.state_0,
                 "fixed link body has come to a rest",
-                lambda q, qd: max(abs(qd)) < 1e-2,
+                lambda _q, qd: max(abs(qd)) < 1e-2,
                 indices=[0],
             )
             newton.examples.test_body_state(
                 self.model,
                 self.state_0,
                 "slider link body has come to a rest",
-                lambda q, qd: max(abs(qd)) < 1e-5,
+                lambda _q, qd: max(abs(qd)) < 1e-5,
                 indices=[3],
             )
             newton.examples.test_body_state(
                 self.model,
                 self.state_0,
                 "movable links are not moving too fast",
-                lambda q, qd: max(abs(qd)) < 3.0,
+                lambda _q, qd: max(abs(qd)) < 3.0,
                 indices=[1, 5],
             )
newton/examples/cloth/example_cloth_style3d.py (1)

175-181: Rename unused lambda parameter to satisfy lint

Ruff (ARG005) complains about the unused qd argument, which will block pre-commit. Rename it to _qd (or _) so CI passes.

         newton.examples.test_particle_state(
             self.state_0,
             "particles are within a reasonable volume",
-            lambda q, qd: newton.utils.vec_inside_limits(q, p_lower, p_upper),
+            lambda q, _qd: newton.utils.vec_inside_limits(q, p_lower, p_upper),
         )
newton/examples/robot/example_robot_allegro_hand.py (1)

199-204: Correct transform access in Allegro hand test

Here too, q is a wp.transform, so q[2] will throw once the Warp kernel runs. Access the position via q.p[2], and mark the unused velocity argument to clear Ruff.

         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "all bodies are above the ground",
-            lambda q, qd: q[2] > 0.9,
+            lambda q, _qd: q.p[2] > 0.9,
         )
⛔ Skipped due to learnings
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/_src/sim/ik/ik_objectives.py:0-0
Timestamp: 2025-09-25T16:14:22.002Z
Learning: In NVIDIA Warp's Newton physics library, wp.transform supports direct numerical indexing (e.g., body_tf[0], body_tf[1], body_tf[2] for position and body_tf[3], body_tf[4], body_tf[5], body_tf[6] for quaternion components) to access its elements. This is the standard API used throughout the codebase.
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/_src/sim/ik/ik_objectives.py:0-0
Timestamp: 2025-09-25T16:14:22.002Z
Learning: wp.transform in NVIDIA Warp supports indexing using numerical indices (e.g., body_tf[0], body_tf[3], etc.) to access translation and rotation components. The indexing approach used in the Newton codebase is valid and compiles correctly.
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering, despite the general warp documentation suggesting copies are made by default.
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering.
Learnt from: adenzler-nvidia
PR: newton-physics/newton#552
File: newton/_src/solvers/mujoco/solver_mujoco.py:0-0
Timestamp: 2025-08-18T15:56:26.587Z
Learning: In Newton's MuJoCo solver, when transforming joint axes from Newton's internal frame to MuJoCo's expected frame, use wp.quat_rotate(joint_rot, axis) not wp.quat_rotate_inv(joint_rot, axis). The joint_rot represents rotation from joint-local to body frame, so forward rotation is correct.
newton/examples/selection/example_selection_cartpole.py (2)

176-218: Confirm body index layout assumption

Assumes per-env bodies are contiguous and ordered [cart, pole1, pole2]. If asset order changes, indices will mismatch. Consider deriving indices from model.body_key names or ArticulationView metadata.


239-239: LGTM: updated runner signature

Switched to run(example, args), aligned with the new API.

newton/examples/robot/example_robot_anymal_c_walk.py (2)

254-254: LGTM: updated runner signature

Switched to run(example, args), aligned with the new API.


231-246: Fix CI import failure: gate top-level torch dependency

Module-level import torch breaks import in environments without PyTorch (see pipeline error). Defer/guard torch imports and JIT decorations so the module can be imported even when torch isn’t installed; raise a clear error only when executing this example.

Suggested approach (changes outside this hunk):

  • Replace top-level import torch with a guarded import and flag:
    try:
    import torch # type: ignore
    TORCH_AVAILABLE = True
    except Exception:
    torch = None # type: ignore
    TORCH_AVAILABLE = False
  • Define quat_rotate_inverse conditionally:
    if TORCH_AVAILABLE:
    @torch.jit.script
    def quat_rotate_inverse(...): ...
    else:
    def quat_rotate_inverse(*_args, **_kwargs):
    raise RuntimeError("This example requires PyTorch; install torch or skip it.")
  • Delay from warp.torch import device_to_torch until inside Example.init and only if TORCH_AVAILABLE; otherwise raise a friendly error there.

Alternatively, install torch in CI for this test matrix.

newton/examples/selection/example_selection_materials.py (1)

282-282: LGTM: updated runner signature

Switched to run(example, args), aligned with the new API.

newton/examples/selection/example_selection_articulations.py (1)

309-309: LGTM: updated runner signature

Switched to run(example, args), aligned with the new API.

newton/examples/cloth/example_cloth_bending.py (3)

162-162: LGTM: updated runner signature

Switched to run(example, args), aligned with the new API.


132-138: Fix Warp lambda: Python max/abs breaks codegen

max(abs(qd)) is not Warp-friendly and causes kernel generation errors. Use wp.length(qd) (or squared length) instead.

-            "particles have come close to a rest",
-            lambda q, qd: max(abs(qd)) < 0.1,
+            "particles have come close to a rest",
+            lambda _q, qd: wp.length(qd) < 0.1,

139-145: Avoid complex multi-arg lambdas for Warp; use a named @wp.func

create_warp_function can fail to extract complex lambdas. Define a small Warp function and pass it instead.

-        p_lower = wp.vec3(-3.0, -3.0, 0.0)
-        p_upper = wp.vec3(3.0, 3.0, 2.0)
-        newton.examples.test_particle_state(
-            self.state_0,
-            "particles are within a reasonable volume",
-            lambda q, qd: newton.utils.vec_inside_limits(q, p_lower, p_upper),
-        )
+        p_lower = wp.vec3(-3.0, -3.0, 0.0)
+        p_upper = wp.vec3(3.0, 3.0, 2.0)
+
+        @wp.func
+        def _within_bounds(q: wp.vec3, _qd: wp.vec3) -> bool:
+            return newton.utils.vec_inside_limits(q, p_lower, p_upper)
+
+        newton.examples.test_particle_state(
+            self.state_0,
+            "particles are within a reasonable volume",
+            _within_bounds,
+        )
newton/tests/test_examples.py (2)

224-224: Normalize option keys to underscores for consistency.

use num_frames not num-frames; the builder will hyphenate automatically. Keeps style consistent and avoids mixed conventions.

Example fix (apply similarly across occurrences):

-    test_options={"num-frames": 200},
+    test_options={"num_frames": 200},
-    test_options_cpu={"width": 32, "height": 16, "num-frames": 10},
+    test_options_cpu={"width": 32, "height": 16, "num_frames": 10},

Based on learnings

Also applies to: 235-240, 251-251, 259-271, 277-279, 285-287, 293-295, 307-309, 315-316, 322-324, 331-331, 337-337, 344-346, 352-354, 360-360, 373-375, 382-382, 391-391, 398-398, 406-406, 415-416, 438-439, 469-470, 477-478, 485-486, 499-500, 508-509, 517-518, 526-527, 535-536, 549-550, 562-562, 570-570, 578-578


87-92: Don’t fail the whole suite on missing example modules; skip gracefully.

Current import check raises ImportError and aborts CI. Skip the test when a module is absent.

Apply this diff:

-    # verify the module exists
-    try:
-        importlib.import_module(f"newton.examples.{name}")
-    except ImportError as e:
-        raise ImportError(f"Test module {name} not found") from e
+    # verify the module exists; if missing, register a skipped test
+    try:
+        importlib.import_module(f"newton.examples.{name}")
+    except ImportError as e:
+        def _skipped(test, device):
+            test.skipTest(f"Example module newton.examples.{name} not found: {e}")
+        test_name = f"test_{name}_{test_suffix}" if test_suffix else f"test_{name}"
+        add_function_test(cls, test_name, _skipped, devices=devices, check_output=False)
+        return

As per pipeline failures

newton/examples/cloth/example_cloth_franka.py (1)

555-573: Make test lambdas Warp-safe and silence unused-arg lint (ARG005).

  • max(abs(qd)) won’t compile inside a Warp-created function.
  • Rename unused lambda params to _ to satisfy Ruff.

Apply this diff:

     newton.examples.test_particle_state(
         self.state_0,
         "particles are within a reasonable volume",
-        lambda q, qd: newton.utils.vec_inside_limits(q, p_lower, p_upper),
+        lambda q, _: newton.utils.vec_inside_limits(q, p_lower, p_upper),
     )
     newton.examples.test_particle_state(
         self.state_0,
         "particle velocities are within a reasonable range",
-        lambda q, qd: max(abs(qd)) < 2.0,
+        lambda _, qd: wp.length(qd) < 2.0,
     )
     newton.examples.test_body_state(
         self.model,
         self.state_0,
         "body velocities are within a reasonable range",
-        lambda q, qd: max(abs(qd)) < 0.7,
+        lambda _, qd: wp.length(qd) < 0.7,
     )

As per coding guidelines and static analysis hints. Based on learnings

newton/examples/cloth/example_cloth_twist.py (1)

292-305: Use Warp intrinsics in test lambdas; fix unused params.

Replace Python builtins and rename unused args to _.

Apply this diff:

     newton.examples.test_particle_state(
         self.state_0,
         "particles are within a reasonable volume",
-        lambda q, qd: newton.utils.vec_inside_limits(q, p_lower, p_upper),
+        lambda q, _: newton.utils.vec_inside_limits(q, p_lower, p_upper),
     )
     newton.examples.test_particle_state(
         self.state_0,
         "particle velocities are within a reasonable range",
-        lambda q, qd: max(abs(qd)) < 0.7,
+        lambda _, qd: wp.length(qd) < 0.7,
     )

As per coding guidelines and static analysis hints. Based on learnings

newton/examples/cloth/example_cloth_hanging.py (1)

187-204: Silence unused-arg lint and keep Warp-compiled lambdas minimal.

qd isn’t used; rename to _ to pass Ruff and keep the Warp-compiled callable clean.

Apply this diff:

     if self.solver_type != "style3d":
         # TODO(Style3D): handle ground collisions
         newton.examples.test_particle_state(
             self.state_0,
             "particles are above the ground",
-            lambda q, qd: q[2] > 0.0,
+            lambda q, _: q[2] > 0.0,
         )

     min_x = -float(self.sim_width) * 0.11
     p_lower = wp.vec3(min_x, -4.0, -1.8)
     p_upper = wp.vec3(0.1, 7.0, 4.0)
     newton.examples.test_particle_state(
         self.state_0,
         "particles are within a reasonable volume",
-        lambda q, qd: newton.utils.vec_inside_limits(q, p_lower, p_upper),
+        lambda q, _: newton.utils.vec_inside_limits(q, p_lower, p_upper),
     )

As per static analysis hints

newton/examples/__init__.py (2)

42-45: Handle Warp extension types without __dict__.

Core Newton types such as newton.Model, State, Control, and Contacts are Warp extension classes that don’t expose a Python __dict__. Hitting _find_nonfinite(model) therefore raises AttributeError, so the new --test flow exits before reporting non-finite buffers. Add a hasattr(obj, "__dict__") guard with a safe fallback iteration (e.g., dir() + getattr()) to keep the helper working across all Newton objects.

-    for key, attr in obj.__dict__.items():
+    if hasattr(obj, "__dict__"):
+        members = obj.__dict__.items()
+    else:
+        members = ((name, getattr(obj, name)) for name in dir(obj) if not name.startswith("_"))
+    for key, attr in members:

103-105: Coerce body keys to strings before joining.

model.body_key can contain NumPy/warp integers, so ", ".join(failed_bodies) throws TypeError when the failure path triggers. Convert each identifier to str() first so the error message is always constructed.

-        failed_bodies = body_key[np.where(failures_np)[0]]
-        raise ValueError(f'Test "{test_name}" failed for the following bodies: [{", ".join(failed_bodies)}]')
+        failed_bodies = body_key[np.where(failures_np)[0]]
+        failed_labels = ", ".join(str(key) for key in np.atleast_1d(failed_bodies))
+        raise ValueError(f'Test "{test_name}" failed for the following bodies: [{failed_labels}]')

Comment thread newton/examples/mpm/example_mpm_anymal.py
Comment thread newton/examples/robot/example_robot_humanoid.py
Comment thread newton/examples/robot/example_robot_policy.py
Comment thread newton/examples/selection/example_selection_cartpole.py
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
asv/benchmarks/simulation/bench_cloth.py (1)

52-55: Fix missing args in second run() call (will raise TypeError)

newton.examples.run now requires args; the call on Line 53 omits it and will fail at runtime. Apply the same args=None convention used above.

-        newton.examples.run(self.example)
+        newton.examples.run(self.example, args=None)

(Reference: run(example, args) in newton/examples/init.py.)

newton/examples/mpm/example_mpm_grain_rendering.py (1)

155-156: Use int for --points-per-particle.

This flag is a count and is passed to sample_render_grains(...); using float risks type issues.

-    parser.add_argument("--points-per-particle", "-ppp", type=float, default=8)
+    parser.add_argument("--points-per-particle", "-ppp", type=int, default=8)
🧹 Nitpick comments (3)
newton/examples/mpm/example_mpm_grain_rendering.py (1)

136-139: Avoid redundant np.prod on a scalar.

cell_volume is already a scalar; np.prod(cell_volume) is an unnecessary no-op.

-        cell_volume = np.prod(cell_size)
+        cell_volume = np.prod(cell_size)
 ...
-        mass = np.prod(cell_volume) * density
+        mass = cell_volume * density
newton/examples/__init__.py (1)

387-387: Export test_particle_state in all.

It’s used as a public helper by examples; export it for consistency.

-__all__ = ["create_parser", "init", "run", "test_body_state"]
+__all__ = ["create_parser", "init", "run", "test_body_state", "test_particle_state"]
newton/examples/mpm/example_mpm_granular.py (1)

76-81: Use the MPM-wrapped model to initialize states. Replace

self.state_0 = self.model.state()
self.state_1 = self.model.state()

with

self.state_0 = mpm_model.state()
self.state_1 = mpm_model.state()

to automatically allocate MPM‐specific buffers (you may then drop the redundant solver.enrich_state(…) calls).

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between caee6c5 and d5f4c5d.

📒 Files selected for processing (6)
  • asv/benchmarks/simulation/bench_cloth.py (1 hunks)
  • newton/examples/__init__.py (5 hunks)
  • newton/examples/mpm/example_mpm_grain_rendering.py (2 hunks)
  • newton/examples/mpm/example_mpm_granular.py (2 hunks)
  • newton/examples/mpm/example_mpm_multi_material.py (2 hunks)
  • newton/tests/test_examples.py (15 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-25T21:41:45.795Z
Learnt from: dylanturpin
PR: newton-physics/newton#634
File: newton/tests/test_examples.py:329-333
Timestamp: 2025-08-25T21:41:45.795Z
Learning: Newton examples use a centralized CLI argument parsing system in newton/examples/__init__.py. The create_parser() function defines common arguments like --device, --viewer, --output-path, and --num-frames, while init(parser) creates viewers based on parsed arguments. Individual example scripts don't need to define these flags themselves - they inherit them from the centralized system via the example_map and runpy execution.

Applied to files:

  • newton/examples/mpm/example_mpm_granular.py
  • newton/examples/mpm/example_mpm_multi_material.py
  • newton/tests/test_examples.py
  • newton/examples/__init__.py
  • newton/examples/mpm/example_mpm_grain_rendering.py
📚 Learning: 2025-08-27T19:05:44.697Z
Learnt from: Milad-Rakhsha-NV
PR: newton-physics/newton#535
File: newton/tests/test_examples.py:320-414
Timestamp: 2025-08-27T19:05:44.697Z
Learning: In newton/examples/__init__.py, the robot policy example is registered with the key "robot_policy" (not "robot.example_robot_policy"), so tests should reference it as name="robot_policy".

Applied to files:

  • newton/tests/test_examples.py
🧬 Code graph analysis (5)
asv/benchmarks/simulation/bench_cloth.py (2)
newton/examples/__init__.py (1)
  • run (164-202)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/mpm/example_mpm_granular.py (2)
newton/examples/__init__.py (2)
  • test_particle_state (108-161)
  • run (164-202)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/mpm/example_mpm_multi_material.py (2)
newton/examples/__init__.py (1)
  • test_particle_state (108-161)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/__init__.py (4)
newton/_src/sim/state.py (1)
  • State (21-112)
newton/_src/sim/contacts.py (1)
  • Contacts (23-93)
newton/_src/sim/control.py (1)
  • Control (21-77)
newton/tests/test_examples.py (1)
  • run (100-204)
newton/examples/mpm/example_mpm_grain_rendering.py (2)
newton/examples/__init__.py (1)
  • test_particle_state (108-161)
newton/tests/test_examples.py (1)
  • run (100-204)
🪛 Ruff (0.13.1)
newton/examples/mpm/example_mpm_granular.py

103-103: Unused lambda argument: qd

(ARG005)


112-112: Unused lambda argument: qd

(ARG005)

newton/examples/mpm/example_mpm_multi_material.py

108-108: Unused lambda argument: qd

(ARG005)

newton/tests/test_examples.py

91-91: Avoid specifying long messages outside the exception class

(TRY003)

newton/examples/__init__.py

91-91: Avoid specifying long messages outside the exception class

(TRY003)


105-105: Avoid specifying long messages outside the exception class

(TRY003)


148-148: Avoid specifying long messages outside the exception class

(TRY003)


161-161: Avoid specifying long messages outside the exception class

(TRY003)


186-186: Avoid specifying long messages outside the exception class

(TRY003)


190-190: Avoid specifying long messages outside the exception class

(TRY003)


194-194: Avoid specifying long messages outside the exception class

(TRY003)


198-198: Avoid specifying long messages outside the exception class

(TRY003)


202-202: Avoid specifying long messages outside the exception class

(TRY003)

newton/examples/mpm/example_mpm_grain_rendering.py

90-90: Unused lambda argument: qd

(ARG005)

🪛 GitHub Actions: Pull Request
newton/tests/test_examples.py

[error] 89-89: ImportError: Test module robot.example_robot_anymal_c_walk not found (likely due to missing torch dependency).

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run GPU Unit Tests on AWS EC2 (Pull Request)
  • GitHub Check: Run GPU Benchmarks (Pull Request)
🔇 Additional comments (5)
asv/benchmarks/simulation/bench_cloth.py (1)

38-38: Update to new run() signature looks good

Passing args=None is appropriate for benchmarks so the test-only paths in run() remain disabled.

newton/tests/test_examples.py (2)

224-224: Use underscore option keys for consistency (auto-converted to hyphens).

Prefer num_frames (and other underscored keys) so _build_command_line_options consistently emits the correct CLI flags.

-    test_options={"num-frames": 200},
+    test_options={"num_frames": 200},

Repeat similarly for other "num-frames" occurrences in this file.

Also applies to: 239-240, 251-251, 260-260, 269-271, 278-278, 285-285, 291-291, 305-306, 320-321, 342-343, 350-351, 466-467, 474-475, 482-483, 495-497, 505-506, 514-515, 523-524, 532-533, 546-547, 559-560, 567-568, 575-576


87-92: Don’t abort suite on missing example; register a skipped test instead.

Gracefully handle ImportError by registering a test that calls skip at runtime.

-    # verify the module exists
-    try:
-        importlib.import_module(f"newton.examples.{name}")
-    except ImportError as e:
-        raise ImportError(f"Test module {name} not found") from e
+    # verify the module exists; if missing, register a skipped test
+    try:
+        importlib.import_module(f"newton.examples.{name}")
+    except ImportError:
+        def _skip_missing(test, device):
+            test.skipTest(f"Test module {name} not found")
+        test_name = f"test_{name}_{test_suffix}" if test_suffix else f"test_{name}"
+        add_function_test(cls, test_name, _skip_missing, devices=devices, check_output=False)
+        return
newton/examples/__init__.py (2)

37-46: Make _find_nonfinite robust for objects without dict.

Some Newton/Warp types don’t expose __dict__; fall back to iterating attributes via dir(...).

-    for key, attr in obj.__dict__.items():
+    if hasattr(obj, "__dict__"):
+        members = obj.__dict__.items()
+    else:
+        members = ((name, getattr(obj, name)) for name in dir(obj) if not name.startswith("_"))
+    for key, attr in members:
         if isinstance(attr, wp.array):
             if not np.isfinite(attr.numpy()).all():
                 nonfinite_members.append(key)

103-106: Join failure labels as strings to avoid TypeError.

failed_bodies may contain non-strings (e.g., NumPy ints). Convert before joining.

-            raise ValueError(f'Test "{test_name}" failed for the following bodies: [{", ".join(failed_bodies)}]')
+            failed_labels = ", ".join(str(k) for k in failed_bodies.tolist())
+            raise ValueError(f'Test "{test_name}" failed for the following bodies: [{failed_labels}]')

Comment thread newton/examples/__init__.py
Comment thread newton/examples/mpm/example_mpm_grain_rendering.py
Comment thread newton/examples/mpm/example_mpm_granular.py
Comment thread newton/examples/mpm/example_mpm_multi_material.py
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>

@coderabbitai coderabbitai 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.

Actionable comments posted: 0

🧹 Nitpick comments (2)
asv/benchmarks/simulation/bench_cloth.py (2)

38-38: Prefer consistent positional None for clarity

In other examples we pass the second argument positionally. Using the keyword form here doesn’t add clarity—please stick with the positional None for consistency.


53-53: Optional: wrap args in Namespace for future-proofing

Although passing None works today, the runner now relies on args.test. Consider handing a namespace with .test = False so future option additions don’t require touching the benchmarks again. Example: newton.examples.run(self.example, SimpleNamespace(test=False)).

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d5f4c5d and 27849be.

📒 Files selected for processing (1)
  • asv/benchmarks/simulation/bench_cloth.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
asv/benchmarks/simulation/bench_cloth.py (2)
newton/examples/__init__.py (1)
  • run (164-202)
newton/tests/test_examples.py (1)
  • run (100-204)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run GPU Unit Tests on AWS EC2 (Pull Request)
  • GitHub Check: Run GPU Benchmarks (Pull Request)

@Kenny-Vilella

Copy link
Copy Markdown
Member

@eric-heiden We already saw these kind of error messages in the past.
The tests are now using 8 process in parallel, I wonder if it counts as 8 cpu, if yes then with 2 jobs per pipeline we will be limited by 4 pipelines at a time.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

♻️ Duplicate comments (7)
newton/examples/robot/example_robot_g1.py (1)

133-144: Critical: Lambda callbacks use Python-only operations that break Warp kernel compilation

The lambdas passed to test_body_state use Python indexing (q[2]) on a wp.transform and max(abs(qd)) on a wp.spatial_vector, which Warp cannot compile. When --test mode executes, the kernel generation will fail.

This is a duplicate of a previous review comment. Define Warp-compatible helpers using intrinsics like wp.transform_get_translation and wp.length:

+@wp.func
+def _body_above_ground(q: wp.transform, qd: wp.spatial_vector) -> bool:
+    return wp.transform_get_translation(q)[2] > 0.0
+
+@wp.func
+def _body_velocity_small(q: wp.transform, qd: wp.spatial_vector) -> bool:
+    return wp.length(qd.linear) < 1.0e-3 and wp.length(qd.angular) < 1.0e-3
+
     def test(self):
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "all bodies are above the ground",
-            lambda q, qd: q[2] > 0.0,
+            _body_above_ground,
         )
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "all body velocities are small",
-            lambda q, qd: max(abs(qd)) < 0.001,
+            _body_velocity_small,
         )
newton/examples/__init__.py (5)

42-42: Fix type hint: use wp.spatial_vector

The type hint uses wp.spatial_vectorf which is not a public Warp dtype. Use wp.spatial_vector instead:

-    test_fn: wp.Function | Callable[[wp.transform, wp.spatial_vectorf], bool],
+    test_fn: wp.Function | Callable[[wp.transform, wp.spatial_vector], bool],

94-94: Fix join on non-string body keys

model.body_key can contain integers. When a failure occurs, ", ".join(failed_bodies) will raise TypeError because NumPy integers aren't strings. Convert identifiers to strings:

-            raise ValueError(f'Test "{test_name}" failed for the following bodies: [{", ".join(failed_bodies)}]')
+            failed_labels = ", ".join(str(k) for k in failed_bodies.tolist())
+            raise ValueError(f'Test "{test_name}" failed for the following bodies: [{failed_labels}]')

136-137: Guard against missing particle buffers

state.particle_q or state.particle_qd may be None (e.g., rigid-only examples). Add an early guard before accessing particle_q.device:

     particle_q = state.particle_q
     particle_qd = state.particle_qd
+    if particle_q is None or particle_qd is None:
+        raise ValueError("Particle state is not available")

23-23: Critical: find_nan_members has blocking issues

The imported find_nan_members from newton.tests.unittest_utils has two critical problems based on past reviews and the provided snippet:

  1. Missing __dict__ guard: Newton core types (Model, State, Control, Contacts) are Warp extension classes without a Python __dict__. Accessing obj.__dict__ will raise AttributeError.

  2. Incomplete check: The function only checks for NaN using np.isnan() but should check for all nonfinite values (NaN, +inf, -inf) using np.isfinite().

These issues should be fixed in newton/tests/unittest_utils.py. Would you like me to generate a fix for that file?


378-378: Add test_particle_state to public exports

The test_particle_state function is a public helper but is not included in __all__:

-__all__ = ["create_parser", "init", "run", "test_body_state"]
+__all__ = ["create_parser", "init", "run", "test_body_state", "test_particle_state"]
newton/examples/basic/example_basic_shapes.py (1)

174-181: Use wp.abs and lookup mesh index dynamically

The lambda uses Python abs instead of wp.abs, and hardcodes the mesh body index as [4]. Replace with Warp intrinsics and dynamic lookup:

         # we only test that the bunny didn't fall through the ground and didn't slide too far
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "bunny at rest pose",
-            lambda q, qd: q[2] > 0.01 and abs(q[0]) < 0.1 and abs(q[1] - 4.0) < 0.1,
-            [4],
+            lambda q, qd: q.p[2] > 0.01 and wp.abs(q.p[0]) < 0.1 and wp.abs(q.p[1] - 4.0) < 0.1,
+            [self.model.body_key.index("mesh")],
         )

Note: Also changed q[2] to q.p[2] to properly access the position component of the transform.

🧹 Nitpick comments (1)
newton/examples/basic/example_basic_shapes.py (1)

138-173: Rename unused lambda parameters to underscore

All the test lambdas ignore the qd parameter. Rename to _ to indicate it's intentionally unused:

         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "sphere at rest pose",
-            lambda q, qd: newton.utils.vec_allclose(q, sphere_q, atol=1e-4),
+            lambda q, _: newton.utils.vec_allclose(q, sphere_q, atol=1e-4),
             [0],
         )
         # ... repeat for capsule, cylinder, box

Apply similar changes to lines 144, 153, 162, and 171.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a13302b and c4841ee.

📒 Files selected for processing (4)
  • newton/examples/__init__.py (5 hunks)
  • newton/examples/basic/example_basic_shapes.py (5 hunks)
  • newton/examples/robot/example_robot_allegro_hand.py (4 hunks)
  • newton/examples/robot/example_robot_g1.py (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-25T21:41:45.795Z
Learnt from: dylanturpin
PR: newton-physics/newton#634
File: newton/tests/test_examples.py:329-333
Timestamp: 2025-08-25T21:41:45.795Z
Learning: Newton examples use a centralized CLI argument parsing system in newton/examples/__init__.py. The create_parser() function defines common arguments like --device, --viewer, --output-path, and --num-frames, while init(parser) creates viewers based on parsed arguments. Individual example scripts don't need to define these flags themselves - they inherit them from the centralized system via the example_map and runpy execution.

Applied to files:

  • newton/examples/basic/example_basic_shapes.py
🧬 Code graph analysis (4)
newton/examples/basic/example_basic_shapes.py (4)
newton/_src/sim/builder.py (1)
  • add_body (1179-1241)
newton/_src/solvers/xpbd/solver_xpbd.py (1)
  • SolverXPBD (40-660)
newton/examples/__init__.py (2)
  • test_body_state (38-94)
  • run (153-193)
newton/_src/utils/__init__.py (1)
  • vec_allclose (200-207)
newton/examples/robot/example_robot_allegro_hand.py (3)
newton/_src/sim/builder.py (1)
  • body_count (515-519)
newton/examples/__init__.py (1)
  • test_body_state (38-94)
newton/_src/utils/__init__.py (1)
  • vec_inside_limits (211-218)
newton/examples/__init__.py (3)
newton/tests/unittest_utils.py (1)
  • find_nan_members (256-265)
newton/_src/sim/state.py (1)
  • State (21-112)
newton/tests/test_examples.py (1)
  • run (98-202)
newton/examples/robot/example_robot_g1.py (1)
newton/examples/__init__.py (2)
  • test_body_state (38-94)
  • run (153-193)
🪛 GitHub Actions: Pull Request
newton/examples/__init__.py

[error] 167-167: NotImplementedError: Example does not have a test method. Failure occurred while running 'coverage run --data-file=/tmp/tmpbpq29xfa/tmphjikd65l -m newton.examples.basic.example_basic_viewer --device cpu --test --viewer usd --output-path /home/runner/work/newton/newton/newton/tests/outputs/basic.example_basic_viewer_cpu.usd'.

🪛 Ruff (0.13.2)
newton/examples/basic/example_basic_shapes.py

144-144: Unused lambda argument: qd

(ARG005)


153-153: Unused lambda argument: qd

(ARG005)


162-162: Unused lambda argument: qd

(ARG005)


171-171: Unused lambda argument: qd

(ARG005)


179-179: Unused lambda argument: qd

(ARG005)

newton/examples/robot/example_robot_allegro_hand.py

210-210: Unused lambda argument: qd

(ARG005)

newton/examples/__init__.py

80-80: Avoid specifying long messages outside the exception class

(TRY003)


94-94: Avoid specifying long messages outside the exception class

(TRY003)


137-137: Avoid specifying long messages outside the exception class

(TRY003)


150-150: Avoid specifying long messages outside the exception class

(TRY003)


177-177: Avoid specifying long messages outside the exception class

(TRY003)


181-181: Avoid specifying long messages outside the exception class

(TRY003)


185-185: Avoid specifying long messages outside the exception class

(TRY003)


189-189: Avoid specifying long messages outside the exception class

(TRY003)


193-193: Avoid specifying long messages outside the exception class

(TRY003)

newton/examples/robot/example_robot_g1.py

137-137: Unused lambda argument: qd

(ARG005)


143-143: Unused lambda argument: q

(ARG005)

Comment thread newton/examples/robot/example_robot_allegro_hand.py
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

♻️ Duplicate comments (2)
newton/examples/__init__.py (1)

92-94: Convert body keys to strings before joining.

failed_bodies can contain non-string keys (e.g., NumPy ints), so ", ".join(failed_bodies) raises TypeError. Convert each key to str before joining to keep the failure path working.

-            failed_bodies = body_key[np.where(failures_np)[0]]
-            raise ValueError(f'Test "{test_name}" failed for the following bodies: [{", ".join(failed_bodies)}]')
+            failed_bodies = body_key[np.where(failures_np)[0]]
+            failed_labels = ", ".join(str(key) for key in failed_bodies.tolist())
+            raise ValueError(f'Test "{test_name}" failed for the following bodies: [{failed_labels}]')
newton/examples/cloth/example_cloth_franka.py (1)

541-559: Replace Python builtins in Warp-compiled lambdas and rename unused args.

This is the same issue flagged in the previous review. The lambda test callbacks use Python builtins (max, abs) that are not Warp-compatible, and have unused parameters that should be renamed to _.

Apply the previously suggested fix:

         newton.examples.test_particle_state(
             self.state_0,
             "particles are within a reasonable volume",
-            lambda q, qd: newton.utils.vec_inside_limits(q, p_lower, p_upper),
+            lambda q, _: newton.utils.vec_inside_limits(q, p_lower, p_upper),
         )
         newton.examples.test_particle_state(
             self.state_0,
             "particle velocities are within a reasonable range",
-            lambda q, qd: max(abs(qd)) < 2.0,
+            lambda _, qd: wp.length(qd) < 2.0,
         )
         newton.examples.test_body_state(
             self.model,
             self.state_0,
             "body velocities are within a reasonable range",
-            lambda q, qd: max(abs(qd)) < 0.7,
+            lambda _, qd: wp.length(qd) < 0.7,
         )

If you need separate bounds for angular vs. linear velocity components, use:
wp.length(wp.spatial_top(qd)) < w_max and wp.length(wp.spatial_bottom(qd)) < v_max

🧹 Nitpick comments (1)
newton/examples/__init__.py (1)

41-44: Use the public Warp spatial-vector type.

Warp exposes wp.spatial_vector, not wp.spatial_vectorf. Keeping the annotation as-is risks AttributeError at import time on newer Warp builds. Swap to wp.spatial_vector for compatibility.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 66e6389 and e86ed1a.

📒 Files selected for processing (2)
  • newton/examples/__init__.py (6 hunks)
  • newton/examples/cloth/example_cloth_franka.py (9 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-25T21:41:45.795Z
Learnt from: dylanturpin
PR: newton-physics/newton#634
File: newton/tests/test_examples.py:329-333
Timestamp: 2025-08-25T21:41:45.795Z
Learning: Newton examples use a centralized CLI argument parsing system in newton/examples/__init__.py. The create_parser() function defines common arguments like --device, --viewer, --output-path, and --num-frames, while init(parser) creates viewers based on parsed arguments. Individual example scripts don't need to define these flags themselves - they inherit them from the centralized system via the example_map and runpy execution.

Applied to files:

  • newton/examples/cloth/example_cloth_franka.py
🧬 Code graph analysis (2)
newton/examples/cloth/example_cloth_franka.py (2)
newton/_src/sim/builder.py (1)
  • ModelBuilder (67-4471)
newton/examples/__init__.py (1)
  • run (153-193)
newton/examples/__init__.py (4)
newton/tests/unittest_utils.py (1)
  • find_nan_members (256-265)
newton/_src/sim/state.py (1)
  • State (21-112)
newton/tests/test_examples.py (1)
  • run (98-202)
newton/examples/cloth/example_cloth_franka.py (1)
  • test (541-559)
🪛 Ruff (0.13.2)
newton/examples/cloth/example_cloth_franka.py

547-547: Unused lambda argument: qd

(ARG005)


552-552: Unused lambda argument: q

(ARG005)


558-558: Unused lambda argument: q

(ARG005)

newton/examples/__init__.py

80-80: Avoid specifying long messages outside the exception class

(TRY003)


94-94: Avoid specifying long messages outside the exception class

(TRY003)


137-137: Avoid specifying long messages outside the exception class

(TRY003)


150-150: Avoid specifying long messages outside the exception class

(TRY003)


177-177: Avoid specifying long messages outside the exception class

(TRY003)


181-181: Avoid specifying long messages outside the exception class

(TRY003)


185-185: Avoid specifying long messages outside the exception class

(TRY003)


189-189: Avoid specifying long messages outside the exception class

(TRY003)


193-193: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run GPU Benchmarks (Pull Request)
  • GitHub Check: Run GPU Unit Tests on AWS EC2 (Pull Request)
🔇 Additional comments (5)
newton/examples/cloth/example_cloth_franka.py (5)

167-176: LGTM! ModelBuilder initialization simplified.

The removal of explicit gravity parameters and transformation arguments simplifies the initialization while maintaining correct behavior through default values and the gravity swap mechanism introduced later.


259-263: LGTM! Clever CUDA graph-compatible gravity swap.

The use of Warp arrays for gravity values enables swapping between zero gravity (robot solver) and earth gravity (cloth solver) via .assign() without invalidating CUDA graph captures. This maintains stable device memory pointers while allowing dynamic behavior changes.


506-521: LGTM! Correct gravity and particle simulation toggling.

The logic correctly disables particle simulation and applies zero gravity for the robot solver, then restores both settings for the cloth solver. The updated comment on line 506 clearly explains the intent.


537-539: LGTM! Updated to new render API.

The render method correctly uses the updated API, passing sim_time to begin_frame and logging state, aligning with the new render flow.


571-571: LGTM! Updated to new run() signature.

The addition of the args parameter aligns with the API change that enables test execution via the --test CLI flag and generic NaN validation.

Comment thread newton/examples/__init__.py
@eric-heiden

Copy link
Copy Markdown
Member Author

OK the tests are working now, thanks @Kenny-Vilella!

The test time is not worse than before this PR, it seems actually slightly faster: 20min vs 22min on main.
I will go ahead and merge it then to unblock the other examples PRs that are up to leverage the test functions from here.

@eric-heiden eric-heiden merged commit ca6bf6d into newton-physics:main Oct 2, 2025
12 of 13 checks passed
eric-heiden added a commit to eric-heiden/newton that referenced this pull request Jan 28, 2026
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
@coderabbitai coderabbitai Bot mentioned this pull request Jan 29, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Feb 6, 2026
4 tasks
mmacklin pushed a commit to mmacklin/newton that referenced this pull request Apr 7, 2026
Signed-off-by: Eric Heiden <eric-heiden@outlook.com>
@coderabbitai coderabbitai Bot mentioned this pull request May 6, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants