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 with default PhysX physics and default kit visualizer.
11 ./isaaclab.sh -p scripts/demos/markers.py
12
13"""
14
15"""Parse CLI first so we can decide whether to launch Isaac Sim Kit."""
16
17import argparse
18from typing import TYPE_CHECKING
19
20from isaaclab.app import add_launcher_args, launch_simulation
21
22# add argparse arguments
23parser = argparse.ArgumentParser(
24 description="This script demonstrates different types of markers.",
25 conflict_handler="resolve",
26)
27parser.add_argument("--physics", default="physx", choices=["physx"], help="Physics backend.")
28# Newton visualizer not supported for markers
29parser.add_argument("--visualizer", default="kit", choices=["kit"], help="Visualizer backend.")
30add_launcher_args(parser)
31parser.set_defaults(visualizer=["kit"])
32args_cli = parser.parse_args()
33
34import torch
35
36import isaaclab.sim as sim_utils
37
38##
39# Pre-defined configs
40##
41from isaaclab.markers.visualization_markers_cfg import VisualizationMarkersCfg
42from isaaclab.physics import PhysicsCfg
43from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR, ISAACLAB_NUCLEUS_DIR
44from isaaclab.utils.math import quat_from_angle_axis
45
46if TYPE_CHECKING:
47 from isaaclab.markers import VisualizationMarkers
48
49
50def define_markers() -> "VisualizationMarkers":
51 """Define markers with various different shapes."""
52 marker_cfg = VisualizationMarkersCfg(
53 prim_path="/Visuals/myMarkers",
54 markers={
55 "frame": sim_utils.UsdFileCfg(
56 usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/UIElements/frame_prim.usd",
57 scale=(0.5, 0.5, 0.5),
58 ),
59 "arrow_x": sim_utils.UsdFileCfg(
60 usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/UIElements/arrow_x.usd",
61 scale=(1.0, 0.5, 0.5),
62 visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 1.0)),
63 ),
64 "cube": sim_utils.CuboidCfg(
65 size=(1.0, 1.0, 1.0),
66 visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.0, 0.0)),
67 ),
68 "sphere": sim_utils.SphereCfg(
69 radius=0.5,
70 visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0)),
71 ),
72 "cylinder": sim_utils.CylinderCfg(
73 radius=0.5,
74 height=1.0,
75 visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 0.0, 1.0)),
76 ),
77 "cone": sim_utils.ConeCfg(
78 radius=0.5,
79 height=1.0,
80 visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 1.0, 0.0)),
81 ),
82 "mesh": sim_utils.UsdFileCfg(
83 usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/DexCube/dex_cube_instanceable.usd",
84 scale=(10.0, 10.0, 10.0),
85 ),
86 "mesh_recolored": sim_utils.UsdFileCfg(
87 usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/DexCube/dex_cube_instanceable.usd",
88 scale=(10.0, 10.0, 10.0),
89 visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.25, 0.0)),
90 ),
91 "robot_mesh": sim_utils.UsdFileCfg(
92 usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/ANYbotics/ANYmal-C/anymal_c.usd",
93 scale=(2.0, 2.0, 2.0),
94 visual_material=sim_utils.GlassMdlCfg(glass_color=(0.0, 0.1, 0.0)),
95 ),
96 },
97 )
98 return marker_cfg.class_type(marker_cfg)
99
100
101def main():
102 """Main function."""
103 with launch_simulation(cfg=PhysicsCfg(), launcher_args=args_cli) as physics_cfg:
104 # Load kit helper
105 sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device, physics=physics_cfg)
106 sim = sim_utils.SimulationContext(sim_cfg)
107 # Set main camera
108 sim.set_camera_view([0.0, 18.0, 12.0], [0.0, 3.0, 0.0])
109
110 # Spawn things into stage
111 # Lights
112 cfg = sim_utils.DomeLightCfg(intensity=3000.0, color=(0.75, 0.75, 0.75))
113 cfg.func("/World/Light", cfg)
114
115 # create markers
116 my_visualizer = define_markers()
117
118 # define a grid of positions where the markers should be placed
119 num_markers_per_type = 5
120 grid_spacing = 2.0
121 # Calculate the half-width and half-height
122 half_width = (num_markers_per_type - 1) / 2.0
123 half_height = (my_visualizer.num_prototypes - 1) / 2.0
124 # Create the x and y ranges centered around the origin
125 x_range = torch.arange(-half_width * grid_spacing, (half_width + 1) * grid_spacing, grid_spacing)
126 y_range = torch.arange(-half_height * grid_spacing, (half_height + 1) * grid_spacing, grid_spacing)
127 # Create the grid
128 x_grid, y_grid = torch.meshgrid(x_range, y_range, indexing="ij")
129 x_grid = x_grid.reshape(-1)
130 y_grid = y_grid.reshape(-1)
131 z_grid = torch.zeros_like(x_grid)
132 # marker locations
133 marker_locations = torch.stack([x_grid, y_grid, z_grid], dim=1)
134 marker_indices = torch.arange(my_visualizer.num_prototypes).repeat(num_markers_per_type)
135
136 # Play the simulator
137 sim.reset()
138 # Now we are ready!
139 print("[INFO]: Setup complete...")
140
141 # Yaw angle
142 yaw = torch.zeros_like(marker_locations[:, 0])
143 # Step while a visualizer window is still open (or none exist, e.g. headless); works for kit and newton.
144 while sim.is_headless_or_exist_active_visualizer():
145 # rotate the markers around the z-axis for visualization
146 marker_orientations = quat_from_angle_axis(yaw, torch.tensor([0.0, 0.0, 1.0]))
147 # visualize
148 my_visualizer.visualize(marker_locations, marker_orientations, marker_indices=marker_indices)
149 # roll corresponding indices to show how marker prototype can be changed
150 if yaw[0].item() % (0.5 * torch.pi) < 0.01:
151 marker_indices = torch.roll(marker_indices, 1)
152 # perform step
153 sim.step()
154 # increment yaw
155 yaw += 0.01
156
157
158if __name__ == "__main__":
159 # run the main function
160 main()
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.
if TYPE_CHECKING:
from isaaclab.markers import VisualizationMarkers
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)),
),
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.
# Play the simulator
sim.reset()
# Now we are ready!
print("[INFO]: Setup complete...")
# Yaw angle
yaw = torch.zeros_like(marker_locations[:, 0])
Executing the Script#
To run the accompanying script, execute the following command:
python 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.