Skip to content

Commit be2b9d7

Browse files
committed
Merge branch 'main' into dev/tw4/improve-cube-stacking-stability
# Conflicts: # newton/_src/geometry/mpr.py
2 parents b6286ed + 0efb72d commit be2b9d7

116 files changed

Lines changed: 3979 additions & 1474 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,25 @@
1818
- Add opt-in isolated multi-world implicit MPM with capacity-bounded rebuildable sparse grids, selective world resets, outer graph capture, and asynchronous overflow reporting; legacy shared topology remains the default.
1919
- Add `cloth_stiff_material_hanging` and `cloth_stiff_material_stretch` examples regression-guarding the new Neo-Hookean triangle material (stability under gravity at extreme stiffness, and bulk area-preservation across a Poisson-ratio sweep)
2020
- Add contact examples for Newton's cradle, a balance bird, and a domino spiral
21+
- Document geometry-pair contact behavior and clarify that MuJoCo Warp currently produces a single contact for cylinder--box pairs even with MultiCCD enabled.
2122
- Add `ViewerUSD(points_as_spheres=...)` to render `log_points` particles as a `UsdGeom.PointInstancer` of sphere prototypes; enabled by default (opt out with `points_as_spheres=False` for flat `UsdGeom.Points` splats)
2223
- Add list-of-pattern and explicit-index selectors to `ArticulationView`.
2324
- Add `newton[onnx]` for ONNX policy inference through Warp-NN; `ControllerNeuralMLP`, `ControllerNeuralLSTM`, and RL policy examples can run exported `.onnx` policies without requiring PyTorch for ONNX execution.
2425
- Add three VBD contact examples — `vbd_rigid_rigid_contact`, `vbd_soft_rigid_contact`, and `vbd_soft_rigid_mix_contact` — demonstrating rigid-rigid, soft (particle-rigid), and mixed cloth-bag contacts
25-
- Add masked rigid-body reset support to `SolverVBD`; particle resets are not yet supported. (#3256)
26+
- Add masked rigid-body reset support to `SolverVBD`. (#3256)
2627
- Add `Mesh.invalidate_cache()` to drop cached derived data (hash, edges, finalized Warp meshes) after in-place modification of `Mesh.vertices` or `Mesh.indices`; reassigning those properties invalidates automatically.
2728
- Add viewer layer system to overlay multiple solvers/models in supported rendering viewers; call `ViewerBase.activate(layer_id)` to route subsequent `set_model` / `log_state` / `log_*` calls into a named layer, `ViewerBase.set_layer_visible()` to toggle layers independently, and `ViewerBase.set_layer_transform()` to position layers side-by-side. See `example_basic_multi_solver_overlay.py`
2829
- Add `Heightfield.create_from_mesh()` and `newton.utils.rasterize_mesh_to_heightfield()` to build a heightfield collider by ray-casting a `wp.Mesh`, replacing a large static terrain mesh with an equivalent heightfield.
2930
- Add `ViewerBase.camera_speed` to configure keyboard translation speed for interactive viewers. (#3439)
31+
- Add read-only `Contacts.contact_matching_mode` metadata reporting whether the `CollisionPipeline` that produced or last filled the buffer used `"disabled"`, `"latest"`, or `"sticky"` contact matching.
3032
- Add a "Show Ground" visualization toggle (`ViewerBase.show_ground`, default on) to hide or show ground-plane shapes in the viewer.
3133
- Add opt-in DVI forward dynamics to `SolverKamino` through `SolverKamino.Config(dynamics_solver="dvi")`, with sparse and dense execution, DVI-specific diagnostics, and warm-starting. PADMM remains the default.
3234
- Add opt-in DVI forward dynamics to `SolverKamino` through `SolverKamino.Config(dynamics_solver="dvi")`, with sparse and dense execution, DVI-specific convergence diagnostics, warm-starting, bounded contact-recovery controls, and RCM-reordered bilateral factorization with reusable ordering and panel-parallel numeric factorization for large systems. PADMM remains the default.
3335
- Add SDF contact support for convex-hull shapes with mesh-attached SDFs and opt-in SDF contact generation for box shapes.
3436
- Warn in `ModelBuilder.add_usd()` when a rigid body prim has a mirrored (negative-determinant) world transform. Improper transforms have no unique rotation decomposition, so imported body and joint frames can acquire a spurious constant rotation (common with mirror-scaled CAD exports); the warning recommends baking the reflection into the mesh geometry before import.
3537
- Add opt-in filtering of static-static, static-kinematic, and kinematic-kinematic contacts during broad-phase collision detection. Set `CollisionPipeline(include_static_kinematic_pairs=False)` to enable filtering; the default preserves existing contact generation. `Model.shape_contact_pairs` remains an unfiltered superset for direct consumers such as `SolverKamino` and hydroelastic SDF setup.
3638
- Add opt-in `body_frame_origin="com"` to `ModelBuilder.add_rod()` and `ModelBuilder.add_rod_graph()` for COM-centered cable capsule body frames.
39+
- Add dedicated gravity for global world `-1` while preserving the single-entry `Model.gravity` array for implicit single-world models and local-only array updates through `Model.set_gravity()`. (#3723)
3740
- Add `sign_method` argument to `Mesh.build_sdf` and `SDF.create_from_mesh` support for a `"normal"` (angle-weighted pseudo-normal) sign strategy, for selecting the inside/outside sign of the baked SDF (`"auto"`, `"parity"`, `"winding"`, or `"normal"`).
3841
- Add opt-in MuJoCo Warp sleeping support to `SolverMuJoCo` with MJCF sleep configuration, initial tree policies, `sleep_tolerance`, compact `nvmax` storage, and a launchable `mujoco_sleeping` example. (#3725)
3942
- Add `forward_depth_image` output support to `SensorTiledCamera.update()` and `SensorTiledCamera.utils.create_forward_depth_image_output()` for native forward-depth rendering without post-processing `depth_image`.
@@ -48,10 +51,12 @@
4851
- Add simulation throughput, real-time factor, p95 step-time, steady-state GPU-memory, timestep, and MuJoCo solver-iteration metrics to the ASV robot-learning benchmarks.
4952
- Add `joint_dof_mask` to `newton.ik.IKSolver` to keep selected joint DOFs fixed during LM optimization. (#3488)
5053
- Add `SolverMuJoCo(disable_sensors=True)` to skip MuJoCo sensor computation.
54+
- Add masked deformable reset to `SolverVBD.reset()`: `StateFlags.PARTICLE_Q` / `StateFlags.PARTICLE_QD` restore cloth and soft-body particle state per world selected by `world_mask`. (#3400)
5155

5256
### Changed
5357

5458
- Decide collider visibility from USD `purpose` and visibility rather than from a bound render material. A collider whose `purpose` resolves to `default` is viewport geometry and is drawn; mark it `guide` to state that it is collision-only. Previously an unrelated visual elsewhere in the scene could make a collider vanish. `force_show_colliders` and `hide_collision_shapes` are unchanged.
59+
- Require `warp-lang>=1.16.0`; upgrade Warp to version 1.16.0 or later.
5560
- Disable the implicit positive Dahl-friction defaults in `SolverVBD.register_custom_attributes()` (deprecated in 1.3.0): `vbd:dahl_eps_max` and `vbd:dahl_tau` now default to zero, and Dahl cable friction is enabled only where both are authored positive. Pass `dahl_defaults_enabled=True` to temporarily restore the old defaults; the compatibility mode will be removed in a future release.
5661
- Keep the authored render mesh when `ModelBuilder.add_usd()` approximates a collider. `physics:approximation` is scoped to collision, so a Mesh that is both render geometry and a collider now imports as an approximated collision shape plus a visual shape carrying the original topology, instead of replacing the render mesh with the approximation. This raises `Model.shape_count` for such prims: iterate on `ShapeFlags.COLLIDE_SHAPES` rather than assuming one shape per collider prim. The visual shape adds no mass and no collision, appends after the originals so existing shape indices and `path_shape_map` entries are unchanged, and is skipped when `load_visual_shapes=False`.
5762
- Compile tiled camera render kernels with CUDA fast math by default for faster rendering; set `SensorTiledCamera.render_config.enable_fast_math = False` for bit-exact, IEEE-precise output.
@@ -91,9 +96,11 @@
9196
- Deprecate `SensorTiledCamera(..., config=...)` in favor of `SensorTiledCamera(..., default_render_config=...)`; migrate constructor calls that pass a render config to the new keyword.
9297
- Deprecate `SensorTiledCamera.render_config` in favor of `SensorTiledCamera.default_render_config`; migrate `sensor.render_config.enable_shadows = True` to `sensor.default_render_config.enable_shadows = True`.
9398
- Deprecate `SensorTiledCamera.utils.compute_pinhole_camera_rays()` in favor of `SensorTiledCamera.utils.compute_camera_rays_pinhole()`.
99+
- Deprecate the legacy DOF-shaped `joint_target_q` layout (`newton.use_coord_layout_targets = False`) for models whose joint coordinate and DOF counts differ (free/ball/distance joints); `ModelBuilder.finalize()` now emits a `DeprecationWarning` for such models. Set `newton.use_coord_layout_targets = True` before building models and index targets via `Model.joint_target_q_start`. A future release will make the coordinate layout the only layout and remove the flag.
94100

95101
### Removed
96102

103+
- Remove the deprecated `joint_target_pos` / `joint_target_vel` aliases from `Model`, `Control`, and `ModelBuilder` (deprecated in 1.3.0); use `joint_target_q` / `joint_target_qd` instead. Reading or assigning the removed names raises `AttributeError` naming the replacement, so a stale `control.joint_target_pos = targets` fails loudly instead of being silently ignored. `Actuator` now always defaults `control_target_pos_attr` / `control_target_vel_attr` to the canonical `joint_target_q` / `joint_target_qd` names; passing `None` explicitly selects the same defaults.
97104
- Remove the deprecated SDF compatibility attributes `Model.shape_sdf_index`, `Model.texture_sdf_data`, `Model.texture_sdf_coarse_textures`, `Model.texture_sdf_subgrid_textures`, `Model.texture_sdf_subgrid_start_slots`, `Model.sdf_block_coords`, `Model.sdf_index2blocks`, and `SDF.texture_block_coords` (deprecated in 1.3.0); the hydroelastic broadphase derives block coordinates arithmetically and the remaining storage is internal.
98105
- Remove the deprecated `newton.geometry.build_bvh_shape()`, `refit_bvh_shape()`, `build_bvh_particle()`, and `refit_bvh_particle()` helpers (deprecated in 1.3.0); use `Model.bvh_build_shapes()`, `Model.bvh_refit_shapes()`, `Model.bvh_build_particles()`, and `Model.bvh_refit_particles()` instead.
99106
- Remove the deprecated `Model.has_heightfields` property (deprecated in 1.3.0); use `Model.heightfield_count`, or `model.heightfield_count > 0` for boolean checks, instead.
@@ -102,6 +109,7 @@
102109

103110
### Fixed
104111

112+
- Fix MPR returning scale-dependent, excessively deep contacts for small convex shapes on large mesh triangles while preserving triangle-specific shared-edge manifold witnesses.
105113
- Make deterministic collision pipelines cover hydroelastic contact generation and reduction, including unique reduced-contact sort keys and overflow-safe fixed-point pressure accumulation.
106114
- Preserve box-box face contact manifolds under sub-microradian solver drift.
107115
- Fix `SolverMuJoCo` retaining an invalid external-contact cache when its first step is captured in a CUDA graph. (#3767)
@@ -117,6 +125,7 @@
117125
- Exclude active particles with non-finite positions from rebuildable `SolverImplicitMPM` sparse-grid packing.
118126
- Fix incorrect hydroelastic contact surfaces for primitive shapes. (#3150, #3239)
119127
- Fix masked `SolverCoupledProxy.reset()` calls clearing proxy feedback history for unselected worlds.
128+
- Fix masked solver resets modifying unselected worlds or discarding their coupling and contact history.
120129
- Fix MJCF, URDF, and USD imports rendering collision-only bodies as visuals when the asset authors visual geometry elsewhere. (#3291)
121130
- Fix `SchemaResolverPhysx` reading every D6 translational limit gain from the `linear` instance instead of its `transX`, `transY`, or `transZ` instance.
122131
- Fix USD capsule, cylinder, and cone visuals and sites without authored `radius`/`height` to use the UsdGeom schema fallbacks, matching collision shapes.
@@ -139,6 +148,8 @@
139148
- Fix Style3D solver divergence caused by isolated vertices.
140149
- Fix a use-after-free where finalizing a second model built from shared mesh geometry (e.g. via `ModelBuilder.replicate()` or `ModelBuilder.add_builder()`) invalidated the meshes referenced by previously finalized models.
141150
- Fix compiler warnings about overflowing int32 constants when compiling SDF texture and `SensorTiledCamera` kernels.
151+
- Fix `SolverVBD` particles using world 0 gravity in multi-world models instead of their assigned world's gravity. (#3692)
152+
- Fix `SensorIMU` to use per-world gravity for world-local sites not attached to a body.
142153
- Fix USD site import to discover sites beneath non-visual containers, collider prims, and instanceable rigid-body prims independently of `load_visual_shapes`; the reworked traversal also speeds up import of scenes with many nested `Xform` or instance prims.
143154
- Fix `SolverFeatherstone` BALL joints to apply passive `joint_damping` on all three angular DOFs.
144155
- Fix `eval_ik()` and `SolverSemiImplicit` rounding small float32 revolute-joint angles to zero. (#3434)
@@ -147,6 +158,7 @@
147158
- Fix `FastKitchenG1` ASV metrics to build the kitchen scene instead of a plain G1 model.
148159
- Fix the `diffsim_bear` example crashing with its default CUDA configuration and diverging after a few training iterations.
149160
- Fix masked PID state reset to execute on the integral-state device. (#3447)
161+
- Fix `eval_inverse_dynamics_passive()` reading past a DOF-sized scratch buffer under `newton.use_coord_layout_targets = True`, producing intermittent NaNs for models with free, ball, or distance joints.
150162
- Fix MJCF imports ignoring `fromto` transforms and lengths on sites.
151163
- Reject invalid hollow primitive shell thickness before computing inertia.
152164
- Fix `ModelBuilder.add_mjcf()` ignoring positive explicit mass on mesh geoms. (#3595)

asv.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"build_command": ["python -m build --wheel -o {build_cache_dir} {build_dir}"],
1717
"install_command": [
1818
"in-dir={env_dir} python -m pip install {wheel_file}[dev] --extra-index-url=https://pypi.nvidia.com/",
19-
"in-dir={env_dir} python -m pip install warp-lang==1.16.0.dev20260716 mujoco==3.11.0 mujoco-warp==3.11.0 --extra-index-url=https://pypi.nvidia.com/",
19+
"in-dir={env_dir} python -m pip install warp-lang==1.16.0 mujoco==3.11.0 mujoco-warp==3.11.0 --extra-index-url=https://pypi.nvidia.com/",
2020
"python -m pip install torch==2.10.0+cu130 --index-url https://download.pytorch.org/whl/cu130"
2121
]
2222
}

docs/concepts/collisions.rst

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,205 @@ Examples:
143143
See :ref:`Solver Integration` for the full code pattern showing how to configure
144144
this.
145145

146+
.. _Geometry Pair Contact Behavior:
147+
148+
Geometry-Pair Contact Behavior
149+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
150+
151+
The two tables below describe contacts generated by Newton's
152+
:class:`~CollisionPipeline` only; they do not apply to contacts generated by the
153+
native MuJoCo CPU or MuJoCo Warp collision pipelines. The values are theoretical
154+
upper bounds per shape pair and collision pass before the shared
155+
``rigid_contact_max`` capacity is applied. Actual counts vary with pose, margin,
156+
and collision settings.
157+
158+
**CollisionPipeline primitive and convex-hull pairs**
159+
160+
.. list-table::
161+
:header-rows: 1
162+
:stub-columns: 1
163+
:widths: 18 9 9 10 11 11 8 9 13
164+
165+
* - Shape A / Shape B
166+
- Plane
167+
- Sphere
168+
- Capsule
169+
- Ellipsoid
170+
- Cylinder
171+
- Box
172+
- Cone
173+
- Convex hull
174+
* - Plane
175+
- 5
176+
- 1
177+
- 2
178+
- 1
179+
- 4
180+
- 4
181+
- 5
182+
- 5
183+
* - Sphere
184+
- 1
185+
- 1
186+
- 1
187+
- 1
188+
- 1
189+
- 1
190+
- 1
191+
- 1
192+
* - Capsule
193+
- 2
194+
- 1
195+
- 2
196+
- 1
197+
- 5
198+
- 5
199+
- 5
200+
- 5
201+
* - Ellipsoid
202+
- 1
203+
- 1
204+
- 1
205+
- 1
206+
- 1
207+
- 1
208+
- 1
209+
- 1
210+
* - Cylinder
211+
- 4
212+
- 1
213+
- 5
214+
- 1
215+
- 5
216+
- 5
217+
- 5
218+
- 5
219+
* - Box
220+
- 4
221+
- 1
222+
- 5
223+
- 1
224+
- 5
225+
- 5
226+
- 5
227+
- 5
228+
* - Cone
229+
- 5
230+
- 1
231+
- 5
232+
- 1
233+
- 5
234+
- 5
235+
- 5
236+
- 5
237+
* - Convex hull
238+
- 5
239+
- 1
240+
- 5
241+
- 1
242+
- 5
243+
- 5
244+
- 5
245+
- 5
246+
247+
The plane--plane upper bound is five when at least one plane is finite. Two
248+
infinite planes produce no contacts.
249+
250+
**CollisionPipeline mesh, heightfield, and SDF routes**
251+
252+
``V`` is a mesh vertex count, ``T_overlap`` is the number of overlapping
253+
triangles, and ``E`` is the number of collision edges. The estimated typical
254+
count is the sizing heuristic used for allocation, not a measured statistical
255+
average or a per-pair limit.
256+
257+
.. list-table::
258+
:header-rows: 1
259+
:widths: 27 18 23 12 20
260+
261+
* - Pair or route
262+
- Reduced maximum (default)
263+
- Unreduced maximum
264+
- Estimated typical count
265+
- Notes
266+
* - Triangle mesh--infinite plane
267+
- 240
268+
- ``V_mesh``
269+
- About 40
270+
- At most one candidate per mesh vertex.
271+
* - Mesh/heightfield--sphere or ellipsoid
272+
- 240
273+
- ``T_overlap``
274+
- About 40
275+
- At most one contact per overlapping triangle.
276+
* - Mesh/heightfield--other primitive or convex hull
277+
- 240
278+
- ``5 * T_overlap``
279+
- About 40
280+
- Each overlapping triangle uses the convex manifold path.
281+
* - Mesh--mesh
282+
- 240
283+
- ``E_A + E_B``
284+
- About 40
285+
- Uses edge-vs-SDF queries, with BVH distance fallback when needed.
286+
* - Heightfield--mesh
287+
- 240
288+
- ``E_heightfield + E_mesh``
289+
- About 40
290+
- Uses the mesh/SDF route with on-the-fly heightfield evaluation.
291+
* - Hydroelastic SDF--SDF
292+
- 240 by default
293+
- Geometry and buffer dependent
294+
- No fixed estimate
295+
- ``anchor_contact=True`` can add contacts beyond the reduced set.
296+
297+
The reduced maximum follows the current 240-slot contact-reduction layout.
298+
Disabling reduction exposes the geometry-dependent candidate bounds shown above.
299+
300+
**Common pair guidance**
301+
302+
.. list-table::
303+
:header-rows: 1
304+
:widths: 16 23 31 30
305+
306+
* - Pair
307+
- Expected behavior
308+
- Backend notes
309+
- Asset guidance
310+
* - Sphere--plane or sphere--box
311+
- A point contact.
312+
- Newton, MuJoCo Warp, and MuJoCo CPU use single-contact primitive paths.
313+
- Use one sphere unless the asset needs a finite support patch; then use
314+
multiple collision shapes or a surface-contact representation.
315+
* - Capsule--plane or capsule--box
316+
- End-on contact is point-like; side-on contact can span the capsule axis.
317+
- Newton and both MuJoCo backends have multi-contact paths for the
318+
line-like side contact.
319+
- A single capsule is normally sufficient. Use a compound only when the
320+
physical profile is not capsule-shaped.
321+
* - Box--plane or box--box
322+
- Face contact forms an area-supporting manifold; edge and corner contacts
323+
use fewer points.
324+
- Newton and both MuJoCo backends generate multi-point face contacts.
325+
- Prefer a single box for box-like parts; it is cheaper and usually more
326+
stable than a tessellated mesh.
327+
* - Cylinder--box
328+
- A cylinder lying across a broad box face should have a manifold spanning
329+
its support region.
330+
- Newton generates a convex manifold. MuJoCo CPU can generate a multi-point
331+
manifold with multi-CCD enabled. MuJoCo Warp currently emits one contact
332+
for this pair even with ``enable_multiccd=True``; contact location can
333+
alternate between the cylinder ends. This is a known discrepancy tracked
334+
in `mujoco_warp#1555
335+
<https://github.com/google-deepmind/mujoco_warp/issues/1555>`__.
336+
- Keep a single cylinder with Newton contacts. While the MuJoCo Warp issue
337+
is open, use ``use_mujoco_contacts=False`` or, if that is not possible,
338+
approximate load-bearing regions with multiple collision shapes.
339+
340+
The MuJoCo Warp cylinder--box behavior above is a known discrepancy, not the intended
341+
single-contact behavior of the geometry pair. For non-convex assets, use a
342+
convex compound or Newton's mesh/SDF paths rather than expecting one primitive
343+
to reproduce the surface. See :ref:`Mesh Collisions` and :ref:`Simulation Tuning`.
344+
146345
.. _Collision Pipeline:
147346

148347
Collision Pipeline

0 commit comments

Comments
 (0)