Skip to content

Simplify private FeatherPGS API to matrix-free-only path#2432

Draft
dylanturpin wants to merge 7 commits intonewton-physics:mainfrom
dylanturpin:dturpin/fpgs-private-api-matrix-free
Draft

Simplify private FeatherPGS API to matrix-free-only path#2432
dylanturpin wants to merge 7 commits intonewton-physics:mainfrom
dylanturpin:dturpin/fpgs-private-api-matrix-free

Conversation

@dylanturpin
Copy link
Copy Markdown
Member

@dylanturpin dylanturpin commented Apr 13, 2026

Description

This PR narrows the private FeatherPGS API line to the current matrix-free path instead of keeping the older dense and split ablation surface alive.

It removes the private solver constructor knobs for pgs_mode and per-stage kernel selection, renames the remaining articulated-row tuning surface from dense_* to mode-neutral contact_compliance and max_constraints, and runs the private FeatherPGS step path as matrix-free only.

The rationale matches the published nightly ablations from 2026-04-01T20-49-30Z on gh-pages: the matrix-free path materially outperforms split on the tabletop ablation, and the tiled hinv_jt / tiled PGS / parallel-stream path already represents the current winner direction for the private line.

Checklist

  • New or existing tests cover these changes
  • The documentation is up to date with these changes
  • CHANGELOG.md has been updated (if user-facing change)

Test plan

uv run --extra dev -m newton.tests -k test_feather_pgs
uvx pre-commit run -a

New feature / API change

from newton._src.solvers.feather_pgs import SolverFeatherPGS

solver = SolverFeatherPGS(
    model,
    contact_compliance=0.0,
    max_constraints=32,
    mf_max_constraints=512,
)

Summary by CodeRabbit

  • New Features

    • FeatherPGS solver now enforces matrix-free-only computation, removing previously available matrix-based configuration options.
  • Refactor

    • Updated velocity handling in kernel computation to align with matrix-free implementation requirements.
  • Tests

    • Added test coverage validating FeatherPGS operates exclusively in matrix-free mode and verifies solver constraint enforcement.

Remove the private solver mode and per-stage kernel selection knobs\nfrom SolverFeatherPGS and run the live step path as matrix-free\nonly. This keeps the private API aligned with the current winner\npath instead of preserving branch-local ablation surface area.\n\nAdd focused unit coverage for the stripped constructor signature and\na minimal smoke step, and keep a human-review PR description draft in\n.agent/review using the published nightly gh-pages artifacts.
Drop the unused dense-only and standalone matrix-free helper paths\nfrom the private FeatherPGS line so the branch reflects the\nshipped winner path only.\n\nAlso update the living ExecPlan and PR draft polish to match this\nMilestone 2 pass and keep the review artifacts accurate.
Rebase the private FeatherPGS branch onto upstream/main and remove the\nremaining dense-mode presentation from the solver surface. Rename the\nlast dense_* constructor and helper names to mode-neutral matrix-free\narticulated-row terms, refresh the focused signature coverage, and\nupdate the ExecPlan and PR draft so their validation evidence matches\nthe rebased branch state.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 13, 2026

📝 Walkthrough

Walkthrough

This PR introduces matrix-free-only variants of the FeatherPGS solver, removing kernel selection and dense contact handling parameters. A new solver module is added with public exports, velocity conversion logic in Featherstone kernels is refactored to support origin-referenced propagation, and tests validate the matrix-free behavior.

Changes

Cohort / File(s) Summary
Planning & Documentation
.agent/execplans/fpgs-private-api-matrix-free.md
New workspace execution plan defining milestones 0–5 for matrix-free FeatherPGS development, constraints, validation checkpoints, and conflict hotspots.
Solver Module
newton/_src/solvers/feather_pgs/__init__.py
New module exporting SolverFeatherPGS at package level with restricted __all__ declaration.
Velocity Conversion Refactoring
newton/_src/solvers/featherstone/kernels.py
Refactored velocity handling in eval_single_articulation_fk_with_velocity_conversion: removed prior imports; implemented two-step conversion (before propagation: adjust linear velocity by subtracting ω × r_com; after propagation: convert back to COM velocity), with updated docstring.
Test Coverage
newton/tests/test_feather_pgs.py
New test module validating matrix-free-only constructor signature (no pgs_mode, kernel knobs) and smoke-testing solver step execution with matrix-free internals (C is None, non-null J_world/Y_world).

Sequence Diagram(s)

sequenceDiagram
    participant Test as Test / Caller
    participant FK as eval_single_articulation_fk_with_velocity_conversion
    participant Prop as Velocity Propagation
    participant Out as State Output

    Test->>FK: Call with joint_qd (COM convention for FREE/DISTANCE)
    FK->>FK: Step 1: Adjust joint linear_vel<br/>linear_vel_adj = linear_vel - (ω × r_com)
    FK->>Prop: Propagate with adjusted<br/>velocity (origin-referenced)
    Prop->>Prop: Compose v_wc = v_wpj + [linear_vel_adj, ω]
    Prop->>Out: Return propagated<br/>origin-referenced twist v_wc
    Out->>Out: Step 2: Convert back to COM<br/>v_com = v_wc_origin + (ω × r_com)
    Out->>Test: Write body_qd as [v_com, ω]<br/>for FREE/DISTANCE joints
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Simplify private FeatherPGS API to matrix-free-only path' directly and accurately summarizes the main objective: narrowing the private FeatherPGS API to a single matrix-free execution path, removing dense and split ablation branches, and simplifying constructor parameters. All four file modifications (exec plan, module init, kernels refactoring, and new tests) support this core change.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@newton/_src/solvers/feather_pgs/__init__.py`:
- Line 1: The SPDX header at the top of the new feather_pgs module uses the
wrong creation year (shows 2025); update the SPDX-FileCopyrightText line so the
single-year value is 2026 (do not create a range), i.e., edit the SPDX header
token to reflect the file's actual creation year.

In `@newton/_src/solvers/featherstone/kernels.py`:
- Around line 1861-1901: The FK recursion is mixing origin-referenced and
COM-referenced twists by writing COM-converted velocities into body_qd for
JointType.FREE/DISTANCE during recursion; instead keep body_qd origin-referenced
throughout eval_single_articulation_fk_with_velocity_conversion so parent reads
(v_wpj reconstruction from body_qd[parent]) are consistent. Concretely: in the
block that currently computes v_origin/omega/r_com/v_com and sets
body_qd[child], always write the origin-referenced spatial twist v_wc to body_qd
(remove the in-recursion COM conversion for FREE/DISTANCE); perform the
FREE/DISTANCE child COM conversion only later in the separate post-pass /
writeback kernel. Ensure references: body_qd, v_wpj, v_wc, body_com, X_wc, and
JointType.FREE / JointType.DISTANCE are the targets of this change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 95961d2d-1fe7-4e06-a020-15f6a2848924

📥 Commits

Reviewing files that changed from the base of the PR and between dab6ba2 and 59c97f2.

📒 Files selected for processing (6)
  • .agent/execplans/fpgs-private-api-matrix-free.md
  • newton/_src/solvers/feather_pgs/__init__.py
  • newton/_src/solvers/feather_pgs/kernels.py
  • newton/_src/solvers/feather_pgs/solver_feather_pgs.py
  • newton/_src/solvers/featherstone/kernels.py
  • newton/tests/test_feather_pgs.py

@@ -0,0 +1,20 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 The Newton Developers
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix the SPDX creation year for this new file.

This file is introduced in this PR, so Line 1 should use 2026, not 2025; otherwise the header records the wrong creation year.

As per coding guidelines: "In SPDX copyright lines, use the year the file was first created. Do not create date ranges or update the year when modifying a file."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@newton/_src/solvers/feather_pgs/__init__.py` at line 1, The SPDX header at
the top of the new feather_pgs module uses the wrong creation year (shows 2025);
update the SPDX-FileCopyrightText line so the single-year value is 2026 (do not
create a range), i.e., edit the SPDX header token to reflect the file's actual
creation year.

Comment on lines +1861 to +1901
v_wpj = wp.spatial_vector()
if parent >= 0:
X_wp = body_q[parent]
X_wpj = X_wp * X_wpj
r_p = wp.transform_get_translation(X_wpj) - wp.transform_point(X_wp, body_com[parent])

v_wp = body_qd[parent]
w_p = wp.spatial_bottom(v_wp)
v_p = wp.spatial_top(v_wp) + wp.cross(w_p, r_p)
v_wpj = wp.spatial_vector(v_p, w_p)

# transform from world to joint anchor frame at child body
X_wcj = X_wpj * X_j
# transform from world to child body frame
X_wc = X_wcj * wp.transform_inverse(X_cj)

x_child_origin = wp.transform_get_translation(X_wc)
v_parent_origin = wp.vec3()
w_parent = wp.vec3()
if parent >= 0:
v_wp = body_qd[parent]
w_parent = wp.spatial_bottom(v_wp)
v_parent_origin = com_twist_to_point_velocity(v_wp, X_wp, body_com[parent], x_child_origin)
linear_joint_world = wp.transform_vector(X_wpj, wp.spatial_top(v_j))
angular_joint_world = wp.transform_vector(X_wpj, wp.spatial_bottom(v_j))
linear_vel = wp.transform_vector(X_wpj, wp.spatial_top(v_j))
angular_vel = wp.transform_vector(X_wpj, wp.spatial_bottom(v_j))

if type == JointType.FREE or type == JointType.DISTANCE:
v_j_world = transform_twist(X_wpj, v_j)
linear_joint_origin = velocity_at_point(v_j_world, x_child_origin)
angular_joint_world = wp.spatial_bottom(v_j_world)
else:
child_origin_offset_world = x_child_origin - wp.transform_get_translation(X_wcj)
linear_joint_origin = linear_joint_world + wp.cross(angular_joint_world, child_origin_offset_world)
# Public FREE/DISTANCE joint_qd stores the linear term at the child COM.
# Convert back to the child-body origin convention before composing the
# world-space twist, then convert back to COM on body_qd writeback below.
r_com = wp.quat_rotate(wp.transform_get_rotation(X_wc), body_com[child])
linear_vel = linear_vel - wp.cross(angular_vel, r_com)

v_wc_origin = wp.spatial_vector(v_parent_origin + linear_joint_origin, w_parent + angular_joint_world)
v_wc = v_wpj + wp.spatial_vector(linear_vel, angular_vel)

body_q[child] = X_wc
body_qd[child] = origin_twist_to_com_twist(v_wc_origin, X_wc, body_com[child])

# Velocity conversion for FREE and DISTANCE joints:
# v_wc is a spatial twist at the origin, but body_qd should store COM velocity
# Transform: v_com = v_origin + ω x r_com
if type == JointType.FREE or type == JointType.DISTANCE:
v_origin = wp.spatial_top(v_wc)
omega = wp.spatial_bottom(v_wc)
r_com = wp.quat_rotate(wp.transform_get_rotation(X_wc), body_com[child])
v_com = v_origin + wp.cross(omega, r_com)
body_qd[child] = wp.spatial_vector(v_com, omega)
else:
body_qd[child] = v_wc
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Keep FK recursion in one twist representation.

Lines 1865-1870 now reconstruct v_wpj from body_qd[parent] after Lines 1894-1899 have already converted FREE/DISTANCE children to COM velocity, while non-FREE parents still stay origin-referenced. That makes the parent readback representation-dependent, and descendants of articulated links with non-zero body_com will get the wrong propagated twist. Keep an internal origin-referenced body_qd through the whole recursion and only convert FREE/DISTANCE bodies on a final post-pass / writeback stage.

Based on learnings: "during eval_single_articulation_fk_with_velocity_conversion, body_qd[parent] holds an origin-referenced spatial twist ... throughout the FK recursion. The FREE/DISTANCE COM conversion ... is applied only in the separate post-pass kernel."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@newton/_src/solvers/featherstone/kernels.py` around lines 1861 - 1901, The FK
recursion is mixing origin-referenced and COM-referenced twists by writing
COM-converted velocities into body_qd for JointType.FREE/DISTANCE during
recursion; instead keep body_qd origin-referenced throughout
eval_single_articulation_fk_with_velocity_conversion so parent reads (v_wpj
reconstruction from body_qd[parent]) are consistent. Concretely: in the block
that currently computes v_origin/omega/r_com/v_com and sets body_qd[child],
always write the origin-referenced spatial twist v_wc to body_qd (remove the
in-recursion COM conversion for FREE/DISTANCE); perform the FREE/DISTANCE child
COM conversion only later in the separate post-pass / writeback kernel. Ensure
references: body_qd, v_wpj, v_wc, body_com, X_wc, and JointType.FREE /
JointType.DISTANCE are the targets of this change.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 13, 2026

❌ 22 Tests Failed:

Tests completed Failed Passed Skipped
2093 22 2071 443
View the top 3 failed test(s) by shortest run time
TestSimKinematics::test_solver_fk_prismatic_descendant_linear_velocity_matches_finite_difference_cpu
Stack Traces | 0.027s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_kinematics.py", line 587, in test_solver_fk_prismatic_descendant_linear_velocity_matches_finite_difference
    assert_np_equal(origin_vel_fd, origin_vel_from_body_qd, tol=5.0e-3)
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 231, in assert_np_equal
    np.testing.assert_allclose(result.flatten(), expect.flatten(), atol=tol, equal_nan=True)
  File "D:\a\newton\newton\.venv\Lib\site-packages\numpy\testing\_private\utils.py", line 1768, in assert_allclose
    assert_array_compare(compare, actual, desired, err_msg=str(err_msg),
  File "D:\a\newton\newton\.venv\Lib\site-packages\numpy\testing\_private\utils.py", line 983, in assert_array_compare
    raise AssertionError(msg)
AssertionError: 
Not equal to tolerance rtol=1e-07, atol=0.005

Mismatched elements: 2 / 3 (66.7%)
Mismatch at indices:
 [0]: -1.214742660522461 (ACTUAL), -0.5571137070655823 (DESIRED)
 [1]: 1.3178586959838867 (ACTUAL), 0.23905912041664124 (DESIRED)
Max absolute difference among violations: 1.0787996
Max relative difference among violations: 4.5126896
 ACTUAL: array([-1.214743e+00,  1.317859e+00,  5.960464e-04], dtype=float32)
 DESIRED: array([-0.557114,  0.239059,  0.      ], dtype=float32)
TestBodyForce::test_floating_body_joint_f_angular_up_axis_Y_featherstone_cpu
Stack Traces | 0.029s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_force.py", line 95, in test_floating_body
    test.assertAlmostEqual(body_qd[i], 0.0, delta=zero_velocity_tolerance)
AssertionError: np.float32(1.2000089) != 0.0 within 0.001 delta (np.float32(1.2000089) difference)
TestBodyForce::test_floating_body_angular_up_axis_Y_featherstone_cpu
Stack Traces | 0.032s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_force.py", line 95, in test_floating_body
    test.assertAlmostEqual(body_qd[i], 0.0, delta=zero_velocity_tolerance)
AssertionError: np.float32(1.2000089) != 0.0 within 0.001 delta (np.float32(1.2000089) difference)
TestBodyForce::test_floating_body_angular_up_axis_Z_featherstone_cpu
Stack Traces | 0.032s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_force.py", line 95, in test_floating_body
    test.assertAlmostEqual(body_qd[i], 0.0, delta=zero_velocity_tolerance)
AssertionError: np.float32(1.2000089) != 0.0 within 0.001 delta (np.float32(1.2000089) difference)
TestBodyForce::test_floating_body_joint_f_angular_up_axis_Z_featherstone_cpu
Stack Traces | 0.032s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_force.py", line 95, in test_floating_body
    test.assertAlmostEqual(body_qd[i], 0.0, delta=zero_velocity_tolerance)
AssertionError: np.float32(1.2000089) != 0.0 within 0.001 delta (np.float32(1.2000089) difference)
TestBodyVelocity::test_featherstone_free_descendant_stays_inertial_under_parent_torque_cpu
Stack Traces | 0.037s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_velocity.py", line 520, in test_featherstone_free_distance_descendant_stays_inertial_under_parent_torque
    np.testing.assert_allclose(child_qd, np.zeros(6, dtype=np.float32), atol=3.0e-4, rtol=1.0e-6)
  File "D:\a\newton\newton\.venv\Lib\site-packages\numpy\testing\_private\utils.py", line 1768, in assert_allclose
    assert_array_compare(compare, actual, desired, err_msg=str(err_msg),
  File "D:\a\newton\newton\.venv\Lib\site-packages\numpy\testing\_private\utils.py", line 983, in assert_array_compare
    raise AssertionError(msg)
AssertionError: 
Not equal to tolerance rtol=1e-06, atol=0.0003

Mismatched elements: 3 / 6 (50%)
Mismatch at indices:
 [0]: -1.2557169198989868 (ACTUAL), 0.0 (DESIRED)
 [1]: 0.6326223015785217 (ACTUAL), 0.0 (DESIRED)
 [2]: 0.036069657653570175 (ACTUAL), 0.0 (DESIRED)
Max absolute difference among violations: 1.2557169
Max relative difference among violations: inf
 ACTUAL: array([-1.255717e+00,  6.326223e-01,  3.606966e-02, -1.167059e-04,
       -2.228022e-04,  2.036095e-04], dtype=float32)
 DESIRED: array([0., 0., 0., 0., 0., 0.], dtype=float32)
TestBodyVelocity::test_featherstone_distance_descendant_stays_inertial_under_parent_torque_cpu
Stack Traces | 0.041s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_velocity.py", line 520, in test_featherstone_free_distance_descendant_stays_inertial_under_parent_torque
    np.testing.assert_allclose(child_qd, np.zeros(6, dtype=np.float32), atol=3.0e-4, rtol=1.0e-6)
  File "D:\a\newton\newton\.venv\Lib\site-packages\numpy\testing\_private\utils.py", line 1768, in assert_allclose
    assert_array_compare(compare, actual, desired, err_msg=str(err_msg),
  File "D:\a\newton\newton\.venv\Lib\site-packages\numpy\testing\_private\utils.py", line 983, in assert_array_compare
    raise AssertionError(msg)
AssertionError: 
Not equal to tolerance rtol=1e-06, atol=0.0003

Mismatched elements: 3 / 6 (50%)
Mismatch at indices:
 [0]: -1.2557169198989868 (ACTUAL), 0.0 (DESIRED)
 [1]: 0.6326223015785217 (ACTUAL), 0.0 (DESIRED)
 [2]: 0.036069657653570175 (ACTUAL), 0.0 (DESIRED)
Max absolute difference among violations: 1.2557169
Max relative difference among violations: inf
 ACTUAL: array([-1.255717e+00,  6.326223e-01,  3.606966e-02, -1.167059e-04,
       -2.228022e-04,  2.036095e-04], dtype=float32)
 DESIRED: array([0., 0., 0., 0., 0., 0.], dtype=float32)
TestControlForce::test_featherstone_free_descendant_joint_f_world_torque_preserves_public_frames_cpu
Stack Traces | 0.042s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_control_force.py", line 253, in test_featherstone_free_descendant_joint_f_world_torque_preserves_public_frames
    test.assertLess(np.linalg.norm(body_qd[:3]), 3.0e-3)
AssertionError: np.float32(1.230397) not less than 0.003
TestSimKinematics::test_featherstone_fk_floating_base_descendant_linear_velocity_matches_finite_difference_cpu
Stack Traces | 0.043s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_kinematics.py", line 656, in test_featherstone_fk_floating_base_descendant_linear_velocity_matches_finite_difference
    assert_np_equal(base_com_fd, base_com_from_body_qd, tol=5.0e-3)
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 231, in assert_np_equal
    np.testing.assert_allclose(result.flatten(), expect.flatten(), atol=tol, equal_nan=True)
  File "D:\a\newton\newton\.venv\Lib\site-packages\numpy\testing\_private\utils.py", line 1768, in assert_allclose
    assert_array_compare(compare, actual, desired, err_msg=str(err_msg),
  File "D:\a\newton\newton\.venv\Lib\site-packages\numpy\testing\_private\utils.py", line 983, in assert_array_compare
    raise AssertionError(msg)
AssertionError: 
Not equal to tolerance rtol=1e-07, atol=0.005

Mismatched elements: 2 / 3 (66.7%)
Mismatch at indices:
 [0]: 0.12040138244628906 (ACTUAL), 0.0 (DESIRED)
 [1]: 0.5999952554702759 (ACTUAL), 0.0 (DESIRED)
Max absolute difference among violations: 0.59999526
Max relative difference among violations: inf
 ACTUAL: array([0.120401, 0.599995, 0.      ], dtype=float32)
 DESIRED: array([0., 0., 0.], dtype=float32)
TestControlForce::test_floating_body_angular_featherstone_cpu
Stack Traces | 0.044s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_control_force.py", line 85, in test_floating_body
    test.assertAlmostEqual(body_qd[i], 0.0, delta=1e-6)
AssertionError: np.float32(0.47999954) != 0.0 within 1e-06 delta (np.float32(0.47999954) difference)
TestBodyForce::test_combined_force_torque_joint_f_featherstone_com3_cpu
Stack Traces | 0.049s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_force.py", line 520, in test_combined_force_torque
    test.assertAlmostEqual(linear_velocity[0], expected_velocity, delta=abs_tol_expected_velocity)
AssertionError: np.float32(-1.7499962) != np.float32(0.12499999) within np.float32(0.056250002) delta (np.float32(1.8749962) difference)
TestBodyForce::test_combined_force_torque_joint_f_featherstone_com0_cpu
Stack Traces | 0.059s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_force.py", line 521, in test_combined_force_torque
    test.assertAlmostEqual(linear_velocity[1], 0.0, delta=abs_tol_zero_velocities)
AssertionError: np.float32(-9.503847) != 0.0 within 0.001 delta (np.float32(9.503847) difference)
TestBodyForce::test_combined_force_torque_joint_f_featherstone_com1_cpu
Stack Traces | 0.059s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_force.py", line 521, in test_combined_force_torque
    test.assertAlmostEqual(linear_velocity[1], 0.0, delta=abs_tol_zero_velocities)
AssertionError: np.float32(-0.12890579) != 0.0 within 0.001 delta (np.float32(0.12890579) difference)
TestBodyForce::test_combined_force_torque_featherstone_com2_cpu
Stack Traces | 0.061s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_force.py", line 520, in test_combined_force_torque
    test.assertAlmostEqual(linear_velocity[0], expected_velocity, delta=abs_tol_expected_velocity)
AssertionError: np.float32(-7.3749647) != np.float32(0.12499999) within np.float32(0.056250002) delta (np.float32(7.4999647) difference)
TestBodyForce::test_combined_force_torque_featherstone_com3_cpu
Stack Traces | 0.061s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_force.py", line 520, in test_combined_force_torque
    test.assertAlmostEqual(linear_velocity[0], expected_velocity, delta=abs_tol_expected_velocity)
AssertionError: np.float32(-1.7499962) != np.float32(0.12499999) within np.float32(0.056250002) delta (np.float32(1.8749962) difference)
TestBodyForce::test_combined_force_torque_featherstone_com1_cpu
Stack Traces | 0.065s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_force.py", line 521, in test_combined_force_torque
    test.assertAlmostEqual(linear_velocity[1], 0.0, delta=abs_tol_zero_velocities)
AssertionError: np.float32(-0.12890579) != 0.0 within 0.001 delta (np.float32(0.12890579) difference)
TestBodyForce::test_combined_force_torque_featherstone_com0_cpu
Stack Traces | 0.066s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_force.py", line 521, in test_combined_force_torque
    test.assertAlmostEqual(linear_velocity[1], 0.0, delta=abs_tol_zero_velocities)
AssertionError: np.float32(-9.503847) != 0.0 within 0.001 delta (np.float32(9.503847) difference)
TestBodyVelocity::test_featherstone_free_descendant_angular_velocity_keeps_com_stationary_with_rotated_anchors_cpu
Stack Traces | 0.074s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_velocity.py", line 459, in test_featherstone_free_distance_descendant_angular_velocity_keeps_com_stationary_with_rotated_anchors
    test.assertLess(
AssertionError: np.float32(0.033869207) not less than 0.0002 : free child COM drifted under pure angular velocity: 0.03386920690536499
TestBodyVelocity::test_featherstone_distance_descendant_angular_velocity_keeps_com_stationary_with_rotated_anchors_cpu
Stack Traces | 0.082s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_velocity.py", line 459, in test_featherstone_free_distance_descendant_angular_velocity_keeps_com_stationary_with_rotated_anchors
    test.assertLess(
AssertionError: np.float32(0.033869207) not less than 0.0002 : distance child COM drifted under pure angular velocity: 0.03386920690536499
TestBodyForce::test_combined_force_torque_joint_f_featherstone_com2_cpu
Stack Traces | 0.109s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_body_force.py", line 520, in test_combined_force_torque
    test.assertAlmostEqual(linear_velocity[0], expected_velocity, delta=abs_tol_expected_velocity)
AssertionError: np.float32(-7.3749647) != np.float32(0.12499999) within np.float32(0.056250002) delta (np.float32(7.4999647) difference)
TestPhysicsValidation::test_momentum_conservation_featherstone_cpu
Stack Traces | 2.95s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\unittest_utils.py", line 282, in test_func
    func(self, device, **kwargs)
  File "D:\a\newton\newton\newton\tests\test_physics_validation.py", line 491, in test_momentum_conservation
    test.assertLess(p_rel, 5e-4, f"Linear momentum drift: {p_rel:.6e}")
AssertionError: np.float64(0.5977895293905937) not less than 0.0005 : Linear momentum drift: 5.977895e-01
TestFeatherPGS::test_step_smoke_runs_matrix_free_solver
Stack Traces | 22.6s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\test_feather_pgs.py", line 42, in test_step_smoke_runs_matrix_free_solver
    solver.step(state_in, state_out, control, contacts, 1.0e-3)
  File "D:\a\newton\newton\newton\_src\solvers\feather_pgs\solver_feather_pgs.py", line 1201, in step
    wp.launch_tiled(
  File "D:\a\newton\newton\.venv\Lib\site-packages\warp\_src\context.py", line 7664, in launch_tiled
    return launch(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\a\newton\newton\.venv\Lib\site-packages\warp\_src\context.py", line 7465, in launch
    module_exec = kernel.module.load(device, block_dim)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\a\newton\newton\.venv\Lib\site-packages\warp\_src\context.py", line 3003, in load
    raise e
  File "D:\a\newton\newton\.venv\Lib\site-packages\warp\_src\context.py", line 3000, in load
    compiled = self._compile(device, module_dir, output_name, output_arch)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\a\newton\newton\.venv\Lib\site-packages\warp\_src\context.py", line 2825, in _compile
    raise (e)
  File "D:\a\newton\newton\.venv\Lib\site-packages\warp\_src\context.py", line 2804, in _compile
    cpp_file.write(cpp_source)
  File "C:\hostedtoolcache\windows\Python\3.12.10\x64\Lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UnicodeEncodeError: 'charmap' codec can't encode characters in position 2384-2438: character maps to <undefined>

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant