0
# Plot Utils
1
2
Utilities for 3D plotting and visualization using matplotlib. This module provides high-level plotting functions for geometric shapes, coordinate frames, and 3D objects commonly used in robotics and computer graphics applications.
3
4
## Capabilities
5
6
### 3D Artists and Objects
7
8
High-level matplotlib artists for drawing 3D objects and coordinate systems.
9
10
```python { .api }
11
class Arrow3D:
12
"""
13
3D arrow artist for matplotlib.
14
15
Parameters:
16
- start: array-like, shape (3,) - arrow start position
17
- direction: array-like, shape (3,) - arrow direction vector
18
- length: float - arrow length
19
- **kwargs: additional matplotlib parameters
20
"""
21
22
class Frame:
23
"""
24
Coordinate frame artist showing x, y, z axes.
25
26
Parameters:
27
- A2B: array-like, shape (4, 4) - transformation matrix
28
- label: str - frame label
29
- s: float - frame scale
30
- **kwargs: additional parameters
31
"""
32
33
class LabeledFrame(Frame):
34
"""
35
Coordinate frame with axis labels (X, Y, Z).
36
37
Parameters:
38
- A2B: array-like, shape (4, 4) - transformation matrix
39
- label: str - frame label
40
- s: float - frame scale
41
- **kwargs: additional parameters
42
"""
43
44
class Trajectory:
45
"""
46
3D trajectory artist for path visualization.
47
48
Parameters:
49
- P: array-like, shape (n_steps, 3) - trajectory positions
50
- show_direction: bool - whether to show direction arrows
51
- **kwargs: additional matplotlib parameters
52
"""
53
54
class Camera:
55
"""
56
Camera visualization artist.
57
58
Parameters:
59
- cam2world: array-like, shape (4, 4) - camera pose
60
- sensor_size: array-like, shape (2,) - sensor dimensions
61
- focal_length: float - camera focal length
62
- **kwargs: additional parameters
63
"""
64
```
65
66
### Layout and Axis Management
67
68
Utilities for creating and managing 3D matplotlib axes.
69
70
```python { .api }
71
def make_3d_axis(ax_s=1, pos=111, unit="m", n_ticks=6):
72
"""
73
Create a 3D matplotlib axis with proper formatting.
74
75
Parameters:
76
- ax_s: float - axis size/scale
77
- pos: int - subplot position (e.g., 111)
78
- unit: str - axis unit label
79
- n_ticks: int - number of axis ticks
80
81
Returns:
82
- ax: matplotlib Axes3D - configured 3D axis
83
"""
84
85
def remove_frame(ax):
86
"""
87
Remove frame/box from 3D axis for cleaner visualization.
88
89
Parameters:
90
- ax: matplotlib Axes3D - axis to modify
91
"""
92
```
93
94
### Geometric Shape Plotting
95
96
Functions for plotting various 3D geometric shapes and objects.
97
98
```python { .api }
99
def plot_box(ax=None, size=[1, 1, 1], A2B=None, **kwargs):
100
"""
101
Plot a 3D box/cube.
102
103
Parameters:
104
- ax: matplotlib Axes3D - axis to plot on
105
- size: array-like, shape (3,) - box dimensions [length, width, height]
106
- A2B: array-like, shape (4, 4) - box pose transformation
107
- **kwargs: additional matplotlib parameters
108
109
Returns:
110
- collection: matplotlib collection - box visualization
111
"""
112
113
def plot_sphere(ax=None, radius=1.0, p=[0, 0, 0], **kwargs):
114
"""
115
Plot a 3D sphere.
116
117
Parameters:
118
- ax: matplotlib Axes3D - axis to plot on
119
- radius: float - sphere radius
120
- p: array-like, shape (3,) - sphere center position
121
- **kwargs: additional matplotlib parameters
122
123
Returns:
124
- surface: matplotlib surface - sphere visualization
125
"""
126
127
def plot_spheres(ax=None, P=None, radius=1.0, **kwargs):
128
"""
129
Plot multiple 3D spheres.
130
131
Parameters:
132
- ax: matplotlib Axes3D - axis to plot on
133
- P: array-like, shape (n_spheres, 3) - sphere center positions
134
- radius: float or array-like - sphere radius/radii
135
- **kwargs: additional matplotlib parameters
136
137
Returns:
138
- collection: matplotlib collection - spheres visualization
139
"""
140
141
def plot_cylinder(ax=None, length=1.0, radius=1.0, A2B=None, **kwargs):
142
"""
143
Plot a 3D cylinder.
144
145
Parameters:
146
- ax: matplotlib Axes3D - axis to plot on
147
- length: float - cylinder length
148
- radius: float - cylinder radius
149
- A2B: array-like, shape (4, 4) - cylinder pose transformation
150
- **kwargs: additional matplotlib parameters
151
152
Returns:
153
- collection: matplotlib collection - cylinder visualization
154
"""
155
156
def plot_mesh(ax=None, filename=None, A2B=None, **kwargs):
157
"""
158
Plot a 3D mesh from file.
159
160
Parameters:
161
- ax: matplotlib Axes3D - axis to plot on
162
- filename: str - path to mesh file
163
- A2B: array-like, shape (4, 4) - mesh pose transformation
164
- **kwargs: additional matplotlib parameters
165
166
Returns:
167
- collection: matplotlib collection - mesh visualization
168
"""
169
170
def plot_ellipsoid(ax=None, radii=[1, 1, 1], A2B=None, **kwargs):
171
"""
172
Plot a 3D ellipsoid.
173
174
Parameters:
175
- ax: matplotlib Axes3D - axis to plot on
176
- radii: array-like, shape (3,) - ellipsoid radii [a, b, c]
177
- A2B: array-like, shape (4, 4) - ellipsoid pose transformation
178
- **kwargs: additional matplotlib parameters
179
180
Returns:
181
- surface: matplotlib surface - ellipsoid visualization
182
"""
183
184
def plot_capsule(ax=None, height=1.0, radius=1.0, A2B=None, **kwargs):
185
"""
186
Plot a 3D capsule (cylinder with hemispherical ends).
187
188
Parameters:
189
- ax: matplotlib Axes3D - axis to plot on
190
- height: float - capsule height
191
- radius: float - capsule radius
192
- A2B: array-like, shape (4, 4) - capsule pose transformation
193
- **kwargs: additional matplotlib parameters
194
195
Returns:
196
- collection: matplotlib collection - capsule visualization
197
"""
198
199
def plot_cone(ax=None, height=1.0, radius=1.0, A2B=None, **kwargs):
200
"""
201
Plot a 3D cone.
202
203
Parameters:
204
- ax: matplotlib Axes3D - axis to plot on
205
- height: float - cone height
206
- radius: float - cone base radius
207
- A2B: array-like, shape (4, 4) - cone pose transformation
208
- **kwargs: additional matplotlib parameters
209
210
Returns:
211
- collection: matplotlib collection - cone visualization
212
"""
213
```
214
215
### Plotting Helpers
216
217
Helper functions for drawing vectors and variable-length objects.
218
219
```python { .api }
220
def plot_vector(ax=None, start=[0, 0, 0], direction=[1, 0, 0], **kwargs):
221
"""
222
Plot a 3D vector as an arrow.
223
224
Parameters:
225
- ax: matplotlib Axes3D - axis to plot on
226
- start: array-like, shape (3,) - vector start position
227
- direction: array-like, shape (3,) - vector direction
228
- **kwargs: additional matplotlib parameters
229
230
Returns:
231
- arrow: Arrow3D - vector visualization
232
"""
233
234
def plot_length_variable(ax=None, start=[0, 0, 0], end=[1, 0, 0], **kwargs):
235
"""
236
Plot a variable-length line between two points.
237
238
Parameters:
239
- ax: matplotlib Axes3D - axis to plot on
240
- start: array-like, shape (3,) - line start position
241
- end: array-like, shape (3,) - line end position
242
- **kwargs: additional matplotlib parameters
243
244
Returns:
245
- line: matplotlib Line3D - line visualization
246
"""
247
```
248
249
## Usage Examples
250
251
### Basic 3D Plotting
252
253
```python
254
import numpy as np
255
import matplotlib.pyplot as plt
256
from pytransform3d.plot_utils import (
257
make_3d_axis,
258
plot_box,
259
plot_sphere,
260
plot_cylinder
261
)
262
263
# Create 3D figure and axis
264
fig = plt.figure(figsize=(10, 8))
265
ax = make_3d_axis(ax_s=2, unit="m")
266
267
# Plot various geometric shapes
268
plot_box(ax, size=[0.5, 0.3, 0.2], A2B=np.eye(4), color='red', alpha=0.7)
269
270
# Sphere at different position
271
sphere_pose = np.eye(4)
272
sphere_pose[:3, 3] = [1, 0, 0] # translate
273
plot_sphere(ax, radius=0.3, p=[1, 0, 0], color='blue', alpha=0.6)
274
275
# Cylinder with rotation
276
cylinder_pose = np.eye(4)
277
cylinder_pose[:3, 3] = [0, 1, 0]
278
plot_cylinder(ax, length=0.8, radius=0.2, A2B=cylinder_pose,
279
color='green', alpha=0.8)
280
281
plt.show()
282
```
283
284
### Coordinate Frame Visualization
285
286
```python
287
import numpy as np
288
import matplotlib.pyplot as plt
289
from pytransform3d.plot_utils import make_3d_axis, LabeledFrame
290
from pytransform3d.transformations import transform_from
291
from pytransform3d.rotations import matrix_from_euler
292
293
# Create axis
294
fig = plt.figure()
295
ax = make_3d_axis(ax_s=1.5)
296
297
# Create and plot multiple coordinate frames
298
base_frame = np.eye(4)
299
frame1 = transform_from(
300
R=matrix_from_euler([0.2, 0.3, 0.1], 0, 1, 2, True),
301
p=[0.5, 0.2, 0.3]
302
)
303
frame2 = transform_from(
304
R=matrix_from_euler([-0.1, 0.5, -0.2], 0, 1, 2, True),
305
p=[-0.3, 0.4, 0.1]
306
)
307
308
# Plot frames with labels
309
LabeledFrame(A2B=base_frame, label="Base", s=0.3, ax=ax)
310
LabeledFrame(A2B=frame1, label="Frame1", s=0.2, ax=ax)
311
LabeledFrame(A2B=frame2, label="Frame2", s=0.2, ax=ax)
312
313
plt.show()
314
```
315
316
### Camera Visualization
317
318
```python
319
import numpy as np
320
import matplotlib.pyplot as plt
321
from pytransform3d.plot_utils import make_3d_axis, Camera
322
from pytransform3d.transformations import transform_from
323
324
# Setup visualization
325
fig = plt.figure()
326
ax = make_3d_axis(ax_s=2)
327
328
# Camera looking at origin from different positions
329
cam_poses = []
330
for i in range(4):
331
angle = i * np.pi / 2
332
cam_pose = transform_from(
333
R=np.eye(3), # simplified - should use proper rotation
334
p=[2*np.cos(angle), 2*np.sin(angle), 1]
335
)
336
cam_poses.append(cam_pose)
337
338
# Plot cameras
339
for i, pose in enumerate(cam_poses):
340
Camera(
341
cam2world=pose,
342
sensor_size=[0.1, 0.1],
343
focal_length=0.2,
344
ax=ax,
345
alpha=0.7
346
)
347
348
plt.show()
349
```
350
351
### Custom Mesh Visualization
352
353
```python
354
import matplotlib.pyplot as plt
355
from pytransform3d.plot_utils import make_3d_axis, plot_mesh
356
from pytransform3d.transformations import transform_from
357
358
# Load and display 3D mesh
359
fig = plt.figure()
360
ax = make_3d_axis(ax_s=1)
361
362
# Plot mesh at different poses (requires mesh file)
363
mesh_poses = [
364
np.eye(4),
365
transform_from(R=np.eye(3), p=[0.5, 0, 0]),
366
transform_from(R=np.eye(3), p=[0, 0.5, 0])
367
]
368
369
for pose in mesh_poses:
370
plot_mesh(
371
ax=ax,
372
filename="path/to/mesh.obj", # replace with actual mesh file
373
A2B=pose,
374
alpha=0.8
375
)
376
377
plt.show()
378
```