Creating Visualization Markers

Creating Visualization Markers#

Visualization markers are useful to debug the state of the environment. They can be used to visualize the frames, commands, and other information in the simulation.

While Isaac Sim provides its own isaacsim.util.debug_draw extension, it is limited to rendering only points, lines and splines. For cases, where you need to render more complex shapes, you can use the markers.VisualizationMarkers class.

This guide is accompanied by a sample script markers.py in the IsaacLab/scripts/demos directory.

Code for markers.py
  1# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
  2# All rights reserved.
  3#
  4# SPDX-License-Identifier: BSD-3-Clause
  5
  6"""This script demonstrates different types of markers.
  7
  8.. code-block:: bash
  9
 10    # Usage
 11    ./isaaclab.sh -p scripts/demos/markers.py
 12
 13"""
 14
 15"""Launch Isaac Sim Simulator first."""
 16
 17import argparse
 18
 19from isaaclab.app import AppLauncher
 20
 21# add argparse arguments
 22parser = argparse.ArgumentParser(description="This script demonstrates different types of markers.")
 23# append AppLauncher cli args
 24AppLauncher.add_app_launcher_args(parser)
 25# demos should open Kit visualizer by default
 26parser.set_defaults(visualizer=["kit"])
 27# parse the arguments
 28args_cli = parser.parse_args()
 29
 30# launch omniverse app
 31app_launcher = AppLauncher(args_cli)
 32simulation_app = app_launcher.app
 33
 34"""Rest everything follows."""
 35
 36import torch
 37
 38import isaaclab.sim as sim_utils
 39from isaaclab.markers import VisualizationMarkers, VisualizationMarkersCfg
 40from isaaclab.sim import SimulationContext
 41from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR, ISAACLAB_NUCLEUS_DIR
 42from isaaclab.utils.math import quat_from_angle_axis
 43
 44
 45def define_markers() -> VisualizationMarkers:
 46    """Define markers with various different shapes."""
 47    marker_cfg = VisualizationMarkersCfg(
 48        prim_path="/Visuals/myMarkers",
 49        markers={
 50            "frame": sim_utils.UsdFileCfg(
 51                usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/UIElements/frame_prim.usd",
 52                scale=(0.5, 0.5, 0.5),
 53            ),
 54            "arrow_x": sim_utils.UsdFileCfg(
 55                usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/UIElements/arrow_x.usd",
 56                scale=(1.0, 0.5, 0.5),
 57                visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 1.0)),
 58            ),
 59            "cube": sim_utils.CuboidCfg(
 60                size=(1.0, 1.0, 1.0),
 61                visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.0, 0.0)),
 62            ),
 63            "sphere": sim_utils.SphereCfg(
 64                radius=0.5,
 65                visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0)),
 66            ),
 67            "cylinder": sim_utils.CylinderCfg(
 68                radius=0.5,
 69                height=1.0,
 70                visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 0.0, 1.0)),
 71            ),
 72            "cone": sim_utils.ConeCfg(
 73                radius=0.5,
 74                height=1.0,
 75                visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 1.0, 0.0)),
 76            ),
 77            "mesh": sim_utils.UsdFileCfg(
 78                usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/DexCube/dex_cube_instanceable.usd",
 79                scale=(10.0, 10.0, 10.0),
 80            ),
 81            "mesh_recolored": sim_utils.UsdFileCfg(
 82                usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/DexCube/dex_cube_instanceable.usd",
 83                scale=(10.0, 10.0, 10.0),
 84                visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.25, 0.0)),
 85            ),
 86            "robot_mesh": sim_utils.UsdFileCfg(
 87                usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/ANYbotics/ANYmal-C/anymal_c.usd",
 88                scale=(2.0, 2.0, 2.0),
 89                visual_material=sim_utils.GlassMdlCfg(glass_color=(0.0, 0.1, 0.0)),
 90            ),
 91        },
 92    )
 93    return VisualizationMarkers(marker_cfg)
 94
 95
 96def main():
 97    """Main function."""
 98    # Load kit helper
 99    sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device)
100    sim = SimulationContext(sim_cfg)
101    # Set main camera
102    sim.set_camera_view([0.0, 18.0, 12.0], [0.0, 3.0, 0.0])
103
104    # Spawn things into stage
105    # Lights
106    cfg = sim_utils.DomeLightCfg(intensity=3000.0, color=(0.75, 0.75, 0.75))
107    cfg.func("/World/Light", cfg)
108
109    # create markers
110    my_visualizer = define_markers()
111
112    # define a grid of positions where the markers should be placed
113    num_markers_per_type = 5
114    grid_spacing = 2.0
115    # Calculate the half-width and half-height
116    half_width = (num_markers_per_type - 1) / 2.0
117    half_height = (my_visualizer.num_prototypes - 1) / 2.0
118    # Create the x and y ranges centered around the origin
119    x_range = torch.arange(-half_width * grid_spacing, (half_width + 1) * grid_spacing, grid_spacing)
120    y_range = torch.arange(-half_height * grid_spacing, (half_height + 1) * grid_spacing, grid_spacing)
121    # Create the grid
122    x_grid, y_grid = torch.meshgrid(x_range, y_range, indexing="ij")
123    x_grid = x_grid.reshape(-1)
124    y_grid = y_grid.reshape(-1)
125    z_grid = torch.zeros_like(x_grid)
126    # marker locations
127    marker_locations = torch.stack([x_grid, y_grid, z_grid], dim=1)
128    marker_indices = torch.arange(my_visualizer.num_prototypes).repeat(num_markers_per_type)
129
130    # Play the simulator
131    sim.reset()
132    # Now we are ready!
133    print("[INFO]: Setup complete...")
134
135    # Yaw angle
136    yaw = torch.zeros_like(marker_locations[:, 0])
137    # Simulate physics
138    while simulation_app.is_running():
139        # rotate the markers around the z-axis for visualization
140        marker_orientations = quat_from_angle_axis(yaw, torch.tensor([0.0, 0.0, 1.0]))
141        # visualize
142        my_visualizer.visualize(marker_locations, marker_orientations, marker_indices=marker_indices)
143        # roll corresponding indices to show how marker prototype can be changed
144        if yaw[0].item() % (0.5 * torch.pi) < 0.01:
145            marker_indices = torch.roll(marker_indices, 1)
146        # perform step
147        sim.step()
148        # increment yaw
149        yaw += 0.01
150
151
152if __name__ == "__main__":
153    # run the main function
154    main()
155    # close sim app
156    simulation_app.close()

Configuring the markers#

The VisualizationMarkersCfg class provides a simple interface to configure different types of markers. It takes in the following parameters:

  • prim_path: The corresponding prim path for the marker class.

  • markers: A dictionary specifying the different marker prototypes handled by the class. The key is the name of the marker prototype and the value is its spawn configuration.

Note

In case the marker prototype specifies a configuration with physics properties, these are removed. This is because the markers are not meant to be simulated.

Here we show all the different types of markers that can be configured. These range from simple shapes like cones and spheres to more complex geometries like a frame or arrows. The marker prototypes can also be configured from USD files.

def define_markers() -> VisualizationMarkers:
    """Define markers with various different shapes."""
    marker_cfg = VisualizationMarkersCfg(
        prim_path="/Visuals/myMarkers",
        markers={
            "frame": sim_utils.UsdFileCfg(
                usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/UIElements/frame_prim.usd",
                scale=(0.5, 0.5, 0.5),
            ),
            "arrow_x": sim_utils.UsdFileCfg(
                usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/UIElements/arrow_x.usd",
                scale=(1.0, 0.5, 0.5),
                visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 1.0)),
            ),
            "cube": sim_utils.CuboidCfg(
                size=(1.0, 1.0, 1.0),
                visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.0, 0.0)),
            ),
            "sphere": sim_utils.SphereCfg(
                radius=0.5,
                visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0)),
            ),
            "cylinder": sim_utils.CylinderCfg(
                radius=0.5,
                height=1.0,
                visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 0.0, 1.0)),
            ),
            "cone": sim_utils.ConeCfg(
                radius=0.5,
                height=1.0,
                visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 1.0, 0.0)),
            ),
            "mesh": sim_utils.UsdFileCfg(
                usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/DexCube/dex_cube_instanceable.usd",
                scale=(10.0, 10.0, 10.0),
            ),
            "mesh_recolored": sim_utils.UsdFileCfg(
                usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/DexCube/dex_cube_instanceable.usd",
                scale=(10.0, 10.0, 10.0),
                visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.25, 0.0)),
            ),
            "robot_mesh": sim_utils.UsdFileCfg(
                usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/ANYbotics/ANYmal-C/anymal_c.usd",
                scale=(2.0, 2.0, 2.0),
                visual_material=sim_utils.GlassMdlCfg(glass_color=(0.0, 0.1, 0.0)),
            ),

Drawing the markers#

To draw the markers, we call the visualize method. This method takes in as arguments the pose of the markers and the corresponding marker prototypes to draw.

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)

Executing the Script#

To run the accompanying script, execute the following command:

./isaaclab.sh -p scripts/demos/markers.py

The simulation should start, and you can observe the different types of markers arranged in a grid pattern. The markers will rotating around their respective axes. Additionally every few rotations, they will roll forward on the grid.

To stop the simulation, close the window, or use Ctrl+C in the terminal.