0
# Visualization
1
2
3D plotting and visualization tools using matplotlib and Open3D backends for transformations, trajectories, and geometric objects with comprehensive rendering capabilities.
3
4
## Capabilities
5
6
### Matplotlib-based Visualization
7
8
2D and 3D plotting using matplotlib with support for transformations and geometric objects.
9
10
```python { .api }
11
# Layout functions
12
def make_3d_axis(ax_s=1, pos=111, unit=None, n_ticks=5, **kwargs):
13
"""
14
Create 3D matplotlib axis with proper scaling.
15
16
Parameters:
17
- ax_s: float - Axis scaling factor
18
- pos: int - Subplot position
19
- unit: str, optional - Axis unit label
20
- n_ticks: int - Number of axis ticks
21
22
Returns:
23
- ax: Axes3D - Configured 3D axis
24
"""
25
26
def remove_frame(ax):
27
"""Remove frame decorations from 3D axis."""
28
29
# Transformation plotting
30
def plot_transform(ax=None, A2B=None, s=1.0, ax_s=1, **kwargs):
31
"""
32
Plot transformation as coordinate frame.
33
34
Parameters:
35
- ax: Axes3D, optional - 3D axis
36
- A2B: array, shape (4, 4), optional - Transformation matrix
37
- s: float - Frame size scaling
38
- ax_s: float - Axis scaling
39
"""
40
41
def plot_screw(ax=None, q=None, s_axis=None, h=None, theta=None, s=1.0, ax_s=1, **kwargs):
42
"""Plot screw motion visualization."""
43
44
def plot_trajectory(P=None, show_direction=True, n_frames=10, s=1.0, ax=None, **kwargs):
45
"""
46
Plot 3D trajectory with direction indicators.
47
48
Parameters:
49
- P: array, shape (n_steps, 3 or 4, 4) - Trajectory as transforms or positions
50
- show_direction: bool - Show trajectory direction arrows
51
- n_frames: int - Number of coordinate frames to show
52
- s: float - Frame size scaling
53
- ax: Axes3D, optional - 3D axis
54
"""
55
56
# Geometry plotting
57
def plot_box(ax=None, size=[1, 1, 1], A2B=np.eye(4), **kwargs):
58
"""Plot 3D box."""
59
60
def plot_sphere(ax=None, radius=1.0, p=np.zeros(3), **kwargs):
61
"""Plot sphere."""
62
63
def plot_cylinder(ax=None, length=1.0, radius=1.0, A2B=np.eye(4), **kwargs):
64
"""Plot cylinder."""
65
66
def plot_ellipsoid(ax=None, radii=[1, 1, 1], A2B=np.eye(4), **kwargs):
67
"""Plot ellipsoid."""
68
69
def plot_capsule(ax=None, height=1.0, radius=1.0, A2B=np.eye(4), **kwargs):
70
"""Plot capsule (cylinder with hemispherical ends)."""
71
72
def plot_cone(ax=None, length=1.0, radius=1.0, A2B=np.eye(4), **kwargs):
73
"""Plot cone."""
74
75
def plot_mesh(ax, filename, A2B=np.eye(4), **kwargs):
76
"""Plot mesh from file."""
77
78
# Vector utilities
79
def plot_vector(ax=None, start=np.zeros(3), direction=np.array([1, 0, 0]), **kwargs):
80
"""Plot 3D vector."""
81
82
def plot_length_variable(ax, start_point, end_point, label, **kwargs):
83
"""Plot length measurement with label."""
84
```
85
86
### Matplotlib Artist Classes
87
88
Reusable artist objects for complex 3D visualizations.
89
90
```python { .api }
91
class Arrow3D:
92
"""3D arrow visualization artist."""
93
94
class Frame:
95
"""Coordinate frame visualization artist."""
96
97
class LabeledFrame:
98
"""Labeled coordinate frame artist."""
99
100
class Trajectory:
101
"""3D trajectory visualization artist."""
102
103
class Camera:
104
"""Camera visualization artist."""
105
```
106
107
### Open3D-based Visualization
108
109
High-performance 3D rendering using Open3D backend (requires open3d dependency).
110
111
```python { .api }
112
def figure(**kwargs):
113
"""
114
Create Open3D-based 3D figure.
115
116
Returns:
117
- fig: Figure - Open3D figure instance
118
"""
119
120
class Figure:
121
"""Open3D-based 3D figure for high-performance rendering."""
122
123
def add(self, artist):
124
"""
125
Add artist to figure.
126
127
Parameters:
128
- artist: Artist - 3D artist object
129
"""
130
131
def show(self):
132
"""Display interactive 3D visualization."""
133
134
def plot(self, **kwargs):
135
"""Configure plot parameters."""
136
137
# Open3D Artist classes
138
class Artist:
139
"""Base artist class for Open3D rendering."""
140
141
class Line3D(Artist):
142
"""3D line visualization."""
143
144
class PointCollection3D(Artist):
145
"""Point cloud visualization."""
146
147
class Vector3D(Artist):
148
"""3D vector artist."""
149
150
class Frame(Artist):
151
"""Coordinate frame artist."""
152
153
class Trajectory(Artist):
154
"""3D trajectory artist."""
155
156
class Camera(Artist):
157
"""Camera visualization artist."""
158
159
class Box(Artist):
160
"""3D box artist."""
161
162
class Sphere(Artist):
163
"""Sphere artist."""
164
165
class Cylinder(Artist):
166
"""Cylinder artist."""
167
168
class Mesh(Artist):
169
"""Mesh visualization artist."""
170
171
class Ellipsoid(Artist):
172
"""Ellipsoid artist."""
173
174
class Capsule(Artist):
175
"""Capsule artist."""
176
177
class Cone(Artist):
178
"""Cone artist."""
179
180
class Plane(Artist):
181
"""Plane artist."""
182
183
class Graph(Artist):
184
"""Graph structure artist."""
185
```
186
187
## Usage Examples
188
189
### Basic Transformation Visualization
190
191
```python
192
import numpy as np
193
import matplotlib.pyplot as plt
194
import pytransform3d.transformations as pt
195
import pytransform3d.rotations as pr
196
from pytransform3d.plot_utils import make_3d_axis, plot_transform
197
198
# Create transformations
199
T1 = pt.transform_from(p=[1, 0, 0])
200
R2 = pr.matrix_from_euler([0, 0, np.pi/4], "xyz", extrinsic=True)
201
T2 = pt.transform_from(R=R2, p=[0, 1, 0])
202
T3 = pt.transform_from(p=[0, 0, 1])
203
204
# Plot transformations
205
ax = make_3d_axis(ax_s=2)
206
207
plot_transform(ax=ax, A2B=np.eye(4), s=0.3, label='Origin')
208
plot_transform(ax=ax, A2B=T1, s=0.3, label='T1')
209
plot_transform(ax=ax, A2B=T2, s=0.3, label='T2')
210
plot_transform(ax=ax, A2B=T3, s=0.3, label='T3')
211
212
ax.legend()
213
plt.show()
214
```
215
216
### Trajectory Visualization
217
218
```python
219
import numpy as np
220
import matplotlib.pyplot as plt
221
import pytransform3d.trajectories as ptr
222
from pytransform3d.plot_utils import make_3d_axis, plot_trajectory
223
224
# Generate circular trajectory
225
n_steps = 50
226
t = np.linspace(0, 2*np.pi, n_steps)
227
trajectory = []
228
229
for angle in t:
230
# Circular motion in x-y plane
231
x = np.cos(angle)
232
y = np.sin(angle)
233
z = 0.1 * angle # slight upward spiral
234
235
# Rotation to keep "forward" direction tangent to circle
236
R = pr.matrix_from_euler([0, 0, angle + np.pi/2], "xyz", extrinsic=True)
237
T = pt.transform_from(R=R, p=[x, y, z])
238
trajectory.append(T)
239
240
trajectory = np.array(trajectory)
241
242
# Plot trajectory
243
ax = make_3d_axis(ax_s=2)
244
plot_trajectory(trajectory, show_direction=True, n_frames=8, s=0.1, ax=ax)
245
246
ax.set_xlabel('X')
247
ax.set_ylabel('Y')
248
ax.set_zlabel('Z')
249
plt.show()
250
```
251
252
### Geometric Objects
253
254
```python
255
import numpy as np
256
import matplotlib.pyplot as plt
257
from pytransform3d.plot_utils import (
258
make_3d_axis, plot_box, plot_sphere, plot_cylinder, plot_cone
259
)
260
import pytransform3d.transformations as pt
261
262
# Create scene with various objects
263
ax = make_3d_axis(ax_s=3)
264
265
# Plot different geometric objects
266
plot_box(ax=ax, size=[0.5, 0.3, 0.2],
267
A2B=pt.transform_from(p=[0, 0, 0]),
268
alpha=0.7, color='red')
269
270
plot_sphere(ax=ax, radius=0.3, p=[1, 0, 0],
271
alpha=0.7, color='green')
272
273
plot_cylinder(ax=ax, length=0.8, radius=0.2,
274
A2B=pt.transform_from(p=[0, 1, 0]),
275
alpha=0.7, color='blue')
276
277
plot_cone(ax=ax, length=0.6, radius=0.25,
278
A2B=pt.transform_from(p=[1, 1, 0]),
279
alpha=0.7, color='yellow')
280
281
ax.set_xlabel('X')
282
ax.set_ylabel('Y')
283
ax.set_zlabel('Z')
284
plt.show()
285
```
286
287
### Robot Visualization
288
289
```python
290
import numpy as np
291
import matplotlib.pyplot as plt
292
from pytransform3d.transform_manager import TransformManager
293
from pytransform3d.plot_utils import make_3d_axis, plot_cylinder, plot_sphere
294
import pytransform3d.transformations as pt
295
import pytransform3d.rotations as pr
296
297
# Create simple robot arm
298
tm = TransformManager()
299
300
# Base
301
tm.add_transform("world", "base", pt.transform_from(p=[0, 0, 0.1]))
302
303
# First joint (shoulder)
304
R1 = pr.matrix_from_euler([0, 0, 0.3], "xyz", extrinsic=True)
305
tm.add_transform("base", "link1", pt.transform_from(R=R1, p=[0, 0, 0.2]))
306
307
# Second joint (elbow)
308
R2 = pr.matrix_from_euler([0, -0.5, 0], "xyz", extrinsic=True)
309
tm.add_transform("link1", "link2", pt.transform_from(R=R2, p=[0.4, 0, 0]))
310
311
# End effector
312
tm.add_transform("link2", "end_effector", pt.transform_from(p=[0.3, 0, 0]))
313
314
# Visualize robot
315
ax = make_3d_axis(ax_s=1)
316
317
# Plot coordinate frames
318
tm.plot_frames_in("world", ax=ax, s=0.1)
319
tm.plot_connections_in_frame("world", ax=ax)
320
321
# Add geometric representation
322
# Base cylinder
323
plot_cylinder(ax=ax, length=0.1, radius=0.05,
324
A2B=tm.get_transform("world", "base"),
325
color='gray', alpha=0.8)
326
327
# Link 1
328
T_link1 = tm.get_transform("world", "link1")
329
link1_T = pt.transform_from(p=[0.2, 0, 0]) # offset for link geometry
330
plot_cylinder(ax=ax, length=0.4, radius=0.03,
331
A2B=pt.concat(T_link1, link1_T),
332
color='blue', alpha=0.8)
333
334
# Link 2
335
T_link2 = tm.get_transform("world", "link2")
336
link2_T = pt.transform_from(p=[0.15, 0, 0])
337
plot_cylinder(ax=ax, length=0.3, radius=0.025,
338
A2B=pt.concat(T_link2, link2_T),
339
color='red', alpha=0.8)
340
341
# End effector
342
T_end = tm.get_transform("world", "end_effector")
343
plot_sphere(ax=ax, radius=0.03, p=T_end[:3, 3], color='green')
344
345
ax.set_xlabel('X')
346
ax.set_ylabel('Y')
347
ax.set_zlabel('Z')
348
plt.show()
349
```
350
351
### Open3D High-Performance Visualization
352
353
```python
354
# Note: Requires 'pip install open3d'
355
try:
356
import pytransform3d.visualizer as pv
357
import pytransform3d.transformations as pt
358
import numpy as np
359
360
# Create Open3D figure
361
fig = pv.figure()
362
363
# Add coordinate frame
364
frame = pv.Frame(A2B=np.eye(4), s=0.3)
365
fig.add(frame)
366
367
# Add trajectory
368
trajectory = ptr.random_trajectories(50)
369
traj_artist = pv.Trajectory(trajectory)
370
fig.add(traj_artist)
371
372
# Add geometric objects
373
box = pv.Box(size=[0.2, 0.2, 0.2], A2B=pt.transform_from(p=[1, 0, 0]))
374
fig.add(box)
375
376
sphere = pv.Sphere(radius=0.1, center=[0, 1, 0])
377
fig.add(sphere)
378
379
# Show interactive visualization
380
fig.show()
381
382
except ImportError:
383
print("Open3D not available - install with 'pip install open3d'")
384
```
385
386
### Animation
387
388
```python
389
import numpy as np
390
import matplotlib.pyplot as plt
391
import matplotlib.animation as animation
392
from pytransform3d.plot_utils import make_3d_axis, plot_transform
393
import pytransform3d.transformations as pt
394
import pytransform3d.rotations as pr
395
396
# Set up figure
397
fig = plt.figure()
398
ax = make_3d_axis(ax_s=2)
399
400
# Animation parameters
401
n_frames = 100
402
t_values = np.linspace(0, 4*np.pi, n_frames)
403
404
def animate(frame):
405
ax.clear()
406
ax = make_3d_axis(ax_s=2)
407
408
# Create rotating transformation
409
angle = t_values[frame]
410
R = pr.matrix_from_euler([0, 0, angle], "xyz", extrinsic=True)
411
p = [np.cos(angle), np.sin(angle), 0.1*angle]
412
T = pt.transform_from(R=R, p=p)
413
414
# Plot reference frame and animated frame
415
plot_transform(ax=ax, A2B=np.eye(4), s=0.2, alpha=0.5)
416
plot_transform(ax=ax, A2B=T, s=0.3)
417
418
ax.set_xlabel('X')
419
ax.set_ylabel('Y')
420
ax.set_zlabel('Z')
421
ax.set_title(f'Frame: {frame}, Angle: {angle:.2f}')
422
423
# Create animation
424
anim = animation.FuncAnimation(fig, animate, frames=n_frames, interval=50)
425
plt.show()
426
427
# Uncomment to save animation
428
# anim.save('rotating_frame.gif', writer='pillow', fps=20)
429
```