Skip to content

Fix ANYmal symmetry augmentation for non-PhysX joint orders - #8205

Merged
kellyguo11 merged 8 commits into
isaac-sim:developfrom
NeoZng:fix/anymal-symmetry-joint-order
Oct 8, 2026
Merged

kellyguo11 merged 8 commits into
isaac-sim:developfrom
NeoZng:fix/anymal-symmetry-joint-order

Conversation

@NeoZng

@NeoZng NeoZng commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Description

The ANYmal symmetry augmentation used by the rsl_rl_with_symmetry agents hard-coded joint indices for the PhysX joint order. The velocity tasks default to Newton, where ANYmal's native order is depth-first, so every mirrored joint observation and action came from the wrong joint.

This PR resolves the left-right and front-back permutations and signs from the robot's joint_names, using the ANYmal <L|R><F|H>_<HAA|HFE|KFE> naming, and feeds them into the cached permutation tables from #8105 (now keyed by joint order). The sign conventions are unchanged: HAA is negated for left-right, and HFE/KFE for front-back. With the PhysX order the tables equal the previous ones.

Resolving by name matches the ordering contract, where public order is backend-native unless joint_ordering is set, and works for any joint_ordering; ANYmal-B/C use the same joint names. Pinning joint_ordering="physx" in the task would add a per-step reorder on Newton and change the observation and action layout of existing Newton checkpoints.

Fixes #8204

Verification on Isaac-Velocity-Flat-AnymalD and Isaac-Velocity-Rough-AnymalD, on both PhysX and Newton, at the current head:

  • Wrong mirrored joints go from 12/12 to 0/12 on Newton, and stay at 0/12 on PhysX.
  • The physical mirror check (base-frame feet of the mirrored configuration against the mirrored feet) goes from 0.17-0.42 m to below 1e-5 m on Newton.
  • test_anymal_symmetry.py keeps the PhysX reference check from [Camera] Remove remaining hot-path host syncs and overhead [7B/7] #8105 and adds one check that the Newton order is mirrored like the PhysX order with the joint columns reordered; it fails on develop and passes with this change.
  • The per-call path is unchanged: one cached gather and multiply per transform.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Release backport

  • Backport this pull request to the active release branch after it merges into develop

Checklist

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks with uv run isaaclab --format
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have validated the changed behavior with focused coverage and applied the test-audit criteria to any test changes
  • I have added a changelog fragment under source/<pkg>/changelog.d/ for every touched package (do not edit CHANGELOG.rst or bump package versions — CI handles that)
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

The ANYmal symmetry augmentation hard-coded joint indices for the PhysX
joint order. On the default Newton backend the articulation uses a
depth-first joint order, so every mirrored joint observation and action
came from the wrong joint. Build the left-right and front-back
permutations and signs from the robot's joint names instead.
@NeoZng
NeoZng requested a review from a team September 30, 2026 18:39
@github-actions github-actions Bot added bug Something isn't working isaac-lab Related to Isaac Lab team labels Sep 30, 2026
@greptile-apps

greptile-apps Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[Medium risk] Fixes ANYmal robot symmetry augmentation for different physics backends.

The PR should not merge until the documented no-input call is preserved.

Findings

  1. P1 Default call now raises ▶

Summary

The PR replaces fixed PhysX joint indices in ANYmal symmetry augmentation with joint-name-derived permutations and adds coverage for PhysX and Newton orders.

  • The name-based mapping aligns with the configured joint observation and action order.
  • The new device-selection step breaks calls made with both optional inputs omitted.

Reviews (1) · Last reviewed commit: "Resolve ANYmal symmetry joint mirrors by..."

Comment thread source/isaaclab_tasks/isaaclab_tasks/core/velocity/mdp/symmetry/anymal.py Outdated

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Isaac Lab Review Bot

The name-derived symmetry maps correctly replace backend-specific joint indices and preserve the existing mirror composition, but the change breaks the valid no-input call path and introduces two style inconsistencies that should be cleaned up.

  • Design and architecture: Resolving permutations from the articulation’s joint names correctly assigns ordering ownership to the asset rather than duplicating a PhysX-specific index table. The diagonal transformation still composes front-back over left-right. The two direction-specific action helpers no longer own distinct behavior, however, and should be replaced by direct _switch_joints calls.
  • API: compute_symmetric_states retains its signature and 4x augmentation layout, while its private transform helpers consistently receive the resolved maps. Its public optional-argument contract is not fully preserved because calling it with both obs and actions omitted now fails instead of returning (None, None).
  • Compatibility and deprecation: Breaking changes: compute_symmetric_states(env) previously returned (None, None), consistent with both inputs being optional, but now dereferences actions.device when both inputs are omitted and raises AttributeError. No guard or deprecation bridge accompanies this regression; return early or defer map resolution into the consuming branches.
  • Implementation: The gather-and-multiply implementation returns fresh tensors, preserves the left-right and front-back sign conventions, and uses an immutable (joint_names, device) cache key with a clear lifetime. Add handling for the both-inputs-omitted path before selecting a device. The now-identical action forwarding helpers should be removed in favor of direct _switch_joints calls.
  • Style consistency: Two concrete contribution-guide inconsistencies remain: _transform_actions_left_right and _transform_actions_front_back are identical one-line wrappers around _switch_joints, contrary to the guidance against trivial forwarding helpers, and _ANYMAL_JOINT_NAME is defined after functions instead of in the constants section following imports.
  • Test quality: The new parametrized test provides focused regression coverage for both PhysX and Newton joint orders, checks observations and actions at the owning symmetry boundary, and derives expected results from independent mirror tables. It is not duplicated by the supplied existing tests. It does not cover the regressed call where both optional inputs are omitted.

Minor fixes needed. Posted 3 actionable findings inline.

Automated review; human maintainers own approval decisions.

Comment thread source/isaaclab_tasks/isaaclab_tasks/core/velocity/mdp/symmetry/anymal.py Outdated
Comment thread source/isaaclab_tasks/isaaclab_tasks/core/velocity/mdp/symmetry/anymal.py Outdated
Comment thread source/isaaclab_tasks/isaaclab_tasks/core/velocity/mdp/symmetry/anymal.py Outdated
NeoZng added 3 commits October 1, 2026 02:49
…fix/anymal-symmetry-joint-order

# Conflicts:
#	source/isaaclab_tasks/isaaclab_tasks/core/velocity/mdp/symmetry/anymal.py
#	source/isaaclab_tasks/test/core/test_anymal_symmetry.py
@NeoZng

NeoZng commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

Merged develop. #8105 turned these helpers into cached permutation tables that still assumed the PhysX joint order; the tables are now built from the robot's joint names, and the #8105 reference test runs unchanged on the PhysX order.

@NeoZng

NeoZng commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

Correction to my earlier replies: after merging develop, #8105's cached tables replaced the _switch_joints change, so the action wrappers are #8105's with a joint_names argument. bbd9ed9 also shortens the name lookup and replaces the mirror tables in the test with one check against the PhysX order.

@AntoineRichard AntoineRichard left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! Thanks for the fix @NeoZng

@kellyguo11

Copy link
Copy Markdown
Contributor

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Oct 7, 2026
@kellyguo11

Copy link
Copy Markdown
Contributor

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Oct 8, 2026
@kellyguo11
kellyguo11 merged commit abe7db4 into isaac-sim:develop Oct 8, 2026
59 checks passed
isaaclab-bot Bot pushed a commit that referenced this pull request Oct 8, 2026
## Description

The ANYmal symmetry augmentation used by the `rsl_rl_with_symmetry`
agents hard-coded joint indices for the PhysX joint order. The velocity
tasks default to Newton, where ANYmal's native order is depth-first, so
every mirrored joint observation and action came from the wrong joint.

This PR resolves the left-right and front-back permutations and signs
from the robot's `joint_names`, using the ANYmal
`<L|R><F|H>_<HAA|HFE|KFE>` naming, and feeds them into the cached
permutation tables from #8105 (now keyed by joint order). The sign
conventions are unchanged: HAA is negated for left-right, and HFE/KFE
for front-back. With the PhysX order the tables equal the previous ones.

Resolving by name matches the ordering contract, where public order is
backend-native unless `joint_ordering` is set, and works for any
`joint_ordering`; ANYmal-B/C use the same joint names. Pinning
`joint_ordering="physx"` in the task would add a per-step reorder on
Newton and change the observation and action layout of existing Newton
checkpoints.

Fixes #8204

Verification on `Isaac-Velocity-Flat-AnymalD` and
`Isaac-Velocity-Rough-AnymalD`, on both PhysX and Newton, at the current
head:
- Wrong mirrored joints go from 12/12 to 0/12 on Newton, and stay at
0/12 on PhysX.
- The physical mirror check (base-frame feet of the mirrored
configuration against the mirrored feet) goes from 0.17-0.42 m to below
1e-5 m on Newton.
- `test_anymal_symmetry.py` keeps the PhysX reference check from #8105
and adds one check that the Newton order is mirrored like the PhysX
order with the joint columns reordered; it fails on develop and passes
with this change.
- The per-call path is unchanged: one cached gather and multiply per
transform.

## Type of change

- Bug fix (non-breaking change which fixes an issue)

## Release backport

- [x] <!-- backport-active-release --> Backport this pull request to the
active release branch after it merges into `develop`

## Checklist

- [x] I have read and understood the [contribution
guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html)
- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`uv run isaaclab --format`
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have validated the changed behavior with focused coverage and
applied the [test-audit
criteria](https://github.com/isaac-sim/IsaacLab/blob/develop/skills/developer/test-audit/SKILL.md)
to any test changes
- [x] I have added a changelog fragment under
`source/<pkg>/changelog.d/` for every touched package (do **not** edit
`CHANGELOG.rst` or bump package versions — CI handles that)
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there

---------

Co-authored-by: Kelly Guo <kellyg@nvidia.com>

(cherry picked from commit abe7db4)
@isaaclab-bot

isaaclab-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Backported to release/3.0.0 as b9efdb7.

@NeoZng
NeoZng deleted the fix/anymal-symmetry-joint-order branch October 9, 2026 06:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug Report] ANYmal symmetry augmentation mirrors the wrong joints on the default Newton backend

5 participants