创建可视化标记#
本指南介绍如何通过 markers.VisualizationMarkers 在场景中绘制坐标系、箭头、球体和自定义网格等调试几何体。标记仅用于显示,不包含物理属性,也不会影响仿真。
对于简单的点、线和样条,Isaac Sim 的 isaacsim.util.debug_draw 扩展更轻量。需要复杂形状时,使用 VisualizationMarkers 。
Kit、Newton GL、Rerun 和 Viser 支持标记,Newton RTX 暂不支持。各可视化器启用标记的方法见 可视化 。
快速开始#
运行内置的 markers 示例:
uv run --extra isaacsim isaaclab example markers
./isaaclab.sh example markers
传入 --visualizer newton_gl 或其他受支持后端,可切换可视化器;默认为 kit 。
示例脚本中的全部标记原型按网格排列。各列原地旋转,并定期向前轮换到下一个原型。#
关闭窗口或按 Ctrl+C 可停止。
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 uvx --from 'isaaclab[isaacsim]' isaaclab example markers
12
13"""
14
15import argparse
16from typing import TYPE_CHECKING
17
18from isaaclab.app import add_launcher_args, launch_simulation
19from isaaclab.utils import instantiate
20
21parser = argparse.ArgumentParser(
22 description="This script demonstrates different types of markers.",
23 conflict_handler="resolve",
24)
25parser.add_argument("--physics", default="isaacsim_physx", choices=["isaacsim_physx"], help="Physics backend.")
26parser.add_argument("--max_steps", type=int, default=-1, help="Stop after this many steps; negative runs forever.")
27add_launcher_args(parser)
28parser.set_defaults(visualizer=["kit"])
29args_cli = parser.parse_args()
30if args_cli.max_steps == 0 or args_cli.max_steps < -1:
31 parser.error("--max_steps must be positive or -1.")
32
33import torch
34
35import isaaclab.sim as sim_utils
36from isaaclab.markers.visualization_markers_cfg import VisualizationMarkersCfg
37from isaaclab.physics import PhysicsCfg
38from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR, ISAACLAB_NUCLEUS_DIR
39from isaaclab.utils.math import quat_from_angle_axis
40
41if TYPE_CHECKING:
42 from isaaclab.markers import VisualizationMarkers
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 instantiate(marker_cfg)
94
95
96def main():
97 """Main function."""
98 with launch_simulation(cfg=PhysicsCfg(), launcher_args=args_cli) as physics_cfg:
99 sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device, physics=physics_cfg)
100 sim = sim_utils.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 sim.reset()
131 print("[INFO]: Setup complete...")
132
133 # Yaw angle
134 yaw = torch.zeros_like(marker_locations[:, 0])
135 step_count = 0
136 # Step while a visualizer window is still open (or none exist, e.g. headless); works for kit and newton.
137 while sim.is_running() and (args_cli.max_steps < 0 or step_count < args_cli.max_steps):
138 # rotate the markers around the z-axis for visualization
139 marker_orientations = quat_from_angle_axis(yaw, torch.tensor([0.0, 0.0, 1.0]))
140 # visualize
141 my_visualizer.visualize(marker_locations, marker_orientations, marker_indices=marker_indices)
142 # roll corresponding indices to show how marker prototype can be changed
143 if yaw[0].item() % (0.5 * torch.pi) < 0.01:
144 marker_indices = torch.roll(marker_indices, 1)
145 # perform step
146 sim.step()
147 step_count += 1
148 # increment yaw
149 yaw += 0.01
150
151
152if __name__ == "__main__":
153 main()
配置标记#
prim_path:创建标记UsdGeom.PointInstancer的 prim 路径。markers:标记原型字典,键是原型名称,值是生成配置,可以是任意SpawnerCfg,包括 USD 文件引用。
备注
由于标记不参与仿真,创建时会移除其原型生成配置中的物理属性。
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)),
),
},
)
return instantiate(marker_cfg)
绘制标记#
visualize() 设置标记位姿,还可通过 marker_indices 指定各标记实例使用的原型。
my_visualizer.visualize(marker_locations, marker_orientations, marker_indices=marker_indices)
参数保持 None 时,沿用之前的值。传入行数与上次不同,会调整标记实例数量。完整参数列表( translations 、 orientations 、 scales 、 marker_indices 、 environment_ids )见 visualize() 的文档字符串。
标记的实际应用#
标记常用于训练期间调试各环境状态,例如比较指令速度与当前速度,或显示接触事件:
AnymalD 机器人上表示速度指令(绿色)和当前速度(蓝色)的箭头标记。
Franka 机械臂上的关节箭头标记,以及立方体上的接触传感器标记。