diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index af25e698a9aa3820dbc68c346a57aa895f97505c..88113c1408093d1bd0bd42f4d703bfb7f67ae663 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -1,6 +1,9 @@
 # ArMem
 /source/RobotAPI/components/armem/ @RainerKartmann @dreher
+
 /source/RobotAPI/libraries/armem/ @RainerKartmann @dreher
+/source/RobotAPI/libraries/armem_robot_localization/ @FabianReister
+/source/RobotAPI/libraries/armem_robot_mapping/ @FabianReister
+
 /source/RobotAPI/interface/armem.ice @RainerKartmann @dreher
-/source/RobotAPI/interface/armem/ @RainerKartmann @dreher
 
diff --git a/source/RobotAPI/components/ArViz/Client/Layer.h b/source/RobotAPI/components/ArViz/Client/Layer.h
index 56056eabf3fbd031d0aeb0b25bee28956c85ffba..27e056d78eb767637ab9b7a96951c01e3035e902 100644
--- a/source/RobotAPI/components/ArViz/Client/Layer.h
+++ b/source/RobotAPI/components/ArViz/Client/Layer.h
@@ -46,6 +46,11 @@ namespace armarx::viz
             (add(std::forward<Ts>(elems)), ...);
         }
 
+        std::size_t size() const noexcept
+        {
+            return data_.elements.size();
+        }
+
         data::LayerUpdate data_;
     };
 
diff --git a/source/RobotAPI/components/ArViz/Client/elements/ElementOps.h b/source/RobotAPI/components/ArViz/Client/elements/ElementOps.h
index 4f7c222f5c8ebb3f6a5f65062033218e058a8ddb..b763c4301703bd83fe3af4b06a8fa9d96e4b6b1d 100644
--- a/source/RobotAPI/components/ArViz/Client/elements/ElementOps.h
+++ b/source/RobotAPI/components/ArViz/Client/elements/ElementOps.h
@@ -85,6 +85,11 @@ namespace armarx::viz
             return this->position(position).orientation(orientation);
         }
 
+        DerivedT& pose(const Eigen::Affine3f& pose)
+        {
+            return this->position(pose.translation()).orientation(pose.linear());
+        }
+
         Eigen::Matrix4f pose() const
         {
             auto& p = data_->pose;
diff --git a/source/RobotAPI/interface/armem/mns/MemoryNameSystemInterface.ice b/source/RobotAPI/interface/armem/mns/MemoryNameSystemInterface.ice
index e102426c44a33acb156a10203e77193689a97f92..85a862f4cd815168d6163d2d085426d71b298068 100644
--- a/source/RobotAPI/interface/armem/mns/MemoryNameSystemInterface.ice
+++ b/source/RobotAPI/interface/armem/mns/MemoryNameSystemInterface.ice
@@ -33,6 +33,15 @@ module armarx
                 string errorMessage;
             };
 
+            dictionary<string, server::MemoryInterface*> MemoryInterfaces;
+            struct GetAllRegisteredMemoriesResult
+            {
+                bool success;
+                string errorMessage;
+
+                MemoryInterfaces proxies;
+            };
+
             struct ResolveMemoryNameInput
             {
                 string name;
@@ -69,6 +78,8 @@ module armarx
                 data::RegisterMemoryResult registerMemory(data::RegisterMemoryInput input);
                 data::RemoveMemoryResult removeMemory(data::RemoveMemoryInput input);
 
+                data::GetAllRegisteredMemoriesResult getAllRegisteredMemories();
+
                 data::ResolveMemoryNameResult resolveMemoryName(data::ResolveMemoryNameInput input);
                 data::WaitForMemoryResult waitForMemory(data::WaitForMemoryInput input);
             };
diff --git a/source/RobotAPI/libraries/CMakeLists.txt b/source/RobotAPI/libraries/CMakeLists.txt
index 369ad1d5504d233fdfac46ccfae3ab90d0b512a5..06c12b18a610b8b05998daea8bc2100cb6839078 100644
--- a/source/RobotAPI/libraries/CMakeLists.txt
+++ b/source/RobotAPI/libraries/CMakeLists.txt
@@ -20,6 +20,7 @@ add_subdirectory(natik)
 add_subdirectory(armem)
 add_subdirectory(armem_gui)
 add_subdirectory(armem_robot_localization)
+add_subdirectory(armem_robot_mapping)
 add_subdirectory(aron)
 
 add_subdirectory(NJointControllerGuiPluginUtility)
diff --git a/source/RobotAPI/libraries/armem/CMakeLists.txt b/source/RobotAPI/libraries/armem/CMakeLists.txt
index 0dca18cdbbbb8d1c4302c26666d7755a3d671673..84bb291a72f5d9b86ed932b1e1422b5a89252ceb 100644
--- a/source/RobotAPI/libraries/armem/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem/CMakeLists.txt
@@ -66,6 +66,8 @@ set(LIB_FILES
     mns/MemoryNameSystem.cpp
     mns/ClientPlugin.cpp
     mns/ComponentPlugin.cpp
+
+    util/util.cpp
 )
 
 set(LIB_HEADERS
@@ -135,6 +137,8 @@ set(LIB_HEADERS
     mns/ClientPlugin.h
     mns/ComponentPlugin.h
 
+    util/util.h
+
 )
 
 armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}")
diff --git a/source/RobotAPI/libraries/armem/core/Time.h b/source/RobotAPI/libraries/armem/core/Time.h
index cc00c9febfc9927d7a4985a63b1dabf2d8621300..328d1f59d793cbcc9a7d0febc0951775d200013a 100644
--- a/source/RobotAPI/libraries/armem/core/Time.h
+++ b/source/RobotAPI/libraries/armem/core/Time.h
@@ -34,4 +34,4 @@ namespace armarx::armem
      */
     Time timeFromStringMicroSeconds(const std::string& microSeconds);
 
-}
+}  // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem/mns/ComponentPlugin.cpp b/source/RobotAPI/libraries/armem/mns/ComponentPlugin.cpp
index 0e5c206b636e6504975736d7c6c81a0ff40255d8..79e58300a6968dfda3f60d89ff0511f9ec72f267 100644
--- a/source/RobotAPI/libraries/armem/mns/ComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/armem/mns/ComponentPlugin.cpp
@@ -37,6 +37,15 @@ namespace armarx::armem::mns
     }
 
 
+    armem::data::GetAllRegisteredMemoriesResult
+    ComponentPluginUser::getAllRegisteredMemories(const Ice::Current&)
+    {
+        std::scoped_lock lock(mnsMutex);
+        armem::data::GetAllRegisteredMemoriesResult result = mns.getAllRegisteredMemories();
+        return result;
+    }
+
+
     armem::data::ResolveMemoryNameResult ComponentPluginUser::resolveMemoryName(const armem::data::ResolveMemoryNameInput& input, const Ice::Current&)
     {
         std::scoped_lock lock(mnsMutex);
diff --git a/source/RobotAPI/libraries/armem/mns/ComponentPlugin.h b/source/RobotAPI/libraries/armem/mns/ComponentPlugin.h
index ade1351d7f24c5315b55056d822fb7b26ef4eec8..1347c197e6d4f560b5773abfed30b92e8f8a7604 100644
--- a/source/RobotAPI/libraries/armem/mns/ComponentPlugin.h
+++ b/source/RobotAPI/libraries/armem/mns/ComponentPlugin.h
@@ -40,6 +40,7 @@ namespace armarx::armem::mns
     public:
         armem::data::RegisterMemoryResult registerMemory(const armem::data::RegisterMemoryInput& input, const Ice::Current& = Ice::emptyCurrent) override;
         armem::data::RemoveMemoryResult removeMemory(const armem::data::RemoveMemoryInput& input, const Ice::Current& = Ice::emptyCurrent) override;
+        armem::data::GetAllRegisteredMemoriesResult getAllRegisteredMemories(const Ice::Current&) override;
         armem::data::ResolveMemoryNameResult resolveMemoryName(const armem::data::ResolveMemoryNameInput& input, const Ice::Current& = Ice::emptyCurrent) override;
         armem::data::WaitForMemoryResult waitForMemory(const armem::data::WaitForMemoryInput& input, const Ice::Current& = Ice::emptyCurrent) override;
 
diff --git a/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.cpp b/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.cpp
index c3cff5bb45c2dfbfa793a32d1ff432a51c740203..ece0fa74306ed77465ce0bb0c643b781ec704178 100644
--- a/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.cpp
+++ b/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.cpp
@@ -82,6 +82,30 @@ namespace armarx::armem::mns
     }
 
 
+    data::GetAllRegisteredMemoriesResult
+    MemoryNameSystem::getAllRegisteredMemories()
+    {
+        data::GetAllRegisteredMemoriesResult result;
+        result.success = true;
+        result.errorMessage = "";
+
+        for (const auto& [name, info] : memoryMap)
+        {
+            try
+            {
+                info.proxy->ice_ping();
+                result.proxies[name] = info.proxy;
+            }
+            catch (const Ice::Exception&)
+            {
+                ;
+            }
+        }
+
+        return result;
+    }
+
+
     armem::data::ResolveMemoryNameResult MemoryNameSystem::resolveMemoryName(const armem::data::ResolveMemoryNameInput& input)
     {
         armem::data::ResolveMemoryNameResult result;
diff --git a/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.h b/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.h
index 891e78f4acf072e49670336b3d95afb4b766695a..7372246d7e8059787f97f117931830d12c9dc082 100644
--- a/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.h
+++ b/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.h
@@ -35,6 +35,8 @@ namespace armarx::armem::mns
          */
         data::RemoveMemoryResult removeMemory(const data::RemoveMemoryInput& input);
 
+        data::GetAllRegisteredMemoriesResult getAllRegisteredMemories();
+
         /**
          * @brief Gets a memory entry, if it is available.
          */
diff --git a/source/RobotAPI/libraries/armem/util/util.cpp b/source/RobotAPI/libraries/armem/util/util.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..34f0e2f56d9d47ea7db8b54e198e6faa9d0b25d9
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/util/util.cpp
@@ -0,0 +1,3 @@
+#include "util.h"
+
+// intentionally left blank
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem/util/util.h b/source/RobotAPI/libraries/armem/util/util.h
new file mode 100644
index 0000000000000000000000000000000000000000..4fa457ab679a0f970974101a53ba04a92b3fc241
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/util/util.h
@@ -0,0 +1,156 @@
+/*
+ * 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    RobotComponents::ArmarXObjects::
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include "ArmarXCore/core/logging/Logging.h"
+#include <vector>
+#include <optional>
+
+#include <RobotAPI/libraries/armem/core/Entity.h>
+#include <RobotAPI/libraries/armem/core/EntityInstance.h>
+#include <RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/AronCppClass.h>
+
+namespace armarx::armem
+{
+
+    /**
+     * @brief Tries to cast a armem::EntityInstance to AronClass
+     *
+     * @tparam AronClass class name. Needs to be derived from armarx::aron::cppcodegenerator::AronCppClass
+     * @param item
+     * @return std::optional<AronClass>
+     */
+    template <typename AronClass>
+    std::optional<AronClass> tryCast(const EntityInstance& item)
+    {
+        static_assert(std::is_base_of<armarx::aron::cppcodegenerator::AronCppClass,
+                      AronClass>::value);
+
+        try
+        {
+            AronClass t;
+            t.fromAron(item.data());
+            return t;
+        }
+        catch (const armarx::aron::error::AronException&)
+        {
+            return std::nullopt;
+        }
+    }
+
+    /**
+     * @brief Returns all entities that can be cast to AronClass
+     *
+     * @tparam AronClass class name. Needs to be derived from armarx::aron::cppcodegenerator::AronCppClass
+     * @param entities collection of entities
+     * @return std::vector<AronClass>
+     */
+    template <typename AronClass>
+    std::vector<AronClass>
+    allOfType(const std::map<std::string, Entity>& entities)
+    {
+        static_assert(std::is_base_of<armarx::aron::cppcodegenerator::AronCppClass,
+                      AronClass>::value);
+
+        std::vector<AronClass> outV;
+
+        // loop over all entities and their snapshots
+        for (const auto &[s, entity] : entities)
+        {
+            for (const auto &[ss, entitySnapshot] : entity.history)
+            {
+                for (const auto& entityInstance : entitySnapshot.instances)
+                {
+                    const auto o = tryCast<AronClass>(entityInstance);
+
+                    if (o)
+                    {
+                        outV.push_back(*o);
+                    }
+                }
+            }
+        }
+
+        return outV;
+    }
+
+    /**
+     * @brief filter + transform for entities.
+     *
+     * Can be used instead of
+     *
+     *      std::vector<Bar> ret;
+     *
+     *      const auto allOf = allOfType<Foo>(entities);
+     *      std::transform(allOf.begin(), allOf.end(), std::back_inserter(ret), pred)
+     *
+     * This function has the benefit that the transform function will be applied directly.
+     * No intermediate vector has to be created (e.g. "allOf" in the example above).
+     *
+     * @tparam AronClass class name. Needs to be derived from armarx::aron::cppcodegenerator::AronCppClass
+     * @param entities collection of entities
+     * @param pred binary predicate function, applied to all entity instances
+     * @return vector of "pred"-transformed elements that can be cast to AronClass
+     */
+    template <typename AronClass>
+    auto transformAllOfType(const std::map<std::string, Entity>& entities,
+                            auto pred) -> std::vector<decltype(pred(AronClass()))>
+    {
+        static_assert(std::is_base_of<armarx::aron::cppcodegenerator::AronCppClass,
+                      AronClass>::value);
+
+        std::vector<decltype(pred(AronClass()))> outV;
+
+        if (entities.empty())
+        {
+            ARMARX_WARNING << "No entities!";
+        }
+
+        // loop over all entities and their snapshots
+        for (const auto &[s, entity] : entities)
+        {
+            if (entity.history.empty())
+            {
+                ARMARX_WARNING << "Empty history for " << s;
+            }
+
+            ARMARX_INFO << "History size: " << entity.history.size();
+
+            for (const auto &[ss, entitySnapshot] : entity.history)
+            {
+                for (const auto& entityInstance : entitySnapshot.instances)
+                {
+                    const auto o = tryCast<AronClass>(entityInstance);
+
+                    if (o)
+                    {
+                        outV.push_back(pred(*o));
+                    }
+                }
+            }
+        }
+
+        return outV;
+    }
+
+} // namespace armarx::armem
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
index 2cff7aa28476ba530a8b72febb11d563e5101b0b..78097af1a7a40ca0e8c46f1e75d8ce72783e06ab 100644
--- a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
+++ b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
@@ -9,6 +9,8 @@
 #include <ArmarXCore/core/time/TimeUtil.h>
 #include <ArmarXCore/observers/variant/Variant.h>
 
+#include <SimoxUtility/algorithm/get_map_keys_values.h>
+
 #include <QBoxLayout>
 #include <QDialog>
 #include <QCheckBox>
@@ -47,8 +49,8 @@ namespace armarx::armem::gui
         ARMARX_CHECK_NULL(_instanceGroupBox);
 
 
-        connect(this, &This::connected, this, &This::updateMemory);
-        connect(updateWidget, &armem::gui::PeriodicUpdateWidget::update, this, &This::updateMemory);
+        connect(this, &This::connected, this, &This::updateMemories);
+        connect(updateWidget, &armem::gui::PeriodicUpdateWidget::update, this, &This::updateMemories);
 
         connect(this, &This::memoryDataChanged, this, &This::updateMemoryTree);
         connect(memoryGroup->tree(), &armem::gui::MemoryTreeWidget::selectedItemChanged, this, &This::updateInstanceTree);
@@ -64,9 +66,9 @@ namespace armarx::armem::gui
 
     void MemoryViewer::onInit(ManagedIceObject& component)
     {
-        if (memoryName.size() > 0)
+        if (mnsName.size() > 0)
         {
-            component.usingProxy(memoryName);
+            component.usingProxy(mnsName);
         }
         if (debugObserverName.size() > 0)
         {
@@ -78,10 +80,15 @@ namespace armarx::armem::gui
 
     void MemoryViewer::onConnect(ManagedIceObject& component)
     {
-        if (!memoryName.empty())
+        if (!mnsName.empty())
         {
-            component.getProxy(memory, memoryName);
-            memoryReader = armem::client::Reader(memory);
+            component.getProxy(mns, mnsName);
+            auto res = mns->getAllRegisteredMemories();
+            for (auto& [name, proxy] : res.proxies)
+            {
+                armem::client::Reader memoryReader{proxy};
+                memoryReaders[name] = memoryReader;
+            }
         }
         // DebugObserver is optional (check for null on every call)
         if (!debugObserverName.empty())
@@ -101,52 +108,78 @@ namespace armarx::armem::gui
     }
 
 
-    void MemoryViewer::updateMemory()
+    void MemoryViewer::updateMemories()
     {
-        if (!memoryReader)
+        memoryReaders.clear();
+        memoryData.clear();
+
+        for (auto& [name, proxy] : mns->getAllRegisteredMemories().proxies)
         {
-            return;
+            armem::client::Reader memoryReader{proxy};
+            memoryReaders[name] = memoryReader;
         }
 
-        TIMING_START(MemoryQuery);
+        bool dataChanged = false;
+
+        for (auto& [name, reader] : memoryReaders)
         {
-            armem::client::QueryInput input = memoryGroup->queryWidget()->queryInput();
-            armem::client::QueryResult result = memoryReader.query(input);
-            if (result)
+            TIMING_START(MemoryQuery);
+            {
+                armem::client::QueryInput input = memoryGroup->queryWidget()->queryInput();
+                armem::client::QueryResult result = reader.query(input);
+                if (result)
+                {
+                    memoryData[name] = std::move(result.memory);
+                }
+                else
+                {
+                    if (statusLabel)
+                    {
+                        statusLabel->setText(QString::fromStdString(result.errorMessage));
+                    }
+                }
+            }
+            TIMING_END_STREAM(MemoryQuery, ARMARX_VERBOSE);
+
+            if (debugObserver)
             {
-                this->memoryData = std::move(result.memory);
+                debugObserver->setDebugDatafield(Logging::tag.tagName, "Memory Query [ms]", new Variant(MemoryQuery.toMilliSecondsDouble()));
+            }
+
+            if (memoryData[name])
+            {
+                dataChanged = true;
             }
             else
             {
                 if (statusLabel)
                 {
-                    statusLabel->setText(QString::fromStdString(result.errorMessage));
+                    statusLabel->setText("No query result.");
                 }
             }
         }
-        TIMING_END_STREAM(MemoryQuery, ARMARX_VERBOSE);
-
-        if (debugObserver)
-        {
-            debugObserver->setDebugDatafield(Logging::tag.tagName, "Memory Query [ms]", new Variant(MemoryQuery.toMilliSecondsDouble()));
-        }
 
-        if (this->memoryData)
+        if (dataChanged)
         {
             emit memoryDataChanged();
         }
-        else
-        {
-            if (statusLabel)
-            {
-                statusLabel->setText("No query result.");
-            }
-        }
     }
 
+
     void MemoryViewer::updateInstanceTree(const armem::MemoryID& selectedID)
     {
-        if (memoryData)
+        if (memoryData.find(selectedID.memoryName) == memoryData.end())
+        {
+            std::stringstream ss;
+            ss << "Memory name '" << selectedID.memoryName << "' is unknown. Known are: "
+               << simox::alg::get_keys(memoryData);
+            statusLabel->setText(QString::fromStdString(ss.str()));
+            return;
+        }
+
+        const std::optional<armem::Memory>& data = memoryData.at(selectedID.memoryName);
+
+        if (data)
         {
             if (!selectedID.hasEntityName())
             {
@@ -156,7 +189,7 @@ namespace armarx::armem::gui
             const armem::EntitySnapshot* snapshot = nullptr;
             if (!id.hasTimestamp())
             {
-                const armem::Entity& entity = memoryData->getEntity(id);
+                const armem::Entity& entity = data->getEntity(id);
                 if (entity.empty())
                 {
                     return;
@@ -170,7 +203,7 @@ namespace armarx::armem::gui
                 {
                     try
                     {
-                        snapshot = &memoryData->getEntitySnapshot(id);
+                        snapshot = &data->getEntitySnapshot(id);
                     }
                     catch (const armem::error::ArMemError& e)
                     {
@@ -187,19 +220,29 @@ namespace armarx::armem::gui
             }
             if (id.hasInstanceIndex())
             {
-                instanceGroup->view->update(id, *memoryData);
+                instanceGroup->view->update(id, *data);
             }
         }
     }
 
     void MemoryViewer::updateMemoryTree()
     {
-        if (!memoryData)
+        std::map<std::string, const armem::Memory*> convMap;
+        for (auto& [name, data] : memoryData)
+        {
+            if (data.has_value())
+            {
+                convMap[name] = &data.value();
+            }
+        }
+
+        if (convMap.empty())
         {
             return;
         }
+
         TIMING_START(GuiUpdate);
-        memoryGroup->tree()->update(*memoryData);
+        memoryGroup->tree()->update(convMap);
         TIMING_END_STREAM(GuiUpdate, ARMARX_VERBOSE);
 
         if (debugObserver)
@@ -209,34 +252,29 @@ namespace armarx::armem::gui
     }
 
 
-    const static std::string CONFIG_KEY_MEMORY = "MemoryViewer.MemoryName";
+    const static std::string CONFIG_KEY_MEMORY = "MemoryViewer.MemoryNameSystem";
     const static std::string CONFIG_KEY_DEBUG_OBSERVER = "MemoryViewer.DebugObserverName";
 
     void MemoryViewer::loadSettings(QSettings* settings)
     {
-        memoryName = settings->value(QString::fromStdString(CONFIG_KEY_MEMORY), "Memory").toString().toStdString();
+        mnsName = settings->value(QString::fromStdString(CONFIG_KEY_MEMORY), "ArMemMemoryNameSystem").toString().toStdString();
         debugObserverName = settings->value(QString::fromStdString(CONFIG_KEY_DEBUG_OBSERVER), "DebugObserver").toString().toStdString();
     }
     void MemoryViewer::saveSettings(QSettings* settings)
     {
-        settings->setValue(QString::fromStdString(CONFIG_KEY_MEMORY), QString::fromStdString(memoryName));
+        settings->setValue(QString::fromStdString(CONFIG_KEY_MEMORY), QString::fromStdString(mnsName));
         settings->setValue(QString::fromStdString(CONFIG_KEY_DEBUG_OBSERVER), QString::fromStdString(debugObserverName));
     }
 
     void MemoryViewer::writeConfigDialog(SimpleConfigDialog* dialog)
     {
-        dialog->addProxyFinder<armem::server::MemoryInterfacePrx>({CONFIG_KEY_MEMORY, "Memory", "*Memory"});
+        dialog->addProxyFinder<armarx::armem::mns::MemoryNameSystemInterfacePrx>({CONFIG_KEY_MEMORY, "ArMemMemoryNameSystem", "*"});
         dialog->addProxyFinder<armarx::DebugObserverInterfacePrx>({CONFIG_KEY_DEBUG_OBSERVER, "Debug Observer", "DebugObserver"});
     }
     void MemoryViewer::readConfigDialog(SimpleConfigDialog* dialog)
     {
-        memoryName = dialog->getProxyName(CONFIG_KEY_MEMORY);
+        mnsName = dialog->getProxyName(CONFIG_KEY_MEMORY);
         debugObserverName = dialog->getProxyName(CONFIG_KEY_DEBUG_OBSERVER);
     }
 
 }
-
-
-
-
-
diff --git a/source/RobotAPI/libraries/armem_gui/MemoryViewer.h b/source/RobotAPI/libraries/armem_gui/MemoryViewer.h
index df66ad86fa603443119744d0ee152f5f126e805a..5c8f4b2f182f798a3c076a89e6a30ff24d10050c 100644
--- a/source/RobotAPI/libraries/armem_gui/MemoryViewer.h
+++ b/source/RobotAPI/libraries/armem_gui/MemoryViewer.h
@@ -7,7 +7,7 @@
 #include <ArmarXCore/interface/observers/ObserverInterface.h>
 #include <ArmarXCore/core/logging/Logging.h>
 
-#include <RobotAPI/interface/armem/server/MemoryInterface.h>
+#include <RobotAPI/interface/armem/mns/MemoryNameSystemInterface.h>
 #include <RobotAPI/libraries/armem/client/Reader.h>
 #include <RobotAPI/libraries/armem_gui/lifecycle.h>
 #include <RobotAPI/libraries/armem_gui/instance/GroupBox.h>
@@ -15,7 +15,6 @@
 #include <RobotAPI/libraries/armem_gui/PeriodicUpdateWidget.h>
 
 
-
 class QBoxLayout;
 class QDialog;
 class QGroupBox;
@@ -63,7 +62,7 @@ namespace armarx::armem::gui
 
     public slots:
 
-        void updateMemory();
+        void updateMemories();
         void updateInstanceTree(const armem::MemoryID& selectedID);
 
 
@@ -95,11 +94,11 @@ namespace armarx::armem::gui
 
     public:
 
-        std::string memoryName;
-        armem::server::MemoryInterfacePrx memory;
-        armem::client::Reader memoryReader;
+        std::string mnsName;
+        armem::mns::MemoryNameSystemInterfacePrx mns;
 
-        std::optional<armem::Memory> memoryData;
+        std::map<std::string, armem::client::Reader> memoryReaders;
+        std::map<std::string, std::optional<armem::Memory>> memoryData;
 
 
         QLayout* updateWidgetLayout;
@@ -121,5 +120,3 @@ namespace armarx::armem::gui
     };
 
 }
-
-
diff --git a/source/RobotAPI/libraries/armem_robot_localization/MemoryConnector.cpp b/source/RobotAPI/libraries/armem_robot_localization/MemoryConnector.cpp
index c66b568c89a28e714bffbe4df1fcba00ccdfd666..4fadf6f65ebb0ade9b91d49d36860bf6e9b0ff64 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/MemoryConnector.cpp
+++ b/source/RobotAPI/libraries/armem_robot_localization/MemoryConnector.cpp
@@ -1,20 +1,24 @@
 #include "MemoryConnector.h"
 
 #include <ArmarXCore/core/ManagedIceObject.h>
+
 #include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
-namespace armarx
+namespace armarx::armem
 {
 
     MemoryConnector::MemoryConnector(ManagedIceObject& component) : component(component) {}
 
+    MemoryConnector::~MemoryConnector() = default;
+
     void MemoryConnector::registerPropertyDefinitions(PropertyDefinitionsPtr& def)
     {
-        ARMARX_INFO << "Memory connector: registerPropertyDefinitions";
-
         const std::string prefix = getPropertyPrefix();
 
+        ARMARX_INFO << "Memory connector: registerPropertyDefinitions with prefix " << prefix;
+
+
         def->component(memoryNameSystem, "ArMemMemoryNameSystem", prefix + "ArMemMemoryNameSystem");
     }
 
@@ -40,4 +44,10 @@ namespace armarx
         return result;
     }
 
-} // namespace armarx
+    const std::string& MemoryConnector::getPropertyPrefix() const
+    {
+        return propertyPrefix;
+    }
+
+
+} // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem_robot_localization/MemoryConnector.h b/source/RobotAPI/libraries/armem_robot_localization/MemoryConnector.h
index 1af5ec5d889f520c62e0dc5e4d89948cba268d3d..d3a9f288da15cefb71eb8bf5ecabf9bf7e250c4b 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/MemoryConnector.h
+++ b/source/RobotAPI/libraries/armem_robot_localization/MemoryConnector.h
@@ -30,17 +30,25 @@
 
 namespace armarx
 {
-
     class ManagedIceObject;
+}
 
-    // TODO(fabian.reister): add
-    // class PropertyDefinitionsPtr;
+namespace armarx::armem
+{
 
+    /**
+     * @brief The MemoryConnector class simplifies connecting to the ArMem memory.
+     *
+     * Use this as the base class of any class that needs to connect to the memory.
+     *
+     *
+     */
     class MemoryConnector
     {
 
     public:
         MemoryConnector(ManagedIceObject& component);
+        virtual ~MemoryConnector();
 
     protected:
         armem::data::WaitForMemoryResult useMemory(const std::string& memoryName);
@@ -48,15 +56,14 @@ namespace armarx
 
         void waitForMemory();
 
-        virtual std::string getPropertyPrefix()
-        {
-            return "mem.";
-        }
+        virtual const std::string& getPropertyPrefix() const;
 
     private:
         ManagedIceObject& component;
 
         armem::mns::MemoryNameSystemInterfacePrx memoryNameSystem;
+
+        const std::string propertyPrefix;
     };
 
-} // namespace armarx
\ No newline at end of file
+} // namespace armarx::armem
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_localization/TransformInterfaces.h b/source/RobotAPI/libraries/armem_robot_localization/TransformInterfaces.h
index cb353f57d73561dfdda4a96ce60137e988e5db09..6962593814414267635efc425637266c7fbcd34a 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/TransformInterfaces.h
+++ b/source/RobotAPI/libraries/armem_robot_localization/TransformInterfaces.h
@@ -46,60 +46,66 @@ namespace armarx
         Eigen::Affine3f transform = Eigen::Affine3f::Identity();
     };
 
-    struct TransformResult
+    namespace armem
     {
-        Transform transform;
 
-        enum class Status
+        struct TransformResult
         {
-            success,
-            errorLookupIntoFuture,
-            errorFrameNotAvailable
-        } status;
+            Transform transform;
 
-        explicit operator bool() const
-        {
-            return status == Status::success;
-        }
+            enum class Status
+            {
+                Success,
+                ErrorLookupIntoFuture,
+                ErrorFrameNotAvailable
+            } status;
 
-        std::string errorMessage = "";
-    };
+            explicit operator bool() const
+            {
+                return status == Status::Success;
+            }
 
-    struct TransformQuery
-    {
-        TransformHeader header;
+            std::string errorMessage = "";
+        };
 
-        // bool exact;
-    };
+        struct TransformQuery
+        {
+            TransformHeader header;
 
-    class TransformInterface
-    {
-    public:
-        virtual ~TransformInterface() = default;
+            // bool exact;
+        };
 
-        virtual void registerPropertyDefinitions(PropertyDefinitionsPtr& def) = 0;
-        virtual void connect()                                                = 0;
-    };
+        class TransformInterface
+        {
+        public:
+            virtual ~TransformInterface() = default;
 
-    class TransformReaderInterface : virtual public TransformInterface
-    {
-    public:
-        virtual ~TransformReaderInterface() = default;
+            virtual void registerPropertyDefinitions(PropertyDefinitionsPtr& def) = 0;
+            virtual void connect() = 0;
+        };
 
-        virtual TransformResult getGlobalPose(const std::string& agentName,
-                                              const std::string& robotRootFrame,
-                                              const std::int64_t& timestamp) const = 0;
+        class TransformReaderInterface : virtual public TransformInterface
+        {
+        public:
+            virtual ~TransformReaderInterface() = default;
 
-        virtual TransformResult lookupTransform(const TransformQuery& query) const = 0;
-        // waitForTransform()
-    };
+            virtual TransformResult
+            getGlobalPose(const std::string& agentName, const std::string& robotRootFrame,
+                          const std::int64_t& timestamp) const = 0;
 
-    class TransformWriterInterface : virtual public TransformInterface
-    {
-    public:
-        ~TransformWriterInterface() override = default;
+            virtual TransformResult
+            lookupTransform(const TransformQuery& query) const = 0;
+            // waitForTransform()
+        };
 
-        virtual bool commitTransform(const Transform& transform) = 0;
-    };
+        class TransformWriterInterface : virtual public TransformInterface
+        {
+        public:
+            ~TransformWriterInterface() override = default;
+
+            virtual bool commitTransform(const Transform& transform) = 0;
+        };
+
+    } // namespace armem
 
 } // namespace armarx
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_localization/TransformReader.cpp b/source/RobotAPI/libraries/armem_robot_localization/TransformReader.cpp
index 80b242b1204a28b255283939cd64588f1c251c01..b14f1a711e490c2bcae4eca0ca81976ca888a6ea 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/TransformReader.cpp
+++ b/source/RobotAPI/libraries/armem_robot_localization/TransformReader.cpp
@@ -56,7 +56,7 @@
 #include <RobotAPI/libraries/armem_robot_localization/aron_conversions.h>
 #include <RobotAPI/libraries/armem_robot_localization/aron/Transform.aron.generated.h>
 
-namespace armarx
+namespace armarx::armem
 {
 
     TransformReader::TransformReader(ManagedIceObject& component) : MemoryConnector(component) {}
@@ -65,7 +65,7 @@ namespace armarx
 
     void TransformReader::registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def)
     {
-        ARMARX_INFO << "TransformReader: registerPropertyDefinitions";
+        ARMARX_DEBUG << "TransformReader: registerPropertyDefinitions";
         MemoryConnector::registerPropertyDefinitions(def);
 
         const std::string prefix = getPropertyPrefix();
@@ -131,7 +131,7 @@ namespace armarx
     std::vector<std::string> TransformReader::buildTransformChain(const armem::Memory& memory,
             const TransformQuery& query) const
     {
-        ARMARX_INFO << "Building transform chain";
+        ARMARX_DEBUG << "Building transform chain";
 
         auto join = [](const std::string & parentFrame, const std::string & frame)
         {
@@ -229,17 +229,17 @@ namespace armarx
     {
         ARMARX_TRACE;
 
-        ARMARX_INFO << "Entering";
+        ARMARX_DEBUG << "Entering";
 
 
         ARMARX_CHECK(not queue.empty())
                 << "The queue has to contain at least two items to perform a lookup";
 
 
-        ARMARX_INFO << "Entering ... "
-                    << "Q front " << queue.front().header.timestamp << "  "
-                    << "Q back " << queue.back().header.timestamp << "  "
-                    << "query timestamp " << timestamp;
+        ARMARX_DEBUG << "Entering ... "
+                     << "Q front " << queue.front().header.timestamp << "  "
+                     << "Q back " << queue.back().header.timestamp << "  "
+                     << "query timestamp " << timestamp;
 
         // TODO(fabian.reister): sort queue.
 
@@ -247,26 +247,26 @@ namespace armarx
         ARMARX_CHECK(queue.back().header.timestamp > timestamp)
                 << "Cannot perform lookup into the future!";
 
-        // ARMARX_INFO << "Entering 1.5 " << queue.front().timestamp << "  " << timestamp;
+        // ARMARX_DEBUG << "Entering 1.5 " << queue.front().timestamp << "  " << timestamp;
         ARMARX_CHECK(queue.front().header.timestamp < timestamp)
                 << "Cannot perform lookup. Timestamp too old";
         // => now we know that there is an element right after and before the timestamp within our queue
 
-        ARMARX_INFO << "Entering 2";
+        ARMARX_DEBUG << "Entering 2";
 
         const auto poseNextIt = findFirstElementAfter(queue, timestamp);
 
-        ARMARX_INFO << "it ari";
+        ARMARX_DEBUG << "it ari";
 
         const auto posePreIt = poseNextIt - 1;
 
-        ARMARX_INFO << "deref";
+        ARMARX_DEBUG << "deref";
 
         // the time fraction [0..1] of the lookup wrt to posePre and poseNext
         const float t = static_cast<float>(timestamp - posePreIt->header.timestamp) /
                         (poseNextIt->header.timestamp - posePreIt->header.timestamp);
 
-        ARMARX_INFO << "interpolate";
+        ARMARX_DEBUG << "interpolate";
 
         return simox::math::interpolatePose(posePreIt->transform, poseNextIt->transform, t);
     }
@@ -300,13 +300,16 @@ namespace armarx
             return convertEntityToTransform(entity.getInstance(0));
         });
 
-        ARMARX_INFO << "obtaining transform";
+        ARMARX_DEBUG << "obtaining transform";
 
         if (transforms.size() > 1)
         {
-            ARMARX_INFO << "More than one snapshots received: " << transforms.size();
+            // TODO(fabian.reister): remove
+            return transforms.front().transform;
+
+            ARMARX_DEBUG << "More than one snapshots received: " << transforms.size();
             const auto p = interpolateTransform(transforms, timestamp);
-            ARMARX_INFO << "Done interpolating transform";
+            ARMARX_DEBUG << "Done interpolating transform";
             return p;
         }
 
@@ -314,12 +317,12 @@ namespace armarx
         // accept this to fail (will raise armem::error::MissingEntry)
         if (transforms.empty())
         {
-            ARMARX_INFO << "empty transform";
+            ARMARX_DEBUG << "empty transform";
 
             throw armem::error::MissingEntry("foo", "bar", "foo2", "bar2");
         }
 
-        ARMARX_INFO << "single transform";
+        ARMARX_DEBUG << "single transform";
 
 
         return transforms.front().transform;
@@ -377,7 +380,7 @@ namespace armarx
 
         const auto durationEpsilon = IceUtil::Time::milliSeconds(100);
 
-        ARMARX_INFO << "Looking up transform at timestamp " << timestamp;
+        ARMARX_DEBUG << "Looking up transform at timestamp " << timestamp;
 
         // Query all entities from provider.
         armem::client::query::Builder qb;
@@ -395,7 +398,7 @@ namespace armarx
 
         const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
 
-        ARMARX_INFO << "Lookup result in reader: " << qResult;
+        ARMARX_DEBUG << "Lookup result in reader: " << qResult;
 
         if (not qResult.success)
         {
@@ -403,7 +406,7 @@ namespace armarx
                 {
                     .header = query.header,
                 },
-                .status       = TransformResult::Status::errorFrameNotAvailable,
+                .status       = TransformResult::Status::ErrorFrameNotAvailable,
                 .errorMessage = "Error in tf lookup '" + query.header.parentFrame + " -> " +
                 query.header.frame + "' : " + qResult.errorMessage};
         }
@@ -413,7 +416,7 @@ namespace armarx
         if (tfChain.empty())
         {
             return {.transform    = {.header = query.header},
-                    .status       = TransformResult::Status::errorFrameNotAvailable,
+                    .status       = TransformResult::Status::ErrorFrameNotAvailable,
                     .errorMessage = "Cannot create tf lookup chain '" +
                                     query.header.parentFrame + " -> " + query.header.frame +
                                     "'"};
@@ -426,7 +429,7 @@ namespace armarx
         {
             ARMARX_WARNING << "No transform available.";
             return {.transform    = {.header = query.header},
-                    .status       = TransformResult::Status::errorFrameNotAvailable,
+                    .status       = TransformResult::Status::ErrorFrameNotAvailable,
                     .errorMessage = "Error in TF loookup:  '" +
                                     query.header.parentFrame + " -> " + query.header.frame +
                                     "'. No memory data in time range."};
@@ -437,10 +440,10 @@ namespace armarx
                                           Eigen::Affine3f::Identity(),
                                           std::multiplies<>());
 
-        ARMARX_INFO << "Found valid transform";
+        ARMARX_DEBUG << "Found valid transform";
 
         return {.transform = {.header = query.header, .transform = transform},
-                .status    = TransformResult::Status::success};
+                .status    = TransformResult::Status::Success};
     }
 
-} // namespace armarx
+} // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem_robot_localization/TransformReader.h b/source/RobotAPI/libraries/armem_robot_localization/TransformReader.h
index 458ce5d89a7ec56a5f34f3d8b49a608158e69fde..061499f7b69fd1a8a1b372efe590229f5722c73e 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/TransformReader.h
+++ b/source/RobotAPI/libraries/armem_robot_localization/TransformReader.h
@@ -27,7 +27,7 @@
 #include "MemoryConnector.h"
 #include "TransformInterfaces.h"
 
-namespace armarx
+namespace armarx::armem
 {
     /**
     * @defgroup Component-ExampleClient ExampleClient
@@ -41,8 +41,8 @@ namespace armarx
     * Detailed description of class ExampleClient.
     */
     class TransformReader :
-        virtual public armarx::TransformReaderInterface,
-        virtual public armarx::MemoryConnector
+        virtual public ::armarx::armem::TransformReaderInterface,
+        virtual public ::armarx::armem::MemoryConnector
     {
     public:
         TransformReader(ManagedIceObject& component);
@@ -56,11 +56,11 @@ namespace armarx
                                       const std::int64_t& timestamp) const override;
         TransformResult lookupTransform(const TransformQuery& query) const override;
 
-        void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def) override;
+        void registerPropertyDefinitions(::armarx::PropertyDefinitionsPtr& def) override;
 
-        std::string getPropertyPrefix() override
+        const std::string& getPropertyPrefix() const override
         {
-            return "mem.read.";
+            return propertyPrefix;
         }
 
     private:
@@ -82,5 +82,8 @@ namespace armarx
             std::string memoryName             = "RobotState";
             std::string localizationMemoryName = "Localization";
         } properties;
+
+
+        const std::string propertyPrefix = "mem.localization.read.";
     };
-} // namespace armarx
+} // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem_robot_localization/TransformWriter.cpp b/source/RobotAPI/libraries/armem_robot_localization/TransformWriter.cpp
index 55100c09eeee08293fac3ca455a04ba31bcbeaea..2db61f978e45fb2f8582532454d6423026b9fcfe 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/TransformWriter.cpp
+++ b/source/RobotAPI/libraries/armem_robot_localization/TransformWriter.cpp
@@ -49,7 +49,7 @@
 #include "aron_conversions.h"
 
 
-namespace armarx
+namespace armarx::armem
 {
 
     TransformWriter::TransformWriter(ManagedIceObject& component) : MemoryConnector(component) {}
@@ -58,7 +58,7 @@ namespace armarx
 
     void TransformWriter::registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def)
     {
-        ARMARX_INFO << "TransformWriter: registerPropertyDefinitions";
+        ARMARX_DEBUG << "TransformWriter: registerPropertyDefinitions";
 
         MemoryConnector::registerPropertyDefinitions(def);
 
@@ -121,10 +121,10 @@ namespace armarx
         update.instancesData = {aronTransform.toAron()};
         update.timeCreated = IceUtil::Time::microSeconds(aronTransform.header.timestamp);
 
-        ARMARX_INFO << "Committing " << update << " at time " << IceUtil::Time::microSeconds(transform.header.timestamp);
+        ARMARX_DEBUG << "Committing " << update << " at time " << IceUtil::Time::microSeconds(transform.header.timestamp);
         armem::EntityUpdateResult updateResult = memoryWriter.commit(update);
 
-        ARMARX_INFO << updateResult;
+        ARMARX_DEBUG << updateResult;
 
         if (not updateResult.success)
         {
@@ -134,4 +134,10 @@ namespace armarx
         return updateResult.success;
     }
 
-} // namespace armarx
+    const std::string& TransformWriter::getPropertyPrefix() const
+    {
+        return propertyPrefix;
+    }
+
+
+} // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem_robot_localization/TransformWriter.h b/source/RobotAPI/libraries/armem_robot_localization/TransformWriter.h
index cc7be8737647cd86a19109ab77da3b5ee2ea2afc..2804fbc53e7a0f61c937dc0a1b6c65d558196e1c 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/TransformWriter.h
+++ b/source/RobotAPI/libraries/armem_robot_localization/TransformWriter.h
@@ -22,13 +22,14 @@
 
 #pragma once
 
-#include <RobotAPI/libraries/armem/client/Writer.h>
 #include <mutex>
 
+#include <RobotAPI/libraries/armem/client/Writer.h>
+
 #include "MemoryConnector.h"
 #include "TransformInterfaces.h"
 
-namespace armarx
+namespace armarx::armem
 {
 
     /**
@@ -43,8 +44,8 @@ namespace armarx
     * Detailed description of class ExampleClient.
     */
     class TransformWriter :
-        virtual public armarx::TransformWriterInterface,
-        virtual public armarx::MemoryConnector
+        virtual public ::armarx::armem::TransformWriterInterface,
+        virtual public ::armarx::armem::MemoryConnector
     {
     public:
         TransformWriter(ManagedIceObject& component);
@@ -60,10 +61,7 @@ namespace armarx
 
         bool commitTransform(const Transform& transform) override;
 
-        std::string getPropertyPrefix() override
-        {
-            return "mem.write.";
-        }
+        const std::string& getPropertyPrefix() const override;
 
     private:
         armem::client::Writer memoryWriter;
@@ -76,5 +74,7 @@ namespace armarx
         } properties;
 
         std::mutex memoryWriterMutex;
+
+        const std::string propertyPrefix = "mem.localization.write.";
     };
-} // namespace armarx
+} // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem_robot_localization/aron_conversions.h b/source/RobotAPI/libraries/armem_robot_localization/aron_conversions.h
index bca16f71ea33e944fdbf77de9751361895882e33..6a5379fe759f73fd03ad7e274a9a2211ba89d846 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/aron_conversions.h
+++ b/source/RobotAPI/libraries/armem_robot_localization/aron_conversions.h
@@ -8,7 +8,7 @@ namespace armarx
     namespace aron
     {
         struct Transform;
-    }
+    } // namespace aron
 
     void fromAron(const aron::Transform& aronTransform, Transform& transform);
     void toAron(const Transform& transform, aron::Transform& aronTransform);
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/CMakeLists.txt b/source/RobotAPI/libraries/armem_robot_mapping/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5712d4c15f338783ac913f3416d6b8fcdb900003
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_mapping/CMakeLists.txt
@@ -0,0 +1,36 @@
+set(LIB_NAME armem_robot_mapping)
+
+armarx_component_set_name("${LIB_NAME}")
+armarx_set_target("Library: ${LIB_NAME}")
+
+armarx_add_library(
+    LIBS 
+        # ArmarX
+        ArmarXCore 
+        # This package
+        RobotAPICore 
+        RobotAPI::libraries::armem
+        # TODO(fabian.reister): remove this dependency!
+        RobotAPI::armem_robot_localization
+        # System / External
+        Eigen3::Eigen
+    HEADERS
+        ./aron_conversions.h
+        ./MappingDataWriter.h
+        ./MappingDataReader.h
+    SOURCES
+        ./aron_conversions.cpp
+        ./MappingDataWriter.cpp
+        ./MappingDataReader.cpp
+)
+
+
+armarx_enable_aron_file_generation_for_target(
+    TARGET_NAME
+        "${LIB_NAME}"
+    ARON_FILES
+        aron/LaserScan.xml
+)
+
+
+add_library(RobotAPI::armem_robot_mapping ALIAS armem_robot_mapping)
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.cpp b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..aae0106dab35ac2252e90f78ee5dd79a37c9188c
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.cpp
@@ -0,0 +1,208 @@
+#include "MappingDataReader.h"
+
+#include <cstring>
+#include <vector>
+#include <algorithm>
+#include <map>
+#include <optional>
+#include <ostream>
+#include <type_traits>
+#include <utility>
+
+#include <IceUtil/Time.h>
+#include <IceUtil/Handle.h>
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/logging/LogSender.h>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include <SimoxUtility/algorithm/get_map_keys_values.h>
+
+#include <RobotAPI/libraries/armem_robot_localization/MemoryConnector.h>
+#include <RobotAPI/libraries/armem/client/Query.h>
+#include <RobotAPI/libraries/armem/client/Reader.h>
+#include <RobotAPI/libraries/armem/client/query/Builder.h>
+#include <RobotAPI/libraries/armem/client/query/selectors.h>
+#include <RobotAPI/libraries/armem/core/CoreSegment.h>
+#include <RobotAPI/libraries/armem/core/Memory.h>
+#include <RobotAPI/libraries/armem/core/ProviderSegment.h>
+#include <RobotAPI/libraries/aron/core/Exception.h>
+#include <RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.h>
+#include <RobotAPI/interface/armem/mns/MemoryNameSystemInterface.h>
+#include <RobotAPI/interface/armem/server/ReadingMemoryInterface.h>
+#include <RobotAPI/interface/units/LaserScannerUnit.h>
+#include <RobotAPI/libraries/armem/core/EntityInstance.h>
+#include <RobotAPI/libraries/armem/util/util.h>
+#include <RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot_mapping/aron_conversions.h>
+#include <RobotAPI/libraries/armem_robot_mapping/types.h>
+
+namespace armarx::armem
+{
+    class Entity;
+}  // namespace armarx
+
+namespace armarx::armem
+{
+
+    MappingDataReader::MappingDataReader(ManagedIceObject& component)
+        : armarx::armem::MemoryConnector(component) {}
+
+    MappingDataReader::~MappingDataReader() = default;
+
+    void MappingDataReader::registerPropertyDefinitions(
+        armarx::PropertyDefinitionsPtr& def)
+    {
+        ARMARX_DEBUG << "TransformReader: registerPropertyDefinitions";
+        MemoryConnector::registerPropertyDefinitions(def);
+
+        const std::string prefix = getPropertyPrefix();
+
+        def->optional(properties.mappingMemoryName, prefix + "MappingMemoryName",
+                      "Name of the mapping memory core segment to use.");
+
+        def->optional(properties.memoryName, prefix + "MemoryName");
+    }
+
+    void MappingDataReader::connect()
+    {
+        // Wait for the memory to become available and add it as dependency.
+        ARMARX_IMPORTANT << "TransformReader: Waiting for memory '"
+                         << properties.memoryName << "' ...";
+        auto result = useMemory(properties.memoryName);
+        if (not result.success)
+        {
+            ARMARX_ERROR << result.errorMessage;
+            return;
+        }
+
+        ARMARX_IMPORTANT << "TransformReader: Connected to memory '"
+                         << properties.memoryName;
+
+        memoryReader.setReadingMemory(result.proxy);
+    }
+
+    armem::client::query::Builder
+    MappingDataReader::buildQuery(const Query& query) const
+    {
+        armem::client::query::Builder qb;
+
+        ARMARX_INFO << "Query for agent: " << query.agent
+                    << " memory name: " << properties.mappingMemoryName;
+
+        if (query.sensorList.empty()) // all sensors
+        {
+            // clang-format off
+            qb
+            .coreSegments().withName(properties.mappingMemoryName)
+            .providerSegments().withName(query.agent)
+            .entities().all()
+            .snapshots().timeRange(query.timeRange.min, query.timeRange.max);
+            // clang-format on
+        }
+        else
+        {
+            // clang-format off
+            qb
+            .coreSegments().withName(properties.mappingMemoryName)
+            .providerSegments().withName(query.agent)
+            .entities().withNames(query.sensorList)
+            .snapshots().timeRange(query.timeRange.min,query.timeRange.max);
+            // clang-format on
+        }
+
+        return qb;
+
+    }
+
+    std::vector<LaserScanStamped> asLaserScans(const std::map<std::string, Entity>& entities)
+    {
+        std::vector<LaserScanStamped> outV;
+
+        if (entities.empty())
+        {
+            ARMARX_WARNING << "No entities!";
+        }
+
+        const auto convert = [](const arondto::LaserScanStamped & aronLaserScanStamped, const EntityInstance & ei) -> LaserScanStamped
+        {
+            LaserScanStamped laserScanStamped;
+            fromAron(aronLaserScanStamped, laserScanStamped);
+
+            const auto ndArrayNavigator = aron::datanavigator::NDArrayNavigator::DynamicCast(ei.data()->getElement("scan"));
+
+            ARMARX_CHECK_NOT_NULL(ndArrayNavigator);
+
+            laserScanStamped.data = fromAron<LaserScanStep>(ndArrayNavigator);
+            ARMARX_IMPORTANT << "4";
+
+
+            return laserScanStamped;
+
+        };
+
+        // loop over all entities and their snapshots
+        for (const auto &[s, entity] : entities)
+        {
+            if (entity.history.empty())
+            {
+                ARMARX_WARNING << "Empty history for " << s;
+            }
+
+            ARMARX_INFO << "History size: " << entity.history.size();
+
+            for (const auto &[ss, entitySnapshot] : entity.history)
+            {
+                for (const auto& entityInstance : entitySnapshot.instances)
+                {
+                    const auto o = tryCast<arondto::LaserScanStamped>(entityInstance);
+
+                    if (o)
+                    {
+                        outV.push_back(convert(*o, entityInstance));
+                    }
+                }
+            }
+        }
+
+        return outV;
+    }
+
+    MappingDataReader::Result
+    MappingDataReader::queryData(const Query& query) const
+    {
+        const auto qb = buildQuery(query);
+
+        ARMARX_IMPORTANT << "[MappingDataReader] query ... ";
+
+        const armem::client::QueryResult qResult =
+            memoryReader.query(qb.buildQueryInput());
+
+        ARMARX_DEBUG << "[MappingDataReader] result: " << qResult;
+
+        if (not qResult.success)
+        {
+            ARMARX_WARNING << "Failed to query data from memory: "
+                           << qResult.errorMessage;
+            return {.laserScans = {},
+                    .sensors = {},
+                    .status = Result::Status::Error,
+                    .errorMessage = qResult.errorMessage};
+        }
+
+        // now create result from memory
+        const auto& entities =
+            qResult.memory.getCoreSegment(properties.mappingMemoryName)
+            .getProviderSegment(query.agent)
+            .entities;
+
+        const auto laserScans = asLaserScans(entities);
+        const auto sensors = simox::alg::get_keys(entities);
+
+        return {.laserScans = laserScans,
+                .sensors = sensors,
+                .status = Result::Status::Success,
+                .errorMessage = ""};
+    }
+
+} // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.h b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.h
new file mode 100644
index 0000000000000000000000000000000000000000..359b88fe8550d9b64f066fe942a5c6fda7dce172
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.h
@@ -0,0 +1,129 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
+
+#include <RobotAPI/libraries/armem/client/Reader.h>
+// TODO(fabian.reister): move MemoryConnector to armem library
+#include <RobotAPI/libraries/armem_robot_localization/MemoryConnector.h>
+#include <RobotAPI/libraries/armem/client/query/Builder.h>
+#include <RobotAPI/libraries/armem_robot_mapping/types.h>
+
+
+
+namespace armarx
+{
+    class ManagedIceObject;
+}
+
+namespace armarx::armem
+{
+
+    struct TimeRange
+    {
+        Time min;
+        Time max;
+    };
+
+    /**
+    * @defgroup Component-ExampleClient ExampleClient
+    * @ingroup RobotAPI-Components
+    * A description of the component ExampleClient.
+    *
+    * @class ExampleClient
+    * @ingroup Component-ExampleClient
+    * @brief Brief description of class ExampleClient.
+    *
+    * Detailed description of class ExampleClient.
+    */
+    class MappingDataReader :
+        virtual public armarx::armem::MemoryConnector
+    {
+    public:
+        MappingDataReader(ManagedIceObject& component);
+
+        virtual ~MappingDataReader();
+
+        void connect();
+
+
+        struct Query
+        {
+            std::string agent;
+
+            TimeRange timeRange;
+
+            // if empty, all sensors will be queried
+            std::vector<std::string> sensorList;
+
+        };
+
+        struct Result
+        {
+
+            std::vector<LaserScanStamped> laserScans;
+
+            std::vector<std::string> sensors;
+
+            enum Status
+            {
+                Error,
+                Success
+            } status;
+
+            std::string errorMessage;
+
+        };
+
+        Result queryData(const Query& query) const;
+
+        void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def);
+
+        const std::string& getPropertyPrefix() const override
+        {
+            return propertyPrefix;
+        }
+
+        client::query::Builder buildQuery(const Query& query) const ;
+
+
+    private:
+
+        armem::client::Reader memoryReader;
+
+        // Properties
+        struct Properties
+        {
+            std::string memoryName             = "RobotState";
+            std::string mappingMemoryName = "Mapping";
+        } properties;
+
+
+        const std::string propertyPrefix = "mem.mapping.read.";
+    };
+
+}  // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/MappingDataWriter.cpp b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataWriter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dd0299ece229eaac2fb4f44758fae23f763f612d
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataWriter.cpp
@@ -0,0 +1,99 @@
+#include "MappingDataWriter.h"
+
+#include "RobotAPI/libraries/armem_robot_mapping/aron_conversions.h"
+#include <RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.aron.generated.h>
+
+
+namespace armarx::armem
+{
+
+    MappingDataWriter::MappingDataWriter(ManagedIceObject& component)
+        : MemoryConnector(component) {}
+
+    MappingDataWriter::~MappingDataWriter() = default;
+
+    void MappingDataWriter::registerPropertyDefinitions(
+        armarx::PropertyDefinitionsPtr& def)
+    {
+        ARMARX_DEBUG << "TransformWriter: registerPropertyDefinitions";
+
+        MemoryConnector::registerPropertyDefinitions(def);
+
+        const std::string prefix = getPropertyPrefix();
+
+        def->optional(properties.mappingMemoryName, prefix + "MappingMemoryName",
+                      "Name of the mapping memory core segment to use.");
+
+        def->optional(properties.memoryName, prefix + "MemoryName");
+    }
+
+    void MappingDataWriter::connect()
+    {
+        // Wait for the memory to become available and add it as dependency.
+        ARMARX_IMPORTANT << "MappingDataWriter: Waiting for memory '" << properties.memoryName
+                         << "' ...";
+        auto result = useMemory(properties.memoryName);
+        if (not result.success)
+        {
+            ARMARX_ERROR << result.errorMessage;
+            return;
+        }
+
+        ARMARX_IMPORTANT << "TransformWriter: Connected to memory '" << properties.memoryName;
+
+        memoryWriter.setWritingMemory(result.proxy);
+    }
+
+
+    bool MappingDataWriter::storeSensorData(const LaserScan& laserScan,
+                                            const std::string& frame,
+                                            const std::string& agentName,
+                                            const std::int64_t& timestamp)
+    {
+        std::lock_guard g{memoryWriterMutex};
+
+        const auto result =
+            memoryWriter.addSegment(properties.mappingMemoryName, agentName);
+
+        if (not result.success)
+        {
+            ARMARX_ERROR << result.errorMessage;
+
+            // TODO(fabian.reister): message
+            return false;
+        }
+
+        const auto iceTimestamp = Time::microSeconds(timestamp);
+
+        const auto providerId = armem::MemoryID(result.segmentID);
+        const auto entityID =
+            providerId.withEntityName(frame).withTimestamp(iceTimestamp);
+
+        armem::EntityUpdate update;
+        update.entityID = entityID;
+        update.timeCreated = armem::Time::now();
+
+        arondto::LaserScanStamped aronSensorData;
+        // currently only sets the header
+        toAron(laserScan, iceTimestamp, frame, agentName, aronSensorData);
+
+        auto dict = aronSensorData.toAron();
+        dict->addElement("scan", toAron(laserScan));
+
+        update.instancesData = {dict};
+        update.timeCreated = iceTimestamp;
+
+        ARMARX_DEBUG << "Committing " << update << " at time " << iceTimestamp;
+        armem::EntityUpdateResult updateResult = memoryWriter.commit(update);
+
+        ARMARX_DEBUG << updateResult;
+
+        if (not updateResult.success)
+        {
+            ARMARX_ERROR << updateResult.errorMessage;
+        }
+
+        return updateResult.success;
+    }
+
+} // namespace armarx::armem
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/MappingDataWriter.h b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..5d5f21185ba6bfad4cb319bef81853ef3bd551f5
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataWriter.h
@@ -0,0 +1,88 @@
+/*
+ * 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::
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <RobotAPI/interface/units/LaserScannerUnit.h>
+#include <mutex>
+
+#include <RobotAPI/libraries/armem/client/Writer.h>
+
+// TODO(fabian.reister): move MemoryConnector to armem lib
+#include "RobotAPI/libraries/armem_robot_localization/MemoryConnector.h"
+
+
+namespace armarx::armem
+{
+
+    /**
+    * @defgroup Component-ExampleClient ExampleClient
+    * @ingroup RobotAPI-Components
+    * A description of the component ExampleClient.
+    *
+    * @class ExampleClient
+    * @ingroup Component-ExampleClient
+    * @brief Brief description of class ExampleClient.
+    *
+    * Detailed description of class ExampleClient.
+    */
+    class MappingDataWriter :
+        virtual public ::armarx::armem::MemoryConnector
+    {
+    public:
+        MappingDataWriter(ManagedIceObject& component);
+        virtual ~MappingDataWriter();
+
+        void connect();
+
+        // MappingDataWriterInterface
+        /// to be called in Component::onConnectComponent
+        // void connect() override;
+
+        /// to be called in Component::addPropertyDefinitions
+        void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def) /*override*/;
+
+        bool storeSensorData(const LaserScan& laserScan, const std::string& frame, const std::string& agentName, const std::int64_t& timestamp);
+
+        const std::string& getPropertyPrefix() const override
+        {
+            return propertyPrefix;
+        }
+
+    private:
+        armem::client::Writer memoryWriter;
+
+        // Properties
+        struct Properties
+        {
+            std::string memoryName         = "RobotState";
+            std::string mappingMemoryName  = "Mapping";
+        } properties;
+
+        std::mutex memoryWriterMutex;
+
+
+        const std::string propertyPrefix = "mem.mapping.write.";
+    };
+
+
+} // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.xml b/source/RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.xml
new file mode 100644
index 0000000000000000000000000000000000000000..659df4a1536b0f81b81ba64f77e4049ba42fdd5c
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.xml
@@ -0,0 +1,54 @@
+<!--Some fancy comment -->
+<?xml version="1.0" encoding="UTF-8" ?>
+<AronTypeDefinition>
+    <CodeIncludes>
+    </CodeIncludes>
+    <AronIncludes>
+    </AronIncludes>
+
+    <GenerateTypes>
+
+        <Object name='armarx::arondto::LaserScannerInfo'>
+            <ObjectChild key='device'>
+                <string />
+            </ObjectChild>
+            <ObjectChild key='frame'>
+                <string />
+            </ObjectChild>
+            <ObjectChild key='minAngle'>
+                <string />
+            </ObjectChild>
+            <ObjectChild key='maxAngle'>
+                <string />
+            </ObjectChild>
+            <ObjectChild key='stepSize'>
+                <string />
+            </ObjectChild>
+        </Object>
+
+        <Object name="armarx::arondto::SensorHeader">
+            <ObjectChild key="agent">
+                <string/>
+            </ObjectChild>
+            <ObjectChild key="frame">
+                <string/>
+            </ObjectChild>
+            <ObjectChild key='timestamp'>
+                <Time />
+            </ObjectChild>
+        </Object>
+
+
+        <Object name='armarx::arondto::LaserScanStamped'>
+            <ObjectChild key="header">
+                <armarx::arondto::SensorHeader />
+            </ObjectChild>
+
+            <!-- 
+            <ObjectChild key='data'>
+                <NdArray />
+            </ObjectChild> -->
+        </Object>
+
+    </GenerateTypes>
+</AronTypeDefinition> 
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.cpp b/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..40471a632c66708ecb8085ea63a65acf6013d5a2
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.cpp
@@ -0,0 +1,100 @@
+#include "aron_conversions.h"
+
+#include <algorithm>
+#include <cstdint>
+#include <iterator>
+
+#include <RobotAPI/interface/units/LaserScannerUnit.h>
+#include <RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.aron.generated.h>
+#include <RobotAPI/libraries/aron/converter/common/Converter.h>
+#include <RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.h>
+
+#include "types.h"
+
+
+namespace armarx
+{
+
+    /************ fromAron ************/
+
+    armem::Time timeFromAron(const int64_t timestamp)
+    {
+        return armem::Time::microSeconds(timestamp);
+    }
+
+    SensorHeader fromAron(const arondto::SensorHeader& aronSensorHeader)
+    {
+        
+        return {.agent = aronSensorHeader.agent,
+                .frame = aronSensorHeader.frame,
+                .timestamp = timeFromAron(aronSensorHeader.timestamp)};
+    }
+
+    void fromAron(const arondto::LaserScanStamped& aronLaserScan,
+                  LaserScanStamped& laserScan)
+    {
+        laserScan.header = fromAron(aronLaserScan.header);
+        // laserScan.data = fromAron(aronLaserScan.data);
+    }
+
+    void fromAron(const arondto::LaserScanStamped& aronLaserScan, LaserScan& laserScan,
+                  std::int64_t& timestamp, std::string& frame,
+                  std::string& agentName)
+    {
+        const auto header = fromAron(aronLaserScan.header);
+
+        // laserScan = fromAron(aronLaserScan.data);
+
+        timestamp = header.timestamp.toMicroSeconds();
+        frame = header.frame;
+        agentName = header.agent;
+    }
+
+
+    /************ toAron ************/
+
+
+    // auto toAron(const LaserScan& laserScan, aron::LaserScan& aronLaserScan)
+    // {
+    //     aronLaserScan.scan = toAron(laserScan);
+    // }
+
+    int64_t toAron(const armem::Time& timestamp)
+    {
+        return timestamp.toMicroSeconds();
+    }
+
+    arondto::SensorHeader toAron(const SensorHeader& sensorHeader)
+    {
+        arondto::SensorHeader aronSensorHeader;
+
+        aronSensorHeader.agent = sensorHeader.agent;
+        aronSensorHeader.frame = sensorHeader.frame;
+        aronSensorHeader.timestamp = toAron(sensorHeader.timestamp);
+
+        return aronSensorHeader;
+    }
+
+    void toAron(const LaserScanStamped& laserScanStamped,
+                arondto::LaserScanStamped& aronLaserScanStamped)
+    {
+        aronLaserScanStamped.header = toAron(laserScanStamped.header);
+        // toAron(laserScanStamped.data, aronLaserScanStamped.data);
+    }
+
+    void toAron(const LaserScan& laserScan,
+                const armem::Time& timestamp,
+                const std::string& frame,
+                const std::string& agentName,
+                arondto::LaserScanStamped& aronLaserScanStamped)
+    {
+        const SensorHeader header
+        {
+            .agent = agentName, .frame = frame, .timestamp = timestamp};
+
+        const LaserScanStamped laserScanStamped{.header = header, .data = laserScan};
+
+        toAron(laserScanStamped, aronLaserScanStamped);
+    }
+
+} // namespace armarx
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.h b/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.h
new file mode 100644
index 0000000000000000000000000000000000000000..7e0d690a48da10f3d07290f6bf32281251a877e5
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.h
@@ -0,0 +1,70 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+
+#pragma once
+
+#include <RobotAPI/interface/units/LaserScannerUnit.h>
+#include <RobotAPI/libraries/aron/converter/common/VectorConverter.h>
+#include <RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.h>
+#include <RobotAPI/libraries/armem/core/Time.h>
+
+namespace armarx
+{
+
+    namespace arondto
+    {
+        struct LaserScanStamped;
+    } // namespace aron
+
+    // struct LaserScan;
+    struct LaserScanStamped;
+
+    void fromAron(
+        const arondto::LaserScanStamped& aronLaserScan,
+        LaserScan& laserScan,
+        std::int64_t& timestamp,
+        std::string& frame,
+        std::string& agentName);
+
+
+    template<typename T>
+    auto fromAron(const aron::datanavigator::NDArrayNavigatorPtr& navigator)
+    {
+        return aron::converter::AronVectorConverter::ConvertToVector<T>(navigator);
+    }
+
+    void fromAron(const arondto::LaserScanStamped& aronLaserScan, LaserScanStamped& laserScan);
+
+    void toAron(
+        const LaserScan& laserScan,
+        const armem::Time& timestamp,
+        const std::string& frame,
+        const std::string& agentName,
+        arondto::LaserScanStamped& aronLaserScan);
+
+    inline aron::datanavigator::NDArrayNavigatorPtr toAron(const LaserScan& laserScan)
+    {
+        return aron::datanavigator::NDArrayNavigator::FromVector(laserScan);
+    }
+
+
+} // namespace armarx
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/types.h b/source/RobotAPI/libraries/armem_robot_mapping/types.h
new file mode 100644
index 0000000000000000000000000000000000000000..d822597e103177b0833014d25f0530e25f2b2075
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_mapping/types.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <RobotAPI/libraries/armem/core/Time.h>
+#include <RobotAPI/interface/units/LaserScannerUnit.h>
+
+namespace armarx
+{
+
+    struct SensorHeader
+    {
+        std::string agent;
+        std::string frame;
+        armem::Time timestamp;
+    };
+
+    struct LaserScanStamped
+    {
+        SensorHeader header;
+        LaserScan data;
+    };
+
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/aron/converter/CMakeLists.txt b/source/RobotAPI/libraries/aron/converter/CMakeLists.txt
index 637345f2b3a4792f269dfd1cee0aed7861db323c..a99bfccfd49d736dc8d4c1ff55e41decb06029ee 100644
--- a/source/RobotAPI/libraries/aron/converter/CMakeLists.txt
+++ b/source/RobotAPI/libraries/aron/converter/CMakeLists.txt
@@ -1,4 +1,19 @@
+add_subdirectory(common)
 add_subdirectory(ivt)
 add_subdirectory(pcl)
 add_subdirectory(eigen)
 add_subdirectory(opencv)
+
+
+add_library(AronConverter INTERFACE)
+
+target_link_libraries(AronConverter
+    INTERFACE
+        RobotAPI::aron::converter::common    
+        RobotAPI::aron::converter::ivt    
+        RobotAPI::aron::converter::pcl    
+        RobotAPI::aron::converter::eigen    
+        RobotAPI::aron::converter::opencv    
+)
+
+add_library(RobotAPI::aron::converter ALIAS AronConverter)
diff --git a/source/RobotAPI/libraries/aron/converter/common/CMakeLists.txt b/source/RobotAPI/libraries/aron/converter/common/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ad1ddc3669b4672d4d9a2f9def8cb4643b8d6821
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/converter/common/CMakeLists.txt
@@ -0,0 +1,23 @@
+set(LIB_NAME aroncommonconverter)
+
+armarx_component_set_name("${LIB_NAME}")
+armarx_set_target("Library: ${LIB_NAME}")
+
+set(LIBS
+    aron
+)
+
+set(LIB_FILES
+    Converter.cpp
+    VectorConverter.cpp
+)
+
+set(LIB_HEADERS
+    Converter.h
+    VectorConverter.h
+)
+
+armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}")
+
+
+add_library(RobotAPI::aron::converter::common ALIAS aroncommonconverter)
diff --git a/source/RobotAPI/libraries/aron/converter/common/Converter.cpp b/source/RobotAPI/libraries/aron/converter/common/Converter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c5161e17c00a2ab5dbe0d893a83ef29d46ac7da9
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/converter/common/Converter.cpp
@@ -0,0 +1 @@
+#include "Converter.h"
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/aron/converter/common/Converter.h b/source/RobotAPI/libraries/aron/converter/common/Converter.h
new file mode 100644
index 0000000000000000000000000000000000000000..570344ab618f8a353327a716aaa9ba5f850eaca8
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/converter/common/Converter.h
@@ -0,0 +1,71 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <vector>
+
+namespace armarx::aron
+{
+
+    /**
+     * @brief Converter function for vector of aron elements to plain cpp type
+     *
+     *  You have to provide a converter function for the element with the signature
+     *
+     *      PlainCppType fromAron(const AronType&)
+     * 
+     * @tparam T the aron vector element
+     * @param v the vector of elements
+     * @return the vector of aron elements
+     */
+    template <typename T> 
+    auto fromAron(const std::vector<T>& v) -> std::vector<decltype(fromAron(T()))>
+    {
+        std::vector<decltype(fromAron(T()))> r;
+        r.reserve(v.size());
+
+        std::transform(v.begin(), v.end(), std::back_inserter(r),
+                       [](const T & t)
+        {
+            return fromAron(t);
+        });
+
+        return r;
+    }
+
+
+    template <typename T> auto toAron(const std::vector<T>& v)
+    {
+        std::vector<decltype(toAron(T()))> r;
+        r.reserve(v.size());
+
+        std::transform(v.begin(), v.end(), std::back_inserter(r),
+                       [](const T & t)
+        {
+            return toAron(t);
+        });
+
+        return r;
+    }
+
+} // namespace armarx::aron
diff --git a/source/RobotAPI/libraries/aron/converter/common/VectorConverter.cpp b/source/RobotAPI/libraries/aron/converter/common/VectorConverter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5f5406cc2be80d443623d0d406865b89279ad00e
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/converter/common/VectorConverter.cpp
@@ -0,0 +1 @@
+#include "VectorConverter.h"
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/aron/converter/common/VectorConverter.h b/source/RobotAPI/libraries/aron/converter/common/VectorConverter.h
new file mode 100644
index 0000000000000000000000000000000000000000..17475a3b9df0f39ee10e82443f24e5251db63c58
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/converter/common/VectorConverter.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+// STD/STL
+#include <memory>
+#include <string>
+#include <numeric>
+
+// ArmarX
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include <RobotAPI/interface/aron.h>
+#include <RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.h>
+
+
+namespace armarx::aron::converter
+{
+    class AronVectorConverter
+    {
+    public:
+        AronVectorConverter() = delete;
+       
+        template<typename T>
+        static std::vector<T> ConvertToVector(const datanavigator::NDArrayNavigatorPtr& nav)
+        {
+            ARMARX_CHECK_NOT_NULL(nav);
+
+            const auto& dims = nav->getDimensions();
+
+            if(dims.size() != 2)
+            {
+                throw error::AronException("AronVectorConverter", "ConvertToVector", "The NDArray must have two dimensions.", nav->getPath());
+            }
+            
+            if(dims.at(1) != sizeof(T))
+            {
+                throw error::AronException("AronVectorConverter", "ConvertToVector", "Dimension 1 of the array has to match the element size.", nav->getPath());
+            }
+            
+            const int size = std::accumulate(std::begin(dims), std::end(dims), 1, std::multiplies<>());
+
+            std::vector<T> v(dims.at(0));
+            memcpy(v.data(), nav->getData(), size);
+
+            return v;
+        }
+    };
+
+}  // namespace armarx::aron::converter
diff --git a/source/RobotAPI/libraries/aron/converter/eigen/CMakeLists.txt b/source/RobotAPI/libraries/aron/converter/eigen/CMakeLists.txt
index 44b70e2e88ffe15465aa558cb153d491f8ce62c4..d4f9008ea45cfb34d3a6056e2155907060e672f0 100644
--- a/source/RobotAPI/libraries/aron/converter/eigen/CMakeLists.txt
+++ b/source/RobotAPI/libraries/aron/converter/eigen/CMakeLists.txt
@@ -8,6 +8,7 @@ armarx_build_if(Eigen3_FOUND "Eigen3 not available")
 
 set(LIBS
     aron
+    Eigen3::Eigen
 )
 
 set(LIB_FILES
@@ -20,6 +21,4 @@ set(LIB_HEADERS
 
 armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}")
 
-if(Eigen3_FOUND)
-    include_directories(${Eigen3_INCLUDE_DIR})
-endif()
+add_library(RobotAPI::aron::converter::eigen ALIAS aroneigenconverter)
diff --git a/source/RobotAPI/libraries/aron/converter/ivt/CMakeLists.txt b/source/RobotAPI/libraries/aron/converter/ivt/CMakeLists.txt
index a7651058d79736edb0797659365ddfc4b62782c6..376a1ae7bcbc17edf348c03d40b7c05602751e04 100644
--- a/source/RobotAPI/libraries/aron/converter/ivt/CMakeLists.txt
+++ b/source/RobotAPI/libraries/aron/converter/ivt/CMakeLists.txt
@@ -7,7 +7,9 @@ find_package(IVT COMPONENTS ivt ivtopencv QUIET)
 armarx_build_if(IVT_FOUND "IVT not available")
 
 set(LIBS
-    aron ivt ivtopencv
+    aron 
+    ivt 
+    ivtopencv
 )
 
 set(LIB_FILES
@@ -21,5 +23,10 @@ set(LIB_HEADERS
 armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}")
 
 if(IVT_FOUND)
-    include_directories(${IVT_INCLUDE_DIRS})
+    target_include_directories(aronivtconverter
+        SYSTEM PUBLIC 
+            ${IVT_INCLUDE_DIRS}
+    )
 endif()
+
+add_library(RobotAPI::aron::converter::ivt ALIAS aronivtconverter)
diff --git a/source/RobotAPI/libraries/aron/converter/opencv/CMakeLists.txt b/source/RobotAPI/libraries/aron/converter/opencv/CMakeLists.txt
index 1b54988b28c2e024b6035a8f722e2fe184ec78bf..5cbe0acad210ec314726aa204e59cefcb9fe23af 100644
--- a/source/RobotAPI/libraries/aron/converter/opencv/CMakeLists.txt
+++ b/source/RobotAPI/libraries/aron/converter/opencv/CMakeLists.txt
@@ -7,7 +7,8 @@ find_package(OpenCV QUIET)
 armarx_build_if(OpenCV_FOUND "OpenCV not available")
 
 set(LIBS
-    aron ${OpenCV_LIBRARIES}
+    aron 
+    ${OpenCV_LIBRARIES}
 )
 
 set(LIB_FILES
@@ -21,5 +22,11 @@ set(LIB_HEADERS
 armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}")
 
 if(OpenCV_FOUND)
-    include_directories(${OpenCV_INCLUDE_DIRS})
+    target_include_directories(aronopencvconverter
+        SYSTEM PUBLIC  
+            ${OpenCV_INCLUDE_DIRS}
+    )
 endif()
+
+
+add_library(RobotAPI::aron::converter::opencv ALIAS aronopencvconverter)
diff --git a/source/RobotAPI/libraries/aron/converter/pcl/CMakeLists.txt b/source/RobotAPI/libraries/aron/converter/pcl/CMakeLists.txt
index 0a1c4532df8ad750b94056911c3cfd157ff937f4..c14d50a5f6f91db9b36088845b63d14ed217a6a4 100644
--- a/source/RobotAPI/libraries/aron/converter/pcl/CMakeLists.txt
+++ b/source/RobotAPI/libraries/aron/converter/pcl/CMakeLists.txt
@@ -7,7 +7,8 @@ find_package(PCL QUIET)
 armarx_build_if(PCL_FOUND "PCL not available")
 
 set(LIBS
-    aron ${PCL_COMMON_LIBRARIES}
+    aron 
+    ${PCL_COMMON_LIBRARIES}
 )
 
 set(LIB_FILES
@@ -21,5 +22,10 @@ set(LIB_HEADERS
 armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}")
 
 if(PCL_FOUND)
-    include_directories(${PCL_INCLUDE_DIRS})
+    target_include_directories(aronpclconverter 
+        SYSTEM PUBLIC
+            ${PCL_INCLUDE_DIRS}
+    )
 endif()
+
+add_library(RobotAPI::aron::converter::pcl ALIAS aronpclconverter)
diff --git a/source/RobotAPI/libraries/aron/core/CMakeLists.txt b/source/RobotAPI/libraries/aron/core/CMakeLists.txt
index 0bdb8203c8083108012fb02e10eac9b7b7a2779e..673ea307e6b52105e4152e54c9c7b2f41f8ca48a 100644
--- a/source/RobotAPI/libraries/aron/core/CMakeLists.txt
+++ b/source/RobotAPI/libraries/aron/core/CMakeLists.txt
@@ -5,15 +5,12 @@ armarx_set_target("Library: ${LIB_NAME}")
 
 find_package(Eigen3 QUIET)
 armarx_build_if(Eigen3_FOUND "Eigen3 not available")
-if(Eigen3_FOUND)
-    include_directories(${Eigen3_INCLUDE_DIR})
-endif()
 
 find_package(Simox QUIET)
 armarx_build_if(Simox_FOUND "Simox not available")
-if(Simox_FOUND)
-    include_directories(${Simox_INCLUDE_DIR})
-endif()
+
+find_package(PCL QUIET COMPONENTS io common)
+armarx_build_if(PCL_FOUND "PCL not available")
 
 
 set(LIBS
@@ -21,7 +18,10 @@ set(LIBS
     ArmarXCore
     RobotAPIInterfaces
     cppgen
-    ${Simox_LIBS}
+    Simox::SimoxUtility
+    # System libraries
+    Eigen3::Eigen
+    # PCLInterface
 )
 
 set(LIB_FILES
@@ -217,7 +217,17 @@ set(LIB_HEADERS
     codegenerator/typeReader/xml/Reader.h
 )
 
+
 armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}")
 
+
+if(PCL_FOUND)
+target_include_directories("${LIB_NAME}" 
+    SYSTEM PUBLIC 
+        "${PCL_INCLUDE_DIRS}"
+)
+endif()
+
+
 # add unit tests
 add_subdirectory(test)
diff --git a/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/serializer/ndarray/PCLPointCloud.cpp b/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/serializer/ndarray/PCLPointCloud.cpp
index 1ba373de5aaaf56fb7062da4134792991b80ac47..cd14f9221dce3541d1f2f2e59720077a8caed805 100644
--- a/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/serializer/ndarray/PCLPointCloud.cpp
+++ b/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/serializer/ndarray/PCLPointCloud.cpp
@@ -36,7 +36,7 @@ namespace armarx::aron::cppcodegenerator::serializer
         {"PointXYZRGB", {"pcl::PointXYZRGB", 32}},
         {"PointXYZRGBL", {"pcl::PointXYZRGBL", 32}},
         {"PointXYZRGBA", {"pcl::PointXYZRGBA", 32}},
-        {"PointXYZHSV", {"pcl::PointXYZHSV", 32}},
+        {"PointXYZHSV", {"pcl::PointXYZHSV", 32}}
     };
 
     // constructors
diff --git a/source/RobotAPI/libraries/aron/core/codegenerator/typeReader/xml/Reader.cpp b/source/RobotAPI/libraries/aron/core/codegenerator/typeReader/xml/Reader.cpp
index 77485c5fdb3b8ce814366b0b73492d249235ab5c..cf56e483356695bf2b54a747e36c4d758e7f1a56 100644
--- a/source/RobotAPI/libraries/aron/core/codegenerator/typeReader/xml/Reader.cpp
+++ b/source/RobotAPI/libraries/aron/core/codegenerator/typeReader/xml/Reader.cpp
@@ -29,20 +29,38 @@
 
 // ArmarX
 #include <ArmarXCore/core/rapidxml/wrapper/RapidXmlReader.h>
+#include <ArmarXCore/core/system/cmake/CMakePackageFinder.h>
 
 #include <RobotAPI/libraries/aron/core/codegenerator/typeReader/xml/Data.h>
 #include <RobotAPI/libraries/aron/core/navigator/type/NavigatorFactory.h>
 
+
+namespace fs = std::filesystem;
+
 namespace armarx::aron::xmltypereader
 {
-    void Reader::parseFile(const std::string& filename)
+    void Reader::parseFile(const std::string& _filename)
     {
-        RapidXmlReaderPtr reader = RapidXmlReader::FromFile(filename);
-        parse(reader);
+        std::string filename = _filename;
+        // Handle C++ style includes like "<path/to/file>".
+        if (!filename.empty() && filename.front() == '<' && filename.back() == '>')
+        {
+            filename = filename.substr(1, filename.size() - 2);
+        }
+        parseFile(std::filesystem::path(filename));
     }
 
-    void Reader::parseFile(const std::filesystem::path& file)
+    void Reader::parseFile(const std::filesystem::path& _file)
     {
+        fs::path file = _file;
+        if (!file.empty() && file.is_relative())
+        {
+            if (std::optional<fs::path> resolved = detail::resolveRelativePackagePath(file))
+            {
+                file = resolved.value();
+            }
+        }
+
         RapidXmlReaderPtr reader = RapidXmlReader::FromFile(file.string());
         parse(reader);
     }
@@ -185,4 +203,30 @@ namespace armarx::aron::xmltypereader
         return typenavigator::IntEnumNavigator::DynamicCastAndCheck(factory.create(node, Path()));
 
     }
+
+
+    std::optional<fs::path> detail::resolveRelativePackagePath(const fs::path& path)
+    {
+        const std::string package = *path.begin();
+        armarx::CMakePackageFinder finder(package);
+        if (finder.packageFound())
+        {
+            for (const std::string& includePath : finder.getIncludePathList())
+            {
+                fs::path absPath = includePath / path;
+                if (fs::is_regular_file(absPath))
+                {
+                    return absPath;
+                }
+            }
+            return std::nullopt;
+        }
+        else
+        {
+            return std::nullopt;
+        }
+    }
+
 }
+
+
diff --git a/source/RobotAPI/libraries/aron/core/codegenerator/typeReader/xml/Reader.h b/source/RobotAPI/libraries/aron/core/codegenerator/typeReader/xml/Reader.h
index 0801465160e06ddbd0ebfc78b57d8b8bb97eafcd..e19083a9aa2718792c705ec41267a4e7f50d2cc8 100644
--- a/source/RobotAPI/libraries/aron/core/codegenerator/typeReader/xml/Reader.h
+++ b/source/RobotAPI/libraries/aron/core/codegenerator/typeReader/xml/Reader.h
@@ -24,8 +24,10 @@
 #pragma once
 
 // STD/STL
-#include <memory>
 #include <filesystem>
+#include <memory>
+#include <optional>
+
 
 // Base Class
 #include <RobotAPI/libraries/aron/core/codegenerator/typeReader/Reader.h>
@@ -63,4 +65,10 @@ namespace armarx::aron::xmltypereader
     private:
         ReaderFactory factory;
     };
+
+
+    namespace detail
+    {
+        std::optional<std::filesystem::path> resolveRelativePackagePath(const std::filesystem::path& path);
+    }
 }
diff --git a/source/RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.cpp b/source/RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.cpp
index 0ed94c664655cbb4668ef4611a843e94fb1e1420..97942372a9c6be2667ff6639c13779fc734e933a 100644
--- a/source/RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.cpp
+++ b/source/RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.cpp
@@ -239,4 +239,5 @@ case type::e##upperType: \
     {
         return 0;
     }
-}
+
+}  // namespace armarx::aron::datanavigator
diff --git a/source/RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.h b/source/RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.h
index 60d8361038c5d0aeba9f9d902f038dfd0386a96f..5e447b102d889f2ba91d95e23a60a89028cf1ff4 100644
--- a/source/RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.h
+++ b/source/RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.h
@@ -24,16 +24,22 @@
 #pragma once
 
 // STD/STL
+#include <cstddef>
+#include <functional>
 #include <memory>
 #include <map>
+#include <numeric>
+#include <vector>
 
 // ArmarX
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
 #include <RobotAPI/libraries/aron/core/navigator/data/Navigator.h>
 
 namespace armarx::aron::datanavigator
 {
     class NDArrayNavigator;
-    typedef std::shared_ptr<NDArrayNavigator> NDArrayNavigatorPtr;
+    using NDArrayNavigatorPtr = std::shared_ptr<NDArrayNavigator>;
 
     class NDArrayNavigator :
         virtual public Navigator
@@ -41,7 +47,6 @@ namespace armarx::aron::datanavigator
     public:
         using PointerType = NDArrayNavigatorPtr;
 
-    public:
         // constructors
         NDArrayNavigator(const Path& path = Path());
         NDArrayNavigator(const data::AronNDArrayPtr&, const Path& path = Path());
@@ -63,11 +68,31 @@ namespace armarx::aron::datanavigator
         /// Return dimensions in a readable string such as "(2, 3, 4)".
         static std::string DimensionsToString(const std::vector<int>& dimensions);
 
+        // TODO(fabian.reister): move this to VectorConverter?
+        template<typename T>
+        static NDArrayNavigatorPtr FromVector(const std::vector<T>& data)
+        {
+            NDArrayNavigatorPtr ndArr(new NDArrayNavigator);
+
+            ndArr->setDimensions({static_cast<int>(data.size()), sizeof(T)});
+            ndArr->setData(data);
+
+            return ndArr;
+        }
+
 
         // public member functions
         unsigned char* getData() const;
         void setData(unsigned int, const unsigned char*);
 
+        // TODO(fabian.reister): move this to VectorConverter?
+        template<typename T>
+        void setData(const std::vector<T>& data)
+        {
+            using E = typename decltype(aron->data)::value_type;
+            setData(sizeof(T) * data.size(), reinterpret_cast < const E* >(data.data()));
+        }
+
         std::vector<int> getDimensions() const;
         void setDimensions(const std::vector<int>&);
         void addDimension(int);
diff --git a/source/RobotAPI/libraries/aron/core/test/CMakeLists.txt b/source/RobotAPI/libraries/aron/core/test/CMakeLists.txt
index 7eeffdbb49db4b321b77ed47fa1e58361d538094..de44d5a1d28a8148139265d1a18a6667c1c4a697 100644
--- a/source/RobotAPI/libraries/aron/core/test/CMakeLists.txt
+++ b/source/RobotAPI/libraries/aron/core/test/CMakeLists.txt
@@ -40,20 +40,22 @@ armarx_enable_aron_file_generation_for_target(
     TARGET_NAME
         ${TEST_NAME}
     ARON_FILES
-        xmls/HumanPoseTest.xml
+        # xmls/BaseClass.xml
+        # xmls/DerivedClassTest.xml
         xmls/DictTest.xml
+        xmls/EigenMatrixTest.xml
+        xmls/EigenQuaternionTest.xml
+        xmls/EnumTest.xml
+        xmls/HumanPoseTest.xml
+        xmls/IVTCByteImageTest.xml
         xmls/ListTest.xml
         xmls/NaturalIKTest.xml
         xmls/ObjectTest.xml
-        xmls/PrimitiveTest.xml
-        xmls/IVTCByteImageTest.xml
-        xmls/EigenMatrixTest.xml
-        xmls/EigenQuaternionTest.xml
         xmls/OpenCVMatTest.xml
-        xmls/PCLPointCloudTest.xml
-        xmls/PositionTest.xml
         xmls/OrientationTest.xml
+        xmls/PCLPointCloudTest.xml
         xmls/PoseTest.xml
-        xmls/EnumTest.xml
+        xmls/PositionTest.xml
+        xmls/PrimitiveTest.xml
     #ENABLE_DEBUG_INFO
 )