├── controller_settings ├── __init__.py └── set_location.py ├── requirements.txt ├── setup.py ├── LICENSE ├── drone_settings ├── drone2_settings.py ├── drone1_settings.py ├── drone3_settings.py └── drone4_settings.py ├── bootstrap-dev.sh ├── .gitignore ├── README.md └── init.sh /controller_settings/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | -e git+https://github.com/andrejsab/hydra-py.git#egg=hydra 2 | -e git+https://github.com/HTTP-APIs/hydrus.git#egg=hydrus 3 | -e git+https://github.com/HTTP-APIs/hydra-flock-central-controller.git#egg=flock_controller 4 | -------------------------------------------------------------------------------- /controller_settings/set_location.py: -------------------------------------------------------------------------------- 1 | from flock_controller.mechanics.location import gen_Location, add_location 2 | 3 | def main(): 4 | """Set initial location of the central controller.""" 5 | location = gen_Location("0.856901647439813,14.08447265625") 6 | add_location(location) 7 | 8 | 9 | if __name__ == "__main__": 10 | main() 11 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | 5 | setup(name='hydra-flock-demo', 6 | version='0.0.1', 7 | description='A simulation for HYDRA: flying a flock of commercial drones', 8 | author='Hydra Ecosystem', 9 | author_email='collective@hydraecosystem.org', 10 | url='https://github.com/HTTP-APIs/hydra-flock-demo', 11 | # install_requires=['-e git+git://github.com/HTTP-APIs/hydra-flock-central-controller.git', 12 | # '-e git+git://github.com/HTTP-APIs/hydra-flock-drone.git'], 13 | packages=[ 14 | 'flock_controller', 'flock_drone' 15 | ], 16 | package_dir={ 17 | 'flock_controller': 'flock_controller', 18 | 'flock_drone': 'flock_drone'}, 19 | ) 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /drone_settings/drone2_settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | ## Using sqlite as database 4 | global DB_URL 5 | db_path = os.path.join(os.path.dirname(__file__), 'database.db') 6 | DB_URL = 'sqlite:///{}'.format(db_path) 7 | 8 | 9 | global HYDRUS_SERVER_URL, PORT, API_NAME 10 | HYDRUS_SERVER_URL = "http://localhost:8082/" 11 | PORT = 8082 12 | API_NAME = "api" 13 | 14 | 15 | ## Drone configuration 16 | global CENTRAL_SERVER_NAMESPACE, DRONE_NAMESPACE 17 | CENTRAL_SERVER_NAMESPACE = "http://localhost:8080/api/vocab#" 18 | DRONE_NAMESPACE = "http://localhost:8082/api/vocab#" 19 | 20 | global DRONE_URL, CENTRAL_SERVER_URL 21 | DRONE_URL = "http://localhost:8082" 22 | CENTRAL_SERVER_URL = "http://localhost:8080" 23 | 24 | global IRI_CS, IRI_DRONE 25 | IRI_CS = "http://localhost:8080/api" 26 | IRI_DRONE = "http://localhost:8082/api" 27 | 28 | # Default drone object with DroneID -1000 for initialization. 29 | # Speed and MaxSpeeds are in Km/h""" 30 | DRONE_DEFAULT = { 31 | "@type": "Drone", 32 | "DroneID": "-1000", 33 | "name": "Drone 2", 34 | "model": "xyz", 35 | "MaxSpeed": "250", 36 | "Sensor": "Temperature", 37 | "State": { 38 | "@type": "State", 39 | "Speed": "90", 40 | "Position": "0,0", 41 | "Battery": "100", 42 | "Direction": "E", 43 | "Status": "Active", 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /drone_settings/drone1_settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | ## Using sqlite as database 4 | global DB_URL 5 | db_path = os.path.join(os.path.dirname(__file__), 'database.db') 6 | DB_URL = 'sqlite:///{}'.format(db_path) 7 | 8 | 9 | global HYDRUS_SERVER_URL, PORT, API_NAME 10 | HYDRUS_SERVER_URL = "http://localhost:8081/" 11 | PORT = 8081 12 | API_NAME = "api" 13 | 14 | 15 | ## Drone configuration 16 | global CENTRAL_SERVER_NAMESPACE, DRONE_NAMESPACE 17 | CENTRAL_SERVER_NAMESPACE = "http://localhost:8080/api/vocab#" 18 | DRONE_NAMESPACE = "http://localhost:8081/api/vocab#" 19 | 20 | global DRONE_URL, CENTRAL_SERVER_URL 21 | DRONE_URL = "http://localhost:8081" 22 | CENTRAL_SERVER_URL = "http://localhost:8080" 23 | 24 | global IRI_CS, IRI_DRONE 25 | IRI_CS = "http://localhost:8080/api" 26 | IRI_DRONE = "http://localhost:8081/api" 27 | 28 | # Default drone object with DroneID -1000 for initialization. 29 | # Speed and MaxSpeeds are in Km/h""" 30 | DRONE_DEFAULT = { 31 | "@type": "Drone", 32 | "DroneID": "-1000", 33 | "name": "Drone 1", 34 | "model": "xyz", 35 | "MaxSpeed": "300", 36 | "Sensor": "Temperature", 37 | "State": { 38 | "@type": "State", 39 | "Speed": "100", 40 | "Position": "0,0", 41 | "Battery": "100", 42 | "Direction": "N", 43 | "Status": "Active", 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /drone_settings/drone3_settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | ## Using sqlite as database 4 | global DB_URL 5 | db_path = os.path.join(os.path.dirname(__file__), 'database.db') 6 | DB_URL = 'sqlite:///{}'.format(db_path) 7 | 8 | 9 | global HYDRUS_SERVER_URL, PORT, API_NAME 10 | HYDRUS_SERVER_URL = "http://localhost:8083/" 11 | PORT = 8083 12 | API_NAME = "api" 13 | 14 | 15 | ## Drone configuration 16 | global CENTRAL_SERVER_NAMESPACE, DRONE_NAMESPACE 17 | CENTRAL_SERVER_NAMESPACE = "http://localhost:8080/api/vocab#" 18 | DRONE_NAMESPACE = "http://localhost:8083/api/vocab#" 19 | 20 | global DRONE_URL, CENTRAL_SERVER_URL 21 | DRONE_URL = "http://localhost:8083" 22 | CENTRAL_SERVER_URL = "http://localhost:8080" 23 | 24 | global IRI_CS, IRI_DRONE 25 | IRI_CS = "http://localhost:8080/api" 26 | IRI_DRONE = "http://localhost:8083/api" 27 | 28 | # Default drone object with DroneID -1000 for initialization. 29 | # Speed and MaxSpeeds are in Km/h""" 30 | DRONE_DEFAULT = { 31 | "@type": "Drone", 32 | "DroneID": "-1000", 33 | "name": "Drone 3", 34 | "model": "xyz", 35 | "MaxSpeed": "200", 36 | "Sensor": "Temperature", 37 | "State": { 38 | "@type": "State", 39 | "Speed": "120", 40 | "Position": "0,0", 41 | "Battery": "100", 42 | "Direction": "S", 43 | "Status": "Active", 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /drone_settings/drone4_settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | ## Using sqlite as database 4 | global DB_URL 5 | db_path = os.path.join(os.path.dirname(__file__), 'database.db') 6 | DB_URL = 'sqlite:///{}'.format(db_path) 7 | 8 | 9 | global HYDRUS_SERVER_URL, PORT, API_NAME 10 | HYDRUS_SERVER_URL = "http://localhost:8084/" 11 | PORT = 8084 12 | API_NAME = "api" 13 | 14 | 15 | ## Drone configuration 16 | global CENTRAL_SERVER_NAMESPACE, DRONE_NAMESPACE 17 | CENTRAL_SERVER_NAMESPACE = "http://localhost:8080/api/vocab#" 18 | DRONE_NAMESPACE = "http://localhost:8084/api/vocab#" 19 | 20 | global DRONE_URL, CENTRAL_SERVER_URL 21 | DRONE_URL = "http://localhost:8084" 22 | CENTRAL_SERVER_URL = "http://localhost:8080" 23 | 24 | global IRI_CS, IRI_DRONE 25 | IRI_CS = "http://localhost:8080/api" 26 | IRI_DRONE = "http://localhost:8084/api" 27 | 28 | # Default drone object with DroneID -1000 for initialization. 29 | # Speed and MaxSpeeds are in Km/h""" 30 | DRONE_DEFAULT = { 31 | "@type": "Drone", 32 | "DroneID": "-1000", 33 | "name": "Drone 4", 34 | "model": "xyz", 35 | "MaxSpeed": "275", 36 | "Sensor": "Temperature", 37 | "State": { 38 | "@type": "State", 39 | "Speed": "100", 40 | "Position": "0,0", 41 | "Battery": "100", 42 | "Direction": "W", 43 | "Status": "Active", 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /bootstrap-dev.sh: -------------------------------------------------------------------------------- 1 | echo "Removing directories if exist" 2 | rm -rf hydrus sim_controller sim_gui sim_drone1 sim_drone2 sim_drone3 sim_drone4 3 | 4 | echo "Install requirements..." 5 | pip install -r requirements.txt 6 | # 7 | 8 | git clone --single-branch https://github.com/HTTP-APIs/hydra-flock-central-controller.git sim_controller 9 | git clone --single-branch https://github.com/HTTP-APIs/hydra-flock-gui.git sim_gui 10 | 11 | # Drone1 12 | git clone --single-branch https://github.com/HTTP-APIs/hydra-flock-drone.git sim_drone1 13 | # Drone2 14 | git clone --single-branch https://github.com/HTTP-APIs/hydra-flock-drone.git sim_drone2 15 | # Drone3 16 | git clone --single-branch https://github.com/HTTP-APIs/hydra-flock-drone.git sim_drone3 17 | # Drone4 18 | git clone --single-branch https://github.com/HTTP-APIs/hydra-flock-drone.git sim_drone4 19 | 20 | ## Updating drone settings 21 | echo "Updating drone settings" 22 | cp drone_settings/drone1_settings.py sim_drone1/flock_drone/settings.py 23 | cp drone_settings/drone2_settings.py sim_drone2/flock_drone/settings.py 24 | cp drone_settings/drone3_settings.py sim_drone3/flock_drone/settings.py 25 | cp drone_settings/drone4_settings.py sim_drone4/flock_drone/settings.py 26 | echo "Done!" 27 | 28 | echo "Generating new docs" 29 | python -m sim_drone1.flock_drone.api_docs.doc_gen 30 | python -m sim_drone2.flock_drone.api_docs.doc_gen 31 | python -m sim_drone3.flock_drone.api_docs.doc_gen 32 | python -m sim_drone4.flock_drone.api_docs.doc_gen 33 | echo "Done!" 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | .idea/ 104 | 105 | src/ 106 | hydrus/ 107 | sim_controller/ 108 | sim_drone/ 109 | sim_drone1/ 110 | sim_drone2/ 111 | sim_drone3/ 112 | sim_drone4/ 113 | sim_gui/ 114 | 115 | # Db files 116 | *.db 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Forestry Patrol Simulation Demo using [Hydrus](https://github.com/HTTP-APIs/hydrus/) and [Hydra-py](https://github.com/pchampin/hydra-py) 2 | An application that simulates the movements of a flock of drones that have as objective to detect the presence of fires or abnormal heat spots in a given geographical area using an infrared sensors. 3 | 4 | 5 | ## How to run the Simulation: 6 | * create and activate a new virtualenv 7 | * upgrade pip and setuptools 8 | * check if `python3-dev` is installed 9 | * `chmod +x bootstrap-dev.sh` 10 | * `./bootstrap-dev.sh` 11 | * `chmod +x init.sh` 12 | * `./init.sh` 13 | 14 | ### Simulation GUI should be available at http://127.0.0.1:5000/ 15 | 16 | #### Central Controller should be available at http://127.0.0.1:8080/api 17 | #### Drones should be available at 18 | - **Drone 1 - http://127.0.0.1:8081/api** 19 | - **Drone 2 - http://127.0.0.1:8082/api** 20 | - **Drone 3 - http://127.0.0.1:8083/api** 21 | - **Drone 4 - http://127.0.0.1:8084/api** 22 | 23 | ## **NOTE**: To stop all simulation processes use `killall python` 24 | Different components are cloned from their repositories and run locally on different ports. 25 | 26 | ## Interacting with the simulation 27 | The user can interact with the simulation from the simulation GUI. He can submit messages in structured format to the central controller, the central controller will then parse the submitted message and issue commands to respective drones. Progress can be seen in controller and drone logs in the GUI. 28 | 29 | **Some Examples** 30 | - `Set Drone 2 speed 100` (Change the speed of drone with id 2 to 100 Km/h.) 31 | - `Set Drone 8 direction N` (Change the direction of drone with id 8 to North.) 32 | - `Set Drone 13 status off` (Turn drone with id 13 off.) 33 | - `Set Drone 8 status active` (Turn drone with id 8 on.) 34 | 35 | ### For design principles and other details please read the [Wiki](https://github.com/HTTP-APIs/hydra-flock-demo/wiki) 36 | -------------------------------------------------------------------------------- /init.sh: -------------------------------------------------------------------------------- 1 | echo "Starting Simulation Central Controller" 2 | cd sim_controller 3 | python -m flock_controller.main & 4 | cd ../ 5 | echo "Central Controller started successfully!" 6 | 7 | ## Wait for 8 seconds. 8 | /bin/sleep 8 9 | 10 | 11 | echo "Initializing Central Controller Location" 12 | python -m controller_settings.set_location 13 | 14 | ## Wait for 2 seconds 15 | /bin/sleep 2 16 | 17 | 18 | echo "Starting Drone1" 19 | cd sim_drone1 20 | python -m flock_drone.main & 21 | cd ../ 22 | echo "Drone1 successfully started!" 23 | 24 | echo "Starting Drone2" 25 | cd sim_drone2 26 | python -m flock_drone.main & 27 | cd ../ 28 | echo "Drone2 successfully started!" 29 | 30 | echo "Starting Drone3" 31 | cd sim_drone3 32 | python -m flock_drone.main & 33 | cd ../ 34 | echo "Drone3 successfully started!" 35 | 36 | echo "Starting Drone4" 37 | cd sim_drone4 38 | python -m flock_drone.main & 39 | cd ../ 40 | echo "Drone4 successfully started!" 41 | 42 | 43 | echo "Starting Simulation GUI" 44 | cd sim_gui 45 | python app.py & 46 | cd ../ 47 | echo "Simulation GUI started successfully" 48 | 49 | ## Wait for 8 seconds. 50 | /bin/sleep 8 51 | 52 | echo "Initializing Drone1" 53 | cd sim_drone1 54 | python -m flock_drone.mechanics.drone_init 55 | cd ../ 56 | /bin/sleep 2 57 | 58 | echo "Initializing Drone2" 59 | cd sim_drone2 60 | python -m flock_drone.mechanics.drone_init 61 | cd ../ 62 | /bin/sleep 2 63 | 64 | echo "Initializing Drone3" 65 | cd sim_drone3 66 | python -m flock_drone.mechanics.drone_init 67 | cd ../ 68 | /bin/sleep 2 69 | 70 | echo "Initializing Drone4" 71 | cd sim_drone4 72 | python -m flock_drone.mechanics.drone_init 73 | cd ../ 74 | /bin/sleep 2 75 | 76 | ## Wait for 8 seconds. 77 | /bin/sleep 8 78 | 79 | echo "Starting Drone1 main mechanics Loop" 80 | cd sim_drone1 81 | python -m flock_drone.mechanics.simulate & 82 | cd ../ 83 | 84 | echo "Starting Drone2 main mechanics Loop" 85 | cd sim_drone2 86 | python -m flock_drone.mechanics.simulate & 87 | cd ../ 88 | 89 | echo "Starting Drone3 main mechanics Loop" 90 | cd sim_drone3 91 | python -m flock_drone.mechanics.simulate & 92 | cd ../ 93 | 94 | echo "Starting Drone4 main mechanics Loop" 95 | cd sim_drone4 96 | python -m flock_drone.mechanics.simulate & 97 | cd ../ 98 | 99 | /bin/sleep 8 100 | echo "Starting Central Controller main mechanics Loop" 101 | cd sim_controller 102 | python -m flock_controller.mechanics.simulate & 103 | cd ../ 104 | --------------------------------------------------------------------------------