Shape scaling issue with MuJoCo solver #714#1012
Conversation
Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com>
📝 WalkthroughWalkthroughRenamed and repurposed shape-mapping kernel and removed per-shape incoming-transform state. Geom property kernel now accepts geom_type/geom_dataid and mesh transforms (mesh_pos/mesh_quat); mesh transforms are composed with geom transforms before writing geom_pos/geom_quat. Tests added for scaling and mesh geoms across worlds. Changes
Sequence Diagram(s)sequenceDiagram
participant Solver
participant MapKer as update_shape_mappings_kernel
participant PropKer as update_geom_properties_kernel
participant MJModel as mjw_model
Note over Solver,MapKer: New mapping phase
Solver->>MapKer: geom_to_shape_idx, geom_is_static, mapping arrays
MapKer-->>Solver: full_shape_mapping, reverse_shape_mapping
Note over Solver,PropKer: Geom property update (mesh-aware)
Solver->>PropKer: geom_type, geom_dataid, mesh_pos, mesh_quat, geom transforms
alt geom_type == GEOM_TYPE_MESH
PropKer->>PropKer: compose(mesh_pos/mesh_quat, geom_transform)
end
PropKer-->>MJModel: write geom_pos, geom_quat
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
newton/_src/solvers/mujoco/solver_mujoco.py (1)
1141-1152: Consider using a named constant for mesh geom type.The mesh transform logic is correct. The check
if geom_type[geom_idx] == 7:uses a magic number where 7 representsmjGEOM_MESH. While the comment clarifies this, consider defining a module-level constant for improved maintainability:MJGEOM_MESH = 7Then use:
if geom_type[geom_idx] == MJGEOM_MESH:
📜 Review details
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
newton/_src/solvers/mujoco/solver_mujoco.py(6 hunks)newton/tests/test_mujoco_solver.py(3 hunks)
🧰 Additional context used
🧠 Learnings (12)
📚 Learning: 2025-10-10T10:47:41.082Z
Learnt from: nvtw
PR: newton-physics/newton#899
File: newton/tests/test_rigid_contact.py:214-268
Timestamp: 2025-10-10T10:47:41.082Z
Learning: In `newton/tests/test_rigid_contact.py`, using `add_shape_plane(width=0, length=0)` for an infinite plane works correctly with the collision system and does not cause degenerate AABB issues in the test scenario `test_shape_collisions_gjk_mpr_multicontact`.
Applied to files:
newton/tests/test_mujoco_solver.py
📚 Learning: 2025-08-18T15:56:26.587Z
Learnt from: adenzler-nvidia
PR: newton-physics/newton#552
File: newton/_src/solvers/mujoco/solver_mujoco.py:0-0
Timestamp: 2025-08-18T15:56:26.587Z
Learning: In Newton's MuJoCo solver, when transforming joint axes from Newton's internal frame to MuJoCo's expected frame, use wp.quat_rotate(joint_rot, axis) not wp.quat_rotate_inv(joint_rot, axis). The joint_rot represents rotation from joint-local to body frame, so forward rotation is correct.
Applied to files:
newton/tests/test_mujoco_solver.pynewton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-25T16:14:22.033Z
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/_src/sim/ik/ik_objectives.py:0-0
Timestamp: 2025-09-25T16:14:22.033Z
Learning: In NVIDIA Warp's Newton physics library, wp.transform supports direct numerical indexing (e.g., body_tf[0], body_tf[1], body_tf[2] for position and body_tf[3], body_tf[4], body_tf[5], body_tf[6] for quaternion components) to access its elements. This is the standard API used throughout the codebase.
Applied to files:
newton/tests/test_mujoco_solver.pynewton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-12T05:17:34.423Z
Learnt from: shi-eric
PR: newton-physics/newton#521
File: newton/examples/example_cloth_hanging.py:36-36
Timestamp: 2025-08-12T05:17:34.423Z
Learning: The STYLE3D solver in Newton is a new solver that did not exist in warp.sim, so it does not require any migration documentation.
Applied to files:
newton/tests/test_mujoco_solver.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
PR: newton-physics/newton#579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, Example.use_mujoco is a high-level attribute that controls whether to use MuJoCo solver vs other solvers (like XPBD), while SolverMuJoCo.use_mujoco_cpu controls the backend within MuJoCo (CPU vs Warp). These are separate concepts serving different purposes - the PR rename only applies to the solver parameter, not the Example class attributes.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 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/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
PR: newton-physics/newton#579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, there's a distinction between solver parameters and Example class attributes. The Example class can have its own use_mujoco attribute for controlling example-level behavior (like CUDA graphs, rendering logic), while the solver uses use_mujoco_cpu for backend selection. These serve different purposes and should not be conflated during API renames.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-18T07:05:56.836Z
Learnt from: gdaviet
PR: newton-physics/newton#750
File: newton/_src/solvers/implicit_mpm/solve_rheology.py:969-986
Timestamp: 2025-09-18T07:05:56.836Z
Learning: In newton/_src/solvers/implicit_mpm/solve_rheology.py, transposed_strain_mat parameter cannot be None - the type signature was corrected to reflect this guarantee, eliminating the need for None checks when accessing transposed_strain_mat.offsets.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-22T21:08:31.901Z
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering, despite the general warp documentation suggesting copies are made by default.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-22T21:08:31.901Z
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-25T20:10:59.536Z
Learnt from: dylanturpin
PR: newton-physics/newton#634
File: newton/examples/ik/example_ik_franka.py:0-0
Timestamp: 2025-08-25T20:10:59.536Z
Learning: In Newton's IK examples, when creating solver arrays with `wp.array(source_array, shape=new_shape)`, this creates a view into the same underlying memory rather than a copy. This means updates to the reshaped array are automatically reflected in the original array without needing explicit copy operations like `wp.copy()`.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-25T16:14:22.033Z
Learnt from: dylanturpin
PR: newton-physics/newton#806
File: newton/_src/sim/ik/ik_objectives.py:0-0
Timestamp: 2025-09-25T16:14:22.033Z
Learning: wp.transform in NVIDIA Warp supports indexing using numerical indices (e.g., body_tf[0], body_tf[3], etc.) to access translation and rotation components. The indexing approach used in the Newton codebase is valid and compiles correctly.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
🧬 Code graph analysis (1)
newton/tests/test_mujoco_solver.py (2)
newton/_src/sim/builder.py (2)
add_shape_sphere(2866-2900)finalize(4455-4841)newton/_src/geometry/types.py (7)
finalize(102-109)finalize(237-254)vertices(219-220)vertices(223-225)indices(228-229)indices(232-234)Mesh(116-300)
⏰ 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 (8)
newton/_src/solvers/mujoco/solver_mujoco.py (4)
1034-1069: LGTM! Kernel renamed and repurposed appropriately.The renaming from
update_incoming_shape_xform_kerneltoupdate_shape_mappings_kernelbetter reflects its current purpose of computing shape index mappings without transform calculations.
2445-2448: LGTM! Good defensive programming.The patch ensures
mesh_posexists onmjw_model, providing compatibility with different versions of mujoco_warp.
2483-2496: LGTM! Kernel call correctly updated.The call to
update_shape_mappings_kernelproperly provides all required parameters and matches the new kernel signature.
2777-2805: LGTM! Kernel call properly updated with mesh parameters.The call to
update_geom_properties_kernelcorrectly passes the new mesh-related parameters (geom_type,geom_dataid,mesh_pos,mesh_quat) from the MuJoCo Warp model.newton/tests/test_mujoco_solver.py (4)
893-932: LGTM! Test correctly updated for body-local coordinates.The clarifying comments about body-local coordinates and the direct use of
shape_transformsalign with the removal ofshape_incoming_xformin the solver implementation.
1103-1148: LGTM! Test properly validates dynamic geom property updates.The test correctly verifies that position and orientation updates work in body-local coordinates after the removal of
shape_incoming_xform.
1738-1817: LGTM! Excellent test coverage for shape scaling across worlds.This test directly addresses the PR's main objective (issue #714) by verifying that shapes maintain correct body-local offsets when different worlds use different scales. The test structure is clear and the assertions validate the expected behavior.
1818-1950: LGTM! Comprehensive test for mesh geom handling across worlds.This test effectively validates that:
mesh_posis correctly retrieved from the MuJoCo model- The mesh centering transform is properly applied to geom positions
- The composition
mesh_tf * shape_tfcorrectly addsmesh_posto the shape's local offsetThe test expectations align perfectly with the kernel implementation at lines 1146-1151 in the solver.
adenzler-nvidia
left a comment
There was a problem hiding this comment.
Thank you, just 1 small nitpick.
dismissing review because of benchmark failure, we should look into that.
Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com>
|
Fun fact: MJWarp stores the real component of a quaternion as q[0] (which is q.x), perhaps following MuJoCo's convention. It even has special math functions different from Warp's built-in which treats q[3] (q.w) as real component. What a mess :) |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
newton/_src/solvers/mujoco/solver_mujoco.py (1)
1143-1157: Consider adding bounds check for mesh_id.The mesh transform composition logic is correct, including the quaternion conversion from MuJoCo's (w,x,y,z) to Warp's (x,y,z,w) convention. However, there's no validation that
mesh_idis within bounds before accessingmesh_pos[mesh_id]andmesh_quat[mesh_id].Consider adding a bounds check:
if geom_type[geom_idx] == GEOM_TYPE_MESH: mesh_id = geom_dataid[geom_idx] + if mesh_id >= 0 and mesh_id < mesh_pos.shape[0]: mesh_p = mesh_pos[mesh_id] mesh_q = mesh_quat[mesh_id] mesh_tf = wp.transform(mesh_p, wp.quat(mesh_q.y, mesh_q.z, mesh_q.w, mesh_q.x)) tf = tf * mesh_tf
📜 Review details
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
newton/_src/solvers/mujoco/solver_mujoco.py(6 hunks)
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
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.
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, Example.use_mujoco is a high-level attribute that controls whether to use MuJoCo solver vs other solvers (like XPBD), while SolverMuJoCo.use_mujoco_cpu controls the backend within MuJoCo (CPU vs Warp). These are separate concepts serving different purposes - the PR rename only applies to the solver parameter, not the Example class attributes.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.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/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-18T07:05:56.836Z
Learnt from: gdaviet
Repo: newton-physics/newton PR: 750
File: newton/_src/solvers/implicit_mpm/solve_rheology.py:969-986
Timestamp: 2025-09-18T07:05:56.836Z
Learning: In newton/_src/solvers/implicit_mpm/solve_rheology.py, transposed_strain_mat parameter cannot be None - the type signature was corrected to reflect this guarantee, eliminating the need for None checks when accessing transposed_strain_mat.offsets.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, there's a distinction between solver parameters and Example class attributes. The Example class can have its own use_mujoco attribute for controlling example-level behavior (like CUDA graphs, rendering logic), while the solver uses use_mujoco_cpu for backend selection. These serve different purposes and should not be conflated during API renames.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 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/_src/solvers/mujoco/solver_mujoco.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 STYLE3D solver in Newton is a new solver that did not exist in warp.sim, so it does not require any migration documentation.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-22T21:08:31.901Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering, despite the general warp documentation suggesting copies are made by default.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-22T21:08:31.901Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-25T20:10:59.536Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 634
File: newton/examples/ik/example_ik_franka.py:0-0
Timestamp: 2025-08-25T20:10:59.536Z
Learning: In Newton's IK examples, when creating solver arrays with `wp.array(source_array, shape=new_shape)`, this creates a view into the same underlying memory rather than a copy. This means updates to the reshaped array are automatically reflected in the original array without needing explicit copy operations like `wp.copy()`.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.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/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-25T16:14:22.033Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_objectives.py:0-0
Timestamp: 2025-09-25T16:14:22.033Z
Learning: In NVIDIA Warp's Newton physics library, wp.transform supports direct numerical indexing (e.g., body_tf[0], body_tf[1], body_tf[2] for position and body_tf[3], body_tf[4], body_tf[5], body_tf[6] for quaternion components) to access its elements. This is the standard API used throughout the codebase.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-12T17:52:15.009Z
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/_src/utils/import_mjcf.py:226-231
Timestamp: 2025-08-12T17:52:15.009Z
Learning: In the Newton codebase, when passing array-like objects (numpy arrays, lists, tuples) to wp.vec3(), the consistent pattern is to use the unpacking operator: wp.vec3(*array) rather than wp.vec3(array). This pattern is used throughout newton/_src/utils/import_mjcf.py and newton/_src/core/types.py.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-25T16:14:22.033Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_objectives.py:0-0
Timestamp: 2025-09-25T16:14:22.033Z
Learning: wp.transform in NVIDIA Warp supports indexing using numerical indices (e.g., body_tf[0], body_tf[3], etc.) to access translation and rotation components. The indexing approach used in the Newton codebase is valid and compiles correctly.
Applied to files:
newton/_src/solvers/mujoco/solver_mujoco.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). (1)
- GitHub Check: Run GPU Benchmarks (Pull Request)
🔇 Additional comments (4)
newton/_src/solvers/mujoco/solver_mujoco.py (4)
1036-1069: LGTM! Kernel rename and signature simplification.The kernel rename from
update_incoming_shape_xform_kerneltoupdate_shape_mappings_kernelaccurately reflects its focused responsibility: mapping shape indices without transform corrections. The removal ofshape_transformhandling aligns with the PR objective to eliminate theshape_incoming_xformfield.
1092-1096: Good addition of mesh transform parameters.The new parameters enable per-mesh transform handling. Passing
GEOM_TYPE_MESHas a kernel parameter is a clean approach that avoids hardcoded magic numbers while still allowing the value to be used in conditionals.
2489-2500: LGTM! Kernel invocation updated correctly.The invocation of
update_shape_mappings_kernelproperly matches the new signature, passing the shape mapping arrays and receiving the bidirectional index mappings.
2793-2797: Mesh field parameters passed correctly.The kernel invocation properly passes the new mesh-related fields:
geom_type, the MuJoCo mesh constant,geom_dataid, and the mesh transform arrays. This aligns with the updated kernel signature.
adenzler-nvidia
left a comment
There was a problem hiding this comment.
thanks - yes the quaternion stuff is annoying, especially the fact that they reuse the wp.quat type for this. I would have gone for a vec4 with custom math to avoid the confusion..
…sics#1012) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com>
…sics#1012) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com>
Description
This PR fixes the shape scaling issue with the MuJoCo solver when using multiple worlds with different scales. Closes #714.
Problem
The MuJoCo solver was incorrectly handling shape transformations across multiple worlds with different scales. The issue was caused by
shape_incoming_xformbeing computed from world0's geometry data and then incorrectly applied to all worlds, resulting in visual shapes being displayed correctly but collision shapes being wrong in scaled worlds.Solution
Removed
shape_incoming_xform- This field was the root cause of the scaling issue. It has been completely removed from the solver and all related computations.Added proper mesh transform support - The solver now correctly handles mesh transformations by applying mesh transformations in the
update_geom_properties_kernelfor mesh geomsTests Added
test_shape_scaling_across_worlds- Verifies that shapes maintain correct offsets when worlds have different scalestest_mesh_geoms_across_worlds- Verifies that mesh geoms with non-zeromesh_posare handled correctly across worldsLimitations
Scaling still won't work for meshes. It works only for primitive shapes.
Newton Migration Guide
Please ensure the migration guide for warp.sim users is up-to-date with the changes made in this PR.
docs/migration.rstis up to dateBefore your PR is "Ready for review"
newton/tests/test_examples.py)pre-commit run -aSummary by CodeRabbit
New Features
Tests