VBD New Features#1479
Conversation
📝 WalkthroughWalkthroughAdds tet-aware VBD kernels and per-type adjacency, refactors graph-coloring to Python edge utilities, updates ModelBuilder coloring and soft-mesh plumbing, expands SolverVBD collision/truncation state and APIs, and adds many new examples, tests, and README gallery entries. Changes
Sequence Diagram(s)sequenceDiagram
participant Example as Example/Viewer
participant Builder as ModelBuilder
participant Graph as GraphColoring
participant Solver as SolverVBD
participant Kernels as VBD_Kernels
Note over Example,Builder: Example builds scene (particles, faces, tets)
Example->>Builder: build model (particles, faces, tets, per-face radii)
Builder->>Graph: request particle graph (tri/tet edges, bending edges, masks)
Graph-->>Builder: canonicalized edge lists + masks
Builder->>Solver: finalize model (adjacency, surface edges, particle radii)
Solver->>Kernels: upload adjacency & initialize device buffers
loop per substep
Example->>Solver: apply external/kinematic forces
Solver->>Kernels: compute contacts & truncation_ts
Kernels-->>Solver: contact/truncation outputs
Solver->>Kernels: solve_elasticity / self-contact (tile solves)
Kernels-->>Solver: updated forces/positions
end
Solver->>Example: render state (positions, diagnostics)
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
There was a problem hiding this comment.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
newton/_src/sim/graph_coloring.py (1)
146-228: Docstring is out of sync with the new signature.The current docstring still describes the old parameters. Please update it to a Google-style docstring that reflects
tri_indices, active masks, bending edges, and the returned unique edge array.As per coding guidelines: "Use Google-style docstrings with clear explanations of what the function does, its parameters, and return values."✍️ Docstring update (example)
def construct_trimesh_graph_edges( tri_indices, tri_active_mask=None, bending_edge_indices=None, bending_edge_active_mask=None, ): - """ - A function that generates vertex coloring for a trimesh, which is represented by the number of vertices and edges of the mesh. - It will convert the trimesh to a graph and then apply coloring. - It returns a list of `np.array` with `dtype`=`int`. The length of the list is the number of colors - and each `np.array` contains the indices of vertices with this color. - - Args: - num_nodes: The number of the nodes in the graph - trimesh_edge_indices: A `wp.array` with of shape (number_edges, 4), each row is (o1, o2, v1, v2), see `sim.Model`'s definition of `edge_indices`. - include_bending_energy: whether to consider bending energy in the coloring process. If set to `True`, the generated - graph will contain all the edges connecting o1 and o2; otherwise, the graph will be equivalent to the trimesh. - """ + """ + Build a unique edge list from triangle indices and optional bending hinges. + + Args: + tri_indices: Triangle indices (N, 3), NumPy or Warp array. + tri_active_mask: Optional active-mask for triangles. + bending_edge_indices: Optional hinge indices (M, 4). + bending_edge_active_mask: Optional active-mask for hinges. + + Returns: + np.ndarray: Unique edges of shape (E, 2), dtype int32. + """newton/_src/sim/builder.py (1)
4040-4057: Document the newheightparameter inadd_ground_plane.The docstring doesn’t mention the new argument, which makes the public API unclear.
✏️ Suggested docstring update
def add_ground_plane( - height=0.0, + height: float = 0.0, cfg: ShapeConfig | None = None, key: str | None = None, ) -> int: """Adds a ground plane collision shape to the model. Args: + height (float): Offset of the plane along the up axis (positive moves the plane in +up). cfg (ShapeConfig | None): The configuration for the shape's physical and collision properties. If `None`, :attr:`default_shape_cfg` is used. Defaults to `None`. key (str | None): An optional unique key for identifying the shape. If `None`, a default key is automatically generated. Defaults to `None`.As per coding guidelines, Use Google-style docstrings with clear explanations of what the function does, its parameters, and return values.
newton/_src/solvers/vbd/solver_vbd.py (1)
1271-1278: Remove the unusedstate_outparameter frominitialize_rigid_bodiesmethod.The
state_outparameter is declared in the method signature but is never used in the method body. If this parameter is not needed for future functionality, it should be removed to avoid confusion. If it is intentionally reserved for future use, add a comment in the docstring explaining this intention.
🤖 Fix all issues with AI agents
In `@newton/_src/sim/graph_coloring.py`:
- Around line 110-143: In construct_tetmesh_graph_edges the local tet_np is
never initialized when tet_indices is a NumPy array and the mask branch indexes
tet_indices instead of tet_np; fix by normalizing inputs up front: if
tet_indices is a wp.array convert it to a NumPy array (tet_np =
tet_indices.numpy()), else assign tet_np = tet_indices; then, if tet_active_mask
is not None, convert tet_active_mask to a NumPy boolean/indices array if needed
and apply it to tet_np (tet_np = tet_np[np.where(tet_active_mask > 0)] or tet_np
= tet_np[mask]) so all subsequent code uses tet_np consistently (refer to
construct_tetmesh_graph_edges, tet_np, and tet_active_mask).
In `@newton/_src/solvers/vbd/particle_vbd_kernels.py`:
- Around line 3029-3034: The debug wp.printf calls pass arguments to
get_vertex_num_adjacent_faces in the wrong order: the function signature is
get_vertex_num_adjacent_faces(adjacency, vertex), but the code calls
get_vertex_num_adjacent_faces(particle_index, particle_adjacency); swap the
arguments to get_vertex_num_adjacent_faces(particle_adjacency, particle_index)
in the wp.printf that prints "num_adj_faces" (and ensure the same fix is applied
to the second identical debug wp.printf further down). Keep the surrounding
static check (wp.static("connectivity" in VBD_DEBUG_PRINTING_OPTIONS)) and
wp.printf invocation unchanged except for the corrected argument order.
- Around line 385-387: Guard the division by lmbd when computing alpha in the
Neo-Hookean code: before computing alpha = 1.0 + mu / lmbd, either
assert/enforce lmbd > 0 or clamp it to a small positive epsilon (e.g.,
lmbd_clamped = max(lmbd, 1e-8)) and then compute alpha = 1.0 + mu /
lmbd_clamped; update any uses of alpha to reference this safe value and/or add a
clear assertion/error message if you intend to require an upstream guarantee
that lmbd > 0.
- Around line 61-74: The new kernel helper types mat99, mat93, mat43, and vec9
are not exposed via the public API and must be either re-exported or marked
private; decide which applies and implement it: if they are intended for public
use, add explicit re-exports for mat99, mat93, mat43, and vec9 from the public
module (e.g., newton/solvers.py or newton/__init__.py) so users can import them,
otherwise rename the classes to _mat99, _mat93, _mat43, and _vec9 in
particle_vbd_kernels.py (matching the internal pattern like _mat43f) to mark
them private and update any internal references to use the new names. Ensure
references to these symbols in other modules are updated accordingly.
In `@newton/_src/solvers/vbd/solver_vbd.py`:
- Around line 1177-1234: The wp.launch calls in penetration_free_truncation pass
kernel arguments in the wrong slots for apply_truncation_ts; move the
displacement_out (self.particle_displacements), pos_out (particle_q_out) and
max_displacement (wp.inf or computed scalar) into the inputs= list in the same
order as the kernel signature and supply only actual output arrays in the
outputs= list (or leave outputs empty if kernel writes to inputs in-place);
update both wp.launch invocations that call apply_truncation_ts (the one in the
non-self-contact branch and the later one in the self-contact branch) so their
inputs match apply_truncation_ts(pos, displacement_in, truncation_ts,
displacement_out, pos_out, max_displacement) and outputs contain only true
output buffers.
- Around line 42-47: The import break is due to renaming kernels:
accumulate_contact_force_and_hessian ->
accumulate_particle_body_contact_force_and_hessian and
accumulate_contact_force_and_hessian_no_self_contact ->
accumulate_self_contact_force_and_hessian; fix by adding backward-compatible
aliases in solver_vbd.py that assign the old names to the new functions (e.g.,
set accumulate_contact_force_and_hessian =
accumulate_particle_body_contact_force_and_hessian and
accumulate_contact_force_and_hessian_no_self_contact =
accumulate_self_contact_force_and_hessian) and ensure they are exported where
other modules import them so collision_legacy.py can continue importing the old
symbols without changes.
In `@newton/examples/__init__.py`:
- Line 485: Fix the typo where the examples package list contains the string
"mutlphysics": replace that entry with the correct module name "multiphysics" so
example discovery (os.listdir iteration) can find the multiphysics examples;
look for the string "mutlphysics" in newton/examples/__init__.py (the package
exports/list of example module names) and correct it to "multiphysics".
- Line 489: The package name "Softbody" in newton/examples/__init__.py uses
PascalCase while all other example directories are lowercase; rename the
filesystem directory from "Softbody" to "softbody" and update the reference
string in __init__.py (replace "Softbody" with "softbody") so imports and
package discovery use the lowercase name consistently; also verify any other
references or imports elsewhere use the new lowercase directory name and adjust
them if present.
In `@newton/examples/mutlphysics/example_falling_gift.py`:
- Around line 22-24: Update the documentation header comment in
example_falling_gift.py to show the correct module run command: replace the
incorrect "python -m newton.examples.cloth.06_FallingGift.falling_gift" with
"python -m newton.examples.mutlphysics.example_falling_gift" so the example
discovery pattern in newton/examples/__init__.py matches this file (edit the
top-of-file comment in example_falling_gift.py).
In `@newton/tests/test_softbody.py`:
- Around line 313-332: The test function test_tet_adjacency_single_tet has
multiple issues: change the call from compute_force_element_adjacency(model) to
the correct method compute_particle_force_element_adjacency() (no args) on the
SolverVBD instance; stop shadowing the passed-in solver by either remove the
local SolverVBD() creation or use the passed solver (ensure solver.model and
solver.device are set); pass the test harness object into the adjacency
assertion by calling _assert_adjacency_matches_tets(test, adjacency,
tet_indices); and register the test at the end of the file with
add_function_test(TestSoftBody, "test_tet_adjacency_single_tet",
test_tet_adjacency_single_tet, devices=devices). Ensure you also remove or use
unused parameters (device) consistently.
- Around line 1-14: Add the standard Apache 2.0 license header to the top of the
test module (test_softbody.py) so the file passes license-eye; place the
multi-line Apache 2.0 header above the existing imports (before the first import
line), keeping the header formatting consistent with other project files and
ensuring it precedes the imported symbols such as ModelBuilder and
evaluate_volumetric_neo_hookean_force_and_hessian.
- Around line 501-506: Add a registration call for the missing test function so
it runs: locate the test registration block where get_test_devices(...) and
add_function_test(...) are called for TestSoftBody (the lines registering
test_tet_adjacency_complex_pyramid, test_tet_graph_coloring_is_valid, and
test_tet_energy) and add a new add_function_test(TestSoftBody,
"test_tet_adjacency_single_tet", test_tet_adjacency_single_tet, devices=devices)
entry next to them to ensure test_tet_adjacency_single_tet is executed.
🧹 Nitpick comments (4)
newton/examples/mutlphysics/example_softbody_dropping_to_cloth.py (1)
126-137: Consider computing contacts once per frame and reusing across substeps.If you want to follow the common example pattern and avoid redundant broad-phase work, move
collide()outside the substep loop and reuse the result for all substeps in a frame. Keep the current approach only if substep-level contact refresh is required for this scenario.Based on learnings: In Newton example code, computing contacts once per frame and reusing them across all substeps is the intended pattern.♻️ Suggested change
def simulate(self): - for _ in range(self.sim_substeps): + self.contacts = self.model.collide(self.state_0, collision_pipeline=self.collision_pipeline) + for _ in range(self.sim_substeps): self.state_0.clear_forces() # apply forces to the model self.viewer.apply_forces(self.state_0) - self.contacts = self.model.collide(self.state_0, collision_pipeline=self.collision_pipeline) self.solver.step(self.state_0, self.state_1, self.control, self.contacts, self.sim_dt)newton/_src/sim/graph_coloring.py (1)
230-249: Add a Google-style docstring forconstruct_particle_graph.This new helper is public within the module but currently undocumented.
As per coding guidelines: "Use Google-style docstrings with clear explanations of what the function does, its parameters, and return values."✍️ Docstring addition (example)
def construct_particle_graph( tri_graph_edges: np.array, tri_active_mask: np.array, bending_edge_indices: np.array, bending_edge_active_mask: np.array, tet_graph_edges_np: np.array, tet_active_mask: np.array, ): + """ + Merge trimesh and tetmesh edges into a single particle-graph edge list. + + Args: + tri_graph_edges: Triangle indices or precomputed triangle edges. + tri_active_mask: Optional active-mask for triangles. + bending_edge_indices: Optional hinge indices. + bending_edge_active_mask: Optional active-mask for hinges. + tet_graph_edges_np: Tet indices or precomputed tet edges. + tet_active_mask: Optional active-mask for tets. + + Returns: + wp.array: Edge list on CPU with shape (E, 2), dtype int. + """newton/examples/mutlphysics/example_falling_gift.py (1)
94-139: Consider extracting shared test data to avoid duplication.
PYRAMID_TET_INDICESandPYRAMID_PARTICLESare duplicated verbatim innewton/tests/test_softbody.py. Consider extracting these to a shared module (e.g.,newton/examples/assets/or a test utilities module) to follow the DRY principle.newton/_src/solvers/vbd/particle_vbd_kernels.py (1)
2325-2335: Renamelto avoid Ruff E741 and improve clarity.Ruff flags
las ambiguous. Rename to a clearer name (e.g.,length) to satisfy linting and readability.✏️ Suggested rename
- l = wp.length(diff) + length = wp.length(diff) l0 = spring_rest_length[spring_idx] @@ - base_force = spring_stiffness[spring_idx] * (l0 - l) / l * diff + base_force = spring_stiffness[spring_idx] * (l0 - length) / length * diff @@ - wp.identity(3, float) - (l0 / l) * (wp.identity(3, float) - wp.outer(diff, diff) / (l * l)) + wp.identity(3, float) - (l0 / length) * (wp.identity(3, float) - wp.outer(diff, diff) / (length * length))
|
I will probably join the review sometime next week, so please don't wait for me if I am late. I can follow up separately. |
There was a problem hiding this comment.
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/solvers/vbd/solver_vbd.py (1)
1275-1282: Unused parameterstate_outininitialize_rigid_bodies.The
state_outparameter is declared but never used within the method body. If this is intentional for API consistency, consider prefixing with underscore (_state_out) to suppress linter warnings.🛡️ Proposed fix
def initialize_rigid_bodies( self, state_in: State, - state_out: State, + _state_out: State, contacts: Contacts | None, dt: float, update_rigid_history: bool, ):
mmacklin
left a comment
There was a problem hiding this comment.
Examples and tests look great, just wasn't clear to me why we need to introduce a new set of defaults here:
self.default_surface_mesh_tri_ka = 0.0
self.default_surface_mesh_tri_kd = 0.0
self.default_surface_mesh_tri_drag = 0.0
self.default_surface_mesh_tri_lift = 0.0
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
newton/_src/sim/graph_coloring.py (1)
162-173: Update docstring to match the new signature.
The docstring still referencesnum_nodes,trimesh_edge_indices, andinclude_bending_energy, which no longer exist. Please update it to the new parameters and return value format.As per coding guidelines: Use Google-style docstrings with clear explanations of what the function does, its parameters, and return values.
newton/_src/sim/builder.py (1)
6420-6778: Guard_to_wp_array()result before passing to BVH methods in Style3D collision.The
_to_wp_array()function returnsNonefor empty arrays, butCollision.__init__()passes these directly toBvhTri.build()andBvhEdge.build()without checking forNone. The BVH update methods access.shapeattributes and will fail withAttributeErrorif the indices areNone.XPBD and VBD solvers handle this correctly by guarding with count checks (
if model.spring_count:,if self.model.tri_indices:) before kernel launches. Style3D collision needs the same pattern—either guard the BVH initialization/calls inCollision.__init__(),rebuild_bvh(),refit_bvh(), andframe_begin(), or ensure BVH methods handleNonegracefully.
🤖 Fix all issues with AI agents
In `@newton/_src/sim/builder.py`:
- Around line 6148-6153: The active-mask creation for bending edges currently
only checks the damping column (edge_bending_properties[:,1]) so edges with
stiffness (edge_k or column 0) but zero damping are skipped; update the building
of bending_edge_active_mask (used when include_bending and edge_indices) to
consider both stiffness and damping — e.g., extract both columns from
edge_bending_properties and set the mask where either stiffness or damping is
nonzero (logical OR / np.any across columns) so bending edges with nonzero
stiffness are included.
- Around line 4025-4031: Before normalizing the plane normal, check that the
computed norm is non-zero (e.g., norm > 1e-12); if it is zero (or below epsilon)
raise a ValueError with a clear message including the problematic plane data
instead of proceeding to divide by zero. Specifically, around the code that
computes normal = np.array(plane[:3]), norm = np.linalg.norm(normal) and then
normal /= norm / d_normalized = plane[3] / norm, add a guard that validates
norm, then only perform the in-place normalization and compute pos when valid;
include the plane or its normal in the exception message to aid debugging.
In `@newton/_src/sim/graph_coloring.py`:
- Around line 210-213: The current indexing of bend_np with
bending_edge_active_mask can collapse dimensions if the mask is a scalar; mirror
the tri_active_mask approach: convert bending_edge_active_mask to a numpy
boolean array, detect scalar masks (np.isscalar or mask.ndim==0) and expand them
to length bend_np.shape[0] (e.g., np.repeat or np.full) before applying mask =
mask != 0 and doing bend_np = bend_np[mask]; update the block around
bending_edge_active_mask and bend_np in graph_coloring.py to perform this
scalar-to-array expansion exactly like the tri_active_mask handling.
- Around line 122-130: The tet_active_mask handling uses a premature comparison
that raises TypeError for lists/tuples; change the creation of mask_arr to first
convert tet_active_mask to a numpy array and then derive the boolean mask (i.e.,
mirror the tri_active_mask pattern) so lists/tuples/scalars/ndarrays are handled
uniformly; keep the existing scalar ndim==0 branch and subsequent filtering of
tet_np using mask_arr and reference the tet_active_mask, mask_arr, and tet_np
variables when making the edit.
In `@newton/_src/solvers/vbd/particle_vbd_kernels.py`:
- Around line 2329-2340: spring_length can be zero when endpoints coincide,
causing NaNs in divisions for base_force and spring_hessian; guard by clamping
the divisor to a small epsilon (e.g., eps = 1e-8) or short-circuiting when
spring_length is near zero: compute safe_length = max(spring_length, eps) and
use safe_length in all divisions (and/or treat base_force and spring_hessian as
zero when spring_length < eps) so updates involving pos, diff,
spring_rest_length[spring_idx], base_force, and spring_hessian remain
numerically stable.
In `@newton/_src/solvers/vbd/solver_vbd.py`:
- Line 159: Update the outdated inline comment and docstring for the parameter
particle_conservative_bound_relaxation: change the inline example from "(e.g.,
0.42 -> 0.84)" to "(e.g., 0.85 -> 1.70)" where ccd_safety_margin is computed,
and expand the function/class docstring that declares
particle_conservative_bound_relaxation to briefly describe its purpose (controls
conservative collision bounds scaling), how the default change (0.85) increases
ccd_safety_margin (to ~1.70) and the practical impact on collision behavior
(more conservative collision checks, fewer false negatives but potentially
reduced permissiveness), so users tuning particle_conservative_bound_relaxation
understand trade-offs; update text in the constructor/definition that contains
the parameter name particle_conservative_bound_relaxation and the
ccd_safety_margin computation to reflect these values.
In `@newton/examples/multiphysics/example_softbody_dropping_to_cloth.py`:
- Around line 16-25: Update the header command example string: replace the long
module invocation "python -m
newton.examples.multiphysics.example_softbody_dropping_to_cloth" with the
shorter discovery-friendly form "python -m
newton.examples.example_softbody_dropping_to_cloth" in the top comment block so
the example discovery system can find and run this example using the shorter
module path.
🧹 Nitpick comments (2)
newton/tests/test_softbody.py (1)
79-91: Unuseddtparameter in kernel.The
dtparameter (Line 83) is declared but never used in the kernel body. Consider removing it if damping is not needed for this energy/force computation, or document why it's kept for API consistency.♻️ Proposed fix
`@wp.kernel` def compute_neo_hookean_energy_and_force( # inputs tet_id: int, - dt: float, pos: wp.array(dtype=wp.vec3), tet_indices: wp.array(dtype=wp.int32, ndim=2), tet_poses: wp.array(dtype=wp.mat33), tet_materials: wp.array(dtype=float, ndim=2), # outputs: particle force and hessian tet_energy: wp.array(dtype=float), particle_forces: wp.array(dtype=float), ):Also update the launch call at Line 437-450 to remove the
dtargument.newton/_src/solvers/vbd/solver_vbd.py (1)
1274-1281: Unusedstate_outparameter.The
state_outparameter (Line 1277) is declared but not used ininitialize_rigid_bodies. Consider removing it if not needed, or document why it's kept for API consistency with other methods.
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@newton/examples/cloth/example_rolling_cloth.py`:
- Around line 181-186: The __init__ method of class Example currently declares
an unused parameter args which triggers Ruff ARG002; either remove the parameter
or make it used—best fix: store it on the instance (e.g., assign args to
self.args) or rename it to _args to indicate intentional unusedness; update the
signature in Example.__init__ accordingly and adjust any call sites if you
remove the parameter.
- Around line 181-497: Add a test_final(self) method on the Example class that
validates the final simulation state: fetch positions =
self.state_0.particle_q.numpy() and first assert/return False if any positions
contain NaN/inf; verify all fixed vertices (self.fixed_point_indices) remain at
the expected attachment line (x approx left_x used earlier and z approx
self.cyl2_center[1]) within a small tolerance (e.g., 1e-3); additionally check
no particle penetrates cylinder 2 by computing radial distances from
(self.cyl2_center[0], self.cyl2_center[1]) for cloth particles and asserting all
distances >= (self.cyl2_radius - small_margin); make the method return True on
success and False (or raise AssertionError) on failure so CI can validate the
example.
- Around line 503-507: The CLI flags use underscores; change them to kebab-case
in the parser.add_argument calls so flags become "--cloth-length", "--cloth-nu",
"--cloth-thickness", "--angular-speed", and "--spin-duration" (refer to
parser.add_argument and the current flag names cloth_length, cloth_nu,
cloth_thickness, angular_speed, spin_duration). If the rest of the code accesses
args.cloth_length-style attributes, add explicit dest="cloth_length" (and
similar dest names) to each add_argument so internal attribute names remain
unchanged while the CLI flags follow kebab-case.
- Around line 34-51: In the rotate_cylinder kernel, replace host-side
math.cos/math.sin calls with the Warp device versions wp.cos and wp.sin (e.g.,
change c0 = math.cos(...) to c0 = wp.cos(...), and same for s0, c1, s1) so the
kernel uses GPU-compatible intrinsics; update any other math.* uses in
rotate_cylinder to wp.* as needed to ensure correct device execution.
🧹 Nitpick comments (1)
newton/examples/cloth/example_rolling_cloth.py (1)
34-71: Align helper docstrings with Google style.The docstrings for
rotate_cylinder,rolled_cloth_mesh, andcylinder_meshdon’t document parameters/returns in Google format.
As per coding guidelines: Use Google-style docstrings with clear explanations of what the function does, its parameters, and return values.Also applies to: 73-178
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@newton/examples/multiphysics/example_poker_cards_stacking.py`:
- Around line 40-43: The __init__ of class Example currently declares an unused
parameter args which triggers Ruff ARG002; either store it as an instance
attribute (e.g., set self.args = args in Example.__init__) or rename the
parameter to _args to indicate intentional unused status; update the signature
in Example.__init__ accordingly so the linter is satisfied and the intent is
clear.
- Around line 289-303: The lint warning is caused by unused lambda parameters in
the test_particle_state calls; update the lambdas passed to
newton.examples.test_particle_state so unused args are prefixed with an
underscore (e.g., change "lambda q, qd: ..." to "lambda _q, _qd: ..." for the
vec_inside_limits call and similarly for the velocity check if any param is
unused) while keeping the predicates' behavior unchanged; target the two calls
that reference self.state_0, the lambda that checks max(abs(qd)) < 0.5 and the
lambda that calls newton.utils.vec_inside_limits(q, p_lower, p_upper), and
rename q/qd to _q/_qd as appropriate.
- Around line 65-67: The comment for self.cube_size in
example_poker_cards_stacking.py is wrong: it says "5 cm" while the value 0.1 is
10 cm; update either the comment or the value so they match and then adjust any
dependent calculations that assume half-size or specific dimensions (search for
usages of cube_size and cube_height in the class/methods to update geometry,
collision, or placement math accordingly); specifically correct the descriptive
comment for cube_size or change cube_size to 0.05 if you intended 5 cm, and
verify cube_height-related computations remain consistent with the chosen
cube_size.
- Around line 24-31: Add this example to the README under the "Multi-Physics
Examples" section: create a screenshot at
docs/images/examples/example_multiphysics_poker_cards_stacking.png, then add an
entry that follows the existing pattern (markdown image link to that screenshot,
a GitHub link to the example module
newton.examples.multiphysics.example_poker_cards_stacking, and the runnable
command "uv run -m newton.examples multiphysics.example_poker_cards_stacking").
Ensure the README entry text and formatting match other examples (caption/title,
link, and the uv run command).
🧹 Nitpick comments (3)
newton/examples/multiphysics/example_poker_cards_stacking.py (3)
108-123: Avoid hard-coded sphere body index.Use the
add_bodyreturn value to keep this robust if body ordering changes.♻️ Proposed fix
- self.sphere_body_index = 1 # Second body (after cube) + self.sphere_body_index = body_sphere # Body index returned by add_body
239-244: Add Google-style docstrings for the Example class and its public methods.This improves discoverability and aligns with repo documentation expectations.
As per coding guidelines: Use Google-style docstrings with clear explanations of what the function does, its parameters, and return values.
244-262: Move sphere animation and collision detection outside the substep loop.Most Newton examples compute contacts once per frame and reuse them across substeps. The kinematic sphere will move the same total distance per frame (total displacement =
sphere_velocity_x * frame_dt), and the collision pipeline will execute only once instead of 20 times, reducing broad-phase computation overhead.♻️ Proposed refactor (single collide per frame)
def simulate(self): - for _ in range(self.sim_substeps): - self.state_0.clear_forces() - - # Apply viewer forces (for interactive manipulation) - self.viewer.apply_forces(self.state_0) - - # Animate kinematic sphere (move it toward the cards) - self.sphere_current_x += self.sphere_velocity_x * self.sim_dt - body_q = self.state_0.body_q.numpy() - # Update sphere position (body_q stores transforms as 7 floats: px, py, pz, qx, qy, qz, qw) - body_q[self.sphere_body_index][0] = self.sphere_current_x - body_q[self.sphere_body_index][1] = 0.0 - body_q[self.sphere_body_index][2] = self.sphere_height - self.state_0.body_q = wp.array(body_q, dtype=wp.transform) - - # Collision detection - self.contacts = self.collision_pipeline.collide(self.model, self.state_0) - - # Solver step - self.solver.step( - self.state_0, - self.state_1, - self.control, - self.contacts, - self.sim_dt, - ) - self.state_0, self.state_1 = self.state_1, self.state_0 + # Animate kinematic sphere once per frame + self.sphere_current_x += self.sphere_velocity_x * self.frame_dt + body_q = self.state_0.body_q.numpy() + # Update sphere position (body_q stores transforms as 7 floats: px, py, pz, qx, qy, qz, qw) + body_q[self.sphere_body_index][0] = self.sphere_current_x + body_q[self.sphere_body_index][1] = 0.0 + body_q[self.sphere_body_index][2] = self.sphere_height + self.state_0.body_q = wp.array(body_q, dtype=wp.transform) + + # Collision detection once per frame + self.contacts = self.collision_pipeline.collide(self.model, self.state_0) + + for _ in range(self.sim_substeps): + self.state_0.clear_forces() + + # Apply viewer forces (for interactive manipulation) + self.viewer.apply_forces(self.state_0) + + # Solver step + self.solver.step( + self.state_0, + self.state_1, + self.control, + self.contacts, + self.sim_dt, + ) + self.state_0, self.state_1 = self.state_1, self.state_0
…city Stage 1: Soft Body Solver + Unified Solver Path Core Changes: - Add volumetric Neo-Hookean FEM for tetrahedral soft bodies - Add tetrahedral mesh adjacency and graph coloring support - Separate self-contact and body-particle contact kernels - Add soft body solve kernels (solve_elasticity, solve_elasticity_tile) - Fix plane equation in add_shape_plane (closest point calculation) - Fix add_edge parameter order in add_soft_mesh New Examples: - example_softbody_hanging.py: Hanging pyramid soft body - falling_gift.py: Stacked soft bodies with cloth straps - example_softbody_dropping_to_cloth.py: Soft body on cloth interaction New Tests: - test_softbody.py: Comprehensive soft body validation suite Documentation: - MERGE_PLAN.md: Multi-stage merge plan - STAGE1_COMPLETION_SUMMARY.md: Detailed implementation notes All examples rewritten as standalone (no M01_Simulator dependency). Truncation mode selection removed (hardcoded to mode 0). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
… bug fix) CRITICAL BUG FIX: The previous commit converted VBD to displacement-based but removed ALL truncation logic, causing particles to penetrate through collision geometry. This commit adds planar truncation (mode 1) to properly constrain displacements. Changes: - Add apply_planar_truncation_parallel_by_collision kernel (mode 1 only) - Add helper functions: segment_plane_intersects, robust_edge_pair_normal, create_vertex_triangle_division_plane_closest_pt, create_edge_edge_division_plane_closest_pt, planar_truncation_t - Add apply_truncation_ts kernel to apply truncation factors - Add particle_displacements and truncation_ts buffers to solver - Add apply_planar_truncation() method to orchestrate truncation - Modify solve_particle_iteration to output to displacements buffer - Apply truncation after color groups solve, before position update Handles both paths correctly: - handle_self_collision=False: Apply displacements without truncation - handle_self_collision=True: Compute and apply planar truncation Fixed bug: When self-contact disabled, use particle_q_in instead of pos_prev_collision_detection (which is never updated in that path) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Consolidate forward_step kernel to remove particle_world parameter - Use single gravity array instead of per-world gravity - Add displacements_out parameter for explicit displacement tracking - Remove redundant forward_step_penetration_free kernel - Update solver initialization logic - Always use unified forward_step kernel regardless of contact mode - Move penetration-free truncation to separate apply_penetration_free_truncation method - Simplify initialize_particles by removing conditional branching - Update finalize_particles signature to include state_in parameter - Add builder helper for empty array handling - Introduce _to_wp_array helper that returns None for empty arrays - Update spring, triangle, edge, and tetrahedra array creation to use helper - Prevents creation of empty warp arrays where not needed
- Added new kernels for handling particle collisions, including `forward_step_penetration_free` for penetration-free integration and `accumulate_contact_force_and_hessian` for improved contact force calculations. - Refactored existing kernels to streamline collision detection and response, ensuring better performance and accuracy in particle interactions. - Updated the `SolverVBD` class to incorporate new collision handling logic, including adjustments to the conservative bounds and collision detection mechanisms. - Enhanced the handling of self-contact and body-particle interactions, ensuring robust force accumulation and hessian calculations. - Introduced new utility functions for edge and triangle collision detection, improving the overall collision response system. - Adjusted parameters for conservative bound relaxation to enhance stability during simulations.
- Removed deprecated kernels: `forward_step_penetration_free`, `solve_trimesh_no_self_contact`, and related functions from `particle_vbd_kernels.py`. - Updated `solver_vbd.py` to reflect these changes by cleaning up imports and ensuring only necessary kernels are included. - This refactor simplifies the codebase and prepares for future enhancements in particle collision handling.
- Call collision_detection_penetration_free unconditionally in initialize_particles - This ensures pos_prev_collision_detection is properly set for both self-contact enabled/disabled paths - Fixes explosion issue when particle_enable_self_contact=False - Remove commented-out tile-based self-contact accumulation code - Remove unused resize_collision_buffers method - Remove trailing whitespace and newlines
- Added particle_enable_self_contact, particle_self_contact_radius, and particle_self_contact_margin to the SolverVBD initialization in example_cloth_hanging.py.
… body methods - Updated initialize_rigid_bodies and initialize_particles methods to accept state_out as a parameter for better state management. - Adjusted finalize_particles to use state_out instead of state_in, ensuring consistency in particle state updates. - Modified collision detection and force calculations to reference state_out, improving the accuracy of the simulation. - Cleaned up redundant code and comments related to state handling.
- Updated the soft body simulation to utilize a tetrahedral grid instead of a pyramid mesh. - Adjusted parameters for the soft grid, including dimensions and cell size. - Enhanced the simulation by fixing the left side of the grid and modifying damping settings. - Updated particle state testing to reflect the new grid positioning.
…ssian calculations - Introduced a new function to evaluate volumetric neo-Hookean force and hessian, incorporating damping effects. - Refactored force and hessian assembly logic to streamline calculations based on vertex orders. - Updated particle state handling to account for inactive particles with zero mass. - Removed unused functions and cleaned up imports for better code organization.
…olor group assignment in ModelBuilder Corrected the angular speed parameter in example_rolling_cloth.py to use a positive value, ensuring proper rotation direction. Additionally, updated the particle color group assignment in ModelBuilder to reference self.particle_count for improved clarity and consistency.
There was a problem hiding this comment.
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)
5993-6012:⚠️ Potential issue | 🟡 MinorHandle NumPy 0‑D arrays as scalars during custom-attribute broadcasting.
Current logic treats 0‑D arrays as sequences and will raise onlen(value). Treat scalar arrays (and NumPy scalar types) as scalars and broadcast them.🔧 Proposed fix
- is_array = isinstance(value, np.ndarray) - is_sequence = isinstance(value, Sequence) and not isinstance(value, (str, bytes)) + is_array = isinstance(value, np.ndarray) + is_numpy_scalar = isinstance(value, np.generic) + if is_array and value.ndim == 0: + broadcast_custom_attrs[key] = [value.item()] * num_particles + continue + if is_numpy_scalar: + broadcast_custom_attrs[key] = [value.item()] * num_particles + continue + is_sequence = isinstance(value, Sequence) and not isinstance(value, (str, bytes))Based on learnings: “ModelBuilder.add_particle_grid custom attribute broadcasting should treat NumPy 0‑D arrays (and NumPy scalar types) as scalars and broadcast them per particle. Prefer checking ndarray.ndim != 0 for sequence handling and using .item() for scalar-like arrays.”
🤖 Fix all issues with AI agents
In `@newton/examples/softbody/example_softbody_hanging.py`:
- Around line 106-112: The simulate() method currently calls
self.model.collide(...) inside its per-substep loop causing collide to run
multiple times during a single CUDA graph capture; move the collide() invocation
so contacts are computed once per frame before the substep loop (i.e., call
self.model.collide(...) once at the start of simulate() and then run the
existing substep integration/advance code), leaving capture() unchanged; refer
to the simulate() method and self.model.collide to locate and update the code.
🧹 Nitpick comments (4)
newton/examples/multiphysics/example_poker_cards_stacking.py (1)
252-258: CPU↔GPU round-trip and fresh allocation every substep is avoidable.
body_q.numpy()→ modify →wp.array(body_q, ...)runs 20× per frame, each time allocating a new Warp array. For a small example this is fine functionally (andcapture()already disables CUDA graphs for this reason), but you can avoid both the allocation and the full-array copy by writing only the sphere's transform via indexed assignment on the existing device array.♻️ Suggested approach
# Animate kinematic sphere (move it toward the cards) self.sphere_current_x += self.sphere_velocity_x * self.sim_dt - body_q = self.state_0.body_q.numpy() - # Update sphere position (body_q stores transforms as 7 floats: px, py, pz, qx, qy, qz, qw) - body_q[self.sphere_body_index][0] = self.sphere_current_x - body_q[self.sphere_body_index][1] = 0.0 - body_q[self.sphere_body_index][2] = self.sphere_height - self.state_0.body_q = wp.array(body_q, dtype=wp.transform) + # Update only the sphere transform in-place + self.state_0.body_q.numpy()[self.sphere_body_index] = ( + self.sphere_current_x, 0.0, self.sphere_height, 0.0, 0.0, 0.0, 1.0 + )If in-place numpy writeback isn't supported by Warp arrays in this context, a tiny Warp kernel that writes a single
wp.transformwould also eliminate the round-trip.newton/_src/solvers/vbd/solver_vbd.py (1)
1254-1267: Redundantmodel = self.modelassignment.
modelis assigned on line 1254 and then again on line 1267. The second assignment is unnecessary.Suggested fix
self.pos_prev_collision_detection.assign(state_in.particle_q) self.particle_displacements.zero_() - model = self.model - wp.launch(newton/examples/cloth/example_rolling_cloth.py (2)
354-358: Prefer using model particle count instead oflen(builder.particle_q)afterfinalize().Accessing
builder.particle_qafterfinalize()couples to ModelBuilder internals. Use the known particle counts instead.Suggested fix
flags = self.model.particle_flags.numpy() - for id in range(self.num_cloth_verts, len(builder.particle_q)): - flags[id] = flags[id] & ~ParticleFlags.ACTIVE + total_particles = self.num_cloth_verts + self.num_cyl1_verts + self.num_cyl2_verts + for id in range(self.num_cloth_verts, total_particles): + flags[id] = flags[id] & ~ParticleFlags.ACTIVE
390-394: Repeated.numpy()calls onfixed_point_indicesinside a loop.
self.fixed_point_indices.numpy()is called on every iteration, transferring data from device to host each time. Cache the numpy array before the loop.Suggested fix
state_positions = self.state_0.particle_q.numpy() - for idx in range(len(self.fixed_point_indices.numpy())): - state_positions[self.fixed_point_indices.numpy()[idx]][0] = left_x - state_positions[self.fixed_point_indices.numpy()[idx]][2] = self.cyl2_center[1] + fixed_indices_np = self.fixed_point_indices.numpy() + for idx in range(len(fixed_indices_np)): + state_positions[fixed_indices_np[idx]][0] = left_x + state_positions[fixed_indices_np[idx]][2] = self.cyl2_center[1]
There was a problem hiding this comment.
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/sim/builder.py (1)
5993-6013:⚠️ Potential issue | 🟠 MajorHandle NumPy 0‑D arrays and numpy scalars when broadcasting custom attributes.
Passing a NumPy 0‑D array (e.g.,
np.array(5)) or numpy scalar type (e.g.,np.float64(3.14)) tocustom_attributeswill fail because the current code callslen()on these values. For 0‑D arrays,len()raisesTypeError, and numpy scalars are not sequences. Both should be treated as scalars and broadcast to all particles.🛠️ Proposed fix
- is_array = isinstance(value, np.ndarray) - is_sequence = isinstance(value, Sequence) and not isinstance(value, (str, bytes)) - - if is_array or is_sequence: + is_array = isinstance(value, np.ndarray) + if is_array and value.ndim == 0: + # 0-D array -> scalar + broadcast_custom_attrs[key] = [value.item()] * num_particles + continue + if isinstance(value, np.generic): + broadcast_custom_attrs[key] = [value.item()] * num_particles + continue + is_sequence = isinstance(value, Sequence) and not isinstance(value, (str, bytes)) + + if is_array or is_sequence:
🧹 Nitpick comments (6)
newton/examples/multiphysics/example_poker_cards_stacking.py (3)
244-271: Per-substep collision detection deviates from the standard single-collide-per-frame pattern.Other Newton examples compute contacts once before the substep loop. Here it's inside the loop, which is justified by the moving kinematic sphere but costs ~20× more broad-phase work per frame. If performance matters, consider moving the sphere update +
collide()outside the loop (one collision per frame) since the sphere displacement per frame is small.Based on learnings: "computing contacts once per frame and reusing them across all substeps is an intentional design choice" in Newton example code.
286-302: Consider tighteningtest_final()thresholds to catch regressions earlier.The current bounds are very generous for a scene where cards stack on a 20 cm cube:
Check Current threshold Observation max_vel< 0.5 m/s Cards settling after being knocked should be slower bbox_size< 2.0 m Scene fits within ~0.5 m; 2.0 m would mask an explosion z_min> −0.1 m 10 cm below ground is significant penetration Tighter values (e.g.,
max_vel < 0.3,bbox_size < 1.0,z_min > −0.01) would make the test a better regression guard while still allowing variance from the sphere impact.Based on learnings: "Example classes must implement a meaningful
test_final()method that verifies the simulation state is valid after the example completes."
252-258: Per-substepnumpy()↔wp.array()round-trip allocates 20 new arrays per frame.The code can be optimized using
wp.array.assign()to update in-place without allocating new arrays:♻️ Suggested in-place update
body_q = self.state_0.body_q.numpy() # Update sphere position (body_q stores transforms as 7 floats: px, py, pz, qx, qy, qz, qw) body_q[self.sphere_body_index][0] = self.sphere_current_x body_q[self.sphere_body_index][1] = 0.0 body_q[self.sphere_body_index][2] = self.sphere_height - self.state_0.body_q = wp.array(body_q, dtype=wp.transform) + self.state_0.body_q.assign(body_q)This pattern is used throughout the codebase (e.g.,
state.joint_q.assign(),state.particle_q.assign()).newton/_src/solvers/vbd/solver_vbd.py (1)
1254-1267: Duplicatemodel = self.modelassignment.
modelis already assigned at line 1254; the reassignment at line 1267 is redundant.🧹 Proposed fix
- model = self.model - wp.launch( kernel=forward_step,newton/examples/cloth/example_rolling_cloth.py (2)
390-394: Repeated.numpy()calls inside a loop are wasteful.
self.fixed_point_indices.numpy()is called on every iteration. Cache it once.🧹 Proposed fix
state_positions = self.state_0.particle_q.numpy() - for idx in range(len(self.fixed_point_indices.numpy())): - state_positions[self.fixed_point_indices.numpy()[idx]][0] = left_x - state_positions[self.fixed_point_indices.numpy()[idx]][2] = self.cyl2_center[1] + fixed_indices_np = self.fixed_point_indices.numpy() + for idx in range(len(fixed_indices_np)): + state_positions[fixed_indices_np[idx]][0] = left_x + state_positions[fixed_indices_np[idx]][2] = self.cyl2_center[1] self.state_0.particle_q = wp.array(state_positions, dtype=wp.vec3)
354-358: Minor:idshadows the built-in.Using
idas a loop variable shadows Python's built-inid(). Consider renaming toidxorp_id.
There was a problem hiding this comment.
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)
5993-6013:⚠️ Potential issue | 🟡 MinorHandle NumPy 0‑D custom-attribute values as scalars.
len()on 0‑D arrays raises aTypeError, so scalar-like numpy arrays should be broadcast instead of treated as sequences.Based on learnings: In newton/_src/sim/builder.py, ModelBuilder.add_particle_grid custom attribute broadcasting should treat NumPy 0‑D arrays (and NumPy scalar types) as scalars and broadcast them per particle. Prefer checking ndarray.ndim != 0 for sequence handling and using .item() for scalar-like arrays.🛠️ Suggested fix
- if is_array or is_sequence: + if is_array and value.ndim == 0: + broadcast_custom_attrs[key] = [value.item()] * num_particles + elif is_array or is_sequence: # Value is already a sequence/array - validate length if len(value) != num_particles: raise ValueError( f"Custom attribute '{key}' has {len(value)} values but {num_particles} particles in grid" ) broadcast_custom_attrs[key] = list(value) if is_array else value
🤖 Fix all issues with AI agents
In `@newton/examples/softbody/example_softbody_hanging.py`:
- Line 23: Update the top-of-file command in example_softbody_hanging.py to
match the project's example-run convention: replace the current "# Command:
python -m newton.examples softbody_hanging" with "# Command: uv run -m
newton.examples softbody_hanging"; ensure the module exposes the Example class
(Example) as other examples do and that README.md is updated to register this
example with the same "uv run -m newton.examples softbody_hanging" invocation so
documentation and usage are consistent.
🧹 Nitpick comments (4)
newton/examples/cloth/example_rolling_cloth.py (2)
84-91: Incomplete docstring — most parameters are undocumented.The docstring only documents
target_x,target_y, andextension_segments, whilelength,width,nu,nv,inner_radius, andthicknessare omitted. As per coding guidelines, Google-style docstrings should document all parameters.
390-394: Repeated.numpy()transfers in a loop — extract once.
self.fixed_point_indices.numpy()is called three times per iteration (once inlen(), twice in the body). Each call triggers a device-to-host transfer. Extract once before the loop.Proposed fix
- state_positions = self.state_0.particle_q.numpy() - for idx in range(len(self.fixed_point_indices.numpy())): - state_positions[self.fixed_point_indices.numpy()[idx]][0] = left_x - state_positions[self.fixed_point_indices.numpy()[idx]][2] = self.cyl2_center[1] - self.state_0.particle_q = wp.array(state_positions, dtype=wp.vec3) + fixed_np = self.fixed_point_indices.numpy() + state_positions = self.state_0.particle_q.numpy() + for idx in fixed_np: + state_positions[idx][0] = left_x + state_positions[idx][2] = self.cyl2_center[1] + self.state_0.particle_q = wp.array(state_positions, dtype=wp.vec3)newton/_src/solvers/vbd/solver_vbd.py (1)
1252-1268: Redundantmodel = self.modelreassignment on Line 1267.
modelis already assigned on Line 1254. The second assignment on Line 1267 is dead code.🧹 Suggested removal
else: self.pos_prev_collision_detection.assign(state_in.particle_q) self.particle_displacements.zero_() - model = self.model - wp.launch(newton/examples/softbody/example_softbody_hanging.py (1)
135-145: Prefix unused lambda parameterqdwith underscore to silence lint.The
qdparameter is unused in the bounds-check lambda. Ruff flags this as ARG005.🧹 Suggested fix
newton.examples.test_particle_state( self.state_0, "particles are within a reasonable volume", - lambda q, qd: newton.utils.vec_inside_limits(q, p_lower, p_upper), + lambda q, _qd: newton.utils.vec_inside_limits(q, p_lower, p_upper), )
There was a problem hiding this comment.
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)
5993-6012:⚠️ Potential issue | 🟠 MajorHandle NumPy 0‑D arrays as scalars when broadcasting custom attributes.
0-D NumPy arrays pass the
isinstance(value, np.ndarray)check but fail whenlen(value)is called, raisingTypeError: len() of unsized object. Detect 0-D arrays by checkingndim == 0, extract the scalar using.item(), and broadcast to all particles.Proposed fix
is_array = isinstance(value, np.ndarray) + if is_array and value.ndim == 0: + # Scalar-like ndarray: broadcast + scalar_value = value.item() + broadcast_custom_attrs[key] = [scalar_value] * num_particles + continue is_sequence = isinstance(value, Sequence) and not isinstance(value, (str, bytes)) if is_array or is_sequence:
🤖 Fix all issues with AI agents
In `@newton/examples/softbody/example_softbody_hanging.py`:
- Around line 141-145: The lambda passed to newton.examples.test_particle_state
is defining an unused parameter qd which triggers ARG005; update the lambda
signature from "lambda q, qd: newton.utils.vec_inside_limits(q, p_lower,
p_upper)" to use a silent unused name (e.g., "lambda q, _qd:
newton.utils.vec_inside_limits(q, p_lower, p_upper)") so the unused argument is
ignored by linters while preserving behavior.
🧹 Nitpick comments (2)
newton/_src/solvers/vbd/solver_vbd.py (1)
846-846: Add a Google‑style docstring forcompute_particle_force_element_adjacency.This is a public method (no leading underscore) but lacks a docstring describing inputs/returns. Please add a concise Google‑style docstring.
As per coding guidelines: “Use Google-style docstrings with clear, concise explanations of what the function does, its parameters, and return value.”
newton/examples/cloth/example_rolling_cloth.py (1)
73-178: Upgrade helper docstrings to Google style.
rolled_cloth_meshandcylinder_meshdocstrings don’t follow the project’s Google‑style requirement. Please addArgs:andReturns:sections.As per coding guidelines: “Use Google-style docstrings with clear, concise explanations of what the function does, its parameters, and return value.”
Increased the number of iterations from 10 to 12 to enhance simulation accuracy. Adjusted the soft contact stiffness from 2.0e5 to 5.0e5 for improved collision response in the cloth simulation.
…example Introduced a new kernel to increment simulation time per substep, enhancing compatibility with CUDA graphs. Updated the rotation logic to utilize a time array instead of a float, ensuring accurate time tracking during the simulation process.
Updated the forward_step function in particle_vbd_kernels.py to initialize displacements_out for inactive particles. This change ensures that displacements are correctly set to zero when the particle is not active or has zero mass, improving the accuracy of the simulation output.
Adjusted edge damping from 0.0 to 0.1 and modified particle self-contact radius from 0.40 to 0.3 to enhance simulation stability and accuracy in the rolling cloth example.
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@newton/_src/solvers/vbd/particle_vbd_kernels.py`:
- Line 2862: Fix the typo in the inline comment that reads "# dont forget to do
the final truncation based on the maximum displament allowance!" by replacing
"displament" with "displacement" so it reads "maximum displacement allowance";
locate the comment in newton/_src/solvers/vbd/particle_vbd_kernels.py (the
inline comment string is the unique identifier) and also correct "dont" to
"don't" or "do not" if you prefer consistent style.
- Around line 2506-2507: The degenerate (vertex-on-triangle) branch in
particle_vbd_kernels.py currently returns is_dummy = (False, False, False,
False); change this so that when wp.length(n_hat) < 1e-12 the function returns
an all-True is_dummy vector to signal skipping truncation. Concretely, in the if
wp.length(n_hat) < 1e-12 branch update the returned wp.vector(...) call to
produce all True (e.g., wp.vector(True, True, True, True, length=4,
dtype=wp.bool)) while keeping the returned normal (wp.vec3(0.0)) and d = v
unchanged; this ensures callers like planar_truncation_t and callers of the
is_dummy flag skip truncation for the degenerate case.
- Around line 3248-3262: The fmt directive was never re-enabled because the line
currently reads "# # fmt: on" — change that to a single "# fmt: on" to close the
earlier "# fmt: off"; update the comment after the wp.printf block (near the if
wp.static(...) and before the h/h_inv logic that uses particle_hessians,
particle_forces, particle_displacements, h, and f) so the formatter applies to
the remainder of the kernel.
- Around line 386-392: The code computes cof = J * wp.transpose(F_inv) but calls
wp.inverse(F) unguarded, producing NaN/Inf when J ≈ 0; fix by guarding the
inverse: check abs(J) > 1e-8 before calling wp.inverse(F) and only compute F_inv
and cof that way when safe, otherwise compute the adjugate/cofactor matrix by a
fallback safe component-wise formula (or reuse the existing
compute_cofactor_derivative-style calculation) and assign cof = adjugate; ensure
alpha computation using lmbd_safe remains unchanged and reference symbols F, J,
wp.inverse, F_inv, cof, and compute_cofactor_derivative in your change.
🧹 Nitpick comments (6)
newton/examples/cloth/example_rolling_cloth.py (4)
396-401: Avoid repeated.numpy()round-trips in a loop.
self.fixed_point_indices.numpy()is called three times per loop iteration, each triggering a device-to-host transfer. Cache it once before the loop.Proposed fix
- state_positions = self.state_0.particle_q.numpy() - for idx in range(len(self.fixed_point_indices.numpy())): - state_positions[self.fixed_point_indices.numpy()[idx]][0] = left_x - state_positions[self.fixed_point_indices.numpy()[idx]][2] = self.cyl2_center[1] - self.state_0.particle_q = wp.array(state_positions, dtype=wp.vec3) + fixed_indices_np = self.fixed_point_indices.numpy() + state_positions = self.state_0.particle_q.numpy() + for idx in range(len(fixed_indices_np)): + state_positions[fixed_indices_np[idx]][0] = left_x + state_positions[fixed_indices_np[idx]][2] = self.cyl2_center[1] + self.state_0.particle_q = wp.array(state_positions, dtype=wp.vec3)
513-537: Consider adding a NaN/Inf check intest_final.The test validates unrolling progress and bbox size, but doesn't guard against NaN/Inf in particle positions, which is a common failure mode in physics simulations.
Proposed addition
def test_final(self): """Test that cloth has unrolled from cylinder 1 to cylinder 2.""" # Get cloth particle positions (exclude cylinder particles) particle_q = self.state_0.particle_q.numpy() cloth_q = particle_q[: self.num_cloth_verts] + # Ensure no NaN or Inf values + assert np.all(np.isfinite(cloth_q)), "Cloth positions contain NaN or Inf values" + # Calculate center of mass
503-511: GPU allocation every frame inrender().
wp.array(scaled_positions, dtype=wp.vec3)allocates a new GPU buffer every frame. For an example this is tolerable, but if render frequency is high it could be a bottleneck. Consider pre-allocatingviz_state.particle_qand usingwp.copyor a kernel to scale in-place.
362-364: Avoid shadowing Python built-inid.Proposed fix
- for id in range(self.num_cloth_verts, len(builder.particle_q)): - flags[id] = flags[id] & ~ParticleFlags.ACTIVE + for idx in range(self.num_cloth_verts, len(builder.particle_q)): + flags[idx] = flags[idx] & ~ParticleFlags.ACTIVEnewton/_src/solvers/vbd/particle_vbd_kernels.py (2)
254-343: Remove the commented-out implementation.This ~90-line block is an earlier version of
evaluate_volumetric_neo_hookean_force_and_hessianthat duplicates the active implementation below. It should be removed to reduce noise.
238-251: Remove unuseddamp_force_and_hessianfunction.This function is not called anywhere in the codebase. The damping logic is inlined directly in
evaluate_volumetric_neo_hookean_force_and_hessian. Removing it will reduce dead code.
Modified command instructions in example_rolling_cloth.py and example_softbody_hanging.py for consistency with the new execution method. Adjusted the number of frames in the test for the rolling cloth example from 800 to 200 to reflect the updated simulation duration.
…force evaluation Added a new function to compute the cofactor (adjugate) matrix directly, enhancing numerical stability when the determinant of F is close to zero. Updated the volumetric Neo-Hookean force evaluation to utilize this new function instead of the inverse, improving accuracy. Also, corrected comments for clarity and consistency.
There was a problem hiding this comment.
Actionable comments posted: 3
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)
5993-6013:⚠️ Potential issue | 🟠 MajorHandle NumPy 0‑D/scalar custom attributes during broadcasting.
np.ndarrayvalues are treated as sequences andlen()is called, which raisesTypeErrorfor 0‑D arrays (and misclassifies NumPy scalar types). Treat 0‑D arrays/scalars as scalars and broadcast with.item().🛠️ Proposed fix
- for key, value in custom_attributes.items(): - # Check if value is a sequence (but not string/bytes) or numpy array - is_array = isinstance(value, np.ndarray) - is_sequence = isinstance(value, Sequence) and not isinstance(value, (str, bytes)) - - if is_array or is_sequence: - # Value is already a sequence/array - validate length - if len(value) != num_particles: - raise ValueError( - f"Custom attribute '{key}' has {len(value)} values but {num_particles} particles in grid" - ) - broadcast_custom_attrs[key] = list(value) if is_array else value - else: - # Scalar value - broadcast to all particles - broadcast_custom_attrs[key] = [value] * num_particles + for key, value in custom_attributes.items(): + # NumPy scalar types -> treat as scalar + if isinstance(value, np.generic): + value = value.item() + + is_array = isinstance(value, np.ndarray) + is_sequence = isinstance(value, Sequence) and not isinstance(value, (str, bytes)) + + if is_array: + if value.ndim == 0: + broadcast_custom_attrs[key] = [value.item()] * num_particles + continue + value = value.tolist() + + if is_sequence: + if len(value) != num_particles: + raise ValueError( + f"Custom attribute '{key}' has {len(value)} values but {num_particles} particles in grid" + ) + broadcast_custom_attrs[key] = value + else: + broadcast_custom_attrs[key] = [value] * num_particlesBased on learnings: In newton/_src/sim/builder.py, ModelBuilder.add_particle_grid custom attribute broadcasting should treat NumPy 0‑D arrays (and NumPy scalar types) as scalars and broadcast them per particle. Prefer checking ndarray.ndim != 0 for sequence handling and using .item() for scalar-like arrays.
🤖 Fix all issues with AI agents
In `@newton/_src/sim/builder.py`:
- Around line 6934-6973: The _validate_structure block is using non-existent
attributes self.eq_type, self.eq_body1, self.eq_body2, self.eq_joint1,
self.eq_joint2; replace those with the actual model fields named
equality_constraint_type, equality_constraint_body1, equality_constraint_body2,
equality_constraint_joint1, equality_constraint_joint2 used elsewhere in the
builder so the numpy arrays and the range checks operate on the correct arrays
(e.g., replace eq_type -> equality_constraint_type, eq_body1 ->
equality_constraint_body1, eq_body2 -> equality_constraint_body2, eq_joint1 ->
equality_constraint_joint1, eq_joint2 -> equality_constraint_joint2 in the
validation logic).
- Around line 6975-6982: The validation currently calls undefined helpers
joint_linear_dim and joint_angular_dim causing a NameError; replace that logic
by using the existing DOF tracking (sum of self.joint_dof_dim or the
already-computed DOF variable) to compute total_joint_q and then compare
len(self.joint_limit_lower) to that value; update the expression that produces
total_joint_q (and any error message) to reference the chosen DOF source (e.g.,
sum(self.joint_dof_dim)) and keep the raised ValueError using joint_limit_lower
and the computed total_joint_q.
In `@newton/tests/test_examples.py`:
- Around line 699-723: Create a new test registration class named
TestSoftbodyExamples and call add_example_test to register the
softbody.example_softbody_hanging example; specifically add a
TestSoftbodyExamples class (empty) and an add_example_test invocation with
name="softbody.example_softbody_hanging", devices=cuda_test_devices, include an
appropriate test_options dict (e.g., {"num-frames": 200}) and use_viewer=True so
the example's test_final() is exercised; reference the existing add_example_test
helper, the TestSoftbodyExamples identifier, and cuda_test_devices when adding
the entry.
🧹 Nitpick comments (3)
newton/examples/cloth/example_rolling_cloth.py (3)
435-437: CUDA graph captures the spin-duration branch unconditionally — rotation never stops under graph replay.The comment on lines 435-436 acknowledges this, but it means once captured,
rotate_cylinderruns every substep regardless of elapsed time. This is fine for the current test (200 frames ≈ 3.3s << 20sspin_duration), but if anyone runs the example longer, rotation won't stop.A more robust approach would be to gate the rotation inside the kernel using the
timearray, or rebuild the graph afterspin_durationelapses. Not blocking, just noting for future robustness.
503-511:wp.array(...)allocation every frame inrender()is expensive on GPU.Line 507 creates a new
wp.arrayeach frame. Consider pre-allocatingself.viz_state.particle_qonce and usingwp.copyor an in-place kernel to scale positions, avoiding repeated GPU allocations.💡 Sketch
+@wp.kernel +def scale_positions(src: wp.array(dtype=wp.vec3), dst: wp.array(dtype=wp.vec3), scale: float): + i = wp.tid() + dst[i] = src[i] * scale def render(self): - positions = self.state_0.particle_q.numpy() - scaled_positions = positions * self.viz_scale - self.viz_state.particle_q = wp.array(scaled_positions, dtype=wp.vec3) + wp.launch(scale_positions, dim=self.state_0.particle_q.shape[0], + inputs=[self.state_0.particle_q, self.viz_state.particle_q, self.viz_scale])
396-401: Repeated.numpy()calls inside loop are inefficient.
self.fixed_point_indices.numpy()is called 3 times per loop iteration (once forlen, twice for index access). Cache it before the loop.💡 Suggested fix
- state_positions = self.state_0.particle_q.numpy() - for idx in range(len(self.fixed_point_indices.numpy())): - state_positions[self.fixed_point_indices.numpy()[idx]][0] = left_x - state_positions[self.fixed_point_indices.numpy()[idx]][2] = self.cyl2_center[1] - self.state_0.particle_q = wp.array(state_positions, dtype=wp.vec3) + state_positions = self.state_0.particle_q.numpy() + fixed_indices_np = self.fixed_point_indices.numpy() + for idx in range(len(fixed_indices_np)): + state_positions[fixed_indices_np[idx]][0] = left_x + state_positions[fixed_indices_np[idx]][2] = self.cyl2_center[1] + self.state_0.particle_q = wp.array(state_positions, dtype=wp.vec3)
Reset builder.py to upstream/main and selectively reapplied soft body features: - add_soft_grid/add_soft_mesh: Add surface mesh edge parameters (add_surface_mesh_edges, edge_ke, edge_kd, particle_radius) - Change tri_* parameters from float|None to float with 0.0 defaults - Add surface mesh edge generation using MeshAdjacency - Update particle coloring to use construct_particle_graph + color_graph instead of color_trimesh for better tet/tri material handling - Import color_graph and construct_particle_graph functions - Update include_bending parameter documentation Preserved upstream changes: - Validation methods (_validate_structure, validate_joint_ordering) - Voxel computation helper function (compute_voxel_resolution_from_aabb) - Shape AABB caching improvements
Introduce _to_wp_array helper that returns None for empty arrays instead of creating empty warp arrays. This improves memory efficiency and matches the soft body implementation requirements. Updated array creation for: - Springs (indices, rest_length, stiffness, damping, control) - Triangles (indices, poses, activations, materials, areas) - Edges (indices, rest_angle, rest_length, bending_properties) - Tetrahedra (indices, poses, activations, materials)
51123ef to
23087f6
Compare
Introduced a new test class, TestSoftbodyExamples, to facilitate testing of soft body examples. Added a test case for the softbody example "softbody.example_softbody_hanging" with specified test options and viewer usage. This enhances the test coverage for soft body simulations.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@newton/examples/softbody/example_softbody_hanging.py`:
- Around line 33-77: The inline comment describing grid spacing is incorrect:
update the comment that currently says "Space between grids along Z-axis" to
reflect that spacing is applied along the Y-axis (variable spacing and y_offset
used), since add_soft_grid positions use pos=wp.vec3(0.0, 1.0 + y_offset, 1.0);
change the comment near the declaration of spacing/y_offset to "Space between
grids along Y-axis" to avoid confusion when inspecting Example and add_soft_grid
usage.
🧹 Nitpick comments (1)
newton/examples/softbody/example_softbody_hanging.py (1)
135-147: Grid size comment is slightly inaccurate.Line 138 states grids are "roughly 1.2 x 0.4 x 0.4" but the actual extent is
(dim - 1) * cell = 1.1 × 0.3 × 0.3. The bounds intest_finalare generous enough that this doesn't affect correctness, but the comment could be tightened.📝 Suggested fix
- # 4 grids, each roughly 1.2 x 0.4 x 0.4 in size, positioned along Y-axis + # 4 grids, each roughly 1.1 x 0.3 x 0.3 in size, positioned along Y-axis
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@newton/examples/softbody/example_softbody_hanging.py`:
- Around line 1-2: Update the SPDX header year from 2025 to 2026 in the new
file's top comments: change the lines containing "SPDX-FileCopyrightText:
Copyright (c) 2025 The Newton Developers" and ensure the SPDX-License-Identifier
remains unchanged; this updates the copyright year for the new file
(example_softbody_hanging.py).
🧹 Nitpick comments (1)
newton/examples/softbody/example_softbody_hanging.py (1)
135-147: Minor inaccuracy in comment: grid dimensions are 1.1 × 0.3 × 0.3, not 1.2 × 0.4 × 0.4.With
dim=12,4,4andcell_size=0.1, physical size is(dim-1)*cell = 1.1 × 0.3 × 0.3.- # 4 grids, each roughly 1.2 x 0.4 x 0.4 in size, positioned along Y-axis + # 4 grids, each roughly 1.1 x 0.3 x 0.3 in size, positioned along Y-axis
There was a problem hiding this comment.
Thanks, looks great! @jumyungc can you please follow up separately with GitHub issues if there are any remaining concerns?
Let's get this merged now.
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* [Warp Raytrace] Added device parameter (newton-physics#1544) * [Warp Raytrace] Added device parameter to previously overlooked call (newton-physics#1545) * SolverMuJoCo: Fix tolerance clamping in update_solver_options_kernel (newton-physics#1546) * Change default shape_ke to align with MuJoCo, parse geom solref from MJCF for contact stiffness/damping (newton-physics#1491) Signed-off-by: Alain Denzler <adenzler@nvidia.com> * Fix log_shapes broadcasting for length-1 warp arrays (newton-physics#1550) * Fix XPBD restitution particle index (newton-physics#1557) * Out-of-Bound memory read in example_diffsim_bear newton-physics#1386 (newton-physics#1533) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Add versioned documentation deployment to GitHub Pages (newton-physics#1560) * Fix broken documentation links after versioned docs deployment (newton-physics#1566) * VBD New Features (newton-physics#1479) Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> * Add banners to membership verification workflow steps (newton-physics#1569) * Support cable junctions (newton-physics#1519) Signed-off-by: JC <jumyungc@nvidia.com> * Rename parameter I to inertia newton-physics#1543 (newton-physics#1551) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Fix example_robot_anymal_c_walk.py (newton-physics#1574) * Change everywhere linesearch to iterative (newton-physics#1573) * Remove standard collision pipeline (newton-physics#1538) * USD Plumbing MJC solver attributes through resolver and custom attribute framework (newton-physics#1463) Signed-off-by: Milad Rakhsha <mrakhsha@nvidia.com> Signed-off-by: Milad-Rakhsha-NV <167464435+Milad-Rakhsha-NV@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: adenzler-nvidia <adenzler@nvidia.com> * Fix child shape filtering (newton-physics#1559) * Fix ViewerRerun ignoring hidden parameter in log_mesh and log_instances (newton-physics#1555) * Make NxN and SAP broad phase respect filtered pairs (newton-physics#1554) * Add --quiet flag to examples to suppress Warp messages (newton-physics#1585) * Defer resolution of MESH_MAXHULLVERT default in importers (newton-physics#1587) * Fix TypeError when finalizing SDF geometry with device kwarg (newton-physics#1586) * Make MESH_MAXHULLVERT a static class attribute Mesh.MAX_HULL_VERTICES. (newton-physics#1598) * Significant non-determinism in unified collision pipeline for anymal_c_walking example newton-physics#1505 (newton-physics#1588) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Add test for non-contiguous case (newton-physics#1549) * Fix nightly Warp CI to resolve pre-release builds (newton-physics#1606) * Verify default class and value handling (newton-physics#1556) * SolverMuJoCo: Expand geom_margin to avoid OOB read with heterogeneous worlds (newton-physics#1607) * Fix bug in control clear method (newton-physics#1602) * Enable Use of Newton IK in Lab newton-physics#662 (newton-physics#1539) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Fix import of non-articulated joints (newton-physics#1535) * Deduplicate _process_joint_custom_attributes frequency handling (newton-physics#1584) * Add CI check for stale API docs and fix local build warnings (newton-physics#1570) * Update Pillow 12.0.0 to 12.1.1 (newton-physics#1612) * Prepare handling of mimic constraints in Newton (newton-physics#1523) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Support floating, base_joint and parent_body arguments for importers (newton-physics#1498) * Fix contact buffer memory overestimation (newton-physics#1614) * Configure banned-module-level-imports for ruff (newton-physics#1583) * Explicit `Contacts` instantiation with `Model.contacts()` and `CollisionPipeline.contacts()` (newton-physics#1445) * Fix the quadruped benchmark regression (newton-physics#1615) * Change default ignore_inertial_definitions from True to False (newton-physics#1537) * Finalize the Recording API (newton-physics#1600) * SolverMuJoCo: Fix ccd_iterations default (newton-physics#1631) * update gitignore to ignore Claude Code sandbox files (newton-physics#1628) * Add mimic joint support to SolverMuJoCo (newton-physics#1627) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Add --no-cache-clear flag to test runner (newton-physics#1629) * Update MuJoCo and MuJoCo Warp to 3.5.0 release (newton-physics#1633) * Improve inertia parsing from USD (newton-physics#1605) Signed-off-by: Eric Heiden <eheiden@nvidia.com> Signed-off-by: Eric Heiden <eric-heiden@outlook.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * Remove standalone .typos.toml in favor of pyproject.toml config (newton-physics#1642) * Heightfield support newton-physics#1189 (newton-physics#1547) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Example_robot_policy: Replace ValueError with clean error for missing PhysX policy (newton-physics#1636) Co-authored-by: Viktor Reutskyy <33062116+vreutskyy@users.noreply.github.com> * Avoid unnecessary inflation of the contact reduction voxel aabb (newton-physics#1650) * Rename num_worlds to world_count (newton-physics#1634) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Support parsing autolimits from MJCF (newton-physics#1651) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Fix particle-shape restitution ignoring body velocity (newton-physics#1273) (newton-physics#1580) * Add overflow warnings for narrow-phase collision buffers (newton-physics#1643) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Documentation: add units to model/state docstrings (newton-physics#1649) * fix(viewer): add missing JointType.BALL support to contact line kernel (newton-physics#1640) * Make terrain mesh visual-only in anymal C walking example (newton-physics#1660) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Fix initialization of collider state in MPM finite difference mode (newton-physics#1652) * docs: document ModelBuilder.default_shape_cfg (newton-physics#1662) * Finalize the collision API (newton-physics#1581) * Remove hardcoded subnet ID from AWS workflow (newton-physics#1664) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Attempt to fix AWS config (newton-physics#1666) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Update AWS workflows to g7e.2xlarge with multi-AZ failover (newton-physics#1669) * fix(viewer-usd): disambiguate log_points colors for N=3 warp arrays (newton-physics#1661) * Viewer gl optimizations (newton-physics#1656) Signed-off-by: Miles Macklin <mmacklin@nvidia.com> Signed-off-by: Eric Heiden <eheiden@nvidia.com> Co-authored-by: Eric Heiden <eheiden@nvidia.com> * docs: add articulation workflow guidance and regression check (newton-physics#1663) * fix(examples): propagate IK solution to model state in Franka example (newton-physics#1637) * fix(deps,docs): bump nbconvert to 7.17.0 and fix ArticulationView doctest (newton-physics#1670) * Cleanup and improve some example (newton-physics#1625) Signed-off-by: adenzler-nvidia <adenzler@nvidia.com> Co-authored-by: adenzler-nvidia <adenzler@nvidia.com> * Handle zero-mass bodies and flip ensure_nonstatic_links default (newton-physics#1635) * Additional testing for ArticulationView (newton-physics#1527) Co-authored-by: Eric Heiden <eheiden@nvidia.com> * Update warp-lang nightly to 1.12.0.dev20260217 (newton-physics#1677) * Change default friction coefficients to match MuJoCo (newton-physics#1681) * Refactor mesh creation functions (newton-physics#1654) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Parse joint frictionloss from MJCF (newton-physics#1680) * Fix free joint body_pos and add ref/qpos0 support for MuJoCo solver (newton-physics#1645) * Fix root shapes in ArticulationView with fixed base (newton-physics#1639) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> Co-authored-by: Eric Heiden <eric-heiden@outlook.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Use model collision methods and remove `create_collision_pipeline` from examples (newton-physics#1648) Co-authored-by: nvtw <110816143+nvtw@users.noreply.github.com> * Fix XPBD apply_joint_forces ignoring child joint transform (newton-physics#1582) * Adjust SDF API (newton-physics#1644) Co-authored-by: Eric Heiden <eheiden@nvidia.com> * Optimize test suite runtime (~18% faster) (newton-physics#1689) * Remove ensure_nonstatic_links option from importers (newton-physics#1682) Signed-off-by: adenzler-nvidia <adenzler@nvidia.com> * SolverMuJoCo: Add geom_margin support, align thickness default with MuJoCo and schemas (newton-physics#1653) * refactor: privatize non-public solver internals (newton-physics#1683) * Fix option parsing with multiple <option> elements from includes (newton-physics#1692) * Bump warp-lang nightly and newton-usd-schemas (newton-physics#1693) * Get rid of tkinter dependency (newton-physics#1676) * Fix SDF example contact buffer overflow (newton-physics#1695) * Fix implicit biastype for position/velocity actuator shortcuts (newton-physics#1678) * Fix include processor to respect meshdir/texturedir (newton-physics#1685) * Reduce cold-cache Warp compile time for geometry modules (newton-physics#1618) Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: adenzler-nvidia <adenzler@nvidia.com> * Fix xyzw-to-wxyz quaternion conversion in body inertia kernel (newton-physics#1694) * Rename key to label and add hierarchical labels (newton-physics#1592) (newton-physics#1632) * Expose geometry SDF helpers on public API (newton-physics#1684) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Improve custom frequency handling from USD, parse MuJoCo actuators and tendons (newton-physics#1510) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> Signed-off-by: Eric Heiden <eheiden@nvidia.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Collapse fixed joints with non articulated bodies (newton-physics#1608) * Fix renaming joint_key -> joint_label (newton-physics#1700) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Bump .python-version from 3.11 to 3.12 (newton-physics#1702) * Replace CITATION.md with CITATION.cff (newton-physics#1706) * Respect MJCF contype=conaffinity=0 via collision_group=0 (newton-physics#1703) * Make ViewerUSD reuse existing USD layers for the same output path (newton-physics#1704) Signed-off-by: Eric Heiden <eheiden@nvidia.com> Signed-off-by: Eric Heiden <eric-heiden@outlook.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Remove dead up-axis conversion from MuJoCo solver (newton-physics#1707) * Skip IK cube stacking example test (newton-physics#1713) * Fix global pairs (world=-1) not exported to MuJoCo spec (newton-physics#1705) * Reduce the memory consumption of hydroelastic contacts (newton-physics#1609) * Fix flakiness cube stacking (newton-physics#1714) * Fix collision shapes not toggleable in viewer UI (newton-physics#1715) * Fix softbody examples table layout in README (newton-physics#1716) * Standardize sensor APIs: label matching, keyword args, and update() method naming (newton-physics#1665) * Fix intermittent crash in parallel test runner from Manager proxy race (newton-physics#1721) * Clean up inertia.py function arguments to match Mesh.create_* API (newton-physics#1719) * Reduce default test runner verbosity (newton-physics#1723) * Add menagerie comparison tests for SolverMuJoCo (newton-physics#1720) Signed-off-by: Alain Denzler <adenzler@nvidia.com> Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> Co-authored-by: Viktor Reutskyy <vreutskyy@nvidia.com> Co-authored-by: Viktor Reutskyy <33062116+vreutskyy@users.noreply.github.com> * Add spatial tendon support for MuJoCo solver (newton-physics#1687) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Expose qfrc_actuator from mujoco (newton-physics#1698) * Skip non-MODEL custom attributes in finalize validation (newton-physics#1734) * Resolve inheritrange for position actuators in MJCF parser (newton-physics#1727) * Support dampratio for position/velocity actuator shortcuts (newton-physics#1722) * Limit concurrency to 1 (newton-physics#1736) * Add a helper method for checking applied usd (newton-physics#1731) * Enhance playback URL handling in ViewerViser (newton-physics#1742) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Removed RenderShapeType (newton-physics#1748) * Override only MassAPI attributes that have been authored (newton-physics#1688) * Integration of newton-actuators (newton-physics#1342) Signed-off-by: jvonmuralt <jvonmuralt@nvidia.com> * Fix ArticulationView crash with fixed-joint-only articulations (newton-physics#1726) * Improve retrieval of Jupyter base URL in ViewerViser (newton-physics#1750) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Disable dynamics testing for UR5e and Apollo tests to avoid CI flakiness (newton-physics#1755) * Margin and Gap rename (newton-physics#1732) * Vbd Demos Fixing (newton-physics#1740) * Fix ViewerViser.log_lines method (newton-physics#1764) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Update warp-lang dependency to 1.12.0rc1 (newton-physics#1763) * Fix fromto capsule/cylinder orientation in MJCF parser (newton-physics#1741) * fix: multi-world particle BVH indexing (newton-physics#1641) Co-authored-by: Eric Heiden <eheiden@nvidia.com> * Clean up unused and internal-only kwargs in SolverMuJoCo (newton-physics#1766) * Parsing of the mimic joint and contact gap/margin from newton schemas (newton-physics#1690) Signed-off-by: Milad Rakhsha <mrakhsha@nvidia.com> * API Refactor v2 (newton-physics#1749) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Support explicit geom mass attributes in MJCF (newton-physics#1744) * Bump flask and werkzeug in lockfile for security (newton-physics#1769) Co-authored-by: Cursor <cursoragent@cursor.com> * Split MJCF worldbody root bodies into separate articulations (newton-physics#1754) * Expose VBD rigid contact forces for solver coupling (newton-physics#1745) Signed-off-by: JC <jumyungc@nvidia.com> * Add MJCF ellipsoid geom import and regression test (newton-physics#1772) Co-authored-by: Cursor <cursoragent@cursor.com> * Weld equality constraints parsed from mjcf are given Nan as the default value of torquescale. The correct default should be 1.0 (newton-physics#1760) * Improve picking accuracy and stability (newton-physics#1712) * Franka cloth demo improvement (newton-physics#1765) * Support computing sensing object transforms & API cleanup (newton-physics#1759) * Remove threading workaround (newton-physics#1751) * [Warp Raytrace] Consolidated ray intersect functions, renamed Options to Config (newton-physics#1767) * Improve README example gallery for PyPI compatibility (newton-physics#1776) * Fix issue with mesh in rerun viewer (newton-physics#1768) * Add PhysxMimicJointAPI parsing to USD importer (newton-physics#1735) * Move some math functions to Warp (newton-physics#1717) Signed-off-by: Eric Heiden <eheiden@nvidia.com> Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Add test to ensure MJCF xform argument is relative (newton-physics#1777) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Emit diaginertia instead of fullinertia for diagonal body inertia (newton-physics#1780) * Change default joint armature from 0.01 to 0 (newton-physics#1782) * Fix default kp/kv for position and velocity actuators (newton-physics#1786) * Lock body inertia after explicit MJCF <inertial> element (newton-physics#1784) * Fix for MJCF actuator custom attributes (newton-physics#1783) * Bump version to 0.2.3 Prepare the package metadata for the v0.2.3 release tag. * Fix ViewerRerun rendering of instances from hidden meshes (newton-physics#1788) * API cleanup (newton-physics#1789) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * BODY actuator target name bypasses body name de-duplication in SolverMuJoCo (newton-physics#1729) * Use default density for visual geoms in MJCF import (newton-physics#1781) * Fix GL viewer crash on Wayland (newton-physics#1793) * Make USD xform parameter control absolute articulation placement (newton-physics#1771) * Fix CUDA context corruption in SDF implementation (newton-physics#1792) * Bump mujoco-warp dependency to 3.5.0.2 (newton-physics#1779) * Fix MuJoCo margin/gap conversion (newton-physics#1785) * Bump version to 1.1.0.dev0 (newton-physics#1798) * Missing unittest.main added back to test_import_mjcf.py. Helps with F5 debugging in VS Code. (newton-physics#1796) * Improve H1 example (newton-physics#1801) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Fix ViewerViser.set_camera() (newton-physics#1805) * Rename examples to follow prefix-first naming convention (newton-physics#1802) * Improve MuJoCo actuator domain randomization (newton-physics#1773) * Restore in_cup test in hydro example (newton-physics#1775) * Fix `newton.geometry` imports and change of Mesh maxhullverts global constant * Adapt to having both margin and gap arrays for each geom/shape * Fix for newton.geometry API changes in primitive/narrowphase.py * Fix removal of `BroadPhaseMode` IntEnum and revert to newton-sytle string literals * WIP: Adapt geometry/unified.py to fix breaking changes to `newton.geometry` API * First pass of API adjustments * Patch more gaps (with respect to margin and gap renaming) * GeoType.SDF was removed - reflect that in Kamino * Introduce CoM position offsets w.r.t body frame and operations to convert between body CoM state and generic local body-fixed reference frames. * Add caching of per-entity labels/names/keys in the Model subcontainers * Remove SDF shape wrapper since it's now internal to mesh handling in CD pipelines * Fix USD test assets * Add Newton <--> Kamino joint type conversion operations and per-space default limit constants * Add some cleanup to geometry and unified CD + UTs * Add Newton <--> Kamino shape type conversion operations * Apply new default joint coord limit constants to limits.py * Adapt foubrar model builder and USD asset to produce the same result in sim example * Purge "physical" goems and collapse all into a single group, and purge geometry "layers" * Disable allocation per-joint wrenches by default and make them optional * Make `Model` a dataclass * Separate ModelData* containers into own `core/data.py` module * Fix imports of ModelData * Rename `Model` as `ModelKamino` * Rename `ModelData` as `DataKamino` * Rename `State` as `StateKamino` * Rename `Control` as `ControlKamino` * Rename `Limits` as `LimitsKamino` * Rename `Contacts` as `ContactsKamino` * Rename `ModelBuilder` as `ModelBuilderKamino` * Make imports in test utilities relative * Revise CD meta-data attributes and their computation in GeometryModel and ModelBuilderKamino * Revise primitive CD pipeline * Revise unified CD pipeline * Revise CD front-end interfaces * Fix UTs and relevant utils for interface changes to CD * Change to `wp.DeviceLike` to account for upcoming deprecation of `Devicelike` * Depracate legacy HDF5 data io (will be replaced in the future) * Fix banned imports at module level * Modify USD importer to detect articulations and order geoms and joints similarly to how the Newton `parse_usd` function does. * Add conversion operation from `newton.Model` to `ModelKamino` * Add data, state and control container conversions * Add SolverKamino wrapper that fullfils newton integration interface * Add newton integration examples * Add SolverKamino to newton solver module imports * WIP: fix problem with lambda_j being allocated for only kinematic constraints and failing on array copying * Fix banned git import in benchmark * Rename *Settings to *Config (#213) * Rename SolverKaminoSettings -> SolverKaminoConfig * Rename DualProblemSettings -> DualProblemConfig * Rename CollisionDetectorSettings -> CollisionDetectorConfig * Rename PADMMSettings -> PADMMConfig * Rename ForwardKinematicsSolverSettings -> ForwardKinematicsSolverConfig * Rename SimulatorSettings -> SimulatorConfig * Add check for model compatibility in SolverKamino (#209) * Fix device assignment in sparse CG test on CPU (#216) * Replace Enum-type config attributes with Literal (#215) * Replace warmstart mode config param with literal * Replace contact warmstart mode config param with literal * Replace rotation correction config param with literal * Replace penalty update config param with literal * Replace FK preconditioner option config param with literal * Add post-init checks for dual/PADMM configs * Rename FKPreconditionerOptions to FKPreconditionerType * Remove WorldDescriptor from ModelKamino (#219) * Add geom index offset array to model info * Replace access to world description in model * Remove world descriptor from model * Fix computation of kinematics residual with sparse Jacobian (#220) * Migrates `ModelKaminoSize` to it's own module to avoid circular dependency between core/model.py and core/state.py and rename it as `SizeKamino`. * WIP: Fix SolverKamino wrapper * Fix circular dependency in conversions.py * Fix some broken unit tests and WIP to fix fourbar contact conversions and rendering * Make some conversions @staticmethods instead, because they dont need common class attributes * Fix declaration of custom state attributes and their conversion to/from newton and kamino * WIP: Debug model conversion and newton sim examples * Rename and cleanup start index array of per-world geoms * Model conversion and newton sim examples now work. * Make gravity conversion operation re-usable * Migrates boxes_fourbar builder using newton.ModelBuilder to it's own module to prepare for migration. * Use gravity conversion utility func in SolverKamino * Add reusable joint-parameterization conversion utility * Remove world-descriptor from model converter * Rename helper converter that handles entity-local transforms * Add some cleanup to DR Legs, ANYmal D and basic four-bar examples * Fix module-level imports of additional kamino-specific development dependencies * Fix module-level imports of additional kamino-specific development dependencies * Fix erroneous merge conflict. --------- Signed-off-by: Alain Denzler <adenzler@nvidia.com> Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> Signed-off-by: JC <jumyungc@nvidia.com> Signed-off-by: Milad Rakhsha <mrakhsha@nvidia.com> Signed-off-by: Milad-Rakhsha-NV <167464435+Milad-Rakhsha-NV@users.noreply.github.com> Signed-off-by: Eric Heiden <eric-heiden@outlook.com> Signed-off-by: Eric Heiden <eheiden@nvidia.com> Signed-off-by: Miles Macklin <mmacklin@nvidia.com> Signed-off-by: adenzler-nvidia <adenzler@nvidia.com> Signed-off-by: jvonmuralt <jvonmuralt@nvidia.com> Co-authored-by: Daniela Hase <116915287+daniela-hase@users.noreply.github.com> Co-authored-by: adenzler-nvidia <adenzler@nvidia.com> Co-authored-by: Viktor Reutskyy <33062116+vreutskyy@users.noreply.github.com> Co-authored-by: Eric Shi <97630937+shi-eric@users.noreply.github.com> Co-authored-by: Anka Chen <AnkaChan@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: JC-nvidia <116605903+jumyungc@users.noreply.github.com> Co-authored-by: Kenny Vilella <kvilella@nvidia.com> Co-authored-by: nvtw <110816143+nvtw@users.noreply.github.com> Co-authored-by: Milad-Rakhsha-NV <167464435+Milad-Rakhsha-NV@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Lennart Röstel <65088822+lenroe@users.noreply.github.com> Co-authored-by: Eric Heiden <eheiden@nvidia.com> Co-authored-by: jvonmuralt <jvonmuralt@nvidia.com> Co-authored-by: camevor <camevor@nvidia.com> Co-authored-by: mzamoramora-nvidia <mzamoramora@nvidia.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Alessandro Roncone <alecive87@gmail.com> Co-authored-by: gdaviet <57617656+gdaviet@users.noreply.github.com> Co-authored-by: Miles Macklin <mmacklin@nvidia.com> Co-authored-by: Gordon Yeoman <gyeomannvidia@users.noreply.github.com> Co-authored-by: Lukasz Wawrzyniak <lwawrzyniak@nvidia.com> Co-authored-by: Eric Heiden <eric-heiden@outlook.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Viktor Reutskyy <vreutskyy@nvidia.com> Co-authored-by: Lorenzo Terenzi <lorenzoterenzi96@gmail.com> Co-authored-by: smollerNV <164020096+smollerNV@users.noreply.github.com> Co-authored-by: twidmer <twidmer@nvidia.com> Co-authored-by: Christian Schumacher <christian.schumacher@disney.com> Co-authored-by: Guirec-Maloisel <25688871+Guirec-Maloisel@users.noreply.github.com>
* [Warp Raytrace] Added device parameter (newton-physics#1544) * [Warp Raytrace] Added device parameter to previously overlooked call (newton-physics#1545) * SolverMuJoCo: Fix tolerance clamping in update_solver_options_kernel (newton-physics#1546) * Change default shape_ke to align with MuJoCo, parse geom solref from MJCF for contact stiffness/damping (newton-physics#1491) Signed-off-by: Alain Denzler <adenzler@nvidia.com> * Fix log_shapes broadcasting for length-1 warp arrays (newton-physics#1550) * Fix XPBD restitution particle index (newton-physics#1557) * Out-of-Bound memory read in example_diffsim_bear newton-physics#1386 (newton-physics#1533) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Add versioned documentation deployment to GitHub Pages (newton-physics#1560) * Fix broken documentation links after versioned docs deployment (newton-physics#1566) * VBD New Features (newton-physics#1479) Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> * Add banners to membership verification workflow steps (newton-physics#1569) * Support cable junctions (newton-physics#1519) Signed-off-by: JC <jumyungc@nvidia.com> * Rename parameter I to inertia newton-physics#1543 (newton-physics#1551) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Fix example_robot_anymal_c_walk.py (newton-physics#1574) * Change everywhere linesearch to iterative (newton-physics#1573) * Remove standard collision pipeline (newton-physics#1538) * USD Plumbing MJC solver attributes through resolver and custom attribute framework (newton-physics#1463) Signed-off-by: Milad Rakhsha <mrakhsha@nvidia.com> Signed-off-by: Milad-Rakhsha-NV <167464435+Milad-Rakhsha-NV@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: adenzler-nvidia <adenzler@nvidia.com> * Fix child shape filtering (newton-physics#1559) * Fix ViewerRerun ignoring hidden parameter in log_mesh and log_instances (newton-physics#1555) * Make NxN and SAP broad phase respect filtered pairs (newton-physics#1554) * Add --quiet flag to examples to suppress Warp messages (newton-physics#1585) * Defer resolution of MESH_MAXHULLVERT default in importers (newton-physics#1587) * Fix TypeError when finalizing SDF geometry with device kwarg (newton-physics#1586) * Make MESH_MAXHULLVERT a static class attribute Mesh.MAX_HULL_VERTICES. (newton-physics#1598) * Significant non-determinism in unified collision pipeline for anymal_c_walking example newton-physics#1505 (newton-physics#1588) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Add test for non-contiguous case (newton-physics#1549) * Fix nightly Warp CI to resolve pre-release builds (newton-physics#1606) * Verify default class and value handling (newton-physics#1556) * SolverMuJoCo: Expand geom_margin to avoid OOB read with heterogeneous worlds (newton-physics#1607) * Fix bug in control clear method (newton-physics#1602) * Enable Use of Newton IK in Lab newton-physics#662 (newton-physics#1539) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Fix import of non-articulated joints (newton-physics#1535) * Deduplicate _process_joint_custom_attributes frequency handling (newton-physics#1584) * Add CI check for stale API docs and fix local build warnings (newton-physics#1570) * Update Pillow 12.0.0 to 12.1.1 (newton-physics#1612) * Prepare handling of mimic constraints in Newton (newton-physics#1523) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Support floating, base_joint and parent_body arguments for importers (newton-physics#1498) * Fix contact buffer memory overestimation (newton-physics#1614) * Configure banned-module-level-imports for ruff (newton-physics#1583) * Explicit `Contacts` instantiation with `Model.contacts()` and `CollisionPipeline.contacts()` (newton-physics#1445) * Fix the quadruped benchmark regression (newton-physics#1615) * Change default ignore_inertial_definitions from True to False (newton-physics#1537) * Finalize the Recording API (newton-physics#1600) * SolverMuJoCo: Fix ccd_iterations default (newton-physics#1631) * update gitignore to ignore Claude Code sandbox files (newton-physics#1628) * Add mimic joint support to SolverMuJoCo (newton-physics#1627) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Add --no-cache-clear flag to test runner (newton-physics#1629) * Update MuJoCo and MuJoCo Warp to 3.5.0 release (newton-physics#1633) * Improve inertia parsing from USD (newton-physics#1605) Signed-off-by: Eric Heiden <eheiden@nvidia.com> Signed-off-by: Eric Heiden <eric-heiden@outlook.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * Remove standalone .typos.toml in favor of pyproject.toml config (newton-physics#1642) * Heightfield support newton-physics#1189 (newton-physics#1547) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Example_robot_policy: Replace ValueError with clean error for missing PhysX policy (newton-physics#1636) Co-authored-by: Viktor Reutskyy <33062116+vreutskyy@users.noreply.github.com> * Avoid unnecessary inflation of the contact reduction voxel aabb (newton-physics#1650) * Rename num_worlds to world_count (newton-physics#1634) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Support parsing autolimits from MJCF (newton-physics#1651) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Fix particle-shape restitution ignoring body velocity (newton-physics#1273) (newton-physics#1580) * Add overflow warnings for narrow-phase collision buffers (newton-physics#1643) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Documentation: add units to model/state docstrings (newton-physics#1649) * fix(viewer): add missing JointType.BALL support to contact line kernel (newton-physics#1640) * Make terrain mesh visual-only in anymal C walking example (newton-physics#1660) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Fix initialization of collider state in MPM finite difference mode (newton-physics#1652) * docs: document ModelBuilder.default_shape_cfg (newton-physics#1662) * Finalize the collision API (newton-physics#1581) * Remove hardcoded subnet ID from AWS workflow (newton-physics#1664) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Attempt to fix AWS config (newton-physics#1666) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Update AWS workflows to g7e.2xlarge with multi-AZ failover (newton-physics#1669) * fix(viewer-usd): disambiguate log_points colors for N=3 warp arrays (newton-physics#1661) * Viewer gl optimizations (newton-physics#1656) Signed-off-by: Miles Macklin <mmacklin@nvidia.com> Signed-off-by: Eric Heiden <eheiden@nvidia.com> Co-authored-by: Eric Heiden <eheiden@nvidia.com> * docs: add articulation workflow guidance and regression check (newton-physics#1663) * fix(examples): propagate IK solution to model state in Franka example (newton-physics#1637) * fix(deps,docs): bump nbconvert to 7.17.0 and fix ArticulationView doctest (newton-physics#1670) * Cleanup and improve some example (newton-physics#1625) Signed-off-by: adenzler-nvidia <adenzler@nvidia.com> Co-authored-by: adenzler-nvidia <adenzler@nvidia.com> * Handle zero-mass bodies and flip ensure_nonstatic_links default (newton-physics#1635) * Additional testing for ArticulationView (newton-physics#1527) Co-authored-by: Eric Heiden <eheiden@nvidia.com> * Update warp-lang nightly to 1.12.0.dev20260217 (newton-physics#1677) * Change default friction coefficients to match MuJoCo (newton-physics#1681) * Refactor mesh creation functions (newton-physics#1654) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Parse joint frictionloss from MJCF (newton-physics#1680) * Fix free joint body_pos and add ref/qpos0 support for MuJoCo solver (newton-physics#1645) * Fix root shapes in ArticulationView with fixed base (newton-physics#1639) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> Co-authored-by: Eric Heiden <eric-heiden@outlook.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Use model collision methods and remove `create_collision_pipeline` from examples (newton-physics#1648) Co-authored-by: nvtw <110816143+nvtw@users.noreply.github.com> * Fix XPBD apply_joint_forces ignoring child joint transform (newton-physics#1582) * Adjust SDF API (newton-physics#1644) Co-authored-by: Eric Heiden <eheiden@nvidia.com> * Optimize test suite runtime (~18% faster) (newton-physics#1689) * Remove ensure_nonstatic_links option from importers (newton-physics#1682) Signed-off-by: adenzler-nvidia <adenzler@nvidia.com> * SolverMuJoCo: Add geom_margin support, align thickness default with MuJoCo and schemas (newton-physics#1653) * refactor: privatize non-public solver internals (newton-physics#1683) * Fix option parsing with multiple <option> elements from includes (newton-physics#1692) * Bump warp-lang nightly and newton-usd-schemas (newton-physics#1693) * Get rid of tkinter dependency (newton-physics#1676) * Fix SDF example contact buffer overflow (newton-physics#1695) * Fix implicit biastype for position/velocity actuator shortcuts (newton-physics#1678) * Fix include processor to respect meshdir/texturedir (newton-physics#1685) * Reduce cold-cache Warp compile time for geometry modules (newton-physics#1618) Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: adenzler-nvidia <adenzler@nvidia.com> * Fix xyzw-to-wxyz quaternion conversion in body inertia kernel (newton-physics#1694) * Rename key to label and add hierarchical labels (newton-physics#1592) (newton-physics#1632) * Expose geometry SDF helpers on public API (newton-physics#1684) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Improve custom frequency handling from USD, parse MuJoCo actuators and tendons (newton-physics#1510) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> Signed-off-by: Eric Heiden <eheiden@nvidia.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Collapse fixed joints with non articulated bodies (newton-physics#1608) * Fix renaming joint_key -> joint_label (newton-physics#1700) Signed-off-by: Eric Heiden <eheiden@nvidia.com> * Bump .python-version from 3.11 to 3.12 (newton-physics#1702) * Replace CITATION.md with CITATION.cff (newton-physics#1706) * Respect MJCF contype=conaffinity=0 via collision_group=0 (newton-physics#1703) * Make ViewerUSD reuse existing USD layers for the same output path (newton-physics#1704) Signed-off-by: Eric Heiden <eheiden@nvidia.com> Signed-off-by: Eric Heiden <eric-heiden@outlook.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Remove dead up-axis conversion from MuJoCo solver (newton-physics#1707) * Skip IK cube stacking example test (newton-physics#1713) * Fix global pairs (world=-1) not exported to MuJoCo spec (newton-physics#1705) * Reduce the memory consumption of hydroelastic contacts (newton-physics#1609) * Fix flakiness cube stacking (newton-physics#1714) * Fix collision shapes not toggleable in viewer UI (newton-physics#1715) * Fix softbody examples table layout in README (newton-physics#1716) * Standardize sensor APIs: label matching, keyword args, and update() method naming (newton-physics#1665) * Fix intermittent crash in parallel test runner from Manager proxy race (newton-physics#1721) * Clean up inertia.py function arguments to match Mesh.create_* API (newton-physics#1719) * Reduce default test runner verbosity (newton-physics#1723) * Add menagerie comparison tests for SolverMuJoCo (newton-physics#1720) Signed-off-by: Alain Denzler <adenzler@nvidia.com> Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> Co-authored-by: Viktor Reutskyy <vreutskyy@nvidia.com> Co-authored-by: Viktor Reutskyy <33062116+vreutskyy@users.noreply.github.com> * Add spatial tendon support for MuJoCo solver (newton-physics#1687) Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> * Expose qfrc_actuator from mujoco (newton-physics#1698) * Skip non-MODEL custom attributes in finalize validation (newton-physics#1734) * Resolve inheritrange for position actuators in MJCF parser (newton-physics#1727) * Support dampratio for position/velocity actuator shortcuts (newton-physics#1722) * Limit concurrency to 1 (newton-physics#1736) * Add a helper method for checking applied usd (newton-physics#1731) * Enhance playback URL handling in ViewerViser (newton-physics#1742) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Removed RenderShapeType (newton-physics#1748) * Override only MassAPI attributes that have been authored (newton-physics#1688) * Integration of newton-actuators (newton-physics#1342) Signed-off-by: jvonmuralt <jvonmuralt@nvidia.com> * Fix ArticulationView crash with fixed-joint-only articulations (newton-physics#1726) * Improve retrieval of Jupyter base URL in ViewerViser (newton-physics#1750) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Disable dynamics testing for UR5e and Apollo tests to avoid CI flakiness (newton-physics#1755) * Margin and Gap rename (newton-physics#1732) * Vbd Demos Fixing (newton-physics#1740) * Fix ViewerViser.log_lines method (newton-physics#1764) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Update warp-lang dependency to 1.12.0rc1 (newton-physics#1763) * Fix fromto capsule/cylinder orientation in MJCF parser (newton-physics#1741) * fix: multi-world particle BVH indexing (newton-physics#1641) Co-authored-by: Eric Heiden <eheiden@nvidia.com> * Clean up unused and internal-only kwargs in SolverMuJoCo (newton-physics#1766) * Parsing of the mimic joint and contact gap/margin from newton schemas (newton-physics#1690) Signed-off-by: Milad Rakhsha <mrakhsha@nvidia.com> * API Refactor v2 (newton-physics#1749) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Support explicit geom mass attributes in MJCF (newton-physics#1744) * Bump flask and werkzeug in lockfile for security (newton-physics#1769) Co-authored-by: Cursor <cursoragent@cursor.com> * Split MJCF worldbody root bodies into separate articulations (newton-physics#1754) * Expose VBD rigid contact forces for solver coupling (newton-physics#1745) Signed-off-by: JC <jumyungc@nvidia.com> * Add MJCF ellipsoid geom import and regression test (newton-physics#1772) Co-authored-by: Cursor <cursoragent@cursor.com> * Weld equality constraints parsed from mjcf are given Nan as the default value of torquescale. The correct default should be 1.0 (newton-physics#1760) * Improve picking accuracy and stability (newton-physics#1712) * Franka cloth demo improvement (newton-physics#1765) * Support computing sensing object transforms & API cleanup (newton-physics#1759) * Remove threading workaround (newton-physics#1751) * [Warp Raytrace] Consolidated ray intersect functions, renamed Options to Config (newton-physics#1767) * Improve README example gallery for PyPI compatibility (newton-physics#1776) * Fix issue with mesh in rerun viewer (newton-physics#1768) * Add PhysxMimicJointAPI parsing to USD importer (newton-physics#1735) * Move some math functions to Warp (newton-physics#1717) Signed-off-by: Eric Heiden <eheiden@nvidia.com> Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Add test to ensure MJCF xform argument is relative (newton-physics#1777) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Emit diaginertia instead of fullinertia for diagonal body inertia (newton-physics#1780) * Change default joint armature from 0.01 to 0 (newton-physics#1782) * Fix default kp/kv for position and velocity actuators (newton-physics#1786) * Lock body inertia after explicit MJCF <inertial> element (newton-physics#1784) * Fix for MJCF actuator custom attributes (newton-physics#1783) * Bump version to 0.2.3 Prepare the package metadata for the v0.2.3 release tag. * Fix ViewerRerun rendering of instances from hidden meshes (newton-physics#1788) * API cleanup (newton-physics#1789) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * BODY actuator target name bypasses body name de-duplication in SolverMuJoCo (newton-physics#1729) * Use default density for visual geoms in MJCF import (newton-physics#1781) * Fix GL viewer crash on Wayland (newton-physics#1793) * Make USD xform parameter control absolute articulation placement (newton-physics#1771) * Fix CUDA context corruption in SDF implementation (newton-physics#1792) * Bump mujoco-warp dependency to 3.5.0.2 (newton-physics#1779) * Fix MuJoCo margin/gap conversion (newton-physics#1785) * Bump version to 1.1.0.dev0 (newton-physics#1798) * Missing unittest.main added back to test_import_mjcf.py. Helps with F5 debugging in VS Code. (newton-physics#1796) * Improve H1 example (newton-physics#1801) Signed-off-by: Eric Heiden <eric-heiden@outlook.com> * Fix ViewerViser.set_camera() (newton-physics#1805) * Rename examples to follow prefix-first naming convention (newton-physics#1802) * Improve MuJoCo actuator domain randomization (newton-physics#1773) * Restore in_cup test in hydro example (newton-physics#1775) * Fix `newton.geometry` imports and change of Mesh maxhullverts global constant * Adapt to having both margin and gap arrays for each geom/shape * Fix for newton.geometry API changes in primitive/narrowphase.py * Fix removal of `BroadPhaseMode` IntEnum and revert to newton-sytle string literals * WIP: Adapt geometry/unified.py to fix breaking changes to `newton.geometry` API * First pass of API adjustments * Patch more gaps (with respect to margin and gap renaming) * GeoType.SDF was removed - reflect that in Kamino * Introduce CoM position offsets w.r.t body frame and operations to convert between body CoM state and generic local body-fixed reference frames. * Add caching of per-entity labels/names/keys in the Model subcontainers * Remove SDF shape wrapper since it's now internal to mesh handling in CD pipelines * Fix USD test assets * Add Newton <--> Kamino joint type conversion operations and per-space default limit constants * Add some cleanup to geometry and unified CD + UTs * Add Newton <--> Kamino shape type conversion operations * Apply new default joint coord limit constants to limits.py * Adapt foubrar model builder and USD asset to produce the same result in sim example * Purge "physical" goems and collapse all into a single group, and purge geometry "layers" * Disable allocation per-joint wrenches by default and make them optional * Make `Model` a dataclass * Separate ModelData* containers into own `core/data.py` module * Fix imports of ModelData * Rename `Model` as `ModelKamino` * Rename `ModelData` as `DataKamino` * Rename `State` as `StateKamino` * Rename `Control` as `ControlKamino` * Rename `Limits` as `LimitsKamino` * Rename `Contacts` as `ContactsKamino` * Rename `ModelBuilder` as `ModelBuilderKamino` * Make imports in test utilities relative * Revise CD meta-data attributes and their computation in GeometryModel and ModelBuilderKamino * Revise primitive CD pipeline * Revise unified CD pipeline * Revise CD front-end interfaces * Fix UTs and relevant utils for interface changes to CD * Change to `wp.DeviceLike` to account for upcoming deprecation of `Devicelike` * Depracate legacy HDF5 data io (will be replaced in the future) * Fix banned imports at module level * Modify USD importer to detect articulations and order geoms and joints similarly to how the Newton `parse_usd` function does. * Add conversion operation from `newton.Model` to `ModelKamino` * Add data, state and control container conversions * Add SolverKamino wrapper that fullfils newton integration interface * Add newton integration examples * Add SolverKamino to newton solver module imports * WIP: fix problem with lambda_j being allocated for only kinematic constraints and failing on array copying * Fix banned git import in benchmark * Rename *Settings to *Config (#213) * Rename SolverKaminoSettings -> SolverKaminoConfig * Rename DualProblemSettings -> DualProblemConfig * Rename CollisionDetectorSettings -> CollisionDetectorConfig * Rename PADMMSettings -> PADMMConfig * Rename ForwardKinematicsSolverSettings -> ForwardKinematicsSolverConfig * Rename SimulatorSettings -> SimulatorConfig * Add check for model compatibility in SolverKamino (#209) * Fix device assignment in sparse CG test on CPU (#216) * Replace Enum-type config attributes with Literal (#215) * Replace warmstart mode config param with literal * Replace contact warmstart mode config param with literal * Replace rotation correction config param with literal * Replace penalty update config param with literal * Replace FK preconditioner option config param with literal * Add post-init checks for dual/PADMM configs * Rename FKPreconditionerOptions to FKPreconditionerType * Remove WorldDescriptor from ModelKamino (#219) * Add geom index offset array to model info * Replace access to world description in model * Remove world descriptor from model * Fix computation of kinematics residual with sparse Jacobian (#220) * Migrates `ModelKaminoSize` to it's own module to avoid circular dependency between core/model.py and core/state.py and rename it as `SizeKamino`. * WIP: Fix SolverKamino wrapper * Fix circular dependency in conversions.py * Fix some broken unit tests and WIP to fix fourbar contact conversions and rendering * Make some conversions @staticmethods instead, because they dont need common class attributes * Fix declaration of custom state attributes and their conversion to/from newton and kamino * WIP: Debug model conversion and newton sim examples * Rename and cleanup start index array of per-world geoms * Model conversion and newton sim examples now work. * Make gravity conversion operation re-usable * Migrates boxes_fourbar builder using newton.ModelBuilder to it's own module to prepare for migration. * Use gravity conversion utility func in SolverKamino * Add reusable joint-parameterization conversion utility * Remove world-descriptor from model converter * Rename helper converter that handles entity-local transforms * Add some cleanup to DR Legs, ANYmal D and basic four-bar examples * Fix module-level imports of additional kamino-specific development dependencies * Fix module-level imports of additional kamino-specific development dependencies * Fix erroneous merge conflict. --------- Signed-off-by: Alain Denzler <adenzler@nvidia.com> Signed-off-by: Viktor Reutskyy <vreutskyy@nvidia.com> Signed-off-by: JC <jumyungc@nvidia.com> Signed-off-by: Milad Rakhsha <mrakhsha@nvidia.com> Signed-off-by: Milad-Rakhsha-NV <167464435+Milad-Rakhsha-NV@users.noreply.github.com> Signed-off-by: Eric Heiden <eric-heiden@outlook.com> Signed-off-by: Eric Heiden <eheiden@nvidia.com> Signed-off-by: Miles Macklin <mmacklin@nvidia.com> Signed-off-by: adenzler-nvidia <adenzler@nvidia.com> Signed-off-by: jvonmuralt <jvonmuralt@nvidia.com> Co-authored-by: Daniela Hase <116915287+daniela-hase@users.noreply.github.com> Co-authored-by: adenzler-nvidia <adenzler@nvidia.com> Co-authored-by: Viktor Reutskyy <33062116+vreutskyy@users.noreply.github.com> Co-authored-by: Eric Shi <97630937+shi-eric@users.noreply.github.com> Co-authored-by: Anka Chen <AnkaChan@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: JC-nvidia <116605903+jumyungc@users.noreply.github.com> Co-authored-by: Kenny Vilella <kvilella@nvidia.com> Co-authored-by: nvtw <110816143+nvtw@users.noreply.github.com> Co-authored-by: Milad-Rakhsha-NV <167464435+Milad-Rakhsha-NV@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Lennart Röstel <65088822+lenroe@users.noreply.github.com> Co-authored-by: Eric Heiden <eheiden@nvidia.com> Co-authored-by: jvonmuralt <jvonmuralt@nvidia.com> Co-authored-by: camevor <camevor@nvidia.com> Co-authored-by: mzamoramora-nvidia <mzamoramora@nvidia.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Alessandro Roncone <alecive87@gmail.com> Co-authored-by: gdaviet <57617656+gdaviet@users.noreply.github.com> Co-authored-by: Miles Macklin <mmacklin@nvidia.com> Co-authored-by: Gordon Yeoman <gyeomannvidia@users.noreply.github.com> Co-authored-by: Lukasz Wawrzyniak <lwawrzyniak@nvidia.com> Co-authored-by: Eric Heiden <eric-heiden@outlook.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Viktor Reutskyy <vreutskyy@nvidia.com> Co-authored-by: Lorenzo Terenzi <lorenzoterenzi96@gmail.com> Co-authored-by: smollerNV <164020096+smollerNV@users.noreply.github.com> Co-authored-by: twidmer <twidmer@nvidia.com> Co-authored-by: Christian Schumacher <christian.schumacher@disney.com> Co-authored-by: Guirec-Maloisel <25688871+Guirec-Maloisel@users.noreply.github.com>
Summary
Adds soft body simulation support to the VBD solver with volumetric Neo-Hookean FEM elasticity. The main piece here is a new planar truncation method for displacement-based self-collision handling—this prevents interpenetration by computing per-particle truncation factors via atomic min operations across all collision primitives.
Key changes:
New Examples
softbody/example_softbody_hanging- hanging soft body with varying dampingmultiphysics/example_falling_gift- gift box with soft body contentsmultiphysics/example_softbody_dropping_to_cloth- soft body landing on clothNewton 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
New Options
Documentation
Tests
Behavior Changes