diff --git a/.vscode/launch.json b/.vscode/launch.json
index a7a67622202f9301e3438db92694d8bb1f432cbd..11cac226602ba57aacc26388ea1ad648749121f2 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -6,17 +6,17 @@
     "configurations": [
         {
             "name": "Python: Train Start",
-            "type": "python",
+            "type": "debugpy",
             "request": "launch",
-            "program": "train/start_training.py",
+            "program": "app/train/start_training.py",
             "console": "integratedTerminal",
             "justMyCode": false
         },
         {
             "name": "Python: Train Navigation",
-            "type": "python",
+            "type": "debugpy",
             "request": "launch",
-            "program": "train/navigation_training.py",
+            "program": "app/train/navigation_training.py",
             "console": "integratedTerminal",
             "justMyCode": false
         }
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..6f4a528e8aefe95dcb0b4bdc94969eacde70fdc0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,26 @@
+# Installation
+## Create venv
+```sh
+virtualenv venv -p python3.11
+source venv/bin/activate
+```
+
+## Install pre requirements
+This step is necessary, as some packages have dependencies in their installation.
+```sh
+pip install -r pre-requirements0.txt
+pip install -r pre-requirements1.txt
+```
+
+## Install application
+```sh
+pip install .
+```
+
+## Install GPU requirements
+Execute this step only if you use a GPU
+```sh
+pip install -r gpu-requirements.txt
+```
+
+Using a GPU requires additional setup, which can be found in [this guide](https://git.420joos.dev/ai-projects/tf_setup).
diff --git a/__init__.py b/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/envs/BaseEnvironment.py b/app/envs/BaseEnvironment.py
similarity index 100%
rename from envs/BaseEnvironment.py
rename to app/envs/BaseEnvironment.py
diff --git a/envs/NavigationEnvironment.py b/app/envs/NavigationEnvironment.py
similarity index 100%
rename from envs/NavigationEnvironment.py
rename to app/envs/NavigationEnvironment.py
diff --git a/envs/StartEnvironment.py b/app/envs/StartEnvironment.py
similarity index 100%
rename from envs/StartEnvironment.py
rename to app/envs/StartEnvironment.py
diff --git a/envs/TestEnvironment.py b/app/envs/TestEnvironment.py
similarity index 100%
rename from envs/TestEnvironment.py
rename to app/envs/TestEnvironment.py
diff --git a/envs/__init__.py b/app/envs/__init__.py
similarity index 100%
rename from envs/__init__.py
rename to app/envs/__init__.py
diff --git a/envs/setup.py b/app/envs/setup.py
similarity index 100%
rename from envs/setup.py
rename to app/envs/setup.py
diff --git a/tests/starting_test.py b/app/tests/starting_test.py
similarity index 100%
rename from tests/starting_test.py
rename to app/tests/starting_test.py
diff --git a/train/navigation_training.py b/app/train/navigation_training.py
similarity index 99%
rename from train/navigation_training.py
rename to app/train/navigation_training.py
index 7c64781fa436734a8bbabc9bc647cc36ceb63100..1c1cd62dcab57753d4529bd5de7cf80f5b88f273 100644
--- a/train/navigation_training.py
+++ b/app/train/navigation_training.py
@@ -1,7 +1,5 @@
 from envs import NavigationEnvironment
 import train.utils as utils
-import airsim
-import numpy as np
 
 from tf_agents.environments.tf_py_environment import TFPyEnvironment
 from tf_agents.train.utils import train_utils
diff --git a/train/start_training.py b/app/train/start_training.py
similarity index 100%
rename from train/start_training.py
rename to app/train/start_training.py
diff --git a/train/utils.py b/app/train/utils.py
similarity index 100%
rename from train/utils.py
rename to app/train/utils.py
diff --git a/gpu-requirements.txt b/gpu-requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a6af284037be25aa56bd7ad4648a05a6db34e91b
--- /dev/null
+++ b/gpu-requirements.txt
@@ -0,0 +1 @@
+tensorflow[and-cuda]
diff --git a/pre-requirements.txt b/pre-requirements.txt
deleted file mode 100644
index 0863282905be439915e57a13506ce1a98055a34b..0000000000000000000000000000000000000000
--- a/pre-requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-numpy
-msgpack-rpc-python
diff --git a/pre-requirements0.txt b/pre-requirements0.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5ecdefef880adc70a1c8a42acb3f8b5afa9f751d
--- /dev/null
+++ b/pre-requirements0.txt
@@ -0,0 +1 @@
+setuptools>=70.0
diff --git a/pre-requirements1.txt b/pre-requirements1.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4c681f5ce1568982e898f019cb7666f251c1d014
--- /dev/null
+++ b/pre-requirements1.txt
@@ -0,0 +1,3 @@
+numpy<2.0.0
+wheel>=0.43
+msgpack-rpc-python
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000000000000000000000000000000000000..b95a379d861aad4788dfb0b6bd65c06f55df7559
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,31 @@
+[build-system]
+requires = ["setuptools >= 61.0"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "automated-drone"
+version = "1.0.0"
+dependencies = [
+    "numpy<2.0.0",
+    "airsim",
+    "tf-agents[reverb]==0.19.0", # Updating this may require an update of the gpu-requirements
+]
+requires-python = ">=3.9,<3.12"
+authors = [
+  {name = "Andri Joos"},
+]
+maintainers = [
+  {name = "Andri Joos"}
+]
+description = "Automate a drone with an unreal backend."
+readme = "README.md"
+
+[project.optional-dependencies]
+test = [
+    "pytest"
+]
+
+[tool.setuptools.packages.find]
+where = [
+    "app/"
+]
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index b60c19fb0b02dbb12c67c12aead7035da2ffc1d6..0000000000000000000000000000000000000000
--- a/requirements.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-pytest
-numpy
-tensorflow[and-cuda]
-airsim
-tf-agents
-tf-agents[reverb]