Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
7edca7a
ray caster to warp transition
pascal-roth Mar 12, 2026
2a131fa
Merge branch 'develop' into dev/ray-caster-warp
pascal-roth Apr 9, 2026
9c7d194
Convert ray caster sensors to Warp kernels
pascal-roth Apr 9, 2026
258b17c
Address code review feedback on Warp ray caster conversion
pascal-roth Apr 9, 2026
fc07afe
Eliminate duplication and fix cross-class behavioral divergence
pascal-roth Apr 9, 2026
d1c4d4e
formatter
pascal-roth Apr 10, 2026
7ab8ee5
Consolidate changelog entries into a single 4.5.28 entry
pascal-roth Apr 10, 2026
5282458
Consolidate single-mesh masked ray-cast into one kernel in utils/warp
pascal-roth Apr 10, 2026
37b7b9c
Consolidate changelog into single PR entry at 4.5.28
pascal-roth Apr 10, 2026
6712db9
Add direct unit tests for raycast_mesh_masked_kernel return flags and…
pascal-roth Apr 10, 2026
b922cf0
Fix sentinel-based assertions in raycast_mesh_masked_kernel tests
pascal-roth Apr 10, 2026
93be93a
Harden sentinel assertions in raycast_mesh_masked_kernel tests
pascal-roth Apr 10, 2026
e73f77d
Add regression tests for quat_yaw_only correctness with non-zero pitc…
pascal-roth Apr 10, 2026
8e06c21
Fix inaccurate docstring in test_quat_yaw_only_pure_yaw
pascal-roth Apr 10, 2026
696104d
Add sensor-level tests for RayCaster alignment modes and reset drift
pascal-roth Apr 10, 2026
b7ac08b
Fix critical bugs in alignment mode tests: wp.to_torch, sign, toleran…
pascal-roth Apr 10, 2026
027ddf2
Add depth clipping independence test for simultaneous d2ip + d2c
pascal-roth Apr 10, 2026
6608b35
Remove redundant local import copy in depth clipping independence test
pascal-roth Apr 10, 2026
112d7e4
Add frame counter increment and set_intrinsic_matrices warp refresh t…
pascal-roth Apr 10, 2026
e93efae
Restore accidentally deleted d2c clipping assertion in Task 4 test
pascal-roth Apr 10, 2026
976784d
Add test for MultiMeshRayCasterCamera image_mesh_ids correctness
pascal-roth Apr 10, 2026
5b12678
Harden image_mesh_ids test: require hit_mask.any() and document clipp…
pascal-roth Apr 10, 2026
f71e26c
Fix test bugs found in final code review
pascal-roth Apr 10, 2026
a5507ff
Merge branch 'develop' into dev/ray-caster-warp
pascal-roth Apr 10, 2026
38c2cf2
Restore valid comments removed during warp kernel refactor
pascal-roth Apr 10, 2026
871f342
Merge branch 'dev/ray-caster-warp' of github.com:pascal-roth/IsaacLab…
pascal-roth Apr 13, 2026
ab81608
Address PR review comments
pascal-roth Apr 13, 2026
d37dd74
Revert torch.Tensor API fix; document wp.array return as intentional …
pascal-roth Apr 13, 2026
2ee89c2
ray caster to warp transition
pascal-roth Mar 12, 2026
7adef4e
Convert ray caster sensors to Warp kernels
pascal-roth Apr 9, 2026
aa710a3
Address code review feedback on Warp ray caster conversion
pascal-roth Apr 9, 2026
32d53c3
Eliminate duplication and fix cross-class behavioral divergence
pascal-roth Apr 9, 2026
34b5101
formatter
pascal-roth Apr 10, 2026
4ed8f26
Consolidate changelog entries into a single 4.5.28 entry
pascal-roth Apr 10, 2026
7917ebe
Consolidate single-mesh masked ray-cast into one kernel in utils/warp
pascal-roth Apr 10, 2026
b921111
Consolidate changelog into single PR entry at 4.5.28
pascal-roth Apr 10, 2026
f68f252
Add direct unit tests for raycast_mesh_masked_kernel return flags and…
pascal-roth Apr 10, 2026
50548e3
Fix sentinel-based assertions in raycast_mesh_masked_kernel tests
pascal-roth Apr 10, 2026
3c9dfdb
Harden sentinel assertions in raycast_mesh_masked_kernel tests
pascal-roth Apr 10, 2026
eb30038
Add regression tests for quat_yaw_only correctness with non-zero pitc…
pascal-roth Apr 10, 2026
d07d0ec
Fix inaccurate docstring in test_quat_yaw_only_pure_yaw
pascal-roth Apr 10, 2026
61ccf99
Add sensor-level tests for RayCaster alignment modes and reset drift
pascal-roth Apr 10, 2026
3ca66ae
Fix critical bugs in alignment mode tests: wp.to_torch, sign, toleran…
pascal-roth Apr 10, 2026
adf4c48
Add depth clipping independence test for simultaneous d2ip + d2c
pascal-roth Apr 10, 2026
9281dc4
Remove redundant local import copy in depth clipping independence test
pascal-roth Apr 10, 2026
8977a89
Add frame counter increment and set_intrinsic_matrices warp refresh t…
pascal-roth Apr 10, 2026
e95500f
Restore accidentally deleted d2c clipping assertion in Task 4 test
pascal-roth Apr 10, 2026
d609a1a
Add test for MultiMeshRayCasterCamera image_mesh_ids correctness
pascal-roth Apr 10, 2026
8916e9d
Harden image_mesh_ids test: require hit_mask.any() and document clipp…
pascal-roth Apr 10, 2026
f6406b0
Fix test bugs found in final code review
pascal-roth Apr 10, 2026
3f3d995
Address PR review: restore API, fix debug vis, add masked kernel
pascal-roth Apr 15, 2026
61cf5b5
Resolve merge conflicts with upstream main
pascal-roth Apr 16, 2026
929e166
Add kernel unit tests, integration tests, and fix frame composition bug
AntoineRichard Apr 20, 2026
9ba27d9
Merge remote-tracking branch 'origin/develop' into dev/ray-caster-warp
AntoineRichard Apr 20, 2026
a48440d
Merge remote-tracking branch 'origin/develop' into dev/ray-caster-warp
AntoineRichard Apr 21, 2026
e5c7250
Key warp mesh cache by (prim_path, device) to prevent cross-device reuse
AntoineRichard Apr 21, 2026
63331e3
Remove leftover merge conflict marker in CHANGELOG.rst
AntoineRichard Apr 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ For more information about the framework, please refer to the `technical report


License
=======
========

The Isaac Lab framework is open-sourced under the BSD-3-Clause license,
with certain parts under Apache-2.0 license. Please refer to :ref:`license` for more details.
Expand Down
109 changes: 109 additions & 0 deletions docs/source/migration/migrating_to_isaaclab_3-0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,14 @@ Common patterns that need updating:
- ``isaaclab_physx``
* - :class:`~isaaclab_physx.sensors.FrameTransformer`
- ``isaaclab_physx``
* - :class:`~isaaclab.sensors.RayCaster`
- ``isaaclab``
* - :class:`~isaaclab.sensors.RayCasterCamera`
- ``isaaclab``
* - :class:`~isaaclab.sensors.MultiMeshRayCaster`
- ``isaaclab``
* - :class:`~isaaclab.sensors.MultiMeshRayCasterCamera`
- ``isaaclab``

.. note::

Expand All @@ -974,6 +982,107 @@ Common patterns that need updating:
already passed to warp-native functions) should not be wrapped.


Ray Caster Warp Backend
~~~~~~~~~~~~~~~~~~~~~~~

The :class:`~isaaclab.sensors.RayCaster`, :class:`~isaaclab.sensors.RayCasterCamera`,
:class:`~isaaclab.sensors.MultiMeshRayCaster`, and
:class:`~isaaclab.sensors.MultiMeshRayCasterCamera` sensors have been transitioned from a
PyTorch/USD-based backend to a native Warp kernel pipeline. This improves performance by
eliminating per-step tensor allocations and torch-to-warp conversions, but introduces several
breaking changes.


RayCasterData Return Types
--------------------------

The :attr:`~isaaclab.sensors.RayCasterData.pos_w`,
:attr:`~isaaclab.sensors.RayCasterData.quat_w`, and
:attr:`~isaaclab.sensors.RayCasterData.ray_hits_w` properties now return ``wp.array`` instead of
``torch.Tensor``. This follows the same pattern as the general warp backend migration described
above.

.. code-block:: python

import warp as wp

# Before (Isaac Lab 2.x)
ray_hits = ray_caster.data.ray_hits_w # torch.Tensor
sensor_pos = ray_caster.data.pos_w # torch.Tensor

# After (Isaac Lab 3.x)
ray_hits = ray_caster.data.ray_hits_w # wp.array
sensor_pos = ray_caster.data.pos_w # wp.array

# To use with torch operations, wrap with wp.to_torch()
ray_hits_torch = wp.to_torch(ray_caster.data.ray_hits_w)
sensor_pos_torch = wp.to_torch(ray_caster.data.pos_w)


Ray Alignment Configuration
----------------------------

The ``attach_yaw_only`` boolean parameter on :class:`~isaaclab.sensors.RayCasterCfg` has been
deprecated in favor of the new ``ray_alignment`` parameter, which accepts one of three string
values:

.. list-table::
:header-rows: 1
:widths: 30 30 40

* - Old (2.x)
- New (3.0)
- Behavior
* - ``attach_yaw_only=False``
- ``ray_alignment="base"``
- Rays follow the full sensor orientation.
* - ``attach_yaw_only=True``
- ``ray_alignment="yaw"``
- Rays follow only the yaw component of the sensor orientation.
* - *(not available)*
- ``ray_alignment="world"``
- Rays are always cast in the world frame (no rotation applied).

.. code-block:: python

# Before (Isaac Lab 2.x)
cfg = RayCasterCfg(attach_yaw_only=True, ...)

# After (Isaac Lab 3.x)
cfg = RayCasterCfg(ray_alignment="yaw", ...)


Raycasting Kernel Signature Change
-----------------------------------

The :func:`~isaaclab.utils.warp.kernels.raycast_dynamic_meshes_kernel` Warp kernel now requires
an ``env_mask`` parameter as its first argument. This is a ``wp.array(dtype=wp.bool)`` that
controls which environments are updated. The public Python wrapper
:func:`~isaaclab.utils.warp.ops.raycast_dynamic_meshes` has been updated to inject an all-True
mask automatically, so code using the wrapper is unaffected.

If you call the kernel directly, update your launch call:

.. code-block:: python

import warp as wp

# Before (Isaac Lab 2.x)
wp.launch(
raycast_dynamic_meshes_kernel,
dim=(num_meshes, num_envs, num_rays),
inputs=[ray_starts, ray_directions, mesh_ids, ...],
)

# After (Isaac Lab 3.x) -- env_mask is now the first input
env_mask = wp.ones(num_envs, dtype=wp.bool, device=device)
wp.launch(
raycast_dynamic_meshes_kernel,
dim=(num_meshes, num_envs, num_rays),
inputs=[env_mask, ray_starts, ray_directions, mesh_ids, ...],
)


Write Method Index/Mask Split
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion docs/source/testing/index.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. _testing:

Testing
=======
========

This section covers testing utilities and patterns for Isaac Lab development.

Expand Down
4 changes: 2 additions & 2 deletions scripts/demos/sensors/raycaster_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,13 @@ def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene):
# print information from the sensors
print("-------------------------------")
print(scene["ray_caster"])
print("Ray cast hit results: ", scene["ray_caster"].data.ray_hits_w)
print("Ray cast hit results: ", wp.to_torch(scene["ray_caster"].data.ray_hits_w))

if not triggered:
if countdown > 0:
countdown -= 1
continue
data = scene["ray_caster"].data.ray_hits_w.cpu().numpy()
data = wp.to_torch(scene["ray_caster"].data.ray_hits_w).cpu().numpy()
np.save("cast_data.npy", data)
triggered = True
else:
Expand Down
5 changes: 4 additions & 1 deletion scripts/tutorials/04_sensors/add_sensors_on_robot.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene):
print("Received shape of depth image: ", scene["camera"].data.output["distance_to_image_plane"].shape)
print("-------------------------------")
print(scene["height_scanner"])
print("Received max height value: ", torch.max(scene["height_scanner"].data.ray_hits_w[..., -1]).item())
print(
"Received max height value: ",
torch.max(wp.to_torch(scene["height_scanner"].data.ray_hits_w)[..., -1]).item(),
)
print("-------------------------------")
print(scene["contact_forces"])
print("Received max contact force of: ", torch.max(scene["contact_forces"].data.net_forces_w).item())
Expand Down
2 changes: 1 addition & 1 deletion scripts/tutorials/04_sensors/run_ray_caster.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def run_simulator(sim: sim_utils.SimulationContext, scene_entities: dict):
# Update the ray-caster
with Timer(
f"Ray-caster update with {4} x {ray_caster.num_rays} rays with max height of"
f" {torch.max(ray_caster.data.pos_w).item():.2f}"
f" {torch.max(wp.to_torch(ray_caster.data.pos_w)).item():.2f}"
):
ray_caster.update(dt=sim.get_physics_dt(), force_recompute=True)
# Update counter
Expand Down
2 changes: 1 addition & 1 deletion source/isaaclab/config/extension.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

# Note: Semantic Versioning is used: https://semver.org/
version = "4.6.7"
version = "4.6.8"

# Description
title = "Isaac Lab framework for Robot Learning"
Expand Down
41 changes: 41 additions & 0 deletions source/isaaclab/docs/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,47 @@
Changelog
---------

4.6.8 (2026-04-21)
~~~~~~~~~~~~~~~~~~

Changed
^^^^^^^

* Converted all four ray caster sensor classes (:class:`~isaaclab.sensors.RayCaster`,
:class:`~isaaclab.sensors.RayCasterCamera`, :class:`~isaaclab.sensors.MultiMeshRayCaster`,
:class:`~isaaclab.sensors.MultiMeshRayCasterCamera`) to launch Warp kernels directly via
``wp.launch`` instead of going through Python-level torch wrappers. A new
:mod:`~isaaclab.sensors.ray_caster.kernels` module contains all sensor-specific kernels.
All intermediate ray buffers are now Warp-owned with zero-copy torch views, eliminating
per-step allocations. The existing :func:`~isaaclab.utils.warp.kernels.raycast_dynamic_meshes_kernel`
gained an ``env_mask`` parameter to support partial environment updates natively. A new
:func:`~isaaclab.utils.warp.kernels.raycast_mesh_masked_kernel` was added to
:mod:`~isaaclab.utils.warp.kernels` as the general-purpose masked single-mesh variant,
with ``return_distance`` and ``return_normal`` flags matching the design of
:func:`~isaaclab.utils.warp.kernels.raycast_mesh_kernel`.

**Breaking change** — :attr:`~isaaclab.sensors.RayCasterData.pos_w`,
:attr:`~isaaclab.sensors.RayCasterData.quat_w`, and
:attr:`~isaaclab.sensors.RayCasterData.ray_hits_w` now return :class:`wp.array`
instead of :class:`torch.Tensor`. Call-sites that previously accessed these as tensors
must wrap the result with :func:`wp.to_torch`:

.. code-block:: python

# Before
hits = sensor.data.ray_hits_w # torch.Tensor (old)
# After
hits = wp.to_torch(sensor.data.ray_hits_w) # torch.Tensor (zero-copy view)

Fixed
^^^^^

* Fixed frame composition in :meth:`~isaaclab.sensors.MultiMeshRayCaster._update_mesh_transforms`
which used simple subtraction instead of proper frame decomposition when applying mesh offsets.
With non-identity orientation offsets, tracked mesh positions were incorrect, causing raycasts to
miss or hit wrong surfaces. The method now uses :func:`~isaaclab.utils.math.combine_frame_transforms`.


4.6.7 (2026-04-20)
~~~~~~~~~~~~~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion source/isaaclab/isaaclab/envs/mdp/observations.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ def height_scan(env: ManagerBasedEnv, sensor_cfg: SceneEntityCfg, offset: float
# extract the used quantities (to enable type-hinting)
sensor: RayCaster = env.scene.sensors[sensor_cfg.name]
# height scan: height = sensor_height - hit_point_z - offset
return sensor.data.pos_w[:, 2].unsqueeze(1) - sensor.data.ray_hits_w[..., 2] - offset
return wp.to_torch(sensor.data.pos_w)[:, 2].unsqueeze(1) - wp.to_torch(sensor.data.ray_hits_w)[..., 2] - offset


def body_incoming_wrench(env: ManagerBasedEnv, asset_cfg: SceneEntityCfg) -> torch.Tensor:
Expand Down
2 changes: 1 addition & 1 deletion source/isaaclab/isaaclab/envs/mdp/rewards.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def base_height_l2(
if sensor_cfg is not None:
sensor: RayCaster = env.scene[sensor_cfg.name]
# Adjust the target height using the sensor data
adjusted_target_height = target_height + torch.mean(sensor.data.ray_hits_w[..., 2], dim=1)
adjusted_target_height = target_height + torch.mean(wp.to_torch(sensor.data.ray_hits_w)[..., 2], dim=1)
else:
# Use the provided target height directly for flat terrain
adjusted_target_height = target_height
Expand Down
Loading
Loading