├── .github └── workflows │ ├── container.yml │ ├── doc.yml │ └── main.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── build_docker_images.sh ├── docker ├── .dockerignore ├── .gitattributes ├── .gitignore ├── LICENSE.md ├── README.md ├── dockerfile-kasm-core-jammy ├── dockerfile-suave ├── follow_bluerov.PNG └── src │ ├── common │ ├── install │ │ ├── configure_firefox.sh │ │ ├── kasm_vnc │ │ │ └── kasmvnc.yaml │ │ └── profile_sync │ │ │ └── kasm_background_profile_sync.sh │ ├── resources │ │ └── images │ │ │ ├── bg_jammy.png │ │ │ ├── bg_kasm.png │ │ │ ├── icon_kasm.png │ │ │ └── icon_ubuntu.png │ ├── scripts │ │ └── kasm_hook_scripts │ │ │ ├── kasm_post_run_root.sh │ │ │ ├── kasm_post_run_user.sh │ │ │ ├── kasm_pre_shutdown_root.sh │ │ │ └── kasm_pre_shutdown_user.sh │ └── startup_scripts │ │ ├── generate_container_user │ │ ├── kasm_default_profile.sh │ │ ├── set_user_permission.sh │ │ └── vnc_startup.sh │ └── ubuntu │ ├── icewm │ ├── .icewm │ │ ├── menu │ │ ├── preferences │ │ ├── theme │ │ └── toolbar │ └── wm_startup.sh │ ├── install │ ├── cursors │ │ ├── cursor-aero.tar.gz │ │ ├── cursor-bridge.tar.gz │ │ ├── cursor-capitaine-r4.tar.gz │ │ └── install_cursors.sh │ ├── extra │ │ ├── kali.sh │ │ ├── noop.sh │ │ └── remnux.sh │ ├── fonts │ │ └── install_custom_fonts.sh │ ├── kasm_upload_server │ │ └── install_kasm_upload_server.sh │ ├── kasm_vnc │ │ └── install_kasm_vnc.sh │ ├── maximize_script │ │ └── maximize_window.sh │ ├── nvidia │ │ └── 10_nvidia.json │ ├── squid │ │ ├── install │ │ │ └── install_squid.sh │ │ └── resources │ │ │ ├── SN.png │ │ │ ├── error_message │ │ │ └── access_denied.html │ │ │ ├── squid.conf │ │ │ ├── ssl_bump_bypass_domains.conf │ │ │ ├── ssl_bump_bypass_ips.conf │ │ │ └── start_squid.sh │ ├── suave │ │ ├── install_suave.sh │ │ └── install_suave_deps.sh │ ├── terminal │ │ └── custom_startup.sh │ ├── tools │ │ ├── install_tools.sh │ │ └── install_tools_deluxe.sh │ ├── unison │ │ └── install_unison.sh │ ├── virtualgl │ │ ├── install_virtualgl.sh │ │ ├── virtualgl_3.0.80_amd64.deb │ │ └── virtualgl_3.0.80_arm64.deb │ ├── vs_code │ │ ├── custom_startup.sh │ │ └── install_vs_code.sh │ └── xfce │ │ └── install_xfce_ui.sh │ └── xfce │ └── .config │ └── xfce4 │ └── xfconf │ ├── single-application-xfce-perchannel-xml │ ├── xfce4-desktop.xml │ ├── xfce4-keyboard-shortcuts.xml │ └── xfwm4.xml │ └── xfce-perchannel-xml │ ├── xfce4-desktop.xml │ ├── xfce4-keyboard-shortcuts.xml │ ├── xfce4-panel.xml │ ├── xfce4-session.xml │ ├── xfwm4.xml │ └── xsettings.xml ├── docs ├── Makefile ├── make.bat └── source │ ├── _templates │ └── autosummary │ │ ├── class.rst │ │ └── module.rst │ ├── api.rst │ ├── citing.md │ ├── conf.py │ ├── docker.md │ ├── extend.md │ ├── index.rst │ ├── installation.md │ ├── related.md │ ├── run.md │ └── troubleshooting.md ├── runner ├── SEAMS2023_results_run.sh ├── example_run.sh ├── headless_runner.sh ├── runner.sh └── scripts │ ├── launch_mission.sh │ ├── launch_sim.sh │ └── start_ardusub.sh ├── suave.repos ├── suave ├── LICENSE ├── config │ └── suave_modes.yaml ├── launch │ ├── simulation.launch.py │ ├── suave.launch.py │ └── system_modes.launch.py ├── package.xml ├── resource │ └── suave ├── setup.cfg ├── setup.py ├── suave │ ├── __init__.py │ ├── bluerov_gazebo.py │ ├── follow_pipeline_lc.py │ ├── pipeline_detection.py │ ├── pipeline_detection_wv.py │ ├── recharge_battery_lc.py │ ├── recover_thrusters_lc.py │ ├── spiral_search_lc.py │ ├── task_bridge.py │ └── task_bridge_none.py └── test │ ├── test_copyright.py │ ├── test_flake8.py │ └── test_pep257.py ├── suave_managing ├── suave_bt │ ├── CMakeLists.txt │ ├── LICENSE │ ├── bts │ │ ├── suave.xml │ │ └── suave_extended.xml │ ├── include │ │ └── suave_bt │ │ │ ├── action_arm_thrusters.hpp │ │ │ ├── action_change_mode.hpp │ │ │ ├── action_inspect_pipeline.hpp │ │ │ ├── action_recharge_battery.hpp │ │ │ ├── action_search_pipeline.hpp │ │ │ ├── action_set_guided_mode.hpp │ │ │ ├── condition_battery_level.hpp │ │ │ ├── condition_thrusters_ok.hpp │ │ │ ├── condition_water_visibility.hpp │ │ │ ├── is_pipeline_found.hpp │ │ │ ├── is_pipeline_inspected.hpp │ │ │ ├── suave_mission.hpp │ │ │ └── visibility_control.h │ ├── launch │ │ ├── suave_bt.launch.py │ │ └── suave_bt_extended.launch.py │ ├── package.xml │ └── src │ │ ├── suave_bt.cpp │ │ ├── suave_bt │ │ ├── action_arm_thrusters.cpp │ │ ├── action_change_mode.cpp │ │ ├── action_inspect_pipeline.cpp │ │ ├── action_recharge_battery.cpp │ │ ├── action_search_pipeline.cpp │ │ ├── action_set_guided_mode.cpp │ │ ├── condition_battery_level.cpp │ │ ├── condition_thrusters_ok.cpp │ │ ├── condition_water_visibility.cpp │ │ ├── is_pipeline_found.cpp │ │ ├── is_pipeline_inspected.cpp │ │ └── suave_mission.cpp │ │ └── suave_bt_extended.cpp ├── suave_metacontrol │ ├── config │ │ ├── metacontrol_config.yaml │ │ └── suave.owl │ ├── launch │ │ └── suave_metacontrol.launch.py │ ├── package.xml │ ├── resource │ │ └── suave_metacontrol │ ├── setup.cfg │ ├── setup.py │ ├── suave_metacontrol │ │ ├── __init__.py │ │ └── task_bridge_metacontrol.py │ └── test │ │ ├── test_copyright.py │ │ ├── test_flake8.py │ │ └── test_pep257.py ├── suave_none │ ├── LICENSE │ ├── launch │ │ └── suave_none.launch.py │ ├── package.xml │ ├── resource │ │ └── suave_none │ ├── setup.cfg │ ├── setup.py │ ├── suave_none │ │ └── __init__.py │ └── test │ │ ├── test_copyright.py │ │ ├── test_flake8.py │ │ └── test_pep257.py └── suave_random │ ├── LICENSE │ ├── launch │ └── suave_random.launch.py │ ├── package.xml │ ├── resource │ └── suave_random │ ├── setup.cfg │ ├── setup.py │ ├── suave_random │ ├── __init__.py │ └── task_bridge_random.py │ └── test │ ├── test_copyright.py │ ├── test_flake8.py │ └── test_pep257.py ├── suave_metrics ├── LICENSE ├── package.xml ├── resource │ └── suave_metrics ├── setup.cfg ├── setup.py ├── suave_metrics │ ├── __init__.py │ └── mission_metrics.py └── test │ ├── test_copyright.py │ ├── test_flake8.py │ └── test_pep257.py ├── suave_missions ├── config │ └── mission_config.yaml ├── launch │ ├── const_distance_mission.launch.py │ ├── mission.launch.py │ ├── mission_bringup.launch.py │ └── time_constrained_mission.launch.py ├── package.xml ├── resource │ └── suave_missions ├── results │ ├── seams2023_mission_config.yaml │ └── seams2023_results.csv ├── setup.cfg ├── setup.py ├── suave_missions │ ├── __init__.py │ ├── const_dist_mission.py │ ├── inspection_mission.py │ ├── mission_planner.py │ └── time_constrained_mission.py └── test │ ├── test_copyright.py │ ├── test_flake8.py │ └── test_pep257.py ├── suave_monitor ├── LICENSE ├── package.xml ├── resource │ └── suave_monitor ├── setup.cfg ├── setup.py ├── suave_monitor │ ├── __init__.py │ ├── battery_monitor.py │ ├── thruster_monitor.py │ └── water_visibility_observer.py └── test │ ├── test_copyright.py │ ├── test_flake8.py │ └── test_pep257.py ├── suave_msgs ├── CMakeLists.txt ├── package.xml └── srv │ ├── GetPath.srv │ └── Task.srv └── suave_runner ├── README.md ├── config └── runner_config.yml ├── docker ├── Dockerfile ├── README.md └── log │ ├── COLCON_IGNORE │ ├── latest │ └── latest_version-check ├── launch └── suave_runner_launch.py ├── package.xml ├── resource └── suave_runner ├── setup.cfg ├── setup.py └── suave_runner ├── __init__.py └── suave_runner.py /.github/workflows/container.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | # GitHub recommends pinning actions to a commit SHA. 7 | # To get a newer version, you will need to update the SHA. 8 | # You can also reference a tag or branch, but the action may change without warning. 9 | 10 | name: Docker Images 11 | 12 | on: 13 | push: 14 | branches: 15 | - main 16 | tags: 17 | - 'v*' 18 | 19 | env: 20 | REGISTRY: ghcr.io 21 | IMAGE_NAME: ${{ github.repository }} 22 | 23 | jobs: 24 | build-and-push-image: 25 | runs-on: ubuntu-latest 26 | permissions: 27 | contents: read 28 | packages: write 29 | 30 | steps: 31 | - name: Checkout repository 32 | uses: actions/checkout@v3 33 | 34 | - name: Log in to the Container registry 35 | uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 36 | with: 37 | registry: ${{ env.REGISTRY }} 38 | username: ${{ github.actor }} 39 | password: ${{ secrets.GITHUB_TOKEN }} 40 | 41 | - name: Extract metadata (tags, labels) for Docker 42 | id: meta 43 | uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 44 | with: 45 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 46 | tags: | 47 | type=ref,event=branch 48 | type=ref,event=pr 49 | type=semver,pattern={{version}} 50 | type=semver,pattern={{major}}.{{minor}} 51 | 52 | - name: Build and push kasm-jammy image 53 | uses: docker/build-push-action@v4 54 | with: 55 | context: . 56 | file: docker/dockerfile-kasm-core-jammy 57 | push: true 58 | tags: ${{ env.REGISTRY }}/kas-lab/kasm-jammy 59 | labels: latest 60 | 61 | - name: Build and push suave image 62 | uses: docker/build-push-action@v4 63 | with: 64 | context: . 65 | file: docker/dockerfile-suave 66 | push: true 67 | tags: ${{ steps.meta.outputs.tags }} 68 | labels: ${{ steps.meta.outputs.labels }} 69 | build-args: BASE_IMAGE=${{ env.REGISTRY }}/kas-lab/kasm-jammy:latest 70 | 71 | - name: Build and push suave image 72 | uses: docker/build-push-action@v4 73 | with: 74 | context: suave_runner/docker/ 75 | file: suave_runner/docker/Dockerfile 76 | push: true 77 | tags: ${{ env.REGISTRY }}/kas-lab/suave-headless 78 | labels: ${{ steps.meta.outputs.labels }} -------------------------------------------------------------------------------- /.github/workflows/doc.yml: -------------------------------------------------------------------------------- 1 | name: documentation 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | 9 | permissions: 10 | contents: write 11 | 12 | jobs: 13 | docs: 14 | runs-on: ubuntu-latest 15 | container: ubuntu:22.04 16 | steps: 17 | - uses: actions/checkout@v3.3.0 18 | - uses: ros-tooling/setup-ros@0.7.1 19 | with: 20 | required-ros-distributions: humble 21 | - uses: ros-tooling/action-ros-ci@0.3.5 22 | id: action_ros_ci_step 23 | with: 24 | package-name: suave suave_monitor suave_metrics suave_msgs suave_missions suave_metacontrol system_modes mavros mavros_wrapper mros2_reasoner mros2_msgs suave_runner 25 | target-ros2-distro: humble 26 | skip-tests: true 27 | vcs-repo-file-url: https://raw.githubusercontent.com/kas-lab/suave/main/suave.repos 28 | - name: Install dependencies 29 | run: | 30 | pip install sphinx sphinx_rtd_theme myst_parser sphinx-autopackagesummary myst-parser 31 | - name: Sphinx build 32 | shell: bash 33 | run: | 34 | source ${{ steps.action_ros_ci_step.outputs.ros-workspace-directory-name }}/install/setup.bash 35 | sphinx-build docs/source docs/build 36 | - name: Deploy to GitHub Pages 37 | uses: peaceiris/actions-gh-pages@v3 38 | if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} 39 | with: 40 | publish_branch: gh-pages 41 | github_token: ${{ secrets.GITHUB_TOKEN }} 42 | publish_dir: docs/build/ 43 | force_orphan: true 44 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Main 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build_docker: 10 | name: Build suave pkg 11 | runs-on: ubuntu-latest 12 | container: 13 | image: rostooling/setup-ros-docker:ubuntu-jammy-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v2 17 | - name: Build pkg 18 | uses: ros-tooling/action-ros-ci@0.3.5 19 | with: 20 | package-name: suave 21 | target-ros2-distro: humble 22 | vcs-repo-file-url: https://raw.githubusercontent.com/kas-lab/suave/main/suave.repos 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *error.owl 2 | docs/source/_autosummary/ 3 | docs/build/ 4 | 5 | !suave_missions/results/seams2023_results.csv 6 | !suave_missions/results/seams2023_mission_config.yaml 7 | suave_missions/results 8 | .idea 9 | 10 | docker/install/ 11 | docker/log/ 12 | 13 | *catalog-*.xml 14 | 15 | *.swp 16 | logs/* 17 | eeprom.bin 18 | mav.parm 19 | mav.tlog 20 | mav.tlog.raw 21 | 22 | # Byte-compiled / optimized / DLL files 23 | __pycache__/ 24 | *.py[cod] 25 | *$py.class 26 | 27 | # C extensions 28 | *.so 29 | 30 | # Distribution / packaging 31 | .Python 32 | build/ 33 | develop-eggs/ 34 | dist/ 35 | downloads/ 36 | eggs/ 37 | .eggs/ 38 | lib/ 39 | lib64/ 40 | parts/ 41 | sdist/ 42 | var/ 43 | wheels/ 44 | pip-wheel-metadata/ 45 | share/python-wheels/ 46 | *.egg-info/ 47 | .installed.cfg 48 | *.egg 49 | MANIFEST 50 | 51 | # PyInstaller 52 | # Usually these files are written by a python script from a template 53 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 54 | *.manifest 55 | *.spec 56 | 57 | # Installer logs 58 | pip-log.txt 59 | pip-delete-this-directory.txt 60 | 61 | # Unit test / coverage reports 62 | htmlcov/ 63 | .tox/ 64 | .nox/ 65 | .coverage 66 | .coverage.* 67 | .cache 68 | nosetests.xml 69 | coverage.xml 70 | *.cover 71 | *.py,cover 72 | .hypothesis/ 73 | .pytest_cache/ 74 | 75 | # Translations 76 | *.mo 77 | *.pot 78 | 79 | # Django stuff: 80 | *.log 81 | local_settings.py 82 | db.sqlite3 83 | db.sqlite3-journal 84 | 85 | # Flask stuff: 86 | instance/ 87 | .webassets-cache 88 | 89 | # Scrapy stuff: 90 | .scrapy 91 | 92 | # Sphinx documentation 93 | docs/_build/ 94 | 95 | # PyBuilder 96 | target/ 97 | 98 | # Jupyter Notebook 99 | .ipynb_checkpoints 100 | 101 | # IPython 102 | profile_default/ 103 | ipython_config.py 104 | 105 | # pyenv 106 | .python-version 107 | 108 | # pipenv 109 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 110 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 111 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 112 | # install all needed dependencies. 113 | #Pipfile.lock 114 | 115 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 116 | __pypackages__/ 117 | 118 | # Celery stuff 119 | celerybeat-schedule 120 | celerybeat.pid 121 | 122 | # SageMath parsed files 123 | *.sage.py 124 | 125 | # Environments 126 | .env 127 | .venv 128 | env/ 129 | venv/ 130 | ENV/ 131 | env.bak/ 132 | venv.bak/ 133 | 134 | # Spyder project settings 135 | .spyderproject 136 | .spyproject 137 | 138 | # Rope project settings 139 | .ropeproject 140 | 141 | # mkdocs documentation 142 | /site 143 | 144 | # mypy 145 | .mypy_cache/ 146 | .dmypy.json 147 | dmypy.json 148 | 149 | # Pyre type checker 150 | .pyre/ 151 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # Change Log 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/). 7 | 8 | ## 1.4.0 9 | 10 | ### Added 11 | 12 | 1. New suave_runner package containing a new python-based runner script 13 | 14 | 2. A new docker image without vnc, allowing it to be executed without the web interface 15 | 16 | 3. Move to gazebo harmonic 17 | 18 | ## 1.3.0 19 | 20 | ### Added 21 | 22 | 1. Added battery monitor node [PR #148] 23 | 24 | 2. Added recharge battery task [PR #148] 25 | 26 | 4. Added battery_constraint argument to mission [PR #155] 27 | 28 | 5. Added qa_comparison_operator to water_visibility in suave.owl 29 | 30 | 6. Documentation with sphinx 31 | 32 | 7. CI to build sphinx documentation 33 | 34 | 8. Added mission metrics node [PR #148] 35 | 36 | 9. Added a behavior tree as a managing subsystem for SUAVE and SUAVE extended to serve as a baseline for comparison [PR #160] 37 | 38 | 10. Added reaction time metrics to measure how long the managing system takes to react and adapt the system [PR #161] 39 | 40 | ### Changed 41 | 42 | 1. Ardusub, mavros, ros_gz, mc_mros_reasoner, mc_mdl_tomasys, mros_ontology verions 43 | 44 | 2. Removed unused code 45 | 46 | 3. Mission config default parameters 47 | 48 | 4. Refactored repository. Created new packages : suave_monitor, and suave_metrics. Moved suave_metacontrol under suave_managing [PR #158] 49 | 50 | 5. Removed suave_reasoner. The Analyze logic was moved to metacontrol. [PR #169] 51 | 52 | ### Fixed 53 | 54 | 1. README.md 55 | 56 | 2. Fix task bridge callbacks 57 | 58 | ## 1.2.1 [SEAMS Publication] 59 | 60 | ### Fixed 61 | 62 | 1. Minor bugs 63 | 64 | ## 1.2.0 [SEAMS Publication] 65 | 66 | Getting repository camera-ready 67 | 68 | ### Added 69 | 70 | 1. Added github action to build the docker images automatically, and push it to the repository registry 71 | 72 | ### Changed 73 | 74 | 1. Refactor mission and mission bridge to match the paper description 75 | * [Issue 117](https://github.com/kas-lab/suave/issues/117) 76 | 77 | 78 | 2. Upgraded mavros, mavros_wrapper, and mros versions 79 | 80 | 3. Refactor dockerfiles 81 | 82 | 4. Moved files within the repository 83 | 84 | 5. Updated README 85 | 86 | ### Fixed 87 | -------------------------------------------------------------------------------- /build_docker_images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | CURDIR=`pwd` 3 | docker build -t kasm-jammy:dev -f docker/dockerfile-kasm-core-jammy . 4 | docker build -t suave:dev --build-arg BASE_IMAGE=kasm-jammy:dev -f docker/dockerfile-suave . 5 | cd $CURDIR 6 | -------------------------------------------------------------------------------- /docker/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !src 3 | -------------------------------------------------------------------------------- /docker/.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behaviour, in case users don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files we want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.c text 7 | *.h text 8 | *.sah text 9 | *.suite text 10 | *.inc text 11 | *.js text 12 | *.json text 13 | 14 | # Declare files that will always have CRLF line endings on checkout. 15 | *.sln text eol=crlf 16 | 17 | # Denote all files that are truly binary and should not be modified. 18 | *.png binary 19 | *.jpg binary 20 | -------------------------------------------------------------------------------- /docker/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .idea 3 | *.iml 4 | *.log -------------------------------------------------------------------------------- /docker/LICENSE.md: -------------------------------------------------------------------------------- 1 | # Disclaimer 2 | 3 | This license applies only to the source code that is directly maintained in this git repository, it does not extend to dependencies from outside of this repository, to include other projects owned and/or maintained by Kasm Technologies. 4 | 5 | ## License 6 | 7 | Copyright 2022 Kasm Technologies Inc 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Workspaces Images 3 | This repository contains several example of desktop and application Workspaces images. 4 | Administrators may leverage these images directly or use them as a starting point for their own custom images. 5 | Each of these images is based off one of the [**Workspaces Core Images**](https://github.com/kasmtech/workspaces-core-images?utm_campaign=Github&utm_source=github) which contain the necessary wiring to work within the Kasm Workspaces platform. 6 | 7 | 8 | For more information about building custom images please review the [**How To Guide**](https://kasmweb.com/docs/latest/how_to/building_images.html?utm_campaign=Github&utm_source=github) 9 | 10 | The Kasm team publishes applications and desktop images for use inside the platform. More information, including source can be found in the [**Default Images List**](https://kasmweb.com/docs/latest/guide/custom_images.html?utm_campaign=Github&utm_source=github) 11 | 12 | 13 | # Manual Deployment 14 | 15 | To build the provided images: 16 | 17 | docker build -t egalberts/desktop-jammy-minimal:dev -f dockerfile-kasm-ubuntu-jammy-desktop-minimal . 18 | 19 | While these image are primarily built to run inside the Workspaces platform, they can also be executed manually. Please note that certain functionality, such as audio, uploads, downloads, and microphone pass-through are only available within the Kasm platform. 20 | 21 | ``` 22 | docker run --rm -it --shm-size=512m -p 6901:6901 -e VNC_PW=password egalberts/desktop-jammy-minimal:dev 23 | ``` 24 | 25 | The container is now accessible via a browser : `https://:6901` 26 | 27 | - **User** : `kasm_user` 28 | - **Password**: `password` 29 | 30 | 31 | # About Workspaces 32 | Kasm Workspaces is a docker container streaming platform that enables you to deliver browser-based access to desktops, applications, and web services. Kasm uses a modern DevOps approach for programmatic delivery of services via Containerized Desktop Infrastructure (CDI) technology to create on-demand, disposable, docker containers that are accessible via web browser. The rendering of the graphical-based containers is powered by the open-source project [**KasmVNC**](https://github.com/kasmtech/KasmVNC?utm_campaign=Github&utm_source=github) 33 | 34 | ![Screenshot][Kasm_Workflow] 35 | 36 | Kasm Workspaces was developed to meet the most demanding secure collaboration requirements that is highly scalable, customizable, and easy to maintain. Most importantly, Kasm provides a solution, rather than a service, so it is infinitely customizable to your unique requirements and includes a developer API so that it can be integrated with, rather than replace, your existing applications and workflows. Kasm can be deployed in the cloud (Public or Private), on-premise (Including Air-Gapped Networks), or in a hybrid configuration. 37 | 38 | # Live Demo 39 | A self-guided on-demand demo is available at [**kasmweb.com**](https://www.kasmweb.com/demo.html?utm_campaign=Github&utm_source=github) 40 | 41 | 42 | [logo]: https://cdn2.hubspot.net/hubfs/5856039/dockerhub/kasm_logo.png "Kasm Logo" 43 | [Kasm_Workflow]: https://cdn2.hubspot.net/hubfs/5856039/dockerhub/kasm_workflow_960.gif "Kasm Workflow" 44 | -------------------------------------------------------------------------------- /docker/follow_bluerov.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/docker/follow_bluerov.PNG -------------------------------------------------------------------------------- /docker/src/common/install/configure_firefox.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### every exit != 0 fails the script 3 | set -ex 4 | 5 | # Add this user pref so the tabs dont crash regularly 6 | cp /usr/lib/firefox/browser/defaults/profile/user.js /usr/lib/firefox/browser/defaults/profile/user.js.bak 7 | echo "user_pref(\"browser.startup.firstrunSkipsHomepage\", false);" >> /usr/lib/firefox/browser/defaults/profile/user.js 8 | echo "user_pref(\"browser.shell.skipDefaultBrowserCheckOnFirstRun\", true);" >> /usr/lib/firefox/browser/defaults/profile/user.js 9 | echo "user_pref(\"startup.homepage_welcome_url\", \"about:blank\");" >> /usr/lib/firefox/browser/defaults/profile/user.js 10 | echo "user_pref(\"datareporting.policy.firstRunURL\", \"\");" >> /usr/lib/firefox/browser/defaults/profile/user.js 11 | echo "user_pref(\"startup.homepage_welcome_url.additional\", \"\");" >> /usr/lib/firefox/browser/defaults/profile/user.js 12 | echo "user_pref(\"browser.shell.checkDefaultBrowser\", false);" >> /usr/lib/firefox/browser/defaults/profile/user.js 13 | echo "user_pref(\"app.update.auto\", false);" >> /usr/lib/firefox/browser/defaults/profile/user.js 14 | echo "user_pref(\"app.update.enabled\", false);" >> /usr/lib/firefox/browser/defaults/profile/user.js -------------------------------------------------------------------------------- /docker/src/common/install/kasm_vnc/kasmvnc.yaml: -------------------------------------------------------------------------------- 1 | network: 2 | ssl: 3 | pem_certificate: ${HOME}/.vnc/self.pem 4 | pem_key: ${HOME}/.vnc/self.pem 5 | -------------------------------------------------------------------------------- /docker/src/common/resources/images/bg_jammy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/docker/src/common/resources/images/bg_jammy.png -------------------------------------------------------------------------------- /docker/src/common/resources/images/bg_kasm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/docker/src/common/resources/images/bg_kasm.png -------------------------------------------------------------------------------- /docker/src/common/resources/images/icon_kasm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/docker/src/common/resources/images/icon_kasm.png -------------------------------------------------------------------------------- /docker/src/common/resources/images/icon_ubuntu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/docker/src/common/resources/images/icon_ubuntu.png -------------------------------------------------------------------------------- /docker/src/common/scripts/kasm_hook_scripts/kasm_post_run_root.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo "Executing kasm_post_run_root.sh" -------------------------------------------------------------------------------- /docker/src/common/scripts/kasm_hook_scripts/kasm_post_run_user.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo "Executing kasm_post_run_user.sh" -------------------------------------------------------------------------------- /docker/src/common/scripts/kasm_hook_scripts/kasm_pre_shutdown_root.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo "Executing kasm_pre_shutdown_root.sh" -------------------------------------------------------------------------------- /docker/src/common/scripts/kasm_hook_scripts/kasm_pre_shutdown_user.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | echo "Executing kasm_pre_shutdown_user.sh" 4 | PAUSE_ON_EXIT="false" 5 | for x in {1..10} 6 | do 7 | 8 | if [[ $(wmctrl -l | awk '{$3=""; $2=""; $1=""; print $0}' | grep -i chrome) ]] 9 | then 10 | PAUSE_ON_EXIT="true" 11 | echo "Closing Chrome Windows Attempt ($x)..." 12 | timeout 1 wmctrl -c chrome 13 | sleep .5 14 | fi 15 | 16 | done 17 | 18 | for x in {1..10} 19 | do 20 | 21 | if [[ $(wmctrl -l | awk '{$3=""; $2=""; $1=""; print $0}' | grep -i firefox) ]] 22 | then 23 | PAUSE_ON_EXIT="true" 24 | echo "Closing Firefox Windows Attempt ($x)..." 25 | timeout 1 wmctrl -c firefox 26 | sleep .5 27 | fi 28 | 29 | done 30 | 31 | if [ "${PAUSE_ON_EXIT}" == "true" ] ; 32 | then 33 | echo "Sleeping..." 34 | sleep 1 35 | fi 36 | 37 | echo "Done" 38 | -------------------------------------------------------------------------------- /docker/src/common/startup_scripts/generate_container_user: -------------------------------------------------------------------------------- 1 | # Attempt to set the username to the kasm username 2 | USERNAME=${KASM_USER:-default} 3 | # Make the username posix compliant 4 | USERNAME=$(echo "$USERNAME" | sed -r 's#[^a-zA-Z0-9\._\-]#_#g') 5 | if ! echo "$USERNAME" | grep -qP "^[a-zA-Z0-9_\.][a-zA-Z0-9_\-\.]*"; then 6 | USERNAME="default" 7 | fi 8 | export PS1="$USERNAME:\w\$ " -------------------------------------------------------------------------------- /docker/src/common/startup_scripts/kasm_default_profile.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | DEFAULT_PROFILE_HOME=/home/kasm-default-profile 4 | PROFILE_SYNC_DIR=/kasm_profile_sync 5 | 6 | 7 | function copy_default_profile_to_home { 8 | echo "Copying default profile to home directory" 9 | cp -rp $DEFAULT_PROFILE_HOME/. $HOME/ 10 | ls -la $HOME 11 | } 12 | 13 | function verify_profile_config { 14 | echo "Verifying Uploads/Downloads Configurations" 15 | 16 | mkdir -p $HOME/Uploads 17 | 18 | if [ -d "$HOME/Desktop/Uploads" ]; then 19 | echo "Uploads Desktop Symlink Exists" 20 | else 21 | echo "Creating Uploads Desktop Symlink" 22 | if [ -d "$HOME/Desktop "]; then 23 | echo "Desktop Exits" 24 | else 25 | echo "desktop didn't exist" 26 | mkdir $HOME/Desktop 27 | fi 28 | ln -sf $HOME/Uploads $HOME/Desktop/Uploads 29 | fi 30 | 31 | 32 | mkdir -p $HOME/Downloads 33 | 34 | if [ -d "$HOME/Desktop/Downloads" ]; then 35 | echo "Downloads Desktop Symlink Exists" 36 | else 37 | echo "Creating Download Desktop Symlink" 38 | ln -sf $HOME/Downloads $HOME/Desktop/Downloads 39 | fi 40 | 41 | 42 | if [ -d "$KASM_VNC_PATH/Downloads/Downloads" ]; then 43 | echo "Downloads RX Symlink Exists" 44 | else 45 | echo "Creating Downloads RX Symlink" 46 | ln -sf $HOME/Downloads $KASM_VNC_PATH/www/Downloads/Downloads 47 | fi 48 | 49 | ls -la $HOME/Desktop 50 | 51 | } 52 | 53 | if [ -f "$HOME/.bashrc" ]; then 54 | echo "Profile already exists. Will not copy default contents" 55 | else 56 | echo "Profile Sync Directory Does Not Exist. No Sync will occur" 57 | copy_default_profile_to_home 58 | fi 59 | 60 | verify_profile_config 61 | 62 | rm -rf $HOME/.config/pulse 63 | 64 | echo "Removing Default Profile Directory" 65 | rm -rf $DEFAULT_PROFILE_HOME/* 66 | 67 | # unknown option ==> call command 68 | echo -e "\n\n------------------ EXECUTE COMMAND ------------------" 69 | echo "Executing command: '$@'" 70 | exec "$@" 71 | -------------------------------------------------------------------------------- /docker/src/common/startup_scripts/set_user_permission.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### every exit != 0 fails the script 3 | set -e 4 | if [[ -n $DEBUG ]]; then 5 | verbose="-v" 6 | fi 7 | 8 | for var in "$@" 9 | do 10 | echo "fix permissions for: $var" 11 | find "$var"/ -name '*.sh' -exec chmod $verbose a+x {} + 12 | find "$var"/ -name '*.desktop' -exec chmod $verbose a+x {} + 13 | chgrp -R 0 "$var" && chmod -R $verbose a+rw "$var" && find "$var" -type d -exec chmod $verbose a+x {} + 14 | done -------------------------------------------------------------------------------- /docker/src/ubuntu/icewm/.icewm/menu: -------------------------------------------------------------------------------- 1 | prog xterm xterm xterm 2 | separator 3 | prog Firefox /usr/lib/firefox/browser/icons/mozicon128.png firefox 4 | prog Chromium /usr/share/pixmaps/chromium-browser.png /usr/bin/chromium-browser 5 | -------------------------------------------------------------------------------- /docker/src/ubuntu/icewm/.icewm/preferences: -------------------------------------------------------------------------------- 1 | WorkspaceNames=" 1 " 2 | TaskBarShowMailboxStatus = 0 3 | TaskBarShowWorkspaces = 0 4 | -------------------------------------------------------------------------------- /docker/src/ubuntu/icewm/.icewm/theme: -------------------------------------------------------------------------------- 1 | Theme=win95/default.theme 2 | -------------------------------------------------------------------------------- /docker/src/ubuntu/icewm/.icewm/toolbar: -------------------------------------------------------------------------------- 1 | prog xterm xterm xterm 2 | separator 3 | prog Firefox /usr/lib/firefox/browser/icons/mozicon128.png firefox 4 | prog "Google Chrome" /usr/share/pixmaps/chromium-browser.png /usr/bin/chromium-browser 5 | -------------------------------------------------------------------------------- /docker/src/ubuntu/icewm/wm_startup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### every exit != 0 fails the script 3 | set -e 4 | 5 | echo -e "\n------------------ startup of IceWM window manager ------------------" 6 | 7 | ### disable screensaver and power management 8 | xset -dpms & 9 | xset s noblank & 10 | xset s off & 11 | 12 | /usr/bin/icewm-session > $HOME/wm.log & 13 | sleep 1 14 | cat $HOME/wm.log -------------------------------------------------------------------------------- /docker/src/ubuntu/install/cursors/cursor-aero.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/docker/src/ubuntu/install/cursors/cursor-aero.tar.gz -------------------------------------------------------------------------------- /docker/src/ubuntu/install/cursors/cursor-bridge.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/docker/src/ubuntu/install/cursors/cursor-bridge.tar.gz -------------------------------------------------------------------------------- /docker/src/ubuntu/install/cursors/cursor-capitaine-r4.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/docker/src/ubuntu/install/cursors/cursor-capitaine-r4.tar.gz -------------------------------------------------------------------------------- /docker/src/ubuntu/install/cursors/install_cursors.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | echo "Installing Cursors" 5 | cd $INST_SCRIPTS/cursors 6 | 7 | tar -xzf cursor-aero.tar.gz -C /usr/share/icons/ 8 | tar -xzf cursor-bridge.tar.gz -C /usr/share/icons/ 9 | tar -xzf cursor-capitaine-r4.tar.gz -C /usr/share/icons/ 10 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/extra/kali.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | apt-get update 5 | 6 | apt-get install -y procps dbus-x11 7 | 8 | # Install the standard default kali tools 9 | # https://tools.kali.org/kali-metapackages 10 | # kali-linux-default use mlocate which breaks plocate 11 | apt-get remove -y plocate 12 | apt-get install -y kali-linux-default 13 | 14 | # Kali installs firefox by default. We need to update this install to utilze the system's certificate store 15 | # in order for web filtering to work 16 | 17 | apt-get install -y p11-kit-modules 18 | 19 | rm -rf /usr/lib/firefox-esr/libnssckbi.so 20 | ln /usr/lib/$(arch)-linux-gnu/pkcs11/p11-kit-trust.so /usr/lib/firefox-esr/libnssckbi.so 21 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/extra/noop.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash -------------------------------------------------------------------------------- /docker/src/ubuntu/install/extra/remnux.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -xe 3 | 4 | # Remnux installs firefox by default. We need to update this install to utilze the system's certificate store 5 | # in order for web filtering to work 6 | 7 | apt-get install -y p11-kit-modules 8 | 9 | rm /usr/lib/firefox/libnssckbi.so 10 | ln /usr/lib/x86_64-linux-gnu/pkcs11/p11-kit-trust.so /usr/lib/firefox/libnssckbi.so 11 | 12 | 13 | # Remnux includes bluetooth drivers which try to autoload causing pluse audio to fail 14 | sed -i "s/module-bluetooth-discover.so/module-bluetooth-discover.so.ignore/g" /etc/pulse/default.pa 15 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/fonts/install_custom_fonts.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### every exit != 0 fails the script 3 | set -e 4 | 5 | echo "Installing ttf-wqy-zenhei" 6 | apt install -y ttf-wqy-zenhei 7 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/kasm_upload_server/install_kasm_upload_server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | ARCH=$(arch | sed 's/aarch64/arm64/g' | sed 's/x86_64/amd64/g') 5 | mkdir $STARTUPDIR/upload_server 6 | wget --quiet https://kasmweb-build-artifacts.s3.amazonaws.com/kasm_upload_service/594ff9c24baa89477ef4fc937933e11529924cce/kasm_upload_service_${DISTRO/kali/ubuntu}_${ARCH}_develop.594ff9.tar.gz -O /tmp/kasm_upload_server.tar.gz 7 | tar -xvf /tmp/kasm_upload_server.tar.gz -C $STARTUPDIR/upload_server 8 | rm /tmp/kasm_upload_server.tar.gz 9 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/kasm_vnc/install_kasm_vnc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | install_libjpeg_turbo() { 5 | local libjpeg_deb=libjpeg-turbo.deb 6 | wget "https://kasmweb-build-artifacts.s3.amazonaws.com/kasmvnc/${COMMIT_ID}/output/${UBUNTU_CODENAME}/libjpeg-turbo_2.1.4_amd64.deb" -O "$libjpeg_deb" 7 | apt-get install -y "./$libjpeg_deb" 8 | rm "$libjpeg_deb" 9 | } 10 | 11 | echo "Install KasmVNC server" 12 | cd /tmp 13 | BUILD_ARCH=$(uname -p) 14 | UBUNTU_CODENAME="" 15 | COMMIT_ID="fdc4a63eda4b0bc77742cf1047434515fdf58d17" 16 | BRANCH="release" # just use 'release' for a release branch 17 | KASMVNC_VER="0.9.3.2" 18 | COMMIT_ID_SHORT=$(echo "${COMMIT_ID}" | cut -c1-6) 19 | 20 | # Naming scheme is now different between an official release and feature branch 21 | KASM_VER_NAME_PART="${KASMVNC_VER}_${BRANCH}_${COMMIT_ID_SHORT}" 22 | if [[ "${BRANCH}" == "release" ]] ; then 23 | KASM_VER_NAME_PART="${KASMVNC_VER}" 24 | fi 25 | 26 | UBUNTU_CODENAME=$(grep -Po -m 1 "(?<=_CODENAME=)\w+" /etc/os-release) 27 | if [[ "${BUILD_ARCH}" =~ ^aarch64$ ]] ; then 28 | BUILD_URL="https://kasmweb-build-artifacts.s3.amazonaws.com/kasmvnc/${COMMIT_ID}/kasmvncserver_${UBUNTU_CODENAME}_${KASM_VER_NAME_PART}_arm64.deb" 29 | elif [ "${UBUNTU_CODENAME}" == "bionic" ] ; then 30 | BUILD_URL="https://kasmweb-build-artifacts.s3.amazonaws.com/kasmvnc/${COMMIT_ID}/kasmvncserver_${UBUNTU_CODENAME}_${KASM_VER_NAME_PART}_libjpeg-turbo-latest_amd64.deb" 31 | else 32 | BUILD_URL="https://kasmweb-build-artifacts.s3.amazonaws.com/kasmvnc/${COMMIT_ID}/kasmvncserver_${UBUNTU_CODENAME}_${KASM_VER_NAME_PART}_amd64.deb" 33 | fi 34 | 35 | wget "${BUILD_URL}" -O kasmvncserver.deb 36 | 37 | apt-get update 38 | apt-get install -y gettext ssl-cert libxfont2 39 | dpkg -i /tmp/kasmvncserver.deb 40 | apt-get -yf install 41 | rm -f /tmp/kasmvncserver.deb 42 | 43 | #mkdir $KASM_VNC_PATH/certs 44 | mkdir -p $KASM_VNC_PATH/www/Downloads 45 | chown -R 0:0 $KASM_VNC_PATH 46 | chmod -R og-w $KASM_VNC_PATH 47 | #chown -R 1000:0 $KASM_VNC_PATH/certs 48 | chown -R 1000:0 $KASM_VNC_PATH/www/Downloads 49 | ln -s $KASM_VNC_PATH/www/index.html $KASM_VNC_PATH/www/vnc.html 50 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/maximize_script/maximize_window.sh: -------------------------------------------------------------------------------- 1 | # MAXIMIZE and MAXIMIZE_NAME are exported by the calling script 2 | # This script will check against the container OS to do the right thing. 3 | enable_x=0 4 | 5 | maximize_window(){ 6 | set +e 7 | if [[ ${MAXIMIZE} == 'true' ]] ; then 8 | if [[ $- =~ x ]] ; 9 | then 10 | set +x 11 | enable_x=1 12 | fi 13 | while true; do 14 | end=$((SECONDS+60)) 15 | while [ $SECONDS -lt $end ]; do 16 | windows=$(wmctrl -l) 17 | if [[ "$windows" =~ "${MAXIMIZE_NAME}" ]]; 18 | then 19 | wmctrl -r "${MAXIMIZE_NAME}" -b add,maximized_vert,maximized_horz 20 | break; 21 | fi 22 | sleep 1 23 | done 24 | sleep 10 25 | done 26 | if [[ ${enable_x} -eq 1 ]]; 27 | then 28 | set -x 29 | fi 30 | fi 31 | set -e 32 | } 33 | 34 | maximize_window -------------------------------------------------------------------------------- /docker/src/ubuntu/install/nvidia/10_nvidia.json: -------------------------------------------------------------------------------- 1 | { 2 | "file_format_version" : "1.0.0", 3 | "ICD" : { 4 | "library_path" : "libEGL_nvidia.so.0" 5 | } 6 | } 7 | 8 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/squid/resources/SN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/docker/src/ubuntu/install/squid/resources/SN.png -------------------------------------------------------------------------------- /docker/src/ubuntu/install/squid/resources/error_message/access_denied.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Access Denied 5 | 12 | 13 |
14 |

ACCESS DENIED

15 |

The requested URL has been rejected due to administrator policies

16 |
17 |
18 | 19 |
20 |

URL:

21 |

Domain:

22 |

Category:

23 | 24 |
25 |
26 |
27 | 28 | 29 |
30 | 31 |
32 |
33 | 34 |
35 | 36 | 65 | 66 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/squid/resources/squid.conf: -------------------------------------------------------------------------------- 1 | # How many instances of our filter to we want running 2 | redirect_children 5 3 | 4 | on_unsupported_protocol tunnel all 5 | 6 | acl blocked_websites dstdomain "/etc/squid/blocked.acl" 7 | http_access deny blocked_websites 8 | 9 | acl ssl_bypass_domains ssl::server_name "/etc/squid/ssl_bump_bypass_domains.conf" 10 | acl ssl_bypass_ips dst "/etc/squid/ssl_bump_bypass_ips.conf" 11 | 12 | deny_info ERR_ACCESS_DENIED blocked_websites 13 | acl step1 at_step SslBump1 14 | ssl_bump peek step1 15 | ssl_bump splice ssl_bypass_domains 16 | ssl_bump splice ssl_bypass_ips 17 | ssl_bump bump all 18 | 19 | acl CONNECT method CONNECT 20 | 21 | # The following two lines are an example of how we can leaverage squid to block ports, there can be as 22 | # many acl statements adding ports to Safe_ports as are needed. 23 | #acl Safe_ports port 443 # https 24 | #http_access deny !Safe_ports 25 | 26 | # Users need to connect to non 443 ports for https traffic. We comment out the standard deny here. 27 | #acl SSL_ports port 443 28 | #http_access deny CONNECT !SSL_ports 29 | 30 | http_access allow localhost manager 31 | http_access deny manager 32 | http_access allow localhost 33 | http_access deny all 34 | 35 | #http_port 3128 36 | http_port 3128 ssl-bump cert=/usr/local/squid/etc/ssl_cert/squid.pem generate-host-certificates=on dynamic_cert_mem_cache_size=4MB 37 | sslcrtd_program /usr/local/squid/libexec/security_file_certgen -s /usr/local/squid/var/logs/ssl_db -M 4MB 38 | 39 | coredump_dir /var/spool/squid 40 | 41 | refresh_pattern ^ftp: 1440 20% 10080 42 | refresh_pattern ^gopher: 1440 0% 1440 43 | refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 44 | refresh_pattern (Release|Packages(.gz)*)$ 0 20% 2880 45 | refresh_pattern . 0 20% 4320 46 | 47 | forwarded_for delete 48 | via off 49 | 50 | url_rewrite_program /bin/bash -c "/etc/squid/kasm_squid_adapter" 51 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/squid/resources/ssl_bump_bypass_domains.conf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/docker/src/ubuntu/install/squid/resources/ssl_bump_bypass_domains.conf -------------------------------------------------------------------------------- /docker/src/ubuntu/install/squid/resources/ssl_bump_bypass_ips.conf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/docker/src/ubuntu/install/squid/resources/ssl_bump_bypass_ips.conf -------------------------------------------------------------------------------- /docker/src/ubuntu/install/squid/resources/start_squid.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | IP=$(ip route get 1.1.1.1 | grep -oP "src \\K\\S+") 4 | 5 | mkdir /tmp/working_certs 6 | cd /tmp/working_certs 7 | 8 | if [ -f /etc/centos-release ]; then 9 | DISTRO=centos 10 | elif [ -f /etc/oracle-release ]; then 11 | DISTRO=oracle7 12 | elif [ -f /usr/bin/zypper ]; then 13 | DISTRO=opensuse 14 | fi 15 | 16 | if [[ "${DISTRO}" == @(centos|oracle7) ]]; then 17 | CERT_FILE=/etc/pki/ca-trust/source/anchors/squid.crt 18 | elif [ "${DISTRO}" == "opensuse" ]; then 19 | CERT_FILE=/usr/share/pki/trust/anchors/squid.crt 20 | else 21 | CERT_FILE=/usr/local/share/ca-certificates/squid.crt 22 | fi 23 | CERT_NAME="Squid Root CA" 24 | openssl req -new -newkey rsa:2048 -sha256 -days 3650 -nodes -x509 -extensions v3_ca -subj "/C=US/ST=CA/O=Kasm Technologies/CN=kasm.localhost.net" -keyout myCA.pem -out myCA.pem 25 | openssl x509 -in myCA.pem -outform DER -out myCA.der 26 | openssl x509 -in myCA.pem -outform DER -out myCA.der 27 | cp myCA.pem ${CERT_FILE} 28 | cp myCA.pem /usr/local/squid/etc/ssl_cert/squid.pem 29 | if [[ "${DISTRO}" == @(centos|oracle7) ]]; then 30 | update-ca-trust 31 | else 32 | update-ca-certificates 33 | fi 34 | 35 | cd $HOME 36 | rm -rf /tmp/working_certs 37 | 38 | for certDB in $(find / -name "cert9.db") 39 | do 40 | certdir=$(dirname ${certDB}); 41 | echo "Updating $certdir" 42 | certutil -A -n "${CERT_NAME}" -t "TCu,," -i ${CERT_FILE} -d sql:${certdir} 43 | chown -R 1000:1000 ${certdir} 44 | done 45 | 46 | export MEMCACHE_PASSWORD="$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 )" 47 | echo $MEMCACHE_PASSWORD | saslpasswd2 -a memcached -c -f /etc/sasl2/memcached-sasldb2 kasm 48 | if [[ "${DISTRO}" == @(centos|oracle7|opensuse) ]]; then 49 | MEMCACHE_USER=memcached 50 | else 51 | MEMCACHE_USER=memcache 52 | fi 53 | chown $MEMCACHE_USER:$MEMCACHE_USER /etc/sasl2/memcached-sasldb2 54 | 55 | 56 | if [[ "${DISTRO}" == @(centos|oracle7) ]]; then 57 | /usr/bin/memcached -u $MEMCACHE_USER & 58 | elif [ "${DISTRO}" == "opensuse" ]; then 59 | /usr/sbin/memcached -u $MEMCACHE_USER & 60 | else 61 | /etc/init.d/memcached start 62 | fi 63 | /etc/squid/kasm_squid_adapter --load-cache 64 | /usr/local/squid/sbin/squid -f /etc/squid/squid.conf 65 | 66 | echo "Done!" 67 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/suave/install_suave.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | source /opt/ros/humble/setup.bash 5 | cd ~/suave_ws/ 6 | colcon build --symlink-install 7 | echo 'source ~/suave_ws/install/setup.bash' >> ~/.bashrc 8 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/suave/install_suave_deps.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | source /opt/ros/humble/setup.bash 5 | cd ~/suave_ws/ 6 | 7 | sudo rosdep init 8 | rosdep update 9 | 10 | rosdep install --from-paths src --ignore-src -r -y 11 | 12 | sudo apt-get install -y python3-dev python3-opencv python3-wxgtk4.0 python3-pip python3-matplotlib python3-lxml python3-pygame 13 | pip3 install PyYAML mavproxy --user 14 | echo 'export PATH="$PATH:$HOME/.local/bin"' >> ~/.bashrc 15 | 16 | cd ~/suave_ws/src/mavros/mavros/scripts 17 | sudo ./install_geographiclib_datasets.sh 18 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/terminal/custom_startup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | START_COMMAND="xfce4-terminal" 4 | PGREP="xfce4-terminal " 5 | export MAXIMIZE="true" 6 | export MAXIMIZE_NAME="Terminal" 7 | MAXIMIZE_SCRIPT=$STARTUPDIR/maximize_window.sh 8 | DEFAULT_ARGS="--hide-borders --hide-menubar --zoom=-1 --hide-scrollbar" 9 | ARGS=${APP_ARGS:-$DEFAULT_ARGS} 10 | 11 | options=$(getopt -o gau: -l go,assign,url: -n "$0" -- "$@") || exit 12 | eval set -- "$options" 13 | 14 | while [[ $1 != -- ]]; do 15 | case $1 in 16 | -g|--go) GO='true'; shift 1;; 17 | -a|--assign) ASSIGN='true'; shift 1;; 18 | -u|--url) OPT_URL=$2; shift 2;; 19 | *) echo "bad option: $1" >&2; exit 1;; 20 | esac 21 | done 22 | shift 23 | 24 | # Process non-option arguments. 25 | for arg; do 26 | echo "arg! $arg" 27 | done 28 | 29 | FORCE=$2 30 | 31 | kasm_exec() { 32 | if [ -n "$OPT_URL" ] ; then 33 | URL=$OPT_URL 34 | elif [ -n "$1" ] ; then 35 | URL=$1 36 | fi 37 | 38 | # Since we are execing into a container that already has the browser running from startup, 39 | # when we don't have a URL to open we want to do nothing. Otherwise a second browser instance would open. 40 | if [ -n "$URL" ] ; then 41 | /usr/bin/filter_ready 42 | /usr/bin/desktop_ready 43 | bash ${MAXIMIZE_SCRIPT} & 44 | $START_COMMAND $ARGS $OPT_URL 45 | else 46 | echo "No URL specified for exec command. Doing nothing." 47 | fi 48 | } 49 | 50 | kasm_startup() { 51 | if [ -n "$KASM_URL" ] ; then 52 | URL=$KASM_URL 53 | elif [ -z "$URL" ] ; then 54 | URL=$LAUNCH_URL 55 | fi 56 | 57 | if [ -z "$DISABLE_CUSTOM_STARTUP" ] || [ -n "$FORCE" ] ; then 58 | 59 | echo "Entering process startup loop" 60 | set +x 61 | while true 62 | do 63 | if ! pgrep -x $PGREP > /dev/null 64 | then 65 | /usr/bin/filter_ready 66 | /usr/bin/desktop_ready 67 | set +e 68 | bash ${MAXIMIZE_SCRIPT} & 69 | cd $HOME 70 | $START_COMMAND $ARGS $URL 71 | set -e 72 | fi 73 | sleep 1 74 | done 75 | set -x 76 | 77 | fi 78 | 79 | } 80 | 81 | if [ -n "$GO" ] || [ -n "$ASSIGN" ] ; then 82 | kasm_exec 83 | else 84 | kasm_startup 85 | fi 86 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/tools/install_tools.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | echo "Install some common tools for further installation" 5 | apt-get update 6 | # Update tzdata noninteractive (otherwise our script is hung on user input later). 7 | DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata 8 | apt-get install -y vim wget locales wmctrl software-properties-common mesa-utils 9 | apt-get clean -y 10 | 11 | echo "generate locales für en_US.UTF-8" 12 | locale-gen en_US.UTF-8 13 | 14 | add-apt-repository ppa:kisak/kisak-mesa 15 | apt full-upgrade -y 16 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/tools/install_tools_deluxe.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | apt-get update 4 | apt-get install -y git tmux 5 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/unison/install_unison.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | apt-get update 5 | apt-get install -y unison 6 | 7 | # FIXME move unison home dir out of profile 8 | 9 | mkdir -p /etc/unison/ 10 | chown 1000:1000 /etc/unison/ 11 | 12 | # FIXME Find and test Trash and other dirs 13 | # FIXME Test Browser only 14 | cat >/etc/unison/kasm-profile.prf <&2; exit 1;; 20 | esac 21 | done 22 | shift 23 | 24 | # Process non-option arguments. 25 | for arg; do 26 | echo "arg! $arg" 27 | done 28 | 29 | FORCE=$2 30 | 31 | kasm_exec() { 32 | if [ -n "$OPT_URL" ] ; then 33 | URL=$OPT_URL 34 | elif [ -n "$1" ] ; then 35 | URL=$1 36 | fi 37 | 38 | # Since we are execing into a container that already has the browser running from startup, 39 | # when we don't have a URL to open we want to do nothing. Otherwise a second browser instance would open. 40 | if [ -n "$URL" ] ; then 41 | /usr/bin/filter_ready 42 | /usr/bin/desktop_ready 43 | bash ${MAXIMIZE_SCRIPT} & 44 | $START_COMMAND $ARGS $OPT_URL 45 | else 46 | echo "No URL specified for exec command. Doing nothing." 47 | fi 48 | } 49 | 50 | kasm_startup() { 51 | if [ -n "$KASM_URL" ] ; then 52 | URL=$KASM_URL 53 | elif [ -z "$URL" ] ; then 54 | URL=$LAUNCH_URL 55 | fi 56 | 57 | if [ -z "$DISABLE_CUSTOM_STARTUP" ] || [ -n "$FORCE" ] ; then 58 | 59 | echo "Entering process startup loop" 60 | set +x 61 | while true 62 | do 63 | if ! pgrep -x $PGREP > /dev/null 64 | then 65 | /usr/bin/filter_ready 66 | /usr/bin/desktop_ready 67 | set +e 68 | bash ${MAXIMIZE_SCRIPT} & 69 | $START_COMMAND $ARGS $URL 70 | set -e 71 | fi 72 | sleep 1 73 | done 74 | set -x 75 | 76 | fi 77 | 78 | } 79 | 80 | if [ -n "$GO" ] || [ -n "$ASSIGN" ] ; then 81 | kasm_exec 82 | else 83 | kasm_startup 84 | fi 85 | -------------------------------------------------------------------------------- /docker/src/ubuntu/install/vs_code/install_vs_code.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | ARCH=$(arch | sed 's/aarch64/arm64/g' | sed 's/x86_64/x64/g') 4 | wget -q https://update.code.visualstudio.com/latest/linux-deb-${ARCH}/stable -O vs_code.deb 5 | apt-get update 6 | apt-get install -y ./vs_code.deb 7 | mkdir -p /usr/share/icons/hicolor/apps 8 | wget -O /usr/share/icons/hicolor/apps/vscode.svg https://kasm-static-content.s3.amazonaws.com/icons/vscode.svg 9 | sed -i '/Icon=/c\Icon=/usr/share/icons/hicolor/apps/vscode.svg' /usr/share/applications/code.desktop 10 | sed -i 's#/usr/share/code/code#/usr/share/code/code --no-sandbox##' /usr/share/applications/code.desktop 11 | cp /usr/share/applications/code.desktop $HOME/Desktop 12 | chmod +x $HOME/Desktop/code.desktop 13 | chown 1000:1000 $HOME/Desktop/code.desktop 14 | rm vs_code.deb 15 | 16 | # Conveniences for python development 17 | apt-get update 18 | apt-get install -y python3-setuptools \ 19 | python3-venv \ 20 | python3-virtualenv 21 | 22 | # Cleanup 23 | apt-get autoclean 24 | rm -rf \ 25 | /var/lib/apt/lists/* \ 26 | /var/tmp/* \ 27 | /tmp/* 28 | -------------------------------------------------------------------------------- /docker/src/ubuntu/xfce/.config/xfce4/xfconf/single-application-xfce-perchannel-xml/xfce4-desktop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /docker/src/ubuntu/xfce/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /docker/src/ubuntu/xfce/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /docker/src/ubuntu/xfce/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-session.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /docker/src/ubuntu/xfce/.config/xfce4/xfconf/xfce-perchannel-xml/xsettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/source/_templates/autosummary/class.rst: -------------------------------------------------------------------------------- 1 | {{ objname | escape | underline}} 2 | 3 | .. currentmodule:: {{ module }} 4 | 5 | .. autoclass:: {{ objname }} 6 | 7 | {% block methods %} 8 | 9 | {% for item in methods %} 10 | {%- if item not in inherited_members %} 11 | .. automethod:: {{ item }} 12 | {%- endif %} 13 | {%- endfor %} 14 | 15 | {% if methods %} 16 | .. rubric:: {{ _('Methods') }} 17 | 18 | .. autosummary:: 19 | {% for item in methods %} 20 | {%- if item not in inherited_members %} 21 | ~{{ name }}.{{ item }} 22 | {%- endif %} 23 | {%- endfor %} 24 | {% endif %} 25 | {% endblock %} 26 | 27 | {% block attributes %} 28 | {% if attributes %} 29 | .. rubric:: {{ _('Attributes') }} 30 | 31 | .. autosummary:: 32 | {% for item in attributes %} 33 | {%- if item not in inherited_members %} 34 | ~{{ name }}.{{ item }} 35 | {%- endif %} 36 | {%- endfor %} 37 | {% endif %} 38 | {% endblock %} 39 | -------------------------------------------------------------------------------- /docs/source/_templates/autosummary/module.rst: -------------------------------------------------------------------------------- 1 | {{ fullname | escape | underline}} 2 | 3 | .. automodule:: {{ fullname }} 4 | 5 | {% block attributes %} 6 | {% if attributes %} 7 | .. rubric:: Module Attributes 8 | 9 | .. autosummary:: 10 | :toctree: 11 | {% for item in attributes %} 12 | {{ item }} 13 | {%- endfor %} 14 | {% endif %} 15 | {% endblock %} 16 | 17 | {% block functions %} 18 | {% if functions %} 19 | .. rubric:: {{ _('Functions') }} 20 | 21 | .. autosummary:: 22 | :toctree: 23 | {% for item in functions %} 24 | {{ item }} 25 | {%- endfor %} 26 | {% endif %} 27 | {% endblock %} 28 | 29 | {% block classes %} 30 | {% if classes %} 31 | .. rubric:: {{ _('Classes') }} 32 | 33 | .. autosummary:: 34 | :toctree: 35 | {% for item in classes %} 36 | {{ item }} 37 | {%- endfor %} 38 | {% endif %} 39 | {% endblock %} 40 | 41 | {% block exceptions %} 42 | {% if exceptions %} 43 | .. rubric:: {{ _('Exceptions') }} 44 | 45 | .. autosummary:: 46 | :toctree: 47 | {% for item in exceptions %} 48 | {{ item }} 49 | {%- endfor %} 50 | {% endif %} 51 | {% endblock %} 52 | 53 | {% block modules %} 54 | {% if modules %} 55 | .. rubric:: Modules 56 | 57 | .. autosummary:: 58 | :toctree: 59 | :recursive: 60 | {% for item in modules %} 61 | {{ item }} 62 | {%- endfor %} 63 | {% endif %} 64 | {% endblock %} 65 | -------------------------------------------------------------------------------- /docs/source/api.rst: -------------------------------------------------------------------------------- 1 | API 2 | ===== 3 | 4 | .. autosummary:: 5 | :toctree: _autosummary 6 | :recursive: 7 | 8 | suave.bluerov_gazebo 9 | suave.follow_pipeline_lc 10 | suave.pipeline_detection 11 | suave.pipeline_detection_wv 12 | suave.recover_thrusters_lc 13 | suave.spiral_search_lc 14 | suave.task_bridge 15 | suave.task_bridge_none 16 | suave_monitor.thruster_monitor 17 | suave_monitor.water_visibility_observer 18 | 19 | .. teste 20 | .. ------ 21 | .. 22 | .. .. automodule:: suave.bluerov_gazebo 23 | .. :members: 24 | -------------------------------------------------------------------------------- /docs/source/citing.md: -------------------------------------------------------------------------------- 1 | # Citation 2 | 3 | If you find this repository useful, please consider citing: 4 | 5 | ``` 6 | @INPROCEEDINGS{10173938, 7 | author={Silva, Gustavo Rezende and Päßler, Juliane and Zwanepol, Jeroen and Alberts, Elvin and Tarifa, S. Lizeth Tapia and Gerostathopoulos, Ilias and Johnsen, Einar Broch and Corbato, Carlos Hernández}, 8 | booktitle={2023 IEEE/ACM 18th Symposium on Software Engineering for Adaptive and Self-Managing Systems (SEAMS)}, 9 | title={SUAVE: An Exemplar for Self-Adaptive Underwater Vehicles}, 10 | year={2023}, 11 | volume={}, 12 | number={}, 13 | pages={181-187}, 14 | doi={10.1109/SEAMS59076.2023.00031}} 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # For the full list of built-in configuration values, see the documentation: 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 5 | 6 | # -- Project information ----------------------------------------------------- 7 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 8 | 9 | project = 'SUAVE' 10 | copyright = '2023, Gustavo Rezende, Juliane Päßler, Jeroen Zwanepol, Elvin Alberts, Lizeth Tarifa, Ilias Gerostathopoulos, Einar Johnsen, Carlos Hernández' 11 | author = 'Gustavo Rezende, Juliane Päßler, Jeroen Zwanepol, Elvin Alberts, Lizeth Tarifa, Ilias Gerostathopoulos, Einar Johnsen, Carlos Hernández' 12 | release = 'v1.2.1' 13 | 14 | # -- General configuration --------------------------------------------------- 15 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 16 | 17 | extensions = [ 18 | "sphinx.ext.duration", 19 | "sphinx.ext.doctest", 20 | "sphinx.ext.autodoc", 21 | "sphinx.ext.autosummary", 22 | "sphinx.ext.intersphinx", 23 | "myst_parser", 24 | ] 25 | autosummary_generate = True 26 | 27 | intersphinx_mapping = { 28 | "rtd": ("https://docs.readthedocs.io/en/stable/", None), 29 | "python": ("https://docs.python.org/3/", None), 30 | "sphinx": ("https://www.sphinx-doc.org/en/master/", None), 31 | } 32 | intersphinx_disabled_domains = ["std"] 33 | 34 | templates_path = ["_templates"] 35 | 36 | # -- Options for EPUB output 37 | epub_show_urls = "footnote" 38 | 39 | # List of patterns, relative to source directory, that match files and 40 | # directories to ignore when looking for source files. 41 | # This pattern also affects html_static_path and html_extra_path. 42 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 43 | 44 | # -- Options for HTML output ------------------------------------------------- 45 | 46 | # The theme to use for HTML and HTML Help pages. See the documentation for 47 | # a list of builtin themes. 48 | # 49 | html_theme = "sphinx_rtd_theme" 50 | 51 | # Add any paths that contain custom static files (such as style sheets) here, 52 | # relative to this directory. They are copied after the builtin static files, 53 | # so a file named "default.css" will overwrite the builtin "default.css". 54 | html_static_path = ["_static"] 55 | 56 | source_suffix = { 57 | '.rst': 'restructuredtext', 58 | '.txt': 'markdown', 59 | '.md': 'markdown', 60 | } 61 | myst_heading_anchors = 3 62 | -------------------------------------------------------------------------------- /docs/source/docker.md: -------------------------------------------------------------------------------- 1 | # Use SUAVE with Docker 2 | 3 | You can pull and run the exemplar as a Docker container using the following command. Keep in mind you need to have [Docker](https://docs.docker.com/get-docker/) installed on your computer and running. 4 | 5 | In a terminal on your computer run: 6 | ```Bash 7 | docker run -it --shm-size=512m -p 6901:6901 -e VNC_PW=password --security-opt seccomp=unconfined ghcr.io/kas-lab/suave:main 8 | ``` 9 | 10 | Optionally you can add the parameter `-v :/home/kasm-user/suave/results` to save the results into your computer, replace `` with the absolute path of where you want the data to be saved in your computer, e.g: 11 | 12 | ```Bash 13 | docker run -it --shm-size=512m -v $HOME/suave_results:/home/kasm-user/suave/results -p 6901:6901 -e VNC_PW=password --security-opt seccomp=unconfined ghcr.io/kas-lab/suave:main 14 | ``` 15 | 16 | **SEAMS2023:** To use the docker image used in the SEAMS2023 paper, replace `ghcr.io/kas-lab/suave:main` with `ghcr.io/kas-lab/suave:seams2023`. 17 | 18 | Once the container is up and running, you can interface with it through your web browser. The container will be hosted locally at the port specified, in this case 6901. So in your browser, go to 19 | `http://localhost:6901`. 20 | 21 | A dialog will request a username and password, these are shown below, with the password being specifiable in the run command. 22 | 23 | - **User** : `kasm_user` 24 | - **Password**: `password` 25 | 26 | 27 | 28 | ## Headless docker image 29 | 30 | We also provide a docker image without VCN/Web interface, so you can just run the experiments directly from your terminal without needing to log in into the web interface. 31 | 32 | Pull image: 33 | ```Bash 34 | docker pull ghcr.io/kas-lab/suave-headless:main 35 | ``` 36 | 37 | Run image (without gpu): 38 | ```Bash 39 | docker run -it --rm --name suave_runner -e DISPLAY=$DISPLAY -e QT_X11_NO_MITSHM=1 -v /tmp/.X11-unix:/tmp/.X11-unix -v /etc/localtime:/etc/localtime:ro -v $HOME/suave_ws/src/suave:/home/ubuntu-user/suave_ws/src/suave suave-headless 40 | ``` 41 | 42 | Run image (with nvidia)(don't forget to install nvidia docker toolkit)[https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html]: 43 | ```Bash 44 | docker run -it --rm --gpus all --runtime=nvidia --name suave_runner -e DISPLAY=$DISPLAY -e QT_X11_NO_MITSHM=1 -e NVIDIA_VISIBLE_DEVICES=all -e NVIDIA_DRIVER_CAPABILITIES=all -v /dev/dri:/dev/dri -v /tmp/.X11-unix:/tmp/.X11-unix -v /etc/localtime:/etc/localtime:ro -v $HOME/suave_ws/src/suave:/home/ubuntu-user/suave_ws/src/suave suave-headless 45 | ``` 46 | 47 | You can try by running: 48 | 49 | ```Bash 50 | ros2 run suave_runner suave_runner \ 51 | --ros-args \ 52 | -p gui:=False \ 53 | -p experiments:='[ 54 | "{\"experiment_launch\": \"ros2 launch suave_bt suave_bt.launch.py\", \ 55 | \"num_runs\": 2, \ 56 | \"adaptation_manager\": \"bt\", \ 57 | \"mission_name\": \"suave\"}" 58 | ]' 59 | ``` 60 | 61 | If you want the image to have acess to the host GUI run the following command before running the image: 62 | ```Bash 63 | xhost + 64 | ``` 65 | 66 | ## Build Docker images locally 67 | To build the docker images locally, run: 68 | 69 | ```Bash 70 | ./build_docker_images.sh 71 | ``` 72 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. SUAVE documentation master file, created by 2 | sphinx-quickstart on Mon Nov 20 11:30:50 2023. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to SUAVE's documentation! 7 | ================================= 8 | 9 | .. toctree:: 10 | Home 11 | installation 12 | docker 13 | run 14 | extend 15 | troubleshooting 16 | related 17 | citing 18 | api 19 | :maxdepth: 1 20 | 21 | Contribute 22 | ---------- 23 | 24 | - Issue Tracker: https://github.com/kas-lab/suave/issues 25 | - Source Code: https://github.com/kas-lab/suave/ 26 | 27 | Support 28 | ------- 29 | 30 | If you are having issues, please let us know by creating an issue in github. 31 | 32 | License 33 | ------- 34 | 35 | The project is licensed under the Apache 2.0 license 36 | 37 | Acknowledgments 38 | ---------------- 39 | .. raw:: html 40 | 41 | 42 | 43 | REMARO Logo 44 | 45 | 46 | 47 | This work is part of the Reliable AI for Marine Robotics (REMARO) Project. For more info, please visit: https://remaro.eu/ 48 | 49 | .. raw:: html 50 | 51 | 52 | 53 | EU Flag 54 | 55 | 56 | 57 | This project has received funding from the European Union's Horizon 2020 research and innovation programme under the Marie Skłodowska-Curie grant agreement No. 956200. 58 | -------------------------------------------------------------------------------- /docs/source/related.md: -------------------------------------------------------------------------------- 1 | # Related works 2 | 3 | [REMARO Summer School Delft 2022](https://github.com/remaro-network/tudelft_hackathon) - Underwater robotics hackathon 4 | -------------------------------------------------------------------------------- /docs/source/troubleshooting.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | 3 | List of known problems and their solutions. If you find new problems and find a solution for it, please consider contributing to this section. 4 | 5 | ## MAVROS and ArduSub integration problems: 6 | 7 | A common problem that occurs over time is that some packages are upgraded in Ubuntu 22.04 and the connection between MAVROS and ArduSub stops working. I don't know how to fix this issue long term, but a workaround is to update MAVROS and/or ArduSub and check if it works again. 8 | 9 | Before updating MAVROS and ArduSub upgrade your Ubuntu: 10 | 11 | ```Bash 12 | sudo apt update && sudo apt upgrade 13 | ``` 14 | 15 | **Update ArduSub:** 16 | 17 | Due to ArduSub usage of submodules, it is simpler to just remove the whole ardupilo repo and build it from scratch again. 18 | 19 | ```Bash 20 | rm -rf ~/ardupilot 21 | ``` 22 | 23 | To find the latest version of ArduSub go to the [ardupilot repo](https://github.com/ArduPilot/ardupilot) and look for the newest branch of ArduSub. At the time of this writing, the latest branch is [Sub-4.1](https://github.com/ArduPilot/ardupilot/commits/Sub-4.1) at commit [e9f46b9](https://github.com/ArduPilot/ardupilot/tree/e9f46b91cda16cf7a48eb9861fea13e452c5c08c). After you know the latest branch or commit you want to get, follow the [install ardusub](https://github.com/kas-lab/suave#install-ardusub) instructions replacing the commit in `git checkout e9f46b9` with the commit/branch you selected. 24 | 25 | **Update MAVROS:** 26 | To update MAVROS, you can either change its version in the [suave.rosinstall](https://github.com/kas-lab/suave/blob/8f0e47571fc6c7524139fcb7ef20d9157d73a3e6/suave.rosinstall#L9) file with the newest version of [mavros](https://github.com/mavlink/mavros), or simply change the version to ros2. Then you need to pull the repo: 27 | 28 | ```Bash 29 | cd ~/suave_ws/ 30 | vcs pull src 31 | ``` 32 | 33 | Alternatively, instead of updating the suave.rosinstall file, you can just update mavros manually: 34 | 35 | ```Bash 36 | cd ~/suave_ws/src/mavros 37 | git checkout ros2 38 | git pull 39 | ``` 40 | 41 | Don't forget to rebuild the suave workspace: 42 | ```Bash 43 | cd ~/suave_ws/ 44 | colcon build --symlink-install 45 | ``` 46 | -------------------------------------------------------------------------------- /runner/SEAMS2023_results_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MTYPE="time" 4 | GUI="false" 5 | 6 | MANAGER="none" 7 | ./runner.sh $GUI $MANAGER $MTYPE 20 8 | 9 | MANAGER="metacontrol" 10 | ./runner.sh $GUI $MANAGER $MTYPE 20 11 | 12 | MANAGER="random" 13 | ./runner.sh $GUI $MANAGER $MTYPE 20 -------------------------------------------------------------------------------- /runner/example_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MTYPE="time" 4 | GUI="true" 5 | MANAGER="metacontrol" 6 | 7 | ./runner.sh $GUI $MANAGER $MTYPE 1 8 | -------------------------------------------------------------------------------- /runner/scripts/launch_mission.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ~/.bashrc 3 | source ~/suave_ws/install/setup.bash 4 | 5 | if [ $# -lt 1 ]; then 6 | echo "usage: $0 adaptation_manager mission_type" 7 | echo example: 8 | echo " "$0 "[metacontrol | random | none | bt] [time | distance | extended]" 9 | exit 1 10 | fi 11 | 12 | MANAGER="" 13 | MTYPE="" 14 | 15 | if [ "$1" == "metacontrol" ] || [ "$1" == "random" ] || [[ "$1" == "none" ]] || [[ "$1" == "bt" ]]; 16 | then 17 | MANAGER=$1 18 | else 19 | echo "adaptation_manager invalid or missing" 20 | exit 1 21 | fi 22 | 23 | if [ "$2" == "time" ]; 24 | then 25 | MTYPE="time_constrained_mission" 26 | elif [ "$2" == "distance" ]; 27 | then 28 | MTYPE="const_dist_mission" 29 | elif [ "$2" == "extended" ]; 30 | then 31 | MTYPE="extended" 32 | else 33 | echo "mission_type invalid or missing" 34 | exit 1 35 | fi 36 | 37 | FILE=$3 38 | MCFILE=${FILE}"_mc_reasoning_time" 39 | 40 | if [ "$MANAGER" == "metacontrol" ] || [ "$MANAGER" == "random" ] || [[ "$MANAGER" == "none" ]]; 41 | then 42 | ros2 launch suave_missions mission.launch.py adaptation_manager:=$MANAGER mission_type:=$MTYPE result_filename:=$FILE mc_reasoning_time_filename:=$MCFILE 43 | elif [ "$MANAGER" == "bt" ]; 44 | then 45 | if [ "$MTYPE" == "extended" ]; 46 | then 47 | ros2 launch suave_bt suave_bt_extended.launch.py result_filename:=$3 48 | else 49 | ros2 launch suave_bt suave_bt.launch.py result_filename:=$3 50 | fi 51 | fi 52 | -------------------------------------------------------------------------------- /runner/scripts/launch_sim.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ~/.bashrc 3 | source ~/suave_ws/install/setup.bash 4 | if [ $# -lt 1 ]; then 5 | echo "usage: $0 gui" 6 | echo example: 7 | echo " "$0 "[true | false]" 8 | exit 1 9 | fi 10 | 11 | GUI="" 12 | 13 | if [ "$1" == "true" ] || [ "$1" == "false" ]; 14 | then 15 | GUI=$1 16 | else 17 | echo "gui argument invalid" 18 | exit 1 19 | fi 20 | 21 | ros2 launch suave simulation.launch.py x:=-17.0 y:=2.0 gui:=$GUI 22 | -------------------------------------------------------------------------------- /runner/scripts/start_ardusub.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -lt 1 ]; then 4 | echo "usage: $0 gui" 5 | echo example: 6 | echo " "$0 "[true | false]" 7 | exit 1 8 | fi 9 | 10 | GUI="" 11 | 12 | if [ "$1" == "true" ]; 13 | then 14 | GUI='--console' 15 | else 16 | if [ "$1" == "false" ]; 17 | then 18 | GUI='' 19 | else 20 | echo "gui argument invalid" 21 | exit 1 22 | fi 23 | fi 24 | 25 | cd /tmp 26 | sim_vehicle.py -L RATBeach -v ArduSub --model=JSON $GUI 27 | -------------------------------------------------------------------------------- /suave.repos: -------------------------------------------------------------------------------- 1 | repositories: 2 | bluerov2_ignition: 3 | type: git 4 | url: https://github.com/Rezenders/bluerov2_ignition.git 5 | version: 909f091 6 | mavros: 7 | type: git 8 | url: https://github.com/mavlink/mavros.git 9 | version: b0da849a06eb1a215b9205b92b8cf39c6d7cf88f 10 | mavros_wrapper: 11 | type: git 12 | url: https://github.com/remaro-network/mavros_wrapper.git 13 | version: 72b9743 14 | remaro_worlds: 15 | type: git 16 | url: https://github.com/remaro-network/remaro_worlds.git 17 | version: 0e50a98 18 | mc_mdl_tomasys: 19 | type: git 20 | url: https://github.com/meta-control/mc_mdl_tomasys.git 21 | version: ros2 22 | mros_ontology: 23 | type: git 24 | url: https://github.com/meta-control/mros_ontology.git 25 | version: main 26 | mc_mros_reasoner: 27 | type: git 28 | url: https://github.com/meta-control/mc_mros_reasoner.git 29 | version: master 30 | system_modes: 31 | type: git 32 | url: https://github.com/micro-ROS/system_modes 33 | version: 682ecb7 -------------------------------------------------------------------------------- /suave/config/suave_modes.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | f_generate_search_path: 3 | ros__parameters: 4 | type: system 5 | parts: 6 | f_generate_search_path_node 7 | modes: 8 | __DEFAULT__: 9 | f_generate_search_path_node: active.__DEFAULT__ 10 | fd_spiral_high: 11 | f_generate_search_path_node: active.fd_spiral_high 12 | fd_spiral_low: 13 | f_generate_search_path_node: active.fd_spiral_low 14 | fd_spiral_medium: 15 | f_generate_search_path_node: active.fd_spiral_medium 16 | fd_unground: 17 | f_generate_search_path_node: inactive 18 | 19 | f_generate_search_path_node: 20 | ros__parameters: 21 | type: node 22 | modes: 23 | __DEFAULT__: 24 | ros__parameters: 25 | spiral_altitude: 1.0 26 | fd_spiral_high: 27 | ros__parameters: 28 | spiral_altitude: 3.0 29 | fd_spiral_medium: 30 | ros__parameters: 31 | spiral_altitude: 2.0 32 | fd_spiral_low: 33 | ros__parameters: 34 | spiral_altitude: 1.0 35 | 36 | f_follow_pipeline: 37 | ros__parameters: 38 | type: system 39 | parts: 40 | f_follow_pipeline_node 41 | modes: 42 | __DEFAULT__: 43 | f_follow_pipeline_node: inactive 44 | fd_follow_pipeline: 45 | f_follow_pipeline_node: active.__DEFAULT__ 46 | fd_unground: 47 | f_follow_pipeline_node: inactive 48 | 49 | f_follow_pipeline_node: 50 | ros__parameters: 51 | type: node 52 | modes: 53 | __DEFAULT__: 54 | ros__parameters: 55 | random_param: 2.0 56 | 57 | f_maintain_motion: 58 | ros__parameters: 59 | type: system 60 | parts: 61 | f_maintain_motion_node 62 | modes: 63 | __DEFAULT__: 64 | f_maintain_motion_node: active.__DEFAULT__ 65 | fd_all_thrusters: 66 | f_maintain_motion_node: inactive 67 | fd_recover_thrusters: 68 | f_maintain_motion_node: active.__DEFAULT__ 69 | fd_unground: 70 | f_maintain_motion_node: inactive 71 | 72 | f_maintain_motion_node: 73 | ros__parameters: 74 | type: node 75 | modes: 76 | __DEFAULT__: 77 | ros__parameters: 78 | random_param: 2.0 79 | 80 | generate_recharge_path: 81 | ros__parameters: 82 | type: system 83 | parts: 84 | generate_recharge_path_node 85 | modes: 86 | __DEFAULT__: 87 | generate_recharge_path_node: inactive 88 | normal: 89 | generate_recharge_path_node: active.__DEFAULT__ 90 | inactive: 91 | generate_recharge_path_node: inactive 92 | fd_unground: 93 | generate_recharge_path_node: inactive 94 | 95 | generate_recharge_path_node: 96 | ros__parameters: 97 | type: node 98 | modes: 99 | __DEFAULT__: 100 | ros__parameters: 101 | random_param: 2.0 102 | -------------------------------------------------------------------------------- /suave/launch/system_modes.launch.py: -------------------------------------------------------------------------------- 1 | from ament_index_python.packages import get_package_share_directory 2 | 3 | from launch import LaunchDescription 4 | from launch_ros.actions import Node 5 | 6 | import os 7 | 8 | 9 | def generate_launch_description(): 10 | 11 | shm_model_path = os.path.join( 12 | get_package_share_directory('suave'), 13 | 'config', 14 | 'suave_modes.yaml') 15 | 16 | mode_manager_node = Node( 17 | package='system_modes', 18 | executable='mode_manager', 19 | parameters=[{'modelfile': shm_model_path}], 20 | ) 21 | 22 | return LaunchDescription([ 23 | mode_manager_node, 24 | ]) 25 | -------------------------------------------------------------------------------- /suave/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | suave 5 | 0.0.0 6 | TODO: Package description 7 | gus 8 | Apache-2.0 9 | 10 | ament_copyright 11 | ament_flake8 12 | ament_pep257 13 | python3-pytest 14 | 15 | mavros 16 | suave_msgs 17 | mavros_msgs 18 | mavros_wrapper 19 | ros_gz 20 | 21 | geometry_msgs 22 | 23 | 24 | ament_python 25 | 26 | 27 | -------------------------------------------------------------------------------- /suave/resource/suave: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave/resource/suave -------------------------------------------------------------------------------- /suave/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/suave 3 | [install] 4 | install_scripts=$base/lib/suave 5 | -------------------------------------------------------------------------------- /suave/setup.py: -------------------------------------------------------------------------------- 1 | from glob import glob 2 | 3 | import os 4 | from setuptools import setup 5 | 6 | package_name = 'suave' 7 | 8 | setup( 9 | name=package_name, 10 | version='0.0.0', 11 | packages=[package_name], 12 | data_files=[ 13 | ('share/ament_index/resource_index/packages', 14 | ['resource/' + package_name]), 15 | ('share/' + package_name, ['package.xml']), 16 | (os.path.join('share', package_name, 'launch'), 17 | glob('launch/*launch.[pxy][yma]*')), 18 | (os.path.join('share', package_name, 'config'), 19 | glob('config/*')) 20 | ], 21 | install_requires=['setuptools'], 22 | zip_safe=True, 23 | maintainer='gus', 24 | maintainer_email='g.rezendesilva@tudelft.nl', 25 | description='TODO: Package description', 26 | license='TODO: License declaration', 27 | # tests_require=['pytest'], 28 | entry_points={ 29 | 'console_scripts': [ 30 | 'pipeline_detection = suave.pipeline_node:main', 31 | 'pipeline_detection_wv = suave.pipeline_detection_wv:main', 32 | 'recharge_battery = suave.recharge_battery_lc:main', 33 | 'spiral_search = suave.spiral_search_lc:main', 34 | 'follow_pipeline = suave.follow_pipeline_lc:main', 35 | 'recover_thrusters = suave.recover_thrusters_lc:main', 36 | 'task_bridge_none = suave.task_bridge_none:main', 37 | ], 38 | }, 39 | ) 40 | -------------------------------------------------------------------------------- /suave/suave/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave/suave/__init__.py -------------------------------------------------------------------------------- /suave/suave/bluerov_gazebo.py: -------------------------------------------------------------------------------- 1 | from geometry_msgs.msg import Pose 2 | from mavros_wrapper.ardusub_wrapper import BlueROVArduSubWrapper 3 | 4 | 5 | class BlueROVGazebo(BlueROVArduSubWrapper): 6 | def __init__(self, node_name='bluerov_gz'): 7 | super().__init__(node_name) 8 | self.gz_to_local_pose_delta = None 9 | self.first_gz_pose = True 10 | self.initial_x = None 11 | self.initial_y = None 12 | 13 | self.gazebo_pos_sub = self.create_subscription( 14 | Pose, 'model/bluerov2/pose', self.gazebo_pos_cb, 10) 15 | 16 | # TODO: make this a ros param 17 | self.ground_depth_gz = -20 18 | self.altitude = 1.25 19 | 20 | def gazebo_pos_cb(self, msg): 21 | self.gazebo_pos = msg 22 | if self.first_gz_pose is True: 23 | self.first_gz_pose = False 24 | self.initial_x = msg.position.x 25 | self.initial_y = msg.position.y 26 | 27 | if self.local_pos_received and self.status.mode == 'GUIDED': 28 | self.gz_to_local_pose_delta = [ 29 | self.local_pos.pose.position.x - msg.position.x, 30 | self.local_pos.pose.position.y - msg.position.y, 31 | self.local_pos.pose.position.z - msg.position.z, 32 | ] 33 | self.destroy_subscription(self.gazebo_pos_sub) 34 | 35 | def convert_gz_to_local_pose(self, gz_pose): 36 | if self.gz_to_local_pose_delta is not None: 37 | local_pose = Pose() 38 | local_pose.position.x = \ 39 | gz_pose.position.x + self.gz_to_local_pose_delta[0] 40 | local_pose.position.y = \ 41 | gz_pose.position.y + self.gz_to_local_pose_delta[1] 42 | local_pose.position.z = \ 43 | gz_pose.position.z + self.gz_to_local_pose_delta[2] 44 | return local_pose 45 | else: 46 | return gz_pose 47 | 48 | def setpoint_position_gz(self, gz_pose, fixed_altitude=True): 49 | if self.gz_to_local_pose_delta is None: 50 | return None 51 | 52 | if fixed_altitude: 53 | gz_pose.position.z = self.ground_depth_gz + self.altitude 54 | 55 | local_pose = self.convert_gz_to_local_pose(gz_pose) 56 | return self.setpoint_position_local( 57 | x=local_pose.position.x, 58 | y=local_pose.position.y, 59 | z=local_pose.position.z) 60 | 61 | def setpoint_position_local( 62 | self, x=.0, y=.0, z=.0, rx=.0, ry=.0, rz=.0, rw=1.0, fixed_altitude=True): 63 | if fixed_altitude and self.gz_to_local_pose_delta is None: 64 | return None 65 | 66 | if fixed_altitude: 67 | z = self.ground_depth_gz + self.altitude \ 68 | + self.gz_to_local_pose_delta[2] 69 | return super().setpoint_position_local(x, y, z) 70 | -------------------------------------------------------------------------------- /suave/suave/pipeline_detection_wv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import rclpy 3 | from diagnostic_msgs.msg import DiagnosticArray 4 | from suave.pipeline_detection import PipelineDetection 5 | from rclpy.callback_groups import MutuallyExclusiveCallbackGroup 6 | from rclpy.executors import MultiThreadedExecutor 7 | 8 | 9 | class PipelineDetectionWV(PipelineDetection): 10 | def __init__(self): 11 | super().__init__() 12 | 13 | self.diagnostics_sub = self.create_subscription( 14 | DiagnosticArray, 15 | '/diagnostics', 16 | self.diagnostics_cb, 17 | 10, 18 | callback_group=MutuallyExclusiveCallbackGroup() 19 | ) 20 | 21 | self.water_visibility = None 22 | 23 | def diagnostics_cb(self, msg): 24 | for status in msg.status: 25 | if status.message == "QA status": 26 | for value in status.values: 27 | if value.key == "water_visibility": 28 | self.water_visibility = float(value.value) 29 | 30 | def compare_poses(self, bluerov_pose, pipe_pose): 31 | result = False 32 | if self.water_visibility is not None: 33 | result = super().compare_poses(bluerov_pose, pipe_pose) 34 | result = result and \ 35 | abs(bluerov_pose.position.z - pipe_pose.position.z) \ 36 | <= self.water_visibility 37 | return result 38 | 39 | 40 | def main(args=None): 41 | rclpy.init(args=args) 42 | try: 43 | executor = MultiThreadedExecutor() 44 | lc_node = PipelineDetectionWV() 45 | executor.add_node(lc_node) 46 | try: 47 | executor.spin() 48 | except (KeyboardInterrupt, rclpy.executors.ExternalShutdownException): 49 | executor.shutdown() 50 | lc_node.destroy_node() 51 | finally: 52 | executor.shutdown() 53 | lc_node.destroy_node() 54 | finally: 55 | rclpy.shutdown() 56 | -------------------------------------------------------------------------------- /suave/suave/task_bridge_none.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import rclpy 4 | 5 | from rclpy.executors import MultiThreadedExecutor 6 | from rclpy.callback_groups import MutuallyExclusiveCallbackGroup 7 | from suave.task_bridge import TaskBridge 8 | from system_modes_msgs.srv import ChangeMode 9 | 10 | 11 | class TaskBridgeNone(TaskBridge): 12 | def __init__(self): 13 | super().__init__() 14 | self.declare_parameter('f_generate_search_path_mode', 'fd_spiral_low') 15 | self.declare_parameter('f_follow_pipeline_mode', 'fd_follow_pipeline') 16 | 17 | self.client_cb_group = MutuallyExclusiveCallbackGroup() 18 | self.generate_path_sm_cli = self.create_client( 19 | ChangeMode, 20 | '/f_generate_search_path/change_mode', 21 | callback_group=self.client_cb_group) 22 | 23 | self.follow_pipeline_sm_cli = self.create_client( 24 | ChangeMode, 25 | '/f_follow_pipeline/change_mode', 26 | callback_group=self.client_cb_group) 27 | 28 | self.sm_cli_dict = { 29 | 'f_generate_search_path': self.generate_path_sm_cli, 30 | 'f_follow_pipeline': self.follow_pipeline_sm_cli, 31 | } 32 | 33 | self.task_functions_dict = { 34 | 'search_pipeline': ['f_generate_search_path'], 35 | 'inspect_pipeline': ['f_follow_pipeline'], 36 | } 37 | 38 | def forward_task_request(self, function): 39 | mode_name = self.get_parameter(function + '_mode').value 40 | return self.call_sysmode_change_mode(function, mode_name) 41 | 42 | def forward_task_cancel_request(self, function): 43 | mode_name = 'fd_unground' 44 | return self.call_sysmode_change_mode(function, mode_name) 45 | 46 | def call_sysmode_change_mode(self, function, mode_name): 47 | mode_req = ChangeMode.Request() 48 | mode_req.mode_name = mode_name 49 | cli = self.sm_cli_dict[function] 50 | response = self.call_service(cli, mode_req) 51 | return response.success 52 | 53 | 54 | def main(): 55 | print('Starting task bridge node') 56 | 57 | rclpy.init(args=sys.argv) 58 | 59 | task_bridge_node = TaskBridgeNone() 60 | 61 | executor = MultiThreadedExecutor() 62 | rclpy.spin(task_bridge_node, executor=executor) 63 | 64 | task_bridge_node.destroy_node() 65 | rclpy.shutdown() 66 | -------------------------------------------------------------------------------- /suave/test/test_copyright.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_copyright.main import main 16 | import pytest 17 | 18 | 19 | # Remove the `skip` decorator once the source file(s) have a copyright header 20 | @pytest.mark.skip(reason='No copyright header has been placed in the generated source file.') 21 | @pytest.mark.copyright 22 | @pytest.mark.linter 23 | def test_copyright(): 24 | rc = main(argv=['.', 'test']) 25 | assert rc == 0, 'Found errors' 26 | -------------------------------------------------------------------------------- /suave/test/test_flake8.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_flake8.main import main_with_errors 16 | import pytest 17 | 18 | 19 | @pytest.mark.flake8 20 | @pytest.mark.linter 21 | def test_flake8(): 22 | rc, errors = main_with_errors(argv=[]) 23 | assert rc == 0, \ 24 | 'Found %d code style errors / warnings:\n' % len(errors) + \ 25 | '\n'.join(errors) 26 | -------------------------------------------------------------------------------- /suave/test/test_pep257.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_pep257.main import main 16 | import pytest 17 | 18 | 19 | @pytest.mark.linter 20 | @pytest.mark.pep257 21 | def test_pep257(): 22 | rc = main(argv=['.', 'test']) 23 | assert rc == 0, 'Found code style errors / warnings' 24 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/action_arm_thrusters.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SUAVE_BT__ARM_THRUSTERS_HPP_ 16 | #define SUAVE_BT__ARM_THRUSTERS_HPP_ 17 | 18 | #include "behaviortree_cpp/behavior_tree.h" 19 | #include "behaviortree_cpp/bt_factory.h" 20 | 21 | #include "rclcpp/rclcpp.hpp" 22 | #include "mavros_msgs/srv/command_bool.hpp" 23 | #include "suave_bt/suave_mission.hpp" 24 | 25 | 26 | namespace suave_bt 27 | { 28 | 29 | class ArmThrusters : public BT::StatefulActionNode{ 30 | 31 | public: 32 | ArmThrusters(const std::string& name, const BT::NodeConfig & conf); 33 | 34 | BT::NodeStatus onRunning() override; 35 | 36 | BT::NodeStatus onStart() override {return BT::NodeStatus::RUNNING;}; 37 | 38 | void onHalted() override {}; 39 | 40 | static BT::PortsList providedPorts() 41 | { 42 | return BT::PortsList( 43 | { 44 | }); 45 | } 46 | 47 | protected: 48 | suave_bt::SuaveMission::SharedPtr node_; 49 | rclcpp::Client::SharedPtr arm_motors_cli_; 50 | }; 51 | 52 | } // namespace suave_bt 53 | 54 | #endif // SUAVE_BT__ARM_THRUSTERS_HPP_ 55 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/action_change_mode.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SUAVE_BT__CHANGE_MODE_HPP_ 16 | #define SUAVE_BT__CHANGE_MODE_HPP_ 17 | 18 | #include "behaviortree_cpp/behavior_tree.h" 19 | #include "behaviortree_cpp/bt_factory.h" 20 | 21 | #include "rclcpp/rclcpp.hpp" 22 | #include "suave_bt/suave_mission.hpp" 23 | #include "system_modes_msgs/srv/change_mode.hpp" 24 | #include "system_modes_msgs/srv/get_mode.hpp" 25 | 26 | 27 | namespace suave_bt 28 | { 29 | 30 | class ChangeMode : public BT::SyncActionNode{ 31 | 32 | public: 33 | ChangeMode(const std::string& name, const BT::NodeConfig & conf); 34 | 35 | BT::NodeStatus tick() override; 36 | 37 | static BT::PortsList providedPorts() 38 | { 39 | return BT::PortsList( 40 | { 41 | BT::InputPort("node_name"), 42 | BT::InputPort("mode_name"), 43 | }); 44 | } 45 | 46 | protected: 47 | suave_bt::SuaveMission::SharedPtr node_; 48 | std::string node_name_; 49 | std::shared_ptr> previous_modes_; 50 | rclcpp::Client::SharedPtr change_mode_cli_; 51 | rclcpp::Client::SharedPtr get_mode_cli_; 52 | }; 53 | 54 | } // namespace suave_bt 55 | 56 | #endif // SUAVE_BT__CHANGE_MODE_HPP_ 57 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/action_inspect_pipeline.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SUAVE_BT__INSPECT_PIPELINE_HPP_ 16 | #define SUAVE_BT__INSPECT_PIPELINE_HPP_ 17 | 18 | #include "behaviortree_cpp/behavior_tree.h" 19 | #include "behaviortree_cpp/bt_factory.h" 20 | 21 | #include "rclcpp/rclcpp.hpp" 22 | #include "std_msgs/msg/bool.hpp" 23 | 24 | #include "suave_bt/suave_mission.hpp" 25 | 26 | using namespace std::placeholders; 27 | 28 | namespace suave_bt 29 | { 30 | 31 | class InspectPipeline : public BT::StatefulActionNode{ 32 | 33 | public: 34 | InspectPipeline(const std::string& name, const BT::NodeConfig & conf); 35 | 36 | BT::NodeStatus onStart() override {return BT::NodeStatus::RUNNING;}; 37 | 38 | BT::NodeStatus onRunning() override; 39 | 40 | void onHalted() override {}; 41 | 42 | static BT::PortsList providedPorts() 43 | { 44 | return BT::PortsList( 45 | { 46 | }); 47 | } 48 | 49 | private: 50 | std::shared_ptr node_; 51 | bool pipeline_inspected_; 52 | rclcpp::Subscription::SharedPtr pipeline_inspected_sub_; 53 | void pipeline_inspected_cb(const std_msgs::msg::Bool &msg); 54 | }; 55 | 56 | } // namespace suave_bt 57 | 58 | #endif // SUAVE_BT__INSPECT_PIPELINE_HPP_ 59 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/action_recharge_battery.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SUAVE_BT__RECHARGE_BATTERY_HPP_ 16 | #define SUAVE_BT__RECHARGE_BATTERY_HPP_ 17 | 18 | #include "behaviortree_cpp/behavior_tree.h" 19 | #include "behaviortree_cpp/bt_factory.h" 20 | 21 | #include "rclcpp/rclcpp.hpp" 22 | #include "std_msgs/msg/bool.hpp" 23 | 24 | #include "suave_bt/suave_mission.hpp" 25 | 26 | using namespace std::placeholders; 27 | 28 | namespace suave_bt 29 | { 30 | 31 | class RechargeBattery : public BT::StatefulActionNode{ 32 | 33 | public: 34 | RechargeBattery(const std::string& name, const BT::NodeConfig & conf); 35 | 36 | BT::NodeStatus onStart() override; 37 | 38 | BT::NodeStatus onRunning() override; 39 | 40 | void onHalted() override {}; 41 | 42 | static BT::PortsList providedPorts() 43 | { 44 | return BT::PortsList( 45 | { 46 | }); 47 | } 48 | 49 | private: 50 | std::shared_ptr node_; 51 | 52 | bool recharged_; 53 | rclcpp::Subscription::SharedPtr battery_level_sub_; 54 | void battery_level_cb(const std_msgs::msg::Bool &msg); 55 | }; 56 | 57 | } // namespace suave_bt 58 | 59 | #endif // SUAVE_BT__RECHARGE_BATTERY_HPP_ 60 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/action_search_pipeline.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SUAVE_BT__SEARCH_PIPELINE_HPP_ 16 | #define SUAVE_BT__SEARCH_PIPELINE_HPP_ 17 | 18 | #include "behaviortree_cpp/behavior_tree.h" 19 | #include "behaviortree_cpp/bt_factory.h" 20 | 21 | #include "rclcpp/rclcpp.hpp" 22 | #include "std_msgs/msg/bool.hpp" 23 | 24 | #include "suave_bt/suave_mission.hpp" 25 | 26 | using namespace std::placeholders; 27 | 28 | namespace suave_bt 29 | { 30 | 31 | class SearchPipeline : public BT::StatefulActionNode{ 32 | 33 | public: 34 | SearchPipeline(const std::string& name, const BT::NodeConfig & conf); 35 | 36 | BT::NodeStatus onStart() override; 37 | 38 | BT::NodeStatus onRunning() override; 39 | 40 | void onHalted() override {}; 41 | 42 | static BT::PortsList providedPorts() 43 | { 44 | return BT::PortsList( 45 | { 46 | }); 47 | } 48 | 49 | private: 50 | std::shared_ptr node_; 51 | 52 | bool pipeline_detected_; 53 | rclcpp::Subscription::SharedPtr pipeline_detection_sub_; 54 | void pipeline_detected_cb(const std_msgs::msg::Bool &msg); 55 | }; 56 | 57 | } // namespace suave_bt 58 | 59 | #endif // SUAVE_BT__SEARCH_PIPELINE_HPP_ 60 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/action_set_guided_mode.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SUAVE_BT__SET_GUIDED_MODE_HPP_ 16 | #define SUAVE_BT__SET_GUIDED_MODE_HPP_ 17 | 18 | #include 19 | #include "behaviortree_cpp/behavior_tree.h" 20 | #include "behaviortree_cpp/bt_factory.h" 21 | 22 | #include "rclcpp/rclcpp.hpp" 23 | #include "mavros_msgs/msg/state.hpp" 24 | #include "mavros_msgs/srv/set_mode.hpp" 25 | 26 | #include "suave_bt/suave_mission.hpp" 27 | 28 | namespace suave_bt 29 | { 30 | 31 | class SetGuidedMode : public BT::StatefulActionNode{ 32 | 33 | public: 34 | SetGuidedMode(const std::string& name, const BT::NodeConfig & conf); 35 | 36 | BT::NodeStatus onStart() override {return BT::NodeStatus::RUNNING;}; 37 | 38 | void onHalted() override {}; 39 | 40 | BT::NodeStatus onRunning() override; 41 | 42 | static BT::PortsList providedPorts() 43 | { 44 | return BT::PortsList( 45 | { 46 | }); 47 | } 48 | 49 | protected: 50 | std::string mode_; 51 | suave_bt::SuaveMission::SharedPtr _node; 52 | rclcpp::Client::SharedPtr set_guided_cli_; 53 | rclcpp::Subscription::SharedPtr mavros_state_sub_; 54 | void state_cb(const mavros_msgs::msg::State &msg); 55 | }; 56 | 57 | } // namespace suave_bt 58 | 59 | #endif // SUAVE_BT__SET_GUIDED_MODE_HPP_ 60 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/condition_battery_level.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SUAVE_BT__CONDITION_BATTERY_LEVEL_HPP_ 16 | #define SUAVE_BT__CONDITION_BATTERY_LEVEL_HPP_ 17 | 18 | #include "behaviortree_cpp/behavior_tree.h" 19 | #include "behaviortree_cpp/bt_factory.h" 20 | 21 | #include "rclcpp/rclcpp.hpp" 22 | #include "diagnostic_msgs/msg/diagnostic_array.hpp" 23 | 24 | #include "suave_bt/suave_mission.hpp" 25 | 26 | using namespace std::chrono_literals; 27 | 28 | namespace suave_bt 29 | { 30 | 31 | class BatteryLevel : public BT::ConditionNode 32 | { 33 | public: 34 | explicit BatteryLevel( 35 | const std::string & xml_tag_name, 36 | const BT::NodeConfig & conf); 37 | 38 | BT::NodeStatus tick() override; 39 | 40 | static BT::PortsList providedPorts() 41 | { 42 | return BT::PortsList( 43 | { 44 | BT::InputPort("threshold"), 45 | }); 46 | } 47 | 48 | private: 49 | std::shared_ptr node_; 50 | 51 | float battery_level_; 52 | rclcpp::Subscription::SharedPtr diagnostics_sub_; 53 | void diagnostics_cb(const diagnostic_msgs::msg::DiagnosticArray &msg); 54 | }; 55 | 56 | } //namespace suave_bt 57 | 58 | #endif // SUAVE_BT__CONDITION_BATTERY_LEVEL_HPP_ 59 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/condition_thrusters_ok.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SUAVE_BT__CONDITION_THRUSTERS_OK_HPP_ 16 | #define SUAVE_BT__CONDITION_THRUSTERS_OK_HPP_ 17 | 18 | #include "behaviortree_cpp/behavior_tree.h" 19 | #include "behaviortree_cpp/bt_factory.h" 20 | 21 | #include "rclcpp/rclcpp.hpp" 22 | #include "diagnostic_msgs/msg/diagnostic_array.hpp" 23 | 24 | #include "suave_bt/suave_mission.hpp" 25 | 26 | using namespace std::chrono_literals; 27 | 28 | namespace suave_bt 29 | { 30 | 31 | class ThrustersOk : public BT::ConditionNode 32 | { 33 | public: 34 | explicit ThrustersOk( 35 | const std::string & xml_tag_name, 36 | const BT::NodeConfig & conf); 37 | 38 | BT::NodeStatus tick() override; 39 | 40 | static BT::PortsList providedPorts() 41 | { 42 | return BT::PortsList( 43 | { 44 | }); 45 | } 46 | 47 | private: 48 | std::shared_ptr node_; 49 | 50 | std::map thrusters_ok_; 51 | rclcpp::Subscription::SharedPtr diagnostics_sub_; 52 | void diagnostics_cb(const diagnostic_msgs::msg::DiagnosticArray &msg); 53 | }; 54 | 55 | } //namespace suave_bt 56 | 57 | #endif // SUAVE_BT__CONDITION_THRUSTERS_OK_HPP_ 58 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/condition_water_visibility.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SUAVE_BT__CONDITION_WATER_VISIBILITY_HPP_ 16 | #define SUAVE_BT__CONDITION_WATER_VISIBILITY_HPP_ 17 | 18 | #include "behaviortree_cpp/behavior_tree.h" 19 | #include "behaviortree_cpp/bt_factory.h" 20 | 21 | #include "rclcpp/rclcpp.hpp" 22 | #include "diagnostic_msgs/msg/diagnostic_array.hpp" 23 | 24 | #include "suave_bt/suave_mission.hpp" 25 | 26 | using namespace std::chrono_literals; 27 | 28 | namespace suave_bt 29 | { 30 | 31 | class WaterVisibility : public BT::ConditionNode 32 | { 33 | public: 34 | explicit WaterVisibility( 35 | const std::string & xml_tag_name, 36 | const BT::NodeConfig & conf); 37 | 38 | BT::NodeStatus tick() override; 39 | 40 | static BT::PortsList providedPorts() 41 | { 42 | return BT::PortsList( 43 | { 44 | BT::InputPort("threshold"), 45 | }); 46 | } 47 | 48 | private: 49 | std::shared_ptr node_; 50 | 51 | float water_visibility_; 52 | rclcpp::Subscription::SharedPtr diagnostics_sub_; 53 | void diagnostics_cb(const diagnostic_msgs::msg::DiagnosticArray &msg); 54 | }; 55 | 56 | } //namespace suave_bt 57 | 58 | #endif // SUAVE_BT__CONDITION_WATER_VISIBILITY_HPP_ 59 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/is_pipeline_found.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SUAVE_BT__PIPELINE_FOUND_HPP_ 16 | #define SUAVE_BT__PIPELINE_FOUND_HPP_ 17 | 18 | #include "behaviortree_cpp/behavior_tree.h" 19 | #include "behaviortree_cpp/bt_factory.h" 20 | 21 | #include "rclcpp/rclcpp.hpp" 22 | #include "std_msgs/msg/bool.hpp" 23 | #include "suave_bt/suave_mission.hpp" 24 | 25 | namespace suave_bt 26 | { 27 | 28 | class IsPipelineFound : public BT::ConditionNode 29 | { 30 | public: 31 | explicit IsPipelineFound(const std::string & xml_tag_name, 32 | const BT::NodeConfig & conf); 33 | 34 | BT::NodeStatus tick() override; 35 | 36 | static BT::PortsList providedPorts() 37 | { 38 | return BT::PortsList( 39 | { 40 | }); 41 | } 42 | 43 | private: 44 | bool _pipeline_detected; 45 | 46 | suave_bt::SuaveMission::SharedPtr _node; 47 | rclcpp::Subscription::SharedPtr pipeline_detection_sub_; 48 | 49 | void pipeline_detected_cb(const std_msgs::msg::Bool &msg); 50 | }; 51 | 52 | } // namespace suave_bt 53 | 54 | #endif // SUAVE_BT__PIPELINE_FOUND_HPP_ 55 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/is_pipeline_inspected.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SUAVE_BT__PIPELINE_INSPECTED_HPP_ 16 | #define SUAVE_BT__PIPELINE_INSPECTED_HPP_ 17 | 18 | #include "behaviortree_cpp/behavior_tree.h" 19 | #include "behaviortree_cpp/bt_factory.h" 20 | 21 | #include "rclcpp/rclcpp.hpp" 22 | #include "std_msgs/msg/bool.hpp" 23 | #include "suave_bt/suave_mission.hpp" 24 | 25 | namespace suave_bt 26 | { 27 | 28 | class IsPipelineInspected : public BT::ConditionNode 29 | { 30 | public: 31 | explicit IsPipelineInspected(const std::string & xml_tag_name, 32 | const BT::NodeConfig & conf); 33 | 34 | BT::NodeStatus tick() override; 35 | 36 | static BT::PortsList providedPorts() 37 | { 38 | return BT::PortsList( 39 | { 40 | }); 41 | } 42 | 43 | private: 44 | bool _pipeline_inspected; 45 | 46 | suave_bt::SuaveMission::SharedPtr _node; 47 | rclcpp::Subscription::SharedPtr pipeline_inspected_sub_; 48 | 49 | void pipeline_inspected_cb(const std_msgs::msg::Bool &msg); 50 | }; 51 | 52 | } // namespace suave_bt 53 | 54 | #endif // SUAVE_BT__PIPELINE_INSPECTED_HPP_ 55 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/suave_mission.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SUAVE_BT__SUAVE_MISSION_HPP_ 16 | #define SUAVE_BT__SUAVE_MISSION_HPP_ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "rclcpp/rclcpp.hpp" 24 | #include "std_msgs/msg/float32.hpp" 25 | #include "std_srvs/srv/empty.hpp" 26 | 27 | namespace suave_bt 28 | { 29 | 30 | class SuaveMission : public rclcpp::Node{ 31 | 32 | public: 33 | SuaveMission(std::string none_name); 34 | 35 | bool time_limit_reached(); 36 | void set_search_started(); 37 | bool is_mission_aborted(){return mission_aborted_;}; 38 | void finish_mission(); 39 | 40 | private: 41 | rclcpp::Time start_time_; 42 | bool search_started_ = false; 43 | int time_limit_; 44 | rclcpp::Client::SharedPtr save_mission_results_cli; 45 | 46 | bool mission_aborted_; 47 | 48 | rclcpp::CallbackGroup::SharedPtr time_limit_timer_cb_group_; 49 | rclcpp::TimerBase::SharedPtr time_limit_timer_; 50 | 51 | void time_limit_cb(); 52 | bool request_save_mission_results(); 53 | }; 54 | 55 | } // namespace suave_bt 56 | 57 | #endif // SUAVE_BT__SUAVE_MISSION_HPP_ 58 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/include/suave_bt/visibility_control.h: -------------------------------------------------------------------------------- 1 | #ifndef SUAVE_BT__VISIBILITY_CONTROL_H_ 2 | #define SUAVE_BT__VISIBILITY_CONTROL_H_ 3 | 4 | // This logic was borrowed (then namespaced) from the examples on the gcc wiki: 5 | // https://gcc.gnu.org/wiki/Visibility 6 | 7 | #if defined _WIN32 || defined __CYGWIN__ 8 | #ifdef __GNUC__ 9 | #define SUAVE_BT_EXPORT __attribute__ ((dllexport)) 10 | #define SUAVE_BT_IMPORT __attribute__ ((dllimport)) 11 | #else 12 | #define SUAVE_BT_EXPORT __declspec(dllexport) 13 | #define SUAVE_BT_IMPORT __declspec(dllimport) 14 | #endif 15 | #ifdef SUAVE_BT_BUILDING_LIBRARY 16 | #define SUAVE_BT_PUBLIC SUAVE_BT_EXPORT 17 | #else 18 | #define SUAVE_BT_PUBLIC SUAVE_BT_IMPORT 19 | #endif 20 | #define SUAVE_BT_PUBLIC_TYPE SUAVE_BT_PUBLIC 21 | #define SUAVE_BT_LOCAL 22 | #else 23 | #define SUAVE_BT_EXPORT __attribute__ ((visibility("default"))) 24 | #define SUAVE_BT_IMPORT 25 | #if __GNUC__ >= 4 26 | #define SUAVE_BT_PUBLIC __attribute__ ((visibility("default"))) 27 | #define SUAVE_BT_LOCAL __attribute__ ((visibility("hidden"))) 28 | #else 29 | #define SUAVE_BT_PUBLIC 30 | #define SUAVE_BT_LOCAL 31 | #endif 32 | #define SUAVE_BT_PUBLIC_TYPE 33 | #endif 34 | 35 | #endif // SUAVE_BT__VISIBILITY_CONTROL_H_ 36 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | suave_bt 5 | 0.0.0 6 | BT implementation of a managing system for SUAVE 7 | gus 8 | Apache-2.0 9 | 10 | ament_cmake 11 | 12 | suave 13 | suave_msgs 14 | mavros_msgs 15 | system_modes_msgs 16 | diagnostic_msgs 17 | behaviortree_cpp 18 | behaviortree_cpp_dbgsym 19 | 20 | ament_lint_auto 21 | ament_lint_common 22 | 23 | 24 | ament_cmake 25 | 26 | 27 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/src/suave_bt/action_arm_thrusters.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "suave_bt/action_arm_thrusters.hpp" 16 | 17 | 18 | namespace suave_bt 19 | { 20 | using namespace std::placeholders; 21 | using namespace std::chrono_literals; 22 | 23 | ArmThrusters::ArmThrusters( 24 | const std::string& name, const BT::NodeConfig & conf) 25 | : BT::StatefulActionNode(name, conf) 26 | { 27 | node_ = config().blackboard->get>("node"); 28 | arm_motors_cli_ = node_->create_client( 29 | "mavros/cmd/arming"); 30 | } 31 | 32 | BT::NodeStatus ArmThrusters::onRunning(){ 33 | 34 | if(arm_motors_cli_->service_is_ready()){ 35 | auto request = std::make_shared(); 36 | request->value = true; 37 | auto arm_motors_result_ = arm_motors_cli_->async_send_request(request); 38 | 39 | if (arm_motors_result_.wait_for(1s) == std::future_status::ready) 40 | { 41 | auto arm_result_ = arm_motors_result_.get(); 42 | if(!arm_result_->success){ 43 | return BT::NodeStatus::FAILURE; 44 | } 45 | 46 | if(arm_result_->success){ 47 | RCLCPP_INFO(node_->get_logger(), "Thrusters armed!"); 48 | return BT::NodeStatus::SUCCESS; 49 | } 50 | } else { 51 | return BT::NodeStatus::FAILURE; 52 | } 53 | } 54 | 55 | RCLCPP_INFO(node_->get_logger(), "mavros/cmd/arming service not available, waiting again..."); 56 | return BT::NodeStatus::RUNNING; 57 | } 58 | } //namespace suave_bt 59 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/src/suave_bt/action_inspect_pipeline.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "suave_bt/action_inspect_pipeline.hpp" 16 | 17 | namespace suave_bt 18 | { 19 | InspectPipeline::InspectPipeline( 20 | const std::string& name, const BT::NodeConfig & conf) 21 | : BT::StatefulActionNode(name, conf), pipeline_inspected_(false) 22 | { 23 | node_ = config().blackboard->get>("node"); 24 | pipeline_inspected_sub_ = node_->create_subscription( 25 | "/pipeline/inspected", 26 | 10, 27 | std::bind(&InspectPipeline::pipeline_inspected_cb, this, _1)); 28 | } 29 | 30 | void InspectPipeline::pipeline_inspected_cb(const std_msgs::msg::Bool &msg){ 31 | pipeline_inspected_ = msg.data; 32 | } 33 | 34 | BT::NodeStatus InspectPipeline::onRunning(){ 35 | std::this_thread::sleep_for(std::chrono::milliseconds(50)); 36 | 37 | if(this->node_->time_limit_reached()){ 38 | std::cout << "Time limit reached. Canceling action "<< this->name() << std::endl; 39 | return BT::NodeStatus::FAILURE; 40 | } 41 | 42 | if(pipeline_inspected_==true){ 43 | std::cout << "Async action finished: "<< this->name() << std::endl; 44 | return BT::NodeStatus::SUCCESS; 45 | } 46 | std::cout<<"Inspecting pipeline! "<get>("node"); 24 | battery_level_sub_ = this->node_->create_subscription( 25 | "/battery_monitor/recharge/complete", 26 | 10, 27 | std::bind(&RechargeBattery::battery_level_cb, this, _1)); 28 | } 29 | 30 | void RechargeBattery::battery_level_cb(const std_msgs::msg::Bool &msg){ 31 | recharged_ = msg.data; 32 | } 33 | 34 | BT::NodeStatus RechargeBattery::onStart() { 35 | recharged_ = false; 36 | return BT::NodeStatus::RUNNING; 37 | } 38 | 39 | BT::NodeStatus RechargeBattery::onRunning() { 40 | std::this_thread::sleep_for(std::chrono::milliseconds(50)); 41 | 42 | if(this->node_->time_limit_reached()){ 43 | std::cout << "Time limit reached. Canceling action "<< this->name() << std::endl; 44 | return BT::NodeStatus::FAILURE; 45 | } 46 | 47 | if(recharged_ == true){ 48 | std::cout << "Async action finished: "<< this->name() << std::endl; 49 | return BT::NodeStatus::SUCCESS; 50 | } 51 | std::cout<<"Recharging! "<get>("node"); 24 | pipeline_detection_sub_ = node_->create_subscription( 25 | "/pipeline/detected", 26 | 10, 27 | std::bind(&SearchPipeline::pipeline_detected_cb, this, _1)); 28 | } 29 | 30 | void SearchPipeline::pipeline_detected_cb(const std_msgs::msg::Bool &msg) 31 | { 32 | pipeline_detected_ = msg.data; 33 | } 34 | 35 | BT::NodeStatus SearchPipeline::onStart() 36 | { 37 | //request node activation 38 | this->node_->set_search_started(); 39 | return BT::NodeStatus::RUNNING; 40 | } 41 | 42 | BT::NodeStatus SearchPipeline::onRunning() 43 | { 44 | std::this_thread::sleep_for(std::chrono::milliseconds(50)); 45 | 46 | if(node_->time_limit_reached()){ 47 | std::cout << "Time limit reached. Canceling action "<< this->name() << std::endl; 48 | return BT::NodeStatus::FAILURE; 49 | } 50 | 51 | if(pipeline_detected_ == true){ 52 | std::cout << "Async action finished: "<< this->name() << std::endl; 53 | return BT::NodeStatus::SUCCESS; 54 | } 55 | std::cout<<"Searching for pipeline! "<get>("node"); 28 | set_guided_cli_ = _node->create_client( 29 | "mavros/set_mode"); 30 | mavros_state_sub_ = _node->create_subscription( 31 | "mavros/state", 32 | 10, 33 | std::bind(&SetGuidedMode::state_cb, this, _1)); 34 | } 35 | 36 | void 37 | SetGuidedMode::state_cb(const mavros_msgs::msg::State &msg) 38 | { 39 | mode_ = msg.mode; 40 | } 41 | 42 | 43 | BT::NodeStatus SetGuidedMode::onRunning(){ 44 | std::this_thread::sleep_for(std::chrono::milliseconds(50)); 45 | 46 | if(set_guided_cli_->service_is_ready()){ 47 | auto request = std::make_shared(); 48 | request->custom_mode = "GUIDED"; 49 | auto set_guided_result_ = set_guided_cli_->async_send_request(request); 50 | 51 | if (set_guided_result_.wait_for(1s) == std::future_status::ready) 52 | { 53 | auto result_ = set_guided_result_.get(); 54 | if(!result_->mode_sent){ 55 | return BT::NodeStatus::FAILURE; 56 | } 57 | 58 | if(result_->mode_sent && mode_ == "GUIDED"){ 59 | RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Mode set to GUIDED!"); 60 | return BT::NodeStatus::SUCCESS; 61 | } 62 | } else { 63 | return BT::NodeStatus::FAILURE; 64 | } 65 | } 66 | 67 | return BT::NodeStatus::RUNNING; 68 | } 69 | } //namespace suave_bt 70 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/src/suave_bt/condition_battery_level.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "suave_bt/condition_battery_level.hpp" 16 | 17 | using namespace std::placeholders; 18 | 19 | namespace suave_bt 20 | { 21 | BatteryLevel::BatteryLevel( 22 | const std::string & xml_tag_name, 23 | const BT::NodeConfig & conf) 24 | : BT::ConditionNode(xml_tag_name, conf), battery_level_(-1.0) 25 | { 26 | node_ = config().blackboard->get>("node"); 27 | diagnostics_sub_ = node_->create_subscription( 28 | "/diagnostics", 29 | 10, 30 | std::bind(&BatteryLevel::diagnostics_cb, this, _1)); 31 | } 32 | 33 | void BatteryLevel::diagnostics_cb(const diagnostic_msgs::msg::DiagnosticArray &msg){ 34 | for(auto status: msg.status){ 35 | if(status.message == "QA status"){ 36 | for(auto value: status.values){ 37 | if(value.key == "battery_level") { 38 | battery_level_ = std::stof(value.value); 39 | } 40 | } 41 | } 42 | } 43 | } 44 | 45 | BT::NodeStatus BatteryLevel::tick() { 46 | float threshold; 47 | getInput("threshold", threshold); 48 | if(battery_level_ >= threshold || battery_level_ == -1.0) return BT::NodeStatus::SUCCESS; 49 | 50 | return BT::NodeStatus::FAILURE; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/src/suave_bt/condition_thrusters_ok.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "suave_bt/condition_thrusters_ok.hpp" 16 | 17 | using namespace std::placeholders; 18 | 19 | namespace suave_bt 20 | { 21 | ThrustersOk::ThrustersOk( 22 | const std::string & xml_tag_name, 23 | const BT::NodeConfig & conf) 24 | : BT::ConditionNode(xml_tag_name, conf) 25 | { 26 | thrusters_ok_["c_thruster_1"] = true; 27 | thrusters_ok_["c_thruster_2"] = true; 28 | thrusters_ok_["c_thruster_3"] = true; 29 | thrusters_ok_["c_thruster_4"] = true; 30 | thrusters_ok_["c_thruster_5"] = true; 31 | thrusters_ok_["c_thruster_6"] = true; 32 | 33 | node_ = config().blackboard->get>("node"); 34 | diagnostics_sub_ = node_->create_subscription( 35 | "/diagnostics", 36 | 10, 37 | std::bind(&ThrustersOk::diagnostics_cb, this, _1)); 38 | } 39 | 40 | void ThrustersOk::diagnostics_cb(const diagnostic_msgs::msg::DiagnosticArray &msg){ 41 | for(auto status: msg.status){ 42 | if(status.message == "Component status"){ 43 | for(auto value: status.values){ 44 | auto it = thrusters_ok_.find(value.key); 45 | if (it != thrusters_ok_.end()) { 46 | it->second = (value.value == "RECOVERED") ? true : false; 47 | } 48 | } 49 | } 50 | } 51 | } 52 | 53 | 54 | BT::NodeStatus ThrustersOk::tick() { 55 | // check if whole thrusters_ok_ map is true 56 | if(std::all_of(thrusters_ok_.begin(), thrusters_ok_.end(), [](const auto& t) { return t.second; })){ 57 | return BT::NodeStatus::SUCCESS; 58 | } 59 | return BT::NodeStatus::FAILURE; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/src/suave_bt/condition_water_visibility.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "suave_bt/condition_water_visibility.hpp" 16 | 17 | using namespace std::placeholders; 18 | 19 | namespace suave_bt 20 | { 21 | WaterVisibility::WaterVisibility( 22 | const std::string & xml_tag_name, 23 | const BT::NodeConfig & conf) 24 | : BT::ConditionNode(xml_tag_name, conf), water_visibility_(-1.0) 25 | { 26 | node_ = config().blackboard->get>("node"); 27 | diagnostics_sub_ = node_->create_subscription( 28 | "/diagnostics", 29 | 10, 30 | std::bind(&WaterVisibility::diagnostics_cb, this, _1)); 31 | } 32 | 33 | void WaterVisibility::diagnostics_cb(const diagnostic_msgs::msg::DiagnosticArray &msg){ 34 | for(auto status: msg.status){ 35 | if(status.message == "QA status"){ 36 | for(auto value: status.values){ 37 | if(value.key == "water_visibility") { 38 | water_visibility_ = std::stof(value.value); 39 | } 40 | } 41 | } 42 | } 43 | } 44 | 45 | BT::NodeStatus WaterVisibility::tick() { 46 | float threshold; 47 | getInput("threshold", threshold); 48 | if(water_visibility_ >= threshold || water_visibility_ == -1.0) return BT::NodeStatus::SUCCESS; 49 | return BT::NodeStatus::FAILURE; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/src/suave_bt/is_pipeline_found.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "suave_bt/is_pipeline_found.hpp" 16 | 17 | namespace suave_bt 18 | { 19 | 20 | using namespace std::placeholders; 21 | 22 | IsPipelineFound::IsPipelineFound( 23 | const std::string & xml_tag_name, 24 | const BT::NodeConfig & conf) 25 | : BT::ConditionNode(xml_tag_name, conf), _pipeline_detected(false) 26 | { 27 | _node = config().blackboard->get>("node"); 28 | 29 | pipeline_detection_sub_ = _node->create_subscription( 30 | "/pipeline/detected", 31 | 10, 32 | std::bind(&IsPipelineFound::pipeline_detected_cb, this, _1)); 33 | } 34 | 35 | void 36 | IsPipelineFound::pipeline_detected_cb(const std_msgs::msg::Bool &msg) 37 | { 38 | _pipeline_detected = msg.data; 39 | } 40 | 41 | BT::NodeStatus 42 | IsPipelineFound::tick() 43 | { 44 | return (_pipeline_detected==true) ? BT::NodeStatus::SUCCESS : BT::NodeStatus::FAILURE; 45 | } 46 | 47 | } // namespace suave_bt 48 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/src/suave_bt/is_pipeline_inspected.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "suave_bt/is_pipeline_inspected.hpp" 16 | 17 | namespace suave_bt 18 | { 19 | 20 | using namespace std::placeholders; 21 | 22 | IsPipelineInspected::IsPipelineInspected( 23 | const std::string & xml_tag_name, 24 | const BT::NodeConfig & conf) 25 | : BT::ConditionNode(xml_tag_name, conf), _pipeline_inspected(false) 26 | { 27 | _node = config().blackboard->get>("node"); 28 | 29 | pipeline_inspected_sub_ = _node->create_subscription( 30 | "/pipeline/inspected", 31 | 10, 32 | std::bind(&IsPipelineInspected::pipeline_inspected_cb, this, _1)); 33 | } 34 | 35 | void 36 | IsPipelineInspected::pipeline_inspected_cb(const std_msgs::msg::Bool &msg) 37 | { 38 | _pipeline_inspected = msg.data; 39 | } 40 | 41 | BT::NodeStatus 42 | IsPipelineInspected::tick() 43 | { 44 | return (_pipeline_inspected==true) ? BT::NodeStatus::SUCCESS : BT::NodeStatus::FAILURE; 45 | } 46 | 47 | } // namespace suave_bt 48 | -------------------------------------------------------------------------------- /suave_managing/suave_bt/src/suave_bt/suave_mission.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Gustavo Rezende Silva 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "suave_bt/suave_mission.hpp" 16 | 17 | namespace suave_bt 18 | { 19 | using namespace std::placeholders; 20 | using namespace std::chrono_literals; 21 | 22 | SuaveMission::SuaveMission(std::string none_name) 23 | : Node(none_name), search_started_(false), mission_aborted_(false) 24 | { 25 | this->declare_parameter("time_limit", 300); 26 | time_limit_ = this->get_parameter("time_limit").as_int(); 27 | 28 | save_mission_results_cli = 29 | this->create_client("mission_metrics/save"); 30 | 31 | time_limit_timer_cb_group_ = create_callback_group( 32 | rclcpp::CallbackGroupType::MutuallyExclusive); 33 | // TODO: create parameter for timer rate? 34 | time_limit_timer_ = this->create_wall_timer( 35 | 100ms, std::bind(&SuaveMission::time_limit_cb, this), time_limit_timer_cb_group_); 36 | } 37 | 38 | void SuaveMission::time_limit_cb(){ 39 | if(this->time_limit_reached()){ 40 | RCLCPP_INFO(this->get_logger(), "Time limit reached!"); 41 | this->finish_mission(); 42 | } 43 | } 44 | 45 | bool SuaveMission::time_limit_reached(){ 46 | if(search_started_){ 47 | return (this->get_clock()->now() - start_time_) >= rclcpp::Duration(time_limit_, 0); 48 | } 49 | return false; 50 | } 51 | 52 | void SuaveMission::finish_mission(){ 53 | this->request_save_mission_results(); 54 | this->time_limit_timer_->cancel(); 55 | mission_aborted_ = true; 56 | } 57 | 58 | bool SuaveMission::request_save_mission_results(){ 59 | while (!save_mission_results_cli->wait_for_service(1s)) { 60 | if (!rclcpp::ok()) { 61 | RCLCPP_ERROR(this->get_logger(), "Interrupted while waiting for the service. Exiting."); 62 | return false; 63 | } 64 | RCLCPP_INFO(this->get_logger(), "mission_metrics/save service not available, waiting again..."); 65 | } 66 | 67 | auto request = std::make_shared(); 68 | auto response = save_mission_results_cli->async_send_request(request); 69 | if (response.wait_for(1s) == std::future_status::ready) 70 | { 71 | return true; 72 | } else { 73 | RCLCPP_ERROR(this->get_logger(), "Failed to call service mission_metrics/save"); 74 | return false; 75 | } 76 | } 77 | 78 | void SuaveMission::set_search_started(){ 79 | if(search_started_ == true) return; 80 | start_time_ = this->get_clock()->now(); 81 | search_started_ = true; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /suave_managing/suave_metacontrol/config/metacontrol_config.yaml: -------------------------------------------------------------------------------- 1 | /suave_reasoner: 2 | ros__parameters: 3 | reasoning_time_save: True 4 | reasoning_time_file_path: '~/suave/results' #Path to save results 5 | reasoning_period: 1.5 6 | -------------------------------------------------------------------------------- /suave_managing/suave_metacontrol/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | suave_metacontrol 5 | 0.0.0 6 | TODO: Package description 7 | jeroen 8 | TODO: License declaration 9 | 10 | rclpy 11 | lifecycle_msgs 12 | std_msgs 13 | system_modes_msgs 14 | system_modes 15 | mros2_msgs 16 | mros2_reasoner 17 | mc_mdl_tomasys 18 | mros_ontology 19 | 20 | ament_copyright 21 | ament_flake8 22 | ament_pep257 23 | python3-pytest 24 | 25 | 26 | ament_python 27 | 28 | 29 | -------------------------------------------------------------------------------- /suave_managing/suave_metacontrol/resource/suave_metacontrol: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_managing/suave_metacontrol/resource/suave_metacontrol -------------------------------------------------------------------------------- /suave_managing/suave_metacontrol/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/suave_metacontrol 3 | [install] 4 | install_scripts=$base/lib/suave_metacontrol 5 | -------------------------------------------------------------------------------- /suave_managing/suave_metacontrol/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from glob import glob 3 | from setuptools import setup 4 | 5 | package_name = 'suave_metacontrol' 6 | 7 | setup( 8 | name=package_name, 9 | version='0.23.0', 10 | packages=[package_name], 11 | data_files=[ 12 | ('share/ament_index/resource_index/packages', 13 | ['resource/' + package_name]), 14 | ('share/' + package_name, ['package.xml']), 15 | (os.path.join('share', package_name, 'launch'), 16 | glob('launch/*launch.[pxy][yma]*')), 17 | (os.path.join('share', package_name, 'config'), 18 | glob('config/*')) 19 | ], 20 | install_requires=['setuptools'], 21 | zip_safe=True, 22 | maintainer='jeroen', 23 | maintainer_email='j.zwanepol@hotmail.com', 24 | description='TODO: Package description', 25 | license='TODO: License declaration', 26 | tests_require=['pytest'], 27 | entry_points={ 28 | 'console_scripts': [ 29 | 'task_bridge_metacontrol = ' + 30 | ' suave_metacontrol.task_bridge_metacontrol:main', 31 | ], 32 | }, 33 | ) 34 | -------------------------------------------------------------------------------- /suave_managing/suave_metacontrol/suave_metacontrol/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_managing/suave_metacontrol/suave_metacontrol/__init__.py -------------------------------------------------------------------------------- /suave_managing/suave_metacontrol/test/test_copyright.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_copyright.main import main 16 | import pytest 17 | 18 | 19 | # Remove the `skip` decorator once the source file(s) have a copyright header 20 | @pytest.mark.skip(reason='No copyright header has been placed in the generated source file.') 21 | @pytest.mark.copyright 22 | @pytest.mark.linter 23 | def test_copyright(): 24 | rc = main(argv=['.', 'test']) 25 | assert rc == 0, 'Found errors' 26 | -------------------------------------------------------------------------------- /suave_managing/suave_metacontrol/test/test_flake8.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_flake8.main import main_with_errors 16 | import pytest 17 | 18 | 19 | @pytest.mark.flake8 20 | @pytest.mark.linter 21 | def test_flake8(): 22 | rc, errors = main_with_errors(argv=[]) 23 | assert rc == 0, \ 24 | 'Found %d code style errors / warnings:\n' % len(errors) + \ 25 | '\n'.join(errors) 26 | -------------------------------------------------------------------------------- /suave_managing/suave_metacontrol/test/test_pep257.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_pep257.main import main 16 | import pytest 17 | 18 | 19 | @pytest.mark.linter 20 | @pytest.mark.pep257 21 | def test_pep257(): 22 | rc = main(argv=['.', 'test']) 23 | assert rc == 0, 'Found code style errors / warnings' 24 | -------------------------------------------------------------------------------- /suave_managing/suave_none/launch/suave_none.launch.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from ament_index_python.packages import get_package_share_directory 4 | 5 | from launch import LaunchDescription 6 | from launch.actions import DeclareLaunchArgument 7 | from launch.actions import IncludeLaunchDescription 8 | from launch.actions import OpaqueFunction 9 | from launch.launch_description_sources import PythonLaunchDescriptionSource 10 | from launch.substitutions import LaunchConfiguration 11 | 12 | from launch_ros.actions import Node 13 | 14 | 15 | def generate_launch_description(): 16 | silent = LaunchConfiguration('silent') 17 | silent_arg = DeclareLaunchArgument( 18 | 'silent', 19 | default_value='false', 20 | description='Suppress all output (launch logs + node logs)' 21 | ) 22 | def configure_logging(context, *args, **kwargs): 23 | if silent.perform(context) == 'true': 24 | import logging 25 | logging.getLogger().setLevel(logging.CRITICAL) 26 | return [] 27 | 28 | result_filename = LaunchConfiguration('result_filename') 29 | result_filename_arg = DeclareLaunchArgument( 30 | 'result_filename', 31 | default_value='none_results', 32 | description='Name of the results file' 33 | ) 34 | mission_config = os.path.join( 35 | get_package_share_directory('suave_missions'), 36 | 'config', 37 | 'mission_config.yaml') 38 | 39 | pkg_suave_path = get_package_share_directory( 40 | 'suave') 41 | 42 | suave_launch_path = os.path.join( 43 | pkg_suave_path, 44 | 'launch', 45 | 'suave.launch.py') 46 | 47 | suave_launch = IncludeLaunchDescription( 48 | PythonLaunchDescriptionSource(suave_launch_path), 49 | launch_arguments={ 50 | 'task_bridge': 'False'}.items() 51 | ) 52 | 53 | mission_config = os.path.join( 54 | get_package_share_directory('suave_missions'), 55 | 'config', 56 | 'mission_config.yaml' 57 | ) 58 | 59 | mission_node = Node( 60 | package='suave_missions', 61 | executable='time_constrained_mission', 62 | name='mission_node', 63 | parameters=[mission_config], 64 | ) 65 | 66 | mission_metrics_node = Node( 67 | package='suave_metrics', 68 | executable='mission_metrics', 69 | name='mission_metrics', 70 | parameters=[mission_config, { 71 | 'adaptation_manager': 'none', 72 | 'mission_name': 'suave', 73 | 'result_filename': result_filename, 74 | }], 75 | ) 76 | 77 | return LaunchDescription([ 78 | result_filename_arg, 79 | silent_arg, 80 | OpaqueFunction(function=configure_logging), 81 | suave_launch, 82 | mission_node, 83 | mission_metrics_node 84 | ]) 85 | -------------------------------------------------------------------------------- /suave_managing/suave_none/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | suave_none 5 | 0.0.0 6 | SUAVE with no managing subsystem 7 | Gustavo Rezende 8 | Apache-2.0 9 | 10 | ament_copyright 11 | ament_flake8 12 | ament_pep257 13 | python3-pytest 14 | 15 | 16 | ament_python 17 | 18 | 19 | -------------------------------------------------------------------------------- /suave_managing/suave_none/resource/suave_none: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_managing/suave_none/resource/suave_none -------------------------------------------------------------------------------- /suave_managing/suave_none/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/suave_none 3 | [install] 4 | install_scripts=$base/lib/suave_none 5 | -------------------------------------------------------------------------------- /suave_managing/suave_none/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from glob import glob 3 | from setuptools import find_packages, setup 4 | 5 | package_name = 'suave_none' 6 | 7 | setup( 8 | name=package_name, 9 | version='0.0.0', 10 | packages=find_packages(exclude=['test']), 11 | data_files=[ 12 | ('share/ament_index/resource_index/packages', 13 | ['resource/' + package_name]), 14 | ('share/' + package_name, ['package.xml']), 15 | (os.path.join('share', package_name, 'launch'), 16 | glob('launch/*launch.[pxy][yma]*')), 17 | ], 18 | install_requires=['setuptools'], 19 | zip_safe=True, 20 | maintainer='Gustavo Rezende', 21 | maintainer_email='g.rezendesilva@tudelft.nl', 22 | description='TODO: Package description', 23 | license='Apache-2.0', 24 | tests_require=['pytest'], 25 | entry_points={ 26 | 'console_scripts': [ 27 | ], 28 | }, 29 | ) 30 | -------------------------------------------------------------------------------- /suave_managing/suave_none/suave_none/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_managing/suave_none/suave_none/__init__.py -------------------------------------------------------------------------------- /suave_managing/suave_none/test/test_copyright.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_copyright.main import main 16 | import pytest 17 | 18 | 19 | # Remove the `skip` decorator once the source file(s) have a copyright header 20 | @pytest.mark.skip(reason='No copyright header has been placed in the generated source file.') 21 | @pytest.mark.copyright 22 | @pytest.mark.linter 23 | def test_copyright(): 24 | rc = main(argv=['.', 'test']) 25 | assert rc == 0, 'Found errors' 26 | -------------------------------------------------------------------------------- /suave_managing/suave_none/test/test_flake8.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_flake8.main import main_with_errors 16 | import pytest 17 | 18 | 19 | @pytest.mark.flake8 20 | @pytest.mark.linter 21 | def test_flake8(): 22 | rc, errors = main_with_errors(argv=[]) 23 | assert rc == 0, \ 24 | 'Found %d code style errors / warnings:\n' % len(errors) + \ 25 | '\n'.join(errors) 26 | -------------------------------------------------------------------------------- /suave_managing/suave_none/test/test_pep257.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_pep257.main import main 16 | import pytest 17 | 18 | 19 | @pytest.mark.linter 20 | @pytest.mark.pep257 21 | def test_pep257(): 22 | rc = main(argv=['.', 'test']) 23 | assert rc == 0, 'Found code style errors / warnings' 24 | -------------------------------------------------------------------------------- /suave_managing/suave_random/launch/suave_random.launch.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from ament_index_python.packages import get_package_share_directory 4 | 5 | from launch import LaunchDescription 6 | from launch.actions import DeclareLaunchArgument 7 | from launch.actions import IncludeLaunchDescription 8 | from launch.actions import OpaqueFunction 9 | from launch.launch_description_sources import PythonLaunchDescriptionSource 10 | from launch.substitutions import LaunchConfiguration 11 | 12 | from launch_ros.actions import Node 13 | 14 | 15 | def generate_launch_description(): 16 | silent = LaunchConfiguration('silent') 17 | silent_arg = DeclareLaunchArgument( 18 | 'silent', 19 | default_value='false', 20 | description='Suppress all output (launch logs + node logs)' 21 | ) 22 | def configure_logging(context, *args, **kwargs): 23 | if silent.perform(context) == 'true': 24 | import logging 25 | logging.getLogger().setLevel(logging.CRITICAL) 26 | return [] 27 | 28 | result_filename = LaunchConfiguration('result_filename') 29 | result_filename_arg = DeclareLaunchArgument( 30 | 'result_filename', 31 | default_value='random_results', 32 | description='Name of the results file' 33 | ) 34 | mission_config = os.path.join( 35 | get_package_share_directory('suave_missions'), 36 | 'config', 37 | 'mission_config.yaml') 38 | 39 | pkg_suave_path = get_package_share_directory( 40 | 'suave') 41 | 42 | suave_launch_path = os.path.join( 43 | pkg_suave_path, 44 | 'launch', 45 | 'suave.launch.py') 46 | 47 | suave_launch = IncludeLaunchDescription( 48 | PythonLaunchDescriptionSource(suave_launch_path), 49 | launch_arguments={ 50 | 'task_bridge': 'False'}.items() 51 | ) 52 | 53 | task_bridge_node = Node( 54 | package='suave_random', 55 | executable='task_bridge_random', 56 | parameters=[mission_config], 57 | ) 58 | 59 | mission_config = os.path.join( 60 | get_package_share_directory('suave_missions'), 61 | 'config', 62 | 'mission_config.yaml' 63 | ) 64 | 65 | mission_node = Node( 66 | package='suave_missions', 67 | executable='time_constrained_mission', 68 | name='mission_node', 69 | parameters=[mission_config], 70 | ) 71 | 72 | mission_metrics_node = Node( 73 | package='suave_metrics', 74 | executable='mission_metrics', 75 | name='mission_metrics', 76 | parameters=[mission_config, { 77 | 'adaptation_manager': 'random', 78 | 'mission_name': 'suave', 79 | 'result_filename': result_filename, 80 | }], 81 | ) 82 | 83 | return LaunchDescription([ 84 | result_filename_arg, 85 | silent_arg, 86 | OpaqueFunction(function=configure_logging), 87 | suave_launch, 88 | task_bridge_node, 89 | mission_node, 90 | mission_metrics_node 91 | ]) 92 | -------------------------------------------------------------------------------- /suave_managing/suave_random/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | suave_random 5 | 0.0.0 6 | Implementation of a random managing system for SUAVE 7 | gus 8 | Apache-2.0 9 | 10 | ament_copyright 11 | ament_flake8 12 | ament_pep257 13 | python3-pytest 14 | 15 | 16 | ament_python 17 | 18 | 19 | -------------------------------------------------------------------------------- /suave_managing/suave_random/resource/suave_random: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_managing/suave_random/resource/suave_random -------------------------------------------------------------------------------- /suave_managing/suave_random/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/suave_random 3 | [install] 4 | install_scripts=$base/lib/suave_random 5 | -------------------------------------------------------------------------------- /suave_managing/suave_random/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from glob import glob 3 | from setuptools import setup 4 | 5 | package_name = 'suave_random' 6 | 7 | setup( 8 | name=package_name, 9 | version='0.0.0', 10 | packages=[package_name], 11 | data_files=[ 12 | ('share/ament_index/resource_index/packages', 13 | ['resource/' + package_name]), 14 | ('share/' + package_name, ['package.xml']), 15 | (os.path.join('share', package_name, 'launch'), 16 | glob('launch/*launch.[pxy][yma]*')), 17 | ], 18 | install_requires=['setuptools'], 19 | zip_safe=True, 20 | maintainer='Gustavo Rezende', 21 | maintainer_email='g.rezendesilva@tudelft.nl', 22 | description='Implementation of a random managing system for SUAVE', 23 | license='Apache-2.0', 24 | tests_require=['pytest'], 25 | entry_points={ 26 | 'console_scripts': [ 27 | 'task_bridge_random = ' + 28 | ' suave_random.task_bridge_random:main', 29 | ], 30 | }, 31 | ) 32 | -------------------------------------------------------------------------------- /suave_managing/suave_random/suave_random/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_managing/suave_random/suave_random/__init__.py -------------------------------------------------------------------------------- /suave_managing/suave_random/suave_random/task_bridge_random.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import random 3 | import rclpy 4 | import sys 5 | 6 | from rclpy.executors import MultiThreadedExecutor 7 | from suave.task_bridge_none import TaskBridgeNone 8 | from system_modes_msgs.srv import GetAvailableModes 9 | 10 | 11 | class TaskBridgeRandom(TaskBridgeNone): 12 | def __init__(self): 13 | super().__init__() 14 | 15 | self.declare_parameter('adaptation_period', 15) 16 | self.adaptation_period = self.get_parameter('adaptation_period').value 17 | 18 | self.generate_path_modes_cli = self.create_client( 19 | GetAvailableModes, 20 | '/f_generate_search_path/get_available_modes', 21 | callback_group=self.client_cb_group) 22 | 23 | self.follow_pipeline_modes_cli = self.create_client( 24 | GetAvailableModes, 25 | '/f_follow_pipeline/get_available_modes', 26 | callback_group=self.client_cb_group) 27 | 28 | self.available_modes_cli = { 29 | 'f_generate_search_path': self.generate_path_modes_cli, 30 | 'f_follow_pipeline': self.follow_pipeline_modes_cli, 31 | } 32 | 33 | self.reasoner_timer = self.create_timer( 34 | self.adaptation_period, 35 | self.reasoner_cb, 36 | callback_group=self.task_cb_group 37 | ) 38 | 39 | def reasoner_cb(self): 40 | for task_name in self.current_tasks: 41 | function_names = self.task_functions_dict[task_name] 42 | for function in function_names: 43 | self.forward_task_request(function) 44 | 45 | def forward_task_request(self, function): 46 | modes_cli = self.available_modes_cli[function] 47 | mode_name = random.choice( 48 | self.call_service( 49 | modes_cli, GetAvailableModes.Request()).available_modes 50 | ) 51 | 52 | return self.call_sysmode_change_mode(function, mode_name) 53 | 54 | 55 | def main(): 56 | print('Starting random task bridge node') 57 | 58 | rclpy.init(args=sys.argv) 59 | 60 | task_bridge_node = TaskBridgeRandom() 61 | 62 | executor = MultiThreadedExecutor() 63 | rclpy.spin(task_bridge_node, executor=executor) 64 | 65 | task_bridge_node.destroy_node() 66 | rclpy.shutdown() 67 | -------------------------------------------------------------------------------- /suave_managing/suave_random/test/test_copyright.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_copyright.main import main 16 | import pytest 17 | 18 | 19 | # Remove the `skip` decorator once the source file(s) have a copyright header 20 | @pytest.mark.skip(reason='No copyright header has been placed in the generated source file.') 21 | @pytest.mark.copyright 22 | @pytest.mark.linter 23 | def test_copyright(): 24 | rc = main(argv=['.', 'test']) 25 | assert rc == 0, 'Found errors' 26 | -------------------------------------------------------------------------------- /suave_managing/suave_random/test/test_flake8.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_flake8.main import main_with_errors 16 | import pytest 17 | 18 | 19 | @pytest.mark.flake8 20 | @pytest.mark.linter 21 | def test_flake8(): 22 | rc, errors = main_with_errors(argv=[]) 23 | assert rc == 0, \ 24 | 'Found %d code style errors / warnings:\n' % len(errors) + \ 25 | '\n'.join(errors) 26 | -------------------------------------------------------------------------------- /suave_managing/suave_random/test/test_pep257.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_pep257.main import main 16 | import pytest 17 | 18 | 19 | @pytest.mark.linter 20 | @pytest.mark.pep257 21 | def test_pep257(): 22 | rc = main(argv=['.', 'test']) 23 | assert rc == 0, 'Found code style errors / warnings' 24 | -------------------------------------------------------------------------------- /suave_metrics/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | suave_metrics 5 | 0.0.0 6 | Package for collecting metrics of SUAVE 7 | gus 8 | Apache-2.0 9 | 10 | ament_copyright 11 | ament_flake8 12 | ament_pep257 13 | python3-pytest 14 | 15 | mavros 16 | mavros_msgs 17 | rclpy 18 | std_msgs 19 | geometry_msgs 20 | 21 | 22 | ament_python 23 | 24 | 25 | -------------------------------------------------------------------------------- /suave_metrics/resource/suave_metrics: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_metrics/resource/suave_metrics -------------------------------------------------------------------------------- /suave_metrics/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/suave_metrics 3 | [install] 4 | install_scripts=$base/lib/suave_metrics 5 | -------------------------------------------------------------------------------- /suave_metrics/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup 2 | 3 | package_name = 'suave_metrics' 4 | 5 | setup( 6 | name=package_name, 7 | version='0.0.0', 8 | packages=find_packages(exclude=['test']), 9 | data_files=[ 10 | ('share/ament_index/resource_index/packages', 11 | ['resource/' + package_name]), 12 | ('share/' + package_name, ['package.xml']), 13 | ], 14 | install_requires=['setuptools'], 15 | zip_safe=True, 16 | maintainer='gus', 17 | maintainer_email='g.rezendesilva@tudelft.nl', 18 | description='Package for collecting metrics of SUAVE', 19 | license='Apache-2.0', 20 | tests_require=['pytest'], 21 | entry_points={ 22 | 'console_scripts': [ 23 | 'mission_metrics = suave_metrics.mission_metrics:main' 24 | ], 25 | }, 26 | ) 27 | -------------------------------------------------------------------------------- /suave_metrics/suave_metrics/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_metrics/suave_metrics/__init__.py -------------------------------------------------------------------------------- /suave_metrics/test/test_copyright.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_copyright.main import main 16 | import pytest 17 | 18 | 19 | # Remove the `skip` decorator once the source file(s) have a copyright header 20 | @pytest.mark.skip(reason='No copyright header has been placed in the generated source file.') 21 | @pytest.mark.copyright 22 | @pytest.mark.linter 23 | def test_copyright(): 24 | rc = main(argv=['.', 'test']) 25 | assert rc == 0, 'Found errors' 26 | -------------------------------------------------------------------------------- /suave_metrics/test/test_flake8.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_flake8.main import main_with_errors 16 | import pytest 17 | 18 | 19 | @pytest.mark.flake8 20 | @pytest.mark.linter 21 | def test_flake8(): 22 | rc, errors = main_with_errors(argv=[]) 23 | assert rc == 0, \ 24 | 'Found %d code style errors / warnings:\n' % len(errors) + \ 25 | '\n'.join(errors) 26 | -------------------------------------------------------------------------------- /suave_metrics/test/test_pep257.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_pep257.main import main 16 | import pytest 17 | 18 | 19 | @pytest.mark.linter 20 | @pytest.mark.pep257 21 | def test_pep257(): 22 | rc = main(argv=['.', 'test']) 23 | assert rc == 0, 'Found code style errors / warnings' 24 | -------------------------------------------------------------------------------- /suave_missions/config/mission_config.yaml: -------------------------------------------------------------------------------- 1 | /mission_metrics: 2 | ros__parameters: 3 | result_path: "~/suave/results" #Path to save results 4 | water_visibiity_threshold: [3.25, 2.25, 1.25] 5 | expected_altitude: [3.0, 2.0, 1.0] 6 | battery_limit: 0.25 7 | 8 | /mission_node: 9 | ros__parameters: 10 | time_limit: 300 #Time limit for a time_constrained mission 11 | f_generate_search_path_mode: "fd_spiral_low" #Default mode for f_generate_search_path when no manager is used 12 | f_follow_pipeline_mode: "fd_follow_pipeline" #Default mode for f_follow_pipeline when no manager is used 13 | 14 | /water_visibility_observer_node: 15 | ros__parameters: 16 | qa_publishing_period: 1.0 17 | water_visibility_period: 80 #Water visibility period in seconds 18 | water_visibility_min: 1.25 #Minimum value for water visibility 19 | water_visibility_max: 3.75 #Maximum value for water visibility 20 | water_visibility_sec_shift: 0.0 #Water visibility seconds shift to left 21 | 22 | /thruster_monitor: 23 | ros__parameters: 24 | thruster_events: # Thruster events, format: (thruster number (1 to 6), failure or recovery, delta time in seconds(from the last event)) 25 | - (1,failure,35) 26 | 27 | /task_bridge: 28 | ros__parameters: 29 | adapt_period: 30 #Period to perform random adaptation in seconds 30 | -------------------------------------------------------------------------------- /suave_missions/launch/const_distance_mission.launch.py: -------------------------------------------------------------------------------- 1 | from launch import LaunchDescription 2 | from launch.actions import DeclareLaunchArgument 3 | from launch.substitutions import LaunchConfiguration 4 | 5 | from launch_ros.actions import Node 6 | 7 | 8 | def generate_launch_description(): 9 | result_path = LaunchConfiguration('result_path') 10 | result_filename = LaunchConfiguration('result_filename') 11 | 12 | result_path_arg = DeclareLaunchArgument( 13 | 'result_path', 14 | default_value='~/suave/results', 15 | description='Path to save mission measured metrics' 16 | ) 17 | 18 | result_filename_arg = DeclareLaunchArgument( 19 | 'result_filename', 20 | default_value='const_distance_mission_results', 21 | description='Filename for the mission measured metrics' 22 | ) 23 | 24 | mission_node = Node( 25 | package='suave_metacontrol', 26 | executable='const_dist_mission', 27 | name='const_dist_mission_node', 28 | parameters=[{ 29 | 'result_path': result_path, 30 | 'result_filename': result_filename, 31 | }] 32 | ) 33 | 34 | return LaunchDescription([ 35 | result_path_arg, 36 | result_filename_arg, 37 | mission_node, 38 | ]) 39 | -------------------------------------------------------------------------------- /suave_missions/launch/mission_bringup.launch.py: -------------------------------------------------------------------------------- 1 | from launch import LaunchDescription 2 | from launch.actions import DeclareLaunchArgument 3 | 4 | 5 | def generate_launch_description(): 6 | 7 | adaptation_manager_arg = DeclareLaunchArgument( 8 | 'adaptation_manager', 9 | default_value='none', 10 | description='Adaptation manager in charge, none/metacontrol/random') 11 | 12 | mission_type_arg = DeclareLaunchArgument( 13 | 'mission_type', 14 | default_value='time_constrained_mission', 15 | description='Which type of mission to have, time or distance' 16 | ) 17 | 18 | return LaunchDescription([ 19 | adaptation_manager_arg, 20 | mission_type_arg, 21 | ]) 22 | -------------------------------------------------------------------------------- /suave_missions/launch/time_constrained_mission.launch.py: -------------------------------------------------------------------------------- 1 | from launch import LaunchDescription 2 | from launch.actions import DeclareLaunchArgument 3 | from launch.substitutions import LaunchConfiguration 4 | 5 | from launch_ros.actions import Node 6 | 7 | 8 | def generate_launch_description(): 9 | mission_type = LaunchConfiguration('mission_type') 10 | result_path = LaunchConfiguration('result_path') 11 | result_filename = LaunchConfiguration('result_filename') 12 | time_limit = LaunchConfiguration('time_limit') 13 | 14 | result_path_arg = DeclareLaunchArgument( 15 | 'result_path', 16 | default_value='~/suave/results', 17 | description='Path to save mission measured metrics' 18 | ) 19 | 20 | result_filename_arg = DeclareLaunchArgument( 21 | 'result_filename', 22 | default_value='time_constrained_mission_results', 23 | description='Filename for the mission measured metrics' 24 | ) 25 | 26 | time_limit_arg = DeclareLaunchArgument( 27 | 'time_limit', 28 | default_value='300', 29 | description='Time limit for the mission (seconds)' 30 | ) 31 | 32 | mission_type_arg = DeclareLaunchArgument( 33 | 'mission_type', 34 | default_value='time_constrained_mission', 35 | description='Which type of mission to have, time or distance' 36 | ) 37 | 38 | mission_node = Node( 39 | package='suave_missions', 40 | executable=mission_type, 41 | name=mission_type, 42 | parameters=[{ 43 | 'result_path': result_path, 44 | 'result_filename': result_filename, 45 | 'time_limit': time_limit, 46 | }] 47 | ) 48 | 49 | return LaunchDescription([ 50 | mission_type_arg, 51 | result_path_arg, 52 | result_filename_arg, 53 | time_limit_arg, 54 | mission_node, 55 | ]) 56 | -------------------------------------------------------------------------------- /suave_missions/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | suave_missions 5 | 0.0.0 6 | TODO: Package description 7 | ega 8 | Apache-2.0 9 | 10 | mavros 11 | suave_msgs 12 | mavros_msgs 13 | mavros_wrapper 14 | ros_gz 15 | rclpy 16 | lifecycle_msgs 17 | std_msgs 18 | system_modes_msgs 19 | system_modes 20 | mros2_msgs 21 | mros2_reasoner 22 | mc_mdl_tomasys 23 | mros_ontology 24 | 25 | ament_copyright 26 | ament_flake8 27 | ament_pep257 28 | python3-pytest 29 | 30 | 31 | geometry_msgs 32 | 33 | 34 | ament_python 35 | 36 | 37 | -------------------------------------------------------------------------------- /suave_missions/resource/suave_missions: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_missions/resource/suave_missions -------------------------------------------------------------------------------- /suave_missions/results/seams2023_mission_config.yaml: -------------------------------------------------------------------------------- 1 | /parent_mission_node: 2 | ros__parameters: 3 | time_limit: 300 #Time limit for a time_constrained mission 4 | result_path: "~/suave/results" #Path to save results 5 | f_generate_search_path_mode: "fd_spiral_low" #Default mode for f_generate_search_path when no manager is used 6 | f_follow_pipeline_mode: "fd_follow_pipeline" #Default mode for f_follow_pipeline when no manager is used 7 | 8 | /water_visibility_observer_node: 9 | ros__parameters: 10 | water_visibility_period: 80 #Water visibility period in seconds 11 | water_visibility_min: 1.25 #Minimum value for water visibility 12 | water_visibility_max: 3.75 #Maximum value for water visibility 13 | water_visibility_sec_shift: 0.0 #Water visibility seconds shift to left 14 | 15 | /thruster_monitor: 16 | ros__parameters: 17 | thruster_events: # Thruster events, format: (thruster number (1 to 6), failure or recovery, delta time in seconds(from the last event)) 18 | - (1,failure,35) 19 | 20 | /random_reasoner_node: 21 | ros__parameters: 22 | adapt_period: 30 #Period to perform random adaptation in seconds 23 | -------------------------------------------------------------------------------- /suave_missions/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/suave_missions 3 | [install] 4 | install_scripts=$base/lib/suave_missions 5 | -------------------------------------------------------------------------------- /suave_missions/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from glob import glob 3 | from setuptools import setup 4 | 5 | package_name = 'suave_missions' 6 | 7 | setup( 8 | name=package_name, 9 | version='0.0.0', 10 | packages=[package_name], 11 | data_files=[ 12 | ('share/ament_index/resource_index/packages', 13 | ['resource/' + package_name]), 14 | ('share/' + package_name, ['package.xml']), 15 | (os.path.join('share', package_name, 'launch'), 16 | glob('launch/*launch.[pxy][yma]*')), 17 | (os.path.join('share', package_name, 'config'), 18 | glob('config/*')) 19 | ], 20 | install_requires=['setuptools'], 21 | zip_safe=True, 22 | maintainer='ega', 23 | maintainer_email='e.g.alberts@', 24 | description='TODO: Package description', 25 | license='TODO: License declaration', 26 | tests_require=['pytest'], 27 | entry_points={ 28 | 'console_scripts': [ 29 | 'const_dist_mission = ' + 30 | 'suave_missions.const_dist_mission:main', 31 | 'time_constrained_mission = ' + 32 | 'suave_missions.time_constrained_mission:main', 33 | ], 34 | }, 35 | ) 36 | -------------------------------------------------------------------------------- /suave_missions/suave_missions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_missions/suave_missions/__init__.py -------------------------------------------------------------------------------- /suave_missions/suave_missions/const_dist_mission.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import rclpy 3 | from rclpy.executors import MultiThreadedExecutor 4 | from suave_missions.inspection_mission import InspectionMission 5 | 6 | 7 | def main(): 8 | 9 | rclpy.init(args=sys.argv) 10 | 11 | mission_node = InspectionMission() 12 | 13 | mt_executor = MultiThreadedExecutor() 14 | mt_executor.add_node(mission_node) 15 | mt_executor.create_task(mission_node.perform_mission) 16 | mt_executor.spin() 17 | 18 | mission_node.destroy_node() 19 | rclpy.shutdown() 20 | 21 | 22 | if __name__ == '__main__': 23 | main() 24 | -------------------------------------------------------------------------------- /suave_missions/suave_missions/mission_planner.py: -------------------------------------------------------------------------------- 1 | from rclpy.callback_groups import MutuallyExclusiveCallbackGroup 2 | from rclpy.node import Node 3 | from suave_msgs.srv import Task 4 | 5 | 6 | class MissionPlanner(Node): 7 | def __init__(self, node_name='mission_node'): 8 | super().__init__(node_name) 9 | 10 | self.cb_group = MutuallyExclusiveCallbackGroup() 11 | self.task_request_service = self.create_client( 12 | Task, 'task/request', callback_group=self.cb_group) 13 | self.task_cancel_service = self.create_client( 14 | Task, 'task/cancel', callback_group=self.cb_group) 15 | 16 | self.declare_parameter('result_path', '~/suave/results') 17 | self.declare_parameter('result_filename', 'mission_results') 18 | 19 | self.result_path = self.get_parameter('result_path').value 20 | self.result_filename = self.get_parameter('result_filename').value 21 | 22 | self.metrics_header = ['mission_name', 'datetime', 'metric'] 23 | 24 | self.mission_start_time = None 25 | self.abort_mission = False 26 | 27 | def request_task(self, task_name): 28 | req = Task.Request() 29 | req.task_name = task_name 30 | return self.call_service(self.task_request_service, req) 31 | 32 | def cancel_task(self, task_name): 33 | req = Task.Request() 34 | req.task_name = task_name 35 | return self.call_service(self.task_cancel_service, req) 36 | 37 | def call_service(self, cli, request): 38 | if cli.wait_for_service(timeout_sec=5.0) is False: 39 | self.get_logger().error( 40 | 'service not available {}'.format(cli.srv_name)) 41 | return None 42 | future = cli.call_async(request) 43 | self.executor.spin_until_future_complete(future, timeout_sec=5.0) 44 | if future.done() is False: 45 | self.get_logger().error( 46 | 'Future not completed {}'.format(cli.srv_name)) 47 | return None 48 | return future.result() 49 | 50 | def perform_mission(self): 51 | self.get_logger().warning("No mission defined!!!") 52 | 53 | def perform_task(self, task_name, condition): 54 | self.task_timer = self.create_rate(1) 55 | task_status = "completed" 56 | if self.abort_mission is False: 57 | self.get_logger().info('Starting {} task'.format(task_name)) 58 | self.request_task(task_name) 59 | while condition() is not True: 60 | if self.abort_mission is True: 61 | task_status = "aborted" 62 | break 63 | self.task_timer.sleep() 64 | else: 65 | task_status = "aborted" 66 | self.get_logger().info('Task {0} {1}'.format(task_name, task_status)) 67 | self.cancel_task(task_name) 68 | -------------------------------------------------------------------------------- /suave_missions/suave_missions/time_constrained_mission.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import rclpy 4 | 5 | from rclpy.callback_groups import MutuallyExclusiveCallbackGroup 6 | from rclpy.executors import MultiThreadedExecutor 7 | from std_srvs.srv import Empty 8 | from suave_missions.inspection_mission import InspectionMission 9 | 10 | 11 | class MissionTimeConstrained(InspectionMission): 12 | def __init__(self, node_name='time_contrained_mission'): 13 | super().__init__(node_name) 14 | if self.result_filename == 'mission_results': 15 | self.result_filename = 'time_mission_results' 16 | 17 | self.declare_parameter('time_limit', 300) 18 | self.time_limit = self.get_parameter('time_limit').value 19 | 20 | self.time_monitor_timer = self.create_timer( 21 | 0.5, 22 | self.time_monitor_cb, 23 | callback_group=MutuallyExclusiveCallbackGroup()) 24 | 25 | self.save_mission_results_cli = self.create_client( 26 | Empty, 27 | 'mission_metrics/save', 28 | callback_group=MutuallyExclusiveCallbackGroup()) 29 | 30 | def time_monitor_cb(self): 31 | if self.mission_start_time is not None: 32 | current_time = self.get_clock().now() 33 | elapsed_time = current_time - self.mission_start_time 34 | if elapsed_time.to_msg().sec >= self.time_limit: 35 | self.abort_mission = True 36 | self.call_service( 37 | self.save_mission_results_cli, Empty.Request()) 38 | self.time_monitor_timer.destroy() 39 | 40 | def call_service(self, cli, request): 41 | if cli.wait_for_service(timeout_sec=5.0) is False: 42 | self.get_logger().error( 43 | 'service not available {}'.format(cli.srv_name)) 44 | return None 45 | future = cli.call_async(request) 46 | self.executor.spin_until_future_complete(future, timeout_sec=5.0) 47 | if future.done() is False: 48 | self.get_logger().error( 49 | 'Future not completed {}'.format(cli.srv_name)) 50 | return None 51 | return future.result() 52 | 53 | 54 | def main(): 55 | rclpy.init(args=sys.argv) 56 | 57 | mission_node = MissionTimeConstrained() 58 | 59 | mt_executor = MultiThreadedExecutor() 60 | mt_executor.add_node(mission_node) 61 | mt_executor.create_task(mission_node.perform_mission) 62 | mt_executor.spin() 63 | 64 | mission_node.destroy_node() 65 | rclpy.shutdown() 66 | 67 | 68 | if __name__ == '__main__': 69 | main() 70 | -------------------------------------------------------------------------------- /suave_missions/test/test_copyright.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_copyright.main import main 16 | import pytest 17 | 18 | 19 | # Remove the `skip` decorator once the source file(s) have a copyright header 20 | @pytest.mark.skip(reason='No copyright header has been placed in the generated source file.') 21 | @pytest.mark.copyright 22 | @pytest.mark.linter 23 | def test_copyright(): 24 | rc = main(argv=['.', 'test']) 25 | assert rc == 0, 'Found errors' 26 | -------------------------------------------------------------------------------- /suave_missions/test/test_flake8.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_flake8.main import main_with_errors 16 | import pytest 17 | 18 | 19 | @pytest.mark.flake8 20 | @pytest.mark.linter 21 | def test_flake8(): 22 | rc, errors = main_with_errors(argv=[]) 23 | assert rc == 0, \ 24 | 'Found %d code style errors / warnings:\n' % len(errors) + \ 25 | '\n'.join(errors) 26 | -------------------------------------------------------------------------------- /suave_missions/test/test_pep257.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_pep257.main import main 16 | import pytest 17 | 18 | 19 | @pytest.mark.linter 20 | @pytest.mark.pep257 21 | def test_pep257(): 22 | rc = main(argv=['.', 'test']) 23 | assert rc == 0, 'Found code style errors / warnings' 24 | -------------------------------------------------------------------------------- /suave_monitor/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | suave_monitor 5 | 0.0.0 6 | Monitor nodes for SUAVE 7 | gus 8 | Apache-2.0 9 | 10 | ament_copyright 11 | ament_flake8 12 | ament_pep257 13 | python3-pytest 14 | 15 | diagnostic_msgs 16 | mavros_msgs 17 | std_msgs 18 | rcl_interfaces 19 | 20 | 21 | ament_python 22 | 23 | 24 | -------------------------------------------------------------------------------- /suave_monitor/resource/suave_monitor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_monitor/resource/suave_monitor -------------------------------------------------------------------------------- /suave_monitor/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/suave_monitor 3 | [install] 4 | install_scripts=$base/lib/suave_monitor 5 | -------------------------------------------------------------------------------- /suave_monitor/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup 2 | 3 | package_name = 'suave_monitor' 4 | 5 | setup( 6 | name=package_name, 7 | version='0.0.0', 8 | packages=find_packages(exclude=['test']), 9 | data_files=[ 10 | ('share/ament_index/resource_index/packages', 11 | ['resource/' + package_name]), 12 | ('share/' + package_name, ['package.xml']), 13 | ], 14 | install_requires=['setuptools'], 15 | zip_safe=True, 16 | maintainer='gus', 17 | maintainer_email='g.rezendesilva@tudelft.nl', 18 | description='Monitor nodes for SUAVE', 19 | license='Apache-2.0', 20 | tests_require=['pytest'], 21 | entry_points={ 22 | 'console_scripts': [ 23 | 'thruster_monitor = suave_monitor.thruster_monitor:main', 24 | 'battery_monitor = suave_monitor.battery_monitor:main', 25 | 'water_visibility_observer = suave_monitor.water_visibility_observer:main', 26 | ], 27 | }, 28 | ) 29 | -------------------------------------------------------------------------------- /suave_monitor/suave_monitor/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_monitor/suave_monitor/__init__.py -------------------------------------------------------------------------------- /suave_monitor/suave_monitor/water_visibility_observer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from diagnostic_msgs.msg import DiagnosticArray 4 | from diagnostic_msgs.msg import DiagnosticStatus 5 | from diagnostic_msgs.msg import KeyValue 6 | from mavros_msgs.msg import State 7 | 8 | import math 9 | import rclpy 10 | from rclpy.node import Node 11 | import sys 12 | 13 | 14 | class WaterVisibilityObserver(Node): 15 | 16 | def __init__(self): 17 | super().__init__('water_visibility') 18 | 19 | self.declare_parameter('qa_publishing_period', 0.2) 20 | self.declare_parameter('water_visibility_period', 150) 21 | self.declare_parameter('water_visibility_min', 1.25) 22 | self.declare_parameter('water_visibility_max', 3.75) 23 | self.declare_parameter('water_visibility_sec_shift', 0.0) 24 | 25 | self.qa_publishing_period = self.get_parameter( 26 | 'qa_publishing_period').value 27 | 28 | self.diagnostics_publisher = self.create_publisher( 29 | DiagnosticArray, '/diagnostics', 10) 30 | 31 | self.mavros_state_sub = self.create_subscription( 32 | State, 'mavros/state', self.status_cb, 10) 33 | 34 | self.initial_time = self.get_clock().now().to_msg().sec 35 | 36 | def status_cb(self, msg): 37 | if msg.mode == "GUIDED": 38 | self.initial_time = self.get_clock().now().to_msg().sec 39 | self.qa_publisher_timer = self.create_timer( 40 | self.qa_publishing_period, self.qa_publisher_cb) 41 | self.destroy_subscription(self.mavros_state_sub) 42 | 43 | def qa_publisher_cb(self): 44 | water_visibility_period = self.get_parameter( 45 | 'water_visibility_period').value 46 | water_visibility_min = self.get_parameter( 47 | 'water_visibility_min').value 48 | water_visibility_max = self.get_parameter( 49 | 'water_visibility_max').value 50 | water_visibility_amp = abs( 51 | water_visibility_max - water_visibility_min)/2 52 | sec_shift = self.get_parameter( 53 | 'water_visibility_sec_shift').value 54 | 55 | current_time = self.get_clock().now().to_msg().sec 56 | t = current_time - self.initial_time 57 | v_delta = water_visibility_amp + water_visibility_min 58 | water_visibility = water_visibility_amp * math.cos( 59 | (2*math.pi/water_visibility_period)*(t + sec_shift)) + v_delta 60 | 61 | key_value = KeyValue() 62 | key_value.key = "water_visibility" 63 | key_value.value = str(water_visibility) 64 | 65 | status_msg = DiagnosticStatus() 66 | status_msg.level = DiagnosticStatus.OK 67 | status_msg.name = "water_visibility_observer: Water visibility measurement" 68 | status_msg.message = "QA status" 69 | status_msg.values.append(key_value) 70 | 71 | diag_msg = DiagnosticArray() 72 | diag_msg.header.stamp = self.get_clock().now().to_msg() 73 | diag_msg.status.append(status_msg) 74 | 75 | self.diagnostics_publisher.publish(diag_msg) 76 | 77 | 78 | def main(): 79 | print("Starting water_visibility observer node") 80 | 81 | rclpy.init(args=sys.argv) 82 | 83 | water_visibility_observer = WaterVisibilityObserver() 84 | rclpy.spin(water_visibility_observer) 85 | 86 | rclpy.shutdown() 87 | -------------------------------------------------------------------------------- /suave_monitor/test/test_copyright.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_copyright.main import main 16 | import pytest 17 | 18 | 19 | # Remove the `skip` decorator once the source file(s) have a copyright header 20 | @pytest.mark.skip(reason='No copyright header has been placed in the generated source file.') 21 | @pytest.mark.copyright 22 | @pytest.mark.linter 23 | def test_copyright(): 24 | rc = main(argv=['.', 'test']) 25 | assert rc == 0, 'Found errors' 26 | -------------------------------------------------------------------------------- /suave_monitor/test/test_flake8.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_flake8.main import main_with_errors 16 | import pytest 17 | 18 | 19 | @pytest.mark.flake8 20 | @pytest.mark.linter 21 | def test_flake8(): 22 | rc, errors = main_with_errors(argv=[]) 23 | assert rc == 0, \ 24 | 'Found %d code style errors / warnings:\n' % len(errors) + \ 25 | '\n'.join(errors) 26 | -------------------------------------------------------------------------------- /suave_monitor/test/test_pep257.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_pep257.main import main 16 | import pytest 17 | 18 | 19 | @pytest.mark.linter 20 | @pytest.mark.pep257 21 | def test_pep257(): 22 | rc = main(argv=['.', 'test']) 23 | assert rc == 0, 'Found code style errors / warnings' 24 | -------------------------------------------------------------------------------- /suave_msgs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(suave_msgs) 3 | 4 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 5 | add_compile_options(-Wall -Wextra -Wpedantic) 6 | endif() 7 | 8 | find_package(ament_cmake REQUIRED) 9 | find_package(geometry_msgs REQUIRED) 10 | find_package(rosidl_default_generators REQUIRED) 11 | 12 | rosidl_generate_interfaces(${PROJECT_NAME} 13 | "srv/GetPath.srv" 14 | "srv/Task.srv" 15 | DEPENDENCIES geometry_msgs 16 | ) 17 | 18 | if(BUILD_TESTING) 19 | find_package(ament_lint_auto REQUIRED) 20 | set(ament_cmake_copyright_FOUND TRUE) 21 | set(ament_cmake_cpplint_FOUND TRUE) 22 | ament_lint_auto_find_test_dependencies() 23 | endif() 24 | 25 | ament_package() 26 | -------------------------------------------------------------------------------- /suave_msgs/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | suave_msgs 5 | 0.0.0 6 | SUAVE msgs 7 | gus 8 | Apache-2.0 9 | 10 | ament_cmake 11 | 12 | ament_lint_auto 13 | ament_lint_common 14 | 15 | rosidl_default_generators 16 | rosidl_default_runtime 17 | rosidl_interface_packages 18 | 19 | 20 | ament_cmake 21 | 22 | 23 | -------------------------------------------------------------------------------- /suave_msgs/srv/GetPath.srv: -------------------------------------------------------------------------------- 1 | --- 2 | geometry_msgs/PoseArray path 3 | -------------------------------------------------------------------------------- /suave_msgs/srv/Task.srv: -------------------------------------------------------------------------------- 1 | string task_name 2 | --- 3 | bool success 4 | -------------------------------------------------------------------------------- /suave_runner/README.md: -------------------------------------------------------------------------------- 1 | # suave_runner 2 | 3 | ``` 4 | docker run -it --rm --gpus all --runtime=nvidia --name suave_runner -e DISPLAY=$DISPLAY -e QT_X11_NO_MITSHM=1 -e NVIDIA_VISIBLE_DEVICES=all -e NVIDIA_DRIVER_CAPABILITIES=all -v /dev/dri:/dev/dri -v /tmp/.X11-unix:/tmp/.X11-unix -v /etc/localtime:/etc/localtime:ro -v $HOME/suave_ws/src/suave:/home/ubuntu-user/suave_ws/src/suave suave_runner 5 | ``` 6 | 7 | ``` 8 | docker run -it --rm --gpus all --runtime=nvidia -e DISPLAY=$DISPLAY -e QT_X11_NO_MITSHM=1 -v /tmp/.X11-unix:/tmp/.X11-unix -v /etc/localtime:/etc/localtime:ro -v /home/gus/suave_ws/src/suave/:/home/ubuntu-user/suave_ws/src/suave suave_runner 9 | ``` 10 | 11 | 12 | ## Metacontrol 13 | ros2 run suave_runner suave_runner \ 14 | --ros-args \ 15 | -p gui:=True \ 16 | -p experiments:='[ 17 | "{\"experiment_launch\": \"ros2 launch suave_metacontrol suave_metacontrol.launch.py\", \ 18 | \"num_runs\": 1, \ 19 | \"adaptation_manager\": \"metacontrol\", \ 20 | \"mission_name\": \"suave\"}" 21 | ]' 22 | 23 | ## Behavior Tree 24 | ros2 run suave_runner suave_runner \ 25 | --ros-args \ 26 | -p gui:=False \ 27 | -p experiments:='[ 28 | "{\"experiment_launch\": \"ros2 launch suave_bt suave_bt.launch.py\", \ 29 | \"num_runs\": 2, \ 30 | \"adaptation_manager\": \"bt\", \ 31 | \"mission_name\": \"suave\"}" 32 | ]' 33 | 34 | ## Random 35 | 36 | ros2 run suave_runner suave_runner \ 37 | --ros-args \ 38 | -p gui:=False \ 39 | -p experiments:='[ 40 | "{\"experiment_launch\": \"ros2 launch suave_random suave_random.launch.py\", \ 41 | \"num_runs\": 2, \ 42 | \"adaptation_manager\": \"random\", \ 43 | \"mission_name\": \"suave\"}" 44 | ]' 45 | 46 | ## None 47 | 48 | ros2 run suave_runner suave_runner \ 49 | --ros-args \ 50 | -p gui:=False \ 51 | -p experiments:='[ 52 | "{\"experiment_launch\": \"ros2 launch suave_none suave_none.launch.py\", \ 53 | \"num_runs\": 2, \ 54 | \"adaptation_manager\": \"none\", \ 55 | \"mission_name\": \"suave\"}" 56 | ]' 57 | 58 | 59 | -------------------------------------------------------------------------------- /suave_runner/config/runner_config.yml: -------------------------------------------------------------------------------- 1 | /suave_runner_node: 2 | ros__parameters: 3 | gui: false #Enable GUI 4 | silent: true #Enable silent mode 5 | experiments: #List of experiments to run 6 | - | 7 | { 8 | "experiment_launch": "ros2 launch suave_bt suave_bt.launch.py", 9 | "num_runs": 2, 10 | "adaptation_manager": "bt", 11 | "mission_name": "suave" 12 | } 13 | - | 14 | { 15 | "experiment_launch": "ros2 launch suave_metacontrol suave_metacontrol.launch.py", 16 | "num_runs": 2, 17 | "adaptation_manager": "metacontrol", 18 | "mission_name": "suave" 19 | } 20 | - | 21 | { 22 | "experiment_launch": "ros2 launch suave_random suave_random.launch.py", 23 | "num_runs": 2, 24 | "adaptation_manager": "random", 25 | "mission_name": "suave" 26 | } 27 | - | 28 | { 29 | "experiment_launch": "ros2 launch suave_none suave_none.launch.py", 30 | "num_runs": 2, 31 | "adaptation_manager": "none", 32 | "mission_name": "suave" 33 | } -------------------------------------------------------------------------------- /suave_runner/docker/README.md: -------------------------------------------------------------------------------- 1 | ## Run docker image 2 | 3 | 4 | ### With GUI and nvidia 5 | 6 | ``` 7 | xhost +local:root # Allow Docker to access the X server 8 | ``` 9 | 10 | ``` 11 | docker run -it --rm \ 12 | --gpus all \ 13 | --runtime=nvidia \ 14 | -e DISPLAY=$DISPLAY \ 15 | -e QT_X11_NO_MITSHM=1 \ 16 | -v /tmp/.X11-unix:/tmp/.X11-unix \ 17 | suave_runner 18 | ``` 19 | 20 | -------------------------------------------------------------------------------- /suave_runner/docker/log/COLCON_IGNORE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_runner/docker/log/COLCON_IGNORE -------------------------------------------------------------------------------- /suave_runner/docker/log/latest: -------------------------------------------------------------------------------- 1 | latest_version-check -------------------------------------------------------------------------------- /suave_runner/docker/log/latest_version-check: -------------------------------------------------------------------------------- 1 | version-check_2025-05-13_13-47-21 -------------------------------------------------------------------------------- /suave_runner/launch/suave_runner_launch.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from launch import LaunchDescription 4 | from launch_ros.actions import Node 5 | from ament_index_python.packages import get_package_share_directory 6 | 7 | 8 | def generate_launch_description(): 9 | # Get the path to the config file 10 | config_path = os.path.join( 11 | get_package_share_directory('suave_runner'), 12 | 'config', 13 | 'runner_config.yml' 14 | ) 15 | 16 | # Launch the suave_runner node with the parameters loaded from YAML 17 | return LaunchDescription([ 18 | Node( 19 | package='suave_runner', 20 | executable='suave_runner', 21 | name='suave_runner_node', 22 | output='screen', 23 | parameters=[config_path], 24 | ) 25 | ]) 26 | -------------------------------------------------------------------------------- /suave_runner/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | suave_runner 6 | 0.0.0 7 | Runners for SUAVE 8 | 9 | Gustavo Rezende 10 | Gustavo Rezende 11 | 12 | Apache-2.0 13 | 14 | rclpy 15 | std_msgs 16 | 17 | 18 | ament_python 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /suave_runner/resource/suave_runner: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_runner/resource/suave_runner -------------------------------------------------------------------------------- /suave_runner/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/suave_runner 3 | [install] 4 | install_scripts=$base/lib/suave_runner 5 | -------------------------------------------------------------------------------- /suave_runner/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from glob import glob 3 | from setuptools import setup 4 | 5 | package_name = 'suave_runner' 6 | 7 | setup( 8 | name=package_name, 9 | version='0.0.0', 10 | packages=[package_name], 11 | data_files=[('share/ament_index/resource_index/packages', 12 | ['resource/' + package_name]), 13 | (os.path.join('share', package_name), ['package.xml']), 14 | (os.path.join('share', package_name, 15 | 'launch'), glob('launch/*launch.[pxy][yma]*')), 16 | (os.path.join('share', package_name, 17 | 'config'), glob('config/*'))], 18 | install_requires=['setuptools'], 19 | zip_safe=True, 20 | maintainer='Gustavo Rezende', 21 | maintainer_email='g.rezendesilva@tudelft.nl', 22 | description='TODO: Package description', 23 | license='Apache-2.0', 24 | tests_require=['pytest'], 25 | entry_points={ 26 | 'console_scripts': 27 | ['suave_runner = suave_runner.suave_runner:main'], 28 | }, 29 | ) 30 | -------------------------------------------------------------------------------- /suave_runner/suave_runner/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kas-lab/suave/46053412026eb148529e17dce8ba761411c574b7/suave_runner/suave_runner/__init__.py --------------------------------------------------------------------------------