Conversation
scipy Rotation.from_euler("XYZ", ...) is the intrinsic (rotating-frame)
convention R = Rx @ Ry @ Rz, while DROID stores euler angles in the
extrinsic fixed-frame "xyz" convention R = Rz(yaw) @ Ry(pitch) @ Rx(roll)
(see droid/misc/transformations.py in the DROID codebase). Only the
extrinsic convention matches tfg.rotation_matrix_3d.from_euler and the
eef_9d statistics of the released pretrained checkpoints, so the previous
code reconstructed a different rotation per timestep.
- gr00t/data/state_action/droid_frame.py: use scipy "xyz" (lowercase)
and document the load-bearing convention difference.
- examples/DROID/main_gr00t.py: sync the vendored mirror.
- scripts/verify_droid_rotation_correction.py: verify against "xyz".
- scripts/download_droid_sample.py: clarify the euler convention comment.
- demo_data/droid_sample: regenerate eef_9d columns and stats with the
corrected convention (raw cartesian_position columns untouched).
- tests: pin the extrinsic convention and guard the vendored mirror.
Author
|
cc. @ryhalabi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Rotation.from_euler("XYZ", ...)in scipy is the intrinsic (rotating-frame) conventionR = Rx @ Ry @ Rz, but DROID stores euler angles in the extrinsic fixed-framexyzconventionR = Rz(yaw) @ Ry(pitch) @ Rx(roll)(seedroid/misc/transformations.py, which usesR.from_euler("xyz", ...)/.as_euler("xyz")throughout). The extrinsic convention is also whattfg.rotation_matrix_3d.from_eulercomputes (R = Rz @ Ry @ Rx).The current code used uppercase
"XYZ"while documenting it as "extrinsic" and "equivalent to tfg" — the comment and the call contradicted each other. Since the two conventions produce different rotation matrices for the same angle triple (median ~46° of angular distortion on real DROID data), the pipeline reconstructed the wrong eef rotation per timestep, and it did not match theeef_9dstatistics of the released pretrained checkpoints (nvidia/GR00T-N1.7-3B,nvidia/GR00T-N1.7-DROID— computed under the extrinsic/tfg convention).Changes
gr00t/data/state_action/droid_frame.py: switch to scipy"xyz"(lowercase) and document why the spelling is load-bearing.examples/DROID/main_gr00t.py: sync the vendored mirror (dataset builder / real-robot client).scripts/verify_droid_rotation_correction.py: verify against the extrinsic convention.scripts/download_droid_sample.py: clarify the convention comment.demo_data/droid_sample: regenerateeef_9dcolumns andmeta/stats.json/meta/relative_stats.jsonwith the corrected convention (rawcartesian_positioncolumns are untouched; non-eef_9dstats dimensions are byte-identical).tests/gr00t/data/state_action/test_droid_frame.pypins the extrinsic/tfg convention (and asserts the intrinsic one differs);tests/examples/test_droid.pygains an AST guard that the vendored mirror stays in sync.Verification
pytest tests/gr00t/data/state_action/test_droid_frame.py tests/examples/test_droid.py -m "not gpu": 14 passed.eef_9dequalsR.from_euler("xyz", euler) @ DROID_EEF_ROTATION_CORRECTexactly for all timesteps.ruff check/ruff formatclean on all touched files.Note
This restores the convention used by the DROID example before commit
c5cadf5(which switched the inference client from"xyz"to"XYZ"based on the incorrect scipy/tfg equivalence claim). Anyone who has post-trained with the interim convention should regenerate their processed dataset with the updated scripts.