Skip to content

Rotate a rotated inertial origin's tensor and a rotated prismatic origin's translation; pinocchio oracle over every fixture - #7

Merged
plancherb1 merged 2 commits into
mainfrom
inertial-origin-rotation
Oct 17, 2026
Merged

plancherb1 merged 2 commits into
mainfrom
inertial-origin-rotation

Conversation

@plancherb1

Copy link
Copy Markdown
Member

Two rotation-direction bugs found through the UR5e, and a pinocchio oracle over every fixture so this class cannot recur silently.

Rotated inertial origin. Link.build_spatial_inertia applied the parallel-axis term for an <inertial><origin> translation but never the origin's rotation, so a tensor written in a rotated inertial frame was taken as if it were in the link frame. The link-frame tensor is E^T I E with the parser's Featherstone E = R^T, equivalently R I R^T with URDF's R = Rz Ry Rx. On the UR5e, whose shoulder and wrists use rpy of plus or minus pi/2 about x, the generated dynamics were 7 to 10 percent off pinocchio on every inertia probe. None of GRiD's ten shipped robots rotates an inertial origin, so every shipped header regenerates byte-identical.

Prismatic joint with a rotated origin. The single-DOF homogeneous transform rotated the joint's variable translation by E instead of E^T, mirroring a prismatic joint's child whenever its <origin> carries a rotation. The 6x6 motion transforms, and so the dynamics, were right; only the homogeneous path used by the end-effector pose was wrong. GRiD's one shipped instance, fr3_finger_joint2, has a yaw of pi whose rotation is its own transpose, which is why no receipt could see it.

Oracle. tests/test_inertia_oracle.py checks every fixture pinocchio's URDF reader can build: each body's mass, first moment and tensor about the joint origin against model.inertias, with fixed-joint children folded on both sides and a decomposed planar joint mapped through its link's frame, and each joint frame's world placement at random configurations, with continuous joints fed as (cos, sin) and a decomposed planar joint as pinocchio's [x, y, cos, sin]. The oracle is built from the URDF with every rpy snapped to the quarter-turn grid the parser snaps joint origins to, the way RBDReference's pinocchio backend does, so both sides model the same robot. Fixtures with no URDF oracle are listed statically with the reason: helical, spherical and translation joints are parser extensions, and pinocchio's URDF reader ignores a planar joint's axis. A new fixture, rotated_inertial_arm.urdf, has rotated and offset inertial origins with full tensors, a prismatic joint with a rotated origin, a massive child behind a fixed joint and hyphenated joint names.

Verification: 87 tests pass with pinocchio 3.9.0; GRiD's CPU lane passes against this branch with the same oracle over its ten shipped robots.

🤖 Generated with Claude Code

… a prismatic joint's translation through its origin; pinocchio oracle over every fixture
@plancherb1
plancherb1 merged commit 6971656 into main Oct 17, 2026
1 check passed
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