Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support widget on JupyterHub / Binder? #67

Open
EricCousineau-TRI opened this issue Feb 26, 2020 · 3 comments
Open

Support widget on JupyterHub / Binder? #67

EricCousineau-TRI opened this issue Feb 26, 2020 · 3 comments

Comments

@EricCousineau-TRI
Copy link

In RobotLocomotion/drake#12645, we did some brief investigation for meshcat-python within Binder / JupyterHub, and it seems like the current setup for it does not work well with the remote interface:
RobotLocomotion/drake#12645 (comment)

Is there any chance that you (or anyone else) have encountered this, either for meshcat-python or MeshCat.jl?

@rdeits
Copy link
Collaborator

rdeits commented May 22, 2020

Copying from my email for posterity:

Oh, yeah, I actually have thought about that a bit. I've tried in the past to communicate with the visualizer through the jupyter messaging protocol and it's been a nightmare. I've never been able to get it to work reliably without requiring the user to install some custom jupyter extension, which is too annoying to be worthwhile.

On the other hand, there's a pretty good compromise which actually turns out to be really easy: rather than rendering the visualizer live, you can ask the visualizer to give you a fully static HTML blob including the whole scene (even any animations you've added). Then the frontend can display that as raw HTML, which should work no matter where the jupyter kernel happens to be running.

If you want to try it out, pull the latest meshcat-python, start up a jupyter notebook, and do something like:

import meshcat
import meshcat.geometry as g
import meshcat.transformations as tf
from meshcat.animation import Animation

vis = meshcat.Visualizer()
vis.set_object(g.Box([1., 1., 1.]))

anim = Animation()
with anim.at_frame(vis, 0) as frame:
    frame.set_transform(tf.translation_matrix([0., 0, 0]))
with anim.at_frame(vis, 30) as frame:
    frame.set_transform(tf.translation_matrix([1., 0, 0]))
vis.set_animation(anim)

vis.render_static()

The jupyter output cell should contain a static version of the meshcat scene. It will still be interactive (as in, you can still access all the controls, move the camera, and replay or record the animation), but any future set_object or set_transform calls won't affect what's displayed there. That's obviously not ideal, but it should be very reliable and should work no matter what kind of hosting setup you're using.

As a further bonus, you can also dump that same HTML to a file if you want to embed it in a website or just save it for later. The static_html function will provide that HTML as a string. It's not exactly efficient, since it includes the entire meshcat javascript library and all its dependencies, but it works.

@EricCousineau-TRI
Copy link
Author

Thanks you so much! We will try that out!

Additionally, it looks like Binder / JupyterHub / whatevs may have a mechanism for a proxy to be used too, so we may investigate that as well for meshcat / meshcat-python:
RobotLocomotion/drake#12645 (comment)

For example, it looks like you can run a Bokeh server through a proxy?

https://mybinder.readthedocs.io/en/latest/sample_repos.html?highlight=port#running-a-bokeh-server-with-binder

The proxy looks interesting, though it would still need some moderate patching on the meshcat side if you can indeed proxy the server through tcp/8888 and forward that to tcp/443.

@RussTedrake
Copy link
Collaborator

@rdeits -- the example worked beautifully on my machine and on Binder!!

fwiw, on colab, I think it failed to start a meshcat_server. The error I got running your example is

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-2-227f3a79d8b5> in <module>()
      4 from meshcat.animation import Animation
      5 
----> 6 vis = meshcat.Visualizer()
      7 vis.set_object(g.Box([1., 1., 1.]))
      8 

3 frames
/opt/drake/lib/python3.6/site-packages/meshcat/visualizer.py in capture(pattern, s)
     20     match = re.match(pattern, s)
     21     if not match:
---> 22         raise ValueError("Could not match {:s} with pattern {:s}".format(s, pattern))
     23     else:
     24         return match.groups()[0]

ValueError: Could not match  with pattern ^zmq_url=(.*)$

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants