Skip to content

[release/3.0.0-beta2] Fix LEAPP projected gravity export#6079

Merged
AntoineRichard merged 1 commit into
isaac-sim:release/3.0.0-beta2from
lgulich:lgulich/backport-6007-3.0.0-beta2
Jun 10, 2026
Merged

[release/3.0.0-beta2] Fix LEAPP projected gravity export#6079
AntoineRichard merged 1 commit into
isaac-sim:release/3.0.0-beta2from
lgulich:lgulich/backport-6007-3.0.0-beta2

Conversation

@lgulich

@lgulich lgulich commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Backports #6007 to release/3.0.0-beta2.

This fixes LEAPP export for mdp.projected_gravity so the exported graph takes root_quat_w as the input and computes projected gravity inside the graph, instead of exporting projected gravity directly as an input.

Changes

  • Export mdp.projected_gravity through root_quat_w for LEAPP graphs.
  • Keep the policy observation as projected gravity by computing it inside the exported graph.
  • Add regression coverage and changelog fragments.

Testing

  • Red check: temporarily removed the projected-gravity dispatch and ran uv run --with pytest --with leapp python -m pytest source/isaaclab_rl/test/export/test_leapp_proxy.py -q -> failed as expected in test_projected_gravity_observation_exports_root_quat_w_input.
  • Green check: restored the fix and reran uv run --with pytest --with leapp python -m pytest source/isaaclab_rl/test/export/test_leapp_proxy.py -q -> 2 passed, 37 warnings.
  • uv run --with ruff --with leapp ruff check source/isaaclab/isaaclab/utils/leapp/export_annotator.py source/isaaclab/isaaclab/utils/leapp/proxy.py source/isaaclab_rl/test/export/test_leapp_proxy.py -> passed.
  • ./isaaclab.sh -f -> passed.

The current LEAPP export emits projected_gravity as an input instead of
root_quat_w. With Warp-backed observation terms, LEAPP can no longer
automatically trace projected gravity back to root_quat_w, so this
backport handles that mapping manually until LEAPP has Warp support.

Changes:
- Export mdp.projected_gravity through root_quat_w for LEAPP graphs.
- Keep the policy observation as projected gravity by computing it
  inside the exported graph.
- Add regression coverage and changelog fragments.

(cherry picked from commit 74f9e8e)
@github-actions github-actions Bot added the isaac-lab Related to Isaac Lab team label Jun 9, 2026
@lgulich lgulich requested a review from frlai June 9, 2026 17:54
@lgulich lgulich marked this pull request as ready for review June 9, 2026 17:54

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 Isaac Lab Review Bot — PR #6079

Title: [release/3.0.0-beta2] Fix LEAPP projected gravity export
Verdict: ✅ Looks Good (minor suggestions below)


Summary

Clean cherry-pick of #6007 that fixes the LEAPP export so mdp.projected_gravity exposes root_quat_w as the graph input boundary and computes projected gravity analytically inside the exported graph. The fix is necessary because the Warp-backed observation terms prevent LEAPP from automatically tracing back through the quaternion-to-gravity projection.


🔵 Suggestion: Inline quaternion math duplicates math_utils.quat_apply_inverse

File: source/isaaclab/isaaclab/utils/leapp/export_annotator.py (lines 469–476)

The rotation logic in _wrap_projected_gravity:

quat_xyz = root_quat_w[..., :3]
quat_w = root_quat_w[..., 3:4]
t = torch.cross(quat_xyz, gravity_w, dim=-1) * 2.0
return gravity_w - quat_w * t + torch.cross(quat_xyz, t, dim=-1)

is functionally identical to isaaclab.utils.math.quat_apply_inverse(root_quat_w, gravity_w). The inline version works correctly, but referencing the canonical utility would reduce duplication and make the quaternion convention dependency explicit.

Likely reason it's inlined: The export path may need torch-traceable ops without the reshape in quat_apply_inverse (which reshapes to (-1, 4) and views back). If traceability is the motivation, a brief comment explaining this would help future maintainers.


🔵 Suggestion: First positional arg (env) is silently consumed

File: source/isaaclab/isaaclab/utils/leapp/export_annotator.py (line 464)

def wrapped(*args, **kwargs):

The original mdp.projected_gravity(env, asset_cfg=...) passes env as args[0], but the wrapper never uses env. This is intentional (the wrapper bypasses the real env and uses proxy_env from the closure), and the test confirms it works. However, adding a brief inline comment like # args[0] is env, unused — we use proxy_env from closure would clarify this for future readers.


🔵 Suggestion: Consider adding @staticmethod consistency note

File: source/isaaclab/isaaclab/utils/leapp/export_annotator.py

_wrap_projected_gravity is correctly a @staticmethod (it doesn't use self), consistent with _wrap_with_proxy. Good.


✅ Architecture/Design

  • The backport is a clean cherry-pick from 74f9e8ec (develop #6007).
  • The dispatch in _patch_observation_manager correctly intercepts "projected_gravity" by function name, matching the pattern used for "last_action" and "generated_commands".
  • Noise is correctly nullified for all patched terms (line 299), which is appropriate for export (noise should not be traced into the deployment graph).

✅ Correctness

  • The quaternion math is correct: uses xyzw convention matching Isaac Lab's standard, and implements quat_apply_inverse(q, [0,0,-1]) identically to the canonical utility.
  • The test validates numerical equivalence against math_utils.quat_apply_inverse with a non-trivial rotation (90° about X axis), confirming the formula is sound.

✅ Test Coverage

  • New test file (test_leapp_proxy.py) provides two focused regression tests:
    1. Direct data proxy read preserves projected_gravity_b as its own VECTOR3D input
    2. Observation term export lowers through root_quat_w with BODY_ROTATION semantics
  • Both tests verify LEAPP annotation side effects (input name, kind, connection metadata).
  • The PR description shows manual red/green verification.

⚠️ CI Note

  • "Check for Broken Links" is failing — this appears pre-existing and unrelated to this PR's changes (no URLs were added/modified in source code).

Overall: This is a well-structured, minimal backport with good test coverage. The fix correctly bridges the gap between Warp-backed observation terms and LEAPP's tracing expectations.

@greptile-apps

greptile-apps Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This backport fixes the LEAPP export of mdp.projected_gravity so that the exported graph boundary exposes root_quat_w (body orientation) as its input, computing gravity projection inside the graph rather than passing an already-projected gravity vector directly.

  • export_annotator.py: Adds _wrap_projected_gravity as a @staticmethod and a new dispatch branch in _patch_observation_manager that matches on func.__name__ == "projected_gravity". The wrapper reads root_quat_w through the _EnvProxy_SceneProxy_EntityProxy_DataProxy chain (triggering the LEAPP BODY_ROTATION annotation) and then computes the inverse quaternion rotation in-graph using the standard Rodrigues formula to reproduce the projected gravity vector.
  • test_leapp_proxy.py: Adds two regression tests — one verifying that direct _DataProxy reads still expose projected gravity as a VECTOR3D input, and one verifying that the observation-manager patch correctly lowers to a BODY_ROTATION (root_quat_w) input with the gravity computation inlined.

Confidence Score: 5/5

Safe to merge — the change is self-contained and the core rotation math matches Isaac Lab's existing quat_apply_inverse reference implementation exactly.

The inverse quaternion rotation is correct and consistent with Isaac Lab's XYZW convention (confirmed by comparing with quat_apply_inverse in math.py). The proxy chain correctly routes through _DataProxy to trigger the LEAPP BODY_ROTATION annotation, and the cache/dedup mechanism is unaffected. Two regression tests cover both the direct-proxy path and the patched-observation path, including a numerical correctness check against the reference implementation.

No files require special attention.

Important Files Changed

Filename Overview
source/isaaclab/isaaclab/utils/leapp/export_annotator.py Adds _wrap_projected_gravity static method and dispatch branch; math is correct (inverse-rotation via Rodrigues), XYZW quaternion convention is consistent with the rest of Isaac Lab, and proxy chain correctly triggers LEAPP annotation.
source/isaaclab_rl/test/export/test_leapp_proxy.py New test file with two regression tests covering both the direct-proxy path and the patched-observation path; assertions validate shape, LEAPP semantics, noise nullification, and numerical correctness against quat_apply_inverse.
source/isaaclab/changelog.d/lgulich-leapp-root-quat-gravity.rst Changelog fragment describing the fix; content is accurate.
source/isaaclab_rl/changelog.d/lgulich-leapp-root-quat-gravity.skip Empty skip-marker file; intentional sentinel for the changelog tooling.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[_patch_observation_manager] --> B{func.__name__?}
    B -- last_action --> C[_wrap_last_action]
    B -- generated_commands --> D[_wrap_generated_commands]
    B -- projected_gravity --> E[_wrap_projected_gravity NEW]
    B -- other --> F[_wrap_with_proxy]
    E --> G[wrapped closure captures proxy_env]
    G --> H[resolve asset_name from asset_cfg, default robot]
    H --> I[proxy_env.scene.asset_name.data.root_quat_w.torch]
    I --> J[LEAPP annotate BODY_ROTATION input]
    J --> K[compute gravity_w = 0 0 -1 broadcast]
    K --> L[t = 2 x cross qxyz gravity_w]
    L --> M[return gravity_w minus qw x t plus cross qxyz t]
    M --> N[projected_gravity_b in body frame]
Loading

Reviews (1): Last reviewed commit: "Fix LEAPP projected gravity export (#600..." | Re-trigger Greptile

@AntoineRichard AntoineRichard merged commit 5f9fa3a into isaac-sim:release/3.0.0-beta2 Jun 10, 2026
60 of 62 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants