Skip to content

Add shared kinematic rigid-object renderer contract - #6308

Merged
kellyguo11 merged 2 commits into
isaac-sim:developfrom
ooctipus:ooctipus/kinematic-rigid-object-rendering-test
Sep 4, 2026
Merged

Add shared kinematic rigid-object renderer contract#6308
kellyguo11 merged 2 commits into
isaac-sim:developfrom
ooctipus:ooctipus/kinematic-rigid-object-rendering-test

Conversation

@ooctipus

@ooctipus ooctipus commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Description

Revives #6308 on current develop and supersedes #3728 with a single backend-neutral contract for kinematic rigid-object rendering.

Architecture

source/isaaclab/test/renderers/rigid_object_rendering_contract.py is the composition root. It owns the cloned scene, kinematic pose sequence, depth measurements, and assertions. Package-local adapters own only availability checks, simulation/renderer selection, and backend cleanup:

  • Isaac RTX + PhysX on CPU and CUDA, with and without a coexisting articulation;
  • Newton Warp + PhysX on CUDA;
  • OVRTX + OVPhysX on CUDA through both legacy and OVStage scene ownership (OVStage runs when installed).

The dependency direction is adapter -> shared test contract -> public Isaac Lab APIs. An AST architecture gate rejects backend imports in the shared contract and rejects scene, asset, sensor, or class ownership in adapters.

The contract creates two cloned instanceable DexCubes with root-level nonuniform scale, verifies their depth silhouettes, moves both kinematic bodies through the public rigid-object tensor API, verifies the physics poses, and requires opposite rendered centroid displacement.

Current-develop audit

Most production changes in the old PR have since landed through newer ownership boundaries: Isaac RTX render-product lifetime in #6729, Newton shadow-state copying in #6773, OVRTX scale-aware transform writes in #7010, and Newton Fabric scale preservation in #7481. This revival removes those stale patches rather than carrying duplicate implementations.

The revived contract exposed one remaining OVRTX bug: composed scale was captured only for clone-plan source paths, while OVRTX creates non-source destinations after exporting the host USD stage. Those destinations therefore defaulted to unit scale. As a deliberately temporary bridge, this PR projects only captured non-unit scales through the existing isaaclab.cloner.query.path_env_ids and path_to_clone boundary using the already-validated ClonePlan; real destination scales take precedence. It adds no plan fields, query APIs, renderer configuration, or per-body fallback, and the bridge can be deleted as one unit when SDP supplies composed scale aligned with canonical rigid-body paths.

Historical context: Isaac Sim forum report.

Type of change

  • Bug fix
  • Shared regression coverage

Testing

  • Isaac RTX contract: 4 passed (CUDA/CPU x articulation absent/present).
  • Newton Warp contract: 1 passed.
  • OVRTX contract: 2 passed (legacy and OVStage).
  • OVRTX renderer unit surface: 167 passed.
  • Core architecture and Newton visualization suites: 25 passed.
  • OVRTX clone-plan suite: 17 passed.
  • Cloner query and rendering-contract architecture suites: 87 passed.
  • Controlled OVRTX regression: failed before the production fix with clone silhouettes of 264 vs. 36 pixels; passed after the fix.
  • Incoming Route clone backends through ClonePlan #7462 NumPy-backed ClonePlan query-boundary smoke check: passed unchanged, including non-dense environment ids.
  • uv run isaaclab -f: all hooks passed against the exact upstream develop base, including changelog validation.

Checklist

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks
  • Documentation changes are not applicable
  • I have added unit and integration regression coverage
  • I have added changelog fragments for every touched package
  • My name is already present in CONTRIBUTORS.md

@github-actions github-actions Bot added the isaac-lab Related to Isaac Lab team label Jul 1, 2026
@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a regression test for the PhysX/Fabric-to-RTX synchronization bug affecting kinematic rigid bodies (Isaac Sim 5.0), verifying that both non-uniform root scale and public pose writes are correctly reflected in the rendered depth output.

  • Adds test_isaac_rtx_renderer_kinematic_rigid_object.py under the renderer integration suite, parametrized over cuda:0/cpu × articulation absent/present (4 variants), using regex-cloned instanceable DexCubes with root-level Z-scale=8 to confirm scale preservation and centroid displacement after pose writes.
  • Adds an empty .skip changelog fragment, intentionally suppressing a changelog entry for this test-only change.

Confidence Score: 4/5

This is a test-only addition with no runtime or API changes; it is safe to merge.

The test correctly uses the public write_root_pose_to_sim_index / root_link_pose_w APIs, follows the established single-frame RTX capture pattern used throughout the renderer test suite, and properly cleans up RTX resources in a finally block. The two findings are purely stylistic: a missing type hint on the sim parameter of _write_pose_and_render, and a bare assert inside a non-test helper where pytest's assertion rewriting may not produce the richest failure output.

No files require special attention — both changed files are straightforward.

Important Files Changed

Filename Overview
source/isaaclab_physx/test/renderers/test_isaac_rtx_renderer_kinematic_rigid_object.py New regression test for PhysX/Fabric-to-RTX synchronization with kinematic rigid objects; well-structured, uses correct public APIs, with two minor style issues (missing type hint for sim, bare assert in a non-test helper)
source/isaaclab_physx/changelog.d/kinematic-rigid-object-rendering-test.skip Empty .skip changelog fragment — intentionally suppresses a changelog entry for this test-only PR

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant T as Test
    participant RO as RigidObject (PhysX)
    participant Sim as SimulationContext
    participant Cam as Camera (RTX)

    T->>Sim: build_simulation_context(device)
    T->>RO: spawn kinematic cubes (scale 1,1,8)
    T->>Cam: spawn pinhole camera
    T->>Sim: sim.reset()
    T->>Cam: set_world_poses_from_view(eyes, targets)

    Note over T,Cam: Scale check
    T->>RO: write_root_pose_to_sim_index(center_poses)
    T->>Sim: sim.step()
    T->>RO: rigid_object.update(dt)
    T->>Cam: camera.update(dt)
    T->>RO: assert root_link_pose_w ≈ center_poses
    Cam-->>T: center_depth
    T->>T: "assert height > 3x width (scale preserved)"

    Note over T,Cam: Centroid-shift check
    T->>RO: write_root_pose_to_sim_index(negative_poses)
    T->>Sim: sim.step()
    Cam-->>T: negative_depth → negative_centroids
    T->>RO: write_root_pose_to_sim_index(positive_poses)
    T->>Sim: sim.step()
    Cam-->>T: positive_depth → positive_centroids
    T->>T: "assert shift > 10px and opposite directions"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant T as Test
    participant RO as RigidObject (PhysX)
    participant Sim as SimulationContext
    participant Cam as Camera (RTX)

    T->>Sim: build_simulation_context(device)
    T->>RO: spawn kinematic cubes (scale 1,1,8)
    T->>Cam: spawn pinhole camera
    T->>Sim: sim.reset()
    T->>Cam: set_world_poses_from_view(eyes, targets)

    Note over T,Cam: Scale check
    T->>RO: write_root_pose_to_sim_index(center_poses)
    T->>Sim: sim.step()
    T->>RO: rigid_object.update(dt)
    T->>Cam: camera.update(dt)
    T->>RO: assert root_link_pose_w ≈ center_poses
    Cam-->>T: center_depth
    T->>T: "assert height > 3x width (scale preserved)"

    Note over T,Cam: Centroid-shift check
    T->>RO: write_root_pose_to_sim_index(negative_poses)
    T->>Sim: sim.step()
    Cam-->>T: negative_depth → negative_centroids
    T->>RO: write_root_pose_to_sim_index(positive_poses)
    T->>Sim: sim.step()
    Cam-->>T: positive_depth → positive_centroids
    T->>T: "assert shift > 10px and opposite directions"
Loading

Reviews (1): Last reviewed commit: "Add kinematic rigid object rendering reg..." | Re-trigger Greptile

Comment on lines +118 to +133
return silhouette_heights, silhouette_widths, centroids_x


def _write_pose_and_render(sim, rigid_object: RigidObject, camera: Camera, root_poses: torch.Tensor) -> torch.Tensor:
"""Write a rigid-object pose, advance one frame, and return rendered depth."""
rigid_object.write_root_pose_to_sim_index(root_pose=root_poses)
sim.step()
rigid_object.update(sim.cfg.dt)
camera.update(sim.cfg.dt)
torch.testing.assert_close(
rigid_object.data.root_link_pose_w.torch,
root_poses,
rtol=0.0,
atol=1.0e-4,
)
return camera.data.output["distance_to_image_plane"].torch.clone()

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 Missing type annotation for sim parameter

The _write_pose_and_render helper is missing a type hint for sim, while rigid_object, camera, and root_poses are all annotated. Downstream tools (e.g. mypy, pyright) and any future callers have no signal about what concrete type is expected — a stale usage passing the wrong context won't be caught statically.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +101 to +116
)
)
return rigid_object, articulation, camera


def _measure_depth_mask(depth: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
"""Return the silhouette height, width, and horizontal centroid for each camera."""
valid = torch.isfinite(depth[..., 0]) & (depth[..., 0] < _MAX_OBJECT_DEPTH)
pixel_counts = valid.sum(dim=(1, 2))
assert torch.all(pixel_counts >= _MIN_OBJECT_PIXELS), (
f"Expected at least {_MIN_OBJECT_PIXELS} object pixels per camera, got {pixel_counts.tolist()}."
)

silhouette_heights = valid.any(dim=2).sum(dim=1)
silhouette_widths = valid.any(dim=1).sum(dim=1)
image_x = torch.arange(depth.shape[2], device=depth.device, dtype=torch.float32)

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 Bare assert in non-test helper function may lose context on failure

_measure_depth_mask is a plain function (not a test), so pytest's assertion introspection / rewriting doesn't apply when it is called from within _write_pose_and_render (which is itself also a plain helper). If pixel_counts fails the minimum-pixel guard, the only output is the f-string message — there's no captured locals, diff view, or surrounding context that pytest normally provides for assertions in test bodies. Consider using pytest.fail or raising a descriptive AssertionError explicitly, or annotating the function with inline comments explaining that assertion rewriting applies only to direct test-function bodies.

@ooctipus ooctipus moved this to In progress in Isaac Lab Jul 1, 2026
@ooctipus ooctipus changed the title Add RTX regression test for kinematic rigid objects Add shared kinematic rigid-object renderer contract Jul 1, 2026
@ooctipus
ooctipus requested a review from kellyguo11 as a code owner July 3, 2026 23:25
ooctipus added a commit that referenced this pull request Jul 6, 2026
# Description

Since #6314 landed, `test-isaaclab-ov` and
`test-rendering-correctness-kitless` are silently skipped on every fork
PR: the job-level `if:` conditions require a same-repository PR (or
`develop`) whenever `ovphysx_wheelhouse_resource` is configured — which
it now always is. Fork contributors and team members working from forks
have had zero OVRTX / kitless rendering CI coverage since then, with no
visible signal (the jobs just show "skipped").

The NGC trust boundary is correct (the wheelhouse download needs
`NGC_API_KEY`, which fork PRs cannot access), and this PR keeps it
intact — the `USE_OVPHYSX_WHEELHOUSE` env var from #6314 already
resolves trust per run, and the NGC download step is gated on
`wheelhouse-resource != ''`, so it never executes without credentials.

This PR's own CI (it is a fork PR, and PR runs use the merge-commit
workflow, so it exercises its own fix) established exactly which
coverage is recoverable on the public pip stack:

- **All `isaaclab_ov` (ovrtx) tests pass** with pip-index `ovrtx` +
`ovphysx` — 0 failures.
- **All 562 `isaaclab_ovphysx` test failures are one error**:
`AttributeError: type object 'PhysX' has no attribute 'set_cpu_mode'` —
`ovphysx_manager` now requires ovphysx ≥ 0.5.1, which only exists in the
NGC wheelhouse; the newest public wheel is 0.4.13.

ovrtx does not depend on ovphysx, so the fallback separates them at the
finest granularity each job allows:

- `test-isaaclab-ov` **runs on fork PRs** via the pip fallback with
`exclude-pattern: isaaclab_ovphysx` (file-level — the two packages live
in separate test trees; the shared `filter-pattern: "isaaclab_ov"` only
bundles them by prefix match).
- `test-rendering-correctness-kitless` **runs on fork PRs** with a new
`test-k-expr` input that reaches the per-file pytest subprocesses
spawned by `tools/conftest.py` (param-level: `not ovphysx` — the
golden-image files parametrize physics backends inside each file, so
fork runs keep the `newton + ovrtx` combinations and deselect only the
ovphysx-backed params).
- Trusted runs (same-repo PRs to `develop`, post-merge `develop`) are
byte-for-byte unchanged.

Once ovphysx ≥ 0.5.1 is published to the public pip index, the exclude
and the `-k` deselect can both be dropped and fork PRs regain full
parity.

cc @AntoineRichard#6314's description says "Do not merge; this PR
exists only for CI validation", so flagging in case the fork-PR skip
wasn't meant to reach `develop` in this form at all.

Fixes the coverage gap observed on #6308, where the OVRTX-variant jobs
skip on every attempt.

## Type of change

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

## 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
`./isaaclab.sh --format`
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there
matthewtrepte pushed a commit to matthewtrepte/IsaacLab that referenced this pull request Aug 4, 2026
…m#6348)

# Description

Since isaac-sim#6314 landed, `test-isaaclab-ov` and
`test-rendering-correctness-kitless` are silently skipped on every fork
PR: the job-level `if:` conditions require a same-repository PR (or
`develop`) whenever `ovphysx_wheelhouse_resource` is configured — which
it now always is. Fork contributors and team members working from forks
have had zero OVRTX / kitless rendering CI coverage since then, with no
visible signal (the jobs just show "skipped").

The NGC trust boundary is correct (the wheelhouse download needs
`NGC_API_KEY`, which fork PRs cannot access), and this PR keeps it
intact — the `USE_OVPHYSX_WHEELHOUSE` env var from isaac-sim#6314 already
resolves trust per run, and the NGC download step is gated on
`wheelhouse-resource != ''`, so it never executes without credentials.

This PR's own CI (it is a fork PR, and PR runs use the merge-commit
workflow, so it exercises its own fix) established exactly which
coverage is recoverable on the public pip stack:

- **All `isaaclab_ov` (ovrtx) tests pass** with pip-index `ovrtx` +
`ovphysx` — 0 failures.
- **All 562 `isaaclab_ovphysx` test failures are one error**:
`AttributeError: type object 'PhysX' has no attribute 'set_cpu_mode'` —
`ovphysx_manager` now requires ovphysx ≥ 0.5.1, which only exists in the
NGC wheelhouse; the newest public wheel is 0.4.13.

ovrtx does not depend on ovphysx, so the fallback separates them at the
finest granularity each job allows:

- `test-isaaclab-ov` **runs on fork PRs** via the pip fallback with
`exclude-pattern: isaaclab_ovphysx` (file-level — the two packages live
in separate test trees; the shared `filter-pattern: "isaaclab_ov"` only
bundles them by prefix match).
- `test-rendering-correctness-kitless` **runs on fork PRs** with a new
`test-k-expr` input that reaches the per-file pytest subprocesses
spawned by `tools/conftest.py` (param-level: `not ovphysx` — the
golden-image files parametrize physics backends inside each file, so
fork runs keep the `newton + ovrtx` combinations and deselect only the
ovphysx-backed params).
- Trusted runs (same-repo PRs to `develop`, post-merge `develop`) are
byte-for-byte unchanged.

Once ovphysx ≥ 0.5.1 is published to the public pip index, the exclude
and the `-k` deselect can both be dropped and fork PRs regain full
parity.

cc @AntoineRichardisaac-sim#6314's description says "Do not merge; this PR
exists only for CI validation", so flagging in case the fork-PR skip
wasn't meant to reach `develop` in this form at all.

Fixes the coverage gap observed on isaac-sim#6308, where the OVRTX-variant jobs
skip on every attempt.

## Type of change

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

## 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
`./isaaclab.sh --format`
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there
@ooctipus
ooctipus force-pushed the ooctipus/kinematic-rigid-object-rendering-test branch from d7577df to 0174e13 Compare September 3, 2026 05:32
@ooctipus
ooctipus requested a review from a team September 3, 2026 05:32
@ooctipus

ooctipus commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

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 Sep 3, 2026
@ooctipus

ooctipus commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

I would make #6308 a deliberately temporary, deletable bridge—using today’s ClonePlan without adding any new plan fields or APIs.

Use the existing query boundary and pass the already-required plan explicitly:

from isaaclab.cloner import ClonePlan
from isaaclab.cloner import query as clone_query

def _capture_object_scales(self, stage: Any, plan: ClonePlan) -> None:
...
for source_path, scale in tuple(self._object_scales_by_path.items()):
for env_id in clone_query.path_env_ids(plan, source_path):
clone_path = clone_query.path_to_clone(plan, source_path, env_id)
assert clone_path is not None
self._object_scales_by_path.setdefault(clone_path, scale)

Call it only after prepare_stage() has validated the plan:

self._capture_object_scales(stage, self._clone_plan)

Why this transition is clean:

  • It works with the current Torch-backed plan and the incoming NumPy plan unchanged; /home/zhengyuz/Projects/IsaacLab.wt/northstar-pr3a/source/isaaclab/isaaclab/cloner/query.py:120 hide that representation.
  • Nested, heterogeneous, partial-environment, and non-dense layouts retain the cloner’s nearest-owner semantics.
  • setdefault() preserves a destination scale already captured from the real stage.
  • There is no silent missing-plan fallback.
  • It adds no ClonePlan.scales, ScaleMap, new query function, or renderer configuration.
  • The extra work remains sparse: scenes without non-unit scales perform no projection.

I would not resolve every object path through path_to_source() inside _create_object_scale_array(). Although visually flatter, it queries every rigid body in every environment. A host-only 4,096×48-body check cost roughly one second, including completely unscaled bodies. Source-side
projection only touches captured non-unit scales.

For testing, keep the cross-backend rendered contract. Change the focused OVRTX unit test to assert the resulting scale array for source and destination bodies, rather than asserting the private dictionary’s exact contents. That lets the temporary cache disappear later without
preserving its implementation.

The later SDP cutover should replace the whole bridge:

Plan completion: exact rigid-body paths + composed scales
Physics: native pose pointer + dirty
OVRTX: requests TransposedMatrix44d
SDP: pose + composed scale → matrix in one conversion
OVRTX: writes that pointer directly

Importantly, future FrameLayout.scale currently records only local xformOp:scale; the final conversion needs composed scale aligned with the canonical rigid-body paths. Once that exists, delete _capture_object_scales, _object_scales_by_path, and the destination projection together.

That version can merge before or after #7462 and should transition without another mechanical rewrite.

@ooctipus

ooctipus commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added the ci:run-docker Trigger the on-demand Docker and GPU CI workflow label Sep 4, 2026
@isaaclab-bot isaaclab-bot Bot removed the ci:run-docker Trigger the on-demand Docker and GPU CI workflow label Sep 4, 2026
@ooctipus

ooctipus commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

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 Sep 4, 2026
@kellyguo11
kellyguo11 merged commit ab34e8c into isaac-sim:develop Sep 4, 2026
83 of 112 checks passed
@github-project-automation github-project-automation Bot moved this from In progress to Done in Isaac Lab Sep 4, 2026
kellyguo11 added a commit that referenced this pull request Sep 4, 2026
# Description

Restores the missing `torch` import in `test_ovrtx_clone_plan.py`.

#7462 converted the existing clone-plan test inputs from Torch tensors
to NumPy arrays and removed the then-unused import. #6308 subsequently
added a new object-scale test using `torch.ones` and `torch.arange`
without restoring the import, causing the repository-wide Ruff
pre-commit check to fail with `F821 Undefined name torch`.

This PR contains only the import repair and an `isaaclab_ov` `.skip`
changelog fragment. It unblocks #7579 and other changes based on the
current `develop` branch.

## Type of change

- Bug fix (non-breaking test fix)

## Release backport

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

No release backport is required: `release/3.0.0` already imports `torch`
in this test.

## Screenshots

Not applicable.

## Testing

- `uv run --no-project --with pre-commit python -m pre_commit run
--all-files`
- `uv run --no-project python tools/changelog/cli.py check
--include-worktree`
- `git diff --check upstream/develop...HEAD`

## Checklist

- [x] I have read and understood the contribution guidelines
- [x] I have run the full pre-commit checks
- [x] Documentation changes are not required because no public API
changed
- [x] My changes generate no new warnings
- [x] The fix directly covers the Ruff `F821` failure
- [x] I have added an `isaaclab_ov` changelog fragment
- [x] My name already exists in `CONTRIBUTORS.md`
@ooctipus
ooctipus deleted the ooctipus/kinematic-rigid-object-rendering-test branch September 4, 2026 19:48
kellyguo11 added a commit that referenced this pull request Sep 5, 2026
#7587)

# Description

Backports #6308 to `release/3.0.0`.

The canonical merged commit `ab34e8c5e3ee7a2c5f260d1511714e5be3bed3eb`
was cherry-picked with `-x` provenance. Eleven of its twelve source
paths replay exactly.
`source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py` required a
localized release-compatible conflict resolution, so this PR is
intentionally a draft for release-maintainer review.

| Field | Commit |
|---|---|
| Original merged change | `ab34e8c5e3ee7a2c5f260d1511714e5be3bed3eb` |
| Release base used | `1c754876008f0806fdcfda8e3a6b2f593b34d6fc` |
| Proposed backport | `740e3d7b2efe15c5a25f671583d29c034602e36f` |

## Conflict resolution

The release renderer already contains the prerequisite work from #6729,
#6773, #7010, and #7481, but differs from the source parent around
clone-plan handling and method documentation.

The resolution preserves the release branch's tensor-backed `ClonePlan`
validation and existing renderer structure, then adds only #6308's
semantic change:

- imports the existing `isaaclab.cloner.query` API;
- passes the validated release clone plan into `_capture_object_scales`;
- projects captured non-unit source scales to active clone destinations
with `path_env_ids` and `path_to_clone`;
- retains real destination scales via `setdefault`.

No paths outside the original PR are changed.

## Type of change

- Bug fix
- Shared regression coverage

## Validation

- Repository backport candidate validation passed across all 12 original
source paths.
- Per-file stable patch IDs match on 11 paths; only the
conflict-resolved renderer path differs.
- Shared rendering-contract architecture tests — 2 passed.
- Focused clone-query tests for `path_env_ids` and `path_to_clone` — 4
passed.
- Python compilation passed for all changed Python files.
- All changed-file pre-commit hooks passed, including changelog and Git
LFS checks.
- `git diff --check upstream/release/3.0.0...HEAD` passed.
- The focused OVRTX runtime test was retried with the documented `ov`
extra, but the release lock has no macOS/arm64 environment. Backend
rendering tests and the canonical `uv run isaaclab -f` remain pending
Linux CI.

## Checklist

- [x] I have read and understood the contribution guidelines
- [x] I have run the available pre-commit checks
- [x] Documentation changes are not applicable
- [x] The original unit and integration regression coverage is preserved
- [x] Changelog fragments are preserved for every touched package
- [x] The original contributor is already listed in `CONTRIBUTORS.md`

Co-authored-by: ooctipus <zhengyuz@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

infrastructure isaac-lab Related to Isaac Lab team

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants