Skip to content

[OVPHYSX] FrameTransformer sensor #5320

@AntoineRichard

Description

@AntoineRichard

Summary

Implement `FrameTransformer` and `FrameTransformerData` for the OVPhysX backend, satisfying the `BaseFrameTransformer` and `BaseFrameTransformerData` contracts. Computes relative transforms between a source frame and multiple target frames attached to rigid bodies.

Validation environment: `Isaac-Lift-Cube-Franka-v0` — tracks Franka end-effector pose relative to robot base.

Scope

  • `frame_transformer.py` (~500 lines), `frame_transformer_data.py` (~150 lines), `kernels.py` (~100 lines)
  • Complex initialization (frame resolution, index mapping, offset precomputation)
  • Simple update (single transform fetch + kernel launch)

OVPhysX API Question

How to read transforms for arbitrary bodies (not just root) from ovphysx? The Articulation's `ARTICULATION_BODY_POSE` binding returns all link poses — FrameTransformer needs to index into specific links. @marcodiiga to clarify.

Dependencies

Spec

Full design spec: `docs/superpowers/specs/2026-04-20-ovphysx-frame-transformer-design.md`

Parent issue: #5315


📋 Full Design Spec (click to expand)

OVPhysX FrameTransformer Sensor — Design Spec

Issue: #5320 — [OVPHYSX] FrameTransformer sensor
Date: 2026-04-20
Status: Draft

Summary

Implement FrameTransformer and FrameTransformerData for the OVPhysX backend, satisfying the BaseFrameTransformer and BaseFrameTransformerData contracts. Computes relative transforms between a source frame and multiple target frames attached to rigid bodies. Only requires body transforms (no velocities or accelerations).

Validation environment: Isaac-Lift-Cube-Franka-v0 (manager-based) — uses FrameTransformer to track end-effector pose relative to robot base. Also validates #5322 (manipulation support).

Contract to Satisfy

BaseFrameTransformer

Inherits SensorBase. Additional abstract:

Property/Method Type Description
data BaseFrameTransformerData Transform data
num_bodies int Number of target frames (deprecated)
body_names list[str] Target frame names (deprecated)
_initialize_impl() method Resolve frames, build index maps
_update_buffers_impl(env_mask) method Fetch transforms, compute relative poses

BaseFrameTransformerData

Property Shape Type Description
target_frame_names list[str] Names of target frames
target_pose_source (N, M) wp.transformf Target pose relative to source
target_pos_source (N, M) wp.vec3f Target position relative to source
target_quat_source (N, M) wp.quatf Target orientation relative to source
target_pose_w (N, M) wp.transformf Target pose in world frame (with offset)
target_pos_w (N, M) wp.vec3f Target world position
target_quat_w (N, M) wp.quatf Target world orientation
source_pose_w (N,) wp.transformf Source pose in world frame (with offset)
source_pos_w (N,) wp.vec3f Source world position
source_quat_w (N,) wp.quatf Source world orientation

Where N=num_envs, M=num_target_frames.

Architecture

File Layout

source/isaaclab_ovphysx/isaaclab_ovphysx/sensors/
└── frame_transformer/
    ├── __init__.py
    ├── __init__.pyi
    ├── frame_transformer.py       (~500 lines)
    ├── frame_transformer_data.py  (~150 lines)
    └── kernels.py                 (~100 lines)

Implementation Pattern

frame_transformer.py:

  1. _initialize_impl() (most complex part):

    • Resolve source prim path and verify rigid body exists
    • Resolve all target frame prim paths and verify rigid bodies
    • Compute fixed offsets for source and target frames (once)
    • Build body tracking: create a combined view of all tracked rigid bodies
    • Build per-env index arrays:
      • _source_raw_indices: maps env → position in raw transform array
      • _target_raw_indices: maps (env, frame) → position in raw transform array
    • Pre-compute offset arrays as GPU warp arrays
    • Allocate output buffers
  2. _update_buffers_impl(env_mask):

    • Read all tracked body transforms from ovphysx bindings (single batched read)
    • Launch frame_transformer_update_kernel with 2D grid (num_envs, num_target_frames):
      • Fetch source transform by index, apply source offset
      • Fetch target transform by index, apply target offset
      • Compute relative: target_relative = source_inverse * target_offset
      • Store 6 outputs (source and target poses in world + relative)

OVPhysX API Requirements

API Purpose Notes
Body transforms Rigid body poses for all tracked frames Available via existing bindings

No new ovphysx APIs needed — only body transforms are required, which are already available through existing Articulation and (future) RigidObject bindings.

The key implementation question is how to create a single batched view spanning multiple distinct body paths. In PhysX, RigidBodyView accepts a glob expression. For ovphysx, the approach depends on whether TensorBindings can be queried by body index within an articulation, or whether a separate mechanism is needed.

Question for @marcodiiga: How to read transforms for arbitrary bodies (not just the root) from ovphysx? The Articulation's ARTICULATION_BODY_POSE binding returns all link poses — FrameTransformer needs to index into specific links by name.

Warp Kernels

Kernel Purpose
frame_transformer_update_kernel 2D launch (env, frame): offset application + relative transform computation

Tests

Source: source/isaaclab_physx/test/sensors/test_frame_transformer.py
Target: source/isaaclab_ovphysx/test/sensors/test_frame_transformer.py

Validation

Isaac-Lift-Cube-Franka-v0:

  • FrameTransformer tracks Franka end-effector relative to base
  • Verify source/target poses match expected robot kinematics
  • Verify relative transforms are consistent with forward kinematics

Dependencies

  • Requires PR ovphysx backend integration #4852 merged
  • No new ovphysx APIs needed (uses body transforms from Articulation bindings)
  • Independent of other sensor specs — can be implemented in parallel

Estimated Scope

  • frame_transformer.py: ~500 lines (initialization is complex, update is simple)
  • frame_transformer_data.py: ~150 lines
  • kernels.py: ~100 lines
  • Tests: ~200 lines of adaptations

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions