Skip to content

Commit

Permalink
Fix show logic in pyplot visualizer (RobotLocomotion#12658)
Browse files Browse the repository at this point in the history
The show arguments passed into the recording methods were doing nothing (they were accidentally setting self.show instead of self._show).  And it was too late, anyhow, to prevent a window being drawn in the jupyter workflow.  This commit does the shenanigans necessary to avoid that extra plot.

Unfortunately, the drawing/not drawing is not something we currently test.
RussTedrake authored Feb 2, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 94925df commit f81df12
Showing 3 changed files with 43 additions and 11 deletions.
8 changes: 6 additions & 2 deletions bindings/pydrake/systems/planar_scenegraph_visualizer.py
Original file line number Diff line number Diff line change
@@ -72,7 +72,8 @@ def __init__(self,
ylim=[-1, 1],
facecolor=[1, 1, 1],
use_random_colors=False,
ax=None):
ax=None,
show=None):
"""
Args:
scene_graph: A SceneGraph object.
@@ -90,13 +91,16 @@ def __init__(self,
ax: If supplied, the visualizer will draw onto those axes instead
of creating a new set of axes. The visualizer will still change
the view range and figure size of those axes.
show: Opens a window during initialization / publish iff True.
Default is None, which implies show=True unless
matplotlib.get_backend() is 'template'.
"""
default_size = matplotlib.rcParams['figure.figsize']
scalefactor = (ylim[1]-ylim[0]) / (xlim[1]-xlim[0])
figsize = (default_size[0], default_size[0]*scalefactor)

PyPlotVisualizer.__init__(self, facecolor=facecolor, figsize=figsize,
ax=ax, draw_period=draw_period)
ax=ax, draw_period=draw_period, show=show)
self.set_name('planar_multibody_visualizer')

self._scene_graph = scene_graph
25 changes: 18 additions & 7 deletions bindings/pydrake/systems/pyplot_visualizer.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import matplotlib
import matplotlib.animation as animation
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
import numpy as np
from warnings import warn

from pydrake.systems.framework import LeafSystem, PublishEvent, TriggerType
from pydrake.systems.primitives import SignalLogger
@@ -26,7 +26,7 @@ class PyPlotVisualizer(LeafSystem):
"""

def __init__(self, draw_period=1./30, facecolor=[1, 1, 1],
figsize=None, ax=None):
figsize=None, ax=None, show=None):
LeafSystem.__init__(self)

self.set_name('pyplot_visualization')
@@ -41,14 +41,22 @@ def __init__(self, draw_period=1./30, facecolor=[1, 1, 1],
self.ax = ax
self.fig = ax.get_figure()

if show is None:
show = (matplotlib.get_backend().lower() != 'template')
self._show = show

self.ax.axis('equal')
self.ax.axis('off')

if not show:
# This is the preferred way to support the jupyter notebook
# animation workflow and the `inline` backend grabbing an
# extraneous render of the figure.
plt.close(self.fig)

self._is_recording = False
self._recorded_contexts = []

self._show = (matplotlib.get_backend().lower() != 'template')

def on_initialize(context, event):
if self._show:
self.fig.show()
@@ -77,13 +85,16 @@ def draw(self, context):
"""
raise NotImplementedError

def start_recording(self, show=True):
self.show = show
def start_recording(self, show=None):
if show is not None:
warn("The `show` argument of this `start_recording()` method "
"actually never worked. Pass `show` to the class "
"constructor instead. This argument will be removed on or "
"after 2020-04-01.")
self._is_recording = True

def stop_recording(self):
self._is_recording = False
self.show = (matplotlib.get_backend().lower() != 'template')

def reset_recording(self):
self._recorded_contexts = [] # Reset recorded data.
21 changes: 19 additions & 2 deletions tutorials/pyplot_animation_multibody_plant.ipynb
Original file line number Diff line number Diff line change
@@ -112,7 +112,7 @@
"metadata": {},
"outputs": [],
"source": [
"def run_pendulum_example(duration=1., playback=True):\n",
"def run_pendulum_example(duration=1., playback=True, show=True):\n",
" \"\"\"\n",
" Runs a simulation of a pendulum.\n",
"\n",
@@ -134,7 +134,7 @@
" [0., 0., 0., 1.]])\n",
" visualizer = builder.AddSystem(PlanarSceneGraphVisualizer(\n",
" scene_graph, T_VW=T_VW,\n",
" xlim=[-1.2, 1.2], ylim=[-1.2, 1.2]))\n",
" xlim=[-1.2, 1.2], ylim=[-1.2, 1.2], show=show))\n",
" builder.Connect(pose_bundle_output_port, visualizer.get_input_port(0))\n",
" if playback:\n",
" visualizer.start_recording()\n",
@@ -239,6 +239,23 @@
"if animation.writers.is_available(\"ffmpeg\"):\n",
" display(HTML(ani.to_html5_video()))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you do not want to render the image (only the animation), then pass `show=False` in to the constructor of `PlanarSceneGraphVisualizer()`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ani = run_pendulum_example(playback=True, show=False)\n",
"HTML(ani.to_jshtml())"
]
}
],
"metadata": {

0 comments on commit f81df12

Please sign in to comment.