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)