diff --git a/ros3rag.coordinator/.gitignore b/ros3rag.coordinator/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..87b4cdd3d7c6a41502ca98703abeeb69a1d536fb
--- /dev/null
+++ b/ros3rag.coordinator/.gitignore
@@ -0,0 +1,5 @@
+build
+src/gen-res/
+src/gen/
+out/
+*.class
diff --git a/ros3rag.coordinator/build.gradle b/ros3rag.coordinator/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..3b03cd87dc7084cfa0ab5df80615c94bff662b6d
--- /dev/null
+++ b/ros3rag.coordinator/build.gradle
@@ -0,0 +1,159 @@
+buildscript {
+    repositories.mavenCentral()
+    dependencies {
+        classpath group: 'org.jastadd', name: 'jastaddgradle', version: '1.13.3'
+    }
+}
+
+plugins {
+    id 'ros3rag.java-application-conventions'
+    id 'ros3rag.java-ragconnect-conventions'
+}
+
+mainClassName = 'de.tudresden.inf.st.coordinator.MainCoordinator'
+
+dependencies {
+}
+
+ext.ragConnectInputGrammar = 'src/main/jastadd/Coordinator.relast'
+ext.ragConnectInputConnect = 'src/main/jastadd/Coordinator.connect'
+ext.ragConnectRootNode = 'Coordinator'
+ext.relastFiles = ["src/gen/jastadd/Coordinator.relast", "src/gen/jastadd/RagConnect.relast"]
+ext.jastaddAstPackage = 'de.tudresden.inf.st.coordinator.ast'
+
+
+apply plugin: 'jastadd'
+
+dependencies {
+//    jastadd2 "org.jastadd:jastadd:2.3.5"
+    jastadd2 fileTree(include: ['jastadd2.jar'], dir: '../libs')
+    api group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15'
+
+}
+
+sourceCompatibility = 11
+targetCompatibility = 11
+
+// phases: ragConnect -> RelAst -> JastAdd
+// phase: ragConnect
+task ragConnect(type: JavaExec) {
+    group = 'Build'
+    main = 'org.jastadd.ragconnect.compiler.Compiler'
+    classpath = configurations.ragconnectClasspath
+
+    args([
+            '--o=src/gen/jastadd',
+            project.ext.ragConnectInputGrammar,
+            project.ext.ragConnectInputConnect,
+            '--logReads',
+            '--logWrites',
+//            '--verbose',
+            '--rootNode=' + project.ext.ragConnectRootNode,
+            '--incremental=param',
+            "--tracing=cache,flush"
+    ])
+
+}
+
+// Input files for relast
+//def relastFiles = ["src/gen/jastadd/MinimalModel.relast", "src/gen/jastadd/RagConnect.relast"]
+
+task grammar2uml(type: JavaExec) {
+    main = 'de.tudresden.inf.st.jastadd.grammar2uml.compiler.Compiler'
+    classpath = configurations.grammar2umlClasspath
+
+    args([
+            '--verbose',
+            'src/gen/jastadd/types.relast'
+    ] + project.ext.relastFiles)
+}
+
+// phase: RelAst
+task relastToJastAdd(type: JavaExec) {
+    group = 'Build'
+    main = "-jar"
+
+    args(["../libs/relast.jar",
+          "--grammarName=./src/gen/jastadd/model",
+          "--useJastAddNames",
+          "--listClass=java.util.ArrayList",
+          "--jastAddList=JastAddList",
+          "--serializer=jackson",
+          "--resolverHelper",
+          "--file",
+          "src/gen/jastadd/types.relast"
+    ] + project.ext.relastFiles)
+
+    inputs.files project.ext.relastFiles + ['src/gen/jastadd/types.relast']
+    outputs.files file("./src/gen/jastadd/model.ast"), file("./src/gen/jastadd/model.jadd")
+}
+
+// phase: JastAdd
+jastadd {
+    configureModuleBuild()
+    modules {
+        //noinspection GroovyAssignabilityCheck
+        module("coordinator") {
+
+//            java {
+//                basedir "src/"
+//                include "main/**/*.java"
+//                include "gen/**/*.java"
+//            }
+
+            jastadd {
+                basedir "src/"
+                include "main/jastadd/**/*.ast"
+                include "main/jastadd/**/*.jadd"
+                include "main/jastadd/**/*.jrag"
+                include "gen/jastadd/**/*.ast"
+                include "gen/jastadd/**/*.jadd"
+                include "gen/jastadd/**/*.jrag"
+            }
+            scanner {
+                include "src/main/jastadd/Coordinator.flex"
+            }
+
+            parser {
+                include "src/main/jastadd/Coordinator.parser"
+            }
+        }
+    }
+
+    cleanGen.doFirst {
+        delete "src/gen/java/de"
+        delete "src/gen-res/BuildInfo.properties"
+    }
+
+    module = "coordinator"
+
+    astPackage = project.ext.jastaddAstPackage
+
+    genDir = 'src/gen/java'
+
+    buildInfoDir = 'src/gen-res'
+
+    parser.name = 'CoordinatorParser'
+
+    scanner.genDir = "src/gen/java/de/tudresden/inf/st/coordinator/scanner"
+    parser.genDir = "src/gen/java/de/tudresden/inf/st/coordinator/parser"
+
+    // jastaddOptions = ["--lineColumnNumbers", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
+    // default options are: '--rewrite=cnta', '--safeLazy', '--visitCheck=false', '--cacheCycle=false'
+    extraJastAddOptions = [
+            '--lineColumnNumbers',
+            '--List=JastAddList',
+            '--cache=all',
+            "--flush=api",
+            "--incremental=param,debug",
+            "--tracing=cache,flush",
+    ]
+}
+
+cleanGen.doFirst {
+    delete "src/gen/jastadd"
+}
+
+// Workflow configuration for phases
+generateAst.dependsOn relastToJastAdd
+relastToJastAdd.dependsOn ragConnect
diff --git a/ros3rag.coordinator/src/main/jastadd/Coordinator.connect b/ros3rag.coordinator/src/main/jastadd/Coordinator.connect
new file mode 100644
index 0000000000000000000000000000000000000000..d7bca5d0925174df4c372f77c2f155fd7abdee94
--- /dev/null
+++ b/ros3rag.coordinator/src/main/jastadd/Coordinator.connect
@@ -0,0 +1,15 @@
+receive Component.IncomingStatus ;
+//send tree Coordinator.NextComponentToStart using NameOfComponent ;
+//
+//NameOfComponent maps Component c to String {:
+//  return c.getName();
+//:}
+
+send Component.NextCommand using CommandCheck ;
+
+CommandCheck maps String command to String {:
+  if (command == null) {
+    reject();
+  }
+  return command;
+:}
diff --git a/ros3rag.coordinator/src/main/jastadd/Coordinator.flex b/ros3rag.coordinator/src/main/jastadd/Coordinator.flex
new file mode 100644
index 0000000000000000000000000000000000000000..39f328d99e5c3dd0f7a151adef8c3b43d5b29fad
--- /dev/null
+++ b/ros3rag.coordinator/src/main/jastadd/Coordinator.flex
@@ -0,0 +1,65 @@
+package de.tudresden.inf.st.coordinator.scanner;
+
+import de.tudresden.inf.st.coordinator.parser.CoordinatorParser.Terminals;
+
+%%
+
+// define the signature for the generated scanner
+%public
+%final
+%class CoordinatorScanner
+%extends beaver.Scanner
+
+// the interface between the scanner and the parser is the nextToken() method
+%type beaver.Symbol
+%function nextToken
+%yylexthrow beaver.Scanner.Exception
+
+// store line and column information in the tokens
+%line
+%column
+
+// this code will be inlined in the body of the generated scanner class
+%{
+  private beaver.Symbol sym(short id) {
+    return new beaver.Symbol(id, yyline + 1, yycolumn + 1, yylength(), yytext());
+  }
+  private beaver.Symbol symText(short id) {
+    return new beaver.Symbol(id, yyline + 1, yycolumn + 1, yylength(), yytext().substring(1, yytext().length() - 1));
+  }
+%}
+
+WhiteSpace = [ ] | \t | \f | \n | \r | \r\n
+//Identifier = [:jletter:][:jletterdigit:]*
+Text = \" ([^\"]*) \"
+
+//Integer = [:digit:]+ // | "+" [:digit:]+ | "-" [:digit:]+
+//Real    = [:digit:]+ "." [:digit:]* | "." [:digit:]+
+
+Comment = "//" [^\n\r]+
+
+%%
+
+// discard whitespace information and comments
+{WhiteSpace}  { }
+{Comment}     { }
+
+// ** token definitions **
+// Begin of line with capital letter
+"components"        { return sym(Terminals.COMPONENTS); }
+"component"        { return sym(Terminals.COMPONENT); }
+"docker compose"        { return sym(Terminals.DOCKER_COMPOSE); }
+"mqtt topic"        { return sym(Terminals.MQTT_TOPIC); }
+"="            { return sym(Terminals.EQUALS); }
+","            { return sym(Terminals.COMMA); }
+"<"            { return sym(Terminals.LT); }
+"{"            { return sym(Terminals.LB_CURLY); }
+"}"            { return sym(Terminals.RB_CURLY); }
+
+//{Identifier}   { return sym(Terminals.NAME); }
+{Text}         { return symText(Terminals.TEXT); }
+//{Integer}      { return sym(Terminals.INTEGER); }
+//{Real}         { return sym(Terminals.REAL); }
+<<EOF>>        { return sym(Terminals.EOF); }
+/* error fallback */
+[^]            { throw new Error("Illegal character '"+ yytext() +"' at line " + (yyline+1) + " column " + (yycolumn+1)); }
diff --git a/ros3rag.coordinator/src/main/jastadd/Coordinator.jrag b/ros3rag.coordinator/src/main/jastadd/Coordinator.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..33bd6e56a684c7e06ee36fdc9839353d0bc408e2
--- /dev/null
+++ b/ros3rag.coordinator/src/main/jastadd/Coordinator.jrag
@@ -0,0 +1,62 @@
+aspect Computation {
+  syn String Component.getNextCommand() {
+    if (!getIncomingStatus().equals("up")) {
+      System.out.println(getName() + " not up");
+      // component is not "up" yet
+      return null;
+    }
+    for (Component predecessor : getPredecessorList()) {
+      if (!predecessor.getIncomingStatus().equals("ready")) {
+        // one of required component is not "ready" yet
+        System.out.println(getName() + " missing " + predecessor.getName());
+        return null;
+      }
+    }
+    // all required components are "ready", and this component is "up"
+    System.out.println(getName() + " ready to be started");
+    return "start";
+  }
+
+  public void Component.callDockerCompose() {
+    String[] args = { "docker-compose", "up", "-d", getDockerComposeName() };
+    System.out.println("Would start > " + java.util.Arrays.toString(args));
+    ProcessBuilder builder = new ProcessBuilder(args);
+//    builder.redirectOutput(err);
+//    builder.redirectError(err);
+
+//    Process process = builder.start();
+//    process.waitFor();
+//    return process.exitValue();
+    return;
+  }
+}
+
+aspect Printing {
+  syn String Coordinator.prettyPrint() {
+    StringBuilder sb = new StringBuilder();
+    for (Component comp : getComponentList()) {
+      sb.append(comp.prettyPrint()).append("\n");
+    }
+    return sb.toString();
+  }
+
+  syn String Component.prettyPrint() {
+    return "<Name: " + getName() + ", DockerComposeName: " + getDockerComposeName() + ", MqttTopicPrefix: " + getMqttTopicPrefix() + ", IncomingStatus: " + getIncomingStatus() + ", NextCommand: " + getNextCommand() + ">";
+  }
+}
+
+aspect AdditionalTypes {
+  public class ReversedList<T> extends beaver.Symbol implements Iterable<T> {
+    private java.util.Deque<T> delegatee = new java.util.ArrayDeque<>();
+
+    public java.util.Iterator<T> iterator() {
+      return delegatee.descendingIterator();
+    }
+
+    public void add(T t) {
+      delegatee.add(t);
+    }
+  }
+
+  public class StringList extends ReversedList<String> {}
+}
diff --git a/ros3rag.coordinator/src/main/jastadd/Coordinator.parser b/ros3rag.coordinator/src/main/jastadd/Coordinator.parser
new file mode 100644
index 0000000000000000000000000000000000000000..e00f826825b8a9825f4a3abc666324cdc2639dfa
--- /dev/null
+++ b/ros3rag.coordinator/src/main/jastadd/Coordinator.parser
@@ -0,0 +1,65 @@
+%header {:
+package de.tudresden.inf.st.coordinator.parser;
+import de.tudresden.inf.st.coordinator.ast.*;
+import java.util.Map;
+import java.util.HashMap;
+:} ;
+
+%embed {:
+  private static <T extends ASTNode<?>> void insertZero(JastAddList<T> listNode, T child) {
+    listNode.insertChild(child, 0);
+  }
+
+  private void replaceRelations(Coordinator o) {
+    for (ParsedPrecedenceRelation rel : o.getParsedPrecedenceRelationList()) {
+      for (Component pred : rel.getPredecessorList()) {
+        for (Component succ : rel.getSuccessorList()) {
+          pred.addSuccessor(succ);
+        }
+      }
+    }
+  }
+:} ;
+
+%goal goal;
+Coordinator goal =
+     COMPONENTS LB_CURLY coordinator_body.o RB_CURLY {: o.treeResolveAll(); replaceRelations(o); return o; :}
+
+Coordinator coordinator_body =
+     component.c goal.o    {: o.addComponent(c); return o; :}
+     string_list.preds LT string_list.succs goal.o
+     {:
+        ParsedPrecedenceRelation rel = new ParsedPrecedenceRelation();
+        o.addParsedPrecedenceRelation(rel);
+        preds.forEach(pred -> rel.addPredecessor(Component.createRef(pred)));
+        succs.forEach(succ -> rel.addPredecessor(Component.createRef(succ)));
+        return o;
+     :}
+  |                        {: return new Coordinator(); :}
+  ;
+
+Component component =
+     COMPONENT TEXT.name DOCKER_COMPOSE EQUALS TEXT.dc MQTT_TOPIC EQUALS TEXT.mqtt
+      {:
+        Component result = new Component();
+        result.setName(name);
+        result.setDockerComposeName(dc);
+        result.setMqttTopicPrefix(mqtt);
+        return result;
+      :}
+  ;
+
+StringList string_list =
+     LB_SQUARE string_list_body.slb RB_SQUARE         {: return slb; :}
+  |  LB_SQUARE RB_SQUARE                              {: return new StringList(); :}
+  ;
+
+StringList string_list_body =
+     TEXT.n COMMA string_list_body.slb                {: slb.add(n); return slb; :}
+  |  TEXT.n
+    {:
+       StringList result = new StringList();
+       result.add(n);
+       return result;
+    :}
+  ;
diff --git a/ros3rag.coordinator/src/main/jastadd/Coordinator.relast b/ros3rag.coordinator/src/main/jastadd/Coordinator.relast
new file mode 100644
index 0000000000000000000000000000000000000000..f5acd03b7aa2ae41cd3dd2609b6156e2e5e07a9d
--- /dev/null
+++ b/ros3rag.coordinator/src/main/jastadd/Coordinator.relast
@@ -0,0 +1,6 @@
+Coordinator ::= Component* ParsedPrecedenceRelation* ; // /NextComponentToStart:Component/ ;
+Component ::= <Name:String> <DockerComposeName:String> <MqttTopicPrefix:String> <IncomingStatus:String> /<NextCommand:String>/ ;
+rel Component.Predecessor* <-> Component.Successor* ;
+ParsedPrecedenceRelation ;
+rel ParsedPrecedenceRelation.Predecessor* -> Component ;
+rel ParsedPrecedenceRelation.Successor* -> Component ;
diff --git a/ros3rag.coordinator/src/main/jastadd/dummy/types.connect b/ros3rag.coordinator/src/main/jastadd/dummy/types.connect
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ros3rag.coordinator/src/main/jastadd/dummy/types.jrag b/ros3rag.coordinator/src/main/jastadd/dummy/types.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ros3rag.coordinator/src/main/jastadd/dummy/types.relast b/ros3rag.coordinator/src/main/jastadd/dummy/types.relast
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ros3rag.coordinator/src/main/java/de/tudresden/inf/st/coordinator/MainCoordinator.java b/ros3rag.coordinator/src/main/java/de/tudresden/inf/st/coordinator/MainCoordinator.java
new file mode 100644
index 0000000000000000000000000000000000000000..e184767ad145c9bcc9b773fa9d938e4945c9dcae
--- /dev/null
+++ b/ros3rag.coordinator/src/main/java/de/tudresden/inf/st/coordinator/MainCoordinator.java
@@ -0,0 +1,166 @@
+package de.tudresden.inf.st.coordinator;
+
+import beaver.Parser;
+import de.tudresden.inf.st.coordinator.ast.Component;
+import de.tudresden.inf.st.coordinator.ast.Coordinator;
+import de.tudresden.inf.st.coordinator.ast.MqttHandler;
+import de.tudresden.inf.st.coordinator.parser.CoordinatorParser;
+import de.tudresden.inf.st.coordinator.scanner.CoordinatorScanner;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Entrypoint for Coordinator.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class MainCoordinator {
+
+  private static final String TOPIC_EXIT = "coordinator/exit";
+  private static final String TOPIC_MODEL = "coordinator/model";
+  private static final String TOPIC_STATUS = "coordinator/status";
+  private static final String TOPIC_READY = "coordinator/ready";
+  private Coordinator coordinator;
+  private MqttHandler mainHandler;
+  private Component rosCore;
+  private Component mosquitto;
+
+  public static void main(String[] args) throws Exception {
+    MainCoordinator main = new MainCoordinator();
+//    main.manuallyBuild();
+    main.parsedBuild();
+    main.start();
+  }
+
+  private void manuallyBuild() {
+    coordinator = new Coordinator();
+    Component robotCtrlA = newComponent("Robot Control A", "ros_place_a", "ros-place-a");
+    Component robotCtrlB = newComponent("Robot Control B", "ros_place_b", "ros-place-b");
+    Component ragA = newComponent("RAG A", "rag_place_a", "rag-a");
+    Component ragB = newComponent("RAG B", "rag_place_b", "rag-b");
+    Component random = newComponent("Random Dummy", "cgv_random_dummy", "random");
+    rosCore = newComponent("ROS core", "ros_core", "");
+    mosquitto = newComponent("MQTT broker", "mosquitto", "");
+
+    coordinator.addComponent(robotCtrlA);
+    coordinator.addComponent(robotCtrlB);
+    coordinator.addComponent(ragA);
+    coordinator.addComponent(ragB);
+    coordinator.addComponent(random);
+    coordinator.addComponent(rosCore);
+    coordinator.addComponent(mosquitto);
+
+    // ros core needed for all other ros nodes
+    rosCore.addSuccessor(robotCtrlA);
+    rosCore.addSuccessor(robotCtrlB);
+    rosCore.addSuccessor(random);
+
+    // mqtt broker needed for all robot ctrl and rag nodes
+    mosquitto.addSuccessor(robotCtrlA);
+    mosquitto.addSuccessor(robotCtrlB);
+    mosquitto.addSuccessor(ragA);
+    mosquitto.addSuccessor(ragB);
+
+    // robot control needs to start before rag
+    robotCtrlA.addSuccessor(ragA);
+    robotCtrlB.addSuccessor(ragB);
+
+    // rag place B needs to start before rag place A
+    ragB.addSuccessor(ragA);
+
+    // random should start last
+    robotCtrlA.addSuccessor(random);
+    robotCtrlB.addSuccessor(random);
+    ragA.addSuccessor(random);
+    ragB.addSuccessor(random);
+  }
+
+  private void parsedBuild() throws IOException, Parser.Exception {
+    Reader in = Files.newBufferedReader(Paths.get("src", "main", "resources", "ros3rag.coordinator"));
+
+    CoordinatorScanner scanner = new CoordinatorScanner(in);
+    CoordinatorParser parser = new CoordinatorParser();
+
+    coordinator = (Coordinator) parser.parse(scanner);
+
+    for (Component comp : coordinator.getComponentList()) {
+      if (comp.getName().equals("rosCore")) {
+        rosCore = comp;
+      }
+      if (comp.getName().equals("mosquitto")) {
+        mosquitto = comp;
+      }
+    }
+
+    in.close();
+  }
+
+  private void start() throws Exception {
+    final String mqttHost = "localhost";
+
+    coordinator.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS);
+
+    for (Component comp : coordinator.getComponentList()) {
+      comp.connectIncomingStatus("mqtt://" + mqttHost + "/" + comp.getMqttTopicPrefix() + "/status");
+      comp.connectNextCommand("mqtt://" + mqttHost + "/" + comp.getMqttTopicPrefix() + "/command", false);
+    }
+
+    for (Component comp : coordinator.getComponentList()) {
+      comp.callDockerCompose();
+    }
+
+    mainHandler = new MqttHandler().dontSendWelcomeMessage();
+    mainHandler.setHost(mqttHost);
+    mainHandler.waitUntilReady(2, TimeUnit.SECONDS);
+    CountDownLatch exitCondition = new CountDownLatch(1);
+    mainHandler.newConnection(TOPIC_EXIT, bytes -> exitCondition.countDown());
+    mainHandler.newConnection(TOPIC_MODEL, bytes -> this.printStatus());
+    mainHandler.newConnection(TOPIC_READY, bytes -> this.setReady());
+    Runtime.getRuntime().addShutdownHook(new Thread(this::close));
+
+    // wait some time for ros_core and mqtt_broker to be started
+    TimeUnit.SECONDS.sleep(2);
+
+    setReady();
+
+    exitCondition.await();
+  }
+
+  private void setReady() {
+    // set ros-core and mqtt-broker to ready
+    rosCore.setIncomingStatus("ready");
+    mosquitto.setIncomingStatus("ready");
+  }
+
+  private void printStatus() {
+    String content = coordinator.prettyPrint();
+    System.out.println(content);
+    if (mainHandler != null) {
+      mainHandler.publish(TOPIC_STATUS, content.getBytes(StandardCharsets.UTF_8));
+    }
+  }
+
+  private void close() {
+    if (coordinator != null) {
+      coordinator.ragconnectCloseConnections();
+    }
+    if (mainHandler != null) {
+      mainHandler.close();
+    }
+  }
+
+  private static Component newComponent(String name, String dockerComposeName, String mqttTopicPrefix) {
+    Component result = new Component();
+    result.setName(name);
+    result.setDockerComposeName(dockerComposeName);
+    result.setMqttTopicPrefix(mqttTopicPrefix);
+    return result;
+  }
+
+}
diff --git a/ros3rag.coordinator/src/main/resources/ros3rag.coordinator b/ros3rag.coordinator/src/main/resources/ros3rag.coordinator
new file mode 100644
index 0000000000000000000000000000000000000000..c37c6a6aaa076ebf9d6dc6a8dee8c52217267bdf
--- /dev/null
+++ b/ros3rag.coordinator/src/main/resources/ros3rag.coordinator
@@ -0,0 +1,25 @@
+components {
+  component "robotCtrlA" docker compose = "ros_place_a" mqtt topic = "ros-place-a"
+  component "robotCtrlB" docker compose = "ros_place_b" mqtt topic = "ros-place-b"
+  component "ragA" docker compose = "rag_place_a" mqtt topic = "rag-a"
+  component "ragB" docker compose = "rag_place_b" mqtt topic = "rag-b"
+  component "random" docker compose = "cgv_random_dummy" mqtt topic = "random"
+  component "rosCore" docker compose = "ros_core" mqtt topic = ""
+  component "mosquitto" docker compose = "mosquitto" mqtt topic = ""
+
+  // ros core needed for all other ros nodes
+  rosCore < robotCtrlA, robotCtrlB, random
+
+  // mqtt broker needed for all robot ctrl and rag nodes
+  mosquitto < robotCtrlA, robotCtrlB, ragA, ragB
+
+  // robot control needs to start before rag
+  robotCtrlA < ragA
+  robotCtrlB < ragB
+
+  // rag place B needs to start before rag place A
+  ragB < ragA
+
+  // random should start last
+  robotCtrlA, robotCtrlB, ragA, ragB < random
+}
diff --git a/settings.gradle b/settings.gradle
index bd2c1a8453b44141ce617dbfeb3570e9786f6637..b2e62ebd90e287a75d9234f132668859ec1bb9ff 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -3,6 +3,7 @@ rootProject.name = 'ros3rag'
 include 'ros3rag.placeA'
 include 'ros3rag.placeB'
 include 'ros3rag.common'
+include 'ros3rag.coordinator'
 
 // include 'ros3rag.senderstub'
 // include 'ros3rag.receiverstub'