Skip to content

Commit c51f133

Browse files
committed
add plot option to save animation as a movie
1 parent 3b466ec commit c51f133

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

roboticstoolbox/backend/PyPlot/functions.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@
99
from spatialmath.base.argcheck import getvector, verifymatrix
1010
from roboticstoolbox.backend.PyPlot.EllipsePlot import EllipsePlot
1111
from matplotlib.widgets import Slider
12+
try:
13+
import PIL
14+
_pil_exists = True
15+
except ImportError:
16+
_pil_exists = False
1217

1318

1419
def _plot(
1520
robot, block, q, dt, limits=None,
1621
vellipse=False, fellipse=False,
17-
jointaxes=True, eeframe=True, shadow=True, name=True):
22+
jointaxes=True, eeframe=True, shadow=True, name=True, movie=None):
1823

1924
# Make an empty 3D figure
2025
env = rp.backend.PyPlot()
@@ -49,11 +54,33 @@ def _plot(
4954
fell = robot.fellipse(centre='ee')
5055
env.add(fell)
5156

57+
if movie is not None:
58+
if not _pil_exists:
59+
raise RuntimeError('to save movies PIL must be installed:\npip3 install PIL')
60+
images = [] # list of images saved from each plot
61+
# make the background white, looks better than grey stipple
62+
env.ax.w_xaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))
63+
env.ax.w_yaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))
64+
env.ax.w_zaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))
65+
5266
if trajn != 1:
5367
for i in range(trajn):
5468
robot.q = q[:, i]
5569
env.step()
5670
time.sleep(dt/1000)
71+
72+
if movie is not None:
73+
# render the frame and save as a PIL image in the list
74+
canvas = env.fig.canvas
75+
img = PIL.Image.frombytes('RGB', canvas.get_width_height(),
76+
canvas.tostring_rgb())
77+
images.append(img)
78+
79+
if movie is not None:
80+
# save it as an animated GIF
81+
images[0].save(movie,
82+
save_all=True, append_images=images[1:], optimize=False,
83+
duration=dt, loop=0)
5784

5885
# Keep the plot open
5986
if block: # pragma: no cover

roboticstoolbox/robot/SerialLink.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2582,7 +2582,7 @@ def teach(
25822582
def plot(
25832583
self, q=None, block=True, dt=50, limits=None,
25842584
vellipse=False, fellipse=False,
2585-
jointaxes=True, eeframe=True, shadow=True, name=True):
2585+
jointaxes=True, eeframe=True, shadow=True, name=True, movie=None):
25862586
'''
25872587
Graphical display and animation
25882588
@@ -2630,6 +2630,8 @@ def plot(
26302630
:type shadow: bool
26312631
:param name: (Plot Option) Plot the name of the robot near its base
26322632
:type name: bool
2633+
:param movie: name of file in which to save an animated GIF
2634+
:type movie: str
26332635
26342636
:retrun: A reference to the PyPlot object which controls the
26352637
matplotlib figure
@@ -2641,7 +2643,8 @@ def plot(
26412643
return _plot(
26422644
self, block, q, dt, limits,
26432645
vellipse=vellipse, fellipse=fellipse,
2644-
jointaxes=jointaxes, eeframe=eeframe, shadow=shadow, name=name)
2646+
jointaxes=jointaxes, eeframe=eeframe, shadow=shadow, name=name,
2647+
movie=movie)
26452648
# except ModuleNotFoundError:
26462649
# print(
26472650
# 'Could not find matplotlib.'

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy