Skip to content

Integrate environment groups with collision detection system #605#615

Merged
eric-heiden merged 15 commits into
newton-physics:mainfrom
vreutskyy:605-integrate-environment-groups-with-collision-detection-system
Aug 29, 2025
Merged

Integrate environment groups with collision detection system #605#615
eric-heiden merged 15 commits into
newton-physics:mainfrom
vreutskyy:605-integrate-environment-groups-with-collision-detection-system

Conversation

@vreutskyy

@vreutskyy vreutskyy commented Aug 22, 2025

Copy link
Copy Markdown
Member

Description

This PR integrates environment groups with the collision detection system in Newton, enabling efficient multi-environment simulations where entities from different environments don't collide with each other.

Key Changes:

  1. Unified Environment and Collision Group Filtering

    • Added test_environment_and_group_pair() function in broad_phase_common.py that handles both environment and collision group filtering
    • Environment group -1 represents global entities that collide with all environments
    • Entities from different environments (except -1) do not collide
  2. Updated Collision Detection Pipeline

    • Modified ModelBuilder.find_shape_contact_pairs() to filter shape pairs based on environment groups
    • Updated broadphase kernels (_nxn_broadphase_kernel and _sap_broadphase_kernel) to pass and utilize environment group information
    • Modified create_soft_contacts kernel to check particle vs shape environment groups
  3. API Changes

    • BREAKING: Removed separate_collision_group parameter from ModelBuilder.add_builder()
    • Environment groups now handle cross-environment contact filtering, making the collision group manipulation redundant

Limitations:

  • VBD solver's self-collision detection has not been updated to respect particle_group environment boundaries (deferred due to complexity)

Example Usage:

builder = ModelBuilder()

# Global ground plane
builder.current_env_group = -1
builder.add_shape_plane()

# Environment 0 robot
builder.current_env_group = 0
builder.add_body(...)

# Environment 1 robot (won't collide with env 0)
builder.current_env_group = 1 
builder.add_body(...)

Newton Migration Guide

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

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

Before your PR is "Ready for review"

  • All commits are signed-off to indicate that your contribution adheres to the Developer Certificate of Origin requirements
  • Necessary tests have been added and new examples are tested (see newton/tests/test_examples.py)
    • Added comprehensive tests in newton/tests/test_environment_group_collision.py
    • Updated existing tests to work with API changes
  • Documentation is up-to-date
    • Updated ModelBuilder docstring to explain environment grouping
    • Added documentation to new functions
  • Code passes formatting and linting checks with pre-commit run -a

Summary by CodeRabbit

  • New Features

    • Environment-aware collision filtering: collisions respect per-environment groups with a global (-1) override across broadphase and soft-contact generation.
  • Refactor

    • Model builder APIs replaced a boolean collision-group flag with an explicit environment parameter; merging and pair-generation simplified using environment rules.
  • Tests

    • New and updated tests covering environment-group collision behavior and broadphase correctness.
  • Chores

    • Examples updated to match the new add_builder signature.

@coderabbitai

coderabbitai Bot commented Aug 22, 2025

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds environment-aware collision filtering: new test_environment_and_group_pair predicate; broadphase kernels (NxN, SAP) and soft-contact kernel accept per-entity environment groups; ModelBuilder and Style3D builder APIs updated to use environment indices; tests and examples adjusted to exercise environment semantics (global = -1).

Changes

Cohort / File(s) Summary
Environment/group predicate
newton/_src/geometry/broad_phase_common.py
Add test_environment_and_group_pair(env_group_a, env_group_b, collision_group_a, collision_group_b) that first excludes pairs from different non-global environments, then defers to existing collision-group check.
Broadphase N×N
newton/_src/geometry/broad_phase_nxn.py
Kernel and launch signatures accept shape_group (geom_shape_group); pair emission now requires AABB overlap and test_environment_and_group_pair to return true; renamed geom_collision_groupsgeom_collision_group.
Broadphase SAP
newton/_src/geometry/broad_phase_sap.py
_sap_broadphase_kernel and BroadPhaseSAP.launch gain shape_group/geom_shape_group; replace test_group_pair with test_environment_and_group_pair; docs updated.
Soft-contact kernel
newton/_src/geometry/kernels.py
create_soft_contacts adds particle_group and shape_group parameters; early-return if particle and shape envs are both defined and different.
Builder & merging
newton/_src/sim/builder.py
Remove separate_collision_group; add_builder signature now uses environment; merging preserves source collision groups and applies runtime environment filtering; canonicalize stored filter pairs.
Collision driver
newton/_src/sim/collide.py
Pass model.particle_group and model.shape_group into create_soft_contacts; invocation order updated to match new kernel signature.
Style3D builder API
newton/_src/sim/style3d/builder_style3d.py
Replace separate_collision_group: bool with `environment: int
Tests: broadphase updates
newton/tests/test_broad_phase.py
Create shape_group array (all -1) and pass to NxN and SAP launch calls.
Tests: new env-group suite
newton/tests/test_environment_group_collision.py
New tests validating environment-based filtering for shapes, particles, builder assignment, mixed env/collision-group interactions, and kernel utility.
Tests/examples: callsite updates
newton/tests/test_model.py, newton/tests/test_mujoco_solver.py, newton/examples/cloth/example_cloth_franka.py
Remove separate_collision_group argument from add_builder calls to match new API.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Builder as ModelBuilder
  participant Broadphase as BroadPhase (NxN / SAP)
  participant Common as test_environment_and_group_pair
  participant Kernel as create_soft_contacts

  Builder->>Broadphase: launch(..., collision_group[], shape_group[])
  Broadphase->>Broadphase: check AABB overlap
  Broadphase->>Common: test_environment_and_group_pair(envA, envB, grpA, grpB)
  alt envs compatible & groups compatible
    Broadphase-->>Builder: emit candidate pair
  else incompatible
    Broadphase-->>Builder: skip pair
  end

  Builder->>Kernel: create_soft_contacts(..., particle_group[], shape_group[])
  Kernel->>Kernel: if particle_env != -1 && shape_env != -1 && differ -> return (no contact)
  Kernel-->>Builder: produce contact(s) if not filtered
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • mmacklin
  • adenzler-nvidia

📜 Recent review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8350993 and 3c4068c.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • newton/tests/test_mujoco_solver.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • newton/tests/test_mujoco_solver.py
⏰ 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). (4)
  • GitHub Check: Run GPU Benchmarks (Pull Request)
  • GitHub Check: Run GPU Unit Tests on AWS EC2 (Pull Request)
  • GitHub Check: run-newton-tests / newton-unittests (windows-latest)
  • GitHub Check: run-newton-tests / newton-unittests (ubuntu-latest)
✨ 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.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

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/broad_phase_sap.py (1)

342-353: Docstring says geom_shape_groups “can be None” but code requires an array

Either handle None by substituting a -1 array, or remove the “can be None” note. Handling None is more user-friendly. Suggestion below.

     def launch(
         self,
@@
-        geom_shape_groups: wp.array,  # Environment group ID per box (dtype=int, ndim=1)
+        geom_shape_groups: wp.array | None,  # Environment group ID per box (dtype=int, ndim=1)
@@
-        The method also handles collision filtering based on both environment groups and collision groups.
+        The method also handles collision filtering based on both environment groups and collision groups.
@@
-                Can be None if environment groups are not used.
+                If None, all elements default to the global environment (-1).

And initialize default -1 groups near the kernel launch:

@@
-        wp.launch(
+        # Default to global environment if not provided
+        if geom_shape_groups is None:
+            # requires: import numpy as np at module scope
+            geom_shape_groups = wp.array(np.full(geom_count, -1, dtype=np.int32), dtype=wp.int32)
+
+        wp.launch(
             kernel=_sap_broadphase_kernel,

Add missing import at the top if needed:

-import warp as wp
+import warp as wp
+import numpy as np
🧹 Nitpick comments (15)
newton/tests/test_mujoco_solver.py (1)

234-241: Make the ground plane global so both environments collide with it.

With environment-group filtering, shapes inherit the builder’s current_env_group. The plane is added before the per-env sub-builders and will default to the current (non-global) group, so only env 0 collides with it. Mark it as global (-1) to share across all envs.

Apply this diff near the plane creation:

-        self.builder.add_shape_plane()
+        # Share the plane across all environments
+        prev_env = self.builder.current_env_group
+        self.builder.current_env_group = -1
+        self.builder.add_shape_plane()
+        self.builder.current_env_group = prev_env
newton/examples/example_robot_manipulating_cloth.py (1)

208-215: API change adoption looks correct.

Switching to builder.add_builder(articulation_builder, xform) matches the new signature. If this example later grows to multi-environment usage, consider passing environment explicitly or setting current_env_group accordingly to avoid unintended cross-env contacts.

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

89-120: Clarify docstring to avoid conflating env -1 with collision-group negatives.

Because collision_group negatives have special “collide with all except same negative” semantics, it’s worth explicitly stating that env_group -1 is unrelated to collision_group -1 and only means “global” for environments.

Apply this doc tweak:

-    Environment groups define which simulation environment an entity belongs to:
+    Environment groups define which simulation environment an entity belongs to:
     - Group -1: Global entities that collide with all environments
     - Groups 0, 1, 2, ...: Environment-specific entities
@@
-    3. Within the same environment, collision groups determine interactions
+    3. Within the same environment (or if one side is global), collision groups determine interactions
+
+    Note:
+        env_group values are independent from collision_group values. In particular,
+        env_group == -1 indicates a global environment membership and must not be
+        confused with collision_group < 0 semantics.
newton/_src/geometry/kernels.py (1)

646-654: Prefer explicit 32-bit types for group arrays (GPU portability).

Using dtype=int can map to 64-bit on some hosts. Declare particle_group and shape_group as wp.int32 to match other integer buffers and avoid implicit casts on device backends.

Apply this change to the kernel signature:

-    particle_group: wp.array(dtype=int),  # Environment groups for particles
+    particle_group: wp.array(dtype=wp.int32),  # Environment groups for particles
@@
-    shape_group: wp.array(dtype=int),  # Environment groups for shapes
+    shape_group: wp.array(dtype=wp.int32),  # Environment groups for shapes
newton/_src/sim/style3d/builder_style3d.py (2)

108-117: Docstring/API alignment for environment parameter

Good addition. Minor mismatch: the parent’s doc explains auto-increment vs. explicit environment behavior; here it still says “incremented by 1”. Align the wording with ModelBuilder.add_builder to avoid confusion.

-            update_num_env_count (bool): if True, the number of environments is incremented by 1.
-            environment (int | None): environment group index to assign to ALL entities from this builder.
+            update_num_env_count (bool): if True, the number of environments is updated appropriately.
+            environment (int | None): Environment group index to assign to ALL entities from this builder.
+                If None, uses the current environment count as the group index. Use -1 for global entities.

119-124: Type narrowness on builder (consider widening to base type)

builder: Style3DModelBuilder limits composition with plain ModelBuilder sub-builders. Consider typing as ModelBuilder (or a union) since you delegate to super().add_builder(...) anyway.

-        builder: Style3DModelBuilder,
+        builder: ModelBuilder,
newton/_src/sim/builder.py (2)

742-755: Offsetting collision pairs/group map before shape arrays are extended is safe—but fragile if re-ordered later

Using shape_count_offset = self.shape_count before extending shape arrays is correct because shape_count is based on shape_type, which hasn’t been extended yet. Add a short comment to future-proof against accidental reordering.

-        shape_count_offset = self.shape_count
+        # NOTE: shape_count is based on shape_type length, which hasn't been extended yet,
+        # so this offset points to the first index of the soon-to-be-appended shapes.
+        shape_count_offset = self.shape_count

4070-4099: Broadphase-precontact filtering by environment is correct and matches semantics

  • Skips cross-env pairs unless one side is global (-1).
  • Applies both for intra-group combinations and group -1 vs. others.
    Consider reusing the same predicate as the kernels for parity (e.g., test_environment_and_group_pair) to keep one source of truth, but current logic is equivalent.
-                # Skip shapes from different environments (unless one is global)
-                if env1 != -1 and env2 != -1 and env1 != env2:
-                    continue
+                # Skip shapes from different environments (unless one is global)
+                # Equivalent to test_environment_and_group_pair(env1, env2, _, _)
+                if env1 != -1 and env2 != -1 and env1 != env2:
+                    continue
newton/tests/test_broad_phase.py (2)

129-131: Passing shape_groups as global (-1) is a good baseline

This keeps parity with the numpy reference (which ignores envs). Consider adding a tiny focused test with two distinct env IDs to assert cross-env filtering at the broadphase level (there’s a separate test file, but a smoke check here helps).


386-388: SAP path parity with NXN

Same comment as above; baseline use is fine. A small follow-up asserting env-separated filtering would increase coverage symmetry.

newton/_src/geometry/broad_phase_nxn.py (4)

98-106: Filter on env+collision groups before AABB

Functionally correct. If you want a minor perf tweak, you could first do the cheap AABB overlap then group filtering, but difference is likely negligible vs. memory access here.


151-156: Launch signature: specify dtype for geom_shape_groups in the API

To match other params, annotate dtype in the signature comment and enforce at runtime (assert) for clearer errors.

-        geom_shape_groups: wp.array,  # Environment group ID per box (dtype=int, ndim=1)
+        geom_shape_groups: wp.array(dtype=int, ndim=1),  # Environment group ID per box (-1=global)

170-179: Docstring mentions collision-group-only test

Update the docstring to reference the env+group predicate and the new parameter.

-    2. Their collision groups allow interaction (determined by test_group_pair())
+    2. Their environment and collision groups allow interaction
+       (determined by test_environment_and_group_pair())

187-201: Optional: accept None for geom_shape_groups (default to global)

SAP’s doc mentions None (see separate comment); for API parity, you could optionally accept None here and substitute a -1-filled array. Not required if you prefer stricter typing.

-        wp.launch(
+        # (Optional) enable if you want to accept None:
+        # if geom_shape_groups is None:
+        #     geom_shape_groups = wp.array(np.full(geom_count, -1, dtype=np.int32), dtype=wp.int32)
+        wp.launch(
newton/_src/geometry/broad_phase_sap.py (1)

458-481: Kernel invocation includes env groups—good. Add a dtype assertion for clearer failures.

-        wp.launch(
+        # Defensive check for dtype/shape
+        assert geom_shape_groups.dtype == wp.int32 and geom_shape_groups.ndim == 1, \
+            "geom_shape_groups must be int32, 1D (values -1 for global or >=0 per environment)"
+        wp.launch(
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e15cac7 and 1f1e06a.

📒 Files selected for processing (12)
  • newton/_src/geometry/broad_phase_common.py (1 hunks)
  • newton/_src/geometry/broad_phase_nxn.py (6 hunks)
  • newton/_src/geometry/broad_phase_sap.py (8 hunks)
  • newton/_src/geometry/kernels.py (2 hunks)
  • newton/_src/sim/builder.py (4 hunks)
  • newton/_src/sim/collide.py (1 hunks)
  • newton/_src/sim/style3d/builder_style3d.py (1 hunks)
  • newton/examples/example_robot_manipulating_cloth.py (1 hunks)
  • newton/tests/test_broad_phase.py (2 hunks)
  • newton/tests/test_environment_group_collision.py (1 hunks)
  • newton/tests/test_model.py (0 hunks)
  • newton/tests/test_mujoco_solver.py (1 hunks)
💤 Files with no reviewable changes (1)
  • newton/tests/test_model.py
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: eric-heiden
PR: newton-physics/newton#587
File: newton/_src/sim/builder.py:656-661
Timestamp: 2025-08-20T18:02:36.042Z
Learning: In Newton physics, collisions between shapes with body index -1 (world-attached/global shapes) are automatically skipped by the collision system, so no manual collision filter pairs need to be added between global shapes from different builders.
📚 Learning: 2025-08-12T17:51:37.474Z
Learnt from: nvlukasz
PR: newton-physics/newton#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/tests/test_environment_group_collision.py
  • newton/_src/geometry/kernels.py
  • newton/_src/sim/collide.py
  • newton/tests/test_broad_phase.py
  • newton/_src/geometry/broad_phase_nxn.py
  • newton/_src/geometry/broad_phase_sap.py
📚 Learning: 2025-08-20T18:02:36.042Z
Learnt from: eric-heiden
PR: newton-physics/newton#587
File: newton/_src/sim/builder.py:656-661
Timestamp: 2025-08-20T18:02:36.042Z
Learning: In Newton physics, collisions between shapes with body index -1 (world-attached/global shapes) are automatically skipped by the collision system, so no manual collision filter pairs need to be added between global shapes from different builders.

Applied to files:

  • newton/_src/sim/builder.py
🧬 Code graph analysis (4)
newton/tests/test_environment_group_collision.py (2)
newton/_src/sim/builder.py (5)
  • ModelBuilder (67-4107)
  • ShapeConfig (142-194)
  • finalize (3719-4055)
  • add_particle (2687-2721)
  • add_builder (589-874)
newton/_src/sim/collide.py (2)
  • device (270-271)
  • collide (140-267)
newton/tests/test_mujoco_solver.py (2)
newton/_src/sim/builder.py (1)
  • add_builder (589-874)
newton/_src/sim/style3d/builder_style3d.py (1)
  • add_builder (103-133)
newton/_src/sim/style3d/builder_style3d.py (1)
newton/_src/sim/builder.py (1)
  • add_builder (589-874)
newton/examples/example_robot_manipulating_cloth.py (2)
newton/_src/sim/builder.py (1)
  • add_builder (589-874)
newton/_src/sim/style3d/builder_style3d.py (1)
  • add_builder (103-133)
⏰ 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). (4)
  • GitHub Check: Run GPU Benchmarks (Pull Request)
  • GitHub Check: Run GPU Unit Tests on AWS EC2 (Pull Request)
  • GitHub Check: run-newton-tests / newton-unittests (ubuntu-latest)
  • GitHub Check: run-newton-tests / newton-unittests (windows-latest)
🔇 Additional comments (21)
newton/tests/test_mujoco_solver.py (1)

237-241: API migration: add_builder call updated correctly.

Dropping separate_collision_group aligns with the new environment-group semantics. Call site looks good.

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

89-120: Environment-aware collision predicate is correct and minimal.

The early-return on different non-global envs followed by test_group_pair preserves intended semantics (global -1 interacts with all, per-env isolation otherwise).

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

674-681: Early env-group rejection is in the right place.

The check is before any expensive geometry work, after the standard ACTIVE/COLLIDE_PARTICLES gates. This minimizes cost for cross-env pairs.

newton/_src/sim/collide.py (2)

160-180: create_soft_contacts call site updated correctly (ordering matches kernel).

particle_group is passed after particle_flags; shape_group after shape_source_ptr; shape_flags after shape_count. Matches the kernel signature.


160-180: ✅ Verified create_soft_contacts kernel signature

All references to create_soft_contacts have been located, and the sole invocation in newton/_src/sim/collide.py (lines 160–180) passes the 15 inputs in the exact order of the updated kernel definition, with the outputs list matching the seven output parameters. No other call sites were found.

newton/_src/sim/builder.py (5)

603-607: Environment-group semantics: clear and correct

The added notes accurately capture the new rules (global -1 collides with all; other envs isolated; collision groups preserved). Nice.


640-646: Group index selection covers all cases; edge-case sanity

Logic for selecting group_idx with/without update_num_env_count is sound and matches the doc. No changes needed.


756-782: Uniform environment assignment across entity kinds

Overriding particle/body/shape/joint/articulation groups to current_env_group is consistent and easy to reason about. LGTM.


863-872: num_envs update correctly skips globals and respects explicit env indices

Update logic is correct for auto-increment vs. explicit indexing. No change.


589-595: No remaining references to separate_collision_group

I ran a global search for any usages of the removed separate_collision_group parameter and found none, so the change to the add_builder() signature does not break any call sites.

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

18-19: Importing combined predicate is the right call

Switch to test_environment_and_group_pair centralizes the policy. Good.

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

18-23: Good centralization on common helpers

Import set is tidy and consistent with NxN.


269-277: SAP pair filtering respects env+group policy

Correctly mirrors NxN behavior. LGTM.

newton/tests/test_environment_group_collision.py (8)

1-22: LGTM - Well-structured test module setup.

The imports and module structure look good. The import of test_environment_and_group_pair from the internal module is appropriate for testing the environment-aware collision filtering functionality.


24-30: LGTM - Standard test class setup.

The test class follows unittest conventions with proper setup method for device initialization.


31-86: LGTM - Comprehensive shape collision filtering test.

This test effectively validates the core environment group functionality:

  • Shapes in different environments (0 vs 1) correctly avoid collision
  • Global environment (-1) properly collides with all environments
  • The test assertions verify both negative (no cross-environment collision) and positive (global collisions) cases

The test design aligns well with the PR objectives for environment-aware collision detection.


87-122: LGTM - Thorough particle-shape collision filtering test.

This test validates the particle collision filtering works correctly with environment groups:

  • Particle in environment 0 doesn't collide with shape in environment 1
  • Particle correctly collides with global shape (environment -1)
  • Proper verification of soft contact counts and contact shape indices

This addresses the particle collision aspect mentioned in the PR objectives.


123-178: LGTM - Excellent test for add_builder environment assignment.

This test thoroughly validates the add_builder functionality:

  • Environment groups are correctly assigned when adding builders
  • Both shape and body groups are properly set
  • Collision groups are preserved during the builder merge process
  • The test covers the breaking API change mentioned in the PR where add_builder now handles environment groups

The assertions comprehensively verify the expected behavior described in the PR objectives.


179-260: LGTM - Comprehensive mixed collision and environment groups test.

This is an excellent stress test that validates the interaction between collision groups and environment groups:

  • Tests multiple environments with various collision group combinations
  • Verifies that environment isolation takes precedence over collision group compatibility
  • Only global environment (-1) can cross environment boundaries
  • The expected pairs calculation and verification is thorough and correct

This test ensures the complex interaction logic works as intended per the PR design.


262-299: LGTM - Thorough broadphase kernel testing.

This test validates the low-level test_environment_and_group_pair function with comprehensive test cases:

  • Covers same environment scenarios with different collision group combinations
  • Tests cross-environment isolation
  • Validates global environment (-1) behavior
  • Uses Warp kernels to test the actual GPU/CPU function implementation

The test cases cover all the important edge cases and align with the broadphase kernel changes mentioned in the PR.


301-304: LGTM - Proper test runner setup.

The kernel cache clearing and main runner setup is appropriate for Warp-based tests.

@codecov

codecov Bot commented Aug 22, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@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

Caution

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

⚠️ Outside diff range comments (1)
newton/_src/sim/builder.py (1)

4217-4224: Fix: constructing wp.array(vec2i) from an empty Python list can error — emit a shaped (0,2) array.

With environment filtering, it’s common to end up with zero contact pairs. Creating a wp.array(..., dtype=wp.vec2i) from an empty list (no shape) is fragile. Emit an (0, 2) int32 ndarray first.

Apply:

-        model.shape_contact_pairs = wp.array(np.array(contact_pairs), dtype=wp.vec2i, device=model.device)
-        model.shape_contact_pair_count = len(contact_pairs)
+        if contact_pairs:
+            pairs_np = np.asarray(contact_pairs, dtype=np.int32).reshape(-1, 2)
+        else:
+            pairs_np = np.empty((0, 2), dtype=np.int32)
+        model.shape_contact_pairs = wp.array(pairs_np, dtype=wp.vec2i, device=model.device)
+        model.shape_contact_pair_count = int(pairs_np.shape[0])
🧹 Nitpick comments (2)
newton/_src/sim/builder.py (2)

665-669: Doc nit: spell out world-attached (-1 body) same-body filtering to avoid confusion with “global collides with all.”

The bullets are accurate but can be misread. Global env-group (-1) shapes still won’t collide with other shapes attached to the same world body (-1) because same-body collisions are filtered. Calling this out here prevents confusion.

Proposed doc tweak:

 Environment groups automatically handle collision filtering between different environments:
 - Entities from different environments (except -1) do not collide with each other
 - Global entities (group -1) collide with all environments
 - Collision groups from the source builder are preserved as-is for fine-grained collision control within each environment
+Note: Shapes attached to the world body (body == -1) do not collide with other shapes on the world body due to same‑body
+collision filtering. This remains true even when those shapes are in the global environment (-1).

4186-4193: Unify env+group predicate with the kernel-side helper to prevent drift.

These blocks re-implement the environment compatibility rule inline. Since the PR introduced test_environment_and_group_pair(envA, envB, groupA, groupB) for kernels, reuse it here to keep CPU-side prefiltering in lockstep with GPU semantics.

Minimal change:

+from ..geometry.broad_phase_common import test_environment_and_group_pair
@@
-                # Check environment groups
-                env1 = self.shape_group[s1] if s1 < len(self.shape_group) else -1
-                env2 = self.shape_group[s2] if s2 < len(self.shape_group) else -1
-
-                # Skip shapes from different environments (unless one is global)
-                if env1 != -1 and env2 != -1 and env1 != env2:
-                    continue
+                env1 = self.shape_group[s1] if s1 < len(self.shape_group) else -1
+                env2 = self.shape_group[s2] if s2 < len(self.shape_group) else -1
+                grp1 = self.shape_collision_group[s1]
+                grp2 = self.shape_collision_group[s2]
+                if not test_environment_and_group_pair(env1, env2, grp1, grp2):
+                    continue
@@
-                    # Check environment groups
-                    env1 = self.shape_group[s1] if s1 < len(self.shape_group) else -1
-                    env2 = self.shape_group[s2] if s2 < len(self.shape_group) else -1
-
-                    # Skip shapes from different environments (unless one is global)
-                    if env1 != -1 and env2 != -1 and env1 != env2:
-                        continue
+                    env1 = self.shape_group[s1] if s1 < len(self.shape_group) else -1
+                    env2 = self.shape_group[s2] if s2 < len(self.shape_group) else -1
+                    grp1 = self.shape_collision_group[s1]
+                    grp2 = self.shape_collision_group[s2]
+                    if not test_environment_and_group_pair(env1, env2, grp1, grp2):
+                        continue

Note: keep the cross-product with collision-group -1; the helper only answers “allowed?”, not “which sets to iterate.”

Also applies to: 4209-4216

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1f1e06a and 18158f8.

📒 Files selected for processing (3)
  • newton/_src/sim/builder.py (4 hunks)
  • newton/_src/sim/collide.py (1 hunks)
  • newton/_src/sim/style3d/builder_style3d.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • newton/_src/sim/collide.py
  • newton/_src/sim/style3d/builder_style3d.py
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: eric-heiden
PR: newton-physics/newton#587
File: newton/_src/sim/builder.py:656-661
Timestamp: 2025-08-20T18:02:36.042Z
Learning: In Newton physics, collisions between shapes with body index -1 (world-attached/global shapes) are automatically skipped by the collision system, so no manual collision filter pairs need to be added between global shapes from different builders.
📚 Learning: 2025-08-20T18:02:36.042Z
Learnt from: eric-heiden
PR: newton-physics/newton#587
File: newton/_src/sim/builder.py:656-661
Timestamp: 2025-08-20T18:02:36.042Z
Learning: In Newton physics, collisions between shapes with body index -1 (world-attached/global shapes) are automatically skipped by the collision system, so no manual collision filter pairs need to be added between global shapes from different builders.

Applied to files:

  • newton/_src/sim/builder.py
🧬 Code graph analysis (1)
newton/_src/sim/builder.py (1)
newton/_src/geometry/flags.py (1)
  • ShapeFlags (30-42)
⏰ 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). (3)
  • GitHub Check: Run GPU Unit Tests on AWS EC2 (Pull Request)
  • GitHub Check: run-newton-tests / newton-unittests (ubuntu-latest)
  • GitHub Check: run-newton-tests / newton-unittests (windows-latest)

Comment thread newton/_src/sim/builder.py
vreutskyy and others added 2 commits August 25, 2025 14:41
Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.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

♻️ Duplicate comments (1)
newton/_src/sim/builder.py (1)

807-811: Canonicalize filter pairs on builder merge to avoid missed filters

find_shape_contact_pairs() canonicalizes pairs as (min, max) before lookup. Merging non-canonical pairs here means filters won’t match and undesired contact pairs can slip through, especially after replication/merging multiple builders.

Apply canonicalization during insertion:

-        shape_count_offset = self.shape_count
-        for i, j in builder.shape_collision_filter_pairs:
-            self.shape_collision_filter_pairs.add((i + shape_count_offset, j + shape_count_offset))
+        shape_count_offset = self.shape_count
+        for i, j in builder.shape_collision_filter_pairs:
+            a = i + shape_count_offset
+            b = j + shape_count_offset
+            if a > b:
+                a, b = b, a
+            self.shape_collision_filter_pairs.add((a, b))

Also consider normalizing other insertion sites (e.g., same-body and parent–child insertions) for consistency; see note in the follow-up comment below.

Run this quick scan to find other non-canonical insertions of shape_collision_filter_pairs.add:

#!/bin/bash
# Show all call sites with context and highlight obvious canonicalization.
rg -nC3 -P '\bshape_collision_filter_pairs\.add\s*\(' newton/_src/sim/builder.py
# Heuristic search for min/max normalization near these sites.
rg -nC1 -P '\b(min|max)\s*\(' newton/_src/sim/builder.py
🧹 Nitpick comments (2)
newton/_src/sim/builder.py (2)

4190-4198: Environment filtering in contact-pair generation: logic is correct; consider small cleanup

  • The predicate “skip when env1 != -1 and env2 != -1 and env1 != env2” implements “same env or either is global,” which matches the PR’s spec.
  • Minor: the defensive indexing defaulting to -1 will silently treat absent env-tags as global. If that’s not expected, consider asserting lengths match shape_count during finalize.

Optional micro-refactor to reduce duplication in both loops:

  • Extract a tiny predicate:
    same_env_or_global = (env1 == -1) or (env2 == -1) or (env1 == env2)

Then use if not same_env_or_global: continue.

Also, leveraging the retrieved learning that world-attached shapes (body == -1) don’t collide with each other automatically, you can save work by pruning world–world pairs here:

  • Early-continue when both self.shape_body[s1] == -1 and self.shape_body[s2] == -1.

This can reduce contact-pair list size and downstream kernel work without changing behavior.

If you want, I can draft a follow-up diff that adds a local _same_env_or_global(env1, env2) predicate and a world–world pruning check in both loops.


4205-4225: Global collision group (-1) cross-pairing looks right; consider DRY-ing the predicate

The special-case loop for group != -1 vs -1 is correct and respects env rules. To reduce duplication and the risk of drift, consider factoring the shared flag/shape/env checks into a local helper used by both loops.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 18158f8 and f26a1e5.

📒 Files selected for processing (2)
  • newton/_src/sim/builder.py (5 hunks)
  • newton/tests/test_environment_group_collision.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • newton/tests/test_environment_group_collision.py
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-20T18:02:36.042Z
Learnt from: eric-heiden
PR: newton-physics/newton#587
File: newton/_src/sim/builder.py:656-661
Timestamp: 2025-08-20T18:02:36.042Z
Learning: In Newton physics, collisions between shapes with body index -1 (world-attached/global shapes) are automatically skipped by the collision system, so no manual collision filter pairs need to be added between global shapes from different builders.

Applied to files:

  • newton/_src/sim/builder.py
🧬 Code graph analysis (1)
newton/_src/sim/builder.py (1)
newton/_src/geometry/flags.py (1)
  • ShapeFlags (30-42)
⏰ 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). (3)
  • GitHub Check: Run GPU Unit Tests on AWS EC2 (Pull Request)
  • GitHub Check: run-newton-tests / newton-unittests (ubuntu-latest)
  • GitHub Check: run-newton-tests / newton-unittests (windows-latest)
🔇 Additional comments (4)
newton/_src/sim/builder.py (4)

665-669: Docs: environment-group collision semantics look correct

The bullets accurately capture the intended behavior: cross-environment collisions are disabled except when either side is in env group -1. No changes requested.


804-806: Preserving shape collision groups as-is is appropriate

Carrying over group IDs without reindexing aligns with the “per-env filtering + group inside env” model. This keeps intra-env collision control intact.


1113-1117: Nice: canonical order for parent–child filter pairs

This prevents lookup mismatches and is consistent with the consumer logic. Good fix.


2169-2199: No normalization needed for same-body and parent–child filter insertions

The review suggests canonicalizing (u, v) pairs so that u ≤ v, but in this context that condition is already guaranteed:

  • Each new shape’s index is self.shape_count, which monotonically increases as shapes are added.
  • In the "same body" loop, same_body_shape always refers to an existing shape ID (< new shape).
  • In the "parent body" loop, parent_shape likewise is from an already-added body, so its index is < new shape.
  • Downstream lookups (e.g., in solver_mujoco.py) even check both (i, j) and (j, i), ensuring no misses.

Since the tuples are inherently inserted in ascending order and lookups handle either ordering, no change is required here.

Likely an incorrect or invalid review comment.

@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

♻️ Duplicate comments (1)
newton/_src/sim/builder.py (1)

1056-1060: Canonicalize merged filter pairs to avoid missed filters

When importing builder.shape_collision_filter_pairs, pairs may be stored non-canonically upstream. Since find_shape_contact_pairs() looks up canonicalized pairs (min, max), a non-canonical insertion here can reintroduce contacts that were meant to be filtered. Canonicalize before insertion.

Apply:

-        for i, j in builder.shape_collision_filter_pairs:
-            self.shape_collision_filter_pairs.add((i + shape_count_offset, j + shape_count_offset))
+        for i, j in builder.shape_collision_filter_pairs:
+            a = i + shape_count_offset
+            b = j + shape_count_offset
+            if a > b:
+                a, b = b, a
+            self.shape_collision_filter_pairs.add((a, b))
#!/bin/bash
# Verify all insertions into shape_collision_filter_pairs are canonicalized.
rg -nC2 -P '\bshape_collision_filter_pairs\.add\s*\('
🧹 Nitpick comments (4)
newton/_src/sim/builder.py (4)

914-918: Doc: clarify world-attached (-1 body) non-collision and cross-reference behavior

Nice summary. Consider adding a one-liner that shapes attached to the world (body == -1) never collide with each other, so users don’t need to add manual filters for those. This aligns expectations with runtime behavior. Based on retrieved learnings from PR #587.


1061-1066: Optional: guard against accidental duplicates in group map

If the source builder ever contained duplicates (or future code paths append the same shape twice), itertools.combinations(shapes, 2) will emit degenerate pairs and extra work. Not critical today, but you can defensively deduplicate during merge.

Example (keep list type, preserve order of first occurrences):

-            self.shape_collision_group_map[group].extend([s + shape_count_offset for s in shapes])
+            seen = set(self.shape_collision_group_map[group])
+            for s in shapes:
+                idx = s + shape_count_offset
+                if idx not in seen:
+                    self.shape_collision_group_map[group].append(idx)
+                    seen.add(idx)

4440-4447: Env filtering logic matches the stated semantics

The check env1 != -1 and env2 != -1 and env1 != env2: continue enforces “same env or either global (-1)” correctly before adding pairs.

Minor maintainability: factor this into a tiny helper to keep parity with the kernel-side predicate and reduce duplication:

+def _envs_collide(e1: int, e2: int) -> bool:
+    return e1 == -1 or e2 == -1 or e1 == e2
...
-                if env1 != -1 and env2 != -1 and env1 != env2:
+                if not _envs_collide(env1, env2):
                     continue

4463-4470: Consistent env filtering for group -1 cross-pairs

Same comment as above; logic is correct and consistent with the doc. Consider reusing the same helper here to avoid divergence over time.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f26a1e5 and d0e98de.

📒 Files selected for processing (4)
  • newton/_src/geometry/kernels.py (2 hunks)
  • newton/_src/sim/builder.py (5 hunks)
  • newton/_src/sim/style3d/builder_style3d.py (1 hunks)
  • newton/examples/example_robot_manipulating_cloth.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • newton/_src/sim/style3d/builder_style3d.py
  • newton/_src/geometry/kernels.py
  • newton/examples/example_robot_manipulating_cloth.py
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-20T18:02:36.042Z
Learnt from: eric-heiden
PR: newton-physics/newton#587
File: newton/_src/sim/builder.py:656-661
Timestamp: 2025-08-20T18:02:36.042Z
Learning: In Newton physics, collisions between shapes with body index -1 (world-attached/global shapes) are automatically skipped by the collision system, so no manual collision filter pairs need to be added between global shapes from different builders.

Applied to files:

  • newton/_src/sim/builder.py
🧬 Code graph analysis (1)
newton/_src/sim/builder.py (1)
newton/_src/geometry/flags.py (1)
  • ShapeFlags (30-42)
⏰ 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). (4)
  • GitHub Check: Run GPU Benchmarks (Pull Request)
  • GitHub Check: Run GPU Unit Tests on AWS EC2 (Pull Request)
  • GitHub Check: run-newton-tests / newton-unittests (ubuntu-latest)
  • GitHub Check: run-newton-tests / newton-unittests (windows-latest)
🔇 Additional comments (1)
newton/_src/sim/builder.py (1)

1362-1367: Good: canonical order for parent–child shape filters

Normalizing to (min, max) avoids lookup mismatches later. This prevents subtle filter misses.

Comment thread newton/_src/geometry/broad_phase_sap.py Outdated
@preist-nvidia preist-nvidia linked an issue Aug 28, 2025 that may be closed by this pull request
Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.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

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/broad_phase_nxn.py (1)

189-201: Fix Warp launch argument mapping; don’t place scalar in outputs

Passing max_candidate_pair (an int) via outputs= is incorrect and mixes styles with the precomputed-pairs path. Standardize to pass all kernel params via inputs in signature order (as done below), or put only array outputs in outputs while keeping positional mapping intact. This version mirrors the precomputed path and avoids confusion.

-        wp.launch(
-            _nxn_broadphase_kernel,
-            dim=num_lower_tri_elements,
-            inputs=[
-                geom_lower,
-                geom_upper,
-                geom_count,
-                geom_cutoffs,
-                geom_collision_group,
-                geom_shape_group,
-            ],
-            outputs=[candidate_pair, num_candidate_pair, max_candidate_pair],
-        )
+        wp.launch(
+            _nxn_broadphase_kernel,
+            dim=num_lower_tri_elements,
+            inputs=[
+                geom_lower,
+                geom_upper,
+                geom_count,
+                geom_cutoffs,
+                geom_collision_group,
+                geom_shape_group,
+                candidate_pair,
+                num_candidate_pair,
+                max_candidate_pair,
+            ],
+        )
🧹 Nitpick comments (1)
newton/_src/geometry/broad_phase_nxn.py (1)

133-140: Docstring is outdated; mention environment groups and new predicate

Update to reflect env-group semantics and the combined predicate.

-    The collision checks take into account per-geometry cutoff distances and collision groups. Two geometries
-    will only be considered as a candidate pair if:
-    1. Their AABBs overlap when expanded by their cutoff distances
-    2. Their collision groups allow interaction (determined by test_group_pair())
+    The collision checks take into account per-geometry cutoff distances, environment groups, and collision
+    groups. Two geometries will only be considered as a candidate pair if:
+    1. Their AABBs overlap when expanded by their cutoff distances
+    2. Their environment groups are compatible (same environment or at least one is global, -1)
+    3. Their collision groups allow interaction (see test_environment_and_group_pair()) 
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d0e98de and 412ad70.

📒 Files selected for processing (3)
  • newton/_src/geometry/broad_phase_nxn.py (6 hunks)
  • newton/_src/geometry/broad_phase_sap.py (10 hunks)
  • newton/tests/test_broad_phase.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • newton/tests/test_broad_phase.py
  • newton/_src/geometry/broad_phase_sap.py
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-12T17:51:37.474Z
Learnt from: nvlukasz
PR: newton-physics/newton#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/_src/geometry/broad_phase_nxn.py
🧬 Code graph analysis (1)
newton/_src/geometry/broad_phase_nxn.py (1)
newton/_src/geometry/broad_phase_common.py (3)
  • check_aabb_overlap (22-38)
  • test_environment_and_group_pair (91-119)
  • write_pair (54-65)
⏰ 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 (4)
newton/_src/geometry/broad_phase_nxn.py (4)

85-86: Kernel now takes env-group input — LGTM

Adding shape_group: wp.array(dtype=int, ndim=1) matches the -1/global semantics and keeps dtype compatible with negatives.


98-106: Early environment/group rejection is correct

Filtering by test_environment_and_group_pair(...) before AABB overlap avoids unnecessary box loads/comparisons.


167-172: Launch docstring additions — LGTM

Collision-group semantics and env-group (-1 global) notes are clear; compatibility criteria spelled out.

Also applies to: 176-180


18-18: No action needed: predicates are annotated as @wp.func

Both test_environment_and_group_pair and check_aabb_overlap are correctly decorated with @wp.func.

Comment thread newton/_src/geometry/broad_phase_nxn.py
…ion-detection-system

Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com>
Comment thread newton/_src/sim/builder.py
@eric-heiden eric-heiden enabled auto-merge (squash) August 29, 2025 19:01
@eric-heiden eric-heiden merged commit 438a146 into newton-physics:main Aug 29, 2025
10 of 11 checks passed
maxkra15 pushed a commit to maxkra15/newton that referenced this pull request Sep 1, 2025
…hysics#605 (newton-physics#615)

Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com>
Co-authored-by: Eric Heiden <eheiden@nvidia.com>
@coderabbitai coderabbitai Bot mentioned this pull request Oct 7, 2025
4 tasks
eric-heiden added a commit to eric-heiden/newton that referenced this pull request Jan 28, 2026
…hysics#605 (newton-physics#615)

Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com>
Co-authored-by: Eric Heiden <eheiden@nvidia.com>
mmacklin pushed a commit to mmacklin/newton that referenced this pull request Apr 7, 2026
…hysics#605 (newton-physics#615)

Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com>
Co-authored-by: Eric Heiden <eheiden@nvidia.com>
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.

Integrate environment groups with collision detection system

2 participants