From 0dda75a92af0cf70749e8733d3cf4aee43833da4 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Mon, 8 Jun 2026 14:20:26 +0800 Subject: [PATCH 01/19] Adapt deformables.py Signed-off-by: Yize Wang --- scripts/demos/deformables.py | 120 +++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 56 deletions(-) diff --git a/scripts/demos/deformables.py b/scripts/demos/deformables.py index 1da56e1df004..3b066c78412b 100644 --- a/scripts/demos/deformables.py +++ b/scripts/demos/deformables.py @@ -7,30 +7,37 @@ .. code-block:: bash - # Usage + # Usage with default PhysX physics and default kit visualizer. ./isaaclab.sh -p scripts/demos/deformables.py + # Usage with Newton visualizer and default PhysX physics. + ./isaaclab.sh -p scripts/demos/deformables.py --visualizer newton + + # Usage with Newton MJWarp backend and default kit visualizer. + ./isaaclab.sh -p scripts/demos/deformables.py --physics newton_mjwarp + + # Usage with Newton visualizer and Newton MJWarp backend. + ./isaaclab.sh -p scripts/demos/deformables.py --visualizer newton --physics newton_mjwarp + """ -"""Launch Isaac Sim Simulator first.""" +"""Parse CLI first so we can decide whether to launch Isaac Sim Kit.""" import argparse +from typing import TYPE_CHECKING -from isaaclab.app import AppLauncher +from isaaclab.app import add_launcher_args, launch_simulation # create argparser -parser = argparse.ArgumentParser(description="This script demonstrates how to spawn deformable prims into the scene.") -parser.add_argument("--backend", type=str, default="physx", choices=["physx", "newton"], help="Physics backend.") -# append AppLauncher cli args -AppLauncher.add_app_launcher_args(parser) -# demos should open Kit visualizer by default +parser = argparse.ArgumentParser( + description="This script demonstrates how to spawn deformable prims into the scene.", + conflict_handler="resolve", +) +parser.add_argument("--physics", default="physx", choices=["physx", "newton_mjwarp"], help="Physics backend.") +add_launcher_args(parser) parser.set_defaults(visualizer=["kit"]) -# parse the arguments args_cli = parser.parse_args() -# launch omniverse app -app_launcher = AppLauncher(args_cli) -simulation_app = app_launcher.app """Rest everything follows.""" @@ -41,10 +48,20 @@ import tqdm import isaaclab.sim as sim_utils -from isaaclab.assets import DeformableObject, DeformableObjectCfg -from isaaclab.utils.assets import ISAACLAB_NUCLEUS_DIR -if args_cli.backend == "newton": +## +# Pre-defined configs +## +from isaaclab_newton.physics import NewtonCfg # isort:skip +from isaaclab.assets import DeformableObjectCfg # isort:skip +from isaaclab.physics import PhysicsCfg # isort:skip +from isaaclab.utils.assets import ISAACLAB_NUCLEUS_DIR # isort:skip + +if TYPE_CHECKING: + from isaaclab.assets import DeformableObject + +if args_cli.physics == "newton_mjwarp": + from isaaclab_contrib.deformable.newton_manager_cfg import VBDSolverCfg # isort:skip from isaaclab_newton.sim.schemas import NewtonDeformableBodyPropertiesCfg as DeformableBodyPropertiesCfg from isaaclab_newton.sim.spawners.materials import ( NewtonDeformableBodyMaterialCfg as VolumeDeformableMaterialCfg, @@ -165,13 +182,13 @@ def design_scene() -> tuple[dict, list[list[float]]]: obj_name = random.choice(list(objects_cfg.keys())) obj_cfg = objects_cfg[obj_name] # randomize the deformable material stiffness - if args_cli.backend == "newton" and obj_name == "cloth": + if args_cli.physics == "newton_mjwarp" and obj_name == "cloth": obj_cfg.physics_material.tri_ke = random.uniform(5e3, 5e4) obj_cfg.physics_material.tri_ka = random.uniform(5e3, 5e4) else: youngs_modulus = random.uniform(5e5, 1e8) poissons_ratio = random.uniform(0.25, 0.45) - if args_cli.backend == "newton": + if args_cli.physics == "newton_mjwarp": obj_cfg.physics_material.k_mu = youngs_modulus / (2.0 * (1.0 + poissons_ratio)) obj_cfg.physics_material.k_lambda = ( youngs_modulus * poissons_ratio / ((1.0 + poissons_ratio) * (1.0 - 2.0 * poissons_ratio)) @@ -189,7 +206,7 @@ def design_scene() -> tuple[dict, list[list[float]]]: spawn=obj_cfg, init_state=DeformableObjectCfg.InitialStateCfg(pos=origin), ) - scene_entities[f"Surface{idx:02d}"] = DeformableObject(cfg=cfg) + scene_entities[f"Surface{idx:02d}"] = cfg.class_type(cfg) else: prim_path = f"/World/Origin/Volume{idx:02d}" cfg = DeformableObjectCfg( @@ -197,21 +214,21 @@ def design_scene() -> tuple[dict, list[list[float]]]: spawn=obj_cfg, init_state=DeformableObjectCfg.InitialStateCfg(pos=origin), ) - scene_entities[f"Volume{idx:02d}"] = DeformableObject(cfg=cfg) + scene_entities[f"Volume{idx:02d}"] = cfg.class_type(cfg) # return the scene information return scene_entities, origins -def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, DeformableObject]): +def run_simulator(sim: "sim_utils.SimulationContext", entities: dict[str, "DeformableObject"]): """Runs the simulation loop.""" # Define simulation stepping sim_dt = sim.get_physics_dt() sim_time = 0.0 count = 0 - # Simulate physics - while simulation_app.is_running(): + # Step while a visualizer window is still open (or none exist, e.g. headless); works for kit and newton. + while sim.is_headless_or_exist_active_visualizer(): # reset if count % int(3.0 / sim_dt) == 0: # reset counters @@ -236,42 +253,33 @@ def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, Deformab def main(): """Main function.""" - # Initialize the simulation context - if args_cli.backend == "newton": - from isaaclab_newton.physics import NewtonCfg - - from isaaclab_contrib.deformable.newton_manager_cfg import VBDSolverCfg - - physics_cfg = NewtonCfg( - solver_cfg=VBDSolverCfg( - iterations=5, - particle_enable_self_contact=True, - particle_self_contact_radius=0.0001, - particle_self_contact_margin=0.1, - ), - num_substeps=4, - ) - else: - from isaaclab_physx.physics import PhysxCfg - - physics_cfg = PhysxCfg() - sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device, physics=physics_cfg) - sim = sim_utils.SimulationContext(sim_cfg) - # Set main camera - sim.set_camera_view([4.0, 4.0, 3.0], [0.5, 0.5, 0.0]) - - # Design scene by adding assets to it - scene_entities, _ = design_scene() - # Play the simulator - sim.reset() - # Now we are ready! - print("[INFO]: Setup complete...") - run_simulator(sim, scene_entities) - print("[INFO]: Simulation complete...") + with launch_simulation(cfg=PhysicsCfg(), launcher_args=args_cli) as physics_cfg: + if args_cli.physics == "newton_mjwarp": + physics_cfg = NewtonCfg( + solver_cfg=VBDSolverCfg( + iterations=5, + particle_enable_self_contact=True, + particle_self_contact_radius=0.0001, + particle_self_contact_margin=0.1, + ), + num_substeps=4, + ) + # Initialize the simulation context + sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device, physics=physics_cfg) + sim = sim_utils.SimulationContext(sim_cfg) + # Set main camera + sim.set_camera_view([4.0, 4.0, 3.0], [0.5, 0.5, 0.0]) + + # Design scene by adding assets to it + scene_entities, _ = design_scene() + # Play the simulator + sim.reset() + # Now we are ready! + print("[INFO]: Setup complete...") + run_simulator(sim, scene_entities) + print("[INFO]: Simulation complete...") if __name__ == "__main__": # run the main function main() - # close sim app - simulation_app.close() From 925b00e8ec630c1532a71e5041477e0b339ebb35 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Tue, 9 Jun 2026 17:28:41 +0800 Subject: [PATCH 02/19] Adapt markers.py --- scripts/demos/markers.py | 153 ++++++++++-------- .../markers/visualization_markers_cfg.py | 10 ++ 2 files changed, 93 insertions(+), 70 deletions(-) diff --git a/scripts/demos/markers.py b/scripts/demos/markers.py index bd44a887d3ed..49e7b36e1a91 100644 --- a/scripts/demos/markers.py +++ b/scripts/demos/markers.py @@ -7,42 +7,56 @@ .. code-block:: bash - # Usage + # Usage with default PhysX physics and default kit visualizer. ./isaaclab.sh -p scripts/demos/markers.py + # Usage with Newton visualizer and default PhysX physics. + ./isaaclab.sh -p scripts/demos/markers.py --visualizer newton + + # Usage with Newton (MJWarp) physics and default kit visualizer. + ./isaaclab.sh -p scripts/demos/markers.py --physics newton_mjwarp + + # Usage with Newton visualizer and Newton (MJWarp) physics. + ./isaaclab.sh -p scripts/demos/markers.py --visualizer newton --physics newton_mjwarp + """ -"""Launch Isaac Sim Simulator first.""" +"""Parse CLI first so we can decide whether to launch Isaac Sim Kit.""" import argparse +from typing import TYPE_CHECKING -from isaaclab.app import AppLauncher +from isaaclab.app import add_launcher_args, launch_simulation # add argparse arguments -parser = argparse.ArgumentParser(description="This script demonstrates different types of markers.") -# append AppLauncher cli args -AppLauncher.add_app_launcher_args(parser) -# demos should open Kit visualizer by default +parser = argparse.ArgumentParser( + description="This script demonstrates different types of markers.", + conflict_handler="resolve", +) +parser.add_argument("--physics", default="physx", choices=["physx", "newton_mjwarp"], help="Physics backend.") +add_launcher_args(parser) parser.set_defaults(visualizer=["kit"]) -# parse the arguments args_cli = parser.parse_args() -# launch omniverse app -app_launcher = AppLauncher(args_cli) -simulation_app = app_launcher.app - """Rest everything follows.""" import torch import isaaclab.sim as sim_utils -from isaaclab.markers import VisualizationMarkers, VisualizationMarkersCfg -from isaaclab.sim import SimulationContext + +## +# Pre-defined configs +## +from isaaclab.markers.visualization_markers_cfg import VisualizationMarkersCfg +from isaaclab.physics import PhysicsCfg from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR, ISAACLAB_NUCLEUS_DIR from isaaclab.utils.math import quat_from_angle_axis +if TYPE_CHECKING: + from isaaclab.markers import VisualizationMarkers + -def define_markers() -> VisualizationMarkers: +def define_markers() -> "VisualizationMarkers": """Define markers with various different shapes.""" marker_cfg = VisualizationMarkersCfg( prim_path="/Visuals/myMarkers", @@ -90,67 +104,66 @@ def define_markers() -> VisualizationMarkers: ), }, ) - return VisualizationMarkers(marker_cfg) + return marker_cfg.class_type(marker_cfg) def main(): """Main function.""" - # Load kit helper - sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device) - sim = SimulationContext(sim_cfg) - # Set main camera - sim.set_camera_view([0.0, 18.0, 12.0], [0.0, 3.0, 0.0]) - - # Spawn things into stage - # Lights - cfg = sim_utils.DomeLightCfg(intensity=3000.0, color=(0.75, 0.75, 0.75)) - cfg.func("/World/Light", cfg) - - # create markers - my_visualizer = define_markers() - - # define a grid of positions where the markers should be placed - num_markers_per_type = 5 - grid_spacing = 2.0 - # Calculate the half-width and half-height - half_width = (num_markers_per_type - 1) / 2.0 - half_height = (my_visualizer.num_prototypes - 1) / 2.0 - # Create the x and y ranges centered around the origin - x_range = torch.arange(-half_width * grid_spacing, (half_width + 1) * grid_spacing, grid_spacing) - y_range = torch.arange(-half_height * grid_spacing, (half_height + 1) * grid_spacing, grid_spacing) - # Create the grid - x_grid, y_grid = torch.meshgrid(x_range, y_range, indexing="ij") - x_grid = x_grid.reshape(-1) - y_grid = y_grid.reshape(-1) - z_grid = torch.zeros_like(x_grid) - # marker locations - marker_locations = torch.stack([x_grid, y_grid, z_grid], dim=1) - marker_indices = torch.arange(my_visualizer.num_prototypes).repeat(num_markers_per_type) - - # Play the simulator - sim.reset() - # Now we are ready! - print("[INFO]: Setup complete...") - - # Yaw angle - yaw = torch.zeros_like(marker_locations[:, 0]) - # Simulate physics - while simulation_app.is_running(): - # rotate the markers around the z-axis for visualization - marker_orientations = quat_from_angle_axis(yaw, torch.tensor([0.0, 0.0, 1.0])) - # visualize - my_visualizer.visualize(marker_locations, marker_orientations, marker_indices=marker_indices) - # roll corresponding indices to show how marker prototype can be changed - if yaw[0].item() % (0.5 * torch.pi) < 0.01: - marker_indices = torch.roll(marker_indices, 1) - # perform step - sim.step() - # increment yaw - yaw += 0.01 + with launch_simulation(cfg=PhysicsCfg(), launcher_args=args_cli) as physics_cfg: + # Load kit helper + sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device, physics=physics_cfg) + sim = sim_utils.SimulationContext(sim_cfg) + # Set main camera + sim.set_camera_view([0.0, 18.0, 12.0], [0.0, 3.0, 0.0]) + + # Spawn things into stage + # Lights + cfg = sim_utils.DomeLightCfg(intensity=3000.0, color=(0.75, 0.75, 0.75)) + cfg.func("/World/Light", cfg) + + # create markers + my_visualizer = define_markers() + + # define a grid of positions where the markers should be placed + num_markers_per_type = 5 + grid_spacing = 2.0 + # Calculate the half-width and half-height + half_width = (num_markers_per_type - 1) / 2.0 + half_height = (my_visualizer.num_prototypes - 1) / 2.0 + # Create the x and y ranges centered around the origin + x_range = torch.arange(-half_width * grid_spacing, (half_width + 1) * grid_spacing, grid_spacing) + y_range = torch.arange(-half_height * grid_spacing, (half_height + 1) * grid_spacing, grid_spacing) + # Create the grid + x_grid, y_grid = torch.meshgrid(x_range, y_range, indexing="ij") + x_grid = x_grid.reshape(-1) + y_grid = y_grid.reshape(-1) + z_grid = torch.zeros_like(x_grid) + # marker locations + marker_locations = torch.stack([x_grid, y_grid, z_grid], dim=1) + marker_indices = torch.arange(my_visualizer.num_prototypes).repeat(num_markers_per_type) + + # Play the simulator + sim.reset() + # Now we are ready! + print("[INFO]: Setup complete...") + + # Yaw angle + yaw = torch.zeros_like(marker_locations[:, 0]) + # Step while a visualizer window is still open (or none exist, e.g. headless); works for kit and newton. + while sim.is_headless_or_exist_active_visualizer(): + # rotate the markers around the z-axis for visualization + marker_orientations = quat_from_angle_axis(yaw, torch.tensor([0.0, 0.0, 1.0])) + # visualize + my_visualizer.visualize(marker_locations, marker_orientations, marker_indices=marker_indices) + # roll corresponding indices to show how marker prototype can be changed + if yaw[0].item() % (0.5 * torch.pi) < 0.01: + marker_indices = torch.roll(marker_indices, 1) + # perform step + sim.step() + # increment yaw + yaw += 0.01 if __name__ == "__main__": # run the main function main() - # close sim app - simulation_app.close() diff --git a/source/isaaclab/isaaclab/markers/visualization_markers_cfg.py b/source/isaaclab/isaaclab/markers/visualization_markers_cfg.py index b7cc2002ccf0..6c6b98ec3268 100644 --- a/source/isaaclab/isaaclab/markers/visualization_markers_cfg.py +++ b/source/isaaclab/isaaclab/markers/visualization_markers_cfg.py @@ -8,10 +8,14 @@ from __future__ import annotations from dataclasses import MISSING +from typing import TYPE_CHECKING from isaaclab.sim.spawners import SpawnerCfg from isaaclab.utils.configclass import configclass +if TYPE_CHECKING: + from isaaclab.markers import VisualizationMarkers + @configclass class VisualizationMarkersCfg: @@ -26,3 +30,9 @@ class VisualizationMarkersCfg: The key is the name of the marker, and the value is the configuration of the marker. The key is used to identify the marker in the class. """ + + class_type: type[VisualizationMarkers] | str = "{DIR}.visualization_markers:VisualizationMarkers" + """The class to use for the visualization markers. + + Defaults to :class:`isaaclab.markers.VisualizationMarkers`. + """ From 41131e617cf49e26e530a8d018cb9abf111d8e2c Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Tue, 9 Jun 2026 20:50:00 +0800 Subject: [PATCH 03/19] Adapt procedural_terrain.py --- scripts/demos/markers.py | 9 --- scripts/demos/procedural_terrain.py | 70 ++++++++++++---------- source/isaaclab/isaaclab/terrains/utils.py | 2 +- 3 files changed, 38 insertions(+), 43 deletions(-) diff --git a/scripts/demos/markers.py b/scripts/demos/markers.py index 49e7b36e1a91..2feb5de0a510 100644 --- a/scripts/demos/markers.py +++ b/scripts/demos/markers.py @@ -10,15 +10,6 @@ # Usage with default PhysX physics and default kit visualizer. ./isaaclab.sh -p scripts/demos/markers.py - # Usage with Newton visualizer and default PhysX physics. - ./isaaclab.sh -p scripts/demos/markers.py --visualizer newton - - # Usage with Newton (MJWarp) physics and default kit visualizer. - ./isaaclab.sh -p scripts/demos/markers.py --physics newton_mjwarp - - # Usage with Newton visualizer and Newton (MJWarp) physics. - ./isaaclab.sh -p scripts/demos/markers.py --visualizer newton --physics newton_mjwarp - """ """Parse CLI first so we can decide whether to launch Isaac Sim Kit.""" diff --git a/scripts/demos/procedural_terrain.py b/scripts/demos/procedural_terrain.py index 98bcd0276789..30d871b20241 100644 --- a/scripts/demos/procedural_terrain.py +++ b/scripts/demos/procedural_terrain.py @@ -27,14 +27,20 @@ """ -"""Launch Isaac Sim Simulator first.""" +from __future__ import annotations + +"""Parse CLI first so we can decide whether to launch Isaac Sim Kit.""" import argparse +from typing import TYPE_CHECKING -from isaaclab.app import AppLauncher +from isaaclab.app import add_launcher_args, launch_simulation # add argparse arguments -parser = argparse.ArgumentParser(description="This script demonstrates procedural terrain generation.") +parser = argparse.ArgumentParser( + description="This script demonstrates procedural terrain generation.", + conflict_handler="resolve", +) parser.add_argument( "--color_scheme", type=str, @@ -54,17 +60,11 @@ default=False, help="Whether to show the flat patches computed during the terrain generation.", ) -# append AppLauncher cli args -AppLauncher.add_app_launcher_args(parser) -# demos should open Kit visualizer by default +parser.add_argument("--physics", default="physx", choices=["physx", "newton_mjwarp"], help="Physics backend.") +add_launcher_args(parser) parser.set_defaults(visualizer=["kit"]) -# parse the arguments args_cli = parser.parse_args() -# launch omniverse app -app_launcher = AppLauncher(args_cli) -simulation_app = app_launcher.app - """Rest everything follows.""" import random @@ -72,15 +72,20 @@ import torch import isaaclab.sim as sim_utils -from isaaclab.assets import AssetBase -from isaaclab.markers import VisualizationMarkers, VisualizationMarkersCfg -from isaaclab.terrains import FlatPatchSamplingCfg, TerrainImporter, TerrainImporterCfg ## # Pre-defined configs ## +from isaaclab.markers.visualization_markers_cfg import VisualizationMarkersCfg +from isaaclab.physics import PhysicsCfg +from isaaclab.terrains.sub_terrain_cfg import FlatPatchSamplingCfg +from isaaclab.terrains.terrain_importer_cfg import TerrainImporterCfg + from isaaclab.terrains.config.rough import ROUGH_TERRAINS_CFG # isort:skip +if TYPE_CHECKING: + from isaaclab.assets import AssetBase + def design_scene() -> tuple[dict, torch.Tensor]: """Designs the scene.""" @@ -115,7 +120,7 @@ def design_scene() -> tuple[dict, torch.Tensor]: if args_cli.color_scheme in ["height", "random"]: terrain_importer_cfg.visual_material = None # Create terrain importer - terrain_importer = TerrainImporter(terrain_importer_cfg) + terrain_importer = terrain_importer_cfg.class_type(terrain_importer_cfg) # Show the flat patches computed if args_cli.show_flat_patches: @@ -127,7 +132,7 @@ def design_scene() -> tuple[dict, torch.Tensor]: height=0.1, visual_material=sim_utils.GlassMdlCfg(glass_color=(random.random(), random.random(), random.random())), ) - flat_patches_visualizer = VisualizationMarkers(vis_cfg) + flat_patches_visualizer = vis_cfg.class_type(vis_cfg) # Visualize the flat patches all_patch_locations = [] @@ -147,31 +152,30 @@ def design_scene() -> tuple[dict, torch.Tensor]: def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, AssetBase], origins: torch.Tensor): """Runs the simulation loop.""" - # Simulate physics - while simulation_app.is_running(): + # Step while a visualizer window is still open (or none exist, e.g. headless); works for kit and newton. + while sim.is_headless_or_exist_active_visualizer(): # perform step sim.step() def main(): """Main function.""" - # Initialize the simulation context - sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device) - sim = sim_utils.SimulationContext(sim_cfg) - # Set main camera - sim.set_camera_view(eye=[5.0, 5.0, 5.0], target=[0.0, 0.0, 0.0]) - # design scene - scene_entities, scene_origins = design_scene() - # Play the simulator - sim.reset() - # Now we are ready! - print("[INFO]: Setup complete...") - # Run the simulator - run_simulator(sim, scene_entities, scene_origins) + with launch_simulation(cfg=PhysicsCfg(), launcher_args=args_cli) as physics_cfg: + # Initialize the simulation context + sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device, physics=physics_cfg) + sim = sim_utils.SimulationContext(sim_cfg) + # Set main camera + sim.set_camera_view(eye=[15.0, 15.0, 15.0], target=[0.0, 0.0, 0.0]) + # design scene + scene_entities, scene_origins = design_scene() + # Play the simulator + sim.reset() + # Now we are ready! + print("[INFO]: Setup complete...") + # Run the simulator + run_simulator(sim, scene_entities, scene_origins) if __name__ == "__main__": # run the main function main() - # close sim app - simulation_app.close() diff --git a/source/isaaclab/isaaclab/terrains/utils.py b/source/isaaclab/isaaclab/terrains/utils.py index 766fe13c6f9c..eb29541d921f 100644 --- a/source/isaaclab/isaaclab/terrains/utils.py +++ b/source/isaaclab/isaaclab/terrains/utils.py @@ -52,7 +52,7 @@ def color_meshes_by_height(meshes: list[trimesh.Trimesh], **kwargs) -> trimesh.T # clip lower and upper bounds to have better color mapping heights_normalized = np.clip(heights_normalized, 0.1, 0.9) # Get the color for each vertex based on the height - color_map = kwargs.pop("color_map", "turbo") + color_map = kwargs.pop("color_map", "inferno") colors = trimesh.visual.color.interpolate(heights_normalized, color_map=color_map) # Set the vertex colors mesh.visual.vertex_colors = colors From 293a188a4781840ff307e14b7107804d3108074e Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Tue, 9 Jun 2026 21:43:25 +0800 Subject: [PATCH 04/19] Adapt arl_robot_1.py Signed-off-by: Yize Wang --- scripts/demos/arl_robot_1.py | 175 ++++++++++++++++++----------------- 1 file changed, 92 insertions(+), 83 deletions(-) diff --git a/scripts/demos/arl_robot_1.py b/scripts/demos/arl_robot_1.py index 987e6be6b2ec..ec09dda6c8e5 100644 --- a/scripts/demos/arl_robot_1.py +++ b/scripts/demos/arl_robot_1.py @@ -3,37 +3,50 @@ # # SPDX-License-Identifier: BSD-3-Clause -""" -Script to view ARL Robot 1. +"""Script to view ARL Robot 1. + +.. code-block:: bash + + # Usage with default PhysX physics and default kit visualizer. + ./isaaclab.sh -p scripts/demos/arl_robot_1.py + + # Usage with Newton visualizer and default PhysX physics. + ./isaaclab.sh -p scripts/demos/arl_robot_1.py --visualizer newton + + # Usage with Newton (MJWarp) physics and default kit visualizer. + ./isaaclab.sh -p scripts/demos/arl_robot_1.py --physics newton_mjwarp + + # Usage with Newton visualizer and Newton (MJWarp) physics. + ./isaaclab.sh -p scripts/demos/arl_robot_1.py --visualizer newton --physics newton_mjwarp -Launch Isaac Sim Simulator first. """ -# Create argparser +"""Parse CLI first so we can decide whether to launch Isaac Sim Kit.""" + import argparse -from isaaclab.app import AppLauncher +from isaaclab.app import add_launcher_args, launch_simulation -parser = argparse.ArgumentParser(description="View ARL Robot 1 with Lee Position Controller.") -# append AppLauncher cli args -AppLauncher.add_app_launcher_args(parser) +parser = argparse.ArgumentParser( + description="View ARL Robot 1 with Lee Position Controller.", + conflict_handler="resolve", +) +parser.add_argument("--physics", default="physx", choices=["physx", "newton_mjwarp"], help="Physics backend.") +add_launcher_args(parser) +parser.set_defaults(visualizer=["kit"]) args_cli = parser.parse_args() -# launch omniverse app -app_launcher = AppLauncher(args_cli) -simulation_app = app_launcher.app - """Rest everything follows.""" import torch -import omni.usd -from pxr import Gf, UsdLux - import isaaclab.sim as sim_utils -from isaaclab.sim import SimulationContext -from isaaclab_contrib.assets import Multirotor +## +# Pre-defined configs +## +from isaaclab.physics import PhysicsCfg + from isaaclab_contrib.controllers.lee_position_control import LeePosController from isaaclab_contrib.controllers.lee_position_control_cfg import LeePosControllerCfg @@ -42,72 +55,68 @@ def main(): """Main function to spawn arl_robot_1.""" - - # Create simulation context - sim_cfg = sim_utils.SimulationCfg(dt=0.01) - sim = SimulationContext(sim_cfg) - - # Create a dome light with light blue color - stage = omni.usd.get_context().get_stage() - dome_light = UsdLux.DomeLight.Define(stage, "/World/DomeLight") - dome_light.CreateColorAttr(Gf.Vec3f(0.53, 0.81, 0.92)) # Light blue - dome_light.CreateIntensityAttr(1000.0) - - # Spawn ground plane - cfg = sim_utils.GroundPlaneCfg() - cfg.func("/World/defaultGroundPlane", cfg) - - # Spawn robot - robot_cfg = ARL_ROBOT_1_CFG.replace(prim_path="/World/Robot") - robot_cfg.actuators["thrusters"].dt = sim_cfg.dt - robot = Multirotor(robot_cfg) - - # Play the simulator - sim.reset() - - # Create Lee position controller - controller_cfg = LeePosControllerCfg( - K_pos_range=((2.5, 2.5, 1.5), (3.5, 3.5, 2.0)), - K_vel_range=((2.5, 2.5, 1.5), (3.5, 3.5, 2.0)), - K_rot_range=((1.6, 1.6, 0.25), (1.85, 1.85, 0.4)), - K_angvel_range=((0.4, 0.4, 0.075), (0.5, 0.5, 0.09)), - max_inclination_angle_rad=1.0471975511965976, - max_yaw_rate=1.0471975511965976, - ) - controller = LeePosController(controller_cfg, robot, num_envs=1, device=str(sim.device)) - - # Get allocation matrix and compute pseudoinverse - allocation_matrix = torch.tensor(robot_cfg.allocation_matrix, device=sim.device, dtype=torch.float32) - # allocation_matrix is (6, num_thrusters), we need pseudoinverse for wrench -> thrust - alloc_pinv = torch.linalg.pinv(allocation_matrix) # Shape: (num_thrusters, 6) - - # Position command: hover in place (zero position, zero yaw) - pos_command = torch.zeros((1, 4), device=sim.device) # [x, y, z, yaw] - pos_command[0, 2] = 1.0 # Hover at 1 meter height - - # Simulation loop - print("[INFO] Starting demo with Lee Position Controller. Press Ctrl+C to stop.") - - while simulation_app.is_running(): - # Compute wrench from velocity controller - wrench = controller.compute(pos_command) # Shape: (1, 6) - - # Allocate wrench to thrusters: thrust = pinv(A) @ wrench - thrust_cmd = torch.matmul(wrench, alloc_pinv.T) # Shape: (1, num_thrusters) - thrust_cmd = thrust_cmd.clamp(min=0.0) # Ensure non-negative thrust - - # Apply thrust - robot.set_thrust_target(thrust_cmd) - - # Step simulation - robot.write_data_to_sim() - sim.step() - - # Update robot - robot.update(sim_cfg.dt) - - # Cleanup - simulation_app.close() + with launch_simulation(cfg=PhysicsCfg(), launcher_args=args_cli) as physics_cfg: + # Create simulation context + sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device, physics=physics_cfg) + sim = sim_utils.SimulationContext(sim_cfg) + + # Create a dome light with light blue color + light_cfg = sim_utils.DomeLightCfg(intensity=1000.0, color=(0.53, 0.81, 0.92)) + light_cfg.func("/World/DomeLight", light_cfg) + + # Spawn ground plane + ground_cfg = sim_utils.GroundPlaneCfg() + ground_cfg.func("/World/defaultGroundPlane", ground_cfg) + + # Spawn robot + robot_cfg = ARL_ROBOT_1_CFG.replace(prim_path="/World/Robot") + robot_cfg.actuators["thrusters"].dt = sim_cfg.dt + robot = robot_cfg.class_type(robot_cfg) + + # Play the simulator + sim.reset() + + # Create Lee position controller + controller_cfg = LeePosControllerCfg( + K_pos_range=((2.5, 2.5, 1.5), (3.5, 3.5, 2.0)), + K_vel_range=((2.5, 2.5, 1.5), (3.5, 3.5, 2.0)), + K_rot_range=((1.6, 1.6, 0.25), (1.85, 1.85, 0.4)), + K_angvel_range=((0.4, 0.4, 0.075), (0.5, 0.5, 0.09)), + max_inclination_angle_rad=1.0471975511965976, + max_yaw_rate=1.0471975511965976, + ) + controller = LeePosController(controller_cfg, robot, num_envs=1, device=str(sim.device)) + + # Get allocation matrix and compute pseudoinverse + allocation_matrix = torch.tensor(robot_cfg.allocation_matrix, device=sim.device, dtype=torch.float32) + # allocation_matrix is (6, num_thrusters), we need pseudoinverse for wrench -> thrust + alloc_pinv = torch.linalg.pinv(allocation_matrix) # Shape: (num_thrusters, 6) + + # Position command: hover in place (zero position, zero yaw) + pos_command = torch.zeros((1, 4), device=sim.device) # [x, y, z, yaw] + pos_command[0, 2] = 1.0 # Hover at 1 meter height + + # Simulation loop + print("[INFO] Starting demo with Lee Position Controller. Press Ctrl+C to stop.") + + # Step while a visualizer window is still open (or none exist, e.g. headless); works for kit and newton. + while sim.is_headless_or_exist_active_visualizer(): + # Compute wrench from position controller + wrench = controller.compute(pos_command) # Shape: (1, 6) + + # Allocate wrench to thrusters: thrust = pinv(A) @ wrench + thrust_cmd = torch.matmul(wrench, alloc_pinv.T) # Shape: (1, num_thrusters) + thrust_cmd = thrust_cmd.clamp(min=0.0) # Ensure non-negative thrust + + # Apply thrust + robot.set_thrust_target(thrust_cmd) + + # Step simulation + robot.write_data_to_sim() + sim.step() + + # Update robot + robot.update(sim_cfg.dt) if __name__ == "__main__": From e7821c15719f78510b5c51a47569d72d7636c6c5 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Wed, 10 Jun 2026 22:08:23 +0800 Subject: [PATCH 05/19] Remove Options For deformables.py Signed-off-by: Yize Wang --- scripts/demos/deformables.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/demos/deformables.py b/scripts/demos/deformables.py index 3b066c78412b..0426167a3810 100644 --- a/scripts/demos/deformables.py +++ b/scripts/demos/deformables.py @@ -10,15 +10,9 @@ # Usage with default PhysX physics and default kit visualizer. ./isaaclab.sh -p scripts/demos/deformables.py - # Usage with Newton visualizer and default PhysX physics. - ./isaaclab.sh -p scripts/demos/deformables.py --visualizer newton - # Usage with Newton MJWarp backend and default kit visualizer. ./isaaclab.sh -p scripts/demos/deformables.py --physics newton_mjwarp - # Usage with Newton visualizer and Newton MJWarp backend. - ./isaaclab.sh -p scripts/demos/deformables.py --visualizer newton --physics newton_mjwarp - """ """Parse CLI first so we can decide whether to launch Isaac Sim Kit.""" From b206dc459f6ac5c5790c4c7b58cda22d78b67b57 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Wed, 10 Jun 2026 22:09:52 +0800 Subject: [PATCH 06/19] Remove Launch Options for arl_robot_1.py Signed-off-by: Yize Wang --- scripts/demos/arl_robot_1.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/demos/arl_robot_1.py b/scripts/demos/arl_robot_1.py index ec09dda6c8e5..842a288f29d5 100644 --- a/scripts/demos/arl_robot_1.py +++ b/scripts/demos/arl_robot_1.py @@ -13,12 +13,6 @@ # Usage with Newton visualizer and default PhysX physics. ./isaaclab.sh -p scripts/demos/arl_robot_1.py --visualizer newton - # Usage with Newton (MJWarp) physics and default kit visualizer. - ./isaaclab.sh -p scripts/demos/arl_robot_1.py --physics newton_mjwarp - - # Usage with Newton visualizer and Newton (MJWarp) physics. - ./isaaclab.sh -p scripts/demos/arl_robot_1.py --visualizer newton --physics newton_mjwarp - """ """Parse CLI first so we can decide whether to launch Isaac Sim Kit.""" From af8170b3114c7cced9212a199cf898ac684e3d30 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Wed, 10 Jun 2026 22:26:59 +0800 Subject: [PATCH 07/19] Remove Invalid Options Signed-off-by: Yize Wang --- scripts/demos/arl_robot_1.py | 2 +- scripts/demos/deformables.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/demos/arl_robot_1.py b/scripts/demos/arl_robot_1.py index 842a288f29d5..e83c528a3c54 100644 --- a/scripts/demos/arl_robot_1.py +++ b/scripts/demos/arl_robot_1.py @@ -25,7 +25,7 @@ description="View ARL Robot 1 with Lee Position Controller.", conflict_handler="resolve", ) -parser.add_argument("--physics", default="physx", choices=["physx", "newton_mjwarp"], help="Physics backend.") +parser.add_argument("--physics", default="physx", choices=["physx"], help="Physics backend.") add_launcher_args(parser) parser.set_defaults(visualizer=["kit"]) args_cli = parser.parse_args() diff --git a/scripts/demos/deformables.py b/scripts/demos/deformables.py index 0426167a3810..62a4008ebef2 100644 --- a/scripts/demos/deformables.py +++ b/scripts/demos/deformables.py @@ -28,7 +28,7 @@ description="This script demonstrates how to spawn deformable prims into the scene.", conflict_handler="resolve", ) -parser.add_argument("--physics", default="physx", choices=["physx", "newton_mjwarp"], help="Physics backend.") +parser.add_argument("--physics", default="physx", choices=["physx"], help="Physics backend.") add_launcher_args(parser) parser.set_defaults(visualizer=["kit"]) args_cli = parser.parse_args() From d0607d8232d0f5ed1fc20c4896aa5150be80f628 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Wed, 10 Jun 2026 22:33:35 +0800 Subject: [PATCH 08/19] Limit Launch Option for markers.py Signed-off-by: Yize Wang --- scripts/demos/markers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/demos/markers.py b/scripts/demos/markers.py index 2feb5de0a510..91dfe4c4d3db 100644 --- a/scripts/demos/markers.py +++ b/scripts/demos/markers.py @@ -24,7 +24,7 @@ description="This script demonstrates different types of markers.", conflict_handler="resolve", ) -parser.add_argument("--physics", default="physx", choices=["physx", "newton_mjwarp"], help="Physics backend.") +parser.add_argument("--physics", default="physx", choices=["physx"], help="Physics backend.") add_launcher_args(parser) parser.set_defaults(visualizer=["kit"]) args_cli = parser.parse_args() From 9efc56626e5d4df0342378095bbc4e605bb5b106 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Wed, 10 Jun 2026 22:47:41 +0800 Subject: [PATCH 09/19] Adapt multi_asset.py Signed-off-by: Yize Wang --- scripts/demos/multi_asset.py | 112 +++++++++++++++++------------------ 1 file changed, 55 insertions(+), 57 deletions(-) diff --git a/scripts/demos/multi_asset.py b/scripts/demos/multi_asset.py index 907c993e9549..12a3fa9bc516 100644 --- a/scripts/demos/multi_asset.py +++ b/scripts/demos/multi_asset.py @@ -7,62 +7,60 @@ .. code-block:: bash - # Usage - ./isaaclab.sh -p scripts/demos/multi_asset.py --num_envs 2048 + # Usage with default PhysX physics and default kit visualizer. + ./isaaclab.sh -p scripts/demos/multi_asset.py --num_envs 128 + + # Usage with Newton visualizer and default PhysX physics. + ./isaaclab.sh -p scripts/demos/multi_asset.py --visualizer newton --num_envs 128 """ from __future__ import annotations -"""Launch Isaac Sim Simulator first.""" - +"""Parse CLI first so we can decide whether to launch Isaac Sim Kit.""" import argparse +from typing import TYPE_CHECKING -from isaaclab.app import AppLauncher +from isaaclab.app import add_launcher_args, launch_simulation # add argparse arguments -parser = argparse.ArgumentParser(description="Demo on spawning different objects in multiple environments.") +parser = argparse.ArgumentParser( + description="Demo on spawning different objects in multiple environments.", + conflict_handler="resolve", +) parser.add_argument("--num_envs", type=int, default=512, help="Number of environments to spawn.") -# append AppLauncher cli args -AppLauncher.add_app_launcher_args(parser) +parser.add_argument("--physics", default="physx", choices=["physx", "newton_mjwarp"], help="Physics backend.") +add_launcher_args(parser) # demos should open Kit visualizer by default parser.set_defaults(visualizer=["kit"]) # parse the arguments args_cli = parser.parse_args() -# launch omniverse app -app_launcher = AppLauncher(args_cli) -simulation_app = app_launcher.app - """Rest everything follows.""" import random -from pxr import Gf, Sdf - import isaaclab.sim as sim_utils -from isaaclab.assets import ( - Articulation, - ArticulationCfg, - AssetBaseCfg, - RigidObject, - RigidObjectCfg, - RigidObjectCollection, - RigidObjectCollectionCfg, -) -from isaaclab.scene import InteractiveScene, InteractiveSceneCfg -from isaaclab.sim import SimulationContext + +## +# Pre-defined configs +## +from isaaclab.assets import ArticulationCfg,AssetBaseCfg,RigidObjectCfg,RigidObjectCollectionCfg +from isaaclab.physics import PhysicsCfg +from isaaclab.scene import InteractiveSceneCfg +from isaaclab_newton.physics import MJWarpSolverCfg, NewtonCfg # isort:skip +from isaaclab_assets.robots.anymal import ANYDRIVE_3_LSTM_ACTUATOR_CFG # isort: skip + from isaaclab.sim.utils.stage import get_current_stage from isaaclab.utils import Timer from isaaclab.utils.assets import ISAACLAB_NUCLEUS_DIR from isaaclab.utils.configclass import configclass -## -# Pre-defined Configuration -## -from isaaclab_assets.robots.anymal import ANYDRIVE_3_LSTM_ACTUATOR_CFG # isort: skip +if TYPE_CHECKING: + from isaaclab.assets import Articulation, RigidObject, RigidObjectCollection + from isaaclab.scene import InteractiveScene ## @@ -72,6 +70,8 @@ def randomize_shape_color(prim_path_expr: str): """Randomize the color of the geometry.""" + from pxr import Gf, Sdf + # get stage handle stage = get_current_stage() # resolve prim paths for spawning and cloning @@ -223,7 +223,7 @@ class MultiObjectSceneCfg(InteractiveSceneCfg): ## -def run_simulator(sim: SimulationContext, scene: InteractiveScene): +def run_simulator(sim: "sim_utils.SimulationContext", scene: "InteractiveScene"): """Runs the simulation loop.""" # Extract scene entities # note: we only do this here for readability. @@ -233,8 +233,8 @@ def run_simulator(sim: SimulationContext, scene: InteractiveScene): # Define simulation stepping sim_dt = sim.get_physics_dt() count = 0 - # Simulation loop - while simulation_app.is_running(): + # Step while a visualizer window is still open (or none exist, e.g. headless); works for kit and newton. + while sim.is_headless_or_exist_active_visualizer(): # Reset if count % 250 == 0: # reset counter @@ -284,33 +284,31 @@ def run_simulator(sim: SimulationContext, scene: InteractiveScene): def main(): """Main function.""" - # Load kit helper - sim_cfg = sim_utils.SimulationCfg(dt=0.005, device=args_cli.device) - sim = SimulationContext(sim_cfg) - # Set main camera - sim.set_camera_view([2.5, 0.0, 4.0], [0.0, 0.0, 2.0]) - - # Design scene - scene_cfg = MultiObjectSceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0, replicate_physics=True) - with Timer("[INFO] Time to create scene: "): - scene = InteractiveScene(scene_cfg) - - with Timer("[INFO] Time to randomize scene: "): - # DO YOUR OWN OTHER KIND OF RANDOMIZATION HERE! - # Note: Just need to acquire the right attribute about the property you want to set - # Here is an example on setting color randomly - randomize_shape_color(scene_cfg.object.prim_path) - - # Play the simulator - sim.reset() - # Now we are ready! - print("[INFO]: Setup complete...") - # Run the simulator - run_simulator(sim, scene) + with launch_simulation(cfg=PhysicsCfg(), launcher_args=args_cli) as physics_cfg: + sim_cfg = sim_utils.SimulationCfg(dt=0.005, device=args_cli.device, physics=physics_cfg) + sim = sim_utils.SimulationContext(sim_cfg) + # Set main camera + sim.set_camera_view([2.5, 0.0, 4.0], [0.0, 0.0, 2.0]) + + # Design scene + scene_cfg = MultiObjectSceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0, replicate_physics=True) + with Timer("[INFO] Time to create scene: "): + scene = scene_cfg.class_type(scene_cfg) + + with Timer("[INFO] Time to randomize scene: "): + # DO YOUR OWN OTHER KIND OF RANDOMIZATION HERE! + # Note: Just need to acquire the right attribute about the property you want to set + # Here is an example on setting color randomly + randomize_shape_color(scene_cfg.object.prim_path) + + # Play the simulator + sim.reset() + # Now we are ready! + print("[INFO]: Setup complete...") + # Run the simulator + run_simulator(sim, scene) if __name__ == "__main__": # run the main execution main() - # close sim app - simulation_app.close() From 06630daf0f8d6790d7edda86d8255f180531dd8a Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Wed, 10 Jun 2026 22:52:23 +0800 Subject: [PATCH 10/19] Adapt haply_teleoperation.py Signed-off-by: Yize Wang --- scripts/demos/haply_teleoperation.py | 94 +++++++++++++++++----------- 1 file changed, 57 insertions(+), 37 deletions(-) diff --git a/scripts/demos/haply_teleoperation.py b/scripts/demos/haply_teleoperation.py index 9880cae46f2e..fd144dac2c45 100644 --- a/scripts/demos/haply_teleoperation.py +++ b/scripts/demos/haply_teleoperation.py @@ -14,9 +14,18 @@ .. code-block:: bash - # Usage + # Usage with default PhysX physics and default kit visualizer. ./isaaclab.sh -p scripts/demos/haply_teleoperation.py + # Usage with Newton visualizer and default PhysX physics. + ./isaaclab.sh -p scripts/demos/haply_teleoperation.py --visualizer newton + + # Usage with Newton (MJWarp) physics and default kit visualizer. + ./isaaclab.sh -p scripts/demos/haply_teleoperation.py --physics newton_mjwarp + + # Usage with Newton visualizer and Newton (MJWarp) physics. + ./isaaclab.sh -p scripts/demos/haply_teleoperation.py --visualizer newton --physics newton_mjwarp + # With custom WebSocket URI ./isaaclab.sh -p scripts/demos/haply_teleoperation.py --websocket_uri ws://localhost:10001 @@ -29,15 +38,20 @@ 3. Connect Inverse3 and VerseGrip devices """ -"""Launch Isaac Sim Simulator first.""" +"""Parse CLI first so we can decide whether to launch Isaac Sim Kit.""" import argparse +from typing import TYPE_CHECKING -from isaaclab.app import AppLauncher +from isaaclab.app import add_launcher_args, launch_simulation # add argparse arguments -parser = argparse.ArgumentParser(description="Demonstration of Haply device teleoperation with Isaac Lab.") +parser = argparse.ArgumentParser( + description="Demonstration of Haply device teleoperation with Isaac Lab.", + conflict_handler="resolve", +) parser.add_argument("--num_envs", type=int, default=1, help="Number of environments to spawn.") +parser.add_argument("--physics", default="physx", choices=["physx", "newton_mjwarp"], help="Physics backend.") parser.add_argument( "--websocket_uri", type=str, @@ -51,26 +65,32 @@ help="Position sensitivity scaling factor.", ) -AppLauncher.add_app_launcher_args(parser) +add_launcher_args(parser) parser.set_defaults(visualizer=["kit"]) args_cli = parser.parse_args() -app_launcher = AppLauncher(args_cli) -simulation_app = app_launcher.app import numpy as np import torch import isaaclab.sim as sim_utils -from isaaclab.assets import Articulation, AssetBaseCfg, RigidObject, RigidObjectCfg +from isaaclab.assets import ArticulationCfg, AssetBaseCfg, RigidObjectCfg from isaaclab.controllers import DifferentialIKController, DifferentialIKControllerCfg -from isaaclab.devices import HaplyDevice, HaplyDeviceCfg -from isaaclab.scene import InteractiveScene, InteractiveSceneCfg -from isaaclab.sensors import ContactSensor, ContactSensorCfg +from isaaclab.devices import HaplyDeviceCfg +from isaaclab.physics import PhysicsCfg +from isaaclab.scene import InteractiveSceneCfg +from isaaclab.sensors import ContactSensorCfg from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR from isaaclab.utils.configclass import configclass +from isaaclab_newton.physics import MJWarpSolverCfg, NewtonCfg # isort:skip from isaaclab_assets import FRANKA_PANDA_HIGH_PD_CFG # isort: skip +if TYPE_CHECKING: + from isaaclab.assets import Articulation, RigidObject + from isaaclab.devices import HaplyDevice + from isaaclab.scene import InteractiveScene + from isaaclab.sensors import ContactSensor + # Workspace mapping constants HAPLY_Z_OFFSET = 0.35 WORKSPACE_LIMITS = { @@ -141,7 +161,7 @@ class FrankaHaplySceneCfg(InteractiveSceneCfg): init_state=AssetBaseCfg.InitialStateCfg(pos=(0.50, 0.0, 1.05), rot=(0.707, 0, 0, 0.707)), ) - robot: Articulation = FRANKA_PANDA_HIGH_PD_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot") + robot: ArticulationCfg = FRANKA_PANDA_HIGH_PD_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot") robot.init_state.pos = (-0.02, 0.0, 1.05) robot.spawn.activate_contact_sensors = True @@ -176,9 +196,9 @@ class FrankaHaplySceneCfg(InteractiveSceneCfg): def run_simulator( - sim: sim_utils.SimulationContext, - scene: InteractiveScene, - haply_device: HaplyDevice, + sim: "sim_utils.SimulationContext", + scene: "InteractiveScene", + haply_device: "HaplyDevice", ): """Runs the simulation loop with Haply teleoperation.""" sim_dt = sim.get_physics_dt() @@ -246,7 +266,7 @@ def run_simulator( print(" Move handler: Control pose of the end-effector") print(" Button A: Open | Button B: Close | Button C: Rotate EE (60°)\n") - while simulation_app.is_running(): + while sim.is_headless_or_exist_active_visualizer(): if count % 10000 == 0: count = 1 root_pose = robot.data.default_root_pose.torch.clone() @@ -343,30 +363,30 @@ def run_simulator( def main(): """Main function to set up and run the Haply teleoperation demo.""" - sim_cfg = sim_utils.SimulationCfg(device=args_cli.device, dt=1 / 200) - sim = sim_utils.SimulationContext(sim_cfg) - - # set the simulation view - sim.set_camera_view([1.6, 1.0, 1.70], [0.4, 0.0, 1.0]) - - scene_cfg = FrankaHaplySceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0) - scene = InteractiveScene(scene_cfg) - - # Create Haply device - haply_cfg = HaplyDeviceCfg( - websocket_uri=args_cli.websocket_uri, - pos_sensitivity=args_cli.pos_sensitivity, - sim_device=args_cli.device, - limit_force=2.0, - ) - haply_device = HaplyDevice(cfg=haply_cfg) - print(f"[INFO] Haply connected: {args_cli.websocket_uri}") + with launch_simulation(cfg=PhysicsCfg(), launcher_args=args_cli) as physics_cfg: + sim_cfg = sim_utils.SimulationCfg(device=args_cli.device, dt=1 / 200, physics=physics_cfg) + sim = sim_utils.SimulationContext(sim_cfg) + + # set the simulation view + sim.set_camera_view([1.6, 1.0, 1.70], [0.4, 0.0, 1.0]) + + scene_cfg = FrankaHaplySceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0) + scene = scene_cfg.class_type(scene_cfg) + + # Create Haply device + haply_cfg = HaplyDeviceCfg( + websocket_uri=args_cli.websocket_uri, + pos_sensitivity=args_cli.pos_sensitivity, + sim_device=args_cli.device, + limit_force=2.0, + ) + haply_device = haply_cfg.class_type(cfg=haply_cfg) + print(f"[INFO] Haply connected: {args_cli.websocket_uri}") - sim.reset() + sim.reset() - run_simulator(sim, scene, haply_device) + run_simulator(sim, scene, haply_device) if __name__ == "__main__": main() - simulation_app.close() From 81a544510d86db42eba5de386cd3a087f899f653 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Thu, 11 Jun 2026 14:02:13 +0800 Subject: [PATCH 11/19] Limit Visualizer Options Signed-off-by: Yize Wang --- scripts/demos/deformables.py | 4 +++- scripts/demos/markers.py | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/demos/deformables.py b/scripts/demos/deformables.py index 62a4008ebef2..313138162691 100644 --- a/scripts/demos/deformables.py +++ b/scripts/demos/deformables.py @@ -28,7 +28,9 @@ description="This script demonstrates how to spawn deformable prims into the scene.", conflict_handler="resolve", ) -parser.add_argument("--physics", default="physx", choices=["physx"], help="Physics backend.") +parser.add_argument("--physics", default="physx", choices=["physx", "newton_mjwarp"], help="Physics backend.") +# Newton visualizer not supported for deformables +parser.add_argument("--visualizer", default="kit", choices=["kit"], help="Visualizer backend.") add_launcher_args(parser) parser.set_defaults(visualizer=["kit"]) args_cli = parser.parse_args() diff --git a/scripts/demos/markers.py b/scripts/demos/markers.py index 91dfe4c4d3db..5f023cfed582 100644 --- a/scripts/demos/markers.py +++ b/scripts/demos/markers.py @@ -25,6 +25,8 @@ conflict_handler="resolve", ) parser.add_argument("--physics", default="physx", choices=["physx"], help="Physics backend.") +# Newton visualizer not supported for markers +parser.add_argument("--visualizer", default="kit", choices=["kit"], help="Visualizer backend.") add_launcher_args(parser) parser.set_defaults(visualizer=["kit"]) args_cli = parser.parse_args() From 3e1dd04aea4024a77a89687ac18e3a6d3061d3e6 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Thu, 11 Jun 2026 14:45:46 +0800 Subject: [PATCH 12/19] Minor Changes Signed-off-by: Yize Wang --- scripts/demos/multi_asset.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/scripts/demos/multi_asset.py b/scripts/demos/multi_asset.py index 12a3fa9bc516..edcc6d0c3d94 100644 --- a/scripts/demos/multi_asset.py +++ b/scripts/demos/multi_asset.py @@ -46,10 +46,9 @@ ## # Pre-defined configs ## -from isaaclab.assets import ArticulationCfg,AssetBaseCfg,RigidObjectCfg,RigidObjectCollectionCfg +from isaaclab.assets import ArticulationCfg, AssetBaseCfg, RigidObjectCfg, RigidObjectCollectionCfg from isaaclab.physics import PhysicsCfg from isaaclab.scene import InteractiveSceneCfg -from isaaclab_newton.physics import MJWarpSolverCfg, NewtonCfg # isort:skip from isaaclab_assets.robots.anymal import ANYDRIVE_3_LSTM_ACTUATOR_CFG # isort: skip from isaaclab.sim.utils.stage import get_current_stage @@ -257,13 +256,11 @@ def run_simulator(sim: "sim_utils.SimulationContext", scene: "InteractiveScene") root_pose = robot.data.default_root_pose.torch.clone() root_pose[:, :3] += scene.env_origins robot.write_root_pose_to_sim_index(root_pose=root_pose) - root_vel = robot.data.default_root_vel.torch.clone() + root_vel = robot.data.default_root_vel.torch robot.write_root_velocity_to_sim_index(root_velocity=root_vel) # -- joint state - joint_pos, joint_vel = ( - robot.data.default_joint_pos.torch.clone(), - robot.data.default_joint_vel.torch.clone(), - ) + joint_pos = robot.data.default_joint_pos.torch + joint_vel = robot.data.default_joint_vel.torch robot.write_joint_position_to_sim_index(position=joint_pos) robot.write_joint_velocity_to_sim_index(velocity=joint_vel) # clear internal buffers From e80df72992b22a751e75900a45423afb08b91f79 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Thu, 11 Jun 2026 15:37:12 +0800 Subject: [PATCH 13/19] Remove Cone for multi_asset.py Signed-off-by: Yize Wang --- scripts/demos/multi_asset.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/demos/multi_asset.py b/scripts/demos/multi_asset.py index edcc6d0c3d94..973357148949 100644 --- a/scripts/demos/multi_asset.py +++ b/scripts/demos/multi_asset.py @@ -110,7 +110,7 @@ class MultiObjectSceneCfg(InteractiveSceneCfg): prim_path="/World/envs/env_.*/Object", spawn=sim_utils.MultiAssetSpawnerCfg( assets_cfg=[ - sim_utils.ConeCfg( + (sim_utils.CylinderCfg)( radius=0.3, height=0.6, visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0), metallic=0.2), @@ -138,7 +138,7 @@ class MultiObjectSceneCfg(InteractiveSceneCfg): object_collection: RigidObjectCollectionCfg = RigidObjectCollectionCfg( rigid_objects={ "object_A": RigidObjectCfg( - prim_path="/World/envs/env_.*/Object_A", + prim_path="/World/envs/env_.*/ObjectCollection/Object_A", spawn=sim_utils.SphereCfg( radius=0.1, visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.0, 0.0), metallic=0.2), @@ -151,7 +151,7 @@ class MultiObjectSceneCfg(InteractiveSceneCfg): init_state=RigidObjectCfg.InitialStateCfg(pos=(0.0, -0.5, 2.0)), ), "object_B": RigidObjectCfg( - prim_path="/World/envs/env_.*/Object_B", + prim_path="/World/envs/env_.*/ObjectCollection/Object_B", spawn=sim_utils.CuboidCfg( size=(0.1, 0.1, 0.1), visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.0, 0.0), metallic=0.2), @@ -164,8 +164,8 @@ class MultiObjectSceneCfg(InteractiveSceneCfg): init_state=RigidObjectCfg.InitialStateCfg(pos=(0.0, 0.5, 2.0)), ), "object_C": RigidObjectCfg( - prim_path="/World/envs/env_.*/Object_C", - spawn=sim_utils.ConeCfg( + prim_path="/World/envs/env_.*/ObjectCollection/Object_C", + spawn=sim_utils.CylinderCfg( radius=0.1, height=0.3, visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.0, 0.0), metallic=0.2), From e0a0bcacc4989e7e5a4700e864b391f448e4765e Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Thu, 11 Jun 2026 15:48:44 +0800 Subject: [PATCH 14/19] Unify Demo Scripts Signed-off-by: Yize Wang --- scripts/demos/arl_robot_1.py | 2 -- scripts/demos/arms.py | 7 +++---- scripts/demos/bin_packing.py | 10 +++++----- scripts/demos/bipeds.py | 3 +-- scripts/demos/deformables.py | 2 -- scripts/demos/h1_locomotion.py | 2 -- scripts/demos/hands.py | 5 ++--- scripts/demos/haply_teleoperation.py | 6 ++++-- scripts/demos/markers.py | 2 -- scripts/demos/pick_and_place.py | 2 -- scripts/demos/procedural_terrain.py | 2 -- scripts/demos/quadcopter.py | 3 +-- scripts/demos/quadrupeds.py | 3 +-- 13 files changed, 17 insertions(+), 32 deletions(-) diff --git a/scripts/demos/arl_robot_1.py b/scripts/demos/arl_robot_1.py index e83c528a3c54..bc9f368d11c4 100644 --- a/scripts/demos/arl_robot_1.py +++ b/scripts/demos/arl_robot_1.py @@ -30,8 +30,6 @@ parser.set_defaults(visualizer=["kit"]) args_cli = parser.parse_args() -"""Rest everything follows.""" - import torch import isaaclab.sim as sim_utils diff --git a/scripts/demos/arms.py b/scripts/demos/arms.py index 7575ddb81a52..b8c4ff6feb7a 100644 --- a/scripts/demos/arms.py +++ b/scripts/demos/arms.py @@ -3,8 +3,7 @@ # # SPDX-License-Identifier: BSD-3-Clause -""" -This script demonstrates different single-arm manipulators. +"""This script demonstrates different single-arm manipulators. .. code-block:: bash @@ -60,7 +59,7 @@ def define_origins(num_origins: int, spacing: float) -> list[list[float]]: - """Defines the origins of the the scene.""" + """Defines the origins of the scene.""" # create tensor based on number of environments env_origins = torch.zeros(num_origins, 3) # create a grid of origins @@ -214,7 +213,7 @@ def run_simulator(sim: "sim_utils.SimulationContext", entities: dict[str, "Artic robot.update(sim_dt) -def main(): +def main() """Main function.""" with launch_simulation(cfg=PhysicsCfg(), launcher_args=args_cli) as physics_cfg: # The default newton mjwarp solver configuration needs to be tuned for these arms. diff --git a/scripts/demos/bin_packing.py b/scripts/demos/bin_packing.py index 273f633fecd4..4b4a9145e4cc 100644 --- a/scripts/demos/bin_packing.py +++ b/scripts/demos/bin_packing.py @@ -50,19 +50,19 @@ import torch +import isaaclab.sim as sim_utils +import isaaclab.utils.math as math_utils + ## # Pre-defined configs ## -from isaaclab_newton.physics import MJWarpSolverCfg, NewtonCfg - -import isaaclab.sim as sim_utils -import isaaclab.utils.math as math_utils from isaaclab.assets import AssetBaseCfg, RigidObjectCfg, RigidObjectCollectionCfg from isaaclab.physics import PhysicsCfg from isaaclab.scene import InteractiveScene, InteractiveSceneCfg from isaaclab.utils import Timer from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR from isaaclab.utils.configclass import configclass +from isaaclab_newton.physics import MJWarpSolverCfg, NewtonCfg # isort:skip if TYPE_CHECKING: from isaaclab.assets import RigidObjectCollection @@ -348,7 +348,7 @@ def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene) -> scene.update(sim_dt) -def main() -> None: +def main(): """Main function. Returns: diff --git a/scripts/demos/bipeds.py b/scripts/demos/bipeds.py index 36a51e7def2e..8bd47a711e13 100644 --- a/scripts/demos/bipeds.py +++ b/scripts/demos/bipeds.py @@ -3,8 +3,7 @@ # # SPDX-License-Identifier: BSD-3-Clause -""" -This script demonstrates how to simulate bipedal robots. +"""This script demonstrates how to simulate bipedal robots. .. code-block:: bash diff --git a/scripts/demos/deformables.py b/scripts/demos/deformables.py index 313138162691..eb2283135b5b 100644 --- a/scripts/demos/deformables.py +++ b/scripts/demos/deformables.py @@ -35,8 +35,6 @@ parser.set_defaults(visualizer=["kit"]) args_cli = parser.parse_args() -"""Rest everything follows.""" - import random import numpy as np diff --git a/scripts/demos/h1_locomotion.py b/scripts/demos/h1_locomotion.py index 04b394a13479..321bd331608d 100644 --- a/scripts/demos/h1_locomotion.py +++ b/scripts/demos/h1_locomotion.py @@ -43,8 +43,6 @@ app_launcher = AppLauncher(args_cli) simulation_app = app_launcher.app -"""Rest everything follows.""" - import torch from rsl_rl.runners import OnPolicyRunner diff --git a/scripts/demos/hands.py b/scripts/demos/hands.py index 3f64104d945a..06cb367c90a1 100644 --- a/scripts/demos/hands.py +++ b/scripts/demos/hands.py @@ -3,8 +3,7 @@ # # SPDX-License-Identifier: BSD-3-Clause -""" -This script demonstrates different dexterous hands. +"""This script demonstrates different dexterous hands. .. code-block:: bash @@ -58,7 +57,7 @@ def define_origins(num_origins: int, spacing: float) -> list[list[float]]: - """Defines the origins of the the scene.""" + """Defines the origins of the scene.""" # create tensor based on number of environments env_origins = torch.zeros(num_origins, 3) # create a grid of origins diff --git a/scripts/demos/haply_teleoperation.py b/scripts/demos/haply_teleoperation.py index fd144dac2c45..b7c84a0cef4f 100644 --- a/scripts/demos/haply_teleoperation.py +++ b/scripts/demos/haply_teleoperation.py @@ -73,6 +73,10 @@ import torch import isaaclab.sim as sim_utils + +## +# Pre-defined configs +## from isaaclab.assets import ArticulationCfg, AssetBaseCfg, RigidObjectCfg from isaaclab.controllers import DifferentialIKController, DifferentialIKControllerCfg from isaaclab.devices import HaplyDeviceCfg @@ -81,8 +85,6 @@ from isaaclab.sensors import ContactSensorCfg from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR from isaaclab.utils.configclass import configclass - -from isaaclab_newton.physics import MJWarpSolverCfg, NewtonCfg # isort:skip from isaaclab_assets import FRANKA_PANDA_HIGH_PD_CFG # isort: skip if TYPE_CHECKING: diff --git a/scripts/demos/markers.py b/scripts/demos/markers.py index 5f023cfed582..78e54c559675 100644 --- a/scripts/demos/markers.py +++ b/scripts/demos/markers.py @@ -31,8 +31,6 @@ parser.set_defaults(visualizer=["kit"]) args_cli = parser.parse_args() -"""Rest everything follows.""" - import torch import isaaclab.sim as sim_utils diff --git a/scripts/demos/pick_and_place.py b/scripts/demos/pick_and_place.py index aa99cb1480fd..b55fd5ca44ec 100644 --- a/scripts/demos/pick_and_place.py +++ b/scripts/demos/pick_and_place.py @@ -23,8 +23,6 @@ app_launcher = AppLauncher(args_cli) simulation_app = app_launcher.app -"""Rest everything follows.""" - from collections.abc import Sequence import torch diff --git a/scripts/demos/procedural_terrain.py b/scripts/demos/procedural_terrain.py index 30d871b20241..36ebc4fa12f5 100644 --- a/scripts/demos/procedural_terrain.py +++ b/scripts/demos/procedural_terrain.py @@ -65,8 +65,6 @@ parser.set_defaults(visualizer=["kit"]) args_cli = parser.parse_args() -"""Rest everything follows.""" - import random import torch diff --git a/scripts/demos/quadcopter.py b/scripts/demos/quadcopter.py index 2c8215cbc152..1558960812c8 100644 --- a/scripts/demos/quadcopter.py +++ b/scripts/demos/quadcopter.py @@ -3,8 +3,7 @@ # # SPDX-License-Identifier: BSD-3-Clause -""" -This script demonstrates how to simulate a quadcopter. +"""This script demonstrates how to simulate a quadcopter. .. code-block:: bash diff --git a/scripts/demos/quadrupeds.py b/scripts/demos/quadrupeds.py index 901c91e0b425..02aeb864f358 100644 --- a/scripts/demos/quadrupeds.py +++ b/scripts/demos/quadrupeds.py @@ -3,8 +3,7 @@ # # SPDX-License-Identifier: BSD-3-Clause -""" -This script demonstrates different legged robots. +"""This script demonstrates different legged robots. .. code-block:: bash From 1f89b384cf8f0de08a7c3da232e3e5371bf210a2 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Thu, 11 Jun 2026 16:19:08 +0800 Subject: [PATCH 15/19] Minor Change Signed-off-by: Yize Wang --- scripts/demos/arms.py | 2 +- scripts/demos/bin_packing.py | 1 + scripts/demos/haply_teleoperation.py | 1 + scripts/demos/procedural_terrain.py | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/demos/arms.py b/scripts/demos/arms.py index b8c4ff6feb7a..edaa0a7f0684 100644 --- a/scripts/demos/arms.py +++ b/scripts/demos/arms.py @@ -213,7 +213,7 @@ def run_simulator(sim: "sim_utils.SimulationContext", entities: dict[str, "Artic robot.update(sim_dt) -def main() +def main(): """Main function.""" with launch_simulation(cfg=PhysicsCfg(), launcher_args=args_cli) as physics_cfg: # The default newton mjwarp solver configuration needs to be tuned for these arms. diff --git a/scripts/demos/bin_packing.py b/scripts/demos/bin_packing.py index 4b4a9145e4cc..ba7fb6e1e5f3 100644 --- a/scripts/demos/bin_packing.py +++ b/scripts/demos/bin_packing.py @@ -62,6 +62,7 @@ from isaaclab.utils import Timer from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR from isaaclab.utils.configclass import configclass + from isaaclab_newton.physics import MJWarpSolverCfg, NewtonCfg # isort:skip if TYPE_CHECKING: diff --git a/scripts/demos/haply_teleoperation.py b/scripts/demos/haply_teleoperation.py index b7c84a0cef4f..ee4b5a83a87e 100644 --- a/scripts/demos/haply_teleoperation.py +++ b/scripts/demos/haply_teleoperation.py @@ -85,6 +85,7 @@ from isaaclab.sensors import ContactSensorCfg from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR from isaaclab.utils.configclass import configclass + from isaaclab_assets import FRANKA_PANDA_HIGH_PD_CFG # isort: skip if TYPE_CHECKING: diff --git a/scripts/demos/procedural_terrain.py b/scripts/demos/procedural_terrain.py index 36ebc4fa12f5..6e26a8b26536 100644 --- a/scripts/demos/procedural_terrain.py +++ b/scripts/demos/procedural_terrain.py @@ -60,7 +60,7 @@ default=False, help="Whether to show the flat patches computed during the terrain generation.", ) -parser.add_argument("--physics", default="physx", choices=["physx", "newton_mjwarp"], help="Physics backend.") +parser.add_argument("--physics", default="physx", choices=["physx"], help="Physics backend.") add_launcher_args(parser) parser.set_defaults(visualizer=["kit"]) args_cli = parser.parse_args() From 00e675177a1e62a875f35bddc004f5a9d94b2195 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Thu, 11 Jun 2026 16:53:00 +0800 Subject: [PATCH 16/19] Clean Up multi_asset.py Signed-off-by: Yize Wang --- scripts/demos/multi_asset.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/scripts/demos/multi_asset.py b/scripts/demos/multi_asset.py index 973357148949..662f1889896a 100644 --- a/scripts/demos/multi_asset.py +++ b/scripts/demos/multi_asset.py @@ -13,6 +13,12 @@ # Usage with Newton visualizer and default PhysX physics. ./isaaclab.sh -p scripts/demos/multi_asset.py --visualizer newton --num_envs 128 + # Usage with Newton (MJWarp) physics and default kit visualizer. + ./isaaclab.sh -p scripts/demos/multi_asset.py --physics newton_mjwarp --num_envs 128 + + # Usage with Newton visualizer and Newton (MJWarp) physics. + ./isaaclab.sh -p scripts/demos/multi_asset.py --visualizer newton --physics newton_mjwarp --num_envs 128 + """ from __future__ import annotations @@ -37,8 +43,6 @@ # parse the arguments args_cli = parser.parse_args() -"""Rest everything follows.""" - import random import isaaclab.sim as sim_utils @@ -49,6 +53,7 @@ from isaaclab.assets import ArticulationCfg, AssetBaseCfg, RigidObjectCfg, RigidObjectCollectionCfg from isaaclab.physics import PhysicsCfg from isaaclab.scene import InteractiveSceneCfg + from isaaclab_assets.robots.anymal import ANYDRIVE_3_LSTM_ACTUATOR_CFG # isort: skip from isaaclab.sim.utils.stage import get_current_stage @@ -56,7 +61,6 @@ from isaaclab.utils.assets import ISAACLAB_NUCLEUS_DIR from isaaclab.utils.configclass import configclass - if TYPE_CHECKING: from isaaclab.assets import Articulation, RigidObject, RigidObjectCollection from isaaclab.scene import InteractiveScene @@ -85,7 +89,8 @@ def randomize_shape_color(prim_path_expr: str): # Note: Just need to acquire the right attribute about the property you want to set # Here is an example on setting color randomly color_spec = prim_spec.GetAttributeAtPath(prim_path + "/geometry/material/Shader.inputs:diffuseColor") - color_spec.default = Gf.Vec3f(random.random(), random.random(), random.random()) + if color_spec is not None: + color_spec.default = Gf.Vec3f(random.random(), random.random(), random.random()) ## @@ -222,7 +227,7 @@ class MultiObjectSceneCfg(InteractiveSceneCfg): ## -def run_simulator(sim: "sim_utils.SimulationContext", scene: "InteractiveScene"): +def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene): """Runs the simulation loop.""" # Extract scene entities # note: we only do this here for readability. @@ -289,6 +294,10 @@ def main(): # Design scene scene_cfg = MultiObjectSceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0, replicate_physics=True) + if args_cli.physics == "newton_mjwarp": + # Newton/MJWarp requires a uniform layout, not supporting different setups across environments. + scene_cfg.object.spawn.assets_cfg = scene_cfg.object.spawn.assets_cfg[1:2] + scene_cfg.robot.spawn.usd_path = scene_cfg.robot.spawn.usd_path[0] with Timer("[INFO] Time to create scene: "): scene = scene_cfg.class_type(scene_cfg) From 681d84fd978075b2010e3d7b3944225916496c4f Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Thu, 11 Jun 2026 17:27:41 +0800 Subject: [PATCH 17/19] Comments Signed-off-by: Yize Wang --- source/isaaclab/isaaclab/terrains/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/source/isaaclab/isaaclab/terrains/utils.py b/source/isaaclab/isaaclab/terrains/utils.py index eb29541d921f..739f80940021 100644 --- a/source/isaaclab/isaaclab/terrains/utils.py +++ b/source/isaaclab/isaaclab/terrains/utils.py @@ -52,6 +52,7 @@ def color_meshes_by_height(meshes: list[trimesh.Trimesh], **kwargs) -> trimesh.T # clip lower and upper bounds to have better color mapping heights_normalized = np.clip(heights_normalized, 0.1, 0.9) # Get the color for each vertex based on the height + # Valid options are ["viridis", "inferno", "plasma", "magma"] color_map = kwargs.pop("color_map", "inferno") colors = trimesh.visual.color.interpolate(heights_normalized, color_map=color_map) # Set the vertex colors From 9c97693d46e059a4ee96b05420aad0d2a8439243 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Thu, 11 Jun 2026 20:41:39 +0800 Subject: [PATCH 18/19] Robot Fix in haply_teleoperation.py Signed-off-by: Yize Wang --- scripts/demos/haply_teleoperation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/demos/haply_teleoperation.py b/scripts/demos/haply_teleoperation.py index ee4b5a83a87e..f28626ecb6c3 100644 --- a/scripts/demos/haply_teleoperation.py +++ b/scripts/demos/haply_teleoperation.py @@ -164,7 +164,8 @@ class FrankaHaplySceneCfg(InteractiveSceneCfg): init_state=AssetBaseCfg.InitialStateCfg(pos=(0.50, 0.0, 1.05), rot=(0.707, 0, 0, 0.707)), ) - robot: ArticulationCfg = FRANKA_PANDA_HIGH_PD_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot") + robot_cfg: ArticulationCfg = FRANKA_PANDA_HIGH_PD_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot") + robot = robot_cfg.class_type(robot_cfg) robot.init_state.pos = (-0.02, 0.0, 1.05) robot.spawn.activate_contact_sensors = True From cba2084f02a1f6a29ded7562430def4bc32d0a49 Mon Sep 17 00:00:00 2001 From: Yize Wang Date: Thu, 11 Jun 2026 22:18:57 +0800 Subject: [PATCH 19/19] Modify multi_asset.py Signed-off-by: Yize Wang --- scripts/demos/multi_asset.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/demos/multi_asset.py b/scripts/demos/multi_asset.py index 662f1889896a..be30806b76b6 100644 --- a/scripts/demos/multi_asset.py +++ b/scripts/demos/multi_asset.py @@ -8,16 +8,16 @@ .. code-block:: bash # Usage with default PhysX physics and default kit visualizer. - ./isaaclab.sh -p scripts/demos/multi_asset.py --num_envs 128 + ./isaaclab.sh -p scripts/demos/multi_asset.py --num_envs 1024 # Usage with Newton visualizer and default PhysX physics. - ./isaaclab.sh -p scripts/demos/multi_asset.py --visualizer newton --num_envs 128 + ./isaaclab.sh -p scripts/demos/multi_asset.py --visualizer newton --num_envs 1024 # Usage with Newton (MJWarp) physics and default kit visualizer. - ./isaaclab.sh -p scripts/demos/multi_asset.py --physics newton_mjwarp --num_envs 128 + ./isaaclab.sh -p scripts/demos/multi_asset.py --physics newton_mjwarp --num_envs 1024 # Usage with Newton visualizer and Newton (MJWarp) physics. - ./isaaclab.sh -p scripts/demos/multi_asset.py --visualizer newton --physics newton_mjwarp --num_envs 128 + ./isaaclab.sh -p scripts/demos/multi_asset.py --visualizer newton --physics newton_mjwarp --num_envs 1024 """ @@ -143,7 +143,7 @@ class MultiObjectSceneCfg(InteractiveSceneCfg): object_collection: RigidObjectCollectionCfg = RigidObjectCollectionCfg( rigid_objects={ "object_A": RigidObjectCfg( - prim_path="/World/envs/env_.*/ObjectCollection/Object_A", + prim_path="/World/envs/env_.*/Object_A", spawn=sim_utils.SphereCfg( radius=0.1, visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.0, 0.0), metallic=0.2), @@ -156,7 +156,7 @@ class MultiObjectSceneCfg(InteractiveSceneCfg): init_state=RigidObjectCfg.InitialStateCfg(pos=(0.0, -0.5, 2.0)), ), "object_B": RigidObjectCfg( - prim_path="/World/envs/env_.*/ObjectCollection/Object_B", + prim_path="/World/envs/env_.*/Object_B", spawn=sim_utils.CuboidCfg( size=(0.1, 0.1, 0.1), visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.0, 0.0), metallic=0.2), @@ -169,7 +169,7 @@ class MultiObjectSceneCfg(InteractiveSceneCfg): init_state=RigidObjectCfg.InitialStateCfg(pos=(0.0, 0.5, 2.0)), ), "object_C": RigidObjectCfg( - prim_path="/World/envs/env_.*/ObjectCollection/Object_C", + prim_path="/World/envs/env_.*/Object_C", spawn=sim_utils.CylinderCfg( radius=0.1, height=0.3,