Skip to content

Conversation

@eric-heiden
Copy link
Member

@eric-heiden eric-heiden commented Jan 9, 2026

First part of the API refactoring we decided to do following the API audit.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced new math module with mathematical utilities for scalar and vector operations.
    • Added quaternion rotation computation between axes.
    • Enhanced terrain generation with configurable per-block parameters and randomization support.
  • Refactor

    • Reorganized math utilities into dedicated math module (moved from utils).
    • Renamed terrain generation functions for improved clarity and consistency.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 9, 2026

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

This PR reorganizes mathematical utility functions by creating a new newton.math submodule and moving 12 math utilities (boltzmann, smooth_max/min, leaky_max/min, vec operations) from newton.utils to the new module. Additionally, terrain generation functions are renamed for consistency: heightfield_to_meshcreate_mesh_heightfield and generate_terrain_gridcreate_mesh_terrain. All imports across examples and tests are updated accordingly.

Changes

Cohort / File(s) Summary
New Public API Module
newton/__init__.py, newton/math.py, newton/_src/math/__init__.py
Introduces new newton.math submodule exporting 12 mathematical utilities (boltzmann, smooth_max/min, leaky_max/min, vec_min/max, vec_leaky_min/max, vec_abs, vec_allclose, vec_inside_limits). Re-exported publicly via newton/math.py.
Utility Functions Relocation
newton/_src/utils/__init__.py
Removes 12 math utility functions previously defined here; retains check_conditional_graph_support and compute_world_offsets. Creates mismatch in __all__ list (references removed definitions).
Terrain API Renaming
newton/_src/geometry/__init__.py, newton/_src/geometry/terrain_generator.py, newton/geometry.py, newton/tests/test_terrain_generator.py
Renames heightfield_to_meshcreate_mesh_heightfield and generate_terrain_gridcreate_mesh_terrain across internal and public APIs. Updates function signatures and all call sites.
Core Type Enhancement
newton/_src/core/types.py
Adds quat_between_axes() method to Axis class for computing quaternion between two axes.
Import Path Updates – Examples (Basic/Selection)
newton/examples/basic/example_basic_shapes.py, newton/examples/selection/example_selection_cartpole.py
Updates vec_allclose calls from newton.utils to newton.math.
Import Path Updates – Examples (Cloth)
newton/examples/cloth/example_cloth_*.py (5 files)
Updates vec_inside_limits calls from newton.utils to newton.math in all cloth examples.
Import Path Updates – Examples (MPM/Robot)
newton/examples/mpm/example_mpm_*.py (2 files), newton/examples/robot/example_robot_allegro_hand.py, newton/examples/robot/example_robot_cartpole.py, newton/examples/robot/example_robot_anymal_c_walk.py
Updates math utility function imports from newton.utils to newton.math. Robot anymal example also updates terrain API usage to create_mesh_terrain with new parameters.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • mmacklin
  • nvtw
🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'WIP: API refactor' is vague and generic, using non-descriptive terms that don't convey meaningful information about the specific changes in the changeset. Consider using a more descriptive title that highlights the main change, such as 'Reorganize math utilities into newton.math module and rename terrain functions' or 'API refactor: consolidate math module and rename terrain generation functions'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

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

⚠️ Outside diff range comments (1)
newton/_src/geometry/terrain_generator.py (1)

414-456: Update the reference to the old function name in the docstring.

Line 423 states "This is a wrapper around heightfield_to_mesh" but the function has been renamed to create_mesh_heightfield. Update this reference for consistency.

📝 Proposed fix
-    This is a wrapper around heightfield_to_mesh that fits the terrain_funcs signature.
+    This is a wrapper around create_mesh_heightfield that fits the terrain_funcs signature.
🧹 Nitpick comments (14)
newton/_src/core/types.py (2)

168-172: Consider accepting AxisType parameter for greater API flexibility.

Based on learnings, the quat_between_axes function should accept AxisType parameters (strings, Axis enums, and integers). The current signature restricts other to only Axis enum values. Since this is part of an API refactoring and the Axis class already provides from_any() for type conversion, consider broadening the parameter type for better usability.

♻️ Proposed enhancement
-    def quat_between_axes(self, other: Axis) -> wp.quat:
+    def quat_between_axes(self, other: AxisType) -> wp.quat:
         """
         Return the quaternion between two axes.
         """
-        return wp.quat_between_vectors(self.to_vec3(), other.to_vec3())
+        return wp.quat_between_vectors(self.to_vec3(), Axis.from_any(other).to_vec3())

Based on learnings, the quat_between_axes function accepts AxisType parameters.


168-172: Enhance the docstring with parameter and return descriptions.

The docstring could be more informative by explaining what the returned quaternion represents, documenting parameters, and providing usage context.

📝 Suggested docstring enhancement
     def quat_between_axes(self, other: Axis) -> wp.quat:
         """
-        Return the quaternion between two axes.
+        Return the quaternion that rotates from this axis to another axis.
+
+        Args:
+            other (Axis): The target axis to rotate to.
+
+        Returns:
+            wp.quat: The quaternion representing the rotation from this axis to the target axis.
         """
         return wp.quat_between_vectors(self.to_vec3(), other.to_vec3())
newton/__init__.py (1)

109-120: LGTM! New math submodule correctly exposed in public API.

The math submodule is properly imported and added to __all__, following the project's incremental export pattern.

The noqa: E402 directive on line 109 appears unnecessary according to the static analysis tool and can be removed for cleaner code.

🧹 Optional cleanup
-from . import geometry, ik, math, selection, sensors, solvers, utils, viewer  # noqa: E402
+from . import geometry, ik, math, selection, sensors, solvers, utils, viewer
newton/examples/selection/example_selection_cartpole.py (1)

179-185: Use _qd for the unused lambda arg (and consider tolerance for q[2]).

The newton.math.vec_allclose(...) switch looks consistent with the refactor. Ruff reports qd unused here; renaming avoids ARG005 if it’s enforced.

Proposed diff
-            lambda q, qd: q[2] == 0.0 and newton.math.vec_allclose(q.q, wp.quat_identity()),
+            lambda q, _qd: q[2] == 0.0 and newton.math.vec_allclose(q.q, wp.quat_identity()),
newton/examples/robot/example_robot_allegro_hand.py (1)

212-236: Freeze loop-captured bounds in the hand-body lambda (and rename unused qd).

The newton.math.vec_inside_limits migration is good. For the hand-body check, freezing hand_lower/hand_upper via defaults removes reliance on # noqa: B023 and addresses Ruff’s unused qd.

Proposed diff
             newton.examples.test_body_state(
                 self.model,
                 self.state_0,
                 f"hand bodies from world {i} are close to the initial position",
-                lambda q, qd: newton.math.vec_inside_limits(q.p, hand_lower, hand_upper),  # noqa: B023
+                lambda q, _qd, lower=hand_lower, upper=hand_upper: newton.math.vec_inside_limits(q.p, lower, upper),
                 indices=hand_body_indices,
             )
newton/examples/mpm/example_mpm_granular.py (1)

156-165: Rename unused qd to _qd to satisfy Ruff ARG005 (if enforced).

The newton.math.vec_inside_limits switch looks correct.

Proposed diff
-                lambda q, qd: not newton.math.vec_inside_limits(q, cube_lower, cube_upper),
+                lambda q, _qd: not newton.math.vec_inside_limits(q, cube_lower, cube_upper),
newton/examples/cloth/example_cloth_bending.py (1)

147-153: Rename unused qd to _qd (Ruff ARG005).

newton.math.vec_inside_limits usage is consistent with the refactor.

Proposed diff
-            lambda q, qd: newton.math.vec_inside_limits(q, p_lower, p_upper),
+            lambda q, _qd: newton.math.vec_inside_limits(q, p_lower, p_upper),
newton/examples/cloth/example_cloth_twist.py (1)

295-301: Rename unused qd to _qd (Ruff ARG005).

API migration looks good.

Proposed diff
-            lambda q, qd: newton.math.vec_inside_limits(q, p_lower, p_upper),
+            lambda q, _qd: newton.math.vec_inside_limits(q, p_lower, p_upper),
newton/examples/mpm/example_mpm_anymal.py (1)

293-301: Fix Ruff ARG005 by marking the unused lambda arg as intentionally unused (keep signature).

Proposed diff
-            lambda q, qd: newton.math.vec_inside_limits(qd, forward_vel_min, forward_vel_max),
+            lambda _q, qd: newton.math.vec_inside_limits(qd, forward_vel_min, forward_vel_max),
newton/examples/cloth/example_cloth_franka.py (1)

558-565: Fix Ruff ARG005 by marking qd as intentionally unused in the predicate.

Proposed diff
-            lambda q, qd: newton.math.vec_inside_limits(q, p_lower, p_upper),
+            lambda q, _qd: newton.math.vec_inside_limits(q, p_lower, p_upper),
newton/examples/robot/example_robot_cartpole.py (1)

113-180: Fix Ruff ARG005 in test_final lambdas (keep the 2-arg predicate signature).

Proposed diff
-            lambda q, qd: q[2] == 0.0 and newton.math.vec_allclose(q.q, wp.quat_identity()),
+            lambda q, _qd: q[2] == 0.0 and newton.math.vec_allclose(q.q, wp.quat_identity()),
@@
-            lambda q, qd: newton.math.vec_allclose(qd, world0_cart_vel),
+            lambda _q, qd: newton.math.vec_allclose(qd, world0_cart_vel),
@@
-            lambda q, qd: newton.math.vec_allclose(qd, world0_pole1_vel),
+            lambda _q, qd: newton.math.vec_allclose(qd, world0_pole1_vel),
@@
-            lambda q, qd: newton.math.vec_allclose(qd, world0_pole2_vel),
+            lambda _q, qd: newton.math.vec_allclose(qd, world0_pole2_vel),
newton/examples/cloth/example_cloth_style3d.py (1)

176-183: Fix Ruff ARG005 by marking qd as intentionally unused in the predicate.

Proposed diff
-            lambda q, qd: newton.math.vec_inside_limits(q, p_lower, p_upper),
+            lambda q, _qd: newton.math.vec_inside_limits(q, p_lower, p_upper),
newton/examples/basic/example_basic_shapes.py (1)

165-218: Fix Ruff ARG005 in test_final lambdas by marking qd as unused (keep signature).

Proposed diff
-            lambda q, qd: newton.math.vec_allclose(q, sphere_q, atol=2e-4),
+            lambda q, _qd: newton.math.vec_allclose(q, sphere_q, atol=2e-4),
@@
-            lambda q, qd: newton.math.vec_allclose(q, ellipsoid_q, atol=2e-2),
+            lambda q, _qd: newton.math.vec_allclose(q, ellipsoid_q, atol=2e-2),
@@
-            lambda q, qd: newton.math.vec_allclose(q, capsule_q, atol=2e-4),
+            lambda q, _qd: newton.math.vec_allclose(q, capsule_q, atol=2e-4),
@@
-            lambda q, qd: newton.math.vec_allclose(q, box_q, atol=0.1),
+            lambda q, _qd: newton.math.vec_allclose(q, box_q, atol=0.1),
newton/examples/robot/example_robot_anymal_c_walk.py (1)

326-326: Unused lambda parameter could be replaced with underscore.

The lambda parameter q is unused in this test assertion. While this matches the expected signature of test_body_state, you could make the intent clearer by using _ instead of q.

♻️ Proposed refactor
-            lambda q, qd: newton.math.vec_inside_limits(qd, forward_vel_min, forward_vel_max),
+            lambda _, qd: newton.math.vec_inside_limits(qd, forward_vel_min, forward_vel_max),
📜 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 963344c and de272d2.

📒 Files selected for processing (22)
  • newton/__init__.py
  • newton/_src/core/types.py
  • newton/_src/geometry/__init__.py
  • newton/_src/geometry/terrain_generator.py
  • newton/_src/math/__init__.py
  • newton/_src/utils/__init__.py
  • newton/examples/basic/example_basic_shapes.py
  • newton/examples/cloth/example_cloth_bending.py
  • newton/examples/cloth/example_cloth_franka.py
  • newton/examples/cloth/example_cloth_h1.py
  • newton/examples/cloth/example_cloth_hanging.py
  • newton/examples/cloth/example_cloth_style3d.py
  • newton/examples/cloth/example_cloth_twist.py
  • newton/examples/mpm/example_mpm_anymal.py
  • newton/examples/mpm/example_mpm_granular.py
  • newton/examples/robot/example_robot_allegro_hand.py
  • newton/examples/robot/example_robot_anymal_c_walk.py
  • newton/examples/robot/example_robot_cartpole.py
  • newton/examples/selection/example_selection_cartpole.py
  • newton/geometry.py
  • newton/math.py
  • newton/tests/test_terrain_generator.py
💤 Files with no reviewable changes (1)
  • newton/_src/utils/init.py
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/geometry.py:16-22
Timestamp: 2025-08-12T17:51:37.474Z
Learning: In the Newton public API refactor, common geometry symbols like ParticleFlags and ShapeFlags are now exposed at the top level in newton/__init__.py rather than through newton.geometry. The newton/geometry.py module is intentionally focused only on broad-phase collision detection classes (BroadPhaseAllPairs, BroadPhaseExplicit, BroadPhaseSAP).
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/tests/test_ik.py:25-26
Timestamp: 2025-08-12T17:58:16.929Z
Learning: In the Newton physics engine codebase, it's acceptable for tests to import and use private `_src` internal modules and functions when needed for testing purposes, even though this breaks the public API boundary. This is an intentional project decision for test code.
📚 Learning: 2025-08-12T17:51:37.474Z
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/geometry.py:16-22
Timestamp: 2025-08-12T17:51:37.474Z
Learning: In the Newton public API refactor, common geometry symbols like ParticleFlags and ShapeFlags are now exposed at the top level in newton/__init__.py rather than through newton.geometry. The newton/geometry.py module is intentionally focused only on broad-phase collision detection classes (BroadPhaseAllPairs, BroadPhaseExplicit, BroadPhaseSAP).

Applied to files:

  • newton/geometry.py
  • newton/examples/cloth/example_cloth_bending.py
  • newton/examples/cloth/example_cloth_style3d.py
  • newton/tests/test_terrain_generator.py
  • newton/examples/basic/example_basic_shapes.py
  • newton/_src/math/__init__.py
  • newton/_src/geometry/__init__.py
  • newton/math.py
  • newton/examples/cloth/example_cloth_h1.py
  • newton/examples/cloth/example_cloth_franka.py
  • newton/examples/mpm/example_mpm_granular.py
  • newton/__init__.py
  • newton/examples/cloth/example_cloth_twist.py
  • newton/_src/geometry/terrain_generator.py
📚 Learning: 2025-08-12T17:58:00.815Z
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/_src/solvers/featherstone/kernels.py:18-20
Timestamp: 2025-08-12T17:58:00.815Z
Learning: In newton/_src/core/__init__.py, the function transform_twist is properly re-exported from the spatial module via "from .spatial import (..., transform_twist, ...)" and included in __all__, making it available for import as "from ...core import transform_twist" from other modules.

Applied to files:

  • newton/geometry.py
  • newton/_src/math/__init__.py
  • newton/_src/geometry/__init__.py
  • newton/math.py
  • newton/__init__.py
  • newton/examples/cloth/example_cloth_twist.py
📚 Learning: 2025-08-14T17:38:36.106Z
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 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/geometry.py
  • newton/_src/math/__init__.py
  • newton/_src/geometry/__init__.py
  • newton/math.py
  • newton/__init__.py
📚 Learning: 2025-08-12T17:58:16.929Z
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/tests/test_ik.py:25-26
Timestamp: 2025-08-12T17:58:16.929Z
Learning: In the Newton physics engine codebase, it's acceptable for tests to import and use private `_src` internal modules and functions when needed for testing purposes, even though this breaks the public API boundary. This is an intentional project decision for test code.

Applied to files:

  • newton/geometry.py
  • newton/examples/cloth/example_cloth_bending.py
  • newton/examples/cloth/example_cloth_style3d.py
  • newton/tests/test_terrain_generator.py
  • newton/examples/basic/example_basic_shapes.py
  • newton/_src/geometry/__init__.py
  • newton/math.py
  • newton/examples/cloth/example_cloth_h1.py
  • newton/examples/cloth/example_cloth_franka.py
  • newton/examples/mpm/example_mpm_granular.py
  • newton/__init__.py
  • newton/examples/cloth/example_cloth_twist.py
📚 Learning: 2025-11-28T11:12:40.805Z
Learnt from: camevor
Repo: newton-physics/newton PR: 1146
File: newton/examples/basic/example_basic_joints.py:206-213
Timestamp: 2025-11-28T11:12:40.805Z
Learning: In Newton's standard solvers (XPBD, SemiImplicit, SolverMuJoCo), spatial vectors in State.body_qd use the ordering (linear, angular): wp.spatial_top(qd) returns linear velocity and wp.spatial_bottom(qd) returns angular velocity. This is the opposite of typical Modern Robotics spatial twist notation where (angular, linear) is used.

Applied to files:

  • newton/examples/selection/example_selection_cartpole.py
  • newton/examples/robot/example_robot_cartpole.py
📚 Learning: 2025-12-12T08:45:43.428Z
Learnt from: nvtw
Repo: newton-physics/newton PR: 1221
File: newton/examples/example_sdf.py:277-287
Timestamp: 2025-12-12T08:45:43.428Z
Learning: In Newtown (Newton) example code, specifically files under newton/examples, computing contacts once per frame and reusing them across all substeps is an intentional design choice, not a bug. Reviewers should verify that contacts are computed before the substep loop and reused for every substep within the same frame. This pattern reduces redundant work and preserves frame-consistency; do not flag as a regression unless the behavior is changed for correctness or performance reasons.

Applied to files:

  • newton/examples/selection/example_selection_cartpole.py
  • newton/examples/cloth/example_cloth_bending.py
  • newton/examples/cloth/example_cloth_style3d.py
  • newton/examples/basic/example_basic_shapes.py
  • newton/examples/cloth/example_cloth_hanging.py
  • newton/examples/mpm/example_mpm_anymal.py
  • newton/examples/robot/example_robot_anymal_c_walk.py
  • newton/examples/robot/example_robot_cartpole.py
  • newton/examples/cloth/example_cloth_h1.py
  • newton/examples/cloth/example_cloth_franka.py
  • newton/examples/mpm/example_mpm_granular.py
  • newton/examples/robot/example_robot_allegro_hand.py
  • newton/examples/cloth/example_cloth_twist.py
📚 Learning: 2025-07-15T21:00:03.709Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 394
File: newton/tests/test_ik.py:119-119
Timestamp: 2025-07-15T21:00:03.709Z
Learning: In the Newton physics engine codebase, it's acceptable to test private API functions (those prefixed with underscore) in unit and component tests, as the maintainers consider this appropriate for testing internal functionality.

Applied to files:

  • newton/examples/cloth/example_cloth_style3d.py
📚 Learning: 2025-12-12T17:45:26.847Z
Learnt from: vastsoun
Repo: newton-physics/newton PR: 1019
File: newton/_src/solvers/kamino/geometry/primitives.py:0-0
Timestamp: 2025-12-12T17:45:26.847Z
Learning: In newton/_src/solvers/kamino/geometry/primitives.py, the narrow-phase kernel `_primitive_narrowphase` does not need to handle symmetric shape-pair orderings (e.g., both SPHERE-BOX and BOX-SPHERE) because `kamino.core.builder.ModelBuilder` and `kamino.geometry.primitive.broadphase` guarantee that explicit candidate geometry pairs are always defined with GIDs in ascending order.

Applied to files:

  • newton/examples/basic/example_basic_shapes.py
📚 Learning: 2025-08-20T03:30:16.037Z
Learnt from: eric-heiden
Repo: newton-physics/newton PR: 584
File: newton/_src/utils/import_urdf.py:159-167
Timestamp: 2025-08-20T03:30:16.037Z
Learning: In the URDF importer (newton/_src/utils/import_urdf.py), cylinders are intentionally created using add_shape_capsule() instead of add_shape_cylinder() because cylinder collisions are not fully supported yet. This is a deliberate workaround until proper cylinder collision support is implemented.

Applied to files:

  • newton/examples/basic/example_basic_shapes.py
📚 Learning: 2025-08-12T05:17:34.423Z
Learnt from: shi-eric
Repo: newton-physics/newton PR: 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/_src/math/__init__.py
📚 Learning: 2025-08-12T17:58:00.815Z
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/_src/solvers/featherstone/kernels.py:18-20
Timestamp: 2025-08-12T17:58:00.815Z
Learning: In newton/_src/core/__init__.py, the function transform_twist is re-exported from the spatial module via "from .spatial import transform_twist", making it available for import as "from ...core import transform_twist" from other modules.

Applied to files:

  • newton/math.py
  • newton/__init__.py
  • newton/examples/cloth/example_cloth_twist.py
📚 Learning: 2025-08-12T18:04:06.287Z
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/_src/utils/import_usd.py:364-365
Timestamp: 2025-08-12T18:04:06.287Z
Learning: The quat_between_axes function in Newton accepts AxisType parameters, which includes strings like "X", "Y", "Z" as well as Axis enum values and integers. The function internally handles conversion using Axis.from_any(), so passing strings directly to quat_between_axes is valid and correct behavior.

Applied to files:

  • newton/_src/core/types.py
📚 Learning: 2025-08-12T18:04:06.287Z
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/_src/utils/import_usd.py:364-365
Timestamp: 2025-08-12T18:04:06.287Z
Learning: The quat_between_axes function in Newton accepts AxisType parameters, which includes both Axis enum values and strings. The function internally handles string-to-Axis conversion using Axis.from_any(), so passing strings directly to quat_between_axes is valid and correct.

Applied to files:

  • newton/_src/core/types.py
📚 Learning: 2025-08-18T15:56:26.587Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 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/_src/core/types.py
📚 Learning: 2025-12-12T16:25:54.685Z
Learnt from: vastsoun
Repo: newton-physics/newton PR: 1019
File: newton/_src/solvers/kamino/core/math.py:248-255
Timestamp: 2025-12-12T16:25:54.685Z
Learning: In newton/_src/solvers/kamino/core/math.py, the quat_conj function's current implementation (negating w instead of x,y,z) is a known issue that will be revised in a future PR per vastsoun's decision, not to be flagged in current Kamino reviews.

Applied to files:

  • newton/_src/core/types.py
📚 Learning: 2025-08-27T19:05:44.697Z
Learnt from: Milad-Rakhsha-NV
Repo: newton-physics/newton PR: 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_cartpole.py
📚 Learning: 2025-10-29T14:55:48.171Z
Learnt from: gdaviet
Repo: newton-physics/newton PR: 940
File: newton/examples/mpm/example_mpm_granular.py:92-101
Timestamp: 2025-10-29T14:55:48.171Z
Learning: In newton/examples/mpm/example_mpm_granular.py, the capture() method intentionally advances the simulation state once during CUDA graph capture. This is expected behavior because CUDA graph capture records exact memory addresses, so the state arrays (state_0, state_1) cannot be reset or reallocated after capture without invalidating the graph.

Applied to files:

  • newton/examples/mpm/example_mpm_granular.py
🧬 Code graph analysis (17)
newton/geometry.py (1)
newton/_src/geometry/terrain_generator.py (2)
  • create_mesh_heightfield (605-724)
  • create_mesh_terrain (459-553)
newton/examples/selection/example_selection_cartpole.py (1)
newton/_src/math/__init__.py (1)
  • vec_allclose (196-203)
newton/examples/cloth/example_cloth_bending.py (1)
newton/_src/math/__init__.py (1)
  • vec_inside_limits (207-214)
newton/examples/cloth/example_cloth_style3d.py (1)
newton/_src/math/__init__.py (1)
  • vec_inside_limits (207-214)
newton/tests/test_terrain_generator.py (1)
newton/_src/geometry/terrain_generator.py (2)
  • create_mesh_heightfield (605-724)
  • create_mesh_terrain (459-553)
newton/examples/basic/example_basic_shapes.py (1)
newton/_src/math/__init__.py (1)
  • vec_allclose (196-203)
newton/examples/cloth/example_cloth_hanging.py (1)
newton/_src/math/__init__.py (1)
  • vec_inside_limits (207-214)
newton/_src/geometry/__init__.py (1)
newton/_src/geometry/terrain_generator.py (2)
  • create_mesh_heightfield (605-724)
  • create_mesh_terrain (459-553)
newton/math.py (1)
newton/_src/math/__init__.py (12)
  • boltzmann (22-40)
  • leaky_max (84-97)
  • leaky_min (101-114)
  • smooth_max (44-60)
  • smooth_min (64-80)
  • vec_abs (182-192)
  • vec_allclose (196-203)
  • vec_inside_limits (207-214)
  • vec_leaky_max (165-178)
  • vec_leaky_min (148-161)
  • vec_max (133-144)
  • vec_min (118-129)
newton/examples/mpm/example_mpm_anymal.py (1)
newton/_src/math/__init__.py (1)
  • vec_inside_limits (207-214)
newton/examples/robot/example_robot_anymal_c_walk.py (2)
newton/_src/geometry/terrain_generator.py (1)
  • create_mesh_terrain (459-553)
newton/_src/math/__init__.py (1)
  • vec_inside_limits (207-214)
newton/examples/robot/example_robot_cartpole.py (1)
newton/_src/math/__init__.py (1)
  • vec_allclose (196-203)
newton/examples/cloth/example_cloth_h1.py (1)
newton/_src/math/__init__.py (1)
  • vec_inside_limits (207-214)
newton/examples/cloth/example_cloth_franka.py (1)
newton/_src/math/__init__.py (1)
  • vec_inside_limits (207-214)
newton/examples/mpm/example_mpm_granular.py (1)
newton/_src/math/__init__.py (1)
  • vec_inside_limits (207-214)
newton/examples/robot/example_robot_allegro_hand.py (1)
newton/_src/math/__init__.py (1)
  • vec_inside_limits (207-214)
newton/examples/cloth/example_cloth_twist.py (1)
newton/_src/math/__init__.py (1)
  • vec_inside_limits (207-214)
🪛 Ruff (0.14.10)
newton/examples/selection/example_selection_cartpole.py

183-183: Unused lambda argument: qd

(ARG005)

newton/examples/cloth/example_cloth_bending.py

152-152: Unused lambda argument: qd

(ARG005)

newton/examples/cloth/example_cloth_style3d.py

182-182: Unused lambda argument: qd

(ARG005)

newton/examples/basic/example_basic_shapes.py

172-172: Unused lambda argument: qd

(ARG005)


182-182: Unused lambda argument: qd

(ARG005)


191-191: Unused lambda argument: qd

(ARG005)


216-216: Unused lambda argument: qd

(ARG005)

newton/examples/cloth/example_cloth_hanging.py

201-201: Unused lambda argument: qd

(ARG005)

newton/examples/mpm/example_mpm_anymal.py

299-299: Unused lambda argument: q

(ARG005)

newton/examples/robot/example_robot_anymal_c_walk.py

326-326: Unused lambda argument: q

(ARG005)

newton/examples/robot/example_robot_cartpole.py

119-119: Unused lambda argument: qd

(ARG005)


164-164: Unused lambda argument: q

(ARG005)


171-171: Unused lambda argument: q

(ARG005)


178-178: Unused lambda argument: q

(ARG005)

newton/examples/cloth/example_cloth_h1.py

315-315: Unused lambda argument: qd

(ARG005)

newton/examples/cloth/example_cloth_franka.py

564-564: Unused lambda argument: qd

(ARG005)

newton/examples/mpm/example_mpm_granular.py

164-164: Unused lambda argument: qd

(ARG005)

newton/examples/robot/example_robot_allegro_hand.py

220-220: Unused lambda argument: qd

(ARG005)

newton/__init__.py

109-109: Unused noqa directive (non-enabled: E402)

Remove unused noqa directive

(RUF100)

newton/examples/cloth/example_cloth_twist.py

300-300: Unused lambda argument: qd

(ARG005)

🔇 Additional comments (15)
newton/_src/core/types.py (1)

168-172: No action needed. wp.quat_between_vectors is available and already used throughout the Newton codebase (in tests, examples, and production code). Since Newton requires nightly Warp builds (specifically >=1.11.0.dev20251205), version compatibility concerns with older stable versions are not applicable to this project.

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

35-35: LGTM! Terrain function names updated consistently.

The import and export statements correctly reflect the renamed terrain generation functions (create_mesh_terrain and create_mesh_heightfield), maintaining consistency with the underlying implementation changes.

Also applies to: 70-71

newton/_src/geometry/terrain_generator.py (2)

459-553: LGTM! Enhanced terrain generation API with expanded parameters.

The function rename to create_mesh_terrain follows a clearer naming convention. The addition of terrain_params and seed parameters significantly enhances flexibility while maintaining backward compatibility through sensible defaults.


605-724: LGTM! Improved heightfield API with explicit positioning parameters.

The rename to create_mesh_heightfield is more descriptive. The expanded signature with explicit center_x, center_y, and ground_z parameters (replacing implicit extent_width/extent_height naming) improves API clarity. Comprehensive validation and documentation are excellent.

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

201-201: LGTM! Namespace updated to use newton.math module.

The reference to vec_inside_limits has been correctly updated to use the new newton.math namespace as part of the API refactor.

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

315-315: LGTM! Namespace updated to use newton.math module.

The reference to vec_inside_limits has been correctly updated to use the new newton.math namespace, consistent with the API refactor.

newton/math.py (1)

1-45: LGTM! Clean public API surface for math utilities.

The module correctly re-exports math functions from the internal _src.math implementation and follows the project's conventions for public API modules. The __all__ list is properly aligned with imports.

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

36-36: LGTM! Import updated for API refactor.

The import correctly uses the new create_mesh_terrain function name.


110-120: LGTM! Terrain generation enhanced with parameterization.

The call to create_mesh_terrain correctly uses the new API with extended parameters (terrain_params and seed), enabling more detailed terrain configuration.

newton/tests/test_terrain_generator.py (3)

28-29: LGTM! Test imports updated for API refactor.

The imports correctly use the new function names create_mesh_heightfield and create_mesh_terrain.


46-219: LGTM! All heightfield test calls updated consistently.

All test cases for create_mesh_heightfield (formerly heightfield_to_mesh) have been updated with the new function name while preserving the same parameter structure and test logic.


394-432: LGTM! All terrain grid test calls updated consistently.

All test cases for create_mesh_terrain (formerly generate_terrain_grid) have been updated with the new function name while maintaining the same test coverage.

newton/geometry.py (2)

32-33: LGTM! Public API imports updated for terrain generation.

The imports correctly reference the renamed functions create_mesh_heightfield and create_mesh_terrain.


62-63: LGTM! Public API exports updated consistently.

The __all__ list correctly exposes the renamed terrain generation functions.

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

1-230: LGTM! Well-implemented math utilities for Warp.

The module provides a comprehensive set of differentiable math utilities with clear documentation:

  • Smooth approximations (Boltzmann, smooth_max/min, leaky_max/min) for gradient-based optimization
  • Elementwise vector operations properly handle wp.vec3 types
  • Generic utilities (vec_allclose, vec_inside_limits) use wp.static(len(a)) for compile-time iteration
  • All functions correctly decorated with @wp.func for device compatibility

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.

1 participant