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
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()