Skip to content

[API] Return ProxyArray from FrameView.get_scales#5712

Merged
hujc7 merged 2 commits into
isaac-sim:developfrom
hujc7:jichuanh/scales-proxyarray
Jun 2, 2026
Merged

[API] Return ProxyArray from FrameView.get_scales#5712
hujc7 merged 2 commits into
isaac-sim:developfrom
hujc7:jichuanh/scales-proxyarray

Conversation

@hujc7
Copy link
Copy Markdown
Collaborator

@hujc7 hujc7 commented May 20, 2026

Summary

  • Aligns BaseFrameView.get_scales with the pose getters: returns ProxyArray instead of raw wp.array across all four backends (USD, Fabric/PhysX, Newton, OvPhysX).
  • Removes the mixed-return-type surprise that bit users reading scales next to get_world_poses / get_local_poses.

1. Motivation

BaseFrameView.get_world_poses and get_local_poses already return ProxyArray (giving callers .warp and .torch accessors), but get_scales still returned a raw wp.array. The mixed contract surprised callers reading scales alongside poses; this PR aligns the three getters on a single return type.

2. Changes

2.1 Contract

  • BaseFrameView.get_scales return annotation changed from wp.array to ProxyArray; docstring updated. Class-level "getters return ProxyArray" doc broadened from "pose getters".

2.2 Backends

  • UsdFrameView.get_scales wraps the constructed wp.array in ProxyArray.
  • FabricFrameView.get_scales wraps the kernel output in ProxyArray and types the signature explicitly.
  • NewtonSiteFrameView.get_scales wraps the gathered output in ProxyArray.
  • OvPhysxFrameView.get_scales (delegating to UsdFrameView) updates the signature and docstring.

2.3 Internal call sites

  • FabricFrameView._sync_fabric_from_usd_once reads self._usd_view.get_scales().warp before feeding the array into set_scales — matches the existing .warp extraction pattern used for poses two lines above.

2.4 Tests

  • frame_view_contract_utils.test_return_types_are_torcharray extended to assert get_scales() and get_scales(indices) return ProxyArray — parallel to the existing pose-getter assertions.

3. Backward compatibility

Marked Breaking in the changelog fragments. Wider grep across source/ and scripts/ found no external callers of get_scales — only the internal FabricFrameView._sync_fabric_from_usd_once path (fixed in this PR). Downstream code that reads .numpy() directly on the previous return will need to extract .warp first; code that already uses the deprecation bridge or wp.to_torch(...) is unaffected.

4. Test plan

  • ./isaaclab.sh -f (pre-commit) — clean.
  • Import smoke for the four backend modules.
  • CI: contract tests across USD / Fabric / Newton backends.

BaseFrameView.get_scales returned a raw wp.array while get_world_poses
and get_local_poses returned ProxyArray. The mixed contract surprised
consumers reading scales alongside poses; align the three getters on
ProxyArray.

Update the USD, Fabric, Newton, and OvPhysX backends to wrap their
returns. The Fabric FabricFrameView -> UsdFrameView sync path now
extracts .warp before feeding the array to set_scales.

Extend the FrameView contract test to assert get_scales returns
ProxyArray, parallel to the existing pose assertions.
@github-actions github-actions Bot added the isaac-lab Related to Isaac Lab team label May 20, 2026
Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

🤖 Automated Code Review

PR: [API] Return ProxyArray from FrameView.get_scales
Commit: b128323


✅ Summary

This PR aligns get_scales() with the existing pose getters by returning ProxyArray instead of raw wp.array. The change improves API consistency across all four backends (USD, Fabric/PhysX, Newton, OvPhysX).


🏗️ Architecture Assessment

Strengths:

  • Consistent return type across all BaseFrameView implementations
  • Follows the established pattern from get_world_poses() and get_local_poses()
  • Clean delegation in OvPhysxFrameView.get_scales() — the method just returns the underlying UsdFrameView result, which now correctly propagates the ProxyArray

Implementation Notes:

  • UsdFrameView: Wraps the constructed wp.array in ProxyArray at the end ✓
  • FabricFrameView: Wraps kernel output appropriately ✓
  • NewtonSiteFrameView: Wraps gathered output ✓
  • OvPhysxFrameView: Signature updated, delegates correctly ✓

🔍 Code Quality

Aspect Status Notes
Type annotations Return types updated to ProxyArray
Docstrings Updated to reference ProxyArray with proper Sphinx cross-refs
Class-level docs "Pose getters" → "All getters" language updated across backends
Internal call sites FabricFrameView._sync_fabric_from_usd_once extracts .warp correctly

🧪 Test Coverage

Good:

  • test_return_types_are_torcharray extended to cover get_scales() and get_scales(indices)
  • Test comment updated to reflect "pose and scale getters"

Suggestions:

  • Consider adding a round-trip test verifying set_scales(view.get_scales().warp) works correctly
  • The test name test_return_types_are_torcharray is now slightly misleading since it tests ProxyArray — consider renaming to test_return_types_are_proxyarray in a follow-up

📋 Changelog Fragments

All four packages have proper changelog entries:

  • isaaclab/changelog.d/jichuanh-scales-proxyarray.rst
  • isaaclab_newton/changelog.d/jichuanh-scales-proxyarray.rst
  • isaaclab_ovphysx/changelog.d/jichuanh-scales-proxyarray.rst
  • isaaclab_physx/changelog.d/jichuanh-scales-proxyarray.rst

Breaking change is clearly documented with migration guidance.


⚠️ Breaking Change Impact

The PR correctly identifies this as a breaking change. The impact is:

  • Code calling .numpy() directly on the return value will break → use .warp.numpy() or .torch.numpy()
  • Code using wp.to_torch(result) is unaffected (can use .torch accessor instead)
  • Code passing directly to Warp kernels or set_scales() needs .warp extraction

The grep audit finding no external callers in source/ and scripts/ is reassuring.


🚦 CI Status

  • Pre-commit: ✅ Passing
  • Changelog check: ✅ Passing
  • Build wheel: ✅ Passing
  • Docs build: ⏳ Pending
  • Contract tests: ⏳ Pending (awaiting CI infrastructure)

📝 Minor Suggestions (Non-blocking)

  1. FabricFrameView.get_scales (line 281): The method has type hints in the signature but the scales and indices parameters in set_scales (line 274) don't — consider adding them for consistency in a follow-up.

  2. Test naming: test_return_types_are_torcharraytest_return_types_are_proxyarray would be more accurate.


✅ Verdict

Looks good to merge once CI completes. The implementation is clean, consistent with the existing codebase patterns, well-documented, and properly tested. The breaking change is appropriately flagged with clear migration guidance.

@hujc7 hujc7 marked this pull request as ready for review May 20, 2026 19:57
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 20, 2026

Greptile Summary

This PR aligns BaseFrameView.get_scales with the existing pose-getter contract by wrapping the raw wp.array return value in ProxyArray across all four backends (USD, Fabric/PhysX, Newton, OvPhysX). The internal FabricFrameView._sync_fabric_from_usd_once call site is updated to extract .warp from the new ProxyArray, mirroring the existing pattern for poses.

  • All four backend get_scales implementations now wrap their wp.array output in ProxyArray before returning, and type annotations are updated accordingly.
  • FabricFrameView._sync_fabric_from_usd_once correctly unpacks .warp from the new return type, consistent with how get_world_poses() results are handled two lines above.
  • Contract tests are extended to assert ProxyArray return types for both get_scales() and get_scales(indices) across all backends.

Confidence Score: 4/5

The change is a clean, consistent wrapping of raw wp.array returns in ProxyArray across all backends; the one internal call site that consumed the raw array is correctly updated to extract .warp.

The wrapping is mechanical and symmetrical across backends. The only finding is that the updated class-level docstrings now say "All getters return ProxyArray" while get_visibility continues to return torch.Tensor, which is a minor documentation inaccuracy rather than a runtime defect.

The class-level docstrings in base_frame_view.py, usd_frame_view.py, newton_site_frame_view.py, and ovphysx_frame_view.py — they all state that all getters return ProxyArray, which does not hold for get_visibility.

Important Files Changed

Filename Overview
source/isaaclab/isaaclab/sim/views/base_frame_view.py Abstract signature updated from wp.array to ProxyArray; docstring broadened from "pose getters" to "getters" — slightly overclaims since get_visibility still returns torch.Tensor.
source/isaaclab/isaaclab/sim/views/usd_frame_view.py Wraps constructed wp.array in ProxyArray before returning; clean two-liner change with no logic alterations.
source/isaaclab_physx/isaaclab_physx/sim/views/fabric_frame_view.py Adds type annotations to get_scales, wraps return in ProxyArray, and correctly extracts .warp in _sync_fabric_from_usd_once to match the pattern used for poses two lines above.
source/isaaclab_newton/isaaclab_newton/sim/views/newton_site_frame_view.py Wraps kernel output out in ProxyArray before returning; consistent with pose-getter pattern in the same class.
source/isaaclab_ovphysx/isaaclab_ovphysx/sim/views/ovphysx_frame_view.py Delegates to UsdFrameView.get_scales, which now returns ProxyArray; signature and docstring updated to match.
source/isaaclab/test/sim/frame_view_contract_utils.py Contract test extended with ProxyArray assertions for get_scales() and get_scales(indices), mirroring the existing pose-getter assertions.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["get_scales(indices)"] --> B{Backend?}
    B -- "USD" --> C["UsdFrameView\n build wp.array from USD xformOp:scale\n wrap in ProxyArray"]
    B -- "Fabric/PhysX" --> D{use_fabric?}
    D -- "No" --> C
    D -- "Yes" --> E["FabricFrameView\n launch Warp kernel → scales_wp\n wrap in ProxyArray"]
    B -- "Newton" --> F["NewtonSiteFrameView\n launch Warp kernel → out\n wrap in ProxyArray"]
    B -- "OvPhysX" --> G["OvPhysxFrameView\n delegate to UsdFrameView"]
    G --> C
    C --> H["ProxyArray\n .warp → wp.array\n .torch → torch.Tensor"]
    E --> H
    F --> H

    style H fill:#d4edda,stroke:#28a745
Loading

Reviews (1): Last reviewed commit: "Return ProxyArray from FrameView.get_sca..." | Re-trigger Greptile

implementation at runtime based on the active physics backend.

All pose getters return :class:`~isaaclab.utils.warp.ProxyArray`. Setters accept ``wp.array``.
All getters return :class:`~isaaclab.utils.warp.ProxyArray`. Setters accept ``wp.array``.
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.

P2 Docstring overclaims ProxyArray for all getters

The class docstring was changed from "All pose getters" to "All getters", but get_visibility (across all backends) still returns torch.Tensor, not ProxyArray. Any reader relying on this class-level contract to infer the return type of get_visibility will be misled. The same inaccuracy propagates to the matching docstring updates in UsdFrameView, NewtonSiteFrameView, and OvPhysxFrameView.

@pbarejko pbarejko self-requested a review May 28, 2026 17:01
@kellyguo11 kellyguo11 moved this to Ready to merge in Isaac Lab May 28, 2026
…oxyarray

# Conflicts:
#	source/isaaclab_newton/isaaclab_newton/sim/views/newton_site_frame_view.py
Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

🤖 Automated Code Review (Updated)

PR: [API] Return ProxyArray from FrameView.get_scales
Commit: e29cc29


✅ Summary

Clean, well-scoped API consistency PR. Aligns get_scales() with the existing pose getters by returning ProxyArray instead of raw wp.array across all four backends. The merge conflict in newton_site_frame_view.py was resolved correctly.


🏗️ Architecture & Correctness

All backends implement the contract correctly:

  • UsdFrameView: Wraps constructed wp.array in ProxyArray
  • FabricFrameView (Fabric path): Wraps kernel output in ProxyArray
  • FabricFrameView (USD fallback): Delegates to UsdFrameView.get_scales() which already returns ProxyArray — no double-wrapping ✓
  • NewtonSiteFrameView: Wraps gathered output in ProxyArray
  • OvPhysxFrameView: Delegates to UsdFrameView — propagation correct ✓

Internal call site fix:
FabricFrameView._sync_fabric_from_usd_once correctly extracts .warp before passing to set_scales(), matching the existing pattern for pose data two lines above. ✓


⚠️ Findings

1. Inconsistent class docstring in FabricFrameView (Minor)

base_frame_view.py, usd_frame_view.py, and ovphysx_frame_view.py all updated their class-level docstrings from "Pose getters" to "Getters" (or "All getters"). However, fabric_frame_view.py still reads:

Pose getters return :class:`~isaaclab.utils.warp.ProxyArray`.  Setters accept ``wp.array``.

This should be updated to match the other backends for consistency.

2. Test function name is now misleading (Nitpick)

test_return_types_are_torcharray now asserts ProxyArray for poses and scales. The name suggests it tests for TorchArray. Consider renaming to test_return_types_are_proxyarray in a follow-up for clarity.


🧪 Test Coverage

Good:

  • Contract test extended with get_scales() and get_scales(indices) assertions
  • Parametrized across cpu and cuda:0 devices

Suggestion (non-blocking):

  • A round-trip test (set_scales(view.get_scales().warp, ...) followed by verify) would exercise the exact path fixed in _sync_fabric_from_usd_once and guard against future regressions.

📋 Changelog & Breaking Change

All four packages have correct changelog fragments with clear migration guidance. The breaking-change classification is appropriate.


🚦 CI Status

  • Pre-commit: ✅ Passing
  • Changelog check: ✅ Passing
  • Build wheel: ✅ Passing
  • Remaining checks: ⏳ Pending

✅ Verdict

Looks good to merge once CI completes. Only one minor inconsistency (Finding #1 — the FabricFrameView class docstring) is worth fixing before merge. The rest are non-blocking suggestions for follow-up.

self._fabric_usd_sync_done = True

def get_scales(self, indices=None):
def get_scales(self, indices: wp.array | None = None) -> ProxyArray:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nit: The class-level docstring (line 22 of this file) still says Pose getters return :class:~isaaclab.utils.warp.ProxyArray`` — should be updated to Getters return for consistency with `BaseFrameView`, `UsdFrameView`, and `OvPhysxFrameView` which were all updated in this PR.

@hujc7 hujc7 merged commit ccc098c into isaac-sim:develop Jun 2, 2026
37 checks passed
@github-project-automation github-project-automation Bot moved this from Ready to merge to Done in Isaac Lab Jun 2, 2026
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

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants