diff --git a/source/RobotAPI/libraries/armem/core/MemoryID.cpp b/source/RobotAPI/libraries/armem/core/MemoryID.cpp
index cce838327d84b2191f603bf22d654d7c5bc55382..e150f1e044f225c73aeda5f330a50ffef1c51a16 100644
--- a/source/RobotAPI/libraries/armem/core/MemoryID.cpp
+++ b/source/RobotAPI/libraries/armem/core/MemoryID.cpp
@@ -6,9 +6,11 @@
 
 #include <SimoxUtility/algorithm/advanced.h>
 #include <SimoxUtility/algorithm/string/string_tools.h>
+#include "ArmarXCore/core/logging/Logging.h"
 
 #include "error/ArMemError.h"
 
+
 namespace armarx::armem
 {
 
@@ -21,6 +23,8 @@ namespace armarx::armem
 
     MemoryID::MemoryID(const std::string& string)
     {
+        //ARMARX_INFO << "Trying to create MemoryID from string";
+        //ARMARX_INFO << VAROUT(string);
         std::forward_list<std::string> items;
         boost::split(items, string, boost::is_any_of(delimiter));
 
@@ -76,6 +80,7 @@ namespace armarx::armem
             return;
         }
         this->instanceIndex = instanceIndexFromStr(*it);
+        //ARMARX_INFO << this->str();
     }
 
     MemoryID::MemoryID(const std::string& memoryName,
@@ -124,6 +129,31 @@ namespace armarx::armem
         return "";
     }
 
+    MemoryID MemoryID::cleanID() const
+    {
+        std::vector<std::string> allItems = this->getAllItems(true);
+        std::string newID = "";
+        for(int i = 0; i < allItems.size(); i++){
+            if(!allItems.at(i).empty()){
+                std::string toAppend = allItems.at(i);
+                if(allItems.at(i).find(delimiter) != std::string::npos){
+                    size_t pos = 0;
+                    std::string token;
+                    while ((pos = toAppend.find(delimiter)) != std::string::npos) {
+                        token = toAppend.substr(0, pos);
+                        toAppend.erase(0, pos + delimiter.length());
+                    }
+                }
+                newID.append(toAppend);
+                if(i < allItems.size() - 1 && !allItems.at(i+1).empty()){
+                    newID.append(delimiter);
+                }
+            }
+        }
+        return MemoryID(newID);
+    }
+
+
     bool
     MemoryID::hasGap() const
     {
diff --git a/source/RobotAPI/libraries/armem/core/MemoryID.h b/source/RobotAPI/libraries/armem/core/MemoryID.h
index d9dca2a2541bae3462a18ad1603a048f804fc551..e54617f4cd7d740b0b7cb95aea78c5b55a82b681 100644
--- a/source/RobotAPI/libraries/armem/core/MemoryID.h
+++ b/source/RobotAPI/libraries/armem/core/MemoryID.h
@@ -218,6 +218,8 @@ namespace armarx::armem
         /// Get the lowest defined level (or empty string if there is none).
         std::string getLeafItem() const;
 
+        MemoryID cleanID() const;
+
 
         // Operators
 
diff --git a/source/RobotAPI/libraries/armem/core/base/EntitySnapshotBase.h b/source/RobotAPI/libraries/armem/core/base/EntitySnapshotBase.h
index 2fb8bd3cc6ffcb217f7882e66fa2ed1e1b52d429..c1eeea7275cecc1f4dd2c76d7723720681fcead1 100644
--- a/source/RobotAPI/libraries/armem/core/base/EntitySnapshotBase.h
+++ b/source/RobotAPI/libraries/armem/core/base/EntitySnapshotBase.h
@@ -269,16 +269,7 @@ namespace armarx::armem::base
         EntityInstanceT&
         addInstance(EntityInstanceT&& instance)
         {
-            if (instance.index() > 0 &&
-                static_cast<size_t>(instance.index()) < this->_container.size())
-            {
-                throw error::InvalidArgument(
-                    std::to_string(instance.index()),
-                    "EntitySnapshot::addInstance",
-                    "Cannot add an EntityInstance because its index already exists.");
-            }
-            if (instance.index() > 0 &&
-                static_cast<size_t>(instance.index()) > this->_container.size())
+            if (instance.index() > 0 && static_cast<size_t>(instance.index()) > this->_container.size())
             {
                 throw error::InvalidArgument(
                     std::to_string(instance.index()),
@@ -286,8 +277,9 @@ namespace armarx::armem::base
                     "Cannot add an EntityInstance because its index is too big.");
             }
 
-            int index = static_cast<int>(this->_container.size());
+            int index = instance.index();
             EntityInstanceT& added = this->_container.emplace_back(std::move(instance));
+
             added.id() = this->id().withInstanceIndex(index);
             return added;
         }
@@ -295,7 +287,8 @@ namespace armarx::armem::base
         EntityInstanceT&
         addInstance()
         {
-            int index = static_cast<int>(this->size());
+            //ARMARX_INFO << "Trying to add an instance without instance yet generated";
+            int index = static_cast<int>(this->size()); //this is the problem, because instances have names 0 and 11 (I do not know why)
             EntityInstanceT& added = this->_container.emplace_back(EntityInstanceT());
             added.id() = this->id().withInstanceIndex(index);
             return added;
diff --git a/source/RobotAPI/libraries/armem/core/base/detail/iteration_mixins.h b/source/RobotAPI/libraries/armem/core/base/detail/iteration_mixins.h
index 9f5190364d66b999fa9d15d64bf9c12454d05715..07930b46e931513cd42f4a6dcdaacd5a3f80a56d 100644
--- a/source/RobotAPI/libraries/armem/core/base/detail/iteration_mixins.h
+++ b/source/RobotAPI/libraries/armem/core/base/detail/iteration_mixins.h
@@ -2,6 +2,7 @@
 
 #include <functional>
 #include <type_traits>
+#include "ArmarXCore/core/logging/Logging.h"
 
 #include <RobotAPI/libraries/armem/core/MemoryID.h>
 
diff --git a/source/RobotAPI/libraries/armem/core/wm/memory_conversions.cpp b/source/RobotAPI/libraries/armem/core/wm/memory_conversions.cpp
index 5856407816fe423e2f93bd0375a631863c304a89..e72b21abffa5e571ffab8437d35ce6026dd1ab62 100644
--- a/source/RobotAPI/libraries/armem/core/wm/memory_conversions.cpp
+++ b/source/RobotAPI/libraries/armem/core/wm/memory_conversions.cpp
@@ -52,6 +52,7 @@ namespace armarx::armem::wm
     toMemory(Memory& m, const std::vector<EntitySnapshot>& e)
     {
         m.clear();
+
         for (const auto& s : e)
         {
             if (!m.hasCoreSegment(s.id().coreSegmentName))
@@ -108,4 +109,42 @@ namespace armarx::armem::wm
             sn->addInstance(s);
         }
     }
+
+    void toMemory(Memory &m, const armarx::armem::server::wm::Memory &structure, const std::vector<EntitySnapshot> &e)
+    {
+        // create an empty working memory:
+        m.clear();
+
+        for (const auto& s : e)
+        {
+            //get name of the core segment:
+            auto coreSegmentName = s.id().coreSegmentName;
+            auto* coreStructure = structure.findCoreSegment(coreSegmentName);
+
+            //if m does not have this core segment yet add the segment but copy the structure from the server wm:
+            if (!m.hasCoreSegment(coreSegmentName))
+            {
+                m.addCoreSegment(coreSegmentName, coreStructure->aronType());
+            }
+            auto* c = m.findCoreSegment(coreSegmentName);
+
+            //get name of provider segment:
+            auto providerSegmentName = s.id().providerSegmentName;
+            auto* providerStructure = coreStructure->findProviderSegment(providerSegmentName);
+
+            if (!c->hasProviderSegment(providerSegmentName))
+            {
+                c->addProviderSegment(providerSegmentName, providerStructure->aronType());
+            }
+            auto* p = c->findProviderSegment(providerSegmentName);
+
+            if (!p->hasEntity(s.id().entityName))
+            {
+                p->addEntity(s.id().entityName);
+            }
+            auto* en = p->findEntity(s.id().entityName);
+            en->addSnapshot(s);
+        }
+    }
+
 } // namespace armarx::armem::wm
diff --git a/source/RobotAPI/libraries/armem/core/wm/memory_conversions.h b/source/RobotAPI/libraries/armem/core/wm/memory_conversions.h
index 53ac02bfc5536150b2d0f01b9457537bb236d95a..7ea40b5f54eb2a994eb98cd5f278ee29582ce11b 100644
--- a/source/RobotAPI/libraries/armem/core/wm/memory_conversions.h
+++ b/source/RobotAPI/libraries/armem/core/wm/memory_conversions.h
@@ -3,6 +3,7 @@
 #include <vector>
 
 #include "memory_definitions.h"
+#include "RobotAPI/libraries/armem/server/wm/memory_definitions.h"
 
 namespace armarx::armem::wm
 {
@@ -10,5 +11,15 @@ namespace armarx::armem::wm
     void toMemory(Memory& m, const std::vector<ProviderSegment>& e);
     void toMemory(Memory& m, const std::vector<Entity>& e);
     void toMemory(Memory& m, const std::vector<EntitySnapshot>& e);
+
+    /**
+     * @brief toMemory converts a vector of entity snapshots into a working memory and considers
+     * the structure of the memory before
+     * @param m the (empty) new memory
+     * @param structure the server working memory for structure information
+     * @param e the vector of entity snapshots
+     */
+    void toMemory(Memory& m, const armarx::armem::server::wm::Memory& structure, const std::vector<EntitySnapshot>& e);
+
     void toMemory(Memory& m, const std::vector<EntityInstance>& e);
 } // namespace armarx::armem::wm
diff --git a/source/RobotAPI/libraries/armem/server/CMakeLists.txt b/source/RobotAPI/libraries/armem/server/CMakeLists.txt
index de2a911560d8d13c2516db3f22348c59cfa38365..0e2544ab302ba69802c699a238a79e71952ccacc 100644
--- a/source/RobotAPI/libraries/armem/server/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem/server/CMakeLists.txt
@@ -22,6 +22,7 @@ set(LIBS
     RemoteGui
     RobotAPI::aron
     RobotAPI::armem
+    RobotAPI::aron::similarity
 
     # LTM
     RobotAPI::aron::converter::json
@@ -60,6 +61,8 @@ set(LIB_FILES
     ltm/processors/filter/Filter.cpp
     ltm/processors/filter/frequencyFilter/FrequencyFilter.cpp
     ltm/processors/filter/equalityFilter/EqualityFilter.cpp
+    #ltm/processors/filter/similarityFilter/SimilarityFilter.cpp
+    ltm/processors/filter/importanceFilter/ImportanceFilter.cpp
 
     ltm/processors/extractor/Extractor.cpp
     ltm/processors/extractor/imageExtractor/ImageExtractor.cpp
@@ -116,6 +119,8 @@ set(LIB_FILES
     query_proc/wm/detail/CoreSegmentQueryProcessorBase.cpp
     query_proc/wm/detail/MemoryQueryProcessorBase.cpp
     query_proc/wm/wm.cpp
+
+    test/ForgettingExperiments.cpp
 )
 
 set(LIB_HEADERS
@@ -149,6 +154,8 @@ set(LIB_HEADERS
     ltm/processors/filter/Filter.h
     ltm/processors/filter/frequencyFilter/FrequencyFilter.h
     ltm/processors/filter/equalityFilter/EqualityFilter.h
+    #ltm/processors/filter/similarityFilter/SimilarityFilter.h
+    ltm/processors/filter/importanceFilter/ImportanceFilter.h
 
     ltm/processors/extractor/Extractor.h
     ltm/processors/extractor/imageExtractor/ImageExtractor.h
@@ -208,6 +215,8 @@ set(LIB_HEADERS
     query_proc/wm/detail/CoreSegmentQueryProcessorBase.h
     query_proc/wm/detail/MemoryQueryProcessorBase.h
     query_proc/wm/wm.h
+
+    test/ForgettingExperiments.h
 )
 
 # Clear variable set by CMakeLists.txt in parent directory.
diff --git a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
index 194785757e80ecbb9b77b06ec9224f500c85ec55..a033f89b0a490ca8f041f9fb3cfcd1bbdf4f035b 100644
--- a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
+++ b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
@@ -1,5 +1,7 @@
 #include "MemoryToIceAdapter.h"
 
+#include <thread>
+
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 #include <ArmarXCore/core/ice_conversions/ice_conversions_templates.h>
 #include <ArmarXCore/core/logging/Logging.h>
@@ -233,15 +235,14 @@ namespace armarx::armem::server
                     ARMARX_DEBUG << "The id " << snapshot.id() << " was removed from wm";
                 }
 
-                // Consollidate to ltm
+
+                // Consollidate to ltm(s)
                 if (longtermMemory->isRecording())
                 {
-                    //ARMARX_IMPORTANT << longtermMemory->id().str();
-                    //ARMARX_IMPORTANT << longtermMemory->getPath();
-
                     // convert removedSnapshots to Memory
                     armem::wm::Memory m(longtermMemory->name());
-                    armem::wm::toMemory(m, updateResult.removedSnapshots);
+                    armem::wm::toMemory(m, *workingMemory, updateResult.removedSnapshots);
+                    //this removes information about segments, because new memory (wm) is used
 
                     // store memory
                     longtermMemory->store(m);
@@ -268,6 +269,10 @@ namespace armarx::armem::server
                 result.success = false;
                 result.errorMessage = e.what();
             }
+            catch (...)
+            {
+                ARMARX_INFO << "Error during LTM consollidation";
+            }
         }
 
         if (publishUpdates)
@@ -399,7 +404,7 @@ namespace armarx::armem::server
         ARMARX_TRACE;
         ARMARX_CHECK_NOT_NULL(longtermMemory);
         ARMARX_IMPORTANT << "Enabling the recording of memory " << longtermMemory->id().str();
-        longtermMemory->startRecording(); // TODO: config and execution time!
+        longtermMemory->startRecording();
 
         dto::StartRecordResult ret;
         ret.success = true;
@@ -413,7 +418,21 @@ namespace armarx::armem::server
         ARMARX_TRACE;
         ARMARX_CHECK_NOT_NULL(longtermMemory);
         ARMARX_IMPORTANT << "Disabling the recording of memory " << longtermMemory->id().str();
-        longtermMemory->stopRecording();
+
+        //put calling stopRecording into a seperate thread and detach to make sure GUI does not freeze
+        auto ltm = longtermMemory;
+        std::thread stopRecordingThread([&ltm](){
+            ltm->stopRecording();
+        });
+        std::thread savingDataUpdateThread([&ltm](){
+            ltm->bufferFinished();
+        });
+        stopRecordingThread.detach();
+        savingDataUpdateThread.detach();
+
+        ARMARX_IMPORTANT
+            << "Stopped all LTM recordings, please wait with stopping the component until "
+               "all files are written";
 
         dto::StopRecordResult ret;
         ret.success = true;
diff --git a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.h b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.h
index f6fdfe9eaf1a985fe3ceba8a17c2665111333b0e..0ae95a4207d86842d1b11e82cd97af6030147401 100644
--- a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.h
+++ b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.h
@@ -25,7 +25,6 @@ namespace armarx::armem::server
 
         void setMemoryListener(client::MemoryListenerInterfacePrx memoryListenerTopic);
 
-
         // WRITING
         data::AddSegmentResult addSegment(const data::AddSegmentInput& input,
                                           bool addCoreSegments = false);
diff --git a/source/RobotAPI/libraries/armem/server/ltm/CoreSegment.cpp b/source/RobotAPI/libraries/armem/server/ltm/CoreSegment.cpp
index 5e0f1908bc411d1270503a273d62d8508707f4be..87575f5d3005a1cf63ec906c41c404d0fb0a2837 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/CoreSegment.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/CoreSegment.cpp
@@ -25,19 +25,6 @@ namespace armarx::armem::server::ltm
     {
         std::lock_guard l(ltm_mutex);
 
-        /*if (connected() && collectionExists())
-        {
-            for (const auto& doc : getAllDocuments())
-            {
-                std::string id_str = doc[FOREIGN_KEY];
-                armem::MemoryID segment_id(id_str);
-                ProviderSegment c(
-                    getMemoryBasePath(), getSettings(), getExportName(), segment_id, processors);
-                func(c);
-            }
-        } else */
-
-        // legacy
         if (fullPathExists())
         {
             for (const auto& subdirName : getAllDirectories())
@@ -59,17 +46,6 @@ namespace armarx::armem::server::ltm
     {
         std::lock_guard l(ltm_mutex);
 
-        /*if (connected() && collectionExists())
-        {
-            auto c = ProviderSegment(getMemoryBasePath(),
-                                     getSettings(),
-                                     getExportName(),
-                                     id().withProviderSegmentName(name),
-                                     processors);
-
-            return (bool)c.collectionExists();
-        }*/
-
         if (fullPathExists())
         {
             auto c = ProviderSegment(getMemoryBasePath(),
@@ -106,26 +82,7 @@ namespace armarx::armem::server::ltm
     {
         std::lock_guard l(ltm_mutex);
 
-        e.id() = id();
-
-        auto& conv = processors->defaultTypeConverter;
-        auto setType = [&conv, &e](const std::vector<unsigned char>& aronJson)
-        {
-            auto typeAron = conv.convert(aronJson, "");
-            e.aronType() = aron::type::Object::DynamicCastAndCheck(typeAron);
-        };
-
-        /*if (connected() && collectionExists())
-        {
-            // TODO:
-        } else */
-
-        if (std::string filename = TYPE_FILENAME + conv.suffix;
-            fullPathExists() && fileExists(filename))
-        {
-            auto typeFileContent = readDataFromFile(filename);
-            setType(typeFileContent);
-        }
+        e.id() = id().getCoreSegmentID().cleanID();
 
         forEachProviderSegment(
             [&e](auto& x)
@@ -195,6 +152,8 @@ namespace armarx::armem::server::ltm
         }
         else
         {
+            ARMARX_INFO << "CoreSegment does not have aron type, so aron type information "
+                           "cannot be exported";
             /*writeForeignKeyToPreviousDocument();*/
         }
 
@@ -208,7 +167,6 @@ namespace armarx::armem::server::ltm
                                   processors);
 
                 c.store(prov);
-                statistics.recordedProviderSegments++;
             });
     }
 } // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/Entity.cpp b/source/RobotAPI/libraries/armem/server/ltm/Entity.cpp
index b34d9d5167b9f505d70e3c20caf8e317b7680be3..ac9433dfb78be5a973925feb9c917a67699f1d7e 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/Entity.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/Entity.cpp
@@ -39,20 +39,6 @@ namespace armarx::armem::server::ltm
     {
         std::lock_guard l(ltm_mutex);
 
-        /*if (connected() && collectionExists())
-        {
-            for (const auto& doc : getAllDocuments())
-            {
-                std::string id_str = doc[ID];
-
-                armem::MemoryID segment_id = id();
-                segment_id.timestampFromStr(id_str);
-
-                EntitySnapshot c(
-                    getMemoryBasePath(), getSettings(), getExportName(), segment_id, processors);
-                func(c);
-            }
-        } else */
         if (fullPathExists())
         {
 
@@ -201,15 +187,6 @@ namespace armarx::armem::server::ltm
     Entity::hasSnapshot(const Time& n) const
     {
         std::lock_guard l(ltm_mutex);
-        /*if (connected() && collectionExists())
-        {
-            auto c = EntitySnapshot(getMemoryBasePath(),
-                                    getSettings(),
-                                    getExportName(),
-                                    id().withTimestamp(n),
-                                    processors);
-            return (bool)c.documentExists();
-        }*/
 
         if (fullPathExists())
         {
@@ -379,7 +356,7 @@ namespace armarx::armem::server::ltm
     Entity::_loadAllReferences(armem::wm::Entity& e)
     {
         std::lock_guard l(ltm_mutex);
-        e.id() = id();
+        e.id() = id().getEntityID().cleanID();
 
         forEachSnapshot(
             [&e](auto& x)
@@ -450,8 +427,7 @@ namespace armarx::armem::server::ltm
 
                 if (hasSnapshot(snap.id().timestamp))
                 {
-                    ARMARX_INFO << deactivateSpam()
-                                << "Ignoring to put an EntitiySnapshot into the LTM because "
+                    ARMARX_INFO  << "Ignoring to put an EntitiySnapshot into the LTM because "
                                    "the timestamp already existed (we assume snapshots are "
                                    "const and do not change outside the ltm).";
                     return;
@@ -459,12 +435,14 @@ namespace armarx::armem::server::ltm
 
                 for (auto& f : processors->snapFilters)
                 {
-                    if (!f->accept(snap))
+
+                    bool accepted = f->accept(snap);
+                    if (!accepted)
                     {
-                        ARMARX_INFO << deactivateSpam()
-                                    << "Ignoring to put an EntitiySnapshot into the LTM because it "
-                                       "got filtered.";
+                        //ARMARX_INFO << "Ignoring to put an EntitiySnapshot into the LTM because it got filtered.";
                         return;
+                    } else {
+                        //ARMARX_INFO << "Storing EntitySnapshot";
                     }
                 }
 
diff --git a/source/RobotAPI/libraries/armem/server/ltm/EntityInstance.cpp b/source/RobotAPI/libraries/armem/server/ltm/EntityInstance.cpp
index b5800ec11fd3cfaa5f8c3fd3fcff6e4a4b5bf599..0be6975beb6785dbb2426b74c0d70000edf0ce27 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/EntityInstance.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/EntityInstance.cpp
@@ -31,16 +31,24 @@ namespace armarx::armem::server::ltm
     {
         std::lock_guard l(ltm_mutex);
         // assure that we put the right index to the snapshot
-        ARMARX_CHECK(e.size() == (size_t)id().instanceIndex);
+        //ARMARX_CHECK(e.size() == (size_t)id().instanceIndex);
+        //int index = e.getInstanceIndices().size();
+
+        //ARMARX_INFO << VAROUT(getFullPath());
+        //ARMARX_INFO << VAROUT(getMemoryID().getEntityInstanceID().getLeafItem());
+        int index = std::stoi(getMemoryID().getEntityInstanceID().getLeafItem());
+
+        armem::wm::EntityInstance i = armem::wm::EntityInstance(index, e.id());
 
         // add instance. Do not set data, since we only return references
-        e.addInstance();
+        e.addInstance(i);
     }
 
     void
     EntityInstance::_resolve(armem::wm::EntityInstance& e) const
     {
         std::lock_guard l(ltm_mutex);
+        //ARMARX_INFO << "resolve for entity instance " << e.id().str();
         auto& dictConverter = processors->defaultObjectConverter;
 
         aron::data::DictPtr datadict = nullptr;
@@ -89,6 +97,8 @@ namespace armarx::armem::server::ltm
             }
         } else */
 
+        //ARMARX_INFO << VAROUT(getFullPath());
+
         if (fullPathExists())
         {
 
@@ -183,13 +193,30 @@ namespace armarx::armem::server::ltm
         auto metadataAron = std::make_shared<aron::data::Dict>();
         to_aron(metadataAron, dataAron, e);
 
+        std::shared_ptr<aron::data::Dict> source;
+
+        bool saveAndExtract = false; //if true the data is saved in extracted form and in data.aron.json
+        // this is needed if several LTMs are recorded at once because otherwise the data from the data.aron.json
+        // is not there anymore to extract from
+
+        if (saveAndExtract)
+        {
+            source = dataAron->clone();
+        }
+        else
+        {
+            source = dataAron;
+        }
+
+        //ARMARX_INFO << "save and extract is " << saveAndExtract;
+
+
         // check special members for special converters
         for (auto& c : processors->converters)
         {
             ARMARX_CHECK_NOT_NULL(c);
             ARMARX_CHECK_NOT_NULL(c->extractor);
-
-            auto dataExt = c->extractor->extract(dataAron);
+            auto dataExt = c->extractor->extract(source);
 
             for (const auto& [memberName, var] : dataExt.extraction)
             {
@@ -202,8 +229,6 @@ namespace armarx::armem::server::ltm
                 ensureFileExists(filename, true);
                 writeDataToFile(filename, memberDataVec);
             }
-
-            dataAron = dataExt.dataWithoutExtraction;
         }
 
         // convert dict and metadata
diff --git a/source/RobotAPI/libraries/armem/server/ltm/EntitySnapshot.cpp b/source/RobotAPI/libraries/armem/server/ltm/EntitySnapshot.cpp
index 693f015a20130142699eb5900eac0824a1728768..2f974697368c5a375dd9a27715f06cd1cc49dfaa 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/EntitySnapshot.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/EntitySnapshot.cpp
@@ -53,18 +53,10 @@ namespace armarx::armem::server::ltm
         {
             for (const auto& i : getAllDirectories())
             {
-                if (!util::fs::detail::isNumberString(i.filename()))
-                {
-                    ARMARX_WARNING << "Found a non-index folder inside an entity '" << id().str()
-                                   << "' with name '" << i.filename() << "'. "
-                                   << "Ignoring this folder, however this is a bad situation.";
-                    continue;
-                }
-
                 EntityInstance c(getMemoryBasePath(),
                                  getSettings(),
                                  getExportName(),
-                                 id().withInstanceIndex(std::stoi(i.filename())),
+                                 id().withInstanceIndex(std::stoi(i.filename())).cleanID(),
                                  processors);
                 func(c);
             }
@@ -121,8 +113,11 @@ namespace armarx::armem::server::ltm
     {
         std::lock_guard l(ltm_mutex);
 
-        e.id() = id();
-        forEachInstance([&e](auto& x) { x.loadAllReferences(e); });
+        e.id() = id().getEntitySnapshotID().cleanID();
+
+        forEachInstance([&e](armem::server::ltm::EntityInstance& x) {
+            x.loadAllReferences(e);
+        });
     }
 
     void
@@ -148,6 +143,7 @@ namespace armarx::armem::server::ltm
     void
     EntitySnapshot::_store(const armem::wm::EntitySnapshot& p)
     {
+
         std::lock_guard l(ltm_mutex);
 
         if (id().timestamp.isInvalid())
diff --git a/source/RobotAPI/libraries/armem/server/ltm/Memory.cpp b/source/RobotAPI/libraries/armem/server/ltm/Memory.cpp
index 06f81e22c947328998187c84d79a7e8a1c5058c8..3f3000dd7b28717547e5721d52722cbf56a676f2 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/Memory.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/Memory.cpp
@@ -18,7 +18,8 @@ namespace armarx::armem::server::ltm
         MongoDBStorageMixin::configureMixin(json);
     }
 
-    Memory::Memory() : Memory(std::filesystem::path("/tmp"), {}, "MemoryExport", "Test")
+    Memory::Memory() :
+        Memory(std::filesystem::path("/tmp/ARMARX/LTM_Exports"), {}, "MemoryExport", "Test")
     {
     }
 
@@ -41,6 +42,7 @@ namespace armarx::armem::server::ltm
         DiskMemoryItemMixin(p, exportName, MemoryID(memoryName, "")),
         MongoDBStorageMixin(s, exportName, MemoryID(memoryName, ""))
     {
+        ARMARX_INFO << "Creating a new memory at " << p.string() << " and " << exportName;
     }
 
     void
@@ -62,6 +64,7 @@ namespace armarx::armem::server::ltm
     {
         BufferedBase::stop();
         MongoDBStorageMixin::stop();
+        ARMARX_IMPORTANT << "Storing of data finished";
     }
 
     void
@@ -80,27 +83,14 @@ namespace armarx::armem::server::ltm
     {
         std::lock_guard l(ltm_mutex);
 
-        // for each
-        /*if (connected() && collectionExists())
-        {
-            for (const auto& doc : getAllDocuments())
-            {
-                std::string segmentName = doc[FOREIGN_KEY];
-                CoreSegment c(getMemoryBasePath(),
-                              getSettings(),
-                              getExportName(),
-                              id().withCoreSegmentName(segmentName),
-                              processors);
-                func(c);
-            }
-        } else */
-
         // legacy: check fs
         if (fullPathExists())
         {
             for (const auto& subdirName : getAllDirectories())
             {
+
                 std::string segmentName = util::fs::detail::unescapeName(subdirName);
+                ARMARX_INFO << VAROUT(id().withCoreSegmentName(segmentName));
                 CoreSegment c(getMemoryBasePath(),
                               getSettings(),
                               getExportName(),
@@ -110,6 +100,8 @@ namespace armarx::armem::server::ltm
             }
         }
 
+        ARMARX_INFO << "All CoreSegments handeled";
+
         return true;
     }
 
@@ -167,12 +159,21 @@ namespace armarx::armem::server::ltm
                                              processors);
     }
 
+    void Memory::createPropertyDefinitions(PropertyDefinitionsPtr &defs, const std::string &prefix)
+    {
+        MemoryBase::createPropertyDefinitions(defs, prefix);
+        DiskMemoryBase::createPropertyDefinitions(defs, prefix);
+        BufferedBase::createPropertyDefinitions(defs, prefix);
+    }
+
     void
     Memory::_loadAllReferences(armem::wm::Memory& m)
     {
         std::lock_guard l(ltm_mutex);
 
-        m.id() = id();
+        m.id() = id().getMemoryID();
+
+        ARMARX_INFO << VAROUT(id());
 
         forEachCoreSegment(
             [&m](auto& x)
@@ -193,6 +194,7 @@ namespace armarx::armem::server::ltm
             m.forEachCoreSegment(
                 [&](auto& e)
                 {
+                    //ARMARX_INFO << "resolve for CoreSegment " << e.id().str();
                     CoreSegment c(getMemoryBasePath(),
                                   getSettings(),
                                   getExportName(),
@@ -246,6 +248,6 @@ namespace armarx::armem::server::ltm
             });
 
         // 4. update cache
-        CachedBase::addToCache(memory);
+        //CachedBase::addToCache(memory);
     }
 } // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/Memory.h b/source/RobotAPI/libraries/armem/server/ltm/Memory.h
index 30e1929dd3156dfb0f9d4412ac78e44bb62ce664..67b16811b8b066661501c782d3d73902532c6cd8 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/Memory.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/Memory.h
@@ -47,10 +47,15 @@ namespace armarx::armem::server::ltm
         std::unique_ptr<CoreSegment>
         findCoreSegment(const std::string& coreSegmentName) const final;
 
+        void createPropertyDefinitions(PropertyDefinitionsPtr& defs, const std::string& prefix) override;
+
     protected:
         void _loadAllReferences(armem::wm::Memory&) final;
         void _resolve(armem::wm::Memory&) final;
         void _store(const armem::wm::Memory&) final;
         void _directlyStore(const armem::wm::Memory&) final;
+
+    private:
+        std::time_t current_date;
     };
 } // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/ProviderSegment.cpp b/source/RobotAPI/libraries/armem/server/ltm/ProviderSegment.cpp
index 0cb941e1fa61aaef583b8d54d3005794039b47ed..cfb613221d44b6353a63e3ea1cebc148cc964a5a 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/ProviderSegment.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/ProviderSegment.cpp
@@ -11,7 +11,6 @@ namespace armarx::armem::server::ltm
 {
     ProviderSegment::ProviderSegment(const detail::mixin::Path& p,
                                      const detail::mixin::MongoDBSettings& s,
-
                                      const std::string& exportName,
                                      const armem::MemoryID& id /* UNESCAPED */,
                                      const std::shared_ptr<Processors>& filters) :
@@ -44,6 +43,7 @@ namespace armarx::armem::server::ltm
 
             for (const auto& subdirName : getAllDirectories())
             {
+
                 std::string segmentName = util::fs::detail::unescapeName(subdirName);
                 Entity c(getMemoryBasePath(),
                          getSettings(),
@@ -73,6 +73,7 @@ namespace armarx::armem::server::ltm
 
         if (fullPathExists())
         {
+            ARMARX_INFO << VAROUT(id().getEntityID());
             auto c = Entity(getMemoryBasePath(),
                             getSettings(),
                             getExportName(),
@@ -105,7 +106,9 @@ namespace armarx::armem::server::ltm
     {
         std::lock_guard l(ltm_mutex);
 
-        e.id() = id();
+        e.id() = id().getProviderSegmentID().cleanID();
+
+        /*
 
         auto& conv = processors->defaultTypeConverter;
         auto setType = [&conv, &e](const std::vector<unsigned char>& aronJson)
@@ -114,11 +117,15 @@ namespace armarx::armem::server::ltm
             e.aronType() = aron::type::Object::DynamicCastAndCheck(typeAron);
         };
 
+        */
+
         /*if (connected() && collectionExists())
         {
             // TODO:
         } else */
 
+        /*
+
         if (std::string filename = TYPE_FILENAME + conv.suffix;
             fullPathExists() && fileExists(filename))
         {
@@ -126,6 +133,8 @@ namespace armarx::armem::server::ltm
             setType(typeFileContent);
         }
 
+        */
+
         forEachEntity(
             [&e](auto& x)
             {
@@ -194,6 +203,7 @@ namespace armarx::armem::server::ltm
         }
         else
         {
+            ARMARX_INFO << "ProviderSegment does not seem to have an aron type, so aron type information connot be exported";
             //writeForeignKeyToPreviousDocument();
         }
 
@@ -209,6 +219,6 @@ namespace armarx::armem::server::ltm
                 c.store(e);
                 statistics.recordedEntities++;
             });
-    }
+        }
 
 } // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryBase.h b/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryBase.h
index 4ca25b8cb1944e345bf6c1f8c285b84c65ad648c..d79c7b3eefa22d8d6748564a839ec5b463d97778 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryBase.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryBase.h
@@ -2,11 +2,11 @@
 
 #include <functional>
 
+
 // BaseClass
 #include "MemoryItem.h"
 
 // ChildType
-#include "CoreSegmentBase.h"
 
 // ArmarX
 #include <ArmarXCore/core/Component.h>
@@ -18,6 +18,7 @@
 #include <RobotAPI/libraries/armem/core/wm/aron_conversions.h>
 #include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
 #include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
+#include <RobotAPI/libraries/armem/server/test/ForgettingExperiments.h>
 
 namespace armarx::armem::server::ltm::detail
 {
@@ -30,6 +31,10 @@ namespace armarx::armem::server::ltm::detail
         {
             armarx::core::time::DateTime lastEnabled = armarx::core::time::DateTime::Invalid();
             long recordedCoreSegments = 0;
+            bool firstStart = true;
+            bool firstStop = true;
+            armarx::core::time::DateTime firstStarted = armarx::core::time::DateTime::Invalid();
+            armarx::core::time::DateTime firstStopped = armarx::core::time::DateTime::Invalid();
         };
 
     public:
@@ -46,6 +51,8 @@ namespace armarx::armem::server::ltm::detail
         {
             bool en = p.enabled_on_startup;
             ARMARX_INFO << VAROUT(p.configuration_on_startup);
+            ARMARX_INFO << VAROUT(p.export_name);
+            this->setExportName(p.export_name);
 
             try
             {
@@ -72,8 +79,14 @@ namespace armarx::armem::server::ltm::detail
         void
         enable()
         {
-            ARMARX_INFO << "Enabling LTM " << id().str();
+            auto now = armarx::core::time::DateTime::Now();
+            ARMARX_INFO << "Enabling LTM " << id().str() << " at " << now.toDateTimeString();
+            ARMARX_INFO << "Storing information at " << this->getExportName();
             enabled = true;
+            if(statistics.firstStart){
+                statistics.firstStarted = armarx::core::time::DateTime::Now();
+                statistics.firstStart = false;
+            }
             this->_enable();
         }
 
@@ -81,9 +94,15 @@ namespace armarx::armem::server::ltm::detail
         void
         disable()
         {
-            ARMARX_INFO << "Disabling LTM " << id().str();
+            auto now = armarx::core::time::DateTime::Now();
+            ARMARX_INFO << "Disabling LTM " << id().str() << " at " << now.toDateTimeString();
             enabled = false;
+            if(statistics.firstStop){
+                statistics.firstStopped = armarx::core::time::DateTime::Now();
+                statistics.firstStop = false;
+            }
             this->_disable();
+            ARMARX_INFO << "Disabling of LTM finished";
         }
 
         /// return the full ltm as a wm::Memory with only references
@@ -137,6 +156,7 @@ namespace armarx::armem::server::ltm::detail
         store(const armem::wm::Memory& memory)
         {
             TIMING_START(LTM_Memory_Append);
+
             for (auto& f : processors->memFilters)
             {
                 if (!f->accept(memory))
@@ -173,7 +193,8 @@ namespace armarx::armem::server::ltm::detail
         createPropertyDefinitions(PropertyDefinitionsPtr& defs, const std::string& prefix)
         {
             defs->optional(p.enabled_on_startup, prefix + "enabled");
-            defs->optional(p.configuration_on_startup, prefix + "configuration");
+            defs->optional(p.configuration_on_startup, prefix + "configuration"); 
+            defs->optional(p.export_name, prefix + "exportName");
         }
 
         /// enable/disable
@@ -181,12 +202,14 @@ namespace armarx::armem::server::ltm::detail
         startRecording()
         {
             statistics.lastEnabled = armarx::core::time::DateTime::Now();
+
             enable();
         }
 
         void
         stopRecording()
         {
+
             disable();
         }
 
@@ -211,7 +234,20 @@ namespace armarx::armem::server::ltm::detail
             return statistics;
         }
 
-        /// get level name
+        std::map<std::string, processor::SnapshotFilter::FilterStatistics>
+        getFilterStatistics(){
+            try{
+                ARMARX_INFO << "Trying to save statistics";
+                auto stats = processors->getSnapshotFilterStatistics();
+                return stats;
+            }catch(...){
+                ARMARX_WARNING << "Saving statistics did not work";
+            }
+            std::map<std::string, processor::SnapshotFilter::FilterStatistics> emptyStatistics;
+            return emptyStatistics;
+        }
+
+        /// get level name1
         static std::string
         getLevelName()
         {
@@ -250,7 +286,9 @@ namespace armarx::armem::server::ltm::detail
         {
             bool enabled_on_startup = false;
             std::string configuration_on_startup =
-                "{\"SnapshotFrequencyFilter\": { \"WaitingTimeInMs\": 1000}, \"PngConverter\": {}}";
+                "{ \"SnapshotFrequencyFilter\": {\"WaitingTimeInMsForFilter\" : 1000}, \"PngConverter\": {}}";
+            std::string export_name ="MemoryExport";
+            std::string export_path = "/tmp";
         } p;
 
     protected:
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryItem.h b/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryItem.h
index bf212bb37f252afb3e848c8fe322d74a4b550b22..821f131bb10b628380359b601aac4d02ff5dbcb7 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryItem.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryItem.h
@@ -23,12 +23,12 @@ namespace armarx::armem::server::ltm::detail
         void setMemoryID(const MemoryID&);
         void setMemoryName(const std::string& memoryName);
 
-        std::string
-        getExportName() const
+        virtual std::string getExportName() const
         {
             return exportName;
         }
 
+
         MemoryID
         getMemoryID() const
         {
@@ -54,7 +54,7 @@ namespace armarx::armem::server::ltm::detail
         std::shared_ptr<Processors> processors;
 
     private:
-        std::string exportName = "MemoryExport";
+        std::string exportName = "MemoryExportMI";
         MemoryID _id;
     };
 } // namespace armarx::armem::server::ltm::detail
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/ProviderSegmentBase.h b/source/RobotAPI/libraries/armem/server/ltm/detail/ProviderSegmentBase.h
index 65021cdbb9a7487dc20f2ea930cb7a37d109e8fc..86f6306c700b9888636c6d7087cc849558a59417 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/detail/ProviderSegmentBase.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/ProviderSegmentBase.h
@@ -70,8 +70,8 @@ namespace armarx::armem::server::ltm::detail
         /// find entity segment
         virtual std::shared_ptr<EntityT> findEntity(const std::string&) const = 0;
 
-        aron::type::ObjectPtr
-        aronType() const
+        ///get aron type
+        aron::type::ObjectPtr aronType() const
         {
             return nullptr;
         }
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/BufferedMemoryMixin.h b/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/BufferedMemoryMixin.h
index 0bbf62f24ab3dd9427a9854bfadf8fe048c98bb1..bc94ec838a5afda6a2d26740f068592bbf49a607 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/BufferedMemoryMixin.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/BufferedMemoryMixin.h
@@ -1,5 +1,9 @@
 #pragma once
 
+#include <atomic>
+#include <chrono>
+#include <thread>
+
 #include <SimoxUtility/json.h>
 
 #include <ArmarXCore/core/services/tasks/PeriodicTask.h>
@@ -31,6 +35,12 @@ namespace armarx::armem::server::ltm::detail::mixin
             TIMING_END_STREAM(LTM_Memory_DirectlyStore, ARMARX_DEBUG);
         }
 
+        void
+        bufferFinished()
+        {
+            //use this to count how much work is still left
+        }
+
     protected:
         void
         setMixinMemoryID(const MemoryID& id)
@@ -51,6 +61,8 @@ namespace armarx::armem::server::ltm::detail::mixin
                 task = new armarx::PeriodicTask<BufferedMemoryMixin>(
                     this, &BufferedMemoryMixin::storeBuffer, waitingTimeMs);
                 task->start();
+                task->setDelayWarningTolerance(
+                    waitingTimeMs); //a warning will be issued if the task takes longer than the waitingTime
             }
         }
 
@@ -62,6 +74,7 @@ namespace armarx::armem::server::ltm::detail::mixin
                 task->stop();
                 task = nullptr;
             }
+
         }
 
         armem::wm::Memory
@@ -87,7 +100,12 @@ namespace armarx::armem::server::ltm::detail::mixin
                 return;
             }
 
+            while (storeFlag.test_and_set(std::memory_order_acquire))
+            {
+                std::this_thread::yield();
+            }
             this->directlyStore(*to_store);
+            storeFlag.clear(std::memory_order_release);
         }
 
         /// configuration
@@ -97,9 +115,17 @@ namespace armarx::armem::server::ltm::detail::mixin
             if (json.find("BufferedMemory.storeFrequency") != json.end())
             {
                 storeFrequency = json.at("BufferedMemory.storeFrequency");
+                ARMARX_INFO << "Setting store frequency from configuration json to "
+                            << storeFrequency;
             }
         }
 
+        void
+        createPropertyDefinitions(PropertyDefinitionsPtr& defs, const std::string& prefix)
+        {
+            defs->optional(storeFrequency, prefix + "storeFrequency");
+        }
+
         virtual void _directlyStore(const armem::wm::Memory& memory) = 0;
 
         void
@@ -109,6 +135,7 @@ namespace armarx::armem::server::ltm::detail::mixin
             buffer->append(memory);
         }
 
+
     protected:
         /// Internal memory for data consolidated from wm to ltm (double-buffer)
         /// The to-put-to-ltm buffer (contains data in plain text)
@@ -116,6 +143,7 @@ namespace armarx::armem::server::ltm::detail::mixin
         /// This means that it is not guaranteed that all data in the buffer will be stored in the ltm
         std::unique_ptr<armem::wm::Memory> buffer;
         std::unique_ptr<armem::wm::Memory> to_store;
+        std::atomic_flag storeFlag = ATOMIC_FLAG_INIT;
 
         /// The frequency (Hz) to store data to the ltm
         float storeFrequency = 10;
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/DiskStorageMixin.cpp b/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/DiskStorageMixin.cpp
index 8ceaf84eb19deaa0db3efdd5595179ed8d4bcbd4..19bfcd18bdb28870df2a9e69b1d0c74e387e07ba 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/DiskStorageMixin.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/DiskStorageMixin.cpp
@@ -23,15 +23,36 @@ namespace armarx::armem::server::ltm::detail::mixin
     {
     }
 
-    void
-    DiskMemoryItemMixin::setMemoryBasePath(const Path& n)
-    {
-        memoryBasePath = n;
+    Path
+    DiskMemoryItemMixin::addDateToMemoryBasePath(const Path& n) const
+    {       
+        //set path to include date of creation as prefix:
+        auto current_date = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
+        std::tm* localTime = std::localtime(&current_date);
+
+        // convert current time into string:
+        std::stringstream ss;
+        ss << std::put_time(localTime, "%Y_%m_%d");
+        std::string dateString = ss.str();
+
+        // change memory base path to include current date (date of memory creation)
+        std::filesystem::path current_base_path = n;
+        current_base_path.append(dateString);
+
+        //inform user about change:
+        ARMARX_DEBUG << "Changed memory base path to include current date of "
+                    << dateString
+                    << " to "
+                    << this->getMemoryBasePath()
+                       ;
+
+        return current_base_path;
     }
 
     void
     DiskMemoryItemMixin::setMixinExportName(const std::string& n)
     {
+        ARMARX_INFO << "Currently setting export name to: " << n;
         exportName = n;
     }
 
@@ -48,21 +69,31 @@ namespace armarx::armem::server::ltm::detail::mixin
     {
         if (json.find("DiskMemory.memoryParentPath") != json.end())
         {
-            memoryBasePath = Path(json.at("DiskMemory.memoryParentPath"));
+            //memoryBasePath = Path(json.at("DiskMemory.memoryParentPath"));
         }
     }
 
     Path
     DiskMemoryItemMixin::getMemoryBasePath() const
     {
-        return memoryBasePath;
+        if(memoryBasePathString.empty()){
+            return memoryBasePath;
+        } else {
+            std::filesystem::path newPath;
+            newPath.assign(memoryBasePathString);
+            return this->addDateToMemoryBasePath(newPath);
+        }
     }
 
     Path
     DiskMemoryItemMixin::getFullPath() const
     {
         auto p = getMemoryBasePath() / exportName;
-        return util::fs::toPath(p, _id);
+        //ARMARX_INFO << VAROUT(_id);
+        //ARMARX_INFO << VAROUT(_id.cleanID());
+        auto cleanID = _id.cleanID(); //somehow, the iDs are jumbled when loading the LTM from disk, this solves it for now
+
+        return util::fs::toPath(p, cleanID);
     }
 
     bool
@@ -134,4 +165,9 @@ namespace armarx::armem::server::ltm::detail::mixin
         auto p = getFullPath();
         return util::fs::getAllFiles(p);
     }
+
+    void DiskMemoryItemMixin::createPropertyDefinitions(PropertyDefinitionsPtr &defs, const std::string &prefix)
+    {
+        defs->optional(memoryBasePathString, prefix + "exportPath");
+    }
 } // namespace armarx::armem::server::ltm::detail::mixin
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/DiskStorageMixin.h b/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/DiskStorageMixin.h
index b9550d4117a0c06675b3788e3c0065c040677fd3..bf02aa5dfdae044416a0d15e91cbdf18f6b1dd83 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/DiskStorageMixin.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/DiskStorageMixin.h
@@ -44,16 +44,20 @@ namespace armarx::armem::server::ltm::detail::mixin
         std::vector<Path> getAllDirectories() const;
         std::vector<Path> getAllFiles() const;
 
+        void createPropertyDefinitions(PropertyDefinitionsPtr& defs, const std::string& prefix);
+
 
     protected:
         // setter
         void setMixinMemoryID(const MemoryID& n);
-        void setMemoryBasePath(const std::filesystem::path& n);
         void setMixinExportName(const std::string& n);
 
-        /// configuration
+        // configuration
         void configureMixin(const nlohmann::json& json);
 
+        //construct correct memory base path
+        Path addDateToMemoryBasePath(const std::filesystem::path& n) const;
+
     public:
         static const int DEPTH_TO_DATA_FILES =
             7; // from memory folder = 1 (cseg) + 1 (pseg) + 1 (ent) + 3 (snap) + 1 (inst)
@@ -67,6 +71,7 @@ namespace armarx::armem::server::ltm::detail::mixin
 
     private:
         std::filesystem::path memoryBasePath;
+        std::string memoryBasePathString;
         std::string exportName;
         armem::MemoryID _id;
     };
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/util/mongodb.h b/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/util/mongodb.h
index 9908e6c5b7f379be2ab7207a28610183c87395f5..5cb419cc05ccc2475bc1ae414b9303dbef25647c 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/util/mongodb.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/mixins/util/mongodb.h
@@ -8,15 +8,16 @@
 
 #include <RobotAPI/libraries/armem/core/MemoryID.h>
 
-#include <bsoncxx/builder/stream/array.hpp>
-#include <bsoncxx/builder/stream/document.hpp>
-#include <bsoncxx/builder/stream/helpers.hpp>
-#include <bsoncxx/json.hpp>
+
 #include <mongocxx/client.hpp>
 #include <mongocxx/instance.hpp>
 #include <mongocxx/pool.hpp>
 #include <mongocxx/stdx.hpp>
 #include <mongocxx/uri.hpp>
+#include <bsoncxx/builder/stream/array.hpp>
+#include <bsoncxx/builder/stream/document.hpp>
+#include <bsoncxx/builder/stream/helpers.hpp>
+#include <bsoncxx/json.hpp>
 
 namespace armarx::armem::server::ltm::util::mongodb
 {
diff --git a/source/RobotAPI/libraries/armem/server/ltm/processors/Processors.cpp b/source/RobotAPI/libraries/armem/server/ltm/processors/Processors.cpp
index 2b4f5afa549ab239b91d05ceafe3e49e13c2b36d..a1e16d2e35d2b6a77956799e6eb3545f8324e046 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/processors/Processors.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/processors/Processors.cpp
@@ -8,6 +8,7 @@
 #include "extractor/imageExtractor/ImageExtractor.h"
 #include "filter/equalityFilter/EqualityFilter.h"
 #include "filter/frequencyFilter/FrequencyFilter.h"
+#include "filter/importanceFilter/ImportanceFilter.h"
 
 namespace armarx::armem::server::ltm
 {
@@ -15,21 +16,51 @@ namespace armarx::armem::server::ltm
     Processors::configure(const nlohmann::json& config)
     {
         // Filters:
+        snapFilters.clear();
         if (config.contains(processor::filter::SnapshotFrequencyFilter::NAME))
         {
-            ARMARX_IMPORTANT << "ADDING SNAPSHOT FILTER";
+            ARMARX_IMPORTANT << "ADDING SNAPSHOT FREQUENCY FILTER";
             auto f = std::make_unique<processor::filter::SnapshotFrequencyFilter>();
             f->configure(config[processor::filter::SnapshotFrequencyFilter::NAME]);
             snapFilters.push_back(std::move(f));
         }
+        if(config.contains(processor::filter::SnapshotSimilarityFilter::NAME)){
+            ARMARX_IMPORTANT << "ADDING SNAPSHOT SIMILARITY FILTER";
+            auto f = std::make_unique<processor::filter::SnapshotSimilarityFilter>();
+            f->configure(config[processor::filter::SnapshotSimilarityFilter::NAME]);
+            snapFilters.push_back(std::move(f));
+        }
+        if(config.contains(processor::filter::SnapshotImportanceFilter::NAME)){
+            ARMARX_IMPORTANT << "ADDING SNAPSHOT IMPORTANCE FILTER";
+            auto f = std::make_unique<processor::filter::SnapshotImportanceFilter>();
+            f->configure(config[processor::filter::SnapshotImportanceFilter::NAME]);
+            snapFilters.push_back(std::move(f));
+        }
 
         // Converters
         if (config.contains(processor::converter::data::image::PngConverter::NAME))
         {
-            ARMARX_IMPORTANT << "ADDING IMG CONVERTER";
+            ARMARX_IMPORTANT << "ADDING IMG CONVERTER PNG";
             auto f = std::make_unique<processor::converter::data::image::PngConverter>();
             f->configure(config[processor::converter::data::image::PngConverter::NAME]);
             converters.push_back(std::move(f));
         }
+        if (config.contains(processor::converter::data::image::ExrConverter::NAME))
+        {
+            ARMARX_IMPORTANT << "ADDING IMG CONVERTER EXR";
+            auto f = std::make_unique<processor::converter::data::image::ExrConverter>();
+            f->configure(config[processor::converter::data::image::ExrConverter::NAME]);
+            converters.push_back(std::move(f));
+        }
+    }
+
+    std::map<std::string, processor::SnapshotFilter::FilterStatistics> Processors::getSnapshotFilterStatistics()
+    {
+        std::map<std::string, processor::SnapshotFilter::FilterStatistics> stats;
+        ARMARX_INFO << "Number of active filters: " << snapFilters.size();
+        for(int i = 0; i < snapFilters.size(); i++){
+            stats[snapFilters.at(i)->getName()] = snapFilters.at(i)->getFilterStatistics();
+        }
+        return stats;
     }
 } // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/processors/Processors.h b/source/RobotAPI/libraries/armem/server/ltm/processors/Processors.h
index 0f4186a2c872f30d6ef1bb9b3ce7652232e0c669..b5dc5c618bb8eac2258fdac4f626c113959552ad 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/processors/Processors.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/processors/Processors.h
@@ -23,6 +23,8 @@ namespace armarx::armem::server::ltm
 
         void configure(const nlohmann::json& config);
 
+        std::map<std::string, processor::SnapshotFilter::FilterStatistics> getSnapshotFilterStatistics();
+
     public:
         // Unique Memory Filters
         std::vector<std::unique_ptr<processor::MemoryFilter>> memFilters;
diff --git a/source/RobotAPI/libraries/armem/server/ltm/processors/converter/data/image/exr/ExrConverter.h b/source/RobotAPI/libraries/armem/server/ltm/processors/converter/data/image/exr/ExrConverter.h
index ce9cc7ab220fd794442b69c4b826b647122d022e..b65d01925c32dd8d45345c6dba78195713a83be5 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/processors/converter/data/image/exr/ExrConverter.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/processors/converter/data/image/exr/ExrConverter.h
@@ -9,6 +9,9 @@ namespace armarx::armem::server::ltm::processor::converter::data::image
     class ExrConverter : public ImageConverter
     {
     public:
+
+        static const constexpr char* NAME = "ExrConverter";
+
         ExrConverter() :
             ImageConverter(ConverterType::Binary,
                            "depthimage",
diff --git a/source/RobotAPI/libraries/armem/server/ltm/processors/converter/data/image/png/PngConverter.h b/source/RobotAPI/libraries/armem/server/ltm/processors/converter/data/image/png/PngConverter.h
index 8fb622d281147068c2c01d4902258867ce3545e3..34904df5c275158b25f9aebd64e60a3ef4f96499 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/processors/converter/data/image/png/PngConverter.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/processors/converter/data/image/png/PngConverter.h
@@ -21,6 +21,7 @@ namespace armarx::armem::server::ltm::processor::converter::data::image
 
         void configure(const nlohmann::json& json) override;
 
+
     protected:
         ConversionResult _convert(const aron::data::NDArrayPtr& data) final;
         aron::data::NDArrayPtr _convert(const ConversionResult& data,
diff --git a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/Filter.cpp b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/Filter.cpp
index c4c53c68888b5fe576572ef8166f9a20807d27ba..c947d7896c1ff08d04389857eeab3b18e5e79fed 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/Filter.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/Filter.cpp
@@ -11,4 +11,16 @@ namespace armarx::armem::server::ltm::processor
     SnapshotFilter::configure(const nlohmann::json& json)
     {
     }
+
+    SnapshotFilter::FilterStatistics SnapshotFilter::getFilterStatistics()
+    {
+        return stats;
+    }
+
+    std::string SnapshotFilter::getName()
+    {
+        return "Base_Filter";
+    }
+
+
 } // namespace armarx::armem::server::ltm::processor
diff --git a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/Filter.h b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/Filter.h
index 9d84c0a0ffdd976b54deb4585279d28161223da6..9b32dc78511a9a9b1ae7bd819558ba43c963ee3c 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/Filter.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/Filter.h
@@ -7,6 +7,7 @@
 #include <SimoxUtility/json.h>
 
 // ArmarX
+#include "RobotAPI/libraries/aron/similarity/data/image/NDArraySimilarity.h"
 #include <RobotAPI/libraries/armem/core/MemoryID.h>
 #include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
 
@@ -30,5 +31,20 @@ namespace armarx::armem::server::ltm::processor
 
         virtual bool accept(const armem::wm::EntitySnapshot& e) = 0;
         virtual void configure(const nlohmann::json& json);
+
+        struct FilterStatistics {
+            double accepted = 0;
+            double rejected = 0;
+            std::chrono::duration<double> additional_time = std::chrono::duration<double>::zero();
+            std::string additional_info = "";
+            aron::similarity::NDArraySimilarity::Type similarity_type;
+            std::chrono::high_resolution_clock::time_point start_time;
+            std::chrono::high_resolution_clock::time_point end_time;
+            int number_of_compared_objects = 2;
+            std::string importance_type = "";
+        } stats;
+
+        virtual FilterStatistics getFilterStatistics();
+        virtual std::string getName();
     };
 } // namespace armarx::armem::server::ltm::processor
diff --git a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/equalityFilter/EqualityFilter.cpp b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/equalityFilter/EqualityFilter.cpp
index 92c8bb26ecf818492401e938b1c95cecb17519e1..715520f7b51d362cfab9df471ef677e5d926e464 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/equalityFilter/EqualityFilter.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/equalityFilter/EqualityFilter.cpp
@@ -1,51 +1,183 @@
 #include "EqualityFilter.h"
+#include <list>
 
 #include <IceUtil/Time.h>
+#include "RobotAPI/libraries/aron/core/data/variant/complex/NDArray.h"
+#include "RobotAPI/libraries/aron/core/data/variant/primitive/Float.h"
+
 
 namespace armarx::armem::server::ltm::processor::filter
 {
     bool
     SnapshotSimilarityFilter::accept(const armem::wm::EntitySnapshot& e)
     {
-        auto entityID = e.id().getEntityID();
-        auto genMs = e.time().toMilliSecondsSinceEpoch();
+        auto start = std::chrono::high_resolution_clock::now();
 
-        long lastMs = 0;
-        std::vector<aron::data::DictPtr> lastData;
-        if (timestampLastCommitInMs.count(entityID) > 0)
-        {
-            lastData = dataLastCommit.at(entityID);
-            lastMs = timestampLastCommitInMs.at(entityID);
+        int num_instances = 0;
+        std::vector<armarx::aron::data::NDArrayPtr> images_snapshot;
+        std::vector<armarx::aron::data::FloatPtr> floats_snapshot;
+        std::vector<float> distances;
+
+        e.forEachInstance([&num_instances, &images_snapshot, &floats_snapshot](armem::wm::EntityInstance& i){
+           auto data = aron::data::Dict::DynamicCastAndCheck(i.data());
+           for(auto key: data->getAllKeys()){
+               aron::data::Descriptor img_desc;
+               try{
+                   auto d = data->at(key);
+;                  img_desc = data->at(key)->getDescriptor();
+               } catch (...){
+                   ARMARX_INFO << "Problem with accessing image description";
+                   img_desc = aron::data::Descriptor::NDARRAY;
+               }
+               if (img_desc == aron::data::Descriptor::NDARRAY){
+                   auto img_nd = aron::data::NDArray::DynamicCastAndCheck(data->at(key));
+                   images_snapshot.insert(images_snapshot.end(), img_nd);
+                   num_instances++;
+               } else if (img_desc == aron::data::Descriptor::FLOAT){
+                    auto fl = aron::data::Float::DynamicCastAndCheck(data->at(key));
+                    floats_snapshot.push_back(fl);
+                    num_instances++;
+               } else {
+                   ARMARX_INFO << "data-type not yet supported. \n"
+                               << "Only ndarray and float data types are supported for equality filters yet.";
+               }
+           }
+        });
+
+        if(images.size() < 2){
+            ARMARX_INFO << "Adding first images, because nothing to compare";
+            images.push_back(images_snapshot);
+            this->stats.accepted += 1;
+            auto end = std::chrono::high_resolution_clock::now();
+            stats.end_time = end;
+            stats.additional_time += (end - start);
+            return true;
+        } else if(images.size() < max_images){
+            ARMARX_INFO << "Not enough elements yet to do full comparison of last " << max_images
+                        << " elements";
+            images.push_back(images_snapshot);
+            this->stats.accepted += 1;
+            auto end = std::chrono::high_resolution_clock::now();
+            stats.end_time = end;
+            stats.additional_time += (end - start);
+            return true;
         }
 
 
-        bool accept = false;
-        std::vector<aron::data::DictPtr> genData;
-        for (unsigned int i = 0; i != e.size(); ++i)
-        {
-            const auto& d = e.getInstance(i).data();
-            genData.push_back(d);
-
-            if (lastMs == 0 ||
-                e.size() != lastData.size()) // nothing stored yet or we cannot compare
-            {
-                accept = true;
-                break;
+        std::vector<armarx::aron::data::NDArrayPtr> lastCommittedImages;
+        int sizeOfCommited = 0;
+        for(int i = 0; i < max_images; i++){
+            std::vector<armarx::aron::data::NDArrayPtr> lastCommitImages = images.at(images.size() - i - 1);
+            sizeOfCommited = lastCommitImages.size();
+            for(int j = 0; j < lastCommitImages.size(); j++){
+                lastCommittedImages.push_back(lastCommitImages.at(j));
             }
+            // we just concatenate all images (instances)
+        }
 
-            const auto& el = lastData.at(i);
-            if ((!d and el) || (d and !el) || (d && el && !(*d == *el))) // data unequal?
-            {
-                accept = true;
-                break;
+        ARMARX_CHECK(sizeOfCommited == images_snapshot.size()); //make sure we have enough instances
+
+        for(int i= 0; i < images_snapshot.size(); i++){
+            armarx::aron::data::NDArrayPtr new_image = images_snapshot.at(i);
+            std::vector<armarx::aron::data::NDArrayPtr> commited_images;
+            for(int j = 0; j < max_images; j++){
+                int index = i + 2*j;
+                auto image = lastCommittedImages.at(index);
+                commited_images.emplace_back(image);
             }
+
+            float distance = aron::similarity::NDArraySimilarity::calculate_similarity_multi(commited_images, new_image, this->similarity_type);
+
+            distances.insert(distances.end(), distance);
+        }
+
+        //check for criterion:
+        float sum_distances = 0;
+        float max_distance = 0;
+        for(auto d: distances){
+            sum_distances += d;
+            if(d > max_distance){
+                max_distance = d;
+            }
+        }
+
+        bool max = true; //set true if only maximum distance value is important and false if sum of distances is important
+        bool accept = false;
+
+        if(max){
+            accept = (max_distance > this->threshold);
+        } else {
+            accept = (sum_distances > this->threshold);
         }
 
-        if (!accept)
+        if(accept){
+            images.pop_front(); //delete first element
+            images.push_back(images_snapshot);
+            this->stats.accepted += 1;
+            auto end = std::chrono::high_resolution_clock::now();
+            stats.additional_time += (end - start);
+            stats.end_time = end;
+            return true;
+        } else {
+            this->stats.rejected += 1;
+            auto end = std::chrono::high_resolution_clock::now();
+            stats.additional_time += (end - start);
+            stats.end_time = end;
             return false;
+        }
+    }
+
+    void SnapshotSimilarityFilter::configure(const nlohmann::json &json)
+    {
+        if (json.find(PARAM_THRESHOLD) != json.end())
+        {
+            threshold = json.at(PARAM_THRESHOLD);
+            ARMARX_INFO << VAROUT(threshold);
+            stats.additional_info += "Threshold-Parameter: ";
+            stats.additional_info += std::to_string(threshold);
+        }
+        if(json.find(PARAM_SIM_MEASURE) != json.end()){
+            std::string type_string = json.at(PARAM_SIM_MEASURE);
+            if(type_string == "MSE"){
+                this->similarity_type = aron::similarity::NDArraySimilarity::Type::MSE;
+                this->float_similarity_type = aron::similarity::FloatSimilarity::Type::MSE;
+                stats.similarity_type = aron::similarity::NDArraySimilarity::Type::MSE;
+            } else if (type_string == "MAE"){
+                this->similarity_type = aron::similarity::NDArraySimilarity::Type::MAE;
+                this->float_similarity_type = aron::similarity::FloatSimilarity::Type::MAE;
+                stats.similarity_type = aron::similarity::NDArraySimilarity::Type::MAE;
+            } else if (type_string == "Chernoff"){
+                this->similarity_type = aron::similarity::NDArraySimilarity::Type::CHERNOFF;
+                this->float_similarity_type = aron::similarity::FloatSimilarity::Type::NONE;
+                stats.similarity_type = aron::similarity::NDArraySimilarity::Type::CHERNOFF;
+            } else if (type_string == "Cosine"){
+                this->similarity_type = aron::similarity::NDArraySimilarity::Type::COSINE;
+                this->float_similarity_type = aron::similarity::FloatSimilarity::Type::NONE;
+                stats.similarity_type = aron::similarity::NDArraySimilarity::Type::COSINE;
+            } else {
+                ARMARX_WARNING << "Undefined similarity measure detected in JSON file";
+                stats.similarity_type = aron::similarity::NDArraySimilarity::Type::NONE;
+                this->float_similarity_type = aron::similarity::FloatSimilarity::Type::NONE;
+            }
+            ARMARX_INFO << VAROUT(this->similarity_type);
+        }
+        if(json.find(PARAM_MAX_OBJECTS) != json.end()){
+            max_images = json.at(PARAM_MAX_OBJECTS);
+            ARMARX_INFO << VAROUT(max_images);
+            stats.number_of_compared_objects = max_images;
+        }
+
+        stats.start_time = std::chrono::high_resolution_clock::now();
+    }
+
+    SnapshotFilter::FilterStatistics SnapshotSimilarityFilter::getFilterStatistics()
+    {
+        return stats;
+    }
 
-        dataLastCommit[entityID] = genData;
-        timestampLastCommitInMs[entityID] = genMs;
-        return true;
+    std::string SnapshotSimilarityFilter::getName()
+    {
+        return this->NAME;
     }
+
 } // namespace armarx::armem::server::ltm::filter
diff --git a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/equalityFilter/EqualityFilter.h b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/equalityFilter/EqualityFilter.h
index 203b1fe3fa87108b144c604a59ebf46e58ab350f..67448db2dba914f0d7de8f392433e55f03725026 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/equalityFilter/EqualityFilter.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/equalityFilter/EqualityFilter.h
@@ -8,6 +8,10 @@
 
 // Aron
 #include <RobotAPI/libraries/aron/core/data/variant/container/Dict.h>
+#include "RobotAPI/libraries/aron/similarity/data/image/NDArraySimilarity.h"
+#include "RobotAPI/libraries/aron/similarity/data/image/FloatSimilarity.h"
+
+#include <chrono>
 
 namespace armarx::armem::server::ltm::processor::filter
 {
@@ -15,16 +19,28 @@ namespace armarx::armem::server::ltm::processor::filter
     {
     public:
         static const constexpr char* NAME = "SnapshotSimilarityFilter";
+        static const constexpr char* PARAM_THRESHOLD = "Threshold";
+        static const constexpr char* PARAM_SIM_MEASURE = "SimilarityMeasure";
+        static const constexpr char* PARAM_MAX_OBJECTS = "NumberOfObjectsToCompare";
 
         SnapshotSimilarityFilter() = default;
 
         virtual bool accept(const armem::wm::EntitySnapshot& e) override;
+        void configure(const nlohmann::json& json) override;
 
-    public:
-        // TODO link aron/similarity
+        FilterStatistics getFilterStatistics() override;
+        std::string getName() override;
 
     private:
-        std::map<MemoryID, std::vector<aron::data::DictPtr>> dataLastCommit;
+        //std::map<MemoryID, std::vector<aron::data::DictPtr>> dataLastCommit;
+        std::deque<std::vector<armarx::aron::data::NDArrayPtr>> images;
+        std::deque<std::vector<armarx::aron::data::FloatPtr>> floats;
         std::map<MemoryID, long> timestampLastCommitInMs;
+        std::double_t threshold;
+        FilterStatistics stats;
+        int max_images = 2;
+        aron::similarity::NDArraySimilarity::Type similarity_type;
+        aron::similarity::FloatSimilarity::Type float_similarity_type;
+
     };
 } // namespace armarx::armem::server::ltm::processor::filter
diff --git a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/frequencyFilter/FrequencyFilter.cpp b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/frequencyFilter/FrequencyFilter.cpp
index 56c7250c37988efd1b5fc824aec8aabd2e040a17..aa773fc1faf83bb36a43801620def4508cf604cd 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/frequencyFilter/FrequencyFilter.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/frequencyFilter/FrequencyFilter.cpp
@@ -1,51 +1,49 @@
 #include "FrequencyFilter.h"
 
-#include <IceUtil/Time.h>
+#include <chrono>
 
 namespace armarx::armem::server::ltm::processor::filter
 {
+
     bool
-    MemoryFrequencyFilter::accept(const armem::wm::Memory& e)
+    SnapshotFrequencyFilter::accept(const armem::wm::EntitySnapshot &e)
     {
-        auto now = armem::Time::Now().toMilliSecondsSinceEpoch();
-        if (waitingTimeInMs < 0 || (now - timestampLastCommitInMs) > waitingTimeInMs)
-        {
-            timestampLastCommitInMs = now;
-            return true;
-        }
-        return false;
-    }
 
-    void
-    MemoryFrequencyFilter::configure(const nlohmann::json& json)
-    {
-        if (json.find(PARAM_WAITING_TIME) != json.end())
-        {
-            waitingTimeInMs = json.at(PARAM_WAITING_TIME);
+        //accepting to many elements makes the filter slow and brings problems with the buffer with itself.
+        auto start = std::chrono::high_resolution_clock::now();
+        bool instances_accepted = false;
+        std::int64_t current;
+
+        if(this->lastTime < 1){ //this is the first instance to be saved
+            lastTime = e.time().toMilliSecondsSinceEpoch();
+            auto end = std::chrono::high_resolution_clock::now();
+            stats.end_time = end;
+            stats.additional_time += (end - start);
+            stats.accepted += 1;
+            return true; //the first one is always accepted
         }
-    }
 
-    bool
-    SnapshotFrequencyFilter::accept(const armem::wm::EntitySnapshot& e)
-    {
-        auto entityID = e.id().getEntityID();
-        auto genMs = e.time().toMilliSecondsSinceEpoch();
+        e.forEachInstance([this, &instances_accepted, &current](armem::wm::EntityInstance& i){
+            int difference = std::abs(i.metadata().sentTime.toMilliSecondsSinceEpoch() - lastTime);
+            if(difference > this->maxDifference){ //at least one instance is older than the last saved instance
+                instances_accepted = true;
+                current = i.metadata().sentTime.toMilliSecondsSinceEpoch();
+            }
+        });
 
-        long lastMs = 0;
-        if (timestampLastCommitInMs.count(entityID) > 0)
-        {
-            lastMs = timestampLastCommitInMs.at(entityID);
-        }
+        //set stats:
+        auto end = std::chrono::high_resolution_clock::now();
+        stats.end_time = end;
+        stats.additional_time += (end - start);
 
-        if (waitingTimeInMs < 0 || (genMs - lastMs) > waitingTimeInMs)
-        {
-            /*std::cout << "diff: " << (dataGeneratedInMs - timestampLastCommitInMs) << std::endl;
-            std::cout << "gen: " << (dataGeneratedInMs) << std::endl;
-            std::cout << "last: " << (timestampLastCommitInMs) << std::endl;*/
-            timestampLastCommitInMs[entityID] = genMs;
-            return true;
+        if(instances_accepted){
+            lastTime = current;
+            this->stats.accepted += 1;
+        } else {
+            this->stats.rejected += 1;
         }
-        return false;
+
+        return instances_accepted;
     }
 
     void
@@ -53,7 +51,23 @@ namespace armarx::armem::server::ltm::processor::filter
     {
         if (json.find(PARAM_WAITING_TIME) != json.end())
         {
-            waitingTimeInMs = json.at(PARAM_WAITING_TIME);
+            this->maxDifference = json.at(PARAM_WAITING_TIME);
+            ARMARX_INFO << VAROUT(maxDifference);
+            stats.additional_info = "Max Difference in ms: " + std::to_string(this->maxDifference);
         }
+        stats.start_time = std::chrono::high_resolution_clock::now();
+        stats.number_of_compared_objects = 1;
+        stats.similarity_type = aron::similarity::NDArraySimilarity::Type::NONE; //information for statistics export
+    }
+
+    SnapshotFilter::FilterStatistics SnapshotFrequencyFilter::getFilterStatistics()
+    {
+        stats.end_time = std::chrono::high_resolution_clock::now();
+        return this->stats;
+    }
+
+    std::string SnapshotFrequencyFilter::getName()
+    {
+        return this->NAME;
     }
 } // namespace armarx::armem::server::ltm::processor::filter
diff --git a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/frequencyFilter/FrequencyFilter.h b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/frequencyFilter/FrequencyFilter.h
index 00ba1e9db0162d4d866a359c920008838ad5e279..1b778528ebd0812c91dada5f1e275f9bfcfa44ca 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/frequencyFilter/FrequencyFilter.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/frequencyFilter/FrequencyFilter.h
@@ -1,45 +1,28 @@
 #pragma once
 
-#include <map>
-
 // Base Class
 #include "../Filter.h"
 
 namespace armarx::armem::server::ltm::processor::filter
 {
-    class MemoryFrequencyFilter : public MemoryFilter
-    {
-    public:
-        static const constexpr char* NAME = "MemoryFrequencyFilter";
-        static const constexpr char* PARAM_WAITING_TIME = "WaitingTimeInMs";
-
-        MemoryFrequencyFilter() = default;
-
-        virtual bool accept(const armem::wm::Memory& e) override;
-        void configure(const nlohmann::json& json) override;
-
-    public:
-        int waitingTimeInMs = -1;
-
-    private:
-        long timestampLastCommitInMs = 0;
-    };
 
     class SnapshotFrequencyFilter : public SnapshotFilter
     {
     public:
         static const constexpr char* NAME = "SnapshotFrequencyFilter";
-        static const constexpr char* PARAM_WAITING_TIME = "WaitingTimeInMs";
+        static const constexpr char* PARAM_WAITING_TIME = "WaitingTimeInMsForFilter";
 
         SnapshotFrequencyFilter() = default;
 
-        virtual bool accept(const armem::wm::EntitySnapshot& e) override;
+        virtual bool accept(const armem::wm::EntitySnapshot &e) override;
         void configure(const nlohmann::json& json) override;
 
-    public:
-        int waitingTimeInMs = -1;
+        FilterStatistics getFilterStatistics() override;
+        std::string getName() override;
 
     private:
-        std::map<MemoryID, long> timestampLastCommitInMs;
+        int maxDifference = 0;
+        std::int64_t lastTime = 0;
+
     };
 } // namespace armarx::armem::server::ltm::processor::filter
diff --git a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/importanceFilter/ImportanceFilter.cpp b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/importanceFilter/ImportanceFilter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0ae255a4d4488048c7786aa1fafa3d67f2538f77
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/importanceFilter/ImportanceFilter.cpp
@@ -0,0 +1,84 @@
+#include "ImportanceFilter.h"
+
+
+namespace armarx::armem::server::ltm::processor::filter
+{
+
+bool SnapshotImportanceFilter::accept(const armem::wm::EntitySnapshot &e)
+{
+    auto start = std::chrono::high_resolution_clock::now();
+    bool instances_accepted = false;
+
+    e.forEachInstance([this, &instances_accepted](armem::wm::EntityInstance& i){  
+        if(!instances_accepted){ //if no instance was accepted yet
+            instances_accepted = important(i); //see if another instance triggers acceptance
+        }
+    });
+
+    //set stats:
+    auto end = std::chrono::high_resolution_clock::now();
+    stats.end_time = end;
+    stats.additional_time += (end - start);
+    if(instances_accepted){
+        stats.accepted += 1;
+    } else {
+        stats.rejected += 1;
+    }
+
+    return instances_accepted;
+}
+
+void SnapshotImportanceFilter::configure(const nlohmann::json &json)
+{
+    if(json.find(PARAM_THRESHOLD) != json.end()){
+        this->threshold = json.at(PARAM_THRESHOLD);
+        ARMARX_INFO << VAROUT(this->threshold);
+        stats.additional_info += "Threshold for importance: ";
+        stats.additional_info += std::to_string(this->threshold);
+    }
+    if(json.find(PARAM_TYPE) != json.end()){
+        auto t = json.at(PARAM_TYPE);
+        if(t == "Confidence"){
+            this->type = ImportanceType::CONFIDENCE;
+        }
+        if(t == "Accesses"){
+            this->type = ImportanceType::ACCESSES;
+        }
+        stats.importance_type = t;
+        ARMARX_INFO << VAROUT(stats.importance_type);
+    }
+
+    stats.start_time = std::chrono::high_resolution_clock::now();
+    stats.number_of_compared_objects = 1;
+    stats.similarity_type = aron::similarity::NDArraySimilarity::Type::NONE; //information for statistics export
+}
+
+SnapshotFilter::FilterStatistics SnapshotImportanceFilter::getFilterStatistics()
+{
+    return this->stats;
+}
+
+std::string SnapshotImportanceFilter::getName()
+{
+    return this->NAME;
+}
+
+bool SnapshotImportanceFilter::important(armem::wm::EntityInstance &i)
+{
+    if(this->type == ImportanceType::CONFIDENCE){
+        auto c = i.metadata().confidence;
+        if ( c > this->threshold){
+            //for now the whole entity snapshot is accepted if at least one instance has a confidence higher than the threshold
+            return true;
+        }
+    } else if (this->type == ImportanceType::ACCESSES){
+        auto a = i.metadata().numAccessed;
+        if (a > this->threshold){
+            return true;
+        }
+    }
+    return false;
+}
+
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/processors/filter/importanceFilter/ImportanceFilter.h b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/importanceFilter/ImportanceFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..929bb2e2ac6b03b31f9225cbda74b4a4b34f8e8d
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/processors/filter/importanceFilter/ImportanceFilter.h
@@ -0,0 +1,41 @@
+#pragma once
+
+// Base Class
+#include "../Filter.h"
+
+#include <chrono>
+
+namespace armarx::armem::server::ltm::processor::filter
+{
+
+enum ImportanceType{
+    CONFIDENCE,
+    ACCESSES
+};
+
+class SnapshotImportanceFilter : public SnapshotFilter
+{
+public:
+
+    static const constexpr char* NAME = "SnapshotImportanceFilter";
+    static const constexpr char* PARAM_THRESHOLD = "Threshold";
+    static const constexpr char* PARAM_TYPE = "Type";
+
+    SnapshotImportanceFilter() = default;
+
+    virtual bool accept(const armem::wm::EntitySnapshot& e) override;
+    void configure(const nlohmann::json& json) override;
+
+    FilterStatistics getFilterStatistics() override;
+    std::string getName() override;
+
+private:
+    double threshold = 1.0;
+    FilterStatistics stats;
+    ImportanceType type;
+
+    bool important(armem::wm::EntityInstance& i);
+
+};
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/plugins/Plugin.cpp b/source/RobotAPI/libraries/armem/server/plugins/Plugin.cpp
index d379cf033d76392d07417b0345aa09a3cca900bf..665d49ca87dbb6596e70f97530ff589da9b34338 100644
--- a/source/RobotAPI/libraries/armem/server/plugins/Plugin.cpp
+++ b/source/RobotAPI/libraries/armem/server/plugins/Plugin.cpp
@@ -8,6 +8,8 @@
 #include <RobotAPI/libraries/armem/client/util/MemoryListener.h>
 #include <RobotAPI/libraries/armem/core/error.h>
 
+#include <chrono>
+
 namespace armarx::armem::server::plugins
 {
 
@@ -41,7 +43,6 @@ namespace armarx::armem::server::plugins
                 workingMemory.name(), prefix + "MemoryName", "Name of this memory server.");
         }
 
-        // stuff for ltm
         longtermMemory.createPropertyDefinitions(properties, prefix + "ltm.");
     }
 
@@ -93,10 +94,35 @@ namespace armarx::armem::server::plugins
     void
     Plugin::preOnDisconnectComponent()
     {
+        ARMARX_INFO << "Preparing to save statistics for " << this->workingMemory.name();
+        try{
+            auto first_stats = longtermMemory.getFilterStatistics();
+            std::map<std::string, std::map<std::string, ltm::processor::SnapshotFilter::FilterStatistics>> information;
+            std::map<std::string, armarx::core::time::DateTime> times;
+
+            try{ 
+                times["Started LTM1"] = longtermMemory.getStatistics().firstStarted;
+                times["Stopped LTM1"] = longtermMemory.getStatistics().firstStopped;
+                information["LTM"] = first_stats;
+            } catch(...){
+                ARMARX_INFO << "Something went wrong after getting the statistics";
+            }
+            auto exportPath = longtermMemory.getMemoryBasePath();
+            auto exportName = longtermMemory.getExportName();
+            auto recording_started = longtermMemory.getStatistics().firstStarted;
+            auto recording_stopped = longtermMemory.getStatistics().firstStopped;
+            test::save_statistics(information, times, recording_started, recording_stopped,
+                                  exportPath, exportName, longtermMemory.name());
+         }catch (...){
+            ARMARX_INFO << "Something went wrong with the statistics saving process";
+         }
+
+        statistics_saved = true;
+
         if (clientPlugin->isMemoryNameSystemEnabled() and clientPlugin->getMemoryNameSystemClient())
         {
             removeServer();
-        }
+        } 
     }
 
     void
@@ -114,6 +140,7 @@ namespace armarx::armem::server::plugins
     mns::dto::RegisterServerResult
     Plugin::registerServer(armarx::Component& parent)
     {
+        ARMARX_INFO << "Registering server for " << workingMemory.name();
         ARMARX_TRACE;
 
         MemoryID id = MemoryID().withMemoryName(workingMemory.name());
@@ -137,6 +164,8 @@ namespace armarx::armem::server::plugins
             result.errorMessage = e.what();
             ARMARX_WARNING << e.what();
         }
+
+
         return result;
     }
 
@@ -152,6 +181,7 @@ namespace armarx::armem::server::plugins
             result.success = true;
             ARMARX_DEBUG << "Removed memory server for " << id
                          << " from the Memory Name System (MNS).";
+
         }
         catch (const armem::error::ServerRegistrationOrRemovalFailed& e)
         {
diff --git a/source/RobotAPI/libraries/armem/server/plugins/Plugin.h b/source/RobotAPI/libraries/armem/server/plugins/Plugin.h
index e37c5e093232af4aae66114703a7debb8f122ba4..0712e4d9f2281adf2c435a7585a019b97907c9d7 100644
--- a/source/RobotAPI/libraries/armem/server/plugins/Plugin.h
+++ b/source/RobotAPI/libraries/armem/server/plugins/Plugin.h
@@ -85,6 +85,7 @@ namespace armarx::armem::server::plugins
 
         std::atomic_bool initialized = false;
         std::atomic_bool connected = false;
+        std::atomic_bool statistics_saved = false;
     };
 } // namespace armarx::armem::server::plugins
 
diff --git a/source/RobotAPI/libraries/armem/server/test/ForgettingExperiments.cpp b/source/RobotAPI/libraries/armem/server/test/ForgettingExperiments.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0025f3e20582dea2ab6891cf11ec9b8b5584a989
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/test/ForgettingExperiments.cpp
@@ -0,0 +1,280 @@
+#include "ForgettingExperiments.h"
+
+#include <iostream>
+#include <fstream>
+#include <chrono>
+#include <filesystem>
+
+namespace armarx::armem::server::test
+{
+
+void get_information_single_ltm(
+        std::map<std::string, ltm::processor::SnapshotFilter::FilterStatistics>& filter
+        )
+{
+    /*
+    nlohmann::json info;
+    for(const auto& pair: filter.second){
+        if(pair.second.accepted + pair.second.rejected < 1){
+            ended_without_recording = true;
+            ARMARX_INFO << "Trying to not add JSON file because accepted + rejected < 1";
+        }
+        std::map<std::string, std::string> information;
+        information["Memory Name: "] = memoryName;
+        information["additional time needed: "] = (std::to_string(pair.second.additional_time.count()) + " sec");
+        information["number of accepted elements: "] = std::to_string(pair.second.accepted);
+        information["number of rejected elements: "] = std::to_string(pair.second.rejected);
+        information["Additional information: "] = pair.second.additional_info;
+        information["Similarity-Type: "] = std::to_string(pair.second.similarity_type);
+        information["Number of objects compared each time: "] = std::to_string((pair.second.number_of_compared_objects));
+        information["Importance type: "] = pair.second.importance_type;
+        auto time = std::chrono::high_resolution_clock::to_time_t(pair.second.start_time);
+        auto t = localtime(&time);
+        std::stringstream ss;
+        ss << std::put_time(t, "%Y-%m-%d %H:%M:%S");
+        std::string timeString = ss.str();
+        information["Filter instance created at: "] = timeString;
+        time = std::chrono::high_resolution_clock::to_time_t(pair.second.end_time);
+        t = localtime(&time);
+        std::stringstream s;
+        s << std::put_time(t, "%Y-%m-%d %H:%M:%S");
+        timeString = s.str();
+        information["Filter instance last used at: "] = timeString;
+        info[pair.first] = information;
+
+        armarx::core::time::DateTime start_time = time_stats["Started " + filter.first];
+        auto started = start_time.toDateTimeString();
+        info["Started"] = started;
+        ARMARX_INFO << started;
+
+        armarx::core::time::DateTime stop_time = time_stats["Stopped " + filter.first];
+        auto stopped = stop_time.toDateTimeString();
+        info["Stopped"] = stopped;
+        ARMARX_INFO << stopped;
+    }
+    jsonData[filter.first] = info;
+    info.clear();
+    */
+}
+
+void save_statistics(
+        std::map<std::string, std::map<std::string, ltm::processor::SnapshotFilter::FilterStatistics>> stats,
+        std::map<std::string, armarx::core::time::DateTime> time_stats,
+        armarx::core::time::DateTime firstStartedRecording,
+        armarx::core::time::DateTime firstStoppedRecording,
+        std::filesystem::path exportPath,
+        std::string exportName,
+        std::string memoryName,
+        std::string sim_json_data,
+        std::string object_memory_json_data)
+{
+    ARMARX_INFO << "Saving statistics";
+
+    std::filesystem::path d_p;
+    try{
+        d_p = test::getStatisticsDirectory(exportPath, exportName, memoryName);
+        std::filesystem::create_directories(d_p);
+        ARMARX_INFO << "Experiments will be saved at: " << d_p.string();
+    } catch(...){
+        ARMARX_WARNING << "Creating needed directories for saving statistics did not work";
+    }
+
+    //json object for statistics:
+    nlohmann::json jsonData;
+
+    //get current date:
+    auto now = std::chrono::high_resolution_clock::now();
+    auto now_time = std::chrono::high_resolution_clock::to_time_t(now);
+    auto time = localtime(&now_time);
+
+    std::stringstream ss;
+    ss << std::put_time(time, "%Y-%m-%d %H:%M:%S");
+    std::string timeString = ss.str();
+    std::stringstream s;
+    s << std::put_time(time, "%Y%m%d%H%M%S");
+    std::string timeID = s.str();
+    jsonData["Statistics saved at"] = timeString;
+
+    bool ended_without_recording = false;
+
+    for(const auto& filter: stats){
+       filter_statistics(filter.second, memoryName,firstStartedRecording, firstStoppedRecording, &jsonData);
+    }
+
+    if(ended_without_recording){
+        return;
+    }
+
+    /*
+    if(sim_json_data.empty() || object_memory_json_data.empty()){
+        jsonData["Scene-Information for Simulation"] = load_scene_information("sim");
+        jsonData["Scene-Information for ObjectMemory"] = load_scene_information("om");
+        jsonData["Additional object in simulation"] = find_difference(jsonData["Scene-Information for ObjectMemory"], jsonData["Scene-Information for Simulation"]);
+    }else {
+        jsonData["Scene-Information for Simulation"] = sim_json_data;
+        jsonData["Scene-Information for ObjectMemory"] = object_memory_json_data;
+    }
+    */
+
+    std::string path = d_p.string();
+    path += "/tmp_wm_";
+    path += timeID;
+    path += ".json";
+    try{
+    std::ofstream outputFile;
+    outputFile.open(path);
+        if(outputFile.is_open()){
+            outputFile << jsonData.dump(4);
+            outputFile.close();
+        } else {
+            if(outputFile.fail()){
+                ARMARX_INFO << outputFile.rdstate();
+                outputFile.clear();
+            }
+            ARMARX_INFO << "File is not open";
+        }
+    } catch(...){
+        ARMARX_WARNING << "std::ofstream failed";
+    }
+
+    ARMARX_INFO << "Saving statistics completed";
+}
+
+nlohmann::json load_scene_information(std::string om_or_sim)
+{
+    std::string home_dir = getenv("HOME");
+    if(home_dir.empty()){
+        ARMARX_WARNING << "Trying to open home directory but env variable HOME is not set";
+    }
+    std::filesystem::path path = home_dir;
+    path /= "code";
+    path /= "h2t" ;
+    path /= "PriorKnowledgeData";
+    path /= "data";
+    path /= "PriorKnowledgeData";
+    path /= "scenes";
+    std::string name_for_current_scene = "ARMAR-III-kitchen"; //this can be changed later, maybe to something that indicates better that these are the changed files
+    std::string file_name = name_for_current_scene + "_" + om_or_sim + ".json";
+    path /= file_name;
+
+    std::ifstream ifs(path);
+    nlohmann::json json_data = nlohmann::json::parse(ifs);
+
+    return json_data;
+
+}
+
+nlohmann::json find_difference(nlohmann::json om, nlohmann::json sim)
+{
+    //the new object is at the last position of sim at the moment
+    auto objects = sim.at("objects");
+    int num_elements = objects.size();
+    auto object = objects[num_elements - 1];
+    return object;
+}
+
+/**
+ * @brief getStatisticsDirectory returns the path to where the statistics for this forgetting process
+ * should be saved
+ * @param memoryName name of the memory, e.g. VisionMemory
+ * @param exportName name of the export
+ * @param exportPath path to the export folder with date for this LTM
+ * @return path
+ */
+std::filesystem::path getStatisticsDirectory(
+        std::filesystem::path exportPath,
+        std::string exportName,
+        std::string memoryName)
+{
+    //path consists of exportPath/Date/exportName/memoryName with the date being the start date!
+    std::filesystem::path statisticsPath = exportPath;
+
+    //add parts to exportPath
+    statisticsPath /= exportName;
+    statisticsPath /= memoryName;
+
+    //add Statistics Directory:
+    statisticsPath /= "Statistics";
+
+    return statisticsPath;
+}
+
+void filter_statistics(
+        std::map<std::string, ltm::processor::SnapshotFilter::FilterStatistics> statistics_processors,
+        std::string memoryName,
+        armarx::core::time::DateTime firstStartedRecording,
+        armarx::core::time::DateTime firstStoppedRecording,
+        nlohmann::json *statistics)
+{
+    //TODO: start time of processor should be when enabling recording for filters... not creation
+    //TODO: make sure order stays the way it was when added
+    nlohmann::json ltm_information;
+
+    for(const auto& statistics_processor: statistics_processors){
+        nlohmann::json processor_information;
+
+        //get start time of the processor:
+        auto time = std::chrono::high_resolution_clock::to_time_t(statistics_processor.second.start_time);
+        auto t = localtime(&time);
+        std::stringstream ss;
+        ss << std::put_time(t, "%Y-%m-%d %H:%M:%S");
+        std::string timeStringStart = ss.str();
+        processor_information["Processor instance created at"] = timeStringStart;
+
+        //get end time of the processor:
+        auto timeEnd = std::chrono::high_resolution_clock::to_time_t(statistics_processor.second.end_time);
+        auto t_end = localtime(&timeEnd);
+        std::stringstream s;
+        s << std::put_time(t_end, "%Y-%m-%d %H:%M:%S");
+        std::string timeStringEnd = s.str();
+        processor_information["Processor instance last used at"] = timeStringEnd;
+
+        //get time the processor ran for in seconds:
+        long seconds = timeEnd - time;
+        processor_information["Lifetime of processor in sec"] = seconds;
+
+        //actual runtime in first recording:
+        processor_information["Processor started at"] = firstStartedRecording.toDateTimeString();
+        processor_information["Processor stopped at"] = firstStoppedRecording.toDateTimeString();
+        auto runtime = firstStoppedRecording.toMilliSecondsSinceEpoch() - firstStartedRecording.toMilliSecondsSinceEpoch();
+        auto seconds_runtime = runtime / 1000.0;
+        processor_information["Duration of recording in seconds"] = seconds_runtime;
+
+        //add additional information:
+        processor_information["Additional information"] = statistics_processor.second.additional_info;
+
+        //add number of accepted elements if this is a filter:
+        processor_information["Accepted elements"] = statistics_processor.second.accepted;
+
+        //add number of rejected elements if this is a filter:
+        processor_information["Rejected elements"] = statistics_processor.second.rejected;
+
+        //add additional time needed:
+        processor_information["Additional time needed in sec"] = statistics_processor.second.additional_time.count();
+
+        //add importance or similarity type if this type of filter:
+        auto importance_type = statistics_processor.second.importance_type;
+        if (!importance_type.empty()){
+            processor_information["Importance type"] = importance_type;
+        }
+        auto similarity_type = statistics_processor.second.similarity_type;
+        if(similarity_type != aron::similarity::NDArraySimilarity::Type::NONE){
+            processor_information["Similarity type"] = std::to_string(similarity_type);
+            //add number of objects compared each time if similarity filter:
+            processor_information["Number of objects compared each time"] =
+                    statistics_processor.second.number_of_compared_objects;
+        }
+
+        //add memory name as a sanity check:
+        processor_information["Memory name"] = memoryName;
+
+        // add information about this specific processor to the information about the ltm:
+        ltm_information[statistics_processor.first] = processor_information;
+    }
+
+
+    // add the ltm information to the statistics json object:
+    (*statistics)["Episodic Memory Information"] = ltm_information;
+}
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/test/ForgettingExperiments.h b/source/RobotAPI/libraries/armem/server/test/ForgettingExperiments.h
new file mode 100644
index 0000000000000000000000000000000000000000..ce929849a4d05cbd343b915d7bad6279aeb0e057
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/test/ForgettingExperiments.h
@@ -0,0 +1,63 @@
+/*
+ * 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     Joana Plewnia ( uhfpm at student dot kit dot edu )
+ * @date       2023
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#include <RobotAPI/libraries/aron/core/data/variant/All.h>
+#include <RobotAPI/libraries/armem/server/ltm/processors/filter/Filter.h>
+
+namespace armarx::armem::server::test
+{
+    void save_statistics(
+            std::map<std::string, std::map<std::string, ltm::processor::SnapshotFilter::FilterStatistics>> stats,
+            std::map<std::string, armarx::core::time::DateTime> time_stats,
+            armarx::core::time::DateTime firstStartedRecording,
+            armarx::core::time::DateTime firstStoppedRecording,
+            std::filesystem::path exportPath = "/tmp",
+            std::string exportName ="MemoryExports",
+            std::string memoryName = "",
+            std::string sim_json_data = "",
+            std::string object_memory_json_data = ""
+            );
+
+    nlohmann::json load_scene_information(std::string om_or_sim);
+
+    nlohmann::json find_difference(nlohmann::json om, nlohmann::json sim);
+
+    std::filesystem::path getStatisticsDirectory(
+            std::filesystem::path exportPath = "/tmp",
+            std::string exportName ="MemoryExports",
+            std::string memoryName = "NoMemoryName");
+
+    nlohmann::json filter_statistics_comparison();
+
+    void filter_statistics(
+            std::map<std::string, ltm::processor::SnapshotFilter::FilterStatistics> statistics_processors,
+            std::string memoryName,
+            armarx::core::time::DateTime firstStartedRecording,
+            armarx::core::time::DateTime firstStoppedRecording,
+            nlohmann::json* statistics);
+
+}
diff --git a/source/RobotAPI/libraries/aron/core/CMakeLists.txt b/source/RobotAPI/libraries/aron/core/CMakeLists.txt
index 6e3ef85cf5ef086450a9896003476d788bcfa69f..863fc5e6efcbad4b7661487d653113199cb4012b 100644
--- a/source/RobotAPI/libraries/aron/core/CMakeLists.txt
+++ b/source/RobotAPI/libraries/aron/core/CMakeLists.txt
@@ -21,7 +21,6 @@ set(LIB_FILES
     aron_conversions.cpp
     rw.cpp
 
-
     data/variant/Variant.cpp
     data/variant/detail/SpecializedVariant.cpp
     data/variant/detail/ContainerVariant.cpp
diff --git a/source/RobotAPI/libraries/aron/similarity/CMakeLists.txt b/source/RobotAPI/libraries/aron/similarity/CMakeLists.txt
index 92661f2d2ecd6994a9978e6c8d1b2aad2ffb7e9a..f85c7d514e045c8a0dbd5a31a8b918bb5afafcdb 100644
--- a/source/RobotAPI/libraries/aron/similarity/CMakeLists.txt
+++ b/source/RobotAPI/libraries/aron/similarity/CMakeLists.txt
@@ -1,2 +1,50 @@
+set(LIB_NAME aronsimilarity)
+
+armarx_component_set_name("${LIB_NAME}")
+armarx_set_target("Library: ${LIB_NAME}")
+
 #add_subdirectory(data/aron)
 #add_subdirectory(data/image)
+
+find_package(Simox QUIET)
+armarx_build_if(Simox_FOUND "Simox not available")
+
+set(LIBS
+    aron
+)
+
+set(LIB_FILES
+
+    data/image/NDArraySimilarity.cpp
+    data/image/mse.cpp
+    data/image/mae.cpp
+    data/image/chernoff.cpp
+    data/image/FloatSimilarity.cpp
+    cosine.cpp
+
+)
+
+set(LIB_HEADERS
+
+    data/image/NDArraySimilarity.h
+    data/image/mse.h
+    data/image/mae.h
+    data/image/chernoff.h
+    data/image/FloatSimilarity.h
+    cosine.h
+
+)
+
+
+armarx_add_library(
+    LIB_NAME
+        "${LIB_NAME}"
+    SOURCES
+        "${LIB_FILES}"
+    HEADERS
+        "${LIB_HEADERS}"
+    LIBS
+        "${LIBS}"
+)
+
+add_library(RobotAPI::aron::similarity ALIAS aronsimilarity)
diff --git a/source/RobotAPI/libraries/aron/similarity/cosine.cpp b/source/RobotAPI/libraries/aron/similarity/cosine.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..396ea66133cf66e6dc1f268c8f3c5bc89c47de05
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/similarity/cosine.cpp
@@ -0,0 +1,72 @@
+#include "cosine.h"
+
+#include <SimoxUtility/algorithm/string.h>
+#include <cmath>
+
+namespace armarx::aron::similarity
+{
+    double
+    cosine::compute_similarity(const aron::data::NDArrayPtr p1, const aron::data::NDArrayPtr p2)
+    {
+        //this does only work for RGB images not RGBDepth at the moment!
+        int width = p1->getShape().at(0);
+        int height = p1->getShape().at(1);
+        int dimensions = p1->getShape().at(2);
+        ARMARX_CHECK(dimensions == p2->getShape().at(2));
+        if(dimensions > 3){
+            ARMARX_INFO << "Trying to calculate cosine similarity for more than 3 channels, only first three channels will be looked at";
+        }
+        Eigen::MatrixXf m1r(width, height);
+        Eigen::MatrixXf m2r(width, height);
+        Eigen::MatrixXf m1g(width, height);
+        Eigen::MatrixXf m2g(width, height);
+        Eigen::MatrixXf m1b(width, height);
+        Eigen::MatrixXf m2b(width, height);
+
+        auto image1 = p1->getDataAsVector();
+        auto image2 = p2->getDataAsVector();
+
+
+        for(int x = 0; x < width; x++){
+            for(int y = 0; y < height; y++){
+                //R-value matices:
+                int index = x + width * (y + 0 * height);
+                double element1 = image1.at(index);
+                double element2 = image2.at(index);
+                m1r(x, y) = element1;
+                m2r(x, y) = element2;
+                //G-value matices:
+                index = x + width * (y + 1 * height);
+                element1 = image1.at(index);
+                element2 = image2.at(index);
+                m1g(x, y) = element1;
+                m2g(x, y) = element2;
+                //B-value matices:
+                index = x + width * (y + 2 * height);
+                element1 = image1.at(index);
+                element2 = image2.at(index);
+                m1b(x, y) = element1;
+                m2b(x, y) = element2;
+            }
+        }
+
+
+        double dotProductR = (m1r.array() * m2r.array()).sum();
+        double normProductR = m1r.norm() * m2r.norm();
+        double cosineR = 1.0 - (dotProductR / normProductR);
+        //ARMARX_INFO << VAROUT(cosineR);
+
+        double dotProductG = (m1g.array() * m2g.array()).sum();
+        double normProductG = m1g.norm() * m2g.norm();
+        double cosineG = 1.0 - (dotProductG / normProductG);
+        //ARMARX_INFO << VAROUT(cosineG);
+
+        double dotProductB = (m1b.array() * m2b.array()).sum();
+        double normProductB = m1b.norm() * m2b.norm();
+        double cosineB = 1.0 - (dotProductB / normProductB);
+        //ARMARX_INFO << VAROUT(cosineB);
+
+        return (cosineR + cosineG + cosineB)/ 3;
+    }
+
+}
diff --git a/source/RobotAPI/libraries/aron/similarity/cosine.h b/source/RobotAPI/libraries/aron/similarity/cosine.h
new file mode 100644
index 0000000000000000000000000000000000000000..8a5e776ff4b0c13a2fd9c36d1c0a9dfc19b8f51a
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/similarity/cosine.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#include <RobotAPI/libraries/aron/core/data/variant/All.h>
+
+namespace armarx::aron::similarity::cosine
+{
+    double compute_similarity(const aron::data::NDArrayPtr p1, const aron::data::NDArrayPtr p2);
+
+}
diff --git a/source/RobotAPI/libraries/aron/similarity/data/image/FloatSimilarity.cpp b/source/RobotAPI/libraries/aron/similarity/data/image/FloatSimilarity.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2724dc3402316b4bb0c261dd67de788dd6fd1b6d
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/similarity/data/image/FloatSimilarity.cpp
@@ -0,0 +1,33 @@
+#include "FloatSimilarity.h"
+#include <cmath>
+#include "ArmarXCore/core/logging/Logging.h"
+
+namespace armarx::aron::similarity{
+
+double FloatSimilarity::calculate_similarity(armarx::aron::data::FloatPtr f1, armarx::aron::data::FloatPtr f2, Type t)
+{
+    switch (t) {
+    case Type::MAE:
+        return calculateMAE(f1, f2);
+   case Type::MSE:
+        return calculateMSE(f1, f2);
+    default:
+        ARMARX_INFO << "Trying to calculate similarity with unknown similarity type";
+        return -1;
+    }
+}
+
+double FloatSimilarity::calculateMAE(armarx::aron::data::FloatPtr f1, armarx::aron::data::FloatPtr f2)
+{
+
+    return std::abs(f1->getValue() - f2->getValue());
+}
+
+double FloatSimilarity::calculateMSE(armarx::aron::data::FloatPtr f1, armarx::aron::data::FloatPtr f2)
+{
+    return std::pow(f1->getValue() - f2->getValue(), 2);
+}
+
+
+
+}
diff --git a/source/RobotAPI/libraries/aron/similarity/data/image/FloatSimilarity.h b/source/RobotAPI/libraries/aron/similarity/data/image/FloatSimilarity.h
new file mode 100644
index 0000000000000000000000000000000000000000..d325c6d61f2a5dc77ad53eb78a456da2dc07acf2
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/similarity/data/image/FloatSimilarity.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <vector>
+#include "RobotAPI/libraries/aron/core/data/variant/primitive/Float.h"
+
+namespace armarx::aron::similarity::FloatSimilarity{
+
+    enum Type {
+        MSE,
+        MAE,
+        NONE
+    };
+
+    double calculate_similarity(armarx::aron::data::FloatPtr f1, armarx::aron::data::FloatPtr f2, Type t);
+
+    double calculate_similarity_multi(std::vector<armarx::aron::data::FloatPtr>& images, armarx::aron::data::FloatPtr p, Type type);
+
+    double calculateMAE(armarx::aron::data::FloatPtr f1, armarx::aron::data::FloatPtr f2);
+
+    double calculateMSE(armarx::aron::data::FloatPtr f1, armarx::aron::data::FloatPtr f2);
+
+}
diff --git a/source/RobotAPI/libraries/aron/similarity/data/image/NDArraySimilarity.cpp b/source/RobotAPI/libraries/aron/similarity/data/image/NDArraySimilarity.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5fb38a7f8859e804e4ea8a71642402a08ce01e2b
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/similarity/data/image/NDArraySimilarity.cpp
@@ -0,0 +1,57 @@
+#include "NDArraySimilarity.h"
+
+#include <cmath>
+#include "mse.h"
+#include "mae.h"
+#include "chernoff.h"
+#include "../../cosine.h"
+
+namespace armarx::aron::similarity{
+
+
+    double NDArraySimilarity::calculate_similarity(data::NDArrayPtr p1, data::NDArrayPtr p2, Type type)
+    {
+        switch(type){
+            case Type::MSE:
+                //ARMARX_INFO << "Calculate MSE";
+                return armarx::aron::similarity::mse::compute_similarity(p1, p2);
+            case Type::MAE:
+                return armarx::aron::similarity::mae::compute_similarity(p1, p2);
+            case Type::CHERNOFF:
+                return armarx::aron::similarity::chernoff::compute_similarity(p1, p2);
+            case Type::COSINE:
+                return armarx::aron::similarity::cosine::compute_similarity(p1, p2);
+            default:
+                ARMARX_WARNING << "Trying to calculate similarity with unspecified similarity measurement";
+                return -1;
+        }
+    }
+
+    std::string NDArraySimilarity::to_string(Type t)
+    {
+        switch(t){
+            case MSE:
+                return "MSE";
+            case MAE:
+                return "MAE";
+            case CHERNOFF:
+                return "Chernoff";
+            case COSINE:
+                return "Cosine";
+            default:
+                return "No similarity type information";
+        }
+    }
+
+    double NDArraySimilarity::calculate_similarity_multi(std::vector<data::NDArrayPtr> images, armarx::aron::data::NDArrayPtr p, Type type)
+    {
+        double sim = 0;
+        for(auto& image: images){
+            //ARMARX_INFO << "Before calculation";
+            sim += calculate_similarity(image, p, type);
+            //ARMARX_INFO << "Sim is currently: " << sim;
+        }
+        return sim / (images.size() + 1); // to average it over the distances, makes it easier to find good parameters
+    }
+
+}
diff --git a/source/RobotAPI/libraries/aron/similarity/data/image/NDArraySimilarity.h b/source/RobotAPI/libraries/aron/similarity/data/image/NDArraySimilarity.h
new file mode 100644
index 0000000000000000000000000000000000000000..70413392f2cc8f2ee50a2c78d019607c3376feef
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/similarity/data/image/NDArraySimilarity.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <vector>
+#include "RobotAPI/libraries/aron/core/data/variant/complex/NDArray.h"
+
+namespace armarx::aron::similarity::NDArraySimilarity{
+
+    enum Type {
+        MSE,
+        MAE,
+        CHERNOFF,
+        COSINE,
+        NONE
+    };
+
+    std::string to_string(Type t);
+
+    double calculate_similarity(armarx::aron::data::NDArrayPtr p1, armarx::aron::data::NDArrayPtr p2, Type type);
+
+    /**
+     * @brief calculate_similarity_multi compares the image p with all images from the images vector, the dissimilarity values are simply summed up
+     * @param images vector of images that are compared to p
+     * @param p main image that you want to know the dissimilarity from
+     * @param type Type of dissimilarity measure used
+     * @return dissimilarity
+     */
+    double calculate_similarity_multi(std::vector<armarx::aron::data::NDArrayPtr> images, armarx::aron::data::NDArrayPtr p, Type type);
+
+}
diff --git a/source/RobotAPI/libraries/aron/similarity/data/image/chernoff.cpp b/source/RobotAPI/libraries/aron/similarity/data/image/chernoff.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0b4d26bc8dd4adb15a612fcc627eed41ed392cc1
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/similarity/data/image/chernoff.cpp
@@ -0,0 +1,180 @@
+#include "chernoff.h"
+
+#include <cmath>
+#include <Eigen/Core>
+#include <Eigen/Eigenvalues>
+
+namespace armarx::aron::similarity::chernoff
+{
+	
+    double compute_similarity(const aron::data::NDArrayPtr p1, const aron::data::NDArrayPtr p2){
+        //TODO: there seems to be an error that leads to the mean vectors always having the same
+        //value, which leads to the diff being zero which leads to distance being 0/inf/nan
+        //aron::data::NDArray image1 = *p1;
+        //aron::data::NDArray image2 = *p2;
+
+        //then normalize them to have values between 0 and 1
+        //TODO: do not rturn new array but change existing one
+        auto f = normalize_ndarray(p1, 255);
+        auto s = normalize_ndarray(p2, 255);
+        //ARMARX_INFO << VAROUT(f);
+        //ARMARX_INFO << VAROUT(s);
+        //then calculate the mean vectors
+        std::vector<double> mean_one = calculate_mean_values(f);
+        std::vector<double> mean_two = calculate_mean_values(s);
+        //ARMARX_INFO << VAROUT(mean_one);
+        //then calculate the covariance matrices
+        std::vector<std::vector<double>> cov_one = calculate_covariance_matrix(f, mean_one);
+        std::vector<std::vector<double>> cov_two = calculate_covariance_matrix(s, mean_two);
+        //then calculate the Bhattacharyya distance and return
+        double distance = calculate_bhattacharyya_distance(mean_one, mean_two, cov_one, cov_two);
+        ARMARX_INFO << "Chernoff distance: "  << std::to_string(distance);
+        return distance;
+    }
+
+    std::vector<double> calculate_mean_values(data::NDArray array)
+    {
+        std::vector<double> mean(3, 0.0);
+        int width = array.getShape().at(0);
+        int height = array.getShape().at(1);
+        int colors = array.getShape().at(2);
+        auto data = array.getDataAsVector();
+
+        for (int row = 0; row < height; row++){
+            for (int col = 0; col < width; col++){
+                double red = data.at(row * width * colors + col * colors);
+                double green = data.at(row * width * colors + col * colors + 1);
+                double blue = data.at(row * width * colors + col * colors + 2);
+                mean[0] += red;
+                mean[1] += green;
+                mean[2] += blue;
+            }
+        }
+        //ARMARX_INFO << VAROUT(mean);
+        int numPixels = width * height; //only per color
+        mean[0] /= numPixels;
+        mean[1] /= numPixels;
+        mean[2] /= numPixels;
+
+        return mean;
+    }
+
+    data::NDArray normalize_ndarray(data::NDArrayPtr array, int j)
+    {
+        std::vector<unsigned char> data = array->getDataAsVector();
+        std::vector<unsigned char> new_data(data.size());
+
+        for(int i = 0; i < data.size(); i++){
+            double a = data.at(i);
+            double n = a/j;
+            new_data.at(i) = n;
+        }
+
+        armarx::aron::data::NDArray n(array->getShape(), array->getType(),new_data, array->getPath());
+        return n;
+    }
+
+    std::vector<std::vector<double> > calculate_covariance_matrix(data::NDArray array, std::vector<double> mean = std::vector<double>())
+    {
+        int width = array.getShape().at(0);
+        int height = array.getShape().at(1);
+        int colors = array.getShape().at(2);
+        auto data = array.getDataAsVector();
+
+        std::vector<double> mean_vec(3, 0.0);
+        if(mean.empty()){
+            mean_vec = calculate_mean_values(array);
+        } else {
+            mean_vec = mean;
+        }
+
+        int numPixels = width * height; //only per color
+
+        std::vector<std::vector<double>> covariance(3, std::vector<double>(3, 0.0));
+
+        for(int row = 0; row < height; row++){
+            for(int col = 0; col < width; col++){
+                double red = data.at(row * width * colors + col * colors);
+                double green = data.at(row * width * colors + col * colors + 1);
+                double blue = data.at(row * width * colors + col * colors + 2);
+
+                double redDeviation = red - mean[0];
+                double greenDeviation = green - mean[1];
+                double blueDeviation = blue - mean[2];
+
+                covariance[0][0] += redDeviation * redDeviation;
+                covariance[0][1] += redDeviation * greenDeviation;
+                covariance[0][2] += redDeviation * blueDeviation;
+                covariance[1][1] += greenDeviation * greenDeviation;
+                covariance[1][2] += greenDeviation * blueDeviation;
+                covariance[2][2] += blueDeviation * blueDeviation;
+            }
+        }
+
+        for(int i = 0; i < 3; i++){
+            for (int j = 0; j < i; j++){
+                covariance[i][j] /= numPixels;
+                covariance[j][i] = covariance[i][j];
+            }
+            covariance[i][i] /= numPixels;
+        }
+
+        return covariance;
+    }
+
+    double calculate_bhattacharyya_distance(std::vector<double> mean_one, std::vector<double> mean_two, std::vector<std::vector<double> > covariance_one, std::vector<std::vector<double> > covariance_two)
+    {
+        //first make mean vectors and covariance matrices in Eigen:: objects
+        Eigen::VectorXd meanOne(3);
+        meanOne << mean_one[0], mean_one[1], mean_one[2];
+        Eigen::VectorXd meanTwo(3);
+        meanTwo << mean_two[0], mean_two[1], mean_two[2];
+
+        //ARMARX_INFO << VAROUT(meanOne);
+        //ARMARX_INFO << VAROUT(meanTwo);
+
+        //these are column-major instead or row-major, but we have a quadratic, symmetric matrix, so it does not matter
+        //this conversion does not work correctly!!
+        //Eigen::MatrixXd cov_one = Eigen::Map<Eigen::MatrixXd>(covariance_one[0].data(), covariance_one.size(), covariance_one[0].size());
+        //Eigen::MatrixXd cov_two = Eigen::Map<Eigen::MatrixXd>(covariance_two[0].data(), covariance_two.size(), covariance_two[0].size());
+
+        Eigen::Matrix3d cov_one;
+        cov_one << covariance_one[0][0], covariance_one[0][1], covariance_one[0][2],
+            covariance_one[1][0], covariance_one[1][1], covariance_one[1][2],
+            covariance_one[2][0], covariance_one[2][1], covariance_one[2][2];
+
+        Eigen::Matrix3d cov_two;
+        cov_two << covariance_two[0][0], covariance_two[0][1], covariance_two[0][2],
+            covariance_two[1][0], covariance_two[1][1], covariance_two[1][2],
+            covariance_two[2][0], covariance_two[2][1], covariance_two[2][2];
+
+
+        //ARMARX_INFO << VAROUT(cov_one);
+
+        Eigen::VectorXd meanDiff = meanOne - meanTwo;
+        //ARMARX_INFO << VAROUT(meanDiff);
+
+        Eigen::MatrixXd sigma = 0.5 * (cov_one + cov_two);
+        Eigen::MatrixXd sigma_inverse = sigma.inverse();
+
+        double det_cov_one = cov_one.determinant();
+        double det_cov_two = cov_two.determinant();
+        double det_sigma = sigma.determinant();
+
+        //formula from https://www.kaggle.com/code/debanga/statistical-distances
+        double bigger = meanDiff.transpose() * (sigma_inverse) * meanDiff;
+        //ARMARX_INFO << "Bigger: " << std::to_string(bigger);
+        double term_one = 0.125 * bigger;
+        double sqr = std::sqrt(det_cov_one * det_cov_two);
+        //ARMARX_INFO << "Sqr: " << std::to_string(sqr);
+        double before_log = det_sigma / (sqr);
+        //ARMARX_INFO << "Before log: " << std::to_string(before_log);
+        double term_two = 0.5 * std::log(before_log);
+
+        double distance = term_one + term_two;
+
+        return distance;
+    }
+
+	
+}
diff --git a/source/RobotAPI/libraries/aron/similarity/data/image/chernoff.h b/source/RobotAPI/libraries/aron/similarity/data/image/chernoff.h
new file mode 100644
index 0000000000000000000000000000000000000000..9c8dc173af489379e00435d9f1c98dda5e2e5f69
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/similarity/data/image/chernoff.h
@@ -0,0 +1,44 @@
+/*
+ * 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     Joana Plewnia ( uhfpm at student dot kit dot edu )
+ * @date       2023
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#include <RobotAPI/libraries/aron/core/data/variant/All.h>
+
+namespace armarx::aron::similarity::chernoff
+{
+    double compute_similarity(const aron::data::NDArrayPtr p1, const aron::data::NDArrayPtr p2);
+    
+    armarx::aron::data::NDArray normalize_ndarray(armarx::aron::data::NDArrayPtr array, int i);
+
+    std::vector<double> calculate_mean_values(armarx::aron::data::NDArray array);
+
+    std::vector<std::vector<double>> calculate_covariance_matrix(armarx::aron::data::NDArray array,
+                                                                 std::vector<double> mean);
+
+    double calculate_bhattacharyya_distance(std::vector<double> mean_one, std::vector<double> mean_two,
+                                            std::vector<std::vector<double>> covariance_one,
+                                            std::vector<std::vector<double>> covariance_two);
+}
diff --git a/source/RobotAPI/libraries/aron/similarity/data/image/mae.cpp b/source/RobotAPI/libraries/aron/similarity/data/image/mae.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3be0d5ef20e5a3325c90a69dbbca0083c7ebfb89
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/similarity/data/image/mae.cpp
@@ -0,0 +1,31 @@
+#include "mae.h"
+
+namespace armarx::aron::similarity::mae
+{
+
+    double compute_similarity(const data::NDArrayPtr p1, const data::NDArrayPtr p2)
+    {
+        double sum = 0;
+        int width = p1->getShape().at(0);
+        int height = p1->getShape().at(1);
+        int colors = p1->getShape().at(2);
+
+        auto first_image = p1->getDataAsVector();
+        auto second_image = p2->getDataAsVector();
+
+        ARMARX_CHECK(first_image.size() == second_image.size());
+
+        for (int w = 0; w < width; w++){
+            for (int h = 0; h < height; h++){
+                for (int c = 0; c < colors; c++){
+                    int k = h * width * colors + w * colors + c;
+                    sum += std::abs(first_image.at(k) - second_image.at(k));
+                }
+            }
+        }
+        return sum / (width * height * colors);
+    }
+
+
+}
+
diff --git a/source/RobotAPI/libraries/aron/similarity/data/image/mae.h b/source/RobotAPI/libraries/aron/similarity/data/image/mae.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb68569c32f4a1ceaef11727ea85f6e5ea12ae7e
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/similarity/data/image/mae.h
@@ -0,0 +1,33 @@
+/*
+ * 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     Joana Plewnia ( uhfpm at student dot kit dot edu )
+ * @date       2023
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#include <RobotAPI/libraries/aron/core/data/variant/All.h>
+
+namespace armarx::aron::similarity::mae
+{
+    double compute_similarity(const aron::data::NDArrayPtr p1, const aron::data::NDArrayPtr p2);
+}
diff --git a/source/RobotAPI/libraries/aron/similarity/data/image/mse.cpp b/source/RobotAPI/libraries/aron/similarity/data/image/mse.cpp
index 0f26147604663e1e752fa8d7a8498faae480d9b3..cb9dcf9d3f7ef6ca4ee31e514e3aa7c122605dee 100644
--- a/source/RobotAPI/libraries/aron/similarity/data/image/mse.cpp
+++ b/source/RobotAPI/libraries/aron/similarity/data/image/mse.cpp
@@ -1,12 +1,63 @@
 #include "mse.h"
 
 #include <SimoxUtility/algorithm/string.h>
+#include <cmath>
 
 namespace armarx::aron::similarity
 {
     double
-    mse::compute_similarity(const aron::data::NDArrayPtr& p1, const aron::data::NDArrayPtr& p2)
+    mse::compute_similarity(const aron::data::NDArrayPtr p1, const aron::data::NDArrayPtr p2)
     {
-        return 0;
+        //ARMARX_INFO << "Begin MSE";
+        //auto start = std::chrono::high_resolution_clock::now();
+    	double sum = 0;
+
+        //TODO: check shapes have same size
+        //ARMARX_INFO << "One";
+        if(p1 != nullptr && p2 != nullptr){
+            p1->getShortName();
+        } else {
+            if(p1 == nullptr){
+                ARMARX_INFO << "P1 is nullptr";
+            }else{
+                ARMARX_INFO << "P2 is Nullpointer";
+            }
+        }
+        //ARMARX_INFO << "Two";
+
+        //return 0;
+
+        std::vector<unsigned char> first_image = p1->getDataAsVector();
+        std::vector<unsigned char> second_image = p2->getDataAsVector();
+        int size = first_image.size();
+
+        //ARMARX_INFO << "Image size: " << std::to_string(int(first_image.size()));
+        //ARMARX_INFO << "Image size: " << std::to_string(int(second_image.size()));
+        ARMARX_CHECK(first_image.size() == second_image.size());
+
+        //auto start = std::chrono::high_resolution_clock::now();
+        int rolling_number = 1; //TODO: make sure that no elements will be left over
+
+        for(int i = 0; i < int(first_image.size()); i+= rolling_number){
+            //loop unrolling to shorten the needed computation time:
+            sum += std::pow(first_image.at(i) - second_image.at(i), 2);
+            /*
+            sum += std::pow(first_image.at(i + 1) - second_image.at(i + 1), 2);
+            sum += std::pow(first_image.at(i + 2) - second_image.at(i + 2), 2);
+            sum += std::pow(first_image.at(i + 3) - second_image.at(i + 3), 2);
+            */
+        }
+
+
+        //auto end = std::chrono::high_resolution_clock::now();
+        //auto additional = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
+        //ARMARX_INFO << "Time with unroll factor " << rolling_number << " MSE: " << std::to_string(additional.count());
+        first_image.clear();
+        second_image.clear();
+
+        //ARMARX_INFO << "MSE is: " << std::to_string(sum / size);
+
+        return sum / (size);
     }
+
 } // namespace armarx::aron::similarity
diff --git a/source/RobotAPI/libraries/aron/similarity/data/image/mse.h b/source/RobotAPI/libraries/aron/similarity/data/image/mse.h
index 461768d99d4624a5a5d92d82ed749845ceef94f1..892a12dd06969404eba03fe21540d53ee4d3df81 100644
--- a/source/RobotAPI/libraries/aron/similarity/data/image/mse.h
+++ b/source/RobotAPI/libraries/aron/similarity/data/image/mse.h
@@ -29,5 +29,6 @@
 
 namespace armarx::aron::similarity::mse
 {
-    double compute_similarity(const aron::data::NDArrayPtr& p1, const aron::data::NDArrayPtr& p2);
+    double compute_similarity(const aron::data::NDArrayPtr p1, const aron::data::NDArrayPtr p2);
+
 }