diff --git a/source/RobotAPI/components/ArMemGlobalStorage/ArMemGlobalStorage.cpp b/source/RobotAPI/components/ArMemGlobalStorage/ArMemGlobalStorage.cpp
deleted file mode 100644
index 802aea2a766fcbdb39ab77c8ffeb924f5c797c3a..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/ArMemGlobalStorage/ArMemGlobalStorage.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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/>.
- *
- * @package    RobotAPI::ArmarXObjects::ArMemGlobalStorage
- * @author     fabian.peller-konrad@kit.edu ( fabian dot peller-konrad at kit dot edu )
- * @date       2020
- * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
- *             GNU General Public License
- */
-
-#include "ArMemGlobalStorage.h"
-
-// STD/STL
-#include <algorithm>
-
-// Boost
-#include <boost/asio.hpp>
-
-// Simox
-#include <SimoxUtility/algorithm/string.h>
-
-// ArmarX
-#include <RobotAPI/interface/armem/legacy.h>
-
-namespace armarx
-{
-    namespace armem
-    {
-
-        armarx::PropertyDefinitionsPtr ArMemGlobalStorage::createPropertyDefinitions()
-        {
-            PropertyDefinitionsPtr defs{new ComponentPropertyDefinitions{getConfigIdentifier()}};
-
-            defs->optional(local_memory_names, "LocalMemoryNames", "The objectnames of the local memories, comma separated");
-            return defs;
-        }
-
-        ArMemGlobalStorage::ArMemGlobalStorage():
-            armarx::Component(),
-            armarx::armem::ArMemBase(),
-            armarx::armem::ArMemGlobalMemoryResolver()
-        {
-        }
-
-        std::string ArMemGlobalStorage::getDefaultName() const
-        {
-            return "ArMemGlobalStorage";
-        }
-
-
-        void ArMemGlobalStorage::onInitComponent()
-        {
-            for (const std::string& name : simox::alg::split(local_memory_names, ","))
-            {
-                usingProxy(GenerateLocalMemoryObjectNameFromHostname(name));
-            }
-        }
-
-
-        void ArMemGlobalStorage::onConnectComponent()
-        {
-            for (const std::string& hostname : simox::alg::split(local_memory_names, ","))
-            {
-                ArMemLocalMemoryInterfacePrx localMemoryPrx = getProxy<ArMemLocalMemoryInterfacePrx>(GenerateLocalMemoryObjectNameFromHostname(hostname));
-                local_memories[hostname] = localMemoryPrx;
-            }
-        }
-
-
-        void ArMemGlobalStorage::onDisconnectComponent()
-        {
-
-        }
-
-
-        void ArMemGlobalStorage::onExitComponent()
-        {
-
-        }
-
-        std::string ArMemGlobalStorage::getHostnameOfCurrentMachine(const Ice::Current&)
-        {
-            return getMyHostname();
-        }
-
-        ArMemLocalMemoryInterfacePrx ArMemGlobalStorage::getMemoryOfCurrentMachine(const Ice::Current& c)
-        {
-            return getMemoryForHostname(getMyHostname(), c);
-        }
-
-        ArMemLocalMemoryInterfacePrx ArMemGlobalStorage::getMemoryForHostname(const std::string& hostname, const Ice::Current&)
-        {
-            if (local_memories.find(hostname) == local_memories.end())
-            {
-                throw LocalException("The local memory of host '" + hostname + "' does not exist!. Could not return proxy!");
-            }
-            return local_memories[hostname];
-        }
-
-        void ArMemGlobalStorage::dynamicallyRegisterNewLocalMemory(const std::string& hostname, const Ice::Current&)
-        {
-            if (local_memories.find(hostname) == local_memories.end())
-            {
-                ArMemLocalMemoryInterfacePrx localMemoryPrx = getProxy<ArMemLocalMemoryInterfacePrx>(GenerateLocalMemoryObjectNameFromHostname(hostname));
-                local_memories[hostname] = localMemoryPrx;
-            }
-        }
-
-        void ArMemGlobalStorage::exportDataOfAllMemoriesToLocation(const std::string&, const Ice::Current&)
-        {
-            // TODO!! Needs Aron-JSON Export?
-        }
-    }
-}
diff --git a/source/RobotAPI/components/ArMemGlobalStorage/ArMemGlobalStorage.h b/source/RobotAPI/components/ArMemGlobalStorage/ArMemGlobalStorage.h
deleted file mode 100644
index 9c9b47801f70c58712d73c68e564ecbd05ba9876..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/ArMemGlobalStorage/ArMemGlobalStorage.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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/>.
- *
- * @package    RobotAPI::ArmarXObjects::ArMemGlobalStorage
- * @author     fabian.peller-konrad@kit.edu ( fabian dot peller-konrad at kit dot edu )
- * @date       2020
- * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
- *             GNU General Public License
- */
-
-#pragma once
-
-// STD/STL
-#include <map>
-
-// Aron
-#include <RobotAPI/interface/aron.h>
-#include <RobotAPI/interface/armem/legacy.h>
-
-// ArmarX
-#include <ArmarXCore/core/Component.h>
-#include <RobotAPI/libraries/armem/legacy/ArMemBase.h>
-
-namespace armarx
-{
-    namespace armem
-    {
-        class ArMemGlobalStorage :
-            virtual public armarx::Component,
-            virtual public armarx::armem::ArMemBase,
-            virtual public armarx::armem::ArMemGlobalMemoryResolver
-        {
-        public:
-            ArMemGlobalStorage();
-
-            std::string getDefaultName() const override;
-
-            std::string getHostnameOfCurrentMachine(const Ice::Current& = Ice::Current());
-            ArMemLocalMemoryInterfacePrx getMemoryOfCurrentMachine(const Ice::Current& = Ice::Current());
-            ArMemLocalMemoryInterfacePrx getMemoryForHostname(const std::string&, const Ice::Current& = Ice::Current());
-
-            void dynamicallyRegisterNewLocalMemory(const std::string&, const Ice::Current& = Ice::Current());
-
-            void exportDataOfAllMemoriesToLocation(const std::string&, const Ice::Current& = Ice::Current());
-
-        protected:
-            void onInitComponent() override;
-            void onConnectComponent() override;
-            void onDisconnectComponent() override;
-            void onExitComponent() override;
-            armarx::PropertyDefinitionsPtr createPropertyDefinitions() override;
-
-        private:
-            std::string local_memory_names;
-            std::map<std::string, ArMemLocalMemoryInterfacePrx> local_memories;
-        };
-    }
-}
diff --git a/source/RobotAPI/components/ArMemGlobalStorage/CMakeLists.txt b/source/RobotAPI/components/ArMemGlobalStorage/CMakeLists.txt
deleted file mode 100644
index df827fa04cd4f34d7c42c861581f12034698a157..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/ArMemGlobalStorage/CMakeLists.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-armarx_component_set_name("ArMemGlobalStorage")
-
-set(COMPONENT_LIBS
-    ArmarXCore
-    ArmarXCoreInterfaces
-    RobotAPICore
-    RobotAPIInterfaces
-    armem
-)
-
-set(SOURCES ArMemGlobalStorage.cpp)
-set(HEADERS ArMemGlobalStorage.h)
-
-armarx_add_component("${SOURCES}" "${HEADERS}")
-
-# add unit tests
-add_subdirectory(test)
-
-armarx_generate_and_add_component_executable(COMPONENT_NAMESPACE "armarx::armem" APPLICATION_APP_SUFFIX)
diff --git a/source/RobotAPI/components/ArMemGlobalStorage/test/ArMemGlobalStorageTest.cpp b/source/RobotAPI/components/ArMemGlobalStorage/test/ArMemGlobalStorageTest.cpp
deleted file mode 100644
index f5451b02e484b0fde7ce24805beb9b46cc5c2b60..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/ArMemGlobalStorage/test/ArMemGlobalStorageTest.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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/>.
- *
- * @package    RobotAPI::ArmarXObjects::ArMemGlobalStorage
- * @author     fabian.peller-konrad@kit.edu ( fabian dot peller-konrad at kit dot edu )
- * @date       2020
- * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
- *             GNU General Public License
- */
-
-#define BOOST_TEST_MODULE RobotAPI::ArmarXObjects::ArMemGlobalStorage
-
-#define ARMARX_BOOST_TEST
-
-#include <RobotAPI/Test.h>
-#include <RobotAPI/components/ArMemGlobalStorage/ArMemGlobalStorage.h>
-
-#include <iostream>
-
-BOOST_AUTO_TEST_CASE(testExample)
-{
-    armarx::armem::ArMemGlobalStorage instance;
-
-    BOOST_CHECK_EQUAL(true, true);
-}
diff --git a/source/RobotAPI/components/ArMemGlobalStorage/test/CMakeLists.txt b/source/RobotAPI/components/ArMemGlobalStorage/test/CMakeLists.txt
deleted file mode 100644
index c7cc9e00f7900fb219e4c2b5a089d832c027d1ef..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/ArMemGlobalStorage/test/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-
-# Libs required for the tests
-SET(LIBS ${LIBS} ArmarXCore ArMemGlobalStorage)
- 
-armarx_add_test(ArMemGlobalStorageTest ArMemGlobalStorageTest.cpp "${LIBS}")
diff --git a/source/RobotAPI/components/ArMemLocalStorage/ArMemLocalStorage.cpp b/source/RobotAPI/components/ArMemLocalStorage/ArMemLocalStorage.cpp
deleted file mode 100644
index 7474703e6289bf2dfbf7aa8c5234307c42e3486c..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/ArMemLocalStorage/ArMemLocalStorage.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * 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/>.
- *
- * @package    RobotAPI::ArmarXObjects::ArMemLocalStorage
- * @author     fabian.peller-konrad@kit.edu ( fabian dot peller-konrad at kit dot edu )
- * @date       2020
- * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
- *             GNU General Public License
- */
-
-// Header
-#include "ArMemLocalStorage.h"
-
-// Boost
-#include <boost/asio.hpp>
-
-namespace armarx
-{
-
-    namespace armem
-    {
-        armarx::PropertyDefinitionsPtr ArMemLocalStorage::createPropertyDefinitions()
-        {
-            PropertyDefinitionsPtr defs(new ComponentPropertyDefinitions(getConfigIdentifier()));
-            defs->optional(maximum_segments, "MaximumNumberOfSegments", "Maximum number of segments (<0 means infinite)");
-            defs->optional(maximum_entries_per_segment, "MaximumEntriesPerSegment", "Maximum number of accepted datatypes per segment  (<0 means infinite)");
-            return defs;
-        }
-
-        std::string ArMemLocalStorage::getDefaultName() const
-        {
-            return GenerateLocalMemoryObjectNameFromHostname(getMyHostname());
-        }
-
-        ArMemLocalStorage::ArMemLocalStorage() :
-            armarx::Component(),
-            armarx::armem::ArMemBase(),
-            num_segments(0),
-            num_entries_per_segment(),
-            maximum_segments(-1),
-            maximum_entries_per_segment(-1)
-        {
-
-        }
-
-        void ArMemLocalStorage::onInitComponent()
-        {
-
-        }
-
-        void ArMemLocalStorage::onConnectComponent()
-        {
-
-        }
-
-        void ArMemLocalStorage::onDisconnectComponent()
-        {
-
-        }
-
-        void ArMemLocalStorage::onExitComponent()
-        {
-
-        }
-
-        ArMemLocalStorage::HasSegmentReturnType ArMemLocalStorage::hasSegment(const std::string& segment) const
-        {
-            auto index_pos = indexed_storage.find(segment);
-            auto timestamped_pos = timestamped_storage.find(segment);
-            auto hashed_pos = hashed_storage.find(segment);
-
-            if (index_pos == indexed_storage.end() && timestamped_pos == timestamped_storage.end() && hashed_pos == hashed_storage.end())
-            {
-                return HasSegmentReturnType::No;
-            }
-
-            if (index_pos != indexed_storage.end() && timestamped_pos != timestamped_storage.end() && hashed_pos != hashed_storage.end())
-            {
-                return HasSegmentReturnType::Yes;
-            }
-
-            bool index_pos_end = (index_pos == indexed_storage.end());
-            bool timestamped_pos_end = (timestamped_pos == timestamped_storage.end());
-            bool hashed_pos_end = (hashed_pos == hashed_storage.end());
-            ARMARX_ERROR << "The memory is in an inconsistent state. A segment was found in some containers but not in all! Resetting segment!\n"
-                         << "The indexed storage " << (index_pos_end ? "does not contain " : "contains ") << " the segment, \n"
-                         << "The timestamped storage " << (timestamped_pos_end ? "does not contain " : "contains ") << " the segment, \n"
-                         << "The hashed storage " << (hashed_pos_end ? "does not contain " : "contains ") << " the segment, \n";
-            return HasSegmentReturnType::InvalidState;
-        }
-
-
-        std::string ArMemLocalStorage::commit(const std::string& segment, long sentAt, const std::vector<aron::data::AronDataPtr>& data, const Ice::Current&)
-        {
-            // Check if segment already exists
-            HasSegmentReturnType has_segment = hasSegment(segment);
-            if (has_segment != HasSegmentReturnType::Yes)
-            {
-                // Need to allocate a new storage for a new segment
-                ARMARX_WARNING << "A new segment '" + segment + "' registered to the memory. Allocating space for its members...";
-                indexed_storage[segment] = IndexedDatatypeStorage();
-                timestamped_storage[segment] = TimestampedDataTypeStorage();
-                hashed_storage[segment] = HashedDataTypeStorage();
-
-                if (has_segment != HasSegmentReturnType::InvalidState)
-                {
-                    // Otherwise we reassign the segment again.
-                    num_segments++;
-                }
-            }
-
-            IndexedDatatypeStorage& indexed_segment_storage = indexed_storage[segment];
-            TimestampedDataTypeStorage& timestamped_segment_storage = timestamped_storage[segment];
-            HashedDataTypeStorage& hashed_segment_storage = hashed_storage[segment];
-
-            long now = IceUtil::Time::now().toMilliSeconds();
-            if (sentAt > now)
-            {
-                ARMARX_WARNING << "Received an invalid timestamp. The timestamp when sending data to the segment '" + segment + "' is greater than the storage timestamp (The transmitted time needs to be in milliseconds [ms]). Please check!" ;
-            }
-
-            // Create new memory entry and save result
-            ArMemCommitPtr entryPtr = ArMemCommitPtr(new ArMemCommit());
-            entryPtr->producer = "TODO";
-            entryPtr->stored_in_segment = segment;
-            entryPtr->produce_timestamp_ms = sentAt;
-            entryPtr->stored_in_segment = IceUtil::Time::now().toMilliSeconds();
-            entryPtr->data = data;
-
-            ARMARX_INFO << "Saving a new commit to segment '" + segment + "'";
-            std::string string_to_hash = segment + "__" + std::to_string(now);
-            size_t hash = std::hash<std::string> {}(string_to_hash);
-
-            if (timestamped_segment_storage.find(now) != timestamped_segment_storage.end())
-            {
-                ARMARX_WARNING << "The segment '" + segment + "' already contains a value at timestamp " + std::to_string(now) + ". Overwriting value!";
-            }
-            if (hashed_segment_storage.find(hash) != hashed_segment_storage.end())
-            {
-                ARMARX_WARNING << "The segment '" + segment + "' already contains data at the commit hash " + std::to_string(hash) + ". Overwriting value!";
-            }
-
-            std::string hash_as_string = std::to_string(hash);
-            ARMARX_DEBUG << "Storing new data with hash: " << hash_as_string;
-            indexed_segment_storage.push_back(entryPtr);
-            timestamped_segment_storage[now] = entryPtr;
-            hashed_segment_storage[hash] = entryPtr;
-            ARMARX_DEBUG << "Stored new data with hash: " << hash_as_string;
-            ARMARX_DEBUG << "The current segment " << segment << " now contains " << indexed_segment_storage.size() << " elements!";
-            return std::to_string(hash);
-        }
-
-        std::string ArMemLocalStorage::commit_single(const std::string& segment, long generatedTS, const aron::data::AronDataPtr& x, const Ice::Current& c)
-        {
-            return commit(segment, generatedTS, {x}, c);
-        }
-
-        void ArMemLocalStorage::checkStorageIntegrity() const
-        {
-            if (indexed_storage.size() != timestamped_storage.size() ||
-                indexed_storage.size() != hashed_storage.size() ||
-                timestamped_storage.size() != hashed_storage.size())
-            {
-                throw LocalException("The memory is in an invalid state. The storages have different sizes! Please Check!");
-            }
-            for (const auto& [segment, datatypeStorage] : indexed_storage)
-            {
-                checkStorageIntegrityForSegment(segment);
-            }
-        }
-
-        void ArMemLocalStorage::checkStorageIntegrityForSegment(const std::string& segment) const
-        {
-            HasSegmentReturnType has_segment = hasSegment(segment);
-            if (has_segment != HasSegmentReturnType::Yes)
-            {
-                throw LocalException("The memory is in an invalid state. Not all storages contain the segment '" + segment + "'! Please Check!");
-            }
-        }
-
-
-        ArMemCommitPtr ArMemLocalStorage::getLatestCommitFromSegment(const std::string& segment, const Ice::Current&)
-        {
-            HasSegmentReturnType has_segment = hasSegment(segment);
-            if (has_segment != HasSegmentReturnType::Yes)
-            {
-                return nullptr;
-            }
-
-            int index = indexed_storage[segment].size() - 1;
-            if (index >= 0)
-            {
-                return indexed_storage[segment][index];
-            }
-            return nullptr;
-        }
-
-        ArMemCommitPtr ArMemLocalStorage::getNextCommitFromSegmentForTimestamp(const std::string&, Ice::Long, const Ice::Current&)
-        {
-            return nullptr;
-        }
-
-        TimestampedArMemCommitList ArMemLocalStorage::getAllCommitsBetweenTimestampsFromSegment(const std::string&, Ice::Long, Ice::Long, const Ice::Current&)
-        {
-            return {};
-        }
-
-        TimestampedArMemCommitList ArMemLocalStorage::getAllCommitsFromSegment(const std::string&, const Ice::Current&)
-        {
-            return {};
-        }
-    }
-}
diff --git a/source/RobotAPI/components/ArMemLocalStorage/ArMemLocalStorage.h b/source/RobotAPI/components/ArMemLocalStorage/ArMemLocalStorage.h
deleted file mode 100644
index ef5622cd60b7f86fdd5096c62fde3e52ee42805d..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/ArMemLocalStorage/ArMemLocalStorage.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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/>.
- *
- * @package    RobotAPI::ArmarXObjects::ArMemLocalStorage
- * @author     fabian.peller-konrad@kit.edu ( fabian dot peller-konrad at kit dot edu )
- * @date       2020
- * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
- *             GNU General Public License
- */
-
-#pragma once
-
-// STD/STL
-#include <map>
-
-// Aron
-#include <RobotAPI/interface/aron.h>
-#include <RobotAPI/interface/armem/legacy.h>
-
-// ArmarX
-#include <ArmarXCore/core/Component.h>
-#include <RobotAPI/libraries/armem/legacy/ArMemBase.h>
-
-namespace armarx
-{
-
-    namespace armem
-    {
-        class ArMemLocalStorage :
-            virtual public armarx::Component,
-            virtual public armarx::armem::ArMemBase,
-            virtual public armarx::armem::ArMemLocalMemoryInterface
-        {
-        public:
-            enum HasSegmentReturnType
-            {
-                Yes,
-                No,
-                InvalidState
-            };
-
-            typedef std::vector<ArMemCommitPtr> IndexedDatatypeStorage;
-            typedef std::map<long, ArMemCommitPtr> TimestampedDataTypeStorage;
-            typedef std::map<std::size_t, ArMemCommitPtr> HashedDataTypeStorage;
-
-            ArMemLocalStorage();
-
-            std::string getDefaultName() const override;
-
-            HasSegmentReturnType hasSegment(const std::string&) const;
-            long size(const std::string&) const;
-
-            ArMemCommitPtr getLatestCommitFromSegment(const std::string&, const Ice::Current& = Ice::Current());
-            ArMemCommitPtr getNextCommitFromSegmentForTimestamp(const std::string&, long, const Ice::Current& = Ice::Current());
-            TimestampedArMemCommitList getAllCommitsBetweenTimestampsFromSegment(const std::string&, Ice::Long, Ice::Long, const Ice::Current& = Ice::Current());
-            TimestampedArMemCommitList getAllCommitsFromSegment(const std::string&, const Ice::Current& = Ice::Current());
-
-            std::string commit(const std::string& segment, long generatedTS, const std::vector<aron::data::AronDataPtr>&, const Ice::Current& = Ice::Current());
-            std::string commit_single(const std::string& segment, long generatedTS, const aron::data::AronDataPtr&, const Ice::Current& = Ice::Current());
-
-        protected:
-            void onInitComponent() override;
-            void onConnectComponent() override;
-            void onDisconnectComponent() override;
-            void onExitComponent() override;
-
-            armarx::PropertyDefinitionsPtr createPropertyDefinitions() override;
-
-        private:
-
-            void checkStorageIntegrity() const;
-            void checkStorageIntegrityForSegment(const std::string&) const;
-
-        private:
-            std::map<std::string, IndexedDatatypeStorage> indexed_storage;
-            std::map<std::string, TimestampedDataTypeStorage> timestamped_storage;
-            std::map<std::string, HashedDataTypeStorage> hashed_storage;
-
-            long num_segments;
-            std::map<std::string, long> num_entries_per_segment;
-
-            long maximum_segments;
-            long maximum_entries_per_segment;
-        };
-    }
-}
diff --git a/source/RobotAPI/components/ArMemLocalStorage/CMakeLists.txt b/source/RobotAPI/components/ArMemLocalStorage/CMakeLists.txt
deleted file mode 100644
index 38cac48d2c54abd4d58c5a64ea5fe6b178a1b79a..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/ArMemLocalStorage/CMakeLists.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-armarx_component_set_name("ArMemLocalStorage")
-
-
-set(COMPONENT_LIBS
-    ArmarXCore
-    ArmarXCoreInterfaces
-    RobotAPICore
-    RobotAPIInterfaces
-    armem
-)
-
-set(SOURCES
-    ./ArMemLocalStorage.cpp
-)
-set(HEADERS
-    ./ArMemLocalStorage.h
-)
-
-
-armarx_add_component("${SOURCES}" "${HEADERS}")
-
-#find_package(MyLib QUIET)
-#armarx_build_if(MyLib_FOUND "MyLib not available")
-# all target_include_directories must be guarded by if(Xyz_FOUND)
-# for multiple libraries write: if(X_FOUND AND Y_FOUND)....
-#if(MyLib_FOUND)
-#    target_include_directories(ArMemLocalStorage PUBLIC ${MyLib_INCLUDE_DIRS})
-#endif()
-
-# add unit tests
-add_subdirectory(test)
-
-#generate the application
-armarx_generate_and_add_component_executable(COMPONENT_NAMESPACE "armarx::armem" APPLICATION_APP_SUFFIX)
diff --git a/source/RobotAPI/components/ArMemLocalStorage/test/ArMemLocalStorageTest.cpp b/source/RobotAPI/components/ArMemLocalStorage/test/ArMemLocalStorageTest.cpp
deleted file mode 100644
index 48a74567fdd35708d0d6e30ee8b25f67f4381be3..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/ArMemLocalStorage/test/ArMemLocalStorageTest.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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/>.
- *
- * @package    RobotAPI::ArmarXObjects::ArMemLocalStorage
- * @author     fabian.peller-konrad@kit.edu ( fabian dot peller-konrad at kit dot edu )
- * @date       2020
- * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
- *             GNU General Public License
- */
-
-#define BOOST_TEST_MODULE RobotAPI::ArmarXObjects::ArMemLocalStorage
-
-#define ARMARX_BOOST_TEST
-
-#include <RobotAPI/Test.h>
-#include <RobotAPI/components/ArMemLocalStorage/ArMemLocalStorage.h>
-
-#include <iostream>
-
-BOOST_AUTO_TEST_CASE(testExample)
-{
-    armarx::armem::ArMemLocalStorage instance;
-
-    BOOST_CHECK_EQUAL(true, true);
-}
diff --git a/source/RobotAPI/components/ArMemLocalStorage/test/CMakeLists.txt b/source/RobotAPI/components/ArMemLocalStorage/test/CMakeLists.txt
deleted file mode 100644
index f72cfa041acff0351e753c642b077c34b3e807b8..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/ArMemLocalStorage/test/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-
-# Libs required for the tests
-SET(LIBS ${LIBS} ArmarXCore ArMemLocalStorage)
- 
-armarx_add_test(ArMemLocalStorageTest ArMemLocalStorageTest.cpp "${LIBS}")
diff --git a/source/RobotAPI/components/armem/ArMemExampleClient/ArMemExampleClient.cpp b/source/RobotAPI/components/armem/ArMemExampleClient/ArMemExampleClient.cpp
index 92429966c7a66dbf2411c38ce8cea7ce0328ee16..b0fdb1f3a5622f37bbd0fcd4cfdaa79513e4cc5b 100644
--- a/source/RobotAPI/components/armem/ArMemExampleClient/ArMemExampleClient.cpp
+++ b/source/RobotAPI/components/armem/ArMemExampleClient/ArMemExampleClient.cpp
@@ -27,8 +27,9 @@
 
 #include <RobotAPI/interface/aron.h>
 
-#include <RobotAPI/libraries/armem/core/ice_conversions.h>
+#include <RobotAPI/libraries/armem/component/MemoryRemoteGui.h>
 #include <RobotAPI/libraries/armem/client/MemoryWriter.h>
+#include <RobotAPI/libraries/armem/memory/ice_conversions.h>
 
 
 namespace armarx
@@ -64,6 +65,9 @@ namespace armarx
 
     void ArMemExampleClient::onConnectComponent()
     {
+        createRemoteGuiTab();
+        RemoteGui_startRunningTask();
+
         {
             ARMARX_IMPORTANT << "Waiting for memory '" << memoryName << "'.";
             armem::Time start = armem::Time::now();
@@ -194,6 +198,68 @@ namespace armarx
                         << "\n- error message: \t" << result.errorMessage
                         ;
         }
+
+
+        if (true)
+        {
+            ARMARX_IMPORTANT
+                    << "Querying latest snapshot:"
+                    << "\n- entityID:     \t'" << snapshotID << "'"
+                    // << "\n" << *memoryQuery
+                    ;
+
+            armem::query::EntityQueryPtr entityQuery =
+                // new armem::query::entity::Single();
+                new armem::query::entity::All();
+            armem::query::ProviderSegmentQueryPtr providerQuery =
+                new armem::query::provider::Single({entityQuery}, snapshotID.entityName);
+            // new armem::query::provider::All({entityQuery});
+            armem::query::CoreSegmentQueryPtr coreQuery =
+                    new armem::query::core::Single({providerQuery}, snapshotID.providerSegmentName);
+            armem::query::MemoryQueryPtr memoryQuery =
+                    new armem::query::memory::Single({coreQuery}, snapshotID.coreSegmentName);
+
+
+
+            armem::data::MemoryPtr iceResult = memory->query({memoryQuery});
+            armem::MemoryPtr result = armem::fromIce<armem::MemoryPtr>(iceResult);
+
+            ARMARX_CHECK_EQUAL(result->coreSegments.size(), 1);
+
+            armem::CoreSegmentPtr& coreSeg = result->coreSegments.begin()->second;
+            ARMARX_CHECK_EQUAL(coreSeg->providerSegments.size(), 1);
+
+            armem::ProviderSegmentPtr& provSeg = coreSeg->providerSegments.begin()->second;
+            ARMARX_CHECK_EQUAL(provSeg->entities.size(), 1);
+
+            armem::EntityPtr& entity = provSeg->entities.begin()->second;
+            ARMARX_CHECK_GREATER_EQUAL(entity->history.size(), 1);
+
+            armem::EntitySnapshotPtr& snapshot = entity->history.begin()->second;
+
+            ARMARX_INFO << "Result: "
+                        << "\n- memory:       \t" << result->name
+                        << "\n- core segment: \t" << coreSeg->name
+                        << "\n- prov segment: \t" << provSeg->name
+                        << "\n- entity:       \t" << entity->name
+                        << "\n- snapshot:     \t" << snapshot->time
+                        << "\n- #instances:   \t" << snapshot->instances.size()
+                        ;
+
+
+            ARMARX_IMPORTANT << "Getting entity from snapshot ID";
+            const armem::Entity& e = result->getEntity(snapshotID);
+            ARMARX_INFO << "Result: "
+                        << "\n- entity:       \t" << e.name
+                        << "\n- snapshot:     \t" << e.getLatestSnapshot().time
+                        << "\n- #instances:   \t" << e.getLatestSnapshot().instances.size()
+                        ;
+
+
+            tab.queryResult = std::move(result);
+            tab.rebuild = true;
+        }
+
     }
 
 
@@ -207,9 +273,26 @@ namespace armarx
     }
 
 
-    void ArMemExampleClient::RemoteGui_update()
+    void ArMemExampleClient::createRemoteGuiTab()
     {
+        using namespace armarx::RemoteGui::Client;
 
+        if (tab.queryResult)
+        {
+            armem::MemoryRemoteGui mrg;
+            tab.queryResultGroup = mrg.makeGroupBox(*tab.queryResult);
+        }
+
+        VBoxLayout root = {tab.queryResultGroup, VSpacer()};
+        RemoteGui_createTab(getName(), root, &tab);
+    }
+
+    void ArMemExampleClient::RemoteGui_update()
+    {
+        if (tab.rebuild.exchange(false))
+        {
+            createRemoteGuiTab();
+        }
     }
 
 }
diff --git a/source/RobotAPI/components/armem/ArMemExampleClient/ArMemExampleClient.h b/source/RobotAPI/components/armem/ArMemExampleClient/ArMemExampleClient.h
index 9fd9033b2d1e2a97a6ca3ef8db6a13034cf06997..c1f6b4b010acb94c0373fafdb0a8e3d8262e0171 100644
--- a/source/RobotAPI/components/armem/ArMemExampleClient/ArMemExampleClient.h
+++ b/source/RobotAPI/components/armem/ArMemExampleClient/ArMemExampleClient.h
@@ -35,6 +35,7 @@
 #include <RobotAPI/interface/armem/MemoryNameSystemInterface.h>
 
 #include <RobotAPI/libraries/armem/client/MemoryClientComponentPlugin.h>
+#include <RobotAPI/libraries/armem/memory/Memory.h>
 
 
 namespace armarx
@@ -76,6 +77,7 @@ namespace armarx
 
         // LightweightRemoteGuiComponentPluginUser interface
     public:
+        void createRemoteGuiTab();
         void RemoteGui_update() override;
 
 
@@ -104,5 +106,15 @@ namespace armarx
         std::string memoryName = "Example";
         armem::MemoryInterfacePrx memory;
 
+
+        struct RemoteGuiTab : RemoteGui::Client::Tab
+        {
+            std::atomic_bool rebuild = false;
+
+            armem::MemoryPtr queryResult;
+            RemoteGui::Client::GroupBox queryResultGroup;
+        };
+        RemoteGuiTab tab;
+
     };
 }
diff --git a/source/RobotAPI/interface/CMakeLists.txt b/source/RobotAPI/interface/CMakeLists.txt
index 3e693d83079b81a535b6b7abdafa47ee7a3e82ad..ac8108e7589ebfbd6179e61ac64ed5ce3bdb1e1f 100644
--- a/source/RobotAPI/interface/CMakeLists.txt
+++ b/source/RobotAPI/interface/CMakeLists.txt
@@ -106,8 +106,9 @@ set(SLICE_FILES
     armem/WritingInterface.ice
     armem/MemoryInterface.ice
     armem/MemoryNameSystemInterface.ice
-    armem/GlobalMemoryResolver.ice
-    armem/legacy.ice
+
+    armem/query.ice
+    armem/memory.ice
 
     components/ObstacleAvoidance/ObstacleAvoidanceInterface.ice
     components/ObstacleAvoidance/ObstacleDetectionInterface.ice
diff --git a/source/RobotAPI/interface/armem.ice b/source/RobotAPI/interface/armem.ice
index b52a5794c64124c0c76583b7587132046ef0db62..6fa4705257ad47e82ec53d8804f9e5d5cadce39c 100644
--- a/source/RobotAPI/interface/armem.ice
+++ b/source/RobotAPI/interface/armem.ice
@@ -3,8 +3,6 @@
 #include <RobotAPI/interface/armem/ReadingInterface.ice>
 #include <RobotAPI/interface/armem/WritingInterface.ice>
 #include <RobotAPI/interface/armem/MemoryInterface.ice>
-#include <RobotAPI/interface/armem/GlobalMemoryResolver.ice>
-#include <RobotAPI/interface/armem/legacy.ice>
 
 
 module armarx
diff --git a/source/RobotAPI/interface/armem/GlobalMemoryResolver.ice b/source/RobotAPI/interface/armem/GlobalMemoryResolver.ice
deleted file mode 100644
index 2007f49b2e2ddee2ded87a49d6e79c1b205e13f7..0000000000000000000000000000000000000000
--- a/source/RobotAPI/interface/armem/GlobalMemoryResolver.ice
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-#include <RobotAPI/interface/armem/MemoryInterface.ice>
-
-
-module armarx
-{
-    module armem
-    {
-
-        interface GlobalMemoryResolver
-        {
-            string getHostnameOfCurrentMachine();
-            MemoryInterface* getMemoryOfCurrentMachine();
-            MemoryInterface* getMemoryForHostname(string hostname);
-
-            void dynamicallyRegisterNewLocalMemory(string hostname);
-
-            void exportDataOfAllMemoriesToLocation(string location);
-        }
-
-    };
-};
diff --git a/source/RobotAPI/interface/armem/ReadingInterface.ice b/source/RobotAPI/interface/armem/ReadingInterface.ice
index a803ae44bda9ddb716bcb6c487020f7c44f6b840..a85c5d90c0adfb786f7c53d0ec356c7fe250fab3 100644
--- a/source/RobotAPI/interface/armem/ReadingInterface.ice
+++ b/source/RobotAPI/interface/armem/ReadingInterface.ice
@@ -2,13 +2,14 @@
 
 #include <RobotAPI/interface/aron.ice>
 
+#include <RobotAPI/interface/armem/query.ice>
+#include <RobotAPI/interface/armem/memory.ice>
+
 
 module armarx
 {
     module armem
     {
-        // WIP
-
         module data
         {
             struct EntitySnapshotQuery
@@ -35,6 +36,8 @@ module armarx
         interface ReadingInterface
         {
             data::EntitySnapshotQueryResultList getEntitySnapshots(data::EntitySnapshotQueryList queries);
+
+            data::Memory query(query::MemoryQuerySeq queries);
         };
 
     };
diff --git a/source/RobotAPI/interface/armem/legacy.ice b/source/RobotAPI/interface/armem/legacy.ice
deleted file mode 100644
index d40c24027b70f045bf69685793f52ca29536042e..0000000000000000000000000000000000000000
--- a/source/RobotAPI/interface/armem/legacy.ice
+++ /dev/null
@@ -1,57 +0,0 @@
-#pragma once
-
-#include <RobotAPI/interface/aron.ice>
-
-
-module armarx
-{
-    module armem
-    {
-        // data in a commit
-        class ArMemCommit
-        {
-            string producer;
-            string stored_in_segment;
-            long produce_timestamp_ms;
-            long storage_timestamp_ms;
-            int priority;
-            aron::data::AronDataList data; // Dict?!?
-        };
-
-        // map storageTS to commit
-        dictionary<long, ArMemCommit> TimestampedArMemCommitList;
-
-
-        interface ArMemReceiverInterface
-        {
-            ArMemCommit getLatestCommitFromSegment(string segment);
-            ArMemCommit getNextCommitFromSegmentForTimestamp(string segment, long timestamp);
-            TimestampedArMemCommitList getAllCommitsBetweenTimestampsFromSegment(string segment, long timestamp1, long timestamp2);
-            TimestampedArMemCommitList getAllCommitsFromSegment(string segment);
-        };
-
-        interface ArMemProducerInterface
-        {
-            string commit(string segment, long produceTimestamp, aron::data::AronDataList values);
-            string commit_single(string segment, long produceTimestamp, aron::data::AronData value);
-        };
-
-        interface ArMemLocalMemoryInterface
-                extends ArMemReceiverInterface, ArMemProducerInterface
-        {
-
-        };
-
-        interface ArMemGlobalMemoryResolver
-        {
-            string getHostnameOfCurrentMachine();
-            ArMemLocalMemoryInterface* getMemoryOfCurrentMachine();
-            ArMemLocalMemoryInterface* getMemoryForHostname(string hostname);
-
-            void dynamicallyRegisterNewLocalMemory(string hostname);
-
-            void exportDataOfAllMemoriesToLocation(string location);
-        }
-
-    };
-};
diff --git a/source/RobotAPI/interface/armem/memory.ice b/source/RobotAPI/interface/armem/memory.ice
new file mode 100644
index 0000000000000000000000000000000000000000..68d25c0e32bd4dd8d4eabc366bc961bf18079338
--- /dev/null
+++ b/source/RobotAPI/interface/armem/memory.ice
@@ -0,0 +1,83 @@
+#pragma once
+
+#include <RobotAPI/interface/aron.ice>
+
+
+module armarx
+{
+    module armem
+    {
+        // WIP
+
+        module data
+        {
+            /// Ice Twin of `armarx::armem::EntityMetadata`.
+            class EntityMetadata
+            {
+                long timeCreatedMicroSeconds;
+                long timeSentMicroSeconds;
+                long timeArrivedMicroSeconds;
+
+                float confidence = 1.0;
+            };
+            /// Ice Twin of `armarx::armem::EntityData`.
+            class EntityData
+            {
+                int index;
+                aron::data::AronData data;
+
+                EntityMetadata metadata;
+            };
+            sequence<EntityData> EntityDataSeq;
+
+
+            /// Ice Twin of `armarx::armem::EntitySnapshot`.
+            class EntitySnapshot
+            {
+                long timeMicroSeconds;
+                EntityDataSeq instances;
+            };
+            dictionary<long, EntitySnapshot> EntityHistory;
+
+
+            /// Ice Twin of `armarx::armem::Entity`.
+            class Entity
+            {
+                string name;
+                EntityHistory history;
+            };
+            dictionary<string, Entity> EntityDict;
+
+
+            /// Ice Twin of `armarx::armem::ProviderSegment`.
+            class ProviderSegment
+            {
+                string name;
+                EntityDict entities;
+            };
+            dictionary<string, ProviderSegment> ProviderSegmentDict;
+
+
+            /// Ice Twin of `armarx::armem::CoreSegment`.
+            class CoreSegment
+            {
+                string name;
+                // aron::type::AronType type;
+                ProviderSegmentDict providerSegments;
+            };
+            dictionary<string, CoreSegment> CoreSegmentDict;
+
+
+            /// Ice Twin of `armarx::armem::Memory`.
+            class Memory
+            {
+                string name;
+                // aron::type::AronType type;
+                CoreSegmentDict coreSegments;
+            };
+            dictionary<string, Memory> MemoryDict;
+
+        }
+
+    };
+};
diff --git a/source/RobotAPI/interface/armem/query.ice b/source/RobotAPI/interface/armem/query.ice
new file mode 100644
index 0000000000000000000000000000000000000000..87cd1b1e5787f00d9fedebb9aa23601276ff48af
--- /dev/null
+++ b/source/RobotAPI/interface/armem/query.ice
@@ -0,0 +1,110 @@
+#pragma once
+
+#include <RobotAPI/interface/aron.ice>
+
+
+module armarx
+{
+    module armem
+    {
+        module query
+        {
+
+            /// Which entity snapshots to get from an entity?
+            class EntityQuery
+            {
+            };
+            sequence<EntityQuery> EntityQuerySeq;
+
+            module entity
+            {
+                class All extends EntityQuery
+                {
+                };
+                class Single extends EntityQuery
+                {
+                    long timestamp = -1;  // -1 for latest
+                };
+                class Range extends EntityQuery
+                {
+                    long minTimestamp = -1;  // -1 for oldest
+                    long maxTimestamp = -1;  // -1 for latest
+                };
+            }
+
+
+            /// Which entities to get from a provider segment?
+            class ProviderSegmentQuery
+            {
+                EntityQuerySeq entityQueries;
+            };
+            sequence<ProviderSegmentQuery> ProviderSegmentQuerySeq;
+            module provider
+            {
+                class All extends ProviderSegmentQuery
+                {
+                };
+                class Single extends ProviderSegmentQuery
+                {
+                    string entityName;
+                };
+                class Regex extends ProviderSegmentQuery
+                {
+                    string entityNameRegex;
+                };
+            }
+
+
+            /// Which provider segments to get from a core segment?
+            class CoreSegmentQuery
+            {
+                ProviderSegmentQuerySeq providerSegmentQueries;
+            };
+            sequence<CoreSegmentQuery> CoreSegmentQuerySeq;
+
+            module core
+            {
+                class All extends CoreSegmentQuery
+                {
+                };
+                class Single extends CoreSegmentQuery
+                {
+                    string providerSegmentName;
+                };
+                class Regex extends CoreSegmentQuery
+                {
+                    string providerSegmentNameRegex;
+                };
+            }
+
+
+            /// Which core segments to get from a memory?
+            class MemoryQuery
+            {
+                CoreSegmentQuerySeq coreSegmentQueries;
+            };
+            sequence<MemoryQuery> MemoryQuerySeq;
+
+            module memory
+            {
+                class All extends MemoryQuery
+                {
+                };
+                class Single extends MemoryQuery
+                {
+                    string coreSegmentName;
+                };
+                class Regex extends MemoryQuery
+                {
+                    string coreSegmentNameRegex;
+                };
+            }
+        }
+
+        interface someReadingInterface
+        {
+            // data::EntitySnapshotQueryResultList getEntitySnapshots(data::EntitySnapshotQueryList queries);
+        };
+
+    };
+};
diff --git a/source/RobotAPI/libraries/armem/CMakeLists.txt b/source/RobotAPI/libraries/armem/CMakeLists.txt
index 080a8124129ca9996024e5595d2c478ed53bd257..8d3ab648046b4322c0dd12753d9465296ddbacc9 100644
--- a/source/RobotAPI/libraries/armem/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem/CMakeLists.txt
@@ -40,6 +40,12 @@ set(LIB_FILES
     component/MemoryComponentPlugin.cpp
     component/MemoryRemoteGui.cpp
 
+    query/BaseQueryProcessor.cpp
+    query/EntityQueryProcessor.cpp
+    query/ProviderSegmentQueryProcessor.cpp
+    query/CoreSegmentQueryProcessor.cpp
+    query/MemoryQueryProcessor.cpp
+
     legacy/ArMemBase.cpp
 )
 set(LIB_HEADERS
@@ -73,6 +79,13 @@ set(LIB_HEADERS
     component/MemoryComponentPlugin.h
     component/MemoryRemoteGui.h
 
+    query.h
+    query/BaseQueryProcessor.h
+    query/EntityQueryProcessor.h
+    query/ProviderSegmentQueryProcessor.h
+    query/CoreSegmentQueryProcessor.h
+    query/MemoryQueryProcessor.h
+
     legacy/ArMemBase.h
 )
 
diff --git a/source/RobotAPI/libraries/armem/component/IceMemory.cpp b/source/RobotAPI/libraries/armem/component/IceMemory.cpp
index c446b8e95746f8956aa8ae60cdb4a16b1adc31e8..936818e1656e87e4f65715e90af7ccd65ad6de79 100644
--- a/source/RobotAPI/libraries/armem/component/IceMemory.cpp
+++ b/source/RobotAPI/libraries/armem/component/IceMemory.cpp
@@ -4,6 +4,7 @@
 
 #include "../error.h"
 #include "../memory/ice_conversions.h"
+#include "../query/MemoryQueryProcessor.h"
 
 
 namespace armarx::armem
@@ -14,6 +15,8 @@ namespace armarx::armem
     }
 
 
+    // WRITING
+
     armem::data::AddSegmentResult IceMemory::addSegment(const armem::data::AddSegmentInput& input, bool addCoreSegments)
     {
         ARMARX_DEBUG << "Adding segment '" << input.coreSegmentName << "/" << input.providerSegmentName << "'.";
@@ -122,4 +125,15 @@ namespace armarx::armem
         return commitResult;
     }
 
+
+    // READING
+
+    armem::data::MemoryPtr IceMemory::query(const armem::query::MemoryQuerySeq& queries)
+    {
+        ARMARX_CHECK_NOT_NULL(memory);
+
+        armem::MemoryQueryProcessor processor;
+        return processor.processToIce(queries, *memory);
+    }
+
 }
diff --git a/source/RobotAPI/libraries/armem/component/IceMemory.h b/source/RobotAPI/libraries/armem/component/IceMemory.h
index 1be749224a800fc4e9f3e5ac1fd474ec95f3fcd0..641b679a666d1b96b42e8c8f0b6e8317128c4ea3 100644
--- a/source/RobotAPI/libraries/armem/component/IceMemory.h
+++ b/source/RobotAPI/libraries/armem/component/IceMemory.h
@@ -23,6 +23,8 @@ namespace armarx::armem
         IceMemory(Memory* memory = nullptr);
 
 
+        // WRITING
+
         armem::data::AddSegmentResult addSegment(
             const armem::data::AddSegmentInput& input, bool addCoreSegments = false);
 
@@ -34,6 +36,11 @@ namespace armarx::armem
         armem::CommitResult commit(const armem::InternalCommit& commit);
 
 
+        // READING
+
+        armem::data::MemoryPtr query(const armem::query::MemoryQuerySeq& queries);
+
+
     public:
 
         Memory* memory;
diff --git a/source/RobotAPI/libraries/armem/component/MemoryComponentPlugin.cpp b/source/RobotAPI/libraries/armem/component/MemoryComponentPlugin.cpp
index fad77819edd1d3702b0d2b2bfb31a034cd29f0f5..151e908967016117635b555506a2365174713116 100644
--- a/source/RobotAPI/libraries/armem/component/MemoryComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/armem/component/MemoryComponentPlugin.cpp
@@ -150,5 +150,10 @@ namespace armarx::armem
         return results;
     }
 
+    armem::data::MemoryPtr MemoryComponentPluginUser::query(const armem::query::MemoryQuerySeq& queries, const Ice::Current&)
+    {
+        std::scoped_lock lock(memoryMutex);
+        return iceMemory.query(queries);
+    }
 
 }
diff --git a/source/RobotAPI/libraries/armem/component/MemoryComponentPlugin.h b/source/RobotAPI/libraries/armem/component/MemoryComponentPlugin.h
index 39a26a3bfb0b0ec0e04d4883961555cba0106f17..a1e0bd423dff46d6ae9914917d85013bd7a01c7e 100644
--- a/source/RobotAPI/libraries/armem/component/MemoryComponentPlugin.h
+++ b/source/RobotAPI/libraries/armem/component/MemoryComponentPlugin.h
@@ -75,6 +75,7 @@ namespace armarx::armem
 
         // ReadingInterface interface
         virtual armem::data::EntitySnapshotQueryResultList getEntitySnapshots(const armem::data::EntitySnapshotQueryList&, const Ice::Current& = Ice::emptyCurrent) override;
+        virtual armem::data::MemoryPtr query(const armem::query::MemoryQuerySeq& queries, const Ice::Current& = Ice::emptyCurrent) override;
 
 
     public:
diff --git a/source/RobotAPI/libraries/armem/core/ice_conversions.cpp b/source/RobotAPI/libraries/armem/core/ice_conversions.cpp
index cc046eed9aaed88f84215b316e0ebcaf380a6286..03d26fb5d7bead2123f2d02577140c773fc045f5 100644
--- a/source/RobotAPI/libraries/armem/core/ice_conversions.cpp
+++ b/source/RobotAPI/libraries/armem/core/ice_conversions.cpp
@@ -4,6 +4,19 @@
 namespace armarx
 {
 
+/*
+    void armem::fromIce(long ice, Time& time)
+    {
+        time = Time::microSeconds(ice);
+    }
+
+    void armem::toIce(long& ice, const Time& time)
+    {
+        ice = time.toMicroSeconds();
+    }
+*/
+
+
     void armem::fromIce(const data::Commit& ice, Commit& commit)
     {
         commit.updates.clear();
@@ -86,3 +99,5 @@ namespace armarx
 }
 
 
+
+
diff --git a/source/RobotAPI/libraries/armem/core/ice_conversions.h b/source/RobotAPI/libraries/armem/core/ice_conversions.h
index e29b0edcf1f616577dc4d497518979cc4d4362f2..9b7550f683c1f1ead59f6ee40717eb744545e6d3 100644
--- a/source/RobotAPI/libraries/armem/core/ice_conversions.h
+++ b/source/RobotAPI/libraries/armem/core/ice_conversions.h
@@ -1,14 +1,33 @@
 #pragma once
 
+#include <memory>
 
 #include <RobotAPI/interface/armem/MemoryInterface.h>
 
 #include "Commit.h"
 
 
+namespace IceUtil
+{
+    // Define in original namespace to allow ADL.
+    inline void fromIce(long ice, Time& time)
+    {
+        time = Time::microSeconds(ice);
+    }
+    inline void toIce(long& ice, const Time& time)
+    {
+        ice = time.toMicroSeconds();
+    }
+}
+
+
 namespace armarx::armem
 {
 
+    // void fromIce(long ice, Time& time);
+    // void toIce(long& ice, const Time& time);
+
+
     void fromIce(const data::Commit& ice, Commit& commit);
     void toIce(data::Commit& ice, const Commit& commit);
 
@@ -22,4 +41,128 @@ namespace armarx::armem
     void fromIce(const data::EntityUpdateResult& ice, EntityUpdateResult& result);
     void toIce(data::EntityUpdateResult& ice, const EntityUpdateResult& result);
 
+
+    template <class T>
+    void toIce(T& ice, const T& cpp)
+    {
+        ice = cpp;
+    }
+    template <class T>
+    void fromIce(const T& ice, T& cpp)
+    {
+        cpp = ice;
+    }
+
+    template <class IceT, class CppT>
+    IceT toIce(const CppT& cpp)
+    {
+        IceT ice;
+        toIce(ice, cpp);
+        return ice;
+    }
+    template <class CppT, class IceT>
+    CppT fromIce(const IceT& ice)
+    {
+        CppT cpp;
+        fromIce(ice, cpp);
+        return cpp;
+    }
+
+    template <class IceT, class CppT>
+    void toIce(IceT& ice, const std::unique_ptr<CppT>& cppPointer)
+    {
+        toIce(ice, *cppPointer);
+    }
+    template <class IceT, class CppT>
+    void fromIce(const IceT& ice, std::unique_ptr<CppT>& cppPointer)
+    {
+        cppPointer = std::make_unique<CppT>();
+        fromIce(ice, *cppPointer);
+    }
+
+    template <class IceT, class CppT>
+    void toIce(::IceInternal::Handle<IceT>& ice, const CppT& cpp)
+    {
+        ice = new IceT();
+        toIce(*ice, cpp);
+    }
+    template <class IceT, class CppT>
+    void fromIce(const ::IceInternal::Handle<IceT>& ice, CppT& cpp)
+    {
+        fromIce(*ice, cpp);
+    }
+
+    template <class IceT, class CppT>
+    void toIce(::IceInternal::Handle<IceT>& ice, const std::unique_ptr<CppT>& cppPointer)
+    {
+        ice = new IceT();
+        toIce(*ice, *cppPointer);
+    }
+    template <class IceT, class CppT>
+    void fromIce(const ::IceInternal::Handle<IceT>& ice, std::unique_ptr<CppT>& cppPointer)
+    {
+        cppPointer = std::make_unique<CppT>();
+        fromIce(*ice, *cppPointer);
+    }
+
+    template <class IceT, class CppT>
+    void toIce(std::vector<IceT>& ices, const std::vector<CppT>& cpps)
+    {
+        ices.clear();
+        ices.reserve(cpps.size());
+        for (const auto& cpp : cpps)
+        {
+            toIce(ices.emplace_back(), cpp);
+        }
+    }
+    template <class IceT, class CppT>
+    void fromIce(const std::vector<IceT>& ices, std::vector<CppT>& cpps)
+    {
+        cpps.clear();
+        cpps.reserve(ices.size());
+        for (const auto& ice : ices)
+        {
+            fromIce(ice, cpps.emplace_back());
+        }
+    }
+
+    template <class IceT, class CppT>
+    std::vector<IceT> toIce(const std::vector<CppT>& cpps)
+    {
+        std::vector<IceT> ices;
+        toIce(ices, cpps);
+        return ices;
+    }
+
+
+    template <class IceKeyT, class IceValueT, class CppKeyT, class CppValueT>
+    void toIce(std::map<IceKeyT, IceValueT>& iceMap,
+               const std::map<CppKeyT, CppValueT>& cppMap)
+    {
+        iceMap.clear();
+        for (const auto& [key, value] : cppMap)
+        {
+            iceMap.emplace(toIce<IceKeyT>(key), toIce<IceValueT>(value));
+        }
+    }
+    template <class IceKeyT, class IceValueT, class CppKeyT, class CppValueT>
+    void fromIce(const std::map<IceKeyT, IceValueT>& iceMap,
+                 std::map<CppKeyT, CppValueT>& cppMap)
+    {
+        cppMap.clear();
+        for (const auto& [key, value] : iceMap)
+        {
+            cppMap.emplace(fromIce<CppKeyT>(key), fromIce<CppValueT>(value));
+        }
+    }
+
+    template <class IceKeyT, class IceValueT, class CppKeyT, class CppValueT>
+    std::map<IceKeyT, IceValueT> toIce(const std::map<CppKeyT, CppValueT>& cppMap)
+    {
+        std::map<IceKeyT, IceValueT> iceMap;
+        toIce(iceMap, cppMap);
+        return iceMap;
+    }
+
+
 }
diff --git a/source/RobotAPI/libraries/armem/error/ArMemError.cpp b/source/RobotAPI/libraries/armem/error/ArMemError.cpp
index 3ba1c5d840964bf8c6fe30016f47f6e139e8d47f..249d7588c285307114385a49046dd9aba5e97617 100644
--- a/source/RobotAPI/libraries/armem/error/ArMemError.cpp
+++ b/source/RobotAPI/libraries/armem/error/ArMemError.cpp
@@ -117,4 +117,18 @@ namespace armarx::armem::error
         return ss.str();
     }
 
+
+
+    UnknownQueryType::UnknownQueryType(const std::string& term, const std::string& typeName) :
+        ArMemError(makeMsg(term, typeName))
+    {
+    }
+
+    std::string UnknownQueryType::makeMsg(const std::string& term, const std::string& typeName)
+    {
+        std::stringstream ss;
+        ss << "Unknown " << term << " query type '" << typeName << "'.";
+        return ss.str();
+    }
+
 }
diff --git a/source/RobotAPI/libraries/armem/error/ArMemError.h b/source/RobotAPI/libraries/armem/error/ArMemError.h
index b529ffc4bfd6b1222e335f7cd1842954bd036210..5dd1a9118fb11a1b66405d15fd41b544955c2bdb 100644
--- a/source/RobotAPI/libraries/armem/error/ArMemError.h
+++ b/source/RobotAPI/libraries/armem/error/ArMemError.h
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <stdexcept>
+#include <SimoxUtility/meta/type_name.h>
 
 #include "../core/MemoryID.h"
 
@@ -107,5 +108,24 @@ namespace armarx::armem::error
     };
 
 
+    /**
+     * @brief Indicates that an entity's history was queried, but is empty.
+     */
+    class UnknownQueryType : public ArMemError
+    {
+    public:
+
+        template <class QueryType>
+        UnknownQueryType(const std::string& term, const QueryType& query) :
+            UnknownQueryType(term, simox::meta::get_type_name(query))
+        {
+        }
+        UnknownQueryType(const std::string& term, const std::string& typeName);
+
+        static std::string makeMsg(const std::string& term, const std::string& typeName);
+
+    };
+
+
 }
 
diff --git a/source/RobotAPI/libraries/armem/memory/CoreSegment.cpp b/source/RobotAPI/libraries/armem/memory/CoreSegment.cpp
index c2b4814416960e55accdf151a6e127ab358391e0..bf3c6e2894721818c8124d6acbcd1a4752bd10d0 100644
--- a/source/RobotAPI/libraries/armem/memory/CoreSegment.cpp
+++ b/source/RobotAPI/libraries/armem/memory/CoreSegment.cpp
@@ -8,6 +8,34 @@
 namespace armarx::armem
 {
 
+    CoreSegment::CoreSegment(const CoreSegment& other) : EntityStorage (other)
+    {
+        *this = other;
+    }
+
+    CoreSegment& CoreSegment::operator=(const CoreSegment& other)
+    {
+        this->name = other.name;
+
+        this->providerSegments.clear();
+        for (const auto& [name, entity] : other.providerSegments)
+        {
+            this->providerSegments.emplace(name, std::make_unique<ProviderSegment>(*entity));
+        }
+
+        return *this;
+    }
+
+    CoreSegment::~CoreSegment()
+    {
+    }
+
+    CoreSegmentPtr CoreSegment::getEmptyCopy() const
+    {
+        CoreSegmentPtr other = std::make_unique<CoreSegment>();
+        other->name = this->name;
+        return other;
+    }
 
     bool CoreSegment::hasProviderSegment(const std::string& name) const
     {
@@ -15,6 +43,11 @@ namespace armarx::armem
     }
 
     ProviderSegment& CoreSegment::getProviderSegment(const std::string& name)
+    {
+        return const_cast<ProviderSegment&>(const_cast<const CoreSegment*>(this)->getProviderSegment(name));
+    }
+
+    const ProviderSegment& CoreSegment::getProviderSegment(const std::string& name) const
     {
         auto it = this->providerSegments.find(name);
         if (it != providerSegments.end())
@@ -28,7 +61,7 @@ namespace armarx::armem
         }
     }
 
-    Entity& CoreSegment::getEntity(const MemoryID& id)
+    const Entity& CoreSegment::getEntity(const MemoryID& id) const
     {
         checkStorageName(id.coreSegmentName, this->name, "core segment");
         return getProviderSegment(id.providerSegmentName).getEntity(id);
@@ -46,6 +79,17 @@ namespace armarx::armem
         return *it->second;
     }
 
+    ProviderSegment& CoreSegment::addProviderSegment(const ProviderSegment& providerSegment)
+    {
+        return addProviderSegment(std::make_unique<ProviderSegment>(providerSegment));
+    }
+
+    ProviderSegment& CoreSegment::addProviderSegment(ProviderSegmentPtr&& providerSegment)
+    {
+        auto it = providerSegments.emplace(providerSegment->name, std::move(providerSegment)).first;
+        return *it->second;
+    }
+
 
     MemoryID CoreSegment::update(const InternalEntityUpdate& update)
     {
diff --git a/source/RobotAPI/libraries/armem/memory/CoreSegment.h b/source/RobotAPI/libraries/armem/memory/CoreSegment.h
index fecf5168bdfdc64616d01eec1ad4751116b27ada..5436b03eb665744d24d6f99bc3537c435c63d5d1 100644
--- a/source/RobotAPI/libraries/armem/memory/CoreSegment.h
+++ b/source/RobotAPI/libraries/armem/memory/CoreSegment.h
@@ -11,6 +11,9 @@
 namespace armarx::armem
 {
 
+    class CoreSegment;
+    using CoreSegmentPtr = std::unique_ptr<CoreSegment>;
+
     /**
      * @brief Data of a core segment containing multiple provider segments.
      */
@@ -20,27 +23,39 @@ namespace armarx::armem
 
         using EntityStorage::EntityStorage;
 
+        CoreSegment(const CoreSegment& other);
+        CoreSegment& operator=(const CoreSegment& other);
+
+        ~CoreSegment() override;
+
+
+        CoreSegmentPtr getEmptyCopy() const;
+
 
         bool hasProviderSegment(const std::string& name) const;
-        ProviderSegment& getProviderSegment(const std::string& name);
 
-        Entity& getEntity(const MemoryID& id) override;
+        ProviderSegment& getProviderSegment(const std::string& name);
+        const ProviderSegment& getProviderSegment(const std::string& name) const;
 
+        const Entity& getEntity(const MemoryID& id) const override;
 
-        ProviderSegment& addProviderSegment(const std::string& name);
 
         virtual MemoryID update(const InternalEntityUpdate& update) override;
         using EntityStorage::update;
 
+        ProviderSegment& addProviderSegment(const std::string& name);
+        ProviderSegment& addProviderSegment(const ProviderSegment& providerSegment);
+        ProviderSegment& addProviderSegment(ProviderSegmentPtr&& providerSegment);
+
+
         void clear() override;
 
 
     public:
 
+        aron::type::AronTypePtr type;
         std::map<std::string, ProviderSegmentPtr> providerSegments;
 
     };
 
-    using CoreSegmentPtr = std::unique_ptr<CoreSegment>;
-
 }
diff --git a/source/RobotAPI/libraries/armem/memory/Entity.cpp b/source/RobotAPI/libraries/armem/memory/Entity.cpp
index 502c29fb5868690c7630b7649aad794acb61222f..e961eee5166795c3e641ac045743e74e6b9d43d5 100644
--- a/source/RobotAPI/libraries/armem/memory/Entity.cpp
+++ b/source/RobotAPI/libraries/armem/memory/Entity.cpp
@@ -16,12 +16,44 @@ namespace armarx::armem
     {
     }
 
+    Entity::Entity(const Entity& other)
+    {
+        *this = other;
+    }
+
+    Entity& Entity::operator=(const Entity& other)
+    {
+        this->name = other.name;
+        this->maxHistorySize = other.maxHistorySize;
+
+        this->history.clear();
+        for (const auto& [time, snapshot] : other.history)
+        {
+            this->addSnapshot(*snapshot);
+        }
+
+        return *this;
+    }
+
+    EntityPtr Entity::getEmptyCopy() const
+    {
+        EntityPtr other = std::make_unique<Entity>();
+        other->name = this->name;
+        other->maxHistorySize = this->maxHistorySize;
+        return other;
+    }
+
     bool Entity::hasSnapshot(Time time) const
     {
         return history.count(time) > 0;
     }
 
     EntitySnapshot& Entity::getSnapshot(Time time)
+    {
+        return const_cast<EntitySnapshot&>(const_cast<const Entity*>(this)->getSnapshot(time));
+    }
+
+    const EntitySnapshot&Entity::getSnapshot(Time time) const
     {
         auto it = history.find(time);
         if (it != history.end())
@@ -37,12 +69,22 @@ namespace armarx::armem
     }
 
     EntitySnapshot& Entity::getSnapshot(const MemoryID& id)
+    {
+        return const_cast<EntitySnapshot&>(const_cast<const Entity*>(this)->getSnapshot(id));
+    }
+
+    const EntitySnapshot&Entity::getSnapshot(const MemoryID& id) const
     {
         checkEntityName(id.entityName);
         return getSnapshot(id.timestamp);
     }
 
     EntitySnapshot& Entity::getLatestSnapshot()
+    {
+        return const_cast<EntitySnapshot&>(const_cast<const Entity*>(this)->getLatestSnapshot());
+    }
+
+    const EntitySnapshot& Entity::getLatestSnapshot() const
     {
         if (history.empty())
         {
@@ -53,6 +95,18 @@ namespace armarx::armem
     }
 
 
+    EntitySnapshot& Entity::addSnapshot(const EntitySnapshot& snapshot)
+    {
+        return addSnapshot(std::make_unique<EntitySnapshot>(snapshot));
+    }
+
+    EntitySnapshot&Entity::addSnapshot(EntitySnapshotPtr&& snapshot)
+    {
+        auto it = history.emplace(snapshot->time, std::move(snapshot)).first;
+        return *it->second;
+    }
+
+
     MemoryID Entity::update(const InternalEntityUpdate& update)
     {
         checkEntityName(update.entityID.entityName);
diff --git a/source/RobotAPI/libraries/armem/memory/Entity.h b/source/RobotAPI/libraries/armem/memory/Entity.h
index 53a1d21830376dfe1e2fb59411a3f90423916c8b..7c2e590a1c1d2717d80c1b53f17c4cb303d4f710 100644
--- a/source/RobotAPI/libraries/armem/memory/Entity.h
+++ b/source/RobotAPI/libraries/armem/memory/Entity.h
@@ -12,6 +12,9 @@
 namespace armarx::armem
 {
 
+    class Entity;
+    using EntityPtr = std::unique_ptr<Entity>;
+
     /**
      * @brief Data of an entity over a period of time.
      */
@@ -22,15 +25,30 @@ namespace armarx::armem
         Entity();
         Entity(const std::string& name);
 
+        /// Copy the history from `other` to this.
+        Entity(const Entity& other);
+        /// Copy the history from `other` to this.
+        Entity& operator=(const Entity& other);
+
+
+        /// Get an empty copy of `*this`.
+        EntityPtr getEmptyCopy() const;
+
+
         bool hasSnapshot(Time time) const;
+
         EntitySnapshot& getSnapshot(Time time);
+        const EntitySnapshot& getSnapshot(Time time) const;
+
         EntitySnapshot& getSnapshot(const MemoryID& id);
+        const EntitySnapshot& getSnapshot(const MemoryID& id) const;
 
         /**
          * @brief Return the snapshot with the most recent timestamp.
          * @return The latest snapshot.
          */
         EntitySnapshot& getLatestSnapshot();
+        const EntitySnapshot& getLatestSnapshot() const;
 
 
         /**
@@ -40,6 +58,10 @@ namespace armarx::armem
          */
         MemoryID update(const InternalEntityUpdate& update);
 
+        /// Add a single snapshot.
+        EntitySnapshot& addSnapshot(const EntitySnapshot& snapshot);
+        EntitySnapshot& addSnapshot(EntitySnapshotPtr&& snapshot);
+
         /**
          * @brief Sets the maximum history size.
          *
@@ -71,6 +93,4 @@ namespace armarx::armem
 
     };
 
-    using EntityPtr = std::unique_ptr<Entity>;
-
 }
diff --git a/source/RobotAPI/libraries/armem/memory/EntityData.cpp b/source/RobotAPI/libraries/armem/memory/EntityData.cpp
index 957157f3523c1511c0ceafab370cdb46a514c097..670b8b3ae8afaf0a0bdf36d1ff2e2b85fe49503d 100644
--- a/source/RobotAPI/libraries/armem/memory/EntityData.cpp
+++ b/source/RobotAPI/libraries/armem/memory/EntityData.cpp
@@ -12,6 +12,15 @@ namespace armarx::armem
 
         this->index = index;
         this->data = update.instancesData.at(size_t(index));
+        try
+        {
+            this->dataNavigator = aron::datanavigator::AronDataNavigator::FromAronData(this->data);
+        }
+        catch (const armarx::LocalException&)
+        {
+            this->dataNavigator = nullptr;
+        }
+
 
         this->metadata.confidence = update.confidence;
 
diff --git a/source/RobotAPI/libraries/armem/memory/EntityData.h b/source/RobotAPI/libraries/armem/memory/EntityData.h
index 113ab78077b270541640c6e577f542d34ba94127..0d8abf52098e715bc8a383d40bc8e6e84340cad7 100644
--- a/source/RobotAPI/libraries/armem/memory/EntityData.h
+++ b/source/RobotAPI/libraries/armem/memory/EntityData.h
@@ -3,6 +3,7 @@
 #include <memory>
 
 #include <RobotAPI/interface/aron.h>
+#include <RobotAPI/libraries/aron/aroncore/navigators/datanavigator/AronDataNavigator.h>
 
 #include "../core/Time.h"
 
@@ -36,7 +37,11 @@ namespace armarx::armem
     {
         int index;
 
+        /// The actual data.
         aron::data::AronDataPtr data;
+        /// Allows investigating `data`'s structure.
+        aron::datanavigator::AronDataNavigatorPtr dataNavigator;
+
         EntityMetadata metadata;
 
         /**
diff --git a/source/RobotAPI/libraries/armem/memory/EntitySnapshot.cpp b/source/RobotAPI/libraries/armem/memory/EntitySnapshot.cpp
index b55c477c5480966908a929c5c99388e1fc671c17..077b208b9794df9987e3466b0b4ed0d7eec243b4 100644
--- a/source/RobotAPI/libraries/armem/memory/EntitySnapshot.cpp
+++ b/source/RobotAPI/libraries/armem/memory/EntitySnapshot.cpp
@@ -9,6 +9,24 @@ namespace armarx::armem
 {
 
 
+    EntitySnapshot::EntitySnapshot(const EntitySnapshot& other)
+    {
+        *this = other;
+    }
+
+    EntitySnapshot& EntitySnapshot::operator=(const EntitySnapshot& other)
+    {
+        this->time = other.time;
+        this->instances.clear();
+        this->instances.reserve(other.instances.size());
+        for (const auto& data : other.instances)
+        {
+            this->instances.emplace_back(std::make_unique<EntityData>(*data));
+        }
+
+        return *this;
+    }
+
     void EntitySnapshot::update(const InternalEntityUpdate& update)
     {
         time = update.timeCreated;
diff --git a/source/RobotAPI/libraries/armem/memory/EntitySnapshot.h b/source/RobotAPI/libraries/armem/memory/EntitySnapshot.h
index 78c5f9e61e4709d827afe6d1a7a484512ca90b81..b6ae2d0ca0bc0d7ce99b1ad86eed3fe9957b67a3 100644
--- a/source/RobotAPI/libraries/armem/memory/EntitySnapshot.h
+++ b/source/RobotAPI/libraries/armem/memory/EntitySnapshot.h
@@ -21,6 +21,11 @@ namespace armarx::armem
 
         EntitySnapshot() = default;
 
+        /// Copy the instances from `other` to this.
+        EntitySnapshot(const EntitySnapshot& other);
+        /// Copy the instances from `other` to this.
+        EntitySnapshot& operator=(const EntitySnapshot& other);
+
 
         void update(const InternalEntityUpdate& update);
 
diff --git a/source/RobotAPI/libraries/armem/memory/EntityStorage.cpp b/source/RobotAPI/libraries/armem/memory/EntityStorage.cpp
index ccae15c3ff29f6554953fcc717140fbcee337b95..742d4f027f4cfeb89ab004a88597c74d8a38ef02 100644
--- a/source/RobotAPI/libraries/armem/memory/EntityStorage.cpp
+++ b/source/RobotAPI/libraries/armem/memory/EntityStorage.cpp
@@ -26,9 +26,19 @@ namespace armarx::armem
         return ids;
     }
 
+    Entity& EntityStorage::getEntity(const MemoryID& id)
+    {
+        return const_cast<Entity&>(const_cast<const EntityStorage*>(this)->getEntity(id));
+    }
+
     EntitySnapshot& EntityStorage::getEntitySnapshot(const MemoryID& id)
     {
-        Entity& entity = getEntity(id);
+        return const_cast<EntitySnapshot&>(const_cast<const EntityStorage*>(this)->getEntitySnapshot(id));
+    }
+
+    const EntitySnapshot&EntityStorage::getEntitySnapshot(const MemoryID& id) const
+    {
+        const Entity& entity = getEntity(id);
 
         if (id.hasTimestamp())
         {
diff --git a/source/RobotAPI/libraries/armem/memory/EntityStorage.h b/source/RobotAPI/libraries/armem/memory/EntityStorage.h
index 43ad2f6b589e54ef04989a5028bc4e7cbd1113fa..75ba385a3012fa50e1911b3cfb8298b628a35f42 100644
--- a/source/RobotAPI/libraries/armem/memory/EntityStorage.h
+++ b/source/RobotAPI/libraries/armem/memory/EntityStorage.h
@@ -47,7 +47,8 @@ namespace armarx::armem
          * @return The entity.
          * @throw An exception deriving from `armem::error::ArMemError` if the entity is missing.
          */
-        virtual Entity& getEntity(const MemoryID& id) = 0;
+        virtual Entity& getEntity(const MemoryID& id);
+        virtual const Entity& getEntity(const MemoryID& id) const = 0;
 
         /**
          * @brief Retrieve an entity snapshot.
@@ -59,6 +60,8 @@ namespace armarx::armem
          * @throw An exception deriving from `armem::error::ArMemError` if the snapshot is missing.
          */
         virtual EntitySnapshot& getEntitySnapshot(const MemoryID& id);
+        virtual const EntitySnapshot& getEntitySnapshot(const MemoryID& id) const;
+
 
 
     protected:
diff --git a/source/RobotAPI/libraries/armem/memory/Memory.cpp b/source/RobotAPI/libraries/armem/memory/Memory.cpp
index c96f6fe48a2c50c8ed8ffc17b96a6eca29ebb653..c42de46863a196c083bf2f1fb7113ce8684fa37a 100644
--- a/source/RobotAPI/libraries/armem/memory/Memory.cpp
+++ b/source/RobotAPI/libraries/armem/memory/Memory.cpp
@@ -9,12 +9,45 @@
 namespace armarx::armem
 {
 
+    Memory::Memory(const Memory& other) : EntityStorage (other)
+    {
+        *this = other;
+    }
+
+    Memory& Memory::operator=(const Memory& other)
+    {
+        this->name = other.name;
+
+        this->coreSegments.clear();
+        for (const auto& [name, coreSegment] : other.coreSegments)
+        {
+            this->coreSegments.emplace(name, std::make_unique<CoreSegment>(*coreSegment));
+        }
+
+        return *this;
+    }
+
+    Memory::~Memory()
+    {
+    }
+
+    MemoryPtr Memory::getEmptyCopy() const
+    {
+        MemoryPtr other = std::make_unique<Memory>();
+        other->name = this->name;
+        return other;
+    }
+
     bool Memory::hasCoreSegment(const std::__cxx11::string& name) const
     {
         return coreSegments.count(name) > 0;
     }
 
     CoreSegment& Memory::getCoreSegment(const std::string& name)
+    {
+        return const_cast<CoreSegment&>(const_cast<const Memory*>(this)->getCoreSegment(name));
+    }
+    const CoreSegment& Memory::getCoreSegment(const std::string& name) const
     {
         auto it = this->coreSegments.find(name);
         if (it != coreSegments.end())
@@ -29,7 +62,7 @@ namespace armarx::armem
     }
 
 
-    Entity& Memory::getEntity(const MemoryID& id)
+    const Entity& Memory::getEntity(const MemoryID& id) const
     {
         checkStorageName(id.memoryName, this->name, "memory");
         return getCoreSegment(id.coreSegmentName).getEntity(id);
@@ -47,6 +80,17 @@ namespace armarx::armem
         return *it->second;
     }
 
+    CoreSegment& Memory::addCoreSegment(const CoreSegment& coreSegment)
+    {
+        return addCoreSegment(std::make_unique<CoreSegment>(coreSegment));
+    }
+
+    CoreSegment& Memory::addCoreSegment(CoreSegmentPtr&& coreSegment)
+    {
+        auto it = coreSegments.emplace(coreSegment->name, std::move(coreSegment)).first;
+        return *it->second;
+    }
+
     std::vector<CoreSegment*> Memory::addCoreSegments(const std::vector<std::string>& names)
     {
         std::vector<CoreSegment*> segments;
diff --git a/source/RobotAPI/libraries/armem/memory/Memory.h b/source/RobotAPI/libraries/armem/memory/Memory.h
index 242f2743a931883d13e1f85df9aeefd2fec87e00..e83555c83fcbf3254acc15d0bdf7258c2e103d29 100644
--- a/source/RobotAPI/libraries/armem/memory/Memory.h
+++ b/source/RobotAPI/libraries/armem/memory/Memory.h
@@ -11,6 +11,10 @@
 namespace armarx::armem
 {
 
+    class Memory;
+    using MemoryPtr = std::unique_ptr<Memory>;
+
+
     /**
      * @brief Data of a memory consisting of multiple core segments.
      */
@@ -20,14 +24,28 @@ namespace armarx::armem
 
         using EntityStorage::EntityStorage;
 
+        Memory(const Memory& other);
+        Memory& operator=(const Memory& other);
+
+        ~Memory() override;
+
+
+        MemoryPtr getEmptyCopy() const;
+
 
         bool hasCoreSegment(const std::string& name) const;
         CoreSegment& getCoreSegment(const std::string& name);
+        const CoreSegment& getCoreSegment(const std::string& name) const;
 
-        Entity& getEntity(const MemoryID& id) override;
+        const Entity& getEntity(const MemoryID& id) const override;
 
 
+        // CoreSegment& addCoreSegment(const std::string& name, aron::type::AronTypePtr type);
         CoreSegment& addCoreSegment(const std::string& name);
+        CoreSegment& addCoreSegment(const CoreSegment& coreSegment);
+        CoreSegment& addCoreSegment(CoreSegmentPtr&& coreSegment);
+
+
         /**
          * @brief Add multiple core segments.
          * @param The core segment names.
@@ -48,7 +66,6 @@ namespace armarx::armem
 
     };
 
-    using MemoryPtr = std::unique_ptr<Memory>;
 
 
 }
diff --git a/source/RobotAPI/libraries/armem/memory/ProviderSegment.cpp b/source/RobotAPI/libraries/armem/memory/ProviderSegment.cpp
index 9b7bbbd94587bad5baca12cadfdbfb96637e4500..991999ea59fdc487824cc92f5dee866f3adc2c71 100644
--- a/source/RobotAPI/libraries/armem/memory/ProviderSegment.cpp
+++ b/source/RobotAPI/libraries/armem/memory/ProviderSegment.cpp
@@ -8,7 +8,42 @@
 namespace armarx::armem
 {
 
-    Entity& ProviderSegment::getEntity(const std::string& name)
+    ProviderSegment::ProviderSegment(const ProviderSegment& other) : EntityStorage (other)
+    {
+        *this = other;
+    }
+
+    ProviderSegment& ProviderSegment::operator=(const ProviderSegment& other)
+    {
+        this->name = other.name;
+
+        this->entities.clear();
+        for (const auto& [name, entity] : other.entities)
+        {
+            this->entities.emplace(name, std::make_unique<Entity>(*entity));
+        }
+
+        return *this;
+    }
+
+    ProviderSegment::~ProviderSegment()
+    {
+    }
+
+    ProviderSegmentPtr ProviderSegment::getEmptyCopy() const
+    {
+        ProviderSegmentPtr other = std::make_unique<ProviderSegment>();
+        other->name = this->name;
+        other->maxHistorySize = this->maxHistorySize;
+        return other;
+    }
+
+    Entity& ProviderSegment::getEntity(const string& name)
+    {
+        return const_cast<Entity&>(const_cast<const ProviderSegment*>(this)->getEntity(name));
+    }
+
+    const Entity& ProviderSegment::getEntity(const std::string& name) const
     {
         auto it = this->entities.find(name);
         if (it != entities.end())
@@ -22,7 +57,7 @@ namespace armarx::armem
         }
     }
 
-    Entity& ProviderSegment::getEntity(const MemoryID& id)
+    const Entity& ProviderSegment::getEntity(const MemoryID& id) const
     {
         checkStorageName(id.providerSegmentName, this->name, "provider segment");
         return getEntity(id.entityName);
@@ -44,6 +79,17 @@ namespace armarx::armem
         return it->second->update(update);
     }
 
+    Entity& ProviderSegment::addEntity(const Entity& entity)
+    {
+        return addEntity(std::make_unique<Entity>(entity));
+    }
+
+    Entity& ProviderSegment::addEntity(EntityPtr&& entity)
+    {
+        auto it = entities.emplace(entity->name, std::move(entity)).first;
+        return *it->second;
+    }
+
     void ProviderSegment::clear()
     {
         entities.clear();
diff --git a/source/RobotAPI/libraries/armem/memory/ProviderSegment.h b/source/RobotAPI/libraries/armem/memory/ProviderSegment.h
index 83c0c783337cb6120c1511a7d9c0392adefd9bc1..c27eb5ca7393c64ee4233fcbb35290edeca524f3 100644
--- a/source/RobotAPI/libraries/armem/memory/ProviderSegment.h
+++ b/source/RobotAPI/libraries/armem/memory/ProviderSegment.h
@@ -11,6 +11,9 @@
 namespace armarx::armem
 {
 
+    class ProviderSegment;
+    using ProviderSegmentPtr = std::unique_ptr<ProviderSegment>;
+
     /**
      * @brief Data of a provider segment containing multiple entities.
      */
@@ -20,13 +23,26 @@ namespace armarx::armem
 
         using EntityStorage::EntityStorage;
 
+        ProviderSegment(const ProviderSegment& other);
+        ProviderSegment& operator=(const ProviderSegment& other);
+
+        ~ProviderSegment() override;
+
+
+        ProviderSegmentPtr getEmptyCopy() const;
+
 
         bool hasEntity(const std::string& name) const
         {
             return entities.count(name) > 0;
         }
+
+        using EntityStorage::getEntity;
+        const Entity& getEntity(const MemoryID& id) const override;
+
         Entity& getEntity(const std::string& name);
-        Entity& getEntity(const MemoryID& id) override;
+        const Entity& getEntity(const std::string& name) const;
+
 
         /**
          * @brief Updates an entity's history.
@@ -36,6 +52,9 @@ namespace armarx::armem
         virtual MemoryID update(const InternalEntityUpdate& update) override;
         using EntityStorage::update;
 
+        Entity& addEntity(const Entity& entity);
+        Entity& addEntity(EntityPtr&& entity);
+
         virtual void clear() override;
 
 
@@ -59,6 +78,4 @@ namespace armarx::armem
 
     };
 
-    using ProviderSegmentPtr = std::unique_ptr<ProviderSegment>;
-
 }
diff --git a/source/RobotAPI/libraries/armem/memory/ice_conversions.cpp b/source/RobotAPI/libraries/armem/memory/ice_conversions.cpp
index dba3703d7d121d25a22cba733ef5a0cfa2c311b6..cf98b613838d990ebdc39e7cdba8da3b51dd5353 100644
--- a/source/RobotAPI/libraries/armem/memory/ice_conversions.cpp
+++ b/source/RobotAPI/libraries/armem/memory/ice_conversions.cpp
@@ -21,6 +21,90 @@ namespace armarx
         update.timeArrived = timeArrived;
     }
 
+    void armem::toIce(data::EntityMetadata& ice, const EntityMetadata& metadata)
+    {
+        ice.confidence = metadata.confidence;
+        toIce(ice.timeArrivedMicroSeconds, metadata.timeArrived);
+        toIce(ice.timeCreatedMicroSeconds, metadata.timeCreated);
+        toIce(ice.timeSentMicroSeconds, metadata.timeSent);
+    }
+    void armem::fromIce(const data::EntityMetadata& ice, EntityMetadata& metadata)
+    {
+        metadata.confidence = ice.confidence;
+        fromIce(ice.timeArrivedMicroSeconds, metadata.timeArrived);
+        fromIce(ice.timeCreatedMicroSeconds, metadata.timeCreated);
+        fromIce(ice.timeSentMicroSeconds, metadata.timeSent);
+    }
+
+    void armem::toIce(data::EntityData& ice, const EntityData& data)
+    {
+        ice.data = data.data;
+        ice.index = data.index;
+        toIce(ice.metadata, data.metadata);
+    }
+    void armem::fromIce(const data::EntityData& ice, EntityData& data)
+    {
+        data.data = ice.data;
+        data.index = ice.index;
+        fromIce(ice.metadata, data.metadata);
+    }
+
+
+    void armem::toIce(data::EntitySnapshot& ice, const EntitySnapshot& snapshot)
+    {
+        toIce(ice.timeMicroSeconds, snapshot.time);
+        toIce(ice.instances, snapshot.instances);
+    }
+    void armem::fromIce(const data::EntitySnapshot& ice, EntitySnapshot& snapshot)
+    {
+        fromIce(ice.timeMicroSeconds, snapshot.time);
+        fromIce(ice.instances, snapshot.instances);
+    }
+
+    void armem::toIce(data::Entity& ice, const Entity& entity)
+    {
+        ice.name = entity.name;
+        toIce(ice.history, entity.history);
+    }
+    void armem::fromIce(const data::Entity& ice, Entity& entity)
+    {
+        entity.name = ice.name;
+        fromIce(ice.history, entity.history);
+    }
+
+
+    void armem::toIce(data::ProviderSegment& ice, const ProviderSegment& providerSegment)
+    {
+        ice.name = providerSegment.name;
+        toIce(ice.entities, providerSegment.entities);
+    }
+    void armem::fromIce(const data::ProviderSegment& ice, ProviderSegment& providerSegment)
+    {
+        providerSegment.name = ice.name;
+        fromIce(ice.entities, providerSegment.entities);
+    }
+
+    void armem::toIce(data::CoreSegment& ice, const CoreSegment& coreSegment)
+    {
+        ice.name = coreSegment.name;
+        toIce(ice.providerSegments, coreSegment.providerSegments);
+    }
+    void armem::fromIce(const data::CoreSegment& ice, CoreSegment& coreSegment)
+    {
+        coreSegment.name = ice.name;
+        fromIce(ice.providerSegments, coreSegment.providerSegments);
+    }
+
+    void armem::toIce(data::Memory& ice, const Memory& memory)
+    {
+        ice.name = memory.name;
+        toIce(ice.coreSegments, memory.coreSegments);
+    }
+    void armem::fromIce(const data::Memory& ice, Memory& memory)
+    {
+        memory.name = ice.name;
+        fromIce(ice.coreSegments, memory.coreSegments);
+    }
 
 }
 
diff --git a/source/RobotAPI/libraries/armem/memory/ice_conversions.h b/source/RobotAPI/libraries/armem/memory/ice_conversions.h
index aefefc6523f6b14752d016f34f06143212d1a9c0..4fad4a8b4c9590426e251978ce0d3812eb412dd5 100644
--- a/source/RobotAPI/libraries/armem/memory/ice_conversions.h
+++ b/source/RobotAPI/libraries/armem/memory/ice_conversions.h
@@ -1,17 +1,43 @@
 #pragma once
 
+#include <RobotAPI/interface/armem/memory.h>
 
 #include "../core/ice_conversions.h"
 
 #include "InternalCommit.h"
+#include "Memory.h"
 
 
 namespace armarx::armem
 {
 
     void fromIce(const data::Commit& ice, InternalCommit& commit, Time timeArrived);
-
     void fromIce(const data::EntityUpdate& ice, InternalEntityUpdate& update, Time timeArrived);
 
 
+    void toIce(data::EntityMetadata& ice, const EntityMetadata& metadata);
+    void fromIce(const data::EntityMetadata& ice, EntityMetadata& metadata);
+
+    void toIce(data::EntityData& ice, const EntityData& data);
+    void fromIce(const data::EntityData& ice, EntityData& data);
+
+
+    void toIce(data::EntitySnapshot& ice, const EntitySnapshot& snapshot);
+    void fromIce(const data::EntitySnapshot& ice, EntitySnapshot& snapshot);
+
+    void toIce(data::Entity& ice, const Entity& entity);
+    void fromIce(const data::Entity& ice, Entity& entity);
+
+
+    void toIce(data::ProviderSegment& ice, const ProviderSegment& providerSegment);
+    void fromIce(const data::ProviderSegment& ice, ProviderSegment& providerSegment);
+
+    void toIce(data::CoreSegment& ice, const CoreSegment& coreSegment);
+    void fromIce(const data::CoreSegment& ice, CoreSegment& coreSegment);
+
+    void toIce(data::Memory& ice, const Memory& memory);
+    void fromIce(const data::Memory& ice, Memory& memory);
+
+
+
 }
diff --git a/source/RobotAPI/libraries/armem/query.h b/source/RobotAPI/libraries/armem/query.h
new file mode 100644
index 0000000000000000000000000000000000000000..8bf723f3a38cc329e8c3c977f0f43f12fd0cf14f
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/query.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "query/EntityQueryProcessor.h"
+#include "query/ice_conversions.h"
+
diff --git a/source/RobotAPI/libraries/armem/query/BaseQueryProcessor.cpp b/source/RobotAPI/libraries/armem/query/BaseQueryProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..aa818cca129e6114a54bb5fc5ec9496f53af4920
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/query/BaseQueryProcessor.cpp
@@ -0,0 +1,14 @@
+#include "BaseQueryProcessor.h"
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include "../error/ArMemError.h"
+
+#include "../core/ice_conversions.h"
+
+
+namespace armarx::armem
+{
+
+}
diff --git a/source/RobotAPI/libraries/armem/query/BaseQueryProcessor.h b/source/RobotAPI/libraries/armem/query/BaseQueryProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..2397b40cc66012b6c1cfae129967247be07ef973
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/query/BaseQueryProcessor.h
@@ -0,0 +1,62 @@
+#pragma once
+
+#include <RobotAPI/interface/armem/query.h>
+
+#include "../memory/Memory.h"
+
+
+namespace armarx::armem
+{
+
+    /**
+     * @brief Base class for memory query processors.
+     */
+    template <class DataT, class QueryT>
+    class BaseQueryProcessor
+    {
+    public:
+
+        using DataPtrT = std::unique_ptr<DataT>;
+        using QueryPtrT = ::IceInternal::Handle<QueryT>;
+        using QuerySeqT = std::vector<QueryPtrT>;
+
+
+    public:
+
+
+        virtual ~BaseQueryProcessor()
+        {}
+
+
+        DataPtrT process(const QueryT& query, const DataT& data) const
+        {
+            DataPtrT result = data.getEmptyCopy();
+            this->process(*result, query, data);
+            return result;
+        }
+        DataPtrT process(const QueryPtrT& query, const DataPtrT& data) const
+        {
+            return this->process(*query, *data);
+        }
+
+        DataPtrT process(const QuerySeqT& queries, const DataT& data) const
+        {
+            DataPtrT result = data.getEmptyCopy();
+            this->process(*result, queries, data);
+            return result;
+        }
+
+
+        void process(DataT& result, const QuerySeqT& queries, const DataT& data) const
+        {
+            for (const auto& query : queries)
+            {
+                this->process(result, *query, data);
+            }
+        }
+
+        virtual void process(DataT& result, const QueryT& query, const DataT& data) const = 0;
+
+    };
+
+}
diff --git a/source/RobotAPI/libraries/armem/query/CoreSegmentQueryProcessor.cpp b/source/RobotAPI/libraries/armem/query/CoreSegmentQueryProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c7ed8bec453ab1b981100ec0930a11599aab0e48
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/query/CoreSegmentQueryProcessor.cpp
@@ -0,0 +1,80 @@
+#include "CoreSegmentQueryProcessor.h"
+
+#include <regex>
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include "../error/ArMemError.h"
+
+#include "../core/ice_conversions.h"
+
+
+namespace armarx::armem
+{
+
+    void CoreSegmentQueryProcessor::process(CoreSegment& result, const query::CoreSegmentQuery& query, const CoreSegment& coreSegment) const
+    {
+        if (auto q = dynamic_cast<const query::core::All*>(&query))
+        {
+            process(result, *q, coreSegment);
+        }
+        else if (auto q = dynamic_cast<const query::core::Single*>(&query))
+        {
+            process(result, *q, coreSegment);
+        }
+        else if (auto q = dynamic_cast<const query::core::Regex*>(&query))
+        {
+            process(result, *q, coreSegment);
+        }
+        else
+        {
+            throw armem::error::UnknownQueryType("core segment", query);
+        }
+    }
+
+
+    void CoreSegmentQueryProcessor::process(CoreSegment& result,
+                                            const query::core::All& query, const CoreSegment& coreSegment) const
+    {
+        for (const auto& [name, providerSegment] : coreSegment.providerSegments)
+        {
+            result.addProviderSegment(providerSegmentProcessor.process(query.providerSegmentQueries, *providerSegment));
+        }
+    }
+
+    void CoreSegmentQueryProcessor::process(CoreSegment& result,
+                                            const query::core::Single& query, const CoreSegment& coreSegment) const
+    {
+        try
+        {
+            const ProviderSegment& providerSegment = coreSegment.getProviderSegment(query.providerSegmentName);
+            result.addProviderSegment(providerSegmentProcessor.process(query.providerSegmentQueries, providerSegment));
+        }
+        catch (const error::MissingEntry&)
+        {
+            // Leave empty.
+        }
+    }
+
+    void CoreSegmentQueryProcessor::process(CoreSegment& result,
+                                            const query::core::Regex& query, const CoreSegment& coreSegment) const
+    {
+        std::regex regex(query.providerSegmentNameRegex);
+        for (const auto& [name, providerSegment] : coreSegment.providerSegments)
+        {
+            if (std::regex_search(providerSegment->name, regex))
+            {
+                result.addProviderSegment(providerSegmentProcessor.process(query.providerSegmentQueries, *providerSegment));
+            }
+        }
+    }
+
+
+    data::CoreSegmentPtr CoreSegmentQueryProcessor::processToIce(
+        const query::CoreSegmentQuery& query, const CoreSegment& coreSegment) const
+    {
+        return toIce<data::CoreSegmentPtr>(process(query, coreSegment));
+    }
+
+}
diff --git a/source/RobotAPI/libraries/armem/query/CoreSegmentQueryProcessor.h b/source/RobotAPI/libraries/armem/query/CoreSegmentQueryProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..a25810750ed2e9fb0e4e46ebb8447c97f9f35bcd
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/query/CoreSegmentQueryProcessor.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <RobotAPI/interface/armem/query.h>
+
+#include "../memory/Memory.h"
+#include "../memory/ice_conversions.h"
+
+#include "BaseQueryProcessor.h"
+#include "ProviderSegmentQueryProcessor.h"
+
+
+
+namespace armarx::armem
+{
+
+    /**
+     * @brief Handles memory queries.
+     */
+    class CoreSegmentQueryProcessor : public BaseQueryProcessor<CoreSegment, query::CoreSegmentQuery>
+    {
+    public:
+
+        using BaseQueryProcessor::process;
+
+        void process(CoreSegment& result, const query::CoreSegmentQuery& query, const CoreSegment& coreSegment) const;
+
+        void process(CoreSegment& result, const query::core::All& query, const CoreSegment& coreSegment) const;
+        void process(CoreSegment& result, const query::core::Single& query, const CoreSegment& coreSegment) const;
+        void process(CoreSegment& result, const query::core::Regex& query, const CoreSegment& coreSegment) const;
+
+
+        data::CoreSegmentPtr processToIce(const query::CoreSegmentQuery& query, const CoreSegment& coreSegment) const;
+
+
+    private:
+
+        ProviderSegmentQueryProcessor providerSegmentProcessor;
+
+    };
+
+}
diff --git a/source/RobotAPI/libraries/armem/query/EntityQueryProcessor.cpp b/source/RobotAPI/libraries/armem/query/EntityQueryProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5ac1e3fbf2d50d53be353eaf6bb895c58c87f4aa
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/query/EntityQueryProcessor.cpp
@@ -0,0 +1,89 @@
+#include "EntityQueryProcessor.h"
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include "../error/ArMemError.h"
+
+#include "../core/ice_conversions.h"
+
+
+namespace armarx::armem
+{
+
+    void EntityQueryProcessor::process(Entity& result, const query::EntityQuery& query, const Entity& entity) const
+    {
+        if (auto q = dynamic_cast<const query::entity::All*>(&query))
+        {
+            process(result, *q, entity);
+        }
+        else if (auto q = dynamic_cast<const query::entity::Single*>(&query))
+        {
+            process(result, *q, entity);
+        }
+        else if (auto q = dynamic_cast<const query::entity::Range*>(&query))
+        {
+            process(result, *q, entity);
+        }
+        else
+        {
+            throw armem::error::UnknownQueryType("entity snapshot", query);
+        }
+    }
+
+    void EntityQueryProcessor::process(Entity& result, const query::entity::All& query, const Entity& entity) const
+    {
+        (void) query;
+        // Copy this entitiy and its contents.
+        result = entity;
+    }
+
+    void EntityQueryProcessor::process(Entity& result, const query::entity::Single& query, const Entity& entity) const
+    {
+        (void) query;
+        if (query.timestamp < 0)
+        {
+            result.addSnapshot(entity.getLatestSnapshot());
+        }
+        else
+        {
+            Time time = fromIce<Time>(query.timestamp);
+            try
+            {
+                result.addSnapshot(entity.getSnapshot(time));
+            }
+            catch (const armem::error::MissingEntry&)
+            {
+                // Leave empty.
+            }
+        }
+    }
+
+    void EntityQueryProcessor::process(Entity& result, const query::entity::Range& query, const Entity& entity) const
+    {
+        if (query.minTimestamp <= query.maxTimestamp || query.minTimestamp < 0 || query.maxTimestamp < 0)
+        {
+            Time min = fromIce<Time>(query.minTimestamp);
+            Time max = fromIce<Time>(query.maxTimestamp);
+            process(result, min, max, entity);
+        }
+    }
+
+    void EntityQueryProcessor::process(Entity& result, const Time& min, const Time& max, const Entity& entity) const
+    {
+        // Returns an iterator pointing to the first element that is not less than (i.e. greater or equal to) key.
+        auto begin = min.toMicroSeconds() > 0 ? entity.history.lower_bound(min) : entity.history.begin();
+        // Returns an iterator pointing to the first element that is *greater than* key.
+        auto end = max.toMicroSeconds() > 0 ? entity.history.upper_bound(max) : entity.history.end();
+
+        for (auto it = begin; it != end && it != entity.history.end(); ++it)
+        {
+            result.addSnapshot(*it->second);
+        }
+    }
+
+    data::EntityPtr EntityQueryProcessor::processToIce(const query::EntityQuery& query, const Entity& entity) const
+    {
+        return toIce<data::EntityPtr>(process(query, entity));
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/query/EntityQueryProcessor.h b/source/RobotAPI/libraries/armem/query/EntityQueryProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..64235ff2844cb14e5fa1a367c3782bbe5f37962e
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/query/EntityQueryProcessor.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <RobotAPI/interface/armem/query.h>
+
+#include "../memory/Memory.h"
+#include "../memory/ice_conversions.h"
+
+#include "BaseQueryProcessor.h"
+
+
+namespace armarx::armem
+{
+
+    /**
+     * @brief Handles memory queries.
+     */
+    class EntityQueryProcessor : public BaseQueryProcessor<Entity, query::EntityQuery>
+    {
+    public:
+
+        using BaseQueryProcessor::process;
+
+        void process(Entity& result, const query::EntityQuery& query, const Entity& entity) const override;
+
+        void process(Entity& result, const query::entity::All& query, const Entity& entity) const;
+        void process(Entity& result, const query::entity::Single& query, const Entity& entity) const;
+        void process(Entity& result, const query::entity::Range& query, const Entity& entity) const;
+
+        void process(Entity& result, const Time& min, const Time& max, const Entity& entity) const;
+
+
+        data::EntityPtr processToIce(const query::EntityQuery& query, const Entity& entity) const;
+
+    };
+
+}
diff --git a/source/RobotAPI/libraries/armem/query/MemoryQueryProcessor.cpp b/source/RobotAPI/libraries/armem/query/MemoryQueryProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..390f0c507c62566e1b7e9eb401dc26c65ba9126e
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/query/MemoryQueryProcessor.cpp
@@ -0,0 +1,85 @@
+#include "MemoryQueryProcessor.h"
+
+#include <regex>
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include "../error/ArMemError.h"
+
+#include "../memory/ice_conversions.h"
+
+
+namespace armarx::armem
+{
+
+    void MemoryQueryProcessor::process(Memory& result, const query::MemoryQuery& query, const Memory& memory) const
+    {
+        if (auto q = dynamic_cast<const query::memory::All*>(&query))
+        {
+            process(result, *q, memory);
+        }
+        else if (auto q = dynamic_cast<const query::memory::Single*>(&query))
+        {
+            process(result, *q, memory);
+        }
+        else if (auto q = dynamic_cast<const query::memory::Regex*>(&query))
+        {
+            process(result, *q, memory);
+        }
+        else
+        {
+            throw armem::error::UnknownQueryType("memory segment", query);
+        }
+    }
+
+
+    void MemoryQueryProcessor::process(Memory& result,
+                                       const query::memory::All& query, const Memory& memory) const
+    {
+        for (const auto& [name, coreSegment] : memory.coreSegments)
+        {
+            result.addCoreSegment(coreSegmentProcessor.process(query.coreSegmentQueries, *coreSegment));
+        }
+    }
+
+    void MemoryQueryProcessor::process(Memory& result,
+                                       const query::memory::Single& query, const Memory& memory) const
+    {
+        try
+        {
+            const CoreSegment& coreSegment = memory.getCoreSegment(query.coreSegmentName);
+            result.addCoreSegment(coreSegmentProcessor.process(query.coreSegmentQueries, coreSegment));
+        }
+        catch (const error::MissingEntry&)
+        {
+            // Leave empty.
+        }
+    }
+
+    void MemoryQueryProcessor::process(Memory& result,
+                                       const query::memory::Regex& query, const Memory& memory) const
+    {
+        std::regex regex(query.coreSegmentNameRegex);
+        for (const auto& [name, coreSegment] : memory.coreSegments)
+        {
+            if (std::regex_search(coreSegment->name, regex))
+            {
+                result.addCoreSegment(coreSegmentProcessor.process(query.coreSegmentQueries, *coreSegment));
+            }
+        }
+    }
+
+
+    data::MemoryPtr MemoryQueryProcessor::processToIce(
+        const query::MemoryQuery& query, const Memory& memory) const
+    {
+        return toIce<data::MemoryPtr>(process(query, memory));
+    }
+
+    data::MemoryPtr MemoryQueryProcessor::processToIce(const query::MemoryQuerySeq& queries, const Memory& memory) const
+    {
+        return toIce<data::MemoryPtr>(process(queries, memory));
+    }
+
+}
diff --git a/source/RobotAPI/libraries/armem/query/MemoryQueryProcessor.h b/source/RobotAPI/libraries/armem/query/MemoryQueryProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..ebbfa1a1ad910b707882e67f427c0e1ed2e9ff4b
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/query/MemoryQueryProcessor.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <RobotAPI/interface/armem/query.h>
+
+#include "../memory/Memory.h"
+#include "../memory/ice_conversions.h"
+
+#include "BaseQueryProcessor.h"
+#include "CoreSegmentQueryProcessor.h"
+
+
+
+namespace armarx::armem
+{
+
+    /**
+     * @brief Handles memory queries.
+     */
+    class MemoryQueryProcessor : public BaseQueryProcessor<Memory, query::MemoryQuery>
+    {
+    public:
+
+        using BaseQueryProcessor::process;
+
+        void process(Memory& result, const query::MemoryQuery& query, const Memory& memory) const;
+
+        void process(Memory& result, const query::memory::All& query, const Memory& memory) const;
+        void process(Memory& result, const query::memory::Single& query, const Memory& memory) const;
+        void process(Memory& result, const query::memory::Regex& query, const Memory& memory) const;
+
+
+        data::MemoryPtr processToIce(const query::MemoryQuery& query, const Memory& memory) const;
+        data::MemoryPtr processToIce(const query::MemoryQuerySeq& query, const Memory& memory) const;
+
+
+    private:
+
+        CoreSegmentQueryProcessor coreSegmentProcessor;
+
+    };
+
+}
diff --git a/source/RobotAPI/libraries/armem/query/ProviderSegmentQueryProcessor.cpp b/source/RobotAPI/libraries/armem/query/ProviderSegmentQueryProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6e5db59e17c74e3a88dc460e543d8f4b7cc2e496
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/query/ProviderSegmentQueryProcessor.cpp
@@ -0,0 +1,80 @@
+#include "ProviderSegmentQueryProcessor.h"
+
+#include <regex>
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include "../error/ArMemError.h"
+
+#include "../core/ice_conversions.h"
+
+
+namespace armarx::armem
+{
+
+    void ProviderSegmentQueryProcessor::process(ProviderSegment& result, const query::ProviderSegmentQuery& query, const ProviderSegment& providerSegment) const
+    {
+        if (auto q = dynamic_cast<const query::provider::All*>(&query))
+        {
+            process(result, *q, providerSegment);
+        }
+        else if (auto q = dynamic_cast<const query::provider::Single*>(&query))
+        {
+            process(result, *q, providerSegment);
+        }
+        else if (auto q = dynamic_cast<const query::provider::Regex*>(&query))
+        {
+            process(result, *q, providerSegment);
+        }
+        else
+        {
+            throw armem::error::UnknownQueryType("provider segment", query);
+        }
+    }
+
+
+    void ProviderSegmentQueryProcessor::process(ProviderSegment& result,
+            const query::provider::All& query, const ProviderSegment& providerSegment) const
+    {
+        for (const auto& [name, entity] : providerSegment.entities)
+        {
+            result.addEntity(std::move(*entityProcessor.process(query.entityQueries, *entity)));
+        }
+    }
+
+    void ProviderSegmentQueryProcessor::process(ProviderSegment& result,
+            const query::provider::Single& query, const ProviderSegment& providerSegment) const
+    {
+        try
+        {
+            const Entity& entity = providerSegment.getEntity(query.entityName);
+            result.addEntity(std::move(*entityProcessor.process(query.entityQueries, entity)));
+        }
+        catch (const error::MissingEntry&)
+        {
+            // Leave empty.
+        }
+    }
+
+    void ProviderSegmentQueryProcessor::process(ProviderSegment& result,
+            const query::provider::Regex& query, const ProviderSegment& providerSegment) const
+    {
+        std::regex regex(query.entityNameRegex);
+        for (const auto& [name, entity] : providerSegment.entities)
+        {
+            if (std::regex_search(entity->name, regex))
+            {
+                result.addEntity(std::move(*entityProcessor.process(query.entityQueries, *entity)));
+            }
+        }
+    }
+
+
+    data::ProviderSegmentPtr ProviderSegmentQueryProcessor::processToIce(
+        const query::ProviderSegmentQuery& query, const ProviderSegment& providerSegment) const
+    {
+        return toIce<data::ProviderSegmentPtr>(process(query, providerSegment));
+    }
+
+}
diff --git a/source/RobotAPI/libraries/armem/query/ProviderSegmentQueryProcessor.h b/source/RobotAPI/libraries/armem/query/ProviderSegmentQueryProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..f0d2a14e18e4e9c71f470ce24a7abab3c66bcf92
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/query/ProviderSegmentQueryProcessor.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <RobotAPI/interface/armem/query.h>
+
+#include "../memory/Memory.h"
+#include "../memory/ice_conversions.h"
+
+#include "BaseQueryProcessor.h"
+#include "EntityQueryProcessor.h"
+
+
+
+namespace armarx::armem
+{
+
+    /**
+     * @brief Handles memory queries.
+     */
+    class ProviderSegmentQueryProcessor : public BaseQueryProcessor<ProviderSegment, query::ProviderSegmentQuery>
+    {
+    public:
+
+        using BaseQueryProcessor::process;
+
+        void process(ProviderSegment& result, const query::ProviderSegmentQuery& query, const ProviderSegment& providerSegment) const;
+
+        void process(ProviderSegment& result, const query::provider::All& query, const ProviderSegment& providerSegment) const;
+        void process(ProviderSegment& result, const query::provider::Single& query, const ProviderSegment& providerSegment) const;
+        void process(ProviderSegment& result, const query::provider::Regex& query, const ProviderSegment& providerSegment) const;
+
+
+        data::ProviderSegmentPtr processToIce(const query::ProviderSegmentQuery& query, const ProviderSegment& providerSegment) const;
+
+
+    private:
+
+        EntityQueryProcessor entityProcessor;
+
+    };
+
+}
diff --git a/source/RobotAPI/libraries/armem/test/ArmemQueryTest.cpp b/source/RobotAPI/libraries/armem/test/ArmemQueryTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..421e672e5fccf4038404e1a3fa52948c4247ad77
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/test/ArmemQueryTest.cpp
@@ -0,0 +1,281 @@
+/*
+ * 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/>.
+ *
+ * @package    RobotAPI::ArmarXObjects::armem
+ * @author     Simon Ottenhaus ( simon dot ottenhaus at kit dot edu )
+ * @date       2020
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#define BOOST_TEST_MODULE RobotAPI::ArmarXLibraries::armem
+
+#define ARMARX_BOOST_TEST
+
+#include <RobotAPI/Test.h>
+#include "../query/EntityQueryProcessor.h"
+#include "../error.h"
+
+
+#include <iostream>
+
+#include <SimoxUtility/algorithm/get_map_keys_values.h>
+#include <SimoxUtility/algorithm/string.h>
+
+
+namespace armem = armarx::armem;
+namespace aron = armarx::aron;
+
+
+namespace ArMemQueryTest
+{
+
+    class UnknownEntityQuery : public armem::query::EntityQuery
+    {
+    };
+
+    struct Fixture
+    {
+        armem::EntityPtr entity;
+
+        armem::EntityQueryProcessor processor;
+        armem::query::EntityQueryPtr entityQuery;
+
+        std::vector<armem::EntityPtr> results;
+
+        Fixture()
+        {
+            entity = std::make_unique<armem::Entity>("entity");
+
+            armem::EntitySnapshot snapshot;
+            snapshot.time = armem::Time::microSeconds(1000);
+            entity->addSnapshot(snapshot);
+            snapshot.time = armem::Time::microSeconds(2000);
+            entity->addSnapshot(snapshot);
+            snapshot.time = armem::Time::microSeconds(3000);
+            entity->addSnapshot(snapshot);
+            snapshot.time = armem::Time::microSeconds(4000);
+            entity->addSnapshot(snapshot);
+            snapshot.time = armem::Time::microSeconds(5000);
+            entity->addSnapshot(snapshot);
+        }
+        ~Fixture()
+        {
+
+        }
+
+        template <class QueryT>
+        void addResults(QueryT query = {})
+        {
+            entityQuery = new QueryT(query);
+
+            results.emplace_back(processor.process(query, *entity));
+            results.emplace_back(processor.process(*entityQuery, *entity));
+        }
+    };
+
+}
+
+
+BOOST_FIXTURE_TEST_SUITE(ArMemQueryTest, ArMemQueryTest::Fixture)
+
+
+BOOST_AUTO_TEST_CASE(test_entity_Single_latest)
+{
+    addResults(armem::query::entity::Single());
+    BOOST_REQUIRE_GT(results.size(), 0);
+
+    for (const auto& result : results)
+    {
+        BOOST_CHECK_EQUAL(result->name, entity->name);
+        BOOST_CHECK_EQUAL(result->history.size(), 1);
+        BOOST_CHECK_EQUAL(result->history.begin()->second->time, entity->getLatestSnapshot().time);
+        BOOST_CHECK_NE(result->history.begin()->second.get(), entity->history.rbegin()->second.get());
+    }
+}
+
+
+BOOST_AUTO_TEST_CASE(test_entity_Single_existing)
+{
+    addResults(armem::query::entity::Single { 3000 });
+    BOOST_REQUIRE_GT(results.size(), 0);
+
+    for (const auto& result : results)
+    {
+        BOOST_CHECK_EQUAL(result->name, entity->name);
+        BOOST_CHECK_EQUAL(result->history.size(), 1);
+        BOOST_CHECK_EQUAL(result->history.begin()->second->time, armem::Time::microSeconds(3000));
+    }
+}
+
+
+BOOST_AUTO_TEST_CASE(test_entity_Single_non_existing)
+{
+    addResults(armem::query::entity::Single { 3500 });
+    BOOST_REQUIRE_GT(results.size(), 0);
+
+    for (const auto& result : results)
+    {
+        BOOST_CHECK_EQUAL(result->name, entity->name);
+        BOOST_CHECK_EQUAL(result->history.size(), 0);
+    }
+}
+
+
+BOOST_AUTO_TEST_CASE(test_entity_All)
+{
+    addResults(armem::query::entity::All());
+    BOOST_REQUIRE_GT(results.size(), 0);
+
+    for (const auto& result : results)
+    {
+        BOOST_CHECK_EQUAL(result->name, entity->name);
+        BOOST_CHECK_EQUAL(result->history.size(), entity->history.size());
+        for (auto it = result->history.begin(), jt = entity->history.begin();
+             it != result->history.end(); ++it, ++jt)
+        {
+            BOOST_CHECK_EQUAL(it->first, jt->first);
+            BOOST_CHECK_EQUAL(it->second->time, jt->second->time);
+            BOOST_CHECK_NE(it->second.get(), jt->second.get());
+        }
+    }
+}
+
+
+BOOST_AUTO_TEST_CASE(test_entity_Range_slice)
+{
+    addResults(armem::query::entity::Range{ 1500, 3500 });
+    BOOST_REQUIRE_GT(results.size(), 0);
+
+    for (const auto& result : results)
+    {
+        BOOST_CHECK_EQUAL(result->name, entity->name);
+        BOOST_CHECK_EQUAL(result->history.size(), 2);
+
+        std::vector<armem::Time> times = simox::get_keys(result->history);
+        std::vector<armem::Time> expected {
+            armem::Time::microSeconds(2000), armem::Time::microSeconds(3000)
+        };
+        BOOST_CHECK_EQUAL_COLLECTIONS(times.begin(), times.end(), expected.begin(), expected.end());
+    }
+}
+
+
+BOOST_AUTO_TEST_CASE(test_entity_Range_exact)
+{
+    addResults(armem::query::entity::Range{ 2000, 4000 });
+    BOOST_REQUIRE_GT(results.size(), 0);
+
+    for (const auto& result : results)
+    {
+        BOOST_CHECK_EQUAL(result->name, entity->name);
+        BOOST_CHECK_EQUAL(result->history.size(), 3);
+
+        std::vector<armem::Time> times = simox::get_keys(result->history);
+        std::vector<armem::Time> expected {
+            armem::Time::microSeconds(2000), armem::Time::microSeconds(3000), armem::Time::microSeconds(4000)
+        };
+        BOOST_CHECK_EQUAL_COLLECTIONS(times.begin(), times.end(), expected.begin(), expected.end());
+    }
+}
+
+BOOST_AUTO_TEST_CASE(test_entity_Range_all)
+{
+    addResults(armem::query::entity::Range{ 0, 10000 });
+    addResults(armem::query::entity::Range{ -1, -1 });
+    BOOST_REQUIRE_GT(results.size(), 0);
+
+    for (const auto& result : results)
+    {
+        BOOST_CHECK_EQUAL(result->name, entity->name);
+        BOOST_CHECK_EQUAL(result->history.size(), entity->history.size());
+
+        std::vector<armem::Time> times = simox::get_keys(result->history);
+        std::vector<armem::Time> expected = simox::get_keys(entity->history);
+        BOOST_CHECK_EQUAL_COLLECTIONS(times.begin(), times.end(), expected.begin(), expected.end());
+    }
+}
+
+
+BOOST_AUTO_TEST_CASE(test_entity_Range_empty)
+{
+    addResults(armem::query::entity::Range{ 2400, 2600 });
+    addResults(armem::query::entity::Range{ 6000, 1000 });
+    BOOST_REQUIRE_GT(results.size(), 0);
+
+    for (const auto& result : results)
+    {
+        BOOST_CHECK_EQUAL(result->name, entity->name);
+        BOOST_CHECK_EQUAL(result->history.size(), 0);
+    }
+}
+
+
+BOOST_AUTO_TEST_CASE(test_entity_Range_from_start)
+{
+    addResults(armem::query::entity::Range{ -1, 2500 });
+    BOOST_REQUIRE_GT(results.size(), 0);
+
+    for (const auto& result : results)
+    {
+        BOOST_CHECK_EQUAL(result->name, entity->name);
+        BOOST_CHECK_EQUAL(result->history.size(), 2);
+
+        std::vector<armem::Time> times = simox::get_keys(result->history);
+        std::vector<armem::Time> expected {
+            armem::Time::microSeconds(1000), armem::Time::microSeconds(2000)
+        };
+        BOOST_CHECK_EQUAL_COLLECTIONS(times.begin(), times.end(), expected.begin(), expected.end());
+    }
+}
+
+
+BOOST_AUTO_TEST_CASE(test_entity_Range_to_end)
+{
+    addResults(armem::query::entity::Range{ 2500, -1 });
+    BOOST_REQUIRE_GT(results.size(), 0);
+
+    for (const auto& result : results)
+    {
+        BOOST_CHECK_EQUAL(result->name, entity->name);
+        BOOST_CHECK_EQUAL(result->history.size(), 3);
+
+        std::vector<armem::Time> times = simox::get_keys(result->history);
+        std::vector<armem::Time> expected {
+            armem::Time::microSeconds(3000), armem::Time::microSeconds(4000), armem::Time::microSeconds(5000)
+        };
+        BOOST_CHECK_EQUAL_COLLECTIONS(times.begin(), times.end(), expected.begin(), expected.end());
+    }
+}
+
+
+BOOST_AUTO_TEST_CASE(test_entity_UnknownQueryType)
+{
+    BOOST_CHECK_THROW(processor.process(UnknownEntityQuery(), *entity), armem::error::UnknownQueryType);
+    std::string msg;
+    try
+    {
+        processor.process(UnknownEntityQuery(), *entity);
+    }
+    catch (const armem::error::UnknownQueryType& e)
+    {
+        msg = e.what();
+    }
+    BOOST_TEST_MESSAGE(msg);
+    BOOST_CHECK(simox::alg::contains(msg, "UnknownEntityQuery"));
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/source/RobotAPI/libraries/armem/test/CMakeLists.txt b/source/RobotAPI/libraries/armem/test/CMakeLists.txt
index 1b2d707ae12a621b80a6909264b941aad0baf5e1..ea0aec9604371b9efd745d85c607f0d23162b78a 100644
--- a/source/RobotAPI/libraries/armem/test/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem/test/CMakeLists.txt
@@ -2,5 +2,5 @@
 # Libs required for the tests
 SET(LIBS ${LIBS} ArmarXCore ${LIB_NAME})
 
-# armarx_add_test(armemTest armemTest.cpp "${LIBS}")
 armarx_add_test(ArmemMemoryTest ArmemMemoryTest.cpp "${LIBS}")
+armarx_add_test(ArmemQueryTest ArmemQueryTest.cpp "${LIBS}")
diff --git a/source/RobotAPI/libraries/armem/test/armemTest.cpp b/source/RobotAPI/libraries/armem/test/armemTest.cpp
deleted file mode 100644
index 2b4b2de157192afd4b7a7346dfb316d8bfce5c04..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/armem/test/armemTest.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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/>.
- *
- * @package    RobotAPI::ArmarXObjects::armem
- * @author     Simon Ottenhaus ( simon dot ottenhaus at kit dot edu )
- * @date       2020
- * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
- *             GNU General Public License
- */
-
-#define BOOST_TEST_MODULE RobotAPI::ArmarXLibraries::armem
-
-#define ARMARX_BOOST_TEST
-
-#include <RobotAPI/Test.h>
-// #include "../armem.h"
-
-#include <iostream>
-
-BOOST_AUTO_TEST_CASE(testExample)
-{
-    BOOST_CHECK_EQUAL(true, true);
-}