diff --git a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp
index 6c84b806ffc36dca5a6e981da5d19a2a67f329d2..5498ee1d8538633506bb7045128f5cf150ac1b55 100644
--- a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp
+++ b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp
@@ -39,9 +39,18 @@ namespace armarx
             switch (runState)
             {
                 case RunState::scannerInit:
-                    initScanner();
-                    //read the scanner parameters for initialization
-                    result = scanner->loopOnce(scanData, scanTime, scanInfo, true);
+                    if (initCnt < 5)
+                    {
+                        initCnt++;
+                        initScanner();
+                        //read the scanner parameters for initialization
+                        result = scanner->loopOnce(scanData, scanTime, scanInfo, true);
+                    }
+                    else
+                    {
+                        ARMARX_WARNING << "Maximum number of reinitializations reached - going to idle state";
+                        runState = RunState::scannerFinalize;
+                    }
                     break;
                 case RunState::scannerRun:
                     if (result == sick_scan::ExitSuccess) // OK -> loop again
@@ -66,7 +75,8 @@ namespace armarx
                     }
                     break;
                 case RunState::scannerFinalize:
-                    ARMARX_WARNING << "scanner offline";
+                    ARMARX_WARNING << "Scanner offline - stopping task.";
+                    this->task->stop();
                     break;
                 default:
                     ARMARX_WARNING << "Invalid run state in task loop";
@@ -81,20 +91,18 @@ namespace armarx
         ARMARX_INFO_S << "Start initialising scanner [Ip: " << this->ip
                       << "] [Port: " << this->port << "]";
         // attempt to connect/reconnect
-        delete this->scanner; // disconnect scanner
-        if (this->useTcp)
+        if (this->scanner)
         {
-            this->scanner = new SickScanAdapter(this->ip, this->port, this->timelimit, this->parser, 'A');
+            ARMARX_WARNING_S << "Scanner already initized.";
+            delete this->scanner; // disconnect scanner
         }
-        else
-        {
-            ARMARX_ERROR_S << "TCP is not switched on. Probably hostname or port not set.\n";
-            return;
-        }
-        result = this->scanner->init();
 
+        this->scanner = new SickScanAdapter(this->ip, this->port, this->timelimit, this->parser, 'A');
+
+        this->result = this->scanner->init();
 
-        if (result == sick_scan::ExitSuccess) // OK -> loop again
+
+        if (this->result == sick_scan::ExitSuccess) // OK -> loop again
         {
             this->isSensorInitialized = true;
             ARMARX_INFO_S << "Scanner initialized.";
@@ -116,20 +124,18 @@ namespace armarx
         // def->topic(myTopicListener);
 
         // Subscribe to a topic (passing the topic name).
-        def->topic<LaserScannerUnitListenerPrx>(properties.topicName);
+        //def->topic<LaserScannerUnitListenerPrx>(properties.topicName);
 
         // Use (and depend on) another component (passing the ComponentInterfacePrx).
         // def->component(myComponentProxy)
 
-        def->optional(properties.topicName, "topicName", "Name of the topic");
+        def->topic(topic, properties.topicName, "TopicName", "Name of the laserscanner topic to report to.");
         //Scanner parameters
         def->optional(properties.devices, "devices", "List of Devices in format frame1,ip1,port1;frame2,ip2,port2");
+        def->optional(properties.scannerType, "scannerType", "Name of the LaserScanner");
         def->optional(properties.timelimit, "timelimit", "timelimit for communication");
-        def->required(properties.scannerType, "scannerType", "Name of the LaserScanner");
-        def->optional(properties.angleOffset, "angleOffset", "offset to the scanning angle");
         def->optional(properties.rangeMin, "rangeMin", "minimum Range of the Scanner");
         def->optional(properties.rangeMax, "rangeMax", "maximum Range of the Scanner");
-        def->optional(properties.timeIncrement, "timeIncrement", "timeIncrement??");
         return def;
     }
 
@@ -137,12 +143,12 @@ namespace armarx
     {
         // Topics and properties defined above are automagically registered.
 
+        //offeringTopic(properties.topicName);
+        //ARMARX_INFO_S << "SickLaserUnit is going to report on topic " << properties.topicName;
         // Keep debug observer data until calling `sendDebugObserverBatch()`.
         // (Requies the armarx::DebugObserverComponentPluginUser.)
         // setDebugObserverBatchModeEnabled(true);
 
-        ARMARX_INFO_S << "initializing SickLaserUnit.";
-
         std::vector<std::string> splitDeviceStrings = Split(properties.devices, ";");
         scanDevices.clear();
         scanDevices.reserve(splitDeviceStrings.size());
@@ -152,7 +158,7 @@ namespace armarx
             if (deviceInfo.size() != 3)
             {
                 ARMARX_WARNING << "Unexpected format for laser scanner device: " << deviceString
-                               << " (split size: " << deviceInfo.size() << ")";
+                               << " (split size: " << deviceInfo.size() << ", expected: 3)";
                 continue;
             }
             SickLaserScanDevice& device = scanDevices.emplace_back();
@@ -161,41 +167,41 @@ namespace armarx
             device.frameName = deviceInfo[0];
             if (deviceInfo[1] != "")
             {
-                device.useTcp = true;
                 device.ip = deviceInfo[1];
             }
+            else
+            {
+                ARMARX_FATAL << "TCP is not switched on. Probably hostname or port not set.";
+                return;
+
+            }
             device.port = deviceInfo[2];
-            device.angleOffset = properties.angleOffset;
             device.timelimit = properties.timelimit;
-            device.scannerType = properties.scannerType;
-            device.rangeMin = properties.rangeMin;
-            device.rangeMax = properties.rangeMax;
-            device.timeIncrement = properties.timeIncrement;
+            //scanInfo
+            device.scanInfo.device = device.ip;
+            device.scanInfo.frame = device.frameName;
             //scanner Parameters
             try
             {
-                device.parser = new sick_scan::SickGenericParser(device.scannerType);
+                device.parser = new sick_scan::SickGenericParser(properties.scannerType);
                 device.parser->set_range_min(properties.rangeMin);
                 device.parser->set_range_max(properties.rangeMax);
-                device.parser->set_time_increment(properties.timeIncrement);
+                device.parser->getCurrentParamPtr()->setUseBinaryProtocol(false);
             }
             catch (std::exception const& e)
             {
                 ARMARX_ERROR_S << "Could not create parser. Wrong Scanner name.";
                 return;
             }
-            device.parser->getCurrentParamPtr()->setUseBinaryProtocol(false);
-            device.colaDialectId = 'A';
-        }
 
-        //addPlugin(heartbeat);
-        //configureHeartbeatChannel();
+            //addPlugin(heartbeat);
+            //configureHeartbeatChannel();
+        }
     }
 
     void SickLaserUnit::onConnectComponent()
     {
-        topic = getTopic<LaserScannerUnitListenerPrx>(properties.topicName);
-        offeringTopic(properties.topicName);
+        //topic = getTopic<LaserScannerUnitListenerPrx>(properties.topicName);
 
         for (SickLaserScanDevice& device : scanDevices)
         {
@@ -203,6 +209,7 @@ namespace armarx
             //start the laser scanner
             if (device.task)
             {
+                ARMARX_WARNING << "this should not happen.";
                 device.task->stop();
                 device.task = nullptr;
             }
@@ -217,23 +224,9 @@ namespace armarx
         // The data can be viewed in the ObserverView and the LivePlotter.
         // (Before starting any threads, we don't need to lock mutexes.)
         {
-            setDebugObserverDatafield("numBoxes", properties.numBoxes);
-            setDebugObserverDatafield("boxLayerName", properties.boxLayerName);
-            sendDebugObserverBatch();
-        }
-        */
-
-        /* (Requires the armarx::ArVizComponentPluginUser.)
-        // Draw boxes in ArViz.
-        // (Before starting any threads, we don't need to lock mutexes.)
-        drawBoxes(properties, arviz);
-        */
-
-        /* (Requires the armarx::LightweightRemoteGuiComponentPluginUser.)
-        // Setup the remote GUI.
-        {
-            createRemoteGuiTab();
-            RemoteGui_startRunningTask();
+        setDebugObserverDatafield("numBoxes", properties.numBoxes);
+        setDebugObserverDatafield("boxLayerName", properties.boxLayerName);
+        sendDebugObserverBatch();
         }
         */
     }
@@ -248,6 +241,14 @@ namespace armarx
                 device.task->stop();
                 device.task = nullptr;
             }
+        }
+    }
+
+    void SickLaserUnit::onExitComponent()
+    {
+        for (SickLaserScanDevice& device : scanDevices)
+        {
+
             if (device.scanner)
             {
                 delete device.scanner;
@@ -257,90 +258,13 @@ namespace armarx
                 delete device.parser;
             }
         }
-    }
 
-    void SickLaserUnit::onExitComponent() {}
 
-    std::string SickLaserUnit::getDefaultName() const
-    {
-        return "SickLaserUnit";
-    }
-
-    /* (Requires the armarx::LightweightRemoteGuiComponentPluginUser.)
-    void SickLaserUnit::createRemoteGuiTab()
-    {
-    using namespace armarx::RemoteGui::Client;
-
-    // Setup the widgets.
-
-    tab.boxLayerName.setValue(properties.boxLayerName);
-
-    tab.numBoxes.setValue(properties.numBoxes);
-    tab.numBoxes.setRange(0, 100);
-
-    tab.drawBoxes.setLabel("Draw Boxes");
-
-    // Setup the layout.
-
-    GridLayout grid;
-    int row = 0;
-    {
-    grid.add(Label("Box Layer"), {row, 0}).add(tab.boxLayerName, {row, 1});
-    ++row;
-
-    grid.add(Label("Num Boxes"), {row, 0}).add(tab.numBoxes, {row, 1});
-    ++row;
-
-    grid.add(tab.drawBoxes, {row, 0}, {2, 1});
-    ++row;
-    }
-
-    VBoxLayout root = {grid, VSpacer()};
-    RemoteGui_createTab(getName(), root, &tab);
     }
 
-
-    void SickLaserUnit::RemoteGui_update()
-    {
-    if (tab.boxLayerName.hasValueChanged() || tab.numBoxes.hasValueChanged())
-    {
-    std::scoped_lock lock(propertiesMutex);
-    properties.boxLayerName = tab.boxLayerName.getValue();
-    properties.numBoxes = tab.numBoxes.getValue();
-
-    {
-    setDebugObserverDatafield("numBoxes", properties.numBoxes);
-    setDebugObserverDatafield("boxLayerName", properties.boxLayerName);
-    sendDebugObserverBatch();
-    }
-    }
-    if (tab.drawBoxes.wasClicked())
-    {
-    // Lock shared variables in methods running in seperate threads
-    // and pass them to functions. This way, the called functions do
-    // not need to think about locking.
-    std::scoped_lock lock(propertiesMutex, arvizMutex);
-    drawBoxes(properties, arviz);
-    }
-    }
-    */
-
-    /* (Requires the armarx::ArVizComponentPluginUser.)
-    void SickLaserUnit::drawBoxes(const SickLaserUnit::Properties& p, viz::Client&
-    arviz)
-    {
-    // Draw something in ArViz (requires the armarx::ArVizComponentPluginUser.
-    // See the ArVizExample in RobotAPI for more examples.
-
-    viz::Layer layer = arviz.layer(p.boxLayerName);
-    for (int i = 0; i < p.numBoxes; ++i)
+    std::string SickLaserUnit::getDefaultName() const
     {
-    layer.add(viz::Box("box_" + std::to_string(i))
-      .position(Eigen::Vector3f(i * 100, 0, 0))
-      .size(20).color(simox::Color::blue()));
-    }
-    arviz.commit(layer);
+        return "SickLaserUnit";
     }
-    */
 
 } // namespace armarx
diff --git a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h
index 69d6385c130969a4d18a6d104f91765ec4d9a876..f6ffc67a1ad3992967c8a4526dd6640b21caa4fb 100644
--- a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h
+++ b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h
@@ -54,30 +54,22 @@ namespace armarx
 
     struct SickLaserScanDevice
     {
-        //scanner parameters
-        std::string scannerType = "sick_tim_5xx";
-        double angleOffset = 0.0;
-        double rangeMin;
-        double rangeMax;
-        double timeIncrement;
         //communication parameters
         std::string ip;
         std::string port;
         int timelimit = 5;
-        bool useTcp = false;
-        char colaDialectId = 'A';
         //data and task pointers
         IceUtil::Time scanTime;
         LaserScan scanData;
         LaserScannerInfo scanInfo;
+        int initCnt = 0;
         RunState runState = RunState::scannerFinalize;
         RunningTask<SickLaserScanDevice>::pointer_type task;
         std::string frameName = "LaserScannerFront";
         LaserScannerUnitListenerPrx scanTopic;
-
-        sick_scan::SickScanConfig cfg;
-        sick_scan::SickGenericParser* parser;
-        SickScanAdapter* scanner;
+        //scanner pointers
+        sick_scan::SickGenericParser* parser = 0;
+        SickScanAdapter* scanner = 0;
         int result = sick_scan::ExitError;
         bool isSensorInitialized = false;
 
@@ -134,12 +126,10 @@ namespace armarx
             std::string topicName = "SICKLaserScanner";
             //scanner parameters
             std::string devices = "LaserScannerFront,192.168.8.133,2112";
-            int timelimit = 5;
             std::string scannerType = "sick_tim_5xx";
-            double angleOffset = 0.0;
+            int timelimit = 5;
             double rangeMin  = 0.0;
             double rangeMax = 10.0;
-            double timeIncrement = 0.1;
         };
         Properties properties;
         std::vector<SickLaserScanDevice> scanDevices;
diff --git a/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.cpp b/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.cpp
index 1e9a011f3b044f6dbab583c5769d8c142fcf9a7c..69d33ced49a00c415f7e08456d21177c27dfb8b6 100644
--- a/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.cpp
+++ b/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.cpp
@@ -111,7 +111,6 @@ namespace armarx
         port_(port),
         timelimit_(timelimit)
     {
-
         if ((cola_dialect_id == 'a') || (cola_dialect_id == 'A'))
         {
             this->setProtocolType(CoLa_A);
@@ -155,9 +154,10 @@ namespace armarx
         unsigned char receiveBuffer[65536];
         int actual_length = 0;
         int packetsInLoop = 0;
+        bool useBinaryProtocol = parser_ptr->getCurrentParamPtr()->getUseBinaryProtocol();
 
         ros::Time recvTimeStamp = ros::Time::now();  // timestamp incoming package, will be overwritten by get_datagram
-        int result = get_datagram(recvTimeStamp, receiveBuffer, 65536, &actual_length, false, &packetsInLoop);
+        int result = get_datagram(recvTimeStamp, receiveBuffer, 65536, &actual_length, useBinaryProtocol, &packetsInLoop);
         //ros::Duration dur = recvTimeStampPush - recvTimeStamp;
         if (result != 0)
         {
@@ -347,6 +347,7 @@ namespace armarx
         // 23: Starting angle (FFF92230)
         if (updateScannerInfo)
         {
+            scanInfo.device = hostname_;
             uint starting_angle = (uint) - 1;
             sscanf(fields[23], "%x", &starting_angle);
             scanInfo.minAngle = (starting_angle / 10000.0) / 180.0 * M_PI - M_PI / 2;
@@ -438,7 +439,6 @@ namespace armarx
             ARMARX_ERROR_S << "Number of distance measurements does not match number of intensity values - Skipping";
             return sick_scan::ExitError;
         }
-        //TODO: Write ScanSteps with intensity
         scanData.reserve(distVal.size());
         for (int i = 0; i < (int) distVal.size(); i++)
         {
diff --git a/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice
index a1ba8214cc56505b4a22af4d136d11e4cff5e7ac..56a17ef1928de4779241c59a432f7b6baaf50019 100644
--- a/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice
+++ b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice
@@ -362,7 +362,7 @@ module armarx
 
         void enableForceStop();
         void disableForceStop();
-        void setForceThreshold(float forceThreshold);
+        void setForceThreshold(Eigen::Vector3f forceThreshold);
     };
 
     class NJointTaskSpaceAdaptiveDMPControllerConfig extends NJointControllerConfig
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/CMakeLists.txt b/source/RobotAPI/libraries/RobotAPIComponentPlugins/CMakeLists.txt
index a4ca9b08ad6d3b0937294c5a9050adb6680abfcc..594e05ed14002d7098c2ecaa41a5d627e3f9ea24 100644
--- a/source/RobotAPI/libraries/RobotAPIComponentPlugins/CMakeLists.txt
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/CMakeLists.txt
@@ -25,6 +25,7 @@ set(LIB_FILES
     NaturalIKComponentPlugin.cpp
     HandUnitComponentPlugin.cpp
     FrameTrackingComponentPlugin.cpp
+    HeartbeatComponentPlugin.cpp
 )
 set(LIB_HEADERS
     RobotStateComponentPlugin.h
@@ -40,6 +41,7 @@ set(LIB_HEADERS
     NaturalIKComponentPlugin.h
     HandUnitComponentPlugin.h
     FrameTrackingComponentPlugin.h
+    HeartbeatComponentPlugin.h
 )
 
 armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}")
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/HeartbeatComponentPlugin.cpp b/source/RobotAPI/libraries/RobotAPIComponentPlugins/HeartbeatComponentPlugin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..510ff8933b6e045ec96e1020e6914f2b064636f2
--- /dev/null
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/HeartbeatComponentPlugin.cpp
@@ -0,0 +1,98 @@
+#include "HeartbeatComponentPlugin.h"
+
+#include "ArmarXCore/core/Component.h"
+#include "ArmarXCore/core/exceptions/local/ExpressionException.h"
+
+#include <RobotAPI/interface/components/RobotHealthInterface.h>
+
+namespace armarx::plugins
+{
+    void
+    HeartbeatComponentPlugin::configureHeartbeatChannel(const std::string& channel,
+            const RobotHealthHeartbeatArgs& args)
+    {
+        channelHeartbeatConfig.emplace(channel, args);
+    }
+
+    void
+    HeartbeatComponentPlugin::heartbeat()
+    {
+
+        if (robotHealthTopic)
+        {
+            robotHealthTopic->heartbeat(componentName, heartbeatArgs);
+        }
+        else
+        {
+            ARMARX_WARNING << "No robot health topic available!";
+        }
+    }
+
+    void
+    HeartbeatComponentPlugin::heartbeat(const std::string& channel)
+    {
+        const auto argsIt = channelHeartbeatConfig.find(channel);
+        ARMARX_CHECK(argsIt != channelHeartbeatConfig.end())
+                << "heartbeat() called for unknown channel '" << channel << "'."
+                << "You must register the config using configureHeartbeatChannel(channel) first!";
+
+        const auto& args = argsIt->second;
+
+        if (robotHealthTopic)
+        {
+            robotHealthTopic->heartbeat(componentName + "_" + channel, args);
+        }
+        else
+        {
+            ARMARX_WARNING << "No robot health topic available!";
+        }
+    }
+
+    void
+    HeartbeatComponentPlugin::preOnInitComponent()
+    {
+        if (topicName.empty())
+        {
+            parent<Component>().getProperty(topicName, makePropertyName(topicPropertyName));
+        }
+        parent<Component>().offeringTopic(topicName);
+    }
+
+    void
+    HeartbeatComponentPlugin::postOnInitComponent()
+    {
+    }
+
+    void
+    HeartbeatComponentPlugin::preOnConnectComponent()
+    {
+        robotHealthTopic = parent<Component>().getTopic<RobotHealthInterfacePrx>(topicName);
+    }
+
+    void
+    HeartbeatComponentPlugin::postCreatePropertyDefinitions(PropertyDefinitionsPtr& properties)
+    {
+        if (!properties->hasDefinition(makePropertyName(topicPropertyName)))
+        {
+            properties->defineOptionalProperty<std::string>(
+                makePropertyName(topicPropertyName),
+                "DebugObserver",
+                "Name of the topic the DebugObserver listens on");
+        }
+
+        if (not properties->hasDefinition(makePropertyName(maximumCycleTimeWarningMSPropertyName)))
+        {
+            properties->defineRequiredProperty<std::string>(
+                makePropertyName(maximumCycleTimeWarningMSPropertyName),
+                "TODO: maximumCycleTimeWarningMS");
+        }
+
+        if (not properties->hasDefinition(makePropertyName(maximumCycleTimeErrorMSPropertyName)))
+        {
+            properties->defineRequiredProperty<std::string>(
+                makePropertyName(maximumCycleTimeErrorMSPropertyName),
+                "TODO: maximumCycleTimeErrorMS");
+        }
+    }
+
+} // namespace armarx::plugins
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/HeartbeatComponentPlugin.h b/source/RobotAPI/libraries/RobotAPIComponentPlugins/HeartbeatComponentPlugin.h
new file mode 100644
index 0000000000000000000000000000000000000000..6a4a6c2bd692484c94bbd42bdfff399b0f5a0aa9
--- /dev/null
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/HeartbeatComponentPlugin.h
@@ -0,0 +1,89 @@
+/**
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <ArmarXCore/core/ComponentPlugin.h>
+
+#include <RobotAPI/interface/components/RobotHealthInterface.h>
+
+namespace armarx::plugins
+{
+
+    class HeartbeatComponentPlugin : public ComponentPlugin
+    {
+    public:
+        using ComponentPlugin::ComponentPlugin;
+
+        /**
+         * @brief Configures a heartbeat subchannel.
+         *
+         * @param channel Identifier of the heartbeat channel
+         * @param args Configuration of this channel's heartbeat properties
+         */
+        void configureHeartbeatChannel(const std::string& channel,
+                                       const RobotHealthHeartbeatArgs& args);
+
+        /**
+         * @brief Sends out a heartbeat using the default config
+         *
+         */
+        void heartbeat();
+
+        /**
+         * @brief Sends out a heartbeat for a subchannel.
+         *
+         * Note: You must call configureHeartbeatChannel(...) first to register the channel config!
+         *
+         * @param channel Identifier of the heartbeat channel
+         */
+        void heartbeat(const std::string& channel);
+
+    protected:
+        void preOnInitComponent() override;
+        void postOnInitComponent() override;
+        void preOnConnectComponent() override;
+
+        void postCreatePropertyDefinitions(PropertyDefinitionsPtr& properties) override;
+
+    private:
+        //! heartbeat topic name (outgoing)
+        std::string topicName;
+
+        //! name of this component used as identifier for heartbeats
+        std::string componentName;
+
+        //
+        static constexpr auto topicPropertyName = "heartbeat.TopicName";
+        static constexpr auto maximumCycleTimeWarningMSPropertyName =
+            "heartbeat.maximumCycleTimeWarningMS";
+        static constexpr auto maximumCycleTimeErrorMSPropertyName =
+            "heartbeat.maximumCycleTimeErrorMS";
+
+        RobotHealthInterfacePrx robotHealthTopic;
+
+        //! default config used in heartbeat(), set via properties
+        RobotHealthHeartbeatArgs heartbeatArgs;
+
+        //! configs used in heartbeat(channel), set by user via configureHeartbeatChannel(...)
+        std::unordered_map<std::string, RobotHealthHeartbeatArgs> channelHeartbeatConfig;
+    };
+} // namespace armarx::plugins
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.cpp
index 5fc97fcf5e21a6368abf52956457a7ec9f642193..d550b478c148c97372098e8e40dd7927bafa144f 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.cpp
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.cpp
@@ -46,7 +46,8 @@ namespace armarx
         forceOffset.setZero();
         filteredForce.setZero();
         filteredForceInRoot.setZero();
-
+        forceThreshold.getWriteBuffer() = cfg->forceThreshold;
+        forceThreshold.commitWrite();
         tcp =  rns->getTCP();
         ik.reset(new VirtualRobot::DifferentialIK(rns, rtGetRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
         ik->setDampedSvdLambda(0.0001);
@@ -292,7 +293,7 @@ namespace armarx
 
                     for (size_t i = 0; i < 3; ++i)
                     {
-                        if (fabs(filteredForceInRoot[i]) > cfg->forceThreshold[i])
+                        if (fabs(filteredForceInRoot[i]) > forceThreshold.getUpToDateReadBuffer()[i])
                         {
                             stopPose = currentPose;
                             targetVel.setZero(6);
@@ -551,6 +552,11 @@ namespace armarx
             usleep(100);
         }
 
+        while (!interfaceData.updateReadBuffer())
+        {
+            usleep(100);
+        }
+
         Eigen::Matrix4f pose = interfaceData.getUpToDateReadBuffer().currentTcpPose;
         dmpCtrl->prepareExecution(dmpCtrl->eigen4f2vec(pose), goals);
 
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.h
index c0f8fea9525c5f261141a0658bdca7852a9eb263..3a6f685e412940d03b483a90dd92b9b346d9436f 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.h
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.h
@@ -94,9 +94,11 @@ namespace armarx
         {
             useForceStop = false;
         }
-        void setForceThreshold(float forceThreshold, const Ice::Current&) override
+
+        void setForceThreshold(const Eigen::Vector3f& f, const Ice::Current& current) override
         {
-            this->forceThreshold = forceThreshold;
+            forceThreshold.getWriteBuffer() = f;
+            forceThreshold.commitWrite();
         }
     protected:
         virtual void onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx&) override;
@@ -248,7 +250,7 @@ namespace armarx
         Eigen::Vector3f filteredForce;
         Eigen::Vector3f forceOffset;
         Eigen::Vector3f filteredForceInRoot;
-        std::atomic<float> forceThreshold;
+        WriteBufferedTripleBuffer<Eigen::Vector3f> forceThreshold;
         std::atomic<bool> useForceStop;
         std::atomic<float> timeForCalibration;
         const SensorValueForceTorque* forceSensor;
diff --git a/source/RobotAPI/libraries/armem/client/Query.h b/source/RobotAPI/libraries/armem/client/Query.h
index 916278a8fcde1679545ed39d59531f5772852c13..c6bb445bfe8ee9a3547ae621aa8c16ec8e0e2be9 100644
--- a/source/RobotAPI/libraries/armem/client/Query.h
+++ b/source/RobotAPI/libraries/armem/client/Query.h
@@ -60,6 +60,38 @@ namespace armarx::armem::client
             }
         }
 
+        void replaceQueryTarget(const armem::query::data::QueryTarget search, const armem::query::data::QueryTarget replace)
+        {
+            for (const auto& memoryQuery : memoryQueries)
+            {
+                if (auto it = std::find(memoryQuery->targets.begin(), memoryQuery->targets.end(), search); it != memoryQuery->targets.end())
+                {
+                    memoryQuery->targets.push_back(replace);
+                }
+                for (const auto& coreSegmentQuery : memoryQuery->coreSegmentQueries)
+                {
+                    if (auto it = std::find(coreSegmentQuery->targets.begin(), coreSegmentQuery->targets.end(), search); it != coreSegmentQuery->targets.end())
+                    {
+                        coreSegmentQuery->targets.push_back(replace);
+                    }
+                    for (const auto& providerSegmentQuery : coreSegmentQuery->providerSegmentQueries)
+                    {
+                        if (auto it = std::find(providerSegmentQuery->targets.begin(), providerSegmentQuery->targets.end(), search); it != providerSegmentQuery->targets.end())
+                        {
+                            providerSegmentQuery->targets.push_back(replace);
+                        }
+                        for (const auto& entityQuery : providerSegmentQuery->entityQueries)
+                        {
+                            if (auto it = std::find(entityQuery->targets.begin(), entityQuery->targets.end(), search); it != entityQuery->targets.end())
+                            {
+                                entityQuery->targets.push_back(replace);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
         static QueryInput fromIce(const armem::query::data::Input& ice);
         armem::query::data::Input toIce() const;
     };
diff --git a/source/RobotAPI/libraries/armem/core/base/MemoryBase.h b/source/RobotAPI/libraries/armem/core/base/MemoryBase.h
index 781322b5493388f2e88d5b0b7d20242b79048ca4..1bc42b0cc579dbf8abe4f2831608166451ff8fbb 100644
--- a/source/RobotAPI/libraries/armem/core/base/MemoryBase.h
+++ b/source/RobotAPI/libraries/armem/core/base/MemoryBase.h
@@ -336,6 +336,25 @@ namespace armarx::armem::base
             return this->name();
         }
 
+        std::string dump() const
+        {
+            std::stringstream ss;
+            ss << "Memory: " << this->name() << "\n";
+            for (const auto& [ckey, cseg] : this->container())
+            {
+                ss << " |- Found core seg: " << ckey << "\n";
+                for (const auto& [pkey, pseg] : cseg.container())
+                {
+                    ss << " |   |- Found prov seg: " << pkey << "\n";
+                    for (const auto& [ekey, eseg] : pseg.container())
+                    {
+                        ss << " |   |   |- Found entity: " << ekey << "\n";
+                    }
+                }
+            }
+            return ss.str();
+        }
+
     protected:
 
         virtual void _copySelf(DerivedT& other) const override
diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/CoreSegment.cpp b/source/RobotAPI/libraries/armem/core/longtermmemory/CoreSegment.cpp
index a64a5982e143e2627718f5039d3559b2d3479348..d47dc46cb63c5266edc8b9e8457c1fb4b75a4527 100644
--- a/source/RobotAPI/libraries/armem/core/longtermmemory/CoreSegment.cpp
+++ b/source/RobotAPI/libraries/armem/core/longtermmemory/CoreSegment.cpp
@@ -10,8 +10,6 @@ namespace armarx::armem::ltm
 
     wm::CoreSegment CoreSegment::convert() const
     {
-        ARMARX_INFO << "CoreSegment: Converting with connection to: " << dbsettings.toString();
-
         wm::CoreSegment m(id());
         for (const auto& [_, s] : _container)
         {
@@ -24,8 +22,6 @@ namespace armarx::armem::ltm
     {
         _container.clear();
 
-        ARMARX_INFO << "CoreSegment: (Re)Establishing connection to: " << dbsettings.toString();
-
         mongocxx::client& client = MongoDBConnectionManager::EstablishConnection(dbsettings);
         mongocxx::database db = client[dbsettings.database];
         mongocxx::collection coll = db[id().str()];
@@ -47,7 +43,7 @@ namespace armarx::armem::ltm
 
             if (const auto& it = _container.find(k); it != _container.end())
             {
-                throw error::ArMemError("Somehow after clearing the container a key k = " + k + " was found. Do you have double entries in mongodb?");
+                throw error::ArMemError("Somehow after clearing the (core) container a key k = " + k + " was found. Do you have double entries in mongodb?");
             }
             else
             {
@@ -56,6 +52,8 @@ namespace armarx::armem::ltm
                 wms.first->second.reload();
             }
         }
+
+        ARMARX_INFO << "After reload has core segment " << id().str() << " size: " << _container.size();
     }
 
     void CoreSegment::append(const wm::CoreSegment& m)
diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.cpp b/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.cpp
index aeb2be76e6ae6951188af4174b9b11dc51d736fc..bccb79c9d1d162a6c67a4f80c57b58b04425863e 100644
--- a/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.cpp
+++ b/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.cpp
@@ -6,8 +6,6 @@ namespace armarx::armem::ltm
 
     wm::Entity Entity::convert() const
     {
-        ARMARX_INFO << "Entity: Converting with connection to: " << dbsettings.toString();
-
         wm::Entity m(id());
         for (const auto& [_, s] : _container)
         {
@@ -20,8 +18,6 @@ namespace armarx::armem::ltm
     {
         _container.clear();
 
-        ARMARX_INFO << "Entity: (Re)Establishing connection to: " << dbsettings.toString();
-
         mongocxx::client& client = MongoDBConnectionManager::EstablishConnection(dbsettings);
         mongocxx::database db = client[dbsettings.database];
         mongocxx::collection coll = db[id().str()];
@@ -42,7 +38,7 @@ namespace armarx::armem::ltm
 
             if (const auto& it = _container.find(k); it != _container.end())
             {
-                throw error::ArMemError("Somehow after clearing the container a key k = " + std::to_string(k.toMicroSeconds()) + " was found. Do you have double entries in mongodb?");
+                throw error::ArMemError("Somehow after clearing the (entity) container a key k = " + std::to_string(k.toMicroSeconds()) + " was found. Do you have double entries in mongodb?");
             }
             else
             {
@@ -52,6 +48,8 @@ namespace armarx::armem::ltm
             }
             ++i;
         }
+
+        ARMARX_INFO << "After reload has entity " << id().str() << " size: " << _container.size();
     }
 
     void Entity::append(const wm::Entity& m)
diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/EntitySnapshot.cpp b/source/RobotAPI/libraries/armem/core/longtermmemory/EntitySnapshot.cpp
index 47a680731f9794c99433a114dd94a9ad22f5cbea..aae8a6d3258c94a27e9f931838a44c8d1b6426aa 100644
--- a/source/RobotAPI/libraries/armem/core/longtermmemory/EntitySnapshot.cpp
+++ b/source/RobotAPI/libraries/armem/core/longtermmemory/EntitySnapshot.cpp
@@ -13,8 +13,6 @@ namespace armarx::armem::ltm
 
     wm::EntitySnapshot EntitySnapshot::convert(const aron::typenavigator::NavigatorPtr& expectedStructure) const
     {
-        ARMARX_INFO << "EntitySnapshot: Converting with connection to: " << dbsettings.toString();
-
         mongocxx::client& client = MongoDBConnectionManager::EstablishConnection(dbsettings);
         mongocxx::database db = client[dbsettings.database];
         mongocxx::collection coll = db[id().getEntityID().str()];
@@ -52,8 +50,6 @@ namespace armarx::armem::ltm
     {
         _container.clear();
 
-        ARMARX_INFO << "EntitySnapshot: (Re)Establishing connection to: " << dbsettings.toString();
-
         mongocxx::client& client = MongoDBConnectionManager::EstablishConnection(dbsettings);
         mongocxx::database db = client[dbsettings.database];
         mongocxx::collection coll = db[id().getEntityID().str()];
@@ -68,10 +64,8 @@ namespace armarx::armem::ltm
         nlohmann::json json = nlohmann::json::parse(bsoncxx::to_json(*res));
         for (unsigned int i = 0; i < json.at("instances").size(); ++i)
         {
-            auto wms = _container.emplace_back(id().withInstanceIndex(i));
+            _container.emplace_back(id().withInstanceIndex(i));
         }
-
-        ARMARX_INFO << "Entity '" + id().str() + "': Found instances in LTM: " << json.at("instances").size();
     }
 
     void EntitySnapshot::setTo(const wm::EntitySnapshot& m, const armem::Time& t)
diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.cpp b/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.cpp
index 95ad5af75460d3f106b81f5fcc9d4c11ebb2038d..2080879c55f1dd94e5aeeb2f6d78f72ada5c4aaf 100644
--- a/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.cpp
+++ b/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.cpp
@@ -27,7 +27,8 @@ namespace armarx::armem::ltm
         dbsettings(other.dbsettings),
         alwaysTransferSettings(other.alwaysTransferSettings),
         periodicTransferSettings(other.periodicTransferSettings),
-        onFullTransferSettings(other.onFullTransferSettings)
+        onFullTransferSettings(other.onFullTransferSettings),
+        reloaded(other.reloaded)
     {
         // Do not move _mutex.
     }
@@ -53,6 +54,7 @@ namespace armarx::armem::ltm
         alwaysTransferSettings = std::move(other.alwaysTransferSettings);
         periodicTransferSettings = std::move(other.periodicTransferSettings);
         onFullTransferSettings = std::move(other.onFullTransferSettings);
+        reloaded = other.reloaded;
 
         // Don't move _mutex.
         return *this;
@@ -88,13 +90,14 @@ namespace armarx::armem::ltm
 
     wm::Memory Memory::convert() const
     {
+        std::lock_guard l(mongoDBMutex);
         if (!checkConnection())
         {
             wm::Memory m(id());
             return m;
         }
 
-        ARMARX_INFO << "Converting with connection to: " << dbsettings.toString();
+        ARMARX_INFO << "Converting Memory with connection to: " << dbsettings.toString();
 
         TIMING_START(LTM_Convert);
 
@@ -110,18 +113,20 @@ namespace armarx::armem::ltm
 
     void Memory::reload()
     {
+        std::lock_guard l(mongoDBMutex);
+        reloaded = false;
+
         if (!checkConnection())
         {
             return;
         }
 
-        std::scoped_lock l(mongoDBMutex);
         ARMARX_INFO << "(Re)Establishing connection to: " << dbsettings.toString();
+
+        TIMING_START(LTM_Reload);
         _container.clear();
 
-        ARMARX_TRACE;
         mongocxx::client& client = MongoDBConnectionManager::EstablishConnection(dbsettings);
-        ARMARX_TRACE;
         if (!client)
         {
             ARMARX_ERROR << "A client has died. Could not reload.";
@@ -139,6 +144,8 @@ namespace armarx::armem::ltm
         ARMARX_INFO << "Getting collection for id: " << id().str();
         mongocxx::collection coll = db[id().str()];
 
+        ARMARX_IMPORTANT << "Memory Container size is: " << _container.size();
+
         mongocxx::cursor cursor = coll.find({});
         for (const auto& doc : cursor)
         {
@@ -155,7 +162,7 @@ namespace armarx::armem::ltm
 
             if (const auto& it = _container.find(k); it != _container.end())
             {
-                throw error::ArMemError("Somehow after clearing the container a key k = " + k + " was found. Do you have double entries in mongodb?");
+                throw error::ArMemError("Somehow after clearing the (memory) container a key k = " + k + " was found. Do you have double entries in mongodb?");
             }
             else
             {
@@ -164,17 +171,26 @@ namespace armarx::armem::ltm
                 wms.first->second.reload();
             }
         }
+
+        reloaded = true;
+        for (const auto& m : toAppendQueue)
+        {
+            _append(m);
+        }
+
+        TIMING_END(LTM_Reload);
+        ARMARX_INFO << "After reload memory " << id().str() << " size: " << _container.size() << ". Setting reloaded: " << reloaded;
     }
 
-    void Memory::append(const wm::Memory& m)
+    void Memory::_append(const wm::Memory& m)
     {
-        if (!checkConnection())
+        if (!checkConnection() || !reloaded)
         {
+            // We ignore if not fully loaded yet
             return;
         }
 
-        std::scoped_lock l(mongoDBMutex);
-        ARMARX_INFO << "Merge memory with name '" << m.name() << "' into the LTM with name '" << name() << "'";
+        //ARMARX_INFO << "Merge memory with name '" << m.name() << "' into the LTM with name '" << name() << "'";
 
         TIMING_START(LTM_Append);
 
@@ -205,4 +221,16 @@ namespace armarx::armem::ltm
 
         TIMING_END(LTM_Append);
     }
+
+    void Memory::append(const wm::Memory& m)
+    {
+        std::lock_guard l(mongoDBMutex);
+        if (!checkConnection() || !reloaded)
+        {
+            toAppendQueue.push_back(m);
+            return;
+        }
+
+        _append(m);
+    }
 }
diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.h b/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.h
index 43b67c82ca91a09e875f1c3f85949a45e4f2c83f..b24f4a7a662e2b5980d3dec00ecbb39b2c972673 100644
--- a/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.h
+++ b/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.h
@@ -87,6 +87,8 @@ namespace armarx::armem::ltm
     private:
         bool checkConnection() const;
 
+        void _append(const wm::Memory&);
+
     public:
         MongoDBConnectionManager::MongoDBSettings dbsettings;
 
@@ -95,8 +97,9 @@ namespace armarx::armem::ltm
         OnFullTransferSettings onFullTransferSettings;
 
     private:
+        bool reloaded = false;
         mutable std::mutex mongoDBMutex;
 
-
+        std::vector<wm::Memory> toAppendQueue;
     };
 }
diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/ProviderSegment.cpp b/source/RobotAPI/libraries/armem/core/longtermmemory/ProviderSegment.cpp
index aac80459904cae59550ecdf33f7057f92ed03aa4..5fcf4a1351e34f257e773c2ac32e9d4eb64c5401 100644
--- a/source/RobotAPI/libraries/armem/core/longtermmemory/ProviderSegment.cpp
+++ b/source/RobotAPI/libraries/armem/core/longtermmemory/ProviderSegment.cpp
@@ -10,8 +10,6 @@ namespace armarx::armem::ltm
 
     wm::ProviderSegment ProviderSegment::convert() const
     {
-        ARMARX_INFO << "ProviderSegment: Converting with connection to: " << dbsettings.toString();
-
         wm::ProviderSegment m(id());
         for (const auto& [_, s] : _container)
         {
@@ -24,8 +22,6 @@ namespace armarx::armem::ltm
     {
         _container.clear();
 
-        ARMARX_INFO << "ProviderSegment: (Re)Establishing connection to: " << dbsettings.toString();
-
         mongocxx::client& client = MongoDBConnectionManager::EstablishConnection(dbsettings);
         mongocxx::database db = client[dbsettings.database];
         mongocxx::collection coll = db[id().str()];
@@ -34,7 +30,6 @@ namespace armarx::armem::ltm
         for (auto doc : cursor)
         {
             nlohmann::json json = nlohmann::json::parse(bsoncxx::to_json(doc));
-            ARMARX_INFO << "ProviderSegment: Found foreign key: " << json.at("foreign_key");
 
             MemoryID i((std::string) json.at("foreign_key"));
             if (i.providerSegmentName != id().providerSegmentName)
@@ -46,7 +41,7 @@ namespace armarx::armem::ltm
 
             if (const auto& it = _container.find(k); it != _container.end())
             {
-                throw error::ArMemError("Somehow after clearing the container a key k = " + k + " was found. Do you have double entries in mongodb?");
+                throw error::ArMemError("Somehow after clearing the (provvider) container a key k = " + k + " was found. Do you have double entries in mongodb?");
             }
             else
             {
@@ -55,6 +50,8 @@ namespace armarx::armem::ltm
                 wms.first->second.reload();
             }
         }
+
+        ARMARX_INFO << "After reload has provider segment " << id().str() << " size: " << _container.size();
     }
 
     void ProviderSegment::append(const wm::ProviderSegment& m)
diff --git a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
index 8015368837e3ea37c8e5a87837d8a3a69536e04e..354eec9cea9d1d1e37f4dc4ea790b47ba1749755 100644
--- a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
+++ b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
@@ -173,6 +173,7 @@ namespace armarx::armem::server
                 result.timeArrived = update.timeArrived;
 
                 // also store in ltm if transfermode is set to always
+                // TODO: Move outside of loop?
                 if (longtermMemory)
                 {
                     if (longtermMemory->alwaysTransferSettings.enabled)
@@ -235,24 +236,43 @@ namespace armarx::armem::server
         // Core segment processors will aquire the core segment locks.
         armem::wm::query_proc::MemoryQueryProcessor wmProcessor(
             input.withData ? armem::DataMode::WithData : armem::DataMode::NoData);
-        wm::Memory wmResult = wmProcessor.process(input, *workingMemory, /* execute if: */ { query::data::QueryTarget::WM });
+        wm::Memory wmResult = wmProcessor.process(input, *workingMemory);
 
         armem::ltm::query_proc::MemoryQueryProcessor ltmProcessor;
-        ltm::Memory ltmResult = ltmProcessor.process(input, *longtermMemory, /* execute if: */ { query::data::QueryTarget::LTM });
+        ltm::Memory ltmResult = ltmProcessor.process(input, *longtermMemory);
 
         armem::query::data::Result result;
         if (ltmResult.hasData())
         {
+            ARMARX_INFO << "The LTM returned data after query";
+
             // ATTENTION: This code block moves data from LTM back into WM.
             // However, since some segments are constrained, the WM might send data back to LTM.
             // This may also affect the data returned by the current query.
             // However, this is expected behavior, since we copy the data in the processor (copyEmpty) we can safely return the copy and
             // remove the original memory reference from WM here.
             wm::Memory ltmConverted = ltmResult.convert();
+            if (!ltmConverted.hasData())
+            {
+                ARMARX_ERROR << "A converted memory contains no data although the original memory contained data. This indicates that something is wrong.";
+            }
+
             wmResult.append(ltmConverted);
+            if (!wmResult.hasData())
+            {
+                ARMARX_ERROR << "A merged Memory has no data although at least the LTM result contains data. This indicates that something is wrong.";
+            }
 
             // query again to limit output size (TODO: Skip if querytype is all)
-            wm::Memory merged_result = wmProcessor.process(input, wmResult);
+            auto queryInput = armem::client::QueryInput::fromIce(input);
+            queryInput.replaceQueryTarget(query::data::QueryTarget::LTM, query::data::QueryTarget::WM);
+
+            wm::Memory merged_result = wmProcessor.process(queryInput.toIce(), wmResult);
+            if (!merged_result.hasData())
+            {
+                ARMARX_ERROR << "A merged and postprocessed Memory has no data although at least the LTM result contains data. This indicates that something is wrong.";
+            }
+
             result.memory = toIce<data::MemoryPtr>(merged_result);
 
             // also move results of ltm to wm
@@ -263,6 +283,7 @@ namespace armarx::armem::server
         }
         else
         {
+            ARMARX_VERBOSE << "The LTM did not return data after query";
             result.memory = toIce<data::MemoryPtr>(wmResult);
         }
 
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h
index 95943dd2f18289360336c22b910913835a84c604..2af92450309d640122bffc9066c1a1df7bdfff49 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h
@@ -22,34 +22,29 @@ namespace armarx::armem::base::query_proc
         virtual ~BaseQueryProcessorBase() = default;
 
 
-        DataT process(const QueryT& query, const DataT& data, const query::data::QueryTargets& executeIf = {}) const
+        DataT process(const QueryT& query, const DataT& data) const
         {
             DataT result = data.copyEmpty();
-
-            for (const auto queryTarget : query.targets)
+            if (getTargets(query.targets).count(getTargetType()))
             {
-                if (std::find(executeIf.begin(), executeIf.end(), queryTarget) != executeIf.end())
-                {
-                    this->process(result, query, data);
-                    break;
-                }
+                this->process(result, query, data);
             }
             return result;
         }
 
-        DataT process(const QueryPtrT& query, const DataT& data, const query::data::QueryTargets& executeIf = {}) const
+        DataT process(const QueryPtrT& query, const DataT& data) const
         {
-            return this->process(*query, *data, executeIf);
+            return this->process(*query, *data);
         }
 
-        DataT process(const QuerySeqT& queries, const DataT& data, const query::data::QueryTargets& executeIf = {}) const
+        DataT process(const QuerySeqT& queries, const DataT& data) const
         {
             DataT result = data.copyEmpty();
-            this->process(result, queries, data, executeIf);
+            this->process(result, queries, data);
             return result;
         }
 
-        void process(DataT& result, const QuerySeqT& queries, const DataT& data, const query::data::QueryTargets& executeIf = {}) const
+        void process(DataT& result, const QuerySeqT& queries, const DataT& data) const
         {
             if (queries.empty())
             {
@@ -57,35 +52,37 @@ namespace armarx::armem::base::query_proc
                 return;
             }
 
-            if (executeIf.empty())
-            {
-                ARMARX_DEBUG << "Could not execute query. ExecuteIf s empty.";
-                return;
-            }
-
             for (const auto& query : queries)
             {
-                if (query->targets.empty())
+                if (getTargets(query->targets).count(getTargetType()))
                 {
-                    ARMARX_DEBUG << "The targets of a query are empty";
-                    continue;
-                }
-
-                for (const auto queryTarget : query->targets)
-                {
-                    if (std::find(executeIf.begin(), executeIf.end(), queryTarget) != executeIf.end())
-                    {
-                        this->process(result, *query, data);
-                        break;
-                    }
-                    else
-                    {
-                        ARMARX_DEBUG << "The query target " << queryTarget << " was not found in executeIf: " << executeIf;
-                    }
+                    this->process(result, *query, data);
                 }
             }
         }
 
         virtual void process(DataT& result, const QueryT& query, const DataT& data) const = 0;
+
+
+    protected:
+
+        virtual query::data::QueryTarget getTargetType() const = 0;
+
+
+    private:
+
+        /// If empty, e.g. when receiving queries from python, we use WM as default.
+        /// We do it here as (Sl)ice does not support default values for vectors.
+        static std::set<query::data::QueryTarget> getTargets(const std::vector<query::data::QueryTarget>& _targets)
+        {
+            std::set<query::data::QueryTarget> targets(_targets.begin(), _targets.end());
+            if (targets.empty())
+            {
+                ARMARX_DEBUG << "Query has no targets - using WM as default.";
+                targets.insert(query::data::QueryTarget::WM);
+            }
+            return targets;
+        }
+
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/base/MemoryQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/base/MemoryQueryProcessorBase.h
index cc06defc93976ea018ab8a7d3823a00d6121543d..55c5e51126b49775db7317d6401aa695c4b5581c 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/base/MemoryQueryProcessorBase.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/base/MemoryQueryProcessorBase.h
@@ -34,9 +34,9 @@ namespace armarx::armem::base::query_proc
 
 
         using Base::process;
-        _MemoryT process(const armem::query::data::Input& input, const _MemoryT& memory, const std::vector<query::data::QueryTarget>& executeIf = {}) const
+        _MemoryT process(const armem::query::data::Input& input, const _MemoryT& memory) const
         {
-            return this->process(input.memoryQueries, memory, executeIf);
+            return this->process(input.memoryQueries, memory);
         }
 
         void process(_MemoryT& result,
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/BaseQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/BaseQueryProcessor.h
index 84f967795fd26d79d173a14e71498dbec7d56ee1..469b5f907d01bbff757b1bea14ff8e80e5769315 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/BaseQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/BaseQueryProcessor.h
@@ -22,5 +22,11 @@ namespace armarx::armem::d_ltm::query_proc
         {}
 
     protected:
+
+        query::data::QueryTarget getTargetType() const override
+        {
+            return query::data::QueryTarget::Disk;
+        }
+
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/CoreSegmentQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/CoreSegmentQueryProcessor.h
index 1c40f7fc64b0a2c59fdc3e54d968c6627480cbb0..5c043a2d1dbe2218078591adc3fc0ebac0bfe932 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/CoreSegmentQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/CoreSegmentQueryProcessor.h
@@ -27,7 +27,7 @@ namespace armarx::armem::d_ltm::query_proc
     protected:
         virtual ProviderSegmentT providerSegmentProcessorProcess(const armem::query::data::ProviderSegmentQuerySeq& q, const ProviderSegmentT& s) const override
         {
-            return providerSegmentProcessor.process(q, s, {armem::query::data::QueryTarget::Disk});
+            return providerSegmentProcessor.process(q, s);
         }
 
     private:
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/MemoryQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/MemoryQueryProcessor.h
index 2abdcc1ccc7c25a317edc67e36835cb4a4df2f9b..038523950bfe399c2ef7a65b79fde43376651617 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/MemoryQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/MemoryQueryProcessor.h
@@ -26,7 +26,7 @@ namespace armarx::armem::d_ltm::query_proc
     protected:
         virtual CoreSegmentT coreSegmentProcessorProcess(const armem::query::data::CoreSegmentQuerySeq& q, const CoreSegmentT& s) const override
         {
-            return coreSegmentProcessor.process(q, s, {armem::query::data::QueryTarget::Disk});
+            return coreSegmentProcessor.process(q, s);
         }
 
     private:
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/ProviderSegmentQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/ProviderSegmentQueryProcessor.h
index 94c2e756875c1152f8018f70c5e0d691a5704582..2043273ec7c5f3fee2d02410a145ef436c47459c 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/ProviderSegmentQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/ProviderSegmentQueryProcessor.h
@@ -26,7 +26,7 @@ namespace armarx::armem::d_ltm::query_proc
     protected:
         virtual EntityT entityProcessorProcess(const armem::query::data::EntityQuerySeq& q, const EntityT& s) const override
         {
-            return entityProcessor.process(q, s, {armem::query::data::QueryTarget::Disk});
+            return entityProcessor.process(q, s);
         }
 
     private:
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/BaseQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/BaseQueryProcessor.h
index 458128e5305139db33a6c25d6ff19e3e92772fd5..64f560afff93e5d0cfff4b036f68f0fb4e8cdaba 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/BaseQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/BaseQueryProcessor.h
@@ -22,5 +22,11 @@ namespace armarx::armem::ltm::query_proc
         {}
 
     protected:
+
+        query::data::QueryTarget getTargetType() const override
+        {
+            return query::data::QueryTarget::LTM;
+        }
+
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/CoreSegmentQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/CoreSegmentQueryProcessor.h
index e333dd816aedabbb8dfa7209c687caf727d9ccf9..dc379f1d88fa82bbe886e412e0341079fa43fce9 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/CoreSegmentQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/CoreSegmentQueryProcessor.h
@@ -27,7 +27,7 @@ namespace armarx::armem::ltm::query_proc
     protected:
         virtual ProviderSegmentT providerSegmentProcessorProcess(const armem::query::data::ProviderSegmentQuerySeq& q, const ProviderSegmentT& s) const override
         {
-            return providerSegmentProcessor.process(q, s, {armem::query::data::QueryTarget::LTM});
+            return providerSegmentProcessor.process(q, s);
         }
 
     private:
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/MemoryQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/MemoryQueryProcessor.h
index 569014d6579eeb6c99996e4be5b7cb68f65457b1..a5129417262515975efa247398602272865ee5ec 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/MemoryQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/MemoryQueryProcessor.h
@@ -26,7 +26,7 @@ namespace armarx::armem::ltm::query_proc
     protected:
         virtual CoreSegmentT coreSegmentProcessorProcess(const armem::query::data::CoreSegmentQuerySeq& q, const CoreSegmentT& s) const override
         {
-            return coreSegmentProcessor.process(q, s, {armem::query::data::QueryTarget::LTM});
+            return coreSegmentProcessor.process(q, s);
         }
 
     private:
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/ProviderSegmentQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/ProviderSegmentQueryProcessor.h
index 5443acfd6594b98250711cf2acfd434a98414066..e0c6db9e3ef06e6241e9af8c572bb7fc78eec452 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/ProviderSegmentQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/longtermmemory/ProviderSegmentQueryProcessor.h
@@ -26,7 +26,7 @@ namespace armarx::armem::ltm::query_proc
     protected:
         virtual EntityT entityProcessorProcess(const armem::query::data::EntityQuerySeq& q, const EntityT& s) const override
         {
-            return entityProcessor.process(q, s, {armem::query::data::QueryTarget::LTM});
+            return entityProcessor.process(q, s);
         }
 
     private:
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/BaseQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/BaseQueryProcessor.h
index 933f9a6fd628b8c2747c2c6449499e596593935b..d4875053c93dc2278cdb9f327fc0739370811fe7 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/BaseQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/BaseQueryProcessor.h
@@ -26,6 +26,11 @@ namespace armarx::armem::wm::query_proc
 
     protected:
 
+        query::data::QueryTarget getTargetType() const override
+        {
+            return query::data::QueryTarget::WM;
+        }
+
         DataMode dataMode;
 
     };
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/CoreSegmentQueryProcessor.cpp b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/CoreSegmentQueryProcessor.cpp
index bda9ad04de5ac7cd46be68a2f5f7ca2ec1419040..4c41f16664af134b66b00355080d8de362d7eaf9 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/CoreSegmentQueryProcessor.cpp
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/CoreSegmentQueryProcessor.cpp
@@ -32,7 +32,7 @@ namespace armarx::armem::wm::query_proc
 
     ProviderSegment CoreSegmentQueryProcessor::providerSegmentProcessorProcess(const armem::query::data::ProviderSegmentQuerySeq& q, const ProviderSegment& s) const
     {
-        return providerSegmentProcessor.process(q, s, {armem::query::data::QueryTarget::WM});
+        return providerSegmentProcessor.process(q, s);
     }
 
 
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/EntityQueryProcessor.cpp b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/EntityQueryProcessor.cpp
index 7ef31f2badfbffbf49f132c855b2143b8ddc10bd..005649b8f670586f16177f90a43c6e0f48b3879d 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/EntityQueryProcessor.cpp
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/EntityQueryProcessor.cpp
@@ -6,7 +6,7 @@
 namespace armarx::armem::wm::query_proc
 {
     EntityQueryProcessor::EntityQueryProcessor(DataMode dataMode) :
-        Base(dataMode)
+        BaseQueryProcessor<wm::Entity, armem::query::data::EntityQuery>(dataMode)
     {}
 
 
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/MemoryQueryProcessor.cpp b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/MemoryQueryProcessor.cpp
index dd249b61caaacaca11e369b19b8f4e0da1dc5cf5..7aa868af13bc525b42d93f230a8398c27531525d 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/MemoryQueryProcessor.cpp
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/MemoryQueryProcessor.cpp
@@ -16,7 +16,7 @@ namespace armarx::armem::wm::query_proc
 
     CoreSegment MemoryQueryProcessor::coreSegmentProcessorProcess(const armem::query::data::CoreSegmentQuerySeq& q, const CoreSegment& s) const
     {
-        return coreSegmentProcessor.process(q, s, {armem::query::data::QueryTarget::WM});
+        return coreSegmentProcessor.process(q, s);
     }
 
 }
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/ProviderSegmentQueryProcessor.cpp b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/ProviderSegmentQueryProcessor.cpp
index a5e23184fa999dc44d72de7588cf77fad0503729..eb2524631b4c1d2fb89eb3e7c36a3aaf86f31e29 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/ProviderSegmentQueryProcessor.cpp
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/ProviderSegmentQueryProcessor.cpp
@@ -24,7 +24,7 @@ namespace armarx::armem::wm::query_proc
 
     Entity ProviderSegmentQueryProcessor::entityProcessorProcess(const armem::query::data::EntityQuerySeq& q, const Entity& s) const
     {
-        return entityProcessor.process(q, s, {armem::query::data::QueryTarget::WM});
+        return entityProcessor.process(q, s);
     }
 
 }
diff --git a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
index 5037bad396c0e7a83b7704b4895a25225ae8106f..f88a2e1731c87de6fa163c307c90f4c6d3e01ae2 100644
--- a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
+++ b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
@@ -245,7 +245,7 @@ namespace armarx::armem::gui
                         input.addQueryTargetToAll(armem::query::data::QueryTarget::Disk);
 
                         armem::d_ltm::query_proc::MemoryQueryProcessor d_ltm_processor;
-                        dMem = d_ltm_processor.process(input.toIce(), dMem, /* execute if: */ { query::data::QueryTarget::Disk });
+                        dMem = d_ltm_processor.process(input.toIce(), dMem);
 
                         wm::Memory converted = dMem.convert();
                         memoryData[k] = std::move(converted);
@@ -275,7 +275,7 @@ namespace armarx::armem::gui
 
                             // requery (e.g. to get only the last n values instead of the last n from disk and the last n from wm)
                             armem::wm::query_proc::MemoryQueryProcessor wm_processor;
-                            result.memory = wm_processor.process(input.toIce(), result.memory, /* execute if: */ { query::data::QueryTarget::WM });
+                            result.memory = wm_processor.process(input.toIce(), result.memory);
 
                             if (!result.memory.hasData())
                             {
@@ -293,7 +293,7 @@ namespace armarx::armem::gui
                 }
                 else
                 {
-                    ARMARX_WARNING << "A query for memory '" + name + "' produced an error: " << result.errorMessage;
+                    ARMARX_WARNING << "A query for memory '" << name << "' produced an error: " << result.errorMessage;
                     if (statusLabel)
                     {
                         statusLabel->setText(QString::fromStdString(result.errorMessage));