Featherstone Origin-Offset Stability Report

Investigation of the tricycle NaN triggered by world-origin-referenced Featherstone internals for floating-base articulations far from the origin.

Generated 2026-06-06 10:54:32 PDT (PT) from CUDA runs on NVIDIA GeForce RTX 4090. Current branch baseline: 1cd4196dc. Fresh origin/main: a046d6131.

Example

The origin-offset probe drives a small floating-base tricycle near the origin while an identical copy follows the same controls 100 m away.

Current branch first non-finite sample
1600
origin/main first non-finite sample
1650
Patched frames completed
2500
Recommended fix: for articulations rooted by FREE or DISTANCE joints, express Featherstone-only scratch quantities in a translated solve frame whose origin is the root body COM and whose axes remain world-aligned. Public State.body_qd, State.body_f, Control.joint_f, and State.body_parent_f remain COM/world-frame quantities.

Reproduction

I first ran test_final() for newton/examples/robot/example_robot_tricycle_origin_offset.py much longer than the registered 20-frame example test. With --far-offset 100 and 2000 frames, the current branch failed because body_q contained non-finite values. A per-frame probe found the first bad frame at 1594 in the exact example path; the reusable benchmark sampled the same failure at frame 1600.

The failure is not that the public generalized mass matrix is visibly large in every branch. In this branch, changes around free-joint COM coordinates keep H small for longer, but the internal spatial Jacobian J and block spatial mass M still carry absolute world-origin moment arms. At frame 1575 on the branch baseline, far |J| is about 306 and far |M| is about 842,808 before becoming non-finite.

What Changed

Results

Code state Long-run frames First non-finite frame far max |J| far max |M| last finite root error last finite local error warm-cache speed
origin/main a046d613116501650314.4068.870e+056.880 m0.006 m35.512 FPS
branch baseline 1cd4196dc16001600306.4878.428e+055.784 m0.023 m43.481 FPS
patched working tree2500none1.0009.0005.450 m0.029 m43.427 FPS
Far internal spatial mass magnitude -1995261250197527008.87e+055.01e+042.83e+03159.469.00 frame max |M| origin/mainbranch baselinepatched
Far internal spatial Jacobian magnitude -199526125019752700314.4174.6717.734.211.00 frame max |J| origin/mainbranch baselinepatched
Near-vs-far root displacement error -1995261250197527007.435.443.441.44-0.55 frame error [m] origin/mainbranch baselinepatched

Interpretation

The patch removes the numerical scale-up in the Featherstone internals for the floating tricycle. In the patched run, far |J| stays around 1 and far |M| stays around 9 through 2500 frames, even when the far root reaches 614.260 m.

The long contact-rich trajectory is still not translation-invariant to the original 0.25 m tolerance at every horizon. The root displacement error oscillates and later grows, while local body layout remains small (0.029 m at frame 2500). That remaining drift appears contact/trajectory sensitive rather than a renewed internal-matrix blow-up: the internal matrices remain bounded and finite.

Alternatives Considered

Verification

Files