Skip to content
Open
Show file tree
Hide file tree
Changes from 86 commits
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
c9bcd3b
Adds multi-mesh raycaster from Orbit (#4)
pascal-roth Jul 25, 2024
b7c172f
Fixes the number of meshes for dynamic raycasting with an regex expre…
pascal-roth Oct 23, 2024
e1a9124
Separates our multi-mesh raycaster as its own file (#63)
pascal-roth Feb 8, 2025
4ca82f6
Removes ClassVar `meshes` and `mesh_views` from MultiMeshRayCatser an…
pascal-roth Feb 10, 2025
d13331c
forgotten merge
pascal-roth Aug 9, 2025
3f5d008
revert classvar changes and apply formatter
pascal-roth Aug 9, 2025
5decd09
revert device change in ray caster
pascal-roth Aug 9, 2025
f585a31
update tests from unittest to pytest
pascal-roth Aug 17, 2025
7242ea2
add initial benchmark scripts and formatter
pascal-roth Aug 17, 2025
2c6c607
Fix check script
renezurbruegg Aug 17, 2025
86418d3
Manually merging pascal-roth changes from static vars branch
renezurbruegg Aug 17, 2025
fa6b498
remove wrongfully pushed wheels
renezurbruegg Aug 17, 2025
8beb0d2
Merge changes from #90 - dropping support for cache_combined_meshes …
renezurbruegg Aug 17, 2025
5ca6e6e
add memory benchmark
renezurbruegg Aug 18, 2025
eefcb3a
fix garbage collection issue
renezurbruegg Aug 18, 2025
6eda9c8
Add initial offset if mesh transform track is set to false
renezurbruegg Aug 23, 2025
0712ee5
avoid visualization when ray hits is not instantiated yet
renezurbruegg Aug 23, 2025
004184e
Add resolve world pose
renezurbruegg Aug 23, 2025
9287efe
Change benchmark to sphere. Add different amount of faces and multi i…
renezurbruegg Aug 23, 2025
f80e384
fix local offsets
renezurbruegg Aug 24, 2025
bcd747a
add example allegro hand
renezurbruegg Aug 24, 2025
4f6c772
Fix local offsets
renezurbruegg Aug 24, 2025
f98150e
Added regex lookups
renezurbruegg Aug 24, 2025
5940b98
Add num assets flag.
renezurbruegg Aug 24, 2025
500931c
Add anymal demo
renezurbruegg Aug 24, 2025
586858c
Add scale randomizations. Drop support for instancer meshes
renezurbruegg Aug 26, 2025
4d167ec
add shapes
renezurbruegg Aug 26, 2025
5b8563d
update benchmark scripts for different use cases - WIP
renezurbruegg Aug 26, 2025
17b5819
cleanup tests
renezurbruegg Aug 27, 2025
b3747c4
Add is shared functionality back
renezurbruegg Aug 27, 2025
ad7cbfc
change default
renezurbruegg Aug 27, 2025
e2e7f9e
cleanup
renezurbruegg Aug 27, 2025
8a37d61
Cleanup benchmark. Add flag to specify if meshse should be referenced
renezurbruegg Aug 28, 2025
3a6a242
remove old scripts
renezurbruegg Aug 28, 2025
16cd7c2
lint
renezurbruegg Aug 29, 2025
8efd58d
Merge branch 'main' into feature/multi-mesh-ray-caster
pascal-roth Aug 29, 2025
7509d45
Update source/isaaclab/isaaclab/sensors/ray_caster/ray_caster.py
renezurbruegg Aug 29, 2025
4e40239
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Aug 29, 2025
88da283
Move move merge_prim_meshes to RaycastTargetCfg
renezurbruegg Sep 5, 2025
13ba4e2
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
abbc8ed
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
df9f660
Update source/isaaclab/isaaclab/sensors/utils.py
renezurbruegg Sep 5, 2025
f2894a0
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
3eaecb5
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
0a47268
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
b27caa5
Move track_mesh_transforms to target config
renezurbruegg Sep 5, 2025
39fa91b
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
82f72ce
Add specification about string targets
renezurbruegg Sep 5, 2025
332b8be
improve docstrings
renezurbruegg Sep 5, 2025
f5e91cf
lint
renezurbruegg Sep 5, 2025
7c98e27
remove absolute paths
renezurbruegg Sep 5, 2025
a048c16
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
123cd01
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
bfeaf48
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
532b1f6
Update docstrings
renezurbruegg Sep 5, 2025
cc7dfee
minor fixes for track mesh transforms
renezurbruegg Sep 5, 2025
2ec9bd7
Improve docstring
renezurbruegg Sep 5, 2025
2743d03
lint
renezurbruegg Sep 5, 2025
b44eaf2
Migrating to pytest
renezurbruegg Sep 5, 2025
7ce6d6d
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
6066474
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
5984c82
Update source/isaaclab/isaaclab/sensors/utils.py
renezurbruegg Sep 5, 2025
09f17f5
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
3a2de0d
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
7b39736
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
e9fb9a1
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
43da984
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
12de1fa
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
1635968
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 5, 2025
115ce9f
Merge branch 'feature/multi-mesh-ray-caster' of github.com:renezurbru…
renezurbruegg Sep 5, 2025
636406b
lint
renezurbruegg Sep 5, 2025
8ac9ad6
move track_mesh_transforms to target cfg
renezurbruegg Sep 5, 2025
404bc69
migrate to pytest
renezurbruegg Sep 5, 2025
eef0399
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 6, 2025
d9a5f3a
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 6, 2025
d196bbd
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 6, 2025
f094b27
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 6, 2025
c764f0c
Update source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_cas…
renezurbruegg Sep 6, 2025
bccb267
removes ununsed files
Mayankm96 Sep 6, 2025
3d7c8f7
adds test for instanced proxies
Mayankm96 Sep 6, 2025
ab7eac2
runs formatter
Mayankm96 Sep 6, 2025
8ae7743
adds resolve prim funcs
Mayankm96 Sep 6, 2025
e6cbead
Apply suggestion from @Copilot
Mayankm96 Sep 6, 2025
796c1a4
updates changelog
Mayankm96 Sep 6, 2025
9c34e95
Merge branch 'feature/prim-prop-funcs' of github.com:Mayankm96/IsaacL…
Mayankm96 Sep 6, 2025
41c5f7a
Merge branch 'main' into feature/multi-mesh-ray-caster
kellyguo11 Sep 7, 2025
371785d
Move utils to sim_utils
renezurbruegg Sep 7, 2025
90ef912
rename to obtain_world_pose_from_view
renezurbruegg Sep 7, 2025
616d677
lint
renezurbruegg Sep 7, 2025
2d1c3c2
fix tests
renezurbruegg Sep 7, 2025
a289d1c
lint
renezurbruegg Sep 7, 2025
20772f4
Remove is global configuration
renezurbruegg Sep 8, 2025
04a7185
lint
renezurbruegg Sep 8, 2025
5c927da
Merge branch 'main' into feature/prim-prop-funcs
kellyguo11 Sep 8, 2025
7864b21
Merge branch 'main' into fix/instanced-proxies
kellyguo11 Sep 8, 2025
dd61d3e
revert changes to merge prs
renezurbruegg Sep 9, 2025
82819d8
Merge branch 'sim_utils' into feature/multi-mesh-ray-caster
renezurbruegg Sep 9, 2025
f5af366
Merge branch 'prim_utils' into feature/multi-mesh-ray-caster
renezurbruegg Sep 9, 2025
50fc172
fix typo
renezurbruegg Sep 9, 2025
c891112
Update trimesh functions
renezurbruegg Sep 9, 2025
85fbe94
Merge branch 'main' into feature/multi-mesh-ray-caster
jtigue-bdai Sep 9, 2025
c251913
Also lookup physics prim for sensor origin
renezurbruegg Sep 16, 2025
22040a7
fix merge issue
renezurbruegg Sep 16, 2025
0c2955b
update benchmarking
renezurbruegg Sep 16, 2025
41924f2
formatter and fix multi mesh raycaster
pascal-roth Sep 18, 2025
a194b3b
image based benchmark
pascal-roth Sep 19, 2025
9a0f5ab
fixes
pascal-roth Sep 19, 2025
80908ed
fix md
pascal-roth Sep 19, 2025
30ceb59
fix data type name
pascal-roth Sep 19, 2025
4439744
fix benchmark ray caster
pascal-roth Sep 21, 2025
0a832b5
plot scripts
pascal-roth Sep 22, 2025
e1a5780
update plot script
pascal-roth Sep 22, 2025
c09b9d0
update
pascal-roth Sep 22, 2025
b2103cb
Create agg. plot script
renezurbruegg Sep 22, 2025
335dc71
Merge branch 'feature/multi-mesh-ray-caster' of github.com:renezurbru…
renezurbruegg Sep 22, 2025
3c5bd81
updated plotting scripts
renezurbruegg Sep 23, 2025
0d3f5be
Change output dir, disable non cached tests
renezurbruegg Sep 23, 2025
ee12bb3
Merge branch 'feature/multi-mesh-ray-caster' of github.com:renezurbru…
pascal-roth Sep 23, 2025
bc6886f
allow plot single nav environment
pascal-roth Sep 23, 2025
8d84fb1
refactor camera benchmark
pascal-roth Sep 24, 2025
8796999
add bash scripts
renezurbruegg Sep 24, 2025
9b2871b
Merge branch 'feature/multi-mesh-ray-caster' of github.com:renezurbru…
renezurbruegg Sep 24, 2025
64a9a61
add fps plot
renezurbruegg Sep 25, 2025
04cd1c5
bugfix
pascal-roth Sep 26, 2025
ee857ce
Merge branch 'main' into feature/multi-mesh-ray-caster
pascal-roth Sep 26, 2025
dfc9283
Add more mesh types
renezurbruegg Oct 10, 2025
8b2de9b
Add generic fan triangulation
renezurbruegg Oct 10, 2025
c97b616
Merge remote-tracking branch 'public/main' into upstream/feature/mult…
renezurbruegg Oct 10, 2025
0dbb2da
Remove unusued benchmarks
renezurbruegg Oct 10, 2025
ddcc3d8
lint
renezurbruegg Oct 10, 2025
dfd08df
remove benchmarks
renezurbruegg Oct 10, 2025
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
1 change: 1 addition & 0 deletions docs/source/api/lab/isaaclab.utils.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
timer
types
warp
mesh
Copy link
Contributor

@Mayankm96 Mayankm96 Sep 6, 2025

Choose a reason for hiding this comment

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

Nice. I think we will need to consolidate the terrain mesh utils also in this to just have one place with bunch of stuff. Right now things have become spreaded out...

Future us task for sure.


.. Rubric:: Functions

Expand Down
258 changes: 258 additions & 0 deletions scripts/benchmarks/benchmark_camera_throughput.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

"""Benchmark throughput of different camera implementations.

This script benchmarks per-step time while varying:
- camera implementation: standard camera, tiled camera, warp ray-caster camera
- image resolutions (height x width)
- number of environments

Sensors are added to the scene config before `InteractiveScene` is constructed.
Each benchmark run initializes a fresh simulation and scene and tears it down.

Examples:

- Benchmark all camera types across resolutions:
./isaaclab.sh -p scripts/benchmarks/benchmark_camera_throughput.py \\
--num_envs 256 512 --impls standard,tiled,ray_caster \\
--resolutions 240x320,480x640 --steps 200 --warmup 20 --headless

- Only standard camera at 720p:
./isaaclab.sh -p scripts/benchmarks/benchmark_camera_throughput.py \\
--num_envs 256 --impls standard --resolutions 720x1280 --steps 200 --warmup 20 --headless
"""

"""Launch Isaac Sim Simulator first."""

import argparse
import csv
import os
import time

from isaaclab.app import AppLauncher

parser = argparse.ArgumentParser(description="Benchmark throughput of different camera implementations.")
parser.add_argument(
"--num_envs",
type=int,
nargs="+",
default=[256, 512, 1024],
help="List of environment counts to benchmark (e.g., 256 512 1024).",
)
parser.add_argument(
"--impls",
type=str,
default="standard,tiled,ray_caster",
help="Comma-separated list of implementations: standard,tiled,ray_caster",
)
parser.add_argument(
"--resolutions",
type=str,
default="240x320,480x640",
help="Comma-separated list of HxW resolutions, e.g., 240x320,480x640",
)
parser.add_argument("--steps", type=int, default=500, help="Steps per run to time.")
parser.add_argument("--warmup", type=int, default=50, help="Warmup steps per run before timing.")

# Append AppLauncher CLI args and parse
AppLauncher.add_app_launcher_args(parser)
args_cli, _ = parser.parse_known_args()
args_cli.enable_cameras = True

# launch omniverse app
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app

"""Rest everything follows."""

import isaaclab.sim as sim_utils
from isaaclab.assets import ArticulationCfg, AssetBaseCfg, RigidObjectCfg
from isaaclab.scene import InteractiveScene, InteractiveSceneCfg
from isaaclab.sensors import CameraCfg, RayCasterCameraCfg, TiledCameraCfg, patterns
from isaaclab.sim import SimulationContext
from isaaclab.utils import configclass
from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR

# Robot config to attach sensors under a valid prim
from isaaclab_assets.robots.anymal import ANYMAL_D_CFG # isort: skip


def _parse_resolutions(res_str: str) -> list[tuple[int, int]]:
resolutions: list[tuple[int, int]] = []
for token in [s for s in res_str.split(",") if s]:
h, w = token.lower().split("x")
resolutions.append((int(h), int(w)))
return resolutions


@configclass
class CameraBenchmarkSceneCfg(InteractiveSceneCfg):
"""Scene config with ground, light, robot, and one camera sensor per env."""

ground = AssetBaseCfg(
prim_path="/World/ground",
spawn=sim_utils.UsdFileCfg(usd_path=f"{ISAAC_NUCLEUS_DIR}/Environments/Terrains/rough_plane.usd"),
)
light = AssetBaseCfg(
prim_path="/World/Light",
spawn=sim_utils.DomeLightCfg(intensity=3000.0, color=(0.75, 0.75, 0.75)),
)
robot: ArticulationCfg = ANYMAL_D_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot") # type: ignore[attr-defined]

# one cube per environment (optional target for ray-caster camera)
cube: RigidObjectCfg = RigidObjectCfg(
prim_path="{ENV_REGEX_NS}/cube",
spawn=sim_utils.CuboidCfg(
size=(0.2, 0.2, 0.2),
rigid_props=sim_utils.RigidBodyPropertiesCfg(max_depenetration_velocity=1.0, disable_gravity=True),
mass_props=sim_utils.MassPropertiesCfg(mass=1.0),
visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.5, 0.0, 0.0)),
),
init_state=RigidObjectCfg.InitialStateCfg(pos=(0.0, 0.0, 1.0)),
)

standard_camera: CameraCfg | None = None
tiled_camera: TiledCameraCfg | None = None
ray_caster_camera: RayCasterCameraCfg | None = None


def _make_scene_cfg_standard(num_envs: int, height: int, width: int, debug_vis: bool) -> CameraBenchmarkSceneCfg:
scene_cfg = CameraBenchmarkSceneCfg(num_envs=num_envs, env_spacing=2.0)
scene_cfg.standard_camera = CameraCfg(
prim_path="{ENV_REGEX_NS}/Camera",
height=height,
width=width,
data_types=["rgb"],
spawn=sim_utils.PinholeCameraCfg(
focal_length=24.0, focus_distance=400.0, horizontal_aperture=20.955, clipping_range=(0.1, 1e4)
),
debug_vis=debug_vis,
)
return scene_cfg


def _make_scene_cfg_tiled(num_envs: int, height: int, width: int, debug_vis: bool) -> CameraBenchmarkSceneCfg:
scene_cfg = CameraBenchmarkSceneCfg(num_envs=num_envs, env_spacing=2.0)
scene_cfg.tiled_camera = TiledCameraCfg(
prim_path="{ENV_REGEX_NS}/TiledCamera",
height=height,
width=width,
data_types=["rgb", "depth"],
spawn=sim_utils.PinholeCameraCfg(
focal_length=24.0, focus_distance=400.0, horizontal_aperture=20.955, clipping_range=(0.1, 1e4)
),
debug_vis=debug_vis,
)
return scene_cfg


def _make_scene_cfg_ray_caster(num_envs: int, height: int, width: int, debug_vis: bool) -> CameraBenchmarkSceneCfg:
scene_cfg = CameraBenchmarkSceneCfg(num_envs=num_envs, env_spacing=2.0)
scene_cfg.ray_caster_camera = RayCasterCameraCfg(
prim_path="{ENV_REGEX_NS}/Robot/base", # attach to existing prim
mesh_prim_paths=["/World/ground", "/World/envs/env_.*/cube"],
pattern_cfg=patterns.PinholeCameraPatternCfg(
focal_length=24.0, horizontal_aperture=20.955, height=height, width=width
),
data_types=["distance_to_image_plane"],
debug_vis=debug_vis,
)
return scene_cfg


import isaacsim.core.utils.stage as stage_utils


def _setup_scene(scene_cfg: CameraBenchmarkSceneCfg) -> tuple[SimulationContext, InteractiveScene, float]:
# Create a new stage to avoid residue across runs
stage_utils.create_new_stage()
sim_cfg = sim_utils.SimulationCfg(device=args_cli.device)
sim = SimulationContext(sim_cfg)
sim.set_camera_view((2.5, 0.0, 4.0), (0.0, 0.0, 2.0))
setup_time_begin = time.perf_counter_ns()
scene = InteractiveScene(scene_cfg)
setup_time_end = time.perf_counter_ns()
print(f"[INFO]: Scene creation time: {(setup_time_end - setup_time_begin) / 1e6:.2f} ms")
reset_time_begin = time.perf_counter_ns()
sim.reset()
reset_time_end = time.perf_counter_ns()
print(f"[INFO]: Sim start time: {(reset_time_end - reset_time_begin) / 1e6:.2f} ms")
return sim, scene, sim.get_physics_dt()


def main():
impls = [s.strip() for s in args_cli.impls.split(",") if s]
resolutions = _parse_resolutions(args_cli.resolutions)
results: list[dict[str, object]] = []

def _bench(num_envs: int, impl: str, height: int, width: int):
if impl == "standard":
scene_cfg = _make_scene_cfg_standard(num_envs, height, width, debug_vis=not args_cli.headless)
sim, scene, sim_dt = _setup_scene(scene_cfg)
camera_obj = scene["standard_camera"]
label = "StandardCamera"
elif impl == "tiled":
scene_cfg = _make_scene_cfg_tiled(num_envs, height, width, debug_vis=not args_cli.headless)
sim, scene, sim_dt = _setup_scene(scene_cfg)
camera_obj = scene["tiled_camera"]
label = "TiledCamera"
elif impl == "ray_caster":
scene_cfg = _make_scene_cfg_ray_caster(num_envs, height, width, debug_vis=not args_cli.headless)
sim, scene, sim_dt = _setup_scene(scene_cfg)
camera_obj = scene["ray_caster_camera"]
label = "RayCasterCamera"
else:
raise ValueError(f"Unknown impl: {impl}")

# Warmup
for _ in range(args_cli.warmup):
sim.step()
camera_obj.update(dt=sim_dt)
# Timing
t0 = time.perf_counter_ns()
for _ in range(args_cli.steps):
sim.step()
camera_obj.update(dt=sim_dt)
t1 = time.perf_counter_ns()
per_step_ms = (t1 - t0) / args_cli.steps / 1e6
print(f"[INFO]: {label}: {num_envs} envs, res={height}x{width}, per-step={per_step_ms:.3f} ms")
results.append({
"impl": impl,
"num_envs": num_envs,
"height": height,
"width": width,
"per_step_ms": float(per_step_ms),
})
# Teardown
sim.clear_instance()

for num_envs in args_cli.num_envs:
for impl in impls:
print(f"\n[INFO]: Benchmarking {impl} cameras with {num_envs} envs")
for h, w in resolutions:
_bench(num_envs, impl, h, w)

# Save results
os.makedirs("outputs/benchmarks", exist_ok=True)
csv_path = os.path.join("outputs/benchmarks", "camera_throughput.csv")
md_path = os.path.join("outputs/benchmarks", "camera_throughput.md")

fieldnames = ["impl", "num_envs", "height", "width", "per_step_ms"]
with open(csv_path, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(results)
with open(md_path, "w") as f:
f.write("| impl | num_envs | height | width | per_step_ms |\n")
f.write("|---|---:|---:|---:|---:|\n")
for r in results:
f.write(f"| {r['impl']} | {r['num_envs']} | {r['height']} | {r['width']} | {r['per_step_ms']:.3f} |\n")
print(f"[INFO]: Saved benchmark results to {csv_path} and {md_path}")


if __name__ == "__main__":
main()
simulation_app.close()
Loading