Add possibility to forward newton generated contacts into mujoco warp#370
Conversation
Signed-off-by: twidmer <twidmer@nvidia.com>
adenzler-nvidia
left a comment
There was a problem hiding this comment.
Can you add some tests that verify this functionality?
📝 Walkthrough""" WalkthroughThis update adds the ability for the MuJoCoSolver to use Newton-generated contact data instead of MuJoCo's internal contact solver, controlled by a new parameter. Supporting device functions and kernels are introduced for contact conversion, and the model's mapping logic is extended. A new test verifies correct solver behavior with Newton contacts. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant MuJoCoSolver
participant NewtonContacts
participant MuJoCoWarp
User->>MuJoCoSolver: Initialize (use_mujoco_contacts=False)
MuJoCoSolver->>MuJoCoWarp: Set run_collision_detection=False
loop Simulation Steps
MuJoCoSolver->>NewtonContacts: Update collision contacts
MuJoCoSolver->>MuJoCoSolver: convert_contacts_to_mjwarp()
MuJoCoSolver->>MuJoCoWarp: Inject converted contacts
MuJoCoSolver->>MuJoCoWarp: Step simulation
end
Suggested reviewers
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
Signed-off-by: twidmer <twidmer@nvidia.com>
ff1605c to
58ccbb8
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
newton/solvers/mujoco/solver_mujoco.py (2)
263-271: Consider enhanced handling for global shapes.The current implementation handles shape indices of -1 but may need additional logic for global shapes that are shared across environments, as mentioned in past review comments.
Also applies to: 294-304
1144-1146: Add safeguards for CPU version of MuJoCo.While the warning for
use_mujoco=Truewithuse_mujoco_contacts=Falseis good, additional safeguards should be added to prevent runtime errors when using CPU MuJoCo with Newton contacts, as mentioned in past review comments.if use_mujoco and not use_mujoco_contacts: print("Setting use_mujoco_contacts to False has no effect when use_mujoco is True") + use_mujoco_contacts = True # Force to True to prevent issues disableflags = 0Also applies to: 1176-1178
🧹 Nitpick comments (2)
newton/solvers/mujoco/solver_mujoco.py (1)
2120-2142: Good implementation of multi-environment shape mapping.The code correctly expands the shape-to-geom mapping to handle all environments when they are separated into different MuJoCo worlds. The warning about non-divisible shape counts is helpful for debugging.
Consider adding a debug log to report the number of shapes mapped:
else: full_shape_mapping = shape_mapping + + if len(full_shape_mapping) > 0: + print(f"Mapped {len(full_shape_mapping)} Newton shapes to {len(shape_mapping)} MuJoCo geoms")Also applies to: 2188-2194
newton/tests/test_mujoco_solver.py (1)
1116-1146: Improve test robustness by adding velocity checks and clarifying tolerance values.The test logic is sound and properly validates the core Newton contact integration functionality. However, consider these improvements:
- Magic numbers: The tolerance multipliers (0.9 and 1.2) should be better documented or defined as named constants
- Settlement verification: The test only checks final position but doesn't verify the sphere has actually settled (velocity near zero)
Consider this enhanced version:
def test_sphere_on_plane_with_newton_contacts(self): """Test that a sphere correctly collides with a plane using Newton contacts.""" try: solver = MuJoCoSolver(self.model, use_mujoco_contacts=False) except ImportError as e: self.skipTest(f"MuJoCo or deps not installed. Skipping test: {e}") return sim_dt = 1.0 / 240.0 num_steps = 120 # Simulate for 0.5 seconds to ensure it settles + + # Define tolerance constants for better readability + SPHERE_HEIGHT_TOLERANCE_LOWER = 0.9 # Allow 10% compression + SPHERE_HEIGHT_TOLERANCE_UPPER = 1.2 # Allow 20% above expected height + VELOCITY_SETTLING_THRESHOLD = 0.01 # Consider settled if velocity below this for _ in range(num_steps): self.contacts = self.model.collide(self.state_in) solver.step(self.state_in, self.state_out, self.control, self.contacts, sim_dt) self.state_in, self.state_out = self.state_out, self.state_in final_pos = self.state_in.body_q.numpy()[self.sphere_body_idx, :3] final_height = final_pos[2] # Z-up in MuJoCo + final_velocity = self.state_in.body_qd.numpy()[self.sphere_body_idx, :3] + final_speed = np.linalg.norm(final_velocity) # The sphere should settle on the plane, with its center at its radius's height self.assertGreater( final_height, - self.sphere_radius * 0.9, + self.sphere_radius * SPHERE_HEIGHT_TOLERANCE_LOWER, f"Sphere fell through the plane. Final height: {final_height}", ) self.assertLess( final_height, - self.sphere_radius * 1.2, + self.sphere_radius * SPHERE_HEIGHT_TOLERANCE_UPPER, f"Sphere is floating above the plane. Final height: {final_height}", ) + + # Verify the sphere has settled (low velocity) + self.assertLess( + final_speed, + VELOCITY_SETTLING_THRESHOLD, + f"Sphere should have settled but still has velocity: {final_speed}", + )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between 067b4cd and ff1605c29e1725f94a9da37d65986be469b0816e.
📒 Files selected for processing (2)
newton/solvers/mujoco/solver_mujoco.py(7 hunks)newton/tests/test_mujoco_solver.py(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: shi-eric
PR: newton-physics/newton#386
File: .github/workflows/aws-gpu-tests.yml:65-82
Timestamp: 2025-07-12T19:46:47.510Z
Learning: In the newton-physics/newton repository AWS GPU workflow, the workflow only triggers on `pull_request_target` and `push` events, not on `pull_request` events. The `pull_request_target` event is used for testing PRs from forks safely on AWS infrastructure.
Learnt from: Kenny-Vilella
PR: newton-physics/newton#398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.659Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.
newton/solvers/mujoco/solver_mujoco.py (1)
Learnt from: Kenny-Vilella
PR: newton-physics/newton#398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.659Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.
🧬 Code Graph Analysis (1)
newton/solvers/mujoco/solver_mujoco.py (3)
newton/sim/model.py (1)
Model(30-505)newton/sim/state.py (1)
State(21-109)newton/sim/contacts.py (1)
Contacts(23-84)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: run-newton-tests / newton-unittests (ubuntu-latest)
- GitHub Check: run-newton-tests / newton-unittests (windows-latest)
- GitHub Check: run-asv-benchmarks
🔇 Additional comments (8)
newton/solvers/mujoco/solver_mujoco.py (7)
61-87: LGTM! Well-implemented orthonormal frame construction.The functions correctly compute orthogonal vectors and construct rotation matrices from normal vectors, with proper handling of edge cases like zero-length vectors.
93-137: LGTM! Contact writing function properly structured.The function correctly writes all contact properties to MuJoCo Warp arrays, following the expected convention as referenced in the comment.
139-198: LGTM! Contact parameter mixing follows MuJoCo conventions.The function correctly implements MuJoCo's contact parameter mixing rules, including priority-based selection, solmix-based averaging, and appropriate edge case handling.
285-285: Verify the normal vector negation is intentional.The normal vector is negated here. Please confirm this is intentional to match MuJoCo's contact normal convention (pointing from body B to body A).
1195-1200: LGTM! Conditional contact handling properly implemented.The step method correctly switches between MuJoCo's collision detection and Newton contact conversion based on the configuration flag.
1205-1253: LGTM! Contact conversion method properly structured.The method correctly launches the conversion kernel with all required inputs and handles the clearing of collision-related arrays.
1116-1116: Clarify test coverage for the new functionality.The PR objectives state that no new tests have been added, but the AI summary mentions a test class
TestMuJoCoSolverNewtonContacts. Please clarify whether tests have been added and ensure adequate test coverage for the newuse_mujoco_contactsparameter and contact conversion functionality.Likely an incorrect or invalid review comment.
newton/tests/test_mujoco_solver.py (1)
1093-1115: Well-structured test setup with good parameterization.The setUp method properly configures a simple sphere-plane collision scenario with appropriate stiffness and damping values. The test setup follows good practices by storing relevant parameters as instance variables for reuse.
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (3)
newton/solvers/mujoco/solver_mujoco.py (3)
89-198: Consider optimizing the contact parameter computation.The
contact_paramsfunction contains complex branching logic that could impact GPU performance. The multiple conditional assignments formixcalculation might benefit from simplification.Consider consolidating the mix calculation logic:
- mix = solmix1 / (solmix1 + solmix2) - mix = wp.where((solmix1 < MJ_MINVAL) and (solmix2 < MJ_MINVAL), 0.5, mix) - mix = wp.where((solmix1 < MJ_MINVAL) and (solmix2 >= MJ_MINVAL), 0.0, mix) - mix = wp.where((solmix1 >= MJ_MINVAL) and (solmix2 < MJ_MINVAL), 1.0, mix) - mix = wp.where(p1 == p2, mix, wp.where(p1 > p2, 1.0, 0.0)) + sum_mix = solmix1 + solmix2 + mix = wp.where(sum_mix < MJ_MINVAL, 0.5, solmix1 / sum_mix) + mix = wp.where(p1 != p2, wp.where(p1 > p2, 1.0, 0.0), mix)
1120-1120: Document the default behavior and interaction with other flags.The
use_mujoco_contactsparameter defaults toTrue, which maintains backward compatibility. However, the interaction withuse_mujocoflag could be better documented.Consider adding more detailed documentation about the parameter interaction:
- use_mujoco_contacts (bool): If True, use the MuJoCo contact solver. If False, use the Newton contact solver (newton contacts must be passed in through the step function in that case). + use_mujoco_contacts (bool): If True, use the MuJoCo contact solver. If False, use the Newton contact solver and newton contacts must be passed in through the step function. Note: This parameter has no effect when use_mujoco=True, as pure MuJoCo backend always uses MuJoCo contacts.
1148-1149: The warning message could be more descriptive.The current warning is functional but could provide more guidance to users about the expected behavior.
- if use_mujoco and not use_mujoco_contacts: - print("Setting use_mujoco_contacts to False has no effect when use_mujoco is True") + if use_mujoco and not use_mujoco_contacts: + print("WARNING: use_mujoco_contacts=False has no effect when use_mujoco=True. Pure MuJoCo backend always uses MuJoCo's contact solver.")
📜 Review details
Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between ff1605c29e1725f94a9da37d65986be469b0816e and 87f1dc5.
📒 Files selected for processing (2)
newton/solvers/mujoco/solver_mujoco.py(7 hunks)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
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: shi-eric
PR: newton-physics/newton#386
File: .github/workflows/aws-gpu-tests.yml:65-82
Timestamp: 2025-07-12T19:46:47.510Z
Learning: In the newton-physics/newton repository AWS GPU workflow, the workflow only triggers on `pull_request_target` and `push` events, not on `pull_request` events. The `pull_request_target` event is used for testing PRs from forks safely on AWS infrastructure.
Learnt from: Kenny-Vilella
PR: newton-physics/newton#398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.659Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.
newton/solvers/mujoco/solver_mujoco.py (1)
Learnt from: Kenny-Vilella
PR: newton-physics/newton#398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.659Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.
⏰ 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-newton-tests / newton-unittests (ubuntu-latest)
- GitHub Check: run-newton-tests / newton-unittests (windows-latest)
- GitHub Check: run-asv-benchmarks
🔇 Additional comments (4)
newton/solvers/mujoco/solver_mujoco.py (4)
61-87: LGTM: Well-implemented orthogonal vector generation and frame construction.The
orthogonalsandmake_framefunctions correctly implement the mathematical operations needed for contact frame generation. The choice of fallback vectors and normalization handling is sound.
1209-1256: The contact conversion method implementation is comprehensive.The method correctly launches the conversion kernel with all necessary parameters and handles data clearing. The parameter setup is thorough and matches the kernel signature.
2119-2124: Good addition of reverse mapping for geom-to-shape indexing.Adding the reverse mapping (
geom_to_shape_idx) is a necessary step for the multi-environment shape mapping that follows.
2127-2201: The multi-environment shape mapping logic is well-implemented.The expansion of shape mapping to cover all environments is correctly implemented. The logic properly handles the case where multiple environments map to the same MuJoCo geom indices, and includes appropriate warning for edge cases.
The mathematical logic is sound:
- Calculate shapes per environment
- For each MuJoCo geom, determine the local shape index
- Map all corresponding global shape indices to the same geom index
- Handle the single-environment case as a fallback
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
newton/solvers/mujoco/solver_mujoco.py (1)
1199-1203: The conditional logic in the step method needs error handling.The code correctly handles the two modes but lacks validation for required Newton contacts when
use_mujoco_contacts=False.This matches the previous review feedback about adding error handling for required Newton contacts.
📜 Review details
Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
newton/solvers/mujoco/solver_mujoco.py(7 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: shi-eric
PR: newton-physics/newton#386
File: .github/workflows/aws-gpu-tests.yml:65-82
Timestamp: 2025-07-12T19:46:47.510Z
Learning: In the newton-physics/newton repository AWS GPU workflow, the workflow only triggers on `pull_request_target` and `push` events, not on `pull_request` events. The `pull_request_target` event is used for testing PRs from forks safely on AWS infrastructure.
Learnt from: Kenny-Vilella
PR: newton-physics/newton#398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.659Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.
newton/solvers/mujoco/solver_mujoco.py (1)
Learnt from: Kenny-Vilella
PR: newton-physics/newton#398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.659Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.
🧬 Code Graph Analysis (1)
newton/solvers/mujoco/solver_mujoco.py (8)
newton/solvers/vbd/solver_vbd.py (1)
step(2147-2151)newton/solvers/solver.py (1)
step(250-263)newton/solvers/featherstone/solver_featherstone.py (1)
step(279-663)newton/solvers/style3d/solver_style3d.py (1)
step(132-314)newton/solvers/xpbd/solver_xpbd.py (1)
step(207-660)newton/sim/model.py (1)
Model(30-508)newton/sim/state.py (1)
State(21-109)newton/sim/contacts.py (1)
Contacts(23-84)
🔇 Additional comments (9)
newton/solvers/mujoco/solver_mujoco.py (9)
94-137: Thewrite_contactfunction looks correct and well-structured.The function properly maps contact data from Newton format to MuJoCo Warp format, following the reference implementation. The parameter naming and data flow are clear.
142-197: Thecontact_paramsfunction correctly implements MuJoCo's contact parameter mixing.The function properly handles priority-based parameter mixing and edge cases for small values. The logic follows the MuJoCo reference implementation.
1120-1120: Theuse_mujoco_contactsparameter addition is well-placed.The parameter is correctly added to the constructor with a sensible default value and clear documentation.
1148-1149: The warning message for conflicting settings is helpful.The warning appropriately informs users when
use_mujoco_contacts=Falsehas no effect withuse_mujoco=True.
1180-1181: The collision detection flag setting is correct.The code properly sets the MuJoCo Warp model's collision detection flag based on the
use_mujoco_contactsparameter.
1209-1256: Theconvert_contacts_to_mjwarpmethod is well-implemented.The method correctly launches the conversion kernel with all required parameters and handles the data flow properly.
2119-2148: The reverse mapping and environment expansion logic is correct.The code properly creates reverse mappings and expands shape mappings to cover all environments. The logic handles multi-environment scenarios correctly.
2195-2201: The shape-to-geom mapping creation is properly implemented.The code correctly creates the mapping array and handles the case where shapes might be out of bounds.
61-72: Theorthogonalsfunction has a potential division by zero issue.The function doesn't handle the case where the input vector
ahas zero length properly. While there's a check on line 68, the normalization on line 67 could fail ifahas zero length.Apply this fix to handle zero-length vectors before normalization:
@wp.func def orthogonals(a: wp.vec3): y = wp.vec3(0.0, 1.0, 0.0) z = wp.vec3(0.0, 0.0, 1.0) + if wp.length(a) == 0.0: + return wp.vec3(0.0, 0.0, 0.0), wp.vec3(0.0, 0.0, 0.0) b = wp.where((-0.5 < a[1]) and (a[1] < 0.5), y, z) b = b - a * wp.dot(a, b) b = wp.normalize(b) - if wp.length(a) == 0.0: - b = wp.vec3(0.0, 0.0, 0.0) c = wp.cross(a, b) return b, cLikely an incorrect or invalid review comment.
# Conflicts: # newton/solvers/mujoco/solver_mujoco.py
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (4)
newton/solvers/mujoco/solver_mujoco.py (4)
75-86: Add zero-length vector check to make_frame function.The function calls
wp.normalize(a)without checking if the vector has zero length, which can cause runtime errors.This was flagged in a previous review. Apply the suggested fix:
@wp.func def make_frame(a: wp.vec3): + if wp.length(a) == 0.0: + return wp.mat33( + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 + ) a = wp.normalize(a) b, c = orthogonals(a) # fmt: off return wp.mat33( a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z ) # fmt: on
299-303: Fix world ID calculation for invalid body pairs.The current logic defaults to
worldid = 0when bothbody_aandbody_bare invalid (< 0), which incorrectly assigns contacts to environment 0.This was flagged in previous reviews. Apply the suggested fix:
- worldid = 0 - if body_a >= 0: - worldid = body_a // bodies_per_env - elif body_b >= 0: - worldid = body_b // bodies_per_env + if body_a >= 0: + worldid = body_a // bodies_per_env + elif body_b >= 0: + worldid = body_b // bodies_per_env + else: + return # both bodies invalid – skip this contact
1112-1113: Collision detection flag setting needs validation.The code sets the collision detection flag but doesn't verify if the MuJoCo Warp model supports this configuration.
This was flagged in a previous review. Add validation:
if self.mjw_model is not None: + if not hasattr(self.mjw_model.opt, 'run_collision_detection'): + raise ValueError("MuJoCo Warp version does not support disabling collision detection") self.mjw_model.opt.run_collision_detection = use_mujoco_contacts
1131-1135: Step function modification needs error handling.The conditional logic properly handles the two contact modes, but lacks validation for required Newton contacts.
This was flagged in a previous review. Add validation:
if self.mjw_model.opt.run_collision_detection: self.mujoco_warp.step(self.mjw_model, self.mjw_data) else: + if contacts is None or contacts.rigid_contact_count is None: + raise ValueError("Newton contacts are required when use_mujoco_contacts=False") self.convert_contacts_to_mjwarp(self.model, state_in, contacts) self.mujoco_warp.step(self.mjw_model, self.mjw_data)
🧹 Nitpick comments (1)
newton/solvers/mujoco/solver_mujoco.py (1)
1079-1080: Warning message is helpful but could be more specific.The warning correctly identifies when the parameter has no effect, but could be more explicit about the behavior.
Consider making the warning more specific:
- print("Setting use_mujoco_contacts to False has no effect when use_mujoco is True") + print("Warning: use_mujoco_contacts=False has no effect when use_mujoco=True. MuJoCo CPU backend will always use its own contact solver.")
📜 Review details
Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
newton/solvers/mujoco/solver_mujoco.py(8 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Kenny-Vilella
PR: newton-physics/newton#398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.659Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.
newton/solvers/mujoco/solver_mujoco.py (1)
Learnt from: Kenny-Vilella
PR: newton-physics/newton#398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.659Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.
🧬 Code Graph Analysis (1)
newton/solvers/mujoco/solver_mujoco.py (3)
newton/sim/model.py (1)
Model(30-508)newton/sim/state.py (1)
State(21-109)newton/sim/contacts.py (1)
Contacts(23-84)
🔇 Additional comments (7)
newton/solvers/mujoco/solver_mujoco.py (7)
94-137: Contact writing function looks correct.The
write_contactfunction properly maps input contact data to MuJoCo Warp output arrays with appropriate data transformations.
142-197: Contact parameters calculation is well-implemented.The
contact_paramsfunction correctly implements MuJoCo's contact parameter mixing logic, handling priority, solmix, and other contact properties appropriately.
200-344: Contact conversion kernel is comprehensive but needs validation.The kernel correctly processes Newton contacts and converts them to MuJoCo Warp format, handling contact frames, distances, and parameters appropriately.
1050-1050: New parameter is well-documented and properly typed.The
use_mujoco_contactsparameter is correctly added with appropriate documentation and default value.Also applies to: 1073-1073
1141-1189: Contact conversion method is well-implemented.The
convert_contacts_to_mjwarpmethod correctly launches the conversion kernel with appropriate parameters and device scoping.
2024-2098: Shape mapping extension is correctly implemented.The logic properly extends the template environment shape mapping to cover all environments by calculating global shape indices and maintaining the correct mapping to MuJoCo geom indices.
The implementation correctly handles the case where multiple Newton environments map to the same MuJoCo geom indices, and includes appropriate warning for shape count validation.
61-72: Fix zero-length vector handling in orthogonals function.The function checks for zero-length vectors at lines 68-69, but this check occurs after the normalize operation at line 67, which will fail on zero vectors.
Apply this fix to handle zero-length vectors properly:
@wp.func def orthogonals(a: wp.vec3): + if wp.length(a) == 0.0: + return wp.vec3(0.0, 0.0, 0.0), wp.vec3(0.0, 0.0, 0.0) y = wp.vec3(0.0, 1.0, 0.0) z = wp.vec3(0.0, 0.0, 1.0) b = wp.where((-0.5 < a[1]) and (a[1] < 0.5), y, z) b = b - a * wp.dot(a, b) b = wp.normalize(b) - if wp.length(a) == 0.0: - b = wp.vec3(0.0, 0.0, 0.0) c = wp.cross(a, b) return b, cLikely an incorrect or invalid review comment.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (3)
newton/solvers/mujoco/solver_mujoco.py (3)
299-303: Fix world ID calculation for invalid body pairs.The current logic defaults
worldid = 0when bothbody_aandbody_bare negative, which incorrectly assigns contacts to environment 0. This was flagged in previous reviews but hasn't been addressed.Apply this fix to handle invalid body pairs correctly:
- worldid = 0 - if body_a >= 0: - worldid = body_a // bodies_per_env - elif body_b >= 0: - worldid = body_b // bodies_per_env + if body_a >= 0: + worldid = body_a // bodies_per_env + elif body_b >= 0: + worldid = body_b // bodies_per_env + else: + return # both bodies invalid – skip this contact
1137-1142: Add error handling for missing Newton contacts.The conditional logic correctly handles the two contact modes, but there's no validation that Newton contacts are provided when
use_mujoco_contacts=False. This was flagged in previous reviews but hasn't been addressed.Add validation for required Newton contacts:
if self.mjw_model.opt.run_collision_detection: self.mujoco_warp.step(self.mjw_model, self.mjw_data) else: + if contacts is None or contacts.rigid_contact_count is None: + raise ValueError("Newton contacts are required when use_mujoco_contacts=False") self.convert_contacts_to_mjwarp(self.model, state_in, contacts) self.mujoco_warp.step(self.mjw_model, self.mjw_data)
75-86: Add zero-length vector handling before normalization.The function normalizes the input vector
awithout checking if it has zero length, which could cause undefined behavior. Even thoughorthogonalshandles zero-length vectors, the normalization should be protected.Apply this fix to handle zero-length vectors:
@wp.func def make_frame(a: wp.vec3): + if wp.length(a) == 0.0: + return wp.mat33( + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 + ) a = wp.normalize(a) b, c = orthogonals(a) # fmt: off return wp.mat33( a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z ) # fmt: on
🧹 Nitpick comments (1)
newton/solvers/mujoco/solver_mujoco.py (1)
2038-2113: Complex but correct multi-environment shape mapping logic.The logic correctly extends the template environment's shape mapping to all environments by calculating global shape indices. The implementation properly handles the case where multiple environments share the same MuJoCo geom indices.
Consider adding more inline comments to explain the mapping logic:
+ # Calculate the global Newton shape index for the current environment. + # Each environment has the same local structure, so we offset by env_idx * shapes_per_env global_shape_idx = env_idx * shapes_per_env + local_shape_idx + # All corresponding shapes map to the same MuJoCo geom index (since mj_model is single-env). full_shape_mapping[global_shape_idx] = geom_idx
📜 Review details
Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
newton/solvers/mujoco/solver_mujoco.py(8 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Kenny-Vilella
PR: newton-physics/newton#398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.659Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.
newton/solvers/mujoco/solver_mujoco.py (1)
Learnt from: Kenny-Vilella
PR: newton-physics/newton#398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.659Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.
🧬 Code Graph Analysis (1)
newton/solvers/mujoco/solver_mujoco.py (3)
newton/sim/model.py (1)
Model(30-508)newton/sim/state.py (1)
State(21-109)newton/sim/contacts.py (1)
Contacts(23-84)
🔇 Additional comments (8)
newton/solvers/mujoco/solver_mujoco.py (8)
61-72: Good implementation of orthogonal vector generation.The function correctly handles zero-length input vectors by returning zero vectors, which addresses the edge case concern from previous reviews. The logic for generating orthogonal vectors is sound.
93-137: Well-implemented contact data writing function.The function correctly writes all contact parameters to the appropriate output arrays with clear parameter mapping. The implementation is straightforward and follows the MuJoCo Warp pattern.
142-197: Correct implementation of contact parameter mixing.The function properly implements the MuJoCo contact parameter mixing logic, including handling of priority-based selection and solmix-based blending. The edge case handling for zero solmix values is correct.
1052-1052: Good addition of contact solver control parameter.The
use_mujoco_contactsparameter with defaultTrueprovides backward compatibility while enabling the new Newton contact functionality.
1083-1085: Helpful warning message for invalid configuration.The warning appropriately informs users that the
use_mujoco_contactsparameter has no effect when using the pure MuJoCo backend.
1118-1120: Correct collision detection flag setting.The code properly sets the MuJoCo Warp collision detection flag based on the
use_mujoco_contactsparameter, enabling the conditional contact processing logic.
1147-1195: Well-implemented contact conversion method.The method correctly launches the conversion kernel with all necessary parameters, properly calculates
bodies_per_env, and includes all required inputs and outputs for the kernel execution.
2022-2022: Good addition of reverse mapping for shape indices.The
geom_to_shape_idxdictionary provides the necessary reverse mapping from MuJoCo geom indices to Newton shape indices, which is needed for the multi-environment expansion logic.
…newton-physics#370) Signed-off-by: twidmer <twidmer@nvidia.com> Co-authored-by: Eric Heiden <eheiden@nvidia.com>
…ton-physics#370) This PR adds a quickstart guide and various references to the setup instructions for Isaac Lab ## Checklist - [X] I have run the [`pre-commit` checks](https://pre-commit.com/) with `./isaaclab.sh --format` - [X] I have made corresponding changes to the documentation - [X] My changes generate no new warnings - [X] I have added tests that prove my fix is effective or that my feature works - [X] I have updated the changelog and the corresponding version in the extension's `config/extension.toml` file - [X] I have added my name to the `CONTRIBUTORS.md` or my name already exists there --------- Signed-off-by: Michael Gussert <michael@gussert.com> Co-authored-by: Kelly Guo <kellyg@nvidia.com>
…newton-physics#370) Signed-off-by: twidmer <twidmer@nvidia.com> Co-authored-by: Eric Heiden <eheiden@nvidia.com>
Description
Add possibility to forward newton generated contacts into mujoco warp
Required mujoco warp MR google-deepmind/mujoco_warp#484 to be merged first
Before your PR is "Ready for review"
pre-commit run -aSummary by CodeRabbit
New Features
Bug Fixes
Tests