diff --git a/ros3rag.common/src/main/java/de/tudresden/inf/st/ros3rag/common/SharedMainParts.java b/ros3rag.common/src/main/java/de/tudresden/inf/st/ros3rag/common/SharedMainParts.java
index 5951e02070cbc6af009932eb27f40c603d4c18f9..0d57d35d53628f881c20562b7d57077108cfe6e0 100644
--- a/ros3rag.common/src/main/java/de/tudresden/inf/st/ros3rag/common/SharedMainParts.java
+++ b/ros3rag.common/src/main/java/de/tudresden/inf/st/ros3rag/common/SharedMainParts.java
@@ -26,8 +26,8 @@ public abstract class SharedMainParts<MqttHandler extends SharedMainParts.MqttHa
   private final String TOPIC_REWIND;
   private final String TOPIC_EXIT;
 
-  private static final String TOPIC_SUFFIX_COORDINATOR_STATUS = "status";
-  private static final String TOPIC_SUFFIX_COORDINATOR_COMMAND = "command";
+  public static final String TOPIC_SUFFIX_COORDINATOR_STATUS = "status";
+  public static final String TOPIC_SUFFIX_COORDINATOR_COMMAND = "command";
 
   protected MqttHandler mainHandler;
   protected WorldModel model;
@@ -61,7 +61,7 @@ public abstract class SharedMainParts<MqttHandler extends SharedMainParts.MqttHa
     mainHandler = createMqttHandler().dontSendWelcomeMessage();
     mainHandler.setHost(config.mqttHost);
     if (!mainHandler.waitUntilReady(2, TimeUnit.SECONDS)) {
-      logger.fatal("Could not connect to mqtt handler. Exiting");
+      logger.fatal("Could not connect to " + config.mqttHost + " -> Exiting");
       return;
     }
     CountDownLatch exitCondition = new CountDownLatch(1);
@@ -101,7 +101,7 @@ public abstract class SharedMainParts<MqttHandler extends SharedMainParts.MqttHa
     exitCondition.await();
   }
 
-  private String joinTopics(String... topics) {
+  public static String joinTopics(String... topics) {
     StringBuilder sb = new StringBuilder();
     for (int i = 0; i < topics.length; i++) {
       String topic = topics[i];
diff --git a/ros3rag.common/src/main/resources/config-scaling-mini.yml b/ros3rag.common/src/main/resources/config-scaling-mini.yml
index 38b28ee0953f729200aa67bf0f082641d68c0e39..d113799d756625234256e0942e432fe44a9b4531 100644
--- a/ros3rag.common/src/main/resources/config-scaling-mini.yml
+++ b/ros3rag.common/src/main/resources/config-scaling-mini.yml
@@ -1,6 +1,5 @@
 mqttHost: "localhost"
-filenameInitialScene: "src/main/resources/config-scene-a.json"
-coordinatorMqttTopicPrefix: "coordinating/rag-a"
+coordinatorMqttTopicPrefix: "coordinating/rag-"
 topicLogicalUpdate: "place-b/logical-update"
 views: 5
 objects: 7
diff --git a/ros3rag.scaling.a/.gitignore b/ros3rag.scaling.a/.gitignore
index fc5fdd28bb5a1302864b7f3483a9a37a742d9485..ac24215235cff68e13758de8e911fb9cea58c214 100644
--- a/ros3rag.scaling.a/.gitignore
+++ b/ros3rag.scaling.a/.gitignore
@@ -3,4 +3,4 @@ src/gen-res/
 src/gen/
 out/
 *.class
-world.svg
+world-a.svg
diff --git a/ros3rag.scaling.a/src/main/java/de/tudresden/inf/st/scaling/a/MainScalingA.java b/ros3rag.scaling.a/src/main/java/de/tudresden/inf/st/scaling/a/MainScalingA.java
index fbe6c33b52263550faf2205023d178306c6134ee..c9b9d09abdf94a8142b6db3f0c88e1d23982a9a6 100644
--- a/ros3rag.scaling.a/src/main/java/de/tudresden/inf/st/scaling/a/MainScalingA.java
+++ b/ros3rag.scaling.a/src/main/java/de/tudresden/inf/st/scaling/a/MainScalingA.java
@@ -2,17 +2,24 @@ package de.tudresden.inf.st.scaling.a;
 
 import de.tudresden.inf.st.jastadd.dumpAst.ast.Dumper;
 import de.tudresden.inf.st.ros3rag.common.ConfigurationScaling;
+import de.tudresden.inf.st.ros3rag.common.SharedMainParts;
 import de.tudresden.inf.st.ros3rag.common.Util;
 import de.tudresden.inf.st.scaling.a.ast.*;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static de.tudresden.inf.st.ros3rag.common.SharedMainParts.TOPIC_SUFFIX_COORDINATOR_STATUS;
+import static de.tudresden.inf.st.ros3rag.common.SharedMainParts.joinTopics;
 
 /**
  * Scaling Case Study - Site A.
@@ -21,27 +28,69 @@ import java.util.Random;
  */
 public class MainScalingA {
   private static final Logger logger = LogManager.getLogger(MainScalingA.class);
+  private static final String TOPIC_EXIT = "place-a/exit";
+
   private CompleteWorld world;
+  private MqttHandler mainHandler;
+  private ConfigurationScaling config;
 
-  public static void main(String[] args) throws IOException {
+  public static void main(String[] args) throws IOException, InterruptedException {
     new MainScalingA().run(args);
   }
 
-  private void run(@SuppressWarnings("unused") String[] args) throws IOException {
+  private void run(@SuppressWarnings("unused") String[] args) throws IOException, InterruptedException {
     logger.info("Hi from A");
     Path pathToConfig = Paths.get("..",
         "ros3rag.common", "src", "main", "resources", "config-scaling-mini.yml");
-    ConfigurationScaling config = Util.parseScalingConfig(pathToConfig.toFile());
+    config = Util.parseScalingConfig(pathToConfig.toFile());
 
     world = createWorld(config);
+    mainHandler = new MqttHandler().dontSendWelcomeMessage().setHost(config.mqttHost);
+    boolean mqttAvailable = mainHandler.waitUntilReady(2, TimeUnit.SECONDS);
+    if (!mqttAvailable) {
+      logger.fatal("Could not connect to " + config.mqttHost + " -> Exiting.");
+      return;
+    }
+
     generateAndSetViews();
-    Dumper.read(world).dumpAsSVG(Paths.get("world.svg"));
+    Dumper.read(world).dumpAsSVG(Paths.get("world-a.svg"));
+
+    logger.info("Using coordinator logic");
+    final String coordinatorPrefix = config.coordinatorMqttTopicPrefix + "a";
+    mainHandler.newConnection(SharedMainParts.joinTopics(coordinatorPrefix,
+            SharedMainParts.TOPIC_SUFFIX_COORDINATOR_COMMAND),
+        bytes -> {
+          connectMyScenes();
+          mainHandler.publish(joinTopics(coordinatorPrefix, TOPIC_SUFFIX_COORDINATOR_STATUS),
+              "ready".getBytes(StandardCharsets.UTF_8));
+        });
+
+    Runtime.getRuntime().addShutdownHook(new Thread(this::close));
+
+    CountDownLatch exitCondition = new CountDownLatch(1);
+    mainHandler.newConnection(TOPIC_EXIT, bytes -> {
+      logger.info("Got exit command");
+      exitCondition.countDown();
+      logger.debug("exit latch count = {}",
+          exitCondition.getCount());
+    });
 
+    mainHandler.publish(joinTopics(coordinatorPrefix, TOPIC_SUFFIX_COORDINATOR_STATUS),
+        "up".getBytes(StandardCharsets.UTF_8));
+
+    exitCondition.await();
+  }
+
+  private void connectMyScenes() {
     for (int viewIndex = 0; viewIndex < world.getConfig().getNumberOfViews(); viewIndex++) {
-      world.connectView(
-          Util.mqttUri(config.topicLogicalUpdate, config.mqttHost),
-          viewIndex,
-          true);
+      try {
+        world.connectView(
+            Util.mqttUri(joinTopics(config.topicLogicalUpdate, String.valueOf(viewIndex)), config.mqttHost),
+            viewIndex,
+            true);
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
     }
   }
 
@@ -93,4 +142,10 @@ public class MainScalingA {
       world.addView(view);
     }
   }
+
+  private void close() {
+    logger.info("Exiting ...");
+    mainHandler.close();
+    world.ragconnectCloseConnections();
+  }
 }
diff --git a/ros3rag.scaling.b/.gitignore b/ros3rag.scaling.b/.gitignore
index 87b4cdd3d7c6a41502ca98703abeeb69a1d536fb..90b7ef48578e2e905cac2779a0b49e98b48734fb 100644
--- a/ros3rag.scaling.b/.gitignore
+++ b/ros3rag.scaling.b/.gitignore
@@ -3,3 +3,4 @@ src/gen-res/
 src/gen/
 out/
 *.class
+world-b.svg
diff --git a/ros3rag.scaling.b/src/main/java/de/tudresden/inf/st/scaling/b/MainScalingB.java b/ros3rag.scaling.b/src/main/java/de/tudresden/inf/st/scaling/b/MainScalingB.java
index 6d333373a0a4f17ef2dd865ad0dcf8db88dda4c1..41b8248dfcd92c784c477673d480e3df7a1d2113 100644
--- a/ros3rag.scaling.b/src/main/java/de/tudresden/inf/st/scaling/b/MainScalingB.java
+++ b/ros3rag.scaling.b/src/main/java/de/tudresden/inf/st/scaling/b/MainScalingB.java
@@ -1,17 +1,25 @@
 package de.tudresden.inf.st.scaling.b;
 
+import de.tudresden.inf.st.jastadd.dumpAst.ast.Dumper;
 import de.tudresden.inf.st.ros3rag.common.ConfigurationScaling;
+import de.tudresden.inf.st.ros3rag.common.SharedMainParts;
 import de.tudresden.inf.st.ros3rag.common.Util;
 import de.tudresden.inf.st.scaling.b.ast.*;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
+import static de.tudresden.inf.st.ros3rag.common.SharedMainParts.TOPIC_SUFFIX_COORDINATOR_STATUS;
+import static de.tudresden.inf.st.ros3rag.common.SharedMainParts.joinTopics;
+
 /**
  * Scaling Case Study - Site B.
  *
@@ -19,37 +27,137 @@ import java.util.stream.IntStream;
  */
 public class MainScalingB {
   private static final Logger logger = LogManager.getLogger(MainScalingB.class);
+  private static final String TOPIC_EXIT = "place-b/exit";
+  private static final String TOPIC_MODEL = "place-b/model";
+  private static final String TOPIC_MODEL_SVG_PATH = "place-b/model/svg/path";
+
   private WorldModelB world;
+  private MqttHandler mainHandler;
+  private ConfigurationScaling config;
 
-  public static void main(String[] args) throws IOException {
+  public static void main(String[] args) throws IOException, InterruptedException {
     new MainScalingB().run(args);
   }
 
-  private void run(@SuppressWarnings("unused") String[] args) throws IOException {
+  private void run(@SuppressWarnings("unused") String[] args) throws IOException, InterruptedException {
     logger.info("Hi from B");
     Path pathToConfig = Paths.get("..",
         "ros3rag.common", "src", "main", "resources", "config-scaling-mini.yml");
-    ConfigurationScaling config = Util.parseScalingConfig(pathToConfig.toFile());
+    config = Util.parseScalingConfig(pathToConfig.toFile());
 
     world = new WorldModelB();
-    generateWorld(config);
+    mainHandler = new MqttHandler().dontSendWelcomeMessage().setHost(config.mqttHost);
+    boolean mqttAvailable = mainHandler.waitUntilReady(2, TimeUnit.SECONDS);
+    if (!mqttAvailable) {
+      logger.fatal("Could not connect to " + config.mqttHost + " -> Exiting.");
+      return;
+    }
+
+    generateWorld();
+    dumpModel();
+
+    logger.info("Using coordinator logic");
+    final String coordinatorPrefix = config.coordinatorMqttTopicPrefix + "b";
+    mainHandler.newConnection(joinTopics(coordinatorPrefix,
+            SharedMainParts.TOPIC_SUFFIX_COORDINATOR_COMMAND),
+        bytes -> {
+          initMyScene();
+          mainHandler.publish(joinTopics(coordinatorPrefix, TOPIC_SUFFIX_COORDINATOR_STATUS),
+              "ready".getBytes(StandardCharsets.UTF_8));
+        });
+
+    Runtime.getRuntime().addShutdownHook(new Thread(this::close));
+
+    CountDownLatch exitCondition = new CountDownLatch(1);
+    mainHandler.newConnection(TOPIC_EXIT, bytes -> {
+      logger.info("Got exit command");
+      exitCondition.countDown();
+      logger.debug("exit latch count = {}",
+          exitCondition.getCount());
+    });
+    mainHandler.newConnection(TOPIC_MODEL, bytes -> dumpModel());
+
+    mainHandler.publish(joinTopics(coordinatorPrefix, TOPIC_SUFFIX_COORDINATOR_STATUS),
+        "up".getBytes(StandardCharsets.UTF_8));
+
+    exitCondition.await();
   }
 
-  private void generateWorld(ConfigurationScaling config) throws IOException {
+  private void initMyScene() {
+    Scene myNewScene = new Scene();
+
+    int pcc = 0; // position-coordination-counter
+    // locations
+    for (Region region : world.getRegionList()) {
+      if (region.getName().startsWith("Collab")) {
+        // exactly one collaboration zone
+        CollaborationZone cz = new CollaborationZone()
+            .setName("P-" + region.getName())
+            .setPosition(Position.of(pcc, pcc, pcc))
+            .setOrientation(Orientation.of(0, 0, 0, 1))
+            .setSize(Size.of(0.1, 0.1, 0));
+        myNewScene.addDropOffLocation(cz);
+        pcc += 1;
+      } else {
+        for (String locationName : region.locationNamesAsList()) {
+          DropOffLocation location = new DropOffLocation()
+              .setName(locationName)
+              .setPosition(Position.of(pcc, pcc, pcc))
+              .setOrientation(Orientation.of(0, 0, 0, 1))
+              .setSize(Size.of(0.1, 0.1, 0));
+          myNewScene.addDropOffLocation(location);
+          pcc += 1;
+        }
+      }
+    }
+
+    // all objects at start
+    for (int objectIndex = 0; objectIndex < config.objects; objectIndex++) {
+      DropOffLocation location = myNewScene.resolveObjectOfInterest("P-Start" + objectIndex).asDropOffLocation();
+      MovableObject obj = new MovableObject()
+          .setName("O" + objectIndex)
+          .setPosition(Position.of(location.getPosition().getX(),
+              location.getPosition().getY(),
+              location.getPosition().getZ()))
+          .setOrientation(Orientation.of(0, 0, 0, 1))
+          .setSize(Size.of(0, 0, 0));
+      myNewScene.addMovableObject(obj);
+    }
+
+    // robot objects
+    for (int robotIndex = 0; robotIndex < config.robots; robotIndex++) {
+      myNewScene.addRobotObject(new RobotObject()
+          .setName("ARM" + robotIndex)
+          .setActive(false)
+          .setPosition(new Position())
+          .setOrientation(new Orientation())
+          .setSize(new Size()));
+    }
+
+    world.setMyScene(myNewScene);
+  }
+
+  private void generateWorld() throws IOException {
     // start region
-    world.addRegion(new Region().setName("Start").setLocationNames(locationsFor("Start", config)));
+    world.addRegion(new Region().setName("Start").setLocationNames(locationsFor("Start")));
 
     // robots
     for (int robotIndex = 0; robotIndex < config.robots; robotIndex++) {
       // region of the robot
       String regionOfRobot = "Region" + robotIndex;
-      world.addRegion(new Region().setName(regionOfRobot).setLocationNames(locationsFor(regionOfRobot, config)));
+      world.addRegion(new Region().setName(regionOfRobot).setLocationNames(locationsFor(regionOfRobot)));
+
+      // region of collaboration zones
+      if (robotIndex != config.robots - 1) {
+        String collaborationRegion = "Collab" + robotIndex;
+        world.addRegion(new Region().setName(collaborationRegion).setLocationNames("P-" + collaborationRegion));
+      }
 
       Robot robot = new Robot().setName("ARM" + robotIndex);
 
       // reachability
       CanReachObjectOfInterestWrapper wrapper = new CanReachObjectOfInterestWrapper();
-      // each robot arm can reach the region with the same index as the arm (and the start region, for the first robot)
+      // each robot arm can reach the location of its region (and the start region, for the first robot)
       if (robotIndex == 0) {
         for (String location : world.findRegion("Start").locationNamesAsList()) {
           wrapper.addCanReachObjectOfInterest(new CanReachObjectOfInterest(location));
@@ -58,6 +166,15 @@ public class MainScalingB {
       for (String location : world.findRegion(regionOfRobot).locationNamesAsList()) {
         wrapper.addCanReachObjectOfInterest(new CanReachObjectOfInterest(location));
       }
+      // add reachability for collaboration zones
+      if (robotIndex != 0) {
+        // reachability to previous collaboration zone
+        wrapper.addCanReachObjectOfInterest(new CanReachObjectOfInterest("P-Collab" + (robotIndex - 1)));
+      }
+      if (robotIndex != config.robots - 1) {
+        // reachability to its collaboration zone
+        wrapper.addCanReachObjectOfInterest(new CanReachObjectOfInterest("P-Collab" + (robotIndex)));
+      }
       robot.setCanReachObjectOfInterestWrapper(wrapper);
       world.addRobot(robot);
     }
@@ -65,16 +182,38 @@ public class MainScalingB {
     // other scenes
     for (int sceneIndex = 0; sceneIndex < config.views; sceneIndex++) {
       world.addOtherScene(new LogicalScene());
-      world.connectOtherScene(config.topicLogicalUpdate, sceneIndex);
     }
+    world.connectOtherScene(Util.mqttUri(joinTopics(config.topicLogicalUpdate, "#"), config.mqttHost));
 
     // my scene
     world.setMyScene(new Scene());
   }
 
-  private String locationsFor(String regionName, ConfigurationScaling config) {
+  private String locationsFor(String regionName) {
     return IntStream.range(0, config.objects)
         .mapToObj(index -> "P-" + regionName + index)
         .collect(Collectors.joining(","));
   }
+
+  private void dumpModel() {
+    try {
+      String filename = world.dumpAst(builder -> {
+        builder.excludeChildren("Orientation", "Size");
+        builder.excludeRelations("ContainedInRegion");
+        builder.includeNonterminalAttributes("LogicalScene", "diffScenes", "diffToOperations");
+        builder.includeAttributes("realRegion", "computeOperations");
+        builder.includeNullNodes();
+      });
+      mainHandler.publish(TOPIC_MODEL_SVG_PATH, filename.getBytes(StandardCharsets.UTF_8));
+    } catch (Exception e) {
+      logger.catching(e);
+    }
+  }
+
+  private void close() {
+    logger.info("Exiting ...");
+    mainHandler.close();
+    world.ragconnectCloseConnections();
+  }
+
 }