Skip to content

Commit 15d01f9

Browse files
authored
Web UI proof of concept with Plotly Dash (#439)
1 parent 2ab03e2 commit 15d01f9

38 files changed

Lines changed: 2232 additions & 55 deletions

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ jobs:
9292
junitxml-path: ./test/results/test_results.xml
9393
pytest-xml-coverage-path: ./test/results/test_results_coverage.xml
9494
coverage-path-prefix: pyrobosim/pyrobosim/
95-
remove-links-to-files: true # gets around issues of comment being too long
95+
remove-links-to-lines: true # gets around issues of comment being too long
9696
if: ${{ !github.event.pull_request.head.repo.fork }}
9797
- name: Create coverage badge
9898
uses: schneegans/dynamic-badges-action@v1.7.0

.readthedocs.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ python:
1313
- requirements: docs/python_docs_requirements.txt
1414
- method: pip
1515
path: pyrobosim
16+
extra_requirements:
17+
- web
1618
- method: pip
1719
path: pyrobosim_ros
1820

docker/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ RUN pip3 install -r docs/python_docs_requirements.txt && \
4141

4242
# Copy the rest of the source directory and install PyRoboSim
4343
COPY . /opt/pyrobosim/
44-
RUN pip3 install -e pyrobosim
44+
RUN pip3 install -e pyrobosim[web]
4545

4646
# Set the default startup command
4747
CMD /bin/bash
@@ -89,7 +89,7 @@ COPY test/python_test_requirements.txt test/
8989
# and lacks the 'build_editable' hook.
9090
RUN source ${VIRTUAL_ENV}/bin/activate && \
9191
pip3 install --upgrade pip setuptools && \
92-
pip3 install -e ./pyrobosim && \
92+
pip3 install -e ./pyrobosim[web] && \
9393
pip3 install -r docs/python_docs_requirements.txt && \
9494
pip3 install -r test/python_test_requirements.txt
9595

docs/source/setup.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ However, note that this will not include any of the ROS 2 or Task and Motion Pla
1717

1818
pip install pyrobosim
1919

20+
To also install the optional dependencies for the web-based visualization, use the ``web`` extra:
21+
22+
::
23+
24+
pip install pyrobosim[web]
25+
2026

2127
Local Setup
2228
-----------

docs/source/usage/basic_usage.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,36 @@ For example:
9191

9292
Refer to the :ref:`yaml_schemas` documentation for more information.
9393

94+
Web UI (Experimental)
95+
---------------------
96+
97+
PyRoboSim also has an experimental browser-based UI built with `Plotly Dash <https://dash.plotly.com/>`_.
98+
This is a lightweight alternative to the Qt GUI, and the goal is to replace it in a future major release.
99+
It requires the optional web dependencies, which you can install with ``pip install pyrobosim[web]``.
100+
101+
Most examples accept a ``--web`` flag to launch the web UI instead of the Qt GUI:
102+
103+
::
104+
105+
python3 examples/demo.py --web
106+
107+
The ROS examples instead expose this as a ``web`` node parameter, which is also available as a launch argument:
108+
109+
::
110+
111+
ros2 launch pyrobosim_ros demo.launch.py web:=true
112+
113+
Then, open ``http://localhost:8050`` in your browser to interact with the world.
114+
115+
To use the web UI in your own scripts, pass ``web=True`` to ``start_gui``:
116+
117+
.. code-block:: python
118+
119+
from pyrobosim.gui import start_gui
120+
121+
start_gui(world, web=True, web_host="127.0.0.1", web_port=8050)
122+
123+
Note that the web server is unauthenticated, so only bind to a non-localhost address (``web_host``) on networks you trust.
94124

95125
Exporting Worlds to Gazebo
96126
--------------------------

docs/source/usage/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ PyRoboSim offers a standalone Python API for modeling worlds and simulating robo
55
Optionally, you can also launch this tool with:
66

77
* A ROS 2 interface that offers topics, services, and actions to interact with the world.
8-
* A `PySide6 <https://doc.qt.io/qtforpython-6/>`_ based GUI for visualizing the world.
8+
* A `PySide6 <https://doc.qt.io/qtforpython-6/>`_ based GUI, and an experimental `Plotly Dash <https://dash.plotly.com/>`_ web UI, for visualizing the world.
99

1010
Refer to the following pages for different types of usage guides.
1111

pyrobosim/examples/demo.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ def parse_args() -> argparse.Namespace:
226226
action="store_true",
227227
help="If True, adds a lidar sensor to the first robot.",
228228
)
229+
parser.add_argument(
230+
"--web",
231+
action="store_true",
232+
help="Launch the browser-based web UI instead of the Qt GUI.",
233+
)
229234
return parser.parse_args()
230235

231236

@@ -238,5 +243,5 @@ def parse_args() -> argparse.Namespace:
238243
else:
239244
world = create_world_from_yaml(args.world_file)
240245

241-
# Start the program either as ROS node or standalone.
242-
start_gui(world)
246+
# Start the program in the web UI or the Qt GUI.
247+
start_gui(world, web=args.web)

pyrobosim/examples/demo_astar.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env python3
22

3+
import argparse
34

45
from pyrobosim.core import WorldYamlLoader
56
from pyrobosim.gui import start_gui
@@ -34,5 +35,13 @@ def demo_astar() -> None:
3435

3536

3637
if __name__ == "__main__":
38+
parser = argparse.ArgumentParser(description="A* planner demo.")
39+
parser.add_argument(
40+
"--web",
41+
action="store_true",
42+
help="Launch the browser-based web UI instead of the Qt GUI.",
43+
)
44+
args = parser.parse_args()
45+
3746
demo_astar()
38-
start_gui(world)
47+
start_gui(world, web=args.web)

pyrobosim/examples/demo_dynamics.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
Test script showing how to command robot velocities and simulate dynamics.
55
"""
66

7+
import argparse
78
import numpy as np
89
import time
910
from threading import Thread
@@ -118,11 +119,18 @@ def command_robots(world: World) -> None:
118119

119120

120121
if __name__ == "__main__":
122+
parser = argparse.ArgumentParser(description="Robot dynamics demo.")
123+
parser.add_argument(
124+
"--web",
125+
action="store_true",
126+
help="Launch the browser-based web UI instead of the Qt GUI.",
127+
)
128+
args = parser.parse_args()
129+
121130
world = create_world()
122131

123132
# Command robots on a separate thread.
124133
robot_commands_thread = Thread(target=lambda: command_robots(world))
125134
robot_commands_thread.start()
126135

127-
# Start the program either as ROS node or standalone.
128-
start_gui(world)
136+
start_gui(world, web=args.web)

pyrobosim/examples/demo_partial_obs_hallways.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ def parse_args() -> argparse.Namespace:
214214
action="store_true",
215215
help="This option will add multiple robots to the world.",
216216
)
217+
parser.add_argument(
218+
"--web",
219+
action="store_true",
220+
help="Launch the browser-based web UI instead of the Qt GUI.",
221+
)
217222
return parser.parse_args()
218223

219224

@@ -223,5 +228,5 @@ def parse_args() -> argparse.Namespace:
223228
# Create a world.
224229
world = create_world(args.multirobot)
225230

226-
# Start the GUI.
227-
start_gui(world)
231+
# Start the program in the web UI or the Qt GUI.
232+
start_gui(world, web=args.web)

0 commit comments

Comments
 (0)