py_trees_ros_viewer icon indicating copy to clipboard operation
py_trees_ros_viewer copied to clipboard

Run as Webapp for easier Docker portability

Open BunteStadt opened this issue 10 months ago • 3 comments

Hallo

i love the features of easy deployment when working on docker. Howevery every time some GUI parts are involved, alot of ease of use is gone as i need to make sure a X Server is setup and running correctly on the host. A Webapp would be way easyer to interact with, as nearly every host has a webbrowser.

Sadly i have only very limited knowledge in this part. I tried to follow the instructions here: https://github.com/splintered-reality/py_trees_js#usage But could not make it work.

I would like to reach one of these to goals and am looking for assistance to achive them.

  1. Right now i use NiceGui to buid my dashboards. I would love to have an easy way to integrate the Tree Viewer inside the NiceGUI website.
  2. As it might be easier to achive. I would like to run a node that automaticly hosts a website under localhost:1234 which i can open and interact with the viewer as in the gui version.

It would help me alot if someone could give me some recomendations or advice on how to achive this.

BunteStadt avatar Jan 25 '25 16:01 BunteStadt

Right now i use NiceGui to buid my dashboards. I would love to have an easy way to integrate the Tree Viewer inside the NiceGUI website.

I'm no expert on web things, but ... some ideas:

  1. You'll need something like QWebEngineView in which you can insert the app that includes the javascript application (e.g. see index.html)

  2. For quick testing - write some python code in your main around NiceGui to send the app some test tree data (that's what I did in the pyqt demo). QWebEngineView has some mechanism for interacting with the app inside it from the python main. NiceGui might or might not have this capability. If not, that's ok. Just proceed to step 3.

  3. Get yoru nicegui app to interact with an external tree. Either drop websockets in your app that your external tree can communicate with or setup python communications of some sort in your python main (this would then redirect the comms to the internal js app).

If that's all possible with NiceGui, it'd be nice to upgrade the reference demo here. It'd have no reliance then on having an X server (or equivalent) in the environment.

stonier avatar Jan 25 '25 18:01 stonier

Hi Stonier, thank you for your advice. After spending the whole weekend i came up with a somewhat working setup.

I use the Backend.tree_snapshot_handler to return the current tree to nicegui. Nicegui calls the render_tree function with that tree.

So far this works quite goo. The the gets rendered and when the render_tree js function is called, the new tree is rendered and added to the timeline.

But when i want to introspect a old tree from the timeline, i run into a problem: I can select the tree and it is desplayed acordingly (the red marker also indicates, that i view a in the timeline) However, every time a new tree gets renderd with render_tree, the whole timepline iterates aswell. So the past tree i want to watch also gets iterated one towards the future.

Do you have an idea why this is happening and how to solve it?

Right now i am workin on a ros2 package as for you to add to the repo.

Here my html code which is basically the one from your readme.

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>PyTrees Viewer</title>
  <link rel="stylesheet" href="js/py_trees-0.6.css"/>
  <link rel="stylesheet" type="text/css" href="js/jointjs/joint-3.0.4.min.css"/>
  <script src="js/jointjs/dagre-0.8.4.min.js"></script>
  <script src="js/jointjs/graphlib-2.1.7.min.js"></script>
  <script src="js/jointjs/jquery-3.4.1.min.js"></script>
  <script src="js/jointjs/lodash-4.17.11.min.js"></script>
  <script src="js/jointjs/backbone-1.4.0.js"></script>
  <script src="js/jointjs/joint-3.0.4.min.js"></script>
  <script src="js/py_trees-0.6.js"></script>
  <!-- Web app integration css here -->
  <style>
    html {
      height: 100%  /* canvas is intended to fill the screen, cascading heights achieves this */
    }
    body {
      margin: 0;
      overflow:hidden;  /* no scrollbars */
      height: 100%  /* canvas is intended to fill the screen, cascading heights achieves this */
    }
  </style>
</head>
<body>
  <script type="text/javascript">
    //py_trees.hello()
  </script>
  <div id="canvas"></div>
  <div id="timeline"></div>
  <script type="text/javascript">
    // rendering canvas
    canvas_graph = py_trees.canvas.create_graph()
    canvas_paper = py_trees.canvas.create_paper({graph: canvas_graph})

    // event timeline
    timeline_graph = py_trees.timeline.create_graph({event_cache_limit: 100});
    timeline_paper = py_trees.timeline.create_paper({
        timeline_graph: timeline_graph,
        canvas_graph: canvas_graph,
        canvas_paper: canvas_paper,
    })

    // react to window resizing events
    $(window).resize(function() {
      py_trees.canvas.on_window_resize(canvas_paper)
      py_trees.timeline.on_window_resize(timeline_paper)
    })


    render_tree = function({tree}) {
      py_trees.canvas.update_graph({graph: canvas_graph, tree: tree})
      py_trees.canvas.layout_graph({graph: canvas_graph})
      if ( canvas_graph.get('scale_content_to_fit') ) {
        py_trees.canvas.scale_content_to_fit(canvas_paper)
      }
      py_trees.timeline.add_tree_to_cache({
          timeline_graph: timeline_graph,
          canvas_graph: canvas_graph,
          canvas_paper: canvas_paper,
          tree: tree
      })
      return "rendered"
    }

    // Here the tree is rendered. The updated tree needs to be put here.
    //render_tree({tree: py_trees.experimental.create_demo_tree_definition()})
  </script>
</body>
</html>

BunteStadt avatar Jan 27 '25 09:01 BunteStadt

Here you can fine my minimal workin prototype: https://github.com/BunteStadt/ros2_nicegui_with_py_tree_ros_viewer

BunteStadt avatar Jan 27 '25 09:01 BunteStadt