diff --git a/README.md b/README.md
index 73fcdd57..7a4d214e 100644
--- a/README.md
+++ b/README.md
@@ -72,7 +72,17 @@ In this scene,
-We will shortly add a [tutorial](https://github.com/KIT-MRT/arbitration_graphs/pull/51) based on this demo â stay tuned!
+## Tutorial
+
+Follow our [Tutorial](./docs/Tutorial.md) and learn how to use the Arbitration Graphs library!
+It's based on this demo and guides you through all important concepts:
+
+0. [Introduction â start here!](./docs/Tutorial.md)
+1. [Implement your first behavior component](./docs/tasks/1_implement_behavior_component.md)
+2. [Extend the arbitration graph with that behavior](./docs/tasks/2_extend_arbitration_graph.md)
+3. [Learn about nested arbitration graphs](./docs/tasks/3_nested_arbitrators.md)
+4. [Arbitrate based on predicted utility](./docs/tasks/4_cost_arbitration.md)
+5. [Verify commands and add a fallback strategy](./docs/tasks/5_verification.md)
## Installation
diff --git a/_config.yml b/_config.yml
index 100338af..b881b7a5 100644
--- a/_config.yml
+++ b/_config.yml
@@ -17,6 +17,8 @@ layouts_dir: docs/_layouts
sass:
sass_dir: docs/assets/_sass
+# This will be used as default HTML (sub)title
+tagline: decision-making for robotics
# Support collapsible details/summary sections
markdown: CommonMarkGhPages
diff --git a/demo/.devcontainer/.bashrc b/demo/.devcontainer/.bashrc
new file mode 100644
index 00000000..b8752c22
--- /dev/null
+++ b/demo/.devcontainer/.bashrc
@@ -0,0 +1,4 @@
+# start Starship prompt
+eval "$(starship init bash)"
+
+source /home/blinky/.motd
\ No newline at end of file
diff --git a/demo/.devcontainer/.zshrc b/demo/.devcontainer/.zshrc
new file mode 100644
index 00000000..5875b839
--- /dev/null
+++ b/demo/.devcontainer/.zshrc
@@ -0,0 +1,89 @@
+# >>> reference: https://carlosneto.dev/blog/2024/2024-02-08-starship-zsh/
+
+# list files with details
+alias ll="ls -larht"
+
+
+# set the locale of the shell
+export LANG="en_US.UTF-8"
+
+# define VSCode as the default text editor
+export EDITOR="code -w"
+
+# specify characters considered as word boundaries for command line navigation
+export WORDCHARS=""
+
+# set the location and filename of the history file
+export HISTFILE="$HOME/.zsh_history"
+
+# set the maximum number of lines to be saved in the history file
+export HISTSIZE="100000"
+export SAVEHIST="$HISTSIZE"
+
+# disable CTRL + S and CTRL + Q
+stty -ixon
+
+# enable comments "#" expressions in the prompt shell
+setopt INTERACTIVE_COMMENTS
+
+# append new history entries to the history file
+setopt APPEND_HISTORY
+
+# save each command to the history file as soon as it is executed
+setopt INC_APPEND_HISTORY
+
+# ignore recording duplicate consecutive commands in the history
+setopt HIST_IGNORE_DUPS
+
+# ignore commands that start with a space in the history
+setopt HIST_IGNORE_SPACE
+
+# >>> bindkey tip: to discovery the code of your keys, execute "$ cat -v" and press the key, the code will be printed in your shell.
+
+# use the ZLE (zsh line editor) in emacs mode. Useful to move the cursor in large commands
+bindkey -e
+
+# navigate words using Ctrl + arrow keys
+# >>> CRTL + right arrow | CRTL + left arrow
+bindkey "^[[1;5C" forward-word
+bindkey "^[[1;5D" backward-word
+
+# macosx override
+if [[ "$OSTYPE" == "darwin"* ]]; then
+ # >>> OPT + right arrow | OPT + left arrow
+ bindkey "^[^[[C" forward-word
+ bindkey "^[^[[D" backward-word
+fi
+
+# search history using Up and Down keys
+# >>> up arrow | down arrow
+bindkey "^[[A" history-beginning-search-backward
+bindkey "^[[B" history-beginning-search-forward
+
+# jump to the start and end of the command line
+# >>> CTRL + A | CTRL + E
+bindkey "^A" beginning-of-line
+bindkey "^E" end-of-line
+# >>> Home | End
+bindkey "^[[H" beginning-of-line
+bindkey "^[[F" end-of-line
+
+# navigate menu for command output
+zstyle ':completion:*:*:*:*:*' menu select
+bindkey '^[[Z' reverse-menu-complete
+
+# delete characters using the "delete" key
+bindkey "^[[3~" delete-char
+
+
+# >>> load ZSH plugin
+
+# enable kubectl plugin autocompletion
+autoload -Uz compinit
+compinit
+
+
+# start Starship prompt
+eval "$(starship init zsh)"
+
+source /home/blinky/.motd
\ No newline at end of file
diff --git a/demo/.devcontainer/Dockerfile b/demo/.devcontainer/Dockerfile
new file mode 100644
index 00000000..13eef83e
--- /dev/null
+++ b/demo/.devcontainer/Dockerfile
@@ -0,0 +1,26 @@
+ARG VERSION=latest
+
+FROM ghcr.io/kit-mrt/arbitration_graphs_pacman_tutorial:$VERSION
+
+USER root
+
+# Install clangd for the VSCode extension to work out of the box
+# Install zsh and tig as modern dev tools
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ clangd \
+ curl \
+ tig \
+ zsh && \
+ apt-get clean
+
+# Install and use starship terminal prompt
+RUN curl https://starship.rs/install.sh > /tmp/starship_install.sh && \
+ chmod +x /tmp/starship_install.sh && \
+ /tmp/starship_install.sh -y && \
+ rm /tmp/starship_install.sh
+
+COPY .devcontainer/.bashrc /home/blinky/.bashrc
+COPY .devcontainer/.zshrc /home/blinky/.zshrc
+
+USER blinky
diff --git a/demo/.devcontainer/devcontainer.json b/demo/.devcontainer/devcontainer.json
new file mode 100644
index 00000000..d83ac6f0
--- /dev/null
+++ b/demo/.devcontainer/devcontainer.json
@@ -0,0 +1,44 @@
+// For format details, see https://aka.ms/devcontainer.json. For config options, see the
+// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose
+{
+ "name": "Arbitration Graphs Tutorial",
+
+ // Update the 'dockerComposeFile' list if you have more compose files or use different names.
+ // The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
+ "dockerComposeFile": [
+ "../docker-compose.tutorial.yaml",
+ "docker-compose.yml"
+ ],
+
+ // The 'service' property is the name of the service for the container that VS Code should
+ // use. Update this value and .devcontainer/docker-compose.yml to the real service name.
+ "service": "tutorial",
+
+ // The optional 'workspaceFolder' property is the path VS Code should open by default when
+ // connected. This is typically a file mount in .devcontainer/docker-compose.yml
+ "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
+ "customizations": {
+ "vscode": {
+ // Install some useful VSCode C++ extensions
+ "extensions": [
+ "llvm-vs-code-extensions.vscode-clangd",
+ "vadimcn.vscode-lldb",
+ "matepek.vscode-catch2-test-adapter",
+ "twxs.cmake"
+ ],
+ "settings": {
+ // Use zsh as default terminal
+ "terminal.integrated.profiles.linux": {
+ "zsh": {
+ "path": "/bin/zsh",
+ "args": ["-l", "-i"]
+ }
+ },
+ "terminal.integrated.defaultProfile.linux": "zsh",
+
+ // Use system installation of clangd
+ "clangd.path": "clangd"
+ }
+ }
+ }
+}
diff --git a/demo/.devcontainer/docker-compose.yml b/demo/.devcontainer/docker-compose.yml
new file mode 100644
index 00000000..77fba341
--- /dev/null
+++ b/demo/.devcontainer/docker-compose.yml
@@ -0,0 +1,13 @@
+version: '3.8'
+services:
+ tutorial:
+ build:
+ context: .
+ dockerfile: .devcontainer/Dockerfile
+
+ volumes:
+ - ..:/workspaces:cached
+
+ # Overrides default command so things don't shut down after the process ends.
+ command: sleep infinity
+
diff --git a/demo/.gitignore b/demo/.gitignore
new file mode 100644
index 00000000..378eac25
--- /dev/null
+++ b/demo/.gitignore
@@ -0,0 +1 @@
+build
diff --git a/demo/.vscode/launch.json b/demo/.vscode/launch.json
new file mode 100644
index 00000000..df67280a
--- /dev/null
+++ b/demo/.vscode/launch.json
@@ -0,0 +1,18 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "lldb",
+ "request": "launch",
+ "name": "Debug Pacman Demo",
+ "program": "${workspaceFolder}/build/arbitration_graphs_pacman_demo",
+ "args": [],
+ "cwd": "${workspaceFolder}",
+ "initCommands":["settings set target.disable-aslr false"],
+ "console": "integratedTerminal"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/demo/.vscode/tasks.json b/demo/.vscode/tasks.json
new file mode 100644
index 00000000..d1bb4811
--- /dev/null
+++ b/demo/.vscode/tasks.json
@@ -0,0 +1,39 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Create build folder",
+ "type": "shell",
+ "command": "mkdir -p ${workspaceFolder}/build"
+ },
+ {
+ "label": "Configure debug build",
+ "type": "shell",
+ "command": "cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=true -S ${workspaceFolder} -B ${workspaceFolder}/build"
+ },
+ {
+ "label": "CMake build for debug",
+ "dependsOn": ["Create build folder", "Configure debug build"],
+ "type": "shell",
+ "command": "cmake --build ${workspaceFolder}/build -j9",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ }
+ },
+ {
+ "label": "Configure release build",
+ "dependsOn": ["Create build folder"],
+ "type": "shell",
+ "command": "cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=true -S ${workspaceFolder} -B ${workspaceFolder}/build"
+ },
+ {
+ "label": "CMake build for release",
+ "dependsOn": ["Create build folder", "Configure release build"],
+ "type": "shell",
+ "command": "cmake --build ${workspaceFolder}/build -j9"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt
index bbdc0040..87c3100d 100644
--- a/demo/CMakeLists.txt
+++ b/demo/CMakeLists.txt
@@ -59,23 +59,25 @@ find_package(Yaml-cpp REQUIRED)
## Build ##
###########
-add_library(${PROJECT_NAME} SHARED
+add_library(${PROJECT_NAME}_lib SHARED
src/astar.cpp
src/avoid_ghost_behavior.cpp
src/change_dot_cluster_behavior.cpp
src/chase_ghost_behavior.cpp
src/cost_estimator.cpp
src/cluster.cpp
+ src/eat_closest_dot_behavior.cpp
src/entities.cpp
src/environment_model.cpp
src/move_randomly_behavior.cpp
+ src/stay_in_place_behavior.cpp
src/utils.cpp
)
-target_include_directories(${PROJECT_NAME} PRIVATE
+target_include_directories(${PROJECT_NAME}_lib PRIVATE
include
${SDL2_INCLUDE_DIR}
)
-target_link_libraries(${PROJECT_NAME} PUBLIC
+target_link_libraries(${PROJECT_NAME}_lib PUBLIC
arbitration_graphs
glog::glog
@@ -86,16 +88,16 @@ target_link_libraries(${PROJECT_NAME} PUBLIC
${SDL2_LIBRARY}
)
-add_executable(${PROJECT_NAME}_exe
+add_executable(${PROJECT_NAME}
src/main.cpp
src/pacman_wrapper.cpp
)
-target_include_directories(${PROJECT_NAME}_exe PRIVATE
+target_include_directories(${PROJECT_NAME} PRIVATE
include
${SDL2_INCLUDE_DIR}
)
-target_link_libraries(${PROJECT_NAME}_exe PRIVATE
- ${PROJECT_NAME}
+target_link_libraries(${PROJECT_NAME} PRIVATE
+ ${PROJECT_NAME}_lib
)
@@ -133,7 +135,7 @@ endif()
## Install ##
#############
-install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_exe
+install(TARGETS ${PROJECT_NAME}_lib ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}Targets
COMPONENT demo
LIBRARY DESTINATION lib COMPONENT Runtime
diff --git a/demo/Dockerfile b/demo/Dockerfile
index 2f9e68ba..89018980 100644
--- a/demo/Dockerfile
+++ b/demo/Dockerfile
@@ -61,5 +61,5 @@ WORKDIR /home/blinky/demo/build
RUN cmake -DCMAKE_BUILD_TYPE=Release .. && \
cmake --build . -j8
-CMD ["bash", "-c", "/home/blinky/.motd && /home/blinky/demo/build/arbitration_graphs_pacman_demo_exe"]
+CMD ["bash", "-c", "/home/blinky/.motd && /home/blinky/demo/build/arbitration_graphs_pacman_demo"]
diff --git a/demo/README.md b/demo/README.md
new file mode 100644
index 00000000..ff88224c
--- /dev/null
+++ b/demo/README.md
@@ -0,0 +1,31 @@
+# Arbitration Graphs Demo and Tutorial
+
+This is a demo of the [arbitration_graphs](https://github.com/KIT-MRT/arbitration_graphs) library using Pac-Man as an example application.
+The arbitration graph controls Pac-Man on its journey to collect tasty dots đŦ
+
+Run the demo with:
+
+```bash
+git clone https://github.com/KIT-MRT/arbitration_graphs.git
+cd arbitration_graphs/demo
+docker compose up
+```
+
+Open the GUI with your favorite browser:
+[http://0.0.0.0:8080](http://0.0.0.0:8080)
+
+
+## Tutorial
+
+If you're here for the tutorial, follow the instructions on our [Tutorial GitHub Page](https://kit-mrt.github.io/arbitration_graphs/docs/Tutorial.md).
+
+For a smooth out-of-the-box experience, we recommend using [Visual Studio Code](https://code.visualstudio.com/) with our DevContainer setup.
+
+- Open this folder in VSCode
+- Build and open the Dev Container by running this [command](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) (use `Ctrl+Shift+P`):
+ `Dev Containers: Reopen in Container`
+- Enjoy a full-blown IDE with code-completion, code-navigation etc.
+ - Compile via `Ctrl+Shift+B`
+ - View, run and debug unit tests via [Testing](https://code.visualstudio.com/docs/editor/testing) sidebar
+ - Debug the Pac-Man Demo via [Run and Debug](https://code.visualstudio.com/docs/editor/debugging) sidebar
+ - Debug with breakpoints etc.
\ No newline at end of file
diff --git a/demo/docker-compose.tutorial.yaml b/demo/docker-compose.tutorial.yaml
new file mode 100644
index 00000000..8bf2b966
--- /dev/null
+++ b/demo/docker-compose.tutorial.yaml
@@ -0,0 +1,13 @@
+services:
+ tutorial:
+ image: ghcr.io/kit-mrt/arbitration_graphs_pacman_tutorial:$VERSION
+ env_file: .env
+ ports:
+ - "8080:8080"
+ volumes:
+ - .:/home/blinky/demo
+ - $HOME/.Xauthority:/home/blinky/.Xauthority
+ - /tmp/.X11-unix:/tmp/.X11-unix
+ environment:
+ - DISPLAY=$DISPLAY
+
diff --git a/demo/docker-compose.yaml b/demo/docker-compose.yaml
index f18bde66..f7193356 100644
--- a/demo/docker-compose.yaml
+++ b/demo/docker-compose.yaml
@@ -1,15 +1,8 @@
services:
tutorial:
- image: ghcr.io/kit-mrt/arbitration_graphs_pacman_tutorial:$VERSION
- env_file: .env
- ports:
- - "8080:8080"
- volumes:
- - .:/home/blinky/demo
- - $HOME/.Xauthority:/home/blinky/.Xauthority
- - /tmp/.X11-unix:/tmp/.X11-unix
- environment:
- - DISPLAY=$DISPLAY
+ extends:
+ file: docker-compose.tutorial.yaml
+ service: tutorial
#
# This makes sure `docker compose up` only runs the demo service
# Use `docker compose run --rm --service-ports tutorial` to run the tutorial
diff --git a/demo/include/demo/avoid_ghost_behavior.hpp b/demo/include/demo/avoid_ghost_behavior.hpp
index 23c68548..0d083af5 100644
--- a/demo/include/demo/avoid_ghost_behavior.hpp
+++ b/demo/include/demo/avoid_ghost_behavior.hpp
@@ -24,9 +24,9 @@ class AvoidGhostBehavior : public arbitration_graphs::Behavior {
double commitmentMinDistance{7};
};
- AvoidGhostBehavior(EnvironmentModel::Ptr environmentModel,
- const Parameters& parameters,
- const std::string& name = "AvoidGhost")
+ explicit AvoidGhostBehavior(EnvironmentModel::Ptr environmentModel,
+ const Parameters& parameters,
+ const std::string& name = "AvoidGhost")
: Behavior(name), environmentModel_{std::move(environmentModel)}, parameters_{parameters} {
}
diff --git a/demo/include/demo/chase_ghost_behavior.hpp b/demo/include/demo/chase_ghost_behavior.hpp
index f1fde928..ce11321e 100644
--- a/demo/include/demo/chase_ghost_behavior.hpp
+++ b/demo/include/demo/chase_ghost_behavior.hpp
@@ -25,9 +25,9 @@ class ChaseGhostBehavior : public arbitration_graphs::Behavior {
int minScaredTicksLeft{5};
};
- ChaseGhostBehavior(EnvironmentModel::Ptr environmentModel,
- const Parameters& parameters,
- const std::string& name = "ChaseGhost")
+ explicit ChaseGhostBehavior(EnvironmentModel::Ptr environmentModel,
+ const Parameters& parameters,
+ const std::string& name = "ChaseGhost")
: Behavior(name), environmentModel_{std::move(environmentModel)}, parameters_{parameters} {
}
diff --git a/demo/include/demo/eat_closest_dot_behavior.hpp b/demo/include/demo/eat_closest_dot_behavior.hpp
index 41884012..6d8a5ee1 100644
--- a/demo/include/demo/eat_closest_dot_behavior.hpp
+++ b/demo/include/demo/eat_closest_dot_behavior.hpp
@@ -19,27 +19,10 @@ class EatClosestDotBehavior : public arbitration_graphs::Behavior {
: Behavior(name), environmentModel_{std::move(environmentModel)} {
}
- Command getCommand(const Time& /*time*/) override {
- auto pacmanPosition = environmentModel_->pacmanPosition();
- std::optional pathToClosestDot = environmentModel_->pathToClosestDot(pacmanPosition);
+ Command getCommand(const Time& /*time*/) override;
- if (!pathToClosestDot) {
- throw std::runtime_error("Failed to compute path to closest dot. Can not provide a sensible command.");
- }
-
- return Command{pathToClosestDot.value()};
- }
-
- bool checkInvocationCondition(const Time& /*time*/) const override {
- // This behavior is only applicable if there is at least one dot. We should check for the presence of a dot
- // here, but since the game is won when all dots are collected, we assume at least one dot exists when this
- // behavior is invoked.
- return true;
- }
-
- bool checkCommitmentCondition(const Time& /*time*/) const override {
- return false;
- }
+ bool checkInvocationCondition(const Time& /*time*/) const override;
+ bool checkCommitmentCondition(const Time& /*time*/) const override;
private:
EnvironmentModel::Ptr environmentModel_;
diff --git a/demo/include/demo/move_randomly_behavior.hpp b/demo/include/demo/move_randomly_behavior.hpp
index 7510de6c..a8e40eb4 100644
--- a/demo/include/demo/move_randomly_behavior.hpp
+++ b/demo/include/demo/move_randomly_behavior.hpp
@@ -29,24 +29,13 @@ class MoveRandomlyBehavior : public arbitration_graphs::Behavior {
Command getCommand(const Time& time) override;
- bool checkInvocationCondition(const Time& time) const override {
- return true;
- }
- bool checkCommitmentCondition(const Time& time) const override {
- return false;
- }
-
- void gainControl(const Time& time) override {
- gainedControlAt_ = time;
- }
- void loseControl(const Time& time) override {
- }
+ bool checkInvocationCondition(const Time& /*time*/) const override;
+ bool checkCommitmentCondition(const Time& /*time*/) const override;
private:
Direction selectRandomDirection();
util_caching::Cache