Arrow visualization

Create arrows for visualizing vectors, directions, and quantities in 3D space.

This example demonstrates viser’s arrow rendering capabilities, which are useful for visualizing directions, forces, velocities, and other vector quantities common in robotics and computer vision applications.

Use cases:

  • Perception rays in robotics and 3D sensing

  • Force vectors (contact forces, thruster forces)

  • Velocity vectors (commanded or actual velocities)

  • Axes of rotation and angular velocities

  • Coordinate frame directions

Arrows are batched into a single call for efficiency, similar to line segments. Each arrow is defined by a start point and end point, with configurable shaft radius, head radius, and head length.

Source: examples/01_scene/11_arrows.py

Arrow visualization

Code

  1import time
  2
  3import numpy as np
  4import viser
  5
  6
  7def main() -> None:
  8    server = viser.ViserServer()
  9
 10    # Batched arrows.
 11    #
 12    # Create multiple arrows in a single call for efficiency.
 13    # points shape: (N, 2, 3) where points[i, 0] is the start and points[i, 1] is the end.
 14    N = 200
 15    points = np.zeros((N, 2, 3), dtype=np.float32)
 16    colors = np.zeros((N, 3), dtype=np.uint8)
 17
 18    for i in range(N):
 19        # Distribute arrows in a spiral pattern
 20        theta = i * 0.3
 21        r = 1.0 + i * 0.02
 22        x = r * np.cos(theta)
 23        y = i * 0.05
 24        z = r * np.sin(theta)
 25
 26        points[i, 0] = [0, y, 0]  # start
 27        points[i, 1] = [x, y, z]  # end
 28
 29        # Color gradient from blue to red based on height
 30        color_value = int(255 * (y / (N * 0.05)))
 31        colors[i] = [color_value, 0, 255 - color_value]
 32
 33    server.scene.add_arrows(
 34        "/arrows/spiral",
 35        points=points,
 36        colors=colors,
 37        shaft_radius=0.02,
 38        head_radius=0.05,
 39        head_length=0.1,
 40    )
 41
 42    # Coordinate frame arrows.
 43    #
 44    # Arrows are useful for visualizing coordinate frames and axes.
 45    origin = [0, 2, 0]
 46    frame_points = np.array(
 47        [
 48            [origin, [1, 2, 0]],  # X axis
 49            [origin, [0, 3, 0]],  # Y axis
 50            [origin, [0, 2, 1]],  # Z axis
 51        ],
 52        dtype=np.float32,
 53    )
 54    frame_colors = np.array(
 55        [
 56            [255, 0, 0],  # X: red
 57            [0, 255, 0],  # Y: green
 58            [0, 0, 255],  # Z: blue
 59        ],
 60        dtype=np.uint8,
 61    )
 62    server.scene.add_arrows(
 63        "/arrows/frame",
 64        points=frame_points,
 65        colors=frame_colors,
 66        shaft_radius=0.03,
 67        head_radius=0.08,
 68        head_length=0.15,
 69    )
 70
 71    # Force vectors example.
 72    #
 73    # Arrows can represent forces on an object. Here we show
 74    # contact forces on a simple object at position (0, 4, 0).
 75    contact_point = [0, 4, 0]
 76    force_points = np.array(
 77        [
 78            [contact_point, [0.5, 4.5, 0.3]],
 79            [contact_point, [-0.3, 4.8, -0.2]],
 80            [contact_point, [0.1, 5.2, -0.4]],
 81            [contact_point, [-0.4, 4.3, 0.5]],
 82        ],
 83        dtype=np.float32,
 84    )
 85    force_colors = np.array(
 86        [[255, 200, 0], [255, 100, 0], [255, 50, 0], [255, 150, 0]],
 87        dtype=np.uint8,
 88    )
 89    server.scene.add_arrows(
 90        "/arrows/forces",
 91        points=force_points,
 92        colors=force_colors,
 93        shaft_radius=0.04,
 94        head_radius=0.1,
 95        head_length=0.2,
 96    )
 97
 98    # Uniform color arrows.
 99    #
100    # For simple visualization, a single color can be applied to all arrows.
101    N_velocities = 50
102    vel_starts = np.random.normal(size=(N_velocities, 3)).astype(np.float32) * 3
103    vel_ends = (
104        vel_starts + np.random.normal(size=(N_velocities, 3)).astype(np.float32) * 0.5
105    )
106    velocity_points = np.stack([vel_starts, vel_ends], axis=1)
107
108    server.scene.add_arrows(
109        "/arrows/velocities",
110        points=velocity_points,
111        colors=(100, 200, 255),  # Uniform light blue
112        shaft_radius=0.015,
113        head_radius=0.04,
114        head_length=0.08,
115    )
116
117    while True:
118        time.sleep(10.0)
119
120
121if __name__ == "__main__":
122    main()