Skip to content

[FEATURE] Add relative quaternion getter#2764

Closed
Travor278 wants to merge 1 commit into
Genesis-Embodied-AI:mainfrom
Travor278:feature/get-quat-relative
Closed

[FEATURE] Add relative quaternion getter#2764
Travor278 wants to merge 1 commit into
Genesis-Embodied-AI:mainfrom
Travor278:feature/get-quat-relative

Conversation

@Travor278
Copy link
Copy Markdown

@Travor278 Travor278 commented May 6, 2026

Description

Adds a keyword-only relative parameter to KinematicEntity.get_quat(). When relative=True, the method returns the base link orientation relative to the entity's initial quaternion. The default remains relative=False, so existing calls to get_quat() and get_quat(envs_idx) keep returning the same absolute quaternion as before.

The relative getter mirrors the existing set_quat(..., relative=True) behavior by using the same initial base-link quaternion reference as the setter, including per-environment initial quaternions for heterogeneous variants. The returned quaternion satisfies abs_quat == transform_quat_by_quat(init_quat, delta).

Related Issue

Resolves #2730

Motivation and Context

set_quat() already supports applying quaternions relative to the initial orientation, which is useful for domain randomization and RL observation pipelines. Without the matching getter, users have to manually track the initial quaternion and repeat the inverse-composition math in their own scripts.

This change makes the API more symmetric, reduces boilerplate quaternion math for users, and keeps the absolute-orientation getter as the backwards-compatible default.

How Has This Been / Can This Be Tested?

The root-pose coverage now checks both the new relative path and the old absolute path:

  • get_quat(relative=True) returns the expected relative quaternion after both relative and absolute set_quat() calls.
  • get_quat(relative=False) matches get_quat(), preserving the previous default behavior.

Additional regression coverage verifies that:

  • heterogeneous variants with different initial quaternions use the per-environment initial pose as the relative reference;
  • envs_idx subsetting keeps the relative getter aligned with the selected environments;
  • non-parallel scene paths return quaternion-shaped relative results, including batch_links_info=True;
  • attached entities without a free-root quaternion slot use the link initial orientation reference instead of reading unrelated qpos0 entries.

Validated locally with Python 3.12.13:

D:\Dev\conda-envs\py312\python.exe -m pytest tests/test_rigid_physics.py::test_get_quat_relative_heterogeneous_initial_quat tests/test_rigid_physics.py::test_get_quat_relative_non_parallel tests/test_rigid_physics.py::test_get_quat_relative_non_parallel_batched_link_info tests/test_rigid_physics.py::test_set_root_pose -q --numprocesses=0
D:\Dev\conda-envs\py312\python.exe -m pytest tests/test_rigid_physics.py::test_merge_entities -q --numprocesses=0

Results:

  • selected quaternion/root-pose cases: 7 passed
  • tests/test_rigid_physics.py::test_merge_entities: 4 passed

Checklist:

  • I read the CONTRIBUTING document.
  • I followed the Submitting Code Changes section of CONTRIBUTING document.
  • I tagged the title correctly (including BUG FIX/FEATURE/MISC/BREAKING)
  • I updated the documentation accordingly or no change is needed.
  • I tested my changes and added instructions on how to test it for reviewers.
  • I have added tests to cover my changes.

@Travor278 Travor278 changed the title Add relative quaternion getter [FEATURE] Add relative quaternion getter May 6, 2026
@Travor278 Travor278 marked this pull request as ready for review May 6, 2026 17:53
@chatgpt-codex-connector
Copy link
Copy Markdown

💡 Codex Review

init_quat = torch.as_tensor(self.base_link.quat, dtype=abs_quat.dtype, device=abs_quat.device)

P1 Badge Compute relative quat from per-env initial pose

get_quat(relative=True) currently uses self.base_link.quat as the reference, but that is a single static quaternion from the primary morph. In heterogeneous simulations, each environment can have a different initial root quaternion via per-variant init_qpos (stored in solver qpos0), and set_quat(..., relative=True) composes against that per-env initial pose. This makes the new getter return wrong relative quaternions for non-primary variants and breaks the expected symmetry between relative set/get in those environments.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Travor278 Travor278 force-pushed the feature/get-quat-relative branch from c6236e1 to f6a4cb1 Compare May 7, 2026 02:41
@Travor278
Copy link
Copy Markdown
Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f6a4cb1da1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1390 to +1396
init_quat = qd_to_torch(
self._solver.qpos0,
envs_idx,
slice(q_start + 3, q_start + 7),
transpose=True,
copy=True,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve unbatched quaternion shape in relative getter

When scene.build() is used without parallel envs (n_envs == 0) and the base link is not fixed, this branch pulls init_quat from qpos0 without removing the singleton env dimension. abs_quat is 1D in this mode, so transform_quat_by_quat(...) returns a (1, 4) tensor instead of (4,), which breaks the documented/output shape parity with get_quat() and can cause silent broadcasting bugs in downstream quaternion math.

Useful? React with 👍 / 👎.

@Travor278 Travor278 force-pushed the feature/get-quat-relative branch from f6a4cb1 to 05673df Compare May 7, 2026 02:57
@Travor278
Copy link
Copy Markdown
Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 05673df30d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1389 to +1394
q_start = self.base_link.q_start
init_quat = qd_to_torch(
self._solver.qpos0,
envs_idx,
slice(q_start + 3, q_start + 7),
transpose=True,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Handle attached fixed-base entities in relative quaternion getter

When relative=True, this branch assumes any non-fixed base link has a free-root quaternion in qpos0, but attach() can flip base_link.is_fixed to False for originally fixed-base entities attached to a non-fixed parent (see link._is_fixed &= parent_link.is_fixed). In that case the base link does not have a root quaternion slot, so slice(q_start + 3, q_start + 7) reads unrelated qpos0 entries (or from an invalid start), producing incorrect relative quaternions for attached entities. This regression is new because the previous get_quat() only returned absolute state and did not depend on q_start.

Useful? React with 👍 / 👎.

@Travor278 Travor278 force-pushed the feature/get-quat-relative branch from 05673df to 0e19ff4 Compare May 7, 2026 03:11
@Travor278
Copy link
Copy Markdown
Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0e19ff4258

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

copy=True,
)
if self._solver.n_envs == 0:
init_quat = init_quat[0]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Remove residual link axis in single-env relative get_quat

When relative=True and batch_links_info=True in a non-parallel scene (n_envs == 0), this branch keeps an extra link dimension ((1, 4)) instead of reducing to (4,). The subsequent quaternion composition broadcasts against abs_quat and returns (1, 4), which violates the documented single-environment return shape and can break consumers that expect a flat quaternion. Squeeze both env and link axes here (for example, index both dimensions) before calling inv_quat.

Useful? React with 👍 / 👎.

@Travor278 Travor278 force-pushed the feature/get-quat-relative branch from 0e19ff4 to 6386ad7 Compare May 7, 2026 03:25
@Travor278
Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Travor278
Copy link
Copy Markdown
Author

Superseded by #2765 with the same final patch in a clean review thread.

@Travor278 Travor278 closed this May 7, 2026
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.

[Feature]: Add get_quat(..., relative=True)

1 participant