Skip to content

Commit

Permalink
first version of mission control ui
Browse files Browse the repository at this point in the history
  • Loading branch information
ipa-rar committed Sep 5, 2023
0 parents commit d8bcc55
Show file tree
Hide file tree
Showing 6 changed files with 322 additions and 0 deletions.
164 changes: 164 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
influxdb.conf/
influxdb2/
config.yaml/
.vscode
temp.py
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
Binary file added assets/swarmbots-graphic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/swarmbots-graphic_.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
138 changes: 138 additions & 0 deletions gui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
from nicegui import ui
import os
import signal
import subprocess


TABS = ["Home",
"Simulation",
"Observers"]

LAUNCH = [
"ros2 launch multirobot_bringup multirobot_bringup.launch.xml",
"ros2 run multirobot_formation agent_formation_node",
"ros2 run multirobot_formation mock_test",
"ros2 run multirobot_formation resetPose",]

OBSERVERS = [
"ros2 run formation_error_observer main",
"ros2 run localization_error_observer localization_error_observer 4",
"ros2 run mileage_observer main 10 4",
"ros2 run power_usage_observer main 4",]

process = None
task = None


async def read_markdown_file(file_path):
with open(file_path, "r") as f:
markdown_content = f.read()
return markdown_content

# Global variable to store the processes
ros2_processes = []

async def start_ros2_launch(ros_launch_command):
global ros2_processes

try:
# Start the ROS 2 launch process
process = subprocess.Popen(
ros_launch_command,
shell=True,
cwd=os.path.dirname(os.path.abspath(__file__)),
preexec_fn=os.setsid # This is used to create a process group to enable sending signals to the entire group
)
ros2_processes.append(process)
print(f"ROS 2 launch process started: {ros_launch_command}")
except Exception as e:
print(f"Error starting ROS 2 launch process: {str(e)}")

async def stop_ros2_launch():
global ros2_processes

for process in ros2_processes:
try:
# Send the SIGINT signal to the entire process group to gracefully terminate ROS 2 launch
os.killpg(os.getpgid(process.pid), signal.SIGINT)
process.wait() # Wait for the process to finish
print(f"ROS 2 launch process terminated.")
except Exception as e:
print(f"Error stopping ROS 2 launch process: {str(e)}")

ros2_processes = []

@ui.page('/')
def view():
with ui.footer(value=True).style('background-color: #bd94ea') as footer:
ui.label(
'SwarmBots @ Fraunhofer IPA 2023').classes('absolute-center items-center')
with ui.column().classes('w-full items-center'):
ui.label('SwarmBots Mission Controller').classes(
'text-h2 mt-10').style('color: #bd94ea')
# ui.label('ROS 2 Demonstrator 326').classes('text-h4 my-2')
with ui.tabs().classes('w-1/2 justify-center').props('h2') as tabs:
for tab in TABS:
ui.tab(tab).classes('w-1/2 text-center').style('font-size: 20px;')

with ui.tab_panels(tabs, value=TABS[1]):
with ui.tab_panel(TABS[0]):
# with ui.card().classes('mt-10 mb-1 w-96 h-96').style('width: 64vw; position: relative'):
with ui.row().classes('text-center'):
ui.label('')
ui.image('assets/swarmbots-graphic.png').classes('mt-10 mb-1 w-96 h-96').style('width: 50vw; position: relative')

with ui.tab_panel(TABS[1]):
with ui.card().classes('mt-10 mb-1 w-96 h-56').style('width: 60vw; position: relative'):
with ui.row().classes('text-center'):
ui.label("").classes("text-h6 text-muted")
with ui.row():
ui.button('Start Simulator', color='#9312fa', on_click=lambda: start_ros2_launch(LAUNCH[0])).style('color: white; font-size: 20px; padding: 20px 20px; border-radius: 50px;').classes("my-10 items-center")
ui.button('Start Formation', color='#9312fa', on_click=lambda: start_ros2_launch(LAUNCH[1])).style('color: white; font-size: 20px; padding: 20px 20px; border-radius: 50px;').classes("my-10 items-center")

with ui.card().classes('mt-10 mb-1 w-96 h-56').style('width: 60vw; position: relative'):
with ui.row().classes('text-center'):
ui.label("").classes("text-h6 text-muted")
with ui.row():
ui.button('Start Navigation', color='#9312fa', on_click=lambda: start_ros2_launch(LAUNCH[2])).style('color: white; font-size: 20px; padding: 20px 20px; border-radius: 50px;').classes("my-10 items-center")
ui.button('Reset Robots', color='#9312fa', on_click=lambda: start_ros2_launch(LAUNCH[3])).style('color: white; font-size: 20px; padding: 20px 20px; border-radius: 50px;').classes("my-10 items-center")

with ui.card().classes('mt-10 mb-1 w-96 h-56').style('width: 60vw; position: relative'):
with ui.row().classes('text-center'):
ui.label("").classes("text-h6 text-muted")
with ui.row():
ui.button('Stop Simulator', color='#cb5153', on_click=stop_ros2_launch).style('color: white; font-size: 20px; padding: 20px 20px; border-radius: 50px;').classes("my-10 absolute-center")


with ui.tab_panel(TABS[2]):
ui.label("Select the property observer").classes(
"text-h4 my-2 text-center").style('color: #9312fa')
with ui.card().classes('mt-10 mb-1 w-96 h-56').style('width: 60vw; position: relative'):
with ui.row().classes('text-center'):
ui.label("").classes("text-h6 text-muted")
with ui.row():
ui.button('Formation', color='#9312fa', on_click=lambda: start_ros2_launch(OBSERVERS[0])).style('color: white; font-size: 20px; padding: 20px 20px; border-radius: 50px;').classes("my-10 justify-center")

ui.button('Localization', color='#9312fa', on_click=lambda: start_ros2_launch(OBSERVERS[1])).style('color: white; font-size: 20px; padding: 20px 20px; border-radius: 50px;').classes("my-10 justify-center")

ui.button('Mileage', color='#9312fa', on_click=lambda: start_ros2_launch(OBSERVERS[3])).style('color: white; font-size: 20px; padding: 20px 20px; border-radius: 50px;').classes("my-10 justify-center")

ui.button('Power usage', color='#9312fa', on_click=lambda: start_ros2_launch(OBSERVERS[2])).style('color: white; font-size: 20px; padding: 20px 20px; border-radius: 50px;').classes("my-10 justify-center")

with ui.card().classes('mt-10 mb-1 w-96 h-56').style('width: 60vw; position: relative'):
with ui.row().classes('text-center'):
ui.label("").classes("text-h6 text-muted")
with ui.row():
ui.button('Stop', color='#cb5153', on_click=stop_ros2_launch).style('color: white; font-size: 20px; padding: 20px 20px; border-radius: 50px;').classes("my-10 absolute-center")

# with ui.tab_panel(TABS[3]):
# ui.label('Documentation').classes('text-h4 my-2 text-center').style('color: #25957b')
# markdown_content = read_markdown_file("multirobot_mission_control/static/docs.md")
# ui.markdown(markdown_content)




ui.run()


2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
nicegui
uvicorn
18 changes: 18 additions & 0 deletions static/docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Multi Robot Formation for SwarmBot

## 1. Bringup the multirobot simulation, Localization and Pathplanning
````
ros2 launch multirobot_bringup multirobot_bringup.launch.xml
````
## 2. Send pallet pose from rviz2
````
ros2 launch multirobot_formation formation_control.launch.py
````
Number of agents vary from 1 to N, ``default value:=4``

## 3. To perform Localization error experiments
Run the launch files in 1 and 2 and then run the mock_test node.
```
ros2 run multirobot_formation mock_test
```
**Note:**- In case the mock test does not start, please provide a goal in the rviz.

0 comments on commit d8bcc55

Please sign in to comment.