diff --git a/libs/ragconnect-0.3.1.jar b/libs/ragconnect-0.3.1.jar
index da8df316201d4ddede05a35e14d01f757df33582..508b2e6617ba61492f47c7237dfbf66c62314dcc 100644
Binary files a/libs/ragconnect-0.3.1.jar and b/libs/ragconnect-0.3.1.jar differ
diff --git a/ros3rag.common/src/main/java/de/tudresden/inf/st/ros3rag/common/Util.java b/ros3rag.common/src/main/java/de/tudresden/inf/st/ros3rag/common/Util.java
index 29c0d850fd2c370f5776469701314c9ac7c5c0d5..e4ca8598e02d52aeac9d1fda7130687004e7e8a6 100644
--- a/ros3rag.common/src/main/java/de/tudresden/inf/st/ros3rag/common/Util.java
+++ b/ros3rag.common/src/main/java/de/tudresden/inf/st/ros3rag/common/Util.java
@@ -72,14 +72,4 @@ public class Util {
     }
     return repoRoot.resolve(moduleName);
   }
-
-  private static class HostAndPort {
-    String host;
-    int port;
-  }
-
-  @FunctionalInterface
-  public interface HandleLink {
-    void handle(boolean isEndEffector, String topic, String name) throws IOException;
-  }
 }
diff --git a/ros3rag.common/src/main/resources/tasks.gradle b/ros3rag.common/src/main/resources/tasks.gradle
index 79b3eab1860edfbace31eb2fda88a3dd09f262e0..9311f58134a7a1b36e692b4de82e54c622807a1c 100644
--- a/ros3rag.common/src/main/resources/tasks.gradle
+++ b/ros3rag.common/src/main/resources/tasks.gradle
@@ -44,9 +44,7 @@ task grammar2uml(type: JavaExec) {
     args([
             '--verbose',
             'src/gen/jastadd/types.relast'
-    ]
-            +
-            project.ext.relastFiles)
+    ] + project.ext.relastFiles)
 }
 
 // phase: RelAst
@@ -62,9 +60,8 @@ task relastToJastAdd(type: JavaExec) {
           "--serializer=jackson",
           "--resolverHelper",
           "--file",
-          "src/gen/jastadd/types.relast"]
-            +
-            project.ext.relastFiles)
+          "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")
diff --git a/ros3rag.placeA/src/main/java/de/tudresden/inf/st/placeA/MainA.java b/ros3rag.placeA/src/main/java/de/tudresden/inf/st/placeA/MainA.java
index 223cf3ea869712b80860ececbb4a19b6e52dd34a..6ecddba2557aad6fb43f6063442bee6f3ad49bb9 100644
--- a/ros3rag.placeA/src/main/java/de/tudresden/inf/st/placeA/MainA.java
+++ b/ros3rag.placeA/src/main/java/de/tudresden/inf/st/placeA/MainA.java
@@ -4,11 +4,14 @@ import de.tudresden.inf.st.placeA.ast.MqttHandler;
 import de.tudresden.inf.st.placeA.ast.Robot;
 import de.tudresden.inf.st.placeA.ast.Scene;
 import de.tudresden.inf.st.placeA.ast.WorldModelA;
+import de.tudresden.inf.st.ros3rag.common.Configuration;
 import de.tudresden.inf.st.ros3rag.common.Util;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
 import java.nio.charset.StandardCharsets;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -25,6 +28,7 @@ public class MainA {
 
   private final static String TOPIC_MODEL = "place-a/model";
   private final static String TOPIC_STATUS = "place-a/status";
+  private final static String TOPIC_REWIND = "place-a/rewind";
   private final static String TOPIC_EXIT = "place-a/exit";
 
   private final static String TOPIC_SCENE_INIT = "place-a/scene/init";
@@ -36,6 +40,13 @@ public class MainA {
 
   private MqttHandler mainHandler;
   private WorldModelA model;
+  private Configuration config;
+
+  private static final Map<String, String> channelDescriptions = new LinkedHashMap<>() {{
+    put(TOPIC_MODEL, "Print current model (detailed if message starts with 'detail");
+    put(TOPIC_REWIND, "Rewind app to start");
+    put(TOPIC_EXIT, "Exit app");
+  }};
 
   public static void main(String[] args) throws Exception {
     new MainA().run(args);
@@ -46,9 +57,7 @@ public class MainA {
 
     // --- No configuration below this line ---
 
-    final var config = Util.parseConfig(UtilA.pathToDirectoryOfPlaceA().resolve(configFile).toFile());
-
-    model = new WorldModelA();
+    config = Util.parseConfig(UtilA.pathToDirectoryOfPlaceA().resolve(configFile).toFile());
 
     /// Prepare main handler
     mainHandler = new MqttHandler("mainHandler").dontSendWelcomeMessage();
@@ -57,6 +66,15 @@ public class MainA {
     mainHandler.waitUntilReady(2, TimeUnit.SECONDS);
     mainHandler.newConnection(TOPIC_EXIT, bytes -> exitCondition.countDown());
     mainHandler.newConnection(TOPIC_MODEL, bytes -> logStatus(new String(bytes)));
+    mainHandler.newConnection(TOPIC_REWIND, bytes ->
+        {
+          try {
+            rewind("rewind");
+          } catch (Exception e) {
+            logger.catching(e);
+          }
+        }
+    );
 
     mainHandler.newConnection(TOPIC_DEMO_MOVE_objectRed1_BLUE, bytes ->
         UtilA.updatePositionOfObjectToLocation(model.getScene(), "objectRed1", "binBlue")
@@ -65,6 +83,18 @@ public class MainA {
       UtilA.updatePositionOfObjectToLocation(model.getScene(), "objectRed1", "binRed")
     );
 
+    logger.info("Supported commands: {}", channelDescriptions);
+
+    rewind("Start");
+
+    Runtime.getRuntime().addShutdownHook(new Thread(this::close));
+
+    exitCondition.await();
+  }
+
+  private void rewind(String statusMessage) throws Exception {
+    model = new WorldModelA();
+
     /// Reading scene and robot
     de.tudresden.inf.st.ceti.Scene scene = readScene(
         UtilA.pathToDirectoryOfPlaceA().resolve(config.filenameInitialScene)
@@ -83,17 +113,9 @@ public class MainA {
     model.connectScene(mqttUri(TOPIC_SCENE_UPDATE_FROM_ROS, config));
     model.getScene().connectLogicalScene(mqttUri(TOPIC_SCENE_UPDATE_TO_PLACE_B, config), true);
 
-    logStatus("Start");
-
-    logger.info("To print the current model states, send a message to the topic '{}'.", TOPIC_MODEL);
-    logger.info("To exit the system cleanly, send a message to the topic '{}', or use Ctrl+C.", TOPIC_EXIT);
+    logStatus(statusMessage);
 
     mainHandler.publish(TOPIC_SCENE_INIT, scene.toByteArray());
-//    logger.fatal("Skipping publishing to {} for now", TOPIC_SCENE_INIT);
-
-    Runtime.getRuntime().addShutdownHook(new Thread(this::close));
-
-    exitCondition.await();
   }
 
   private void setRobot(String name) {
diff --git a/ros3rag.placeB/src/main/jastadd/WorldModelB.jadd b/ros3rag.placeB/src/main/jastadd/WorldModelB.jadd
index 0a63106de789c89b84ed8b808322c620287f67ae..8443d3414568223fd0c93c8e9e09c47f6ac30ec7 100644
--- a/ros3rag.placeB/src/main/jastadd/WorldModelB.jadd
+++ b/ros3rag.placeB/src/main/jastadd/WorldModelB.jadd
@@ -21,24 +21,27 @@ aspect Computation {
         result.add(diff);
         continue;
       }
+      if (myObject.hasLocatedAt() && !otherObject.hasLocatedAt()) {
+        var diff = new DifferenceObjectMisplaced();
+        diff.setObject(myObject);
+        diff.setPreviousLocation(myObject.getLocatedAt());
+        result.add(diff);
+        continue;
+      }
+      if (!myObject.hasLocatedAt() && !otherObject.hasLocatedAt() ||
+          (myObject.hasLocatedAt() && otherObject.hasLocatedAt() &&
+           myObject.getLocatedAt().getName().equals(otherObject.getLocatedAt().getName()))) {
+        // no diff if otherObject has no location information, and if both objects are located at same location
+        // otherObject is always non-null, so this case does not need to be treated
+        continue;
+      }
+      var difference = new DifferenceObjectAtWrongPlace();
+      difference.setObject(myObject);
       if (myObject.hasLocatedAt()) {
-        if (!otherObject.hasLocatedAt()) {
-          var diff = new DifferenceObjectMisplaced();
-          diff.setObject(myObject);
-          diff.setPreviousLocation(myObject.getLocatedAt());
-          result.add(diff);
-          continue;
-        }
-        if (!myObject.getLocatedAt().getName().equals(otherObject.getLocatedAt().getName())) {
-          // object at different locations
-          var difference = new DifferenceObjectAtWrongPlace();
-          difference.setObject(myObject);
-          difference.setPreviousLocation(myObject.getLocatedAt());
-          difference.setNewLocation(otherObject.getLocatedAt());
-          result.add(difference);
-        }
+        difference.setPreviousLocation(myObject.getLocatedAt());
       }
-      // other difference not handled yet, e.g. object deleted, or objects having no locations
+      difference.setNewLocation(otherObject.getLocatedAt());
+      result.add(difference);
     }
     return result;
   }
@@ -60,7 +63,9 @@ aspect Computation {
     Set<Robot> robotsFitForPreviousLocation = new HashSet<>();
     Set<Robot> robotsFitForNewLocation = new HashSet<>();
     for (var robot : worldModelB().getRobotList()) {
-      if (robot.canReach(getPreviousLocation().getName())) {
+      // check if robot can reach both, location (if any) and the object
+      if ((!hasPreviousLocation() || robot.canReach(getPreviousLocation().getName())) &&
+           robot.canReach(getObject().getName())) {
         robotsFitForPreviousLocation.add(robot);
       }
       if (robot.canReach(getNewLocation().getName())) {
@@ -68,7 +73,13 @@ aspect Computation {
       }
     }
     if (robotsFitForPreviousLocation.isEmpty()) {
-      return Collections.singletonList(new ErrorOperation("No robot can reach previous location " + getPreviousLocation().getName()));
+      StringBuilder sb = new StringBuilder("No robot can reach object ");
+      sb.append(getObject().getName());
+      if (hasPreviousLocation()) {
+        sb.append(" and ").append(getPreviousLocation().getName());
+      }
+      sb.append("!");
+      return Collections.singletonList(new ErrorOperation(sb.toString()));
     }
     if (robotsFitForNewLocation.isEmpty()) {
       return Collections.singletonList(new ErrorOperation("No robot can reach new location " + getNewLocation().getName()));
@@ -178,13 +189,13 @@ aspect Printing {
 
   syn String Difference.prettyPrint();
   eq DifferenceObjectAtWrongPlace.prettyPrint() {
-    return "+DifferenceObjectAtWrongPlace of " + getObject().prettyPrint() + ": " + getPreviousLocation().prettyPrint() + " -> " + getNewLocation().prettyPrint() + "+";
+    return "-DifferenceObjectAtWrongPlace of " + getObject().prettyPrint() + ": " + (hasPreviousLocation() ? getPreviousLocation().prettyPrint() : "_") + " -> " + getNewLocation().prettyPrint() + "-";
   }
   eq DifferenceNewObject.prettyPrint() {
-    return "+DifferenceNewObject of " + getObject().prettyPrint() + "+";
+    return "-DifferenceNewObject of " + getObject().prettyPrint() + "-";
   }
   eq DifferenceObjectMisplaced.prettyPrint() {
-    return "+DifferenceObjectMisplaced of " + getObject().prettyPrint() + ": " + getPreviousLocation().prettyPrint() + "+";
+    return "-DifferenceObjectMisplaced of " + getObject().prettyPrint() + ": " + getPreviousLocation().prettyPrint() + "-";
   }
 
   syn String Operation.prettyPrint();
diff --git a/ros3rag.placeB/src/main/jastadd/WorldModelB.relast b/ros3rag.placeB/src/main/jastadd/WorldModelB.relast
index dbb21249db70b8a3a05ded34b61b5d0cb94a06b6..3263e7ff0b6d8b9de31237299829ed48abce0292 100644
--- a/ros3rag.placeB/src/main/jastadd/WorldModelB.relast
+++ b/ros3rag.placeB/src/main/jastadd/WorldModelB.relast
@@ -5,7 +5,7 @@ Robot ::= <Name:String> CanReachObjectOfInterestWrapper ;
 abstract Difference ;
 rel Difference.Object -> LogicalMovableObject ;
 DifferenceObjectAtWrongPlace : Difference ;
-rel DifferenceObjectAtWrongPlace.PreviousLocation -> LogicalDropOffLocation ;
+rel DifferenceObjectAtWrongPlace.PreviousLocation? -> LogicalDropOffLocation ;
 rel DifferenceObjectAtWrongPlace.NewLocation -> LogicalDropOffLocation ;
 DifferenceNewObject : Difference ;
 DifferenceObjectMisplaced : Difference ;
diff --git a/ros3rag.placeB/src/main/java/de/tudresden/inf/st/placeB/MainB.java b/ros3rag.placeB/src/main/java/de/tudresden/inf/st/placeB/MainB.java
index d7ce667c1169305a873e22d5b73adb254a2d89ce..201fa0eba667d16d21520f99e937eaa23415af0a 100644
--- a/ros3rag.placeB/src/main/java/de/tudresden/inf/st/placeB/MainB.java
+++ b/ros3rag.placeB/src/main/java/de/tudresden/inf/st/placeB/MainB.java
@@ -7,9 +7,12 @@ import de.tudresden.inf.st.ros3rag.common.Util;
 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.LinkedHashMap;
+import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -26,6 +29,7 @@ public class MainB {
 
   private final static String TOPIC_MODEL = "place-b/model";
   private final static String TOPIC_STATUS = "place-b/status";
+  private final static String TOPIC_REWIND = "place-b/rewind";
   private final static String TOPIC_EXIT = "place-b/exit";
 
   private final static String TOPIC_MY_SCENE_INIT = "place-b/scene/init";
@@ -39,6 +43,13 @@ public class MainB {
 
   private MqttHandler mainHandler;
   private WorldModelB model;
+  private Configuration config;
+
+  private static final Map<String, String> channelDescriptions = new LinkedHashMap<>() {{
+    put(TOPIC_MODEL, "Print current model (detailed if message starts with 'detail");
+    put(TOPIC_REWIND, "Rewind app to start");
+    put(TOPIC_EXIT, "Exit app");
+  }};
 
   public static void main(String[] args) throws Exception {
     new MainB().run(args);
@@ -49,8 +60,7 @@ public class MainB {
 
     // --- No configuration below this line ---
 
-    final var config = Util.parseConfig(UtilB.pathToDirectoryOfPlaceB().resolve(configFile).toFile());
-    model = new WorldModelB();
+    config = Util.parseConfig(UtilB.pathToDirectoryOfPlaceB().resolve(configFile).toFile());
 
     /// Prepare main handler
     mainHandler = new MqttHandler("mainHandler").dontSendWelcomeMessage();
@@ -59,11 +69,32 @@ public class MainB {
     CountDownLatch exitCondition = new CountDownLatch(1);
     mainHandler.newConnection(TOPIC_EXIT, bytes -> exitCondition.countDown());
     mainHandler.newConnection(TOPIC_MODEL, bytes -> logStatus(new String(bytes)));
+    mainHandler.newConnection(TOPIC_REWIND, bytes ->
+        {
+          try {
+            rewind("rewind");
+          } catch (Exception e) {
+            logger.catching(e);
+          }
+        }
+    );
 
     mainHandler.newConnection(TOPIC_DEMO_MOVE_objectRed1_RED, bytes ->
         UtilB.updatePositionOfObjectToLocation(model.getMyScene(), "objectRed1", "binRed")
     );
 
+    logger.info("Supported commands: {}", channelDescriptions);
+
+    rewind("Start");
+
+    Runtime.getRuntime().addShutdownHook(new Thread(this::close));
+
+    exitCondition.await();
+  }
+
+  private void rewind(String statusMessage) throws Exception {
+    model = new WorldModelB();
+
     /// Reading scene and robots
     de.tudresden.inf.st.ceti.Scene scene = readScene(
         UtilB.pathToDirectoryOfPlaceB().resolve(config.filenameInitialScene)
@@ -99,17 +130,9 @@ public class MainB {
     model.connectOtherScene(mqttUri(TOPIC_OTHER_SCENE_UPDATE_FROM_PLACE_A, config));
     model.connectNextOperation(mqttUri(TOPIC_COMMAND, config), false);
 
-    logStatus("Start");
-
-    logger.info("To print the current model states, send a message to the topic '{}'.", TOPIC_MODEL);
-    logger.info("To exit the system cleanly, send a message to the topic '{}', or use Ctrl+C.", TOPIC_EXIT);
+    logStatus(statusMessage);
 
     mainHandler.publish(TOPIC_MY_SCENE_INIT, scene.toByteArray());
-//    logger.fatal("Skipping publishing to {} for now", TOPIC_MY_SCENE_INIT);
-
-    Runtime.getRuntime().addShutdownHook(new Thread(this::close));
-
-    exitCondition.await();
   }
 
   private void logStatus(String message) {