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