From db2e356d0a61a264557e344ccbc588605cfa8ab4 Mon Sep 17 00:00:00 2001
From: Fabian Peller-Konrad <fabian.peller-konrad@kit.edu>
Date: Mon, 21 Mar 2022 15:31:37 +0100
Subject: [PATCH] ltm updates and improved export of depth images in exr format

---
 .../libraries/armem/server/CMakeLists.txt     |  6 ++
 .../server/ltm/base/converter/Converter.h     |  8 +-
 .../ltm/base/converter/image/Converter.cpp    |  6 +-
 .../ltm/base/converter/image/Converter.h      | 12 +--
 .../base/converter/image/exr/ExrConverter.cpp | 33 +++++++++
 .../base/converter/image/exr/ExrConverter.h   | 21 ++++++
 .../base/converter/image/png/PngConverter.cpp | 45 ++++++++++--
 .../base/converter/image/png/PngConverter.h   |  6 +-
 .../ltm/base/converter/object/Converter.cpp   |  6 +-
 .../ltm/base/converter/object/Converter.h     | 12 +--
 .../converter/object/bson/BsonConverter.cpp   | 10 +--
 .../converter/object/bson/BsonConverter.h     |  6 +-
 .../converter/object/json/JsonConverter.cpp   |  6 +-
 .../converter/object/json/JsonConverter.h     |  6 +-
 .../armem/server/ltm/base/detail/MemoryBase.h | 15 +---
 .../armem/server/ltm/base/detail/MemoryItem.h | 41 +----------
 .../server/ltm/base/detail/Processors.cpp     | 35 +++++++++
 .../armem/server/ltm/base/detail/Processors.h | 52 +++++++++++++
 .../server/ltm/base/extractor/Extractor.h     |  3 +-
 .../imageExtractor/DepthImageExtractor.cpp    | 48 ++++++++++++
 .../imageExtractor/DepthImageExtractor.h      | 31 ++++++++
 .../imageExtractor/ImageExtractor.cpp         |  2 +-
 .../extractor/imageExtractor/ImageExtractor.h |  2 +-
 .../armem/server/ltm/disk/CoreSegment.cpp     |  5 +-
 .../armem/server/ltm/disk/Entity.cpp          | 49 +++++++++++--
 .../armem/server/ltm/disk/EntitySnapshot.cpp  | 73 +++++++++++--------
 .../armem/server/ltm/disk/Memory.cpp          | 28 ++++---
 .../libraries/armem/server/ltm/disk/Memory.h  |  5 +-
 .../armem/server/ltm/disk/ProviderSegment.cpp |  5 +-
 .../server/ltm/disk/detail/util/util.cpp      | 23 ++++++
 .../armem/server/ltm/disk/detail/util/util.h  |  2 +
 .../armem_gui/disk/ControlWidget.cpp          | 10 +--
 .../armem_gui/instance/InstanceView.cpp       |  5 +-
 33 files changed, 457 insertions(+), 160 deletions(-)
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/base/converter/image/exr/ExrConverter.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/base/converter/image/exr/ExrConverter.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/base/detail/Processors.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/base/detail/Processors.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/DepthImageExtractor.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/DepthImageExtractor.h

diff --git a/source/RobotAPI/libraries/armem/server/CMakeLists.txt b/source/RobotAPI/libraries/armem/server/CMakeLists.txt
index 7fc48a638..51efca0f2 100644
--- a/source/RobotAPI/libraries/armem/server/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem/server/CMakeLists.txt
@@ -45,6 +45,7 @@ set(LIB_FILES
     MemoryRemoteGui.cpp
     RemoteGuiAronDataVisitor.cpp
 
+    ltm/base/detail/Processors.cpp
     ltm/base/detail/MemoryItem.cpp
     ltm/base/detail/MemoryBase.cpp
     ltm/base/detail/BufferedMemoryBase.cpp
@@ -60,6 +61,7 @@ set(LIB_FILES
 
     ltm/base/extractor/Extractor.cpp
     ltm/base/extractor/imageExtractor/ImageExtractor.cpp
+    ltm/base/extractor/imageExtractor/DepthImageExtractor.cpp
 
     ltm/base/converter/Converter.cpp
     ltm/base/converter/object/Converter.cpp
@@ -67,6 +69,7 @@ set(LIB_FILES
     ltm/base/converter/object/bson/BsonConverter.cpp
     ltm/base/converter/image/Converter.cpp
     ltm/base/converter/image/png/PngConverter.cpp
+    ltm/base/converter/image/exr/ExrConverter.cpp
 
     ltm/base/forgetter/Forgetter.cpp
     ltm/base/forgetter/LRUForgetter/LRUForgetter.cpp
@@ -120,6 +123,7 @@ set(LIB_HEADERS
     MemoryRemoteGui.h
     RemoteGuiAronDataVisitor.h
 
+    ltm/base/detail/Processors.h
     ltm/base/detail/MemoryItem.h
     ltm/base/detail/MemoryBase.h
     ltm/base/detail/BufferedMemoryBase.h
@@ -135,6 +139,7 @@ set(LIB_HEADERS
 
     ltm/base/extractor/Extractor.h
     ltm/base/extractor/imageExtractor/ImageExtractor.h
+    ltm/base/extractor/imageExtractor/DepthImageExtractor.h
 
     ltm/base/converter/Converter.h
     ltm/base/converter/object/Converter.h
@@ -142,6 +147,7 @@ set(LIB_HEADERS
     ltm/base/converter/object/bson/BsonConverter.h
     ltm/base/converter/image/Converter.h
     ltm/base/converter/image/png/PngConverter.h
+    ltm/base/converter/image/exr/ExrConverter.h
 
 
     ltm/base/forgetter/Forgetter.h
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/Converter.h b/source/RobotAPI/libraries/armem/server/ltm/base/converter/Converter.h
index f6eb1f71e..b109bb9af 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/converter/Converter.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/Converter.h
@@ -17,17 +17,19 @@ namespace armarx::armem::server::ltm
             Binary
         };
 
-        Converter(const ConverterType t, const std::string& s, const aron::type::Descriptor c):
+        Converter(const ConverterType t, const std::string& id, const std::string& s, const aron::type::Descriptor c):
             type(t),
+            identifier(id),
             suffix(s),
             convertsType(c)
         {}
         virtual ~Converter() = default;
 
-        virtual std::vector<unsigned char> convert(const aron::data::VariantPtr& data) = 0;
-        virtual aron::data::VariantPtr convert(const std::vector<unsigned char>& data) = 0;
+        virtual std::pair<std::vector<unsigned char>, std::string> convert(const aron::data::VariantPtr& data) = 0;
+        virtual aron::data::VariantPtr convert(const std::vector<unsigned char>& data, const std::string&) = 0;
 
         const ConverterType type;
+        const std::string identifier;
         const std::string suffix;
         const aron::type::Descriptor convertsType;
         bool enabled = false;
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/Converter.cpp b/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/Converter.cpp
index a36db667d..39b4d94b0 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/Converter.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/Converter.cpp
@@ -3,15 +3,15 @@
 namespace armarx::armem::server::ltm
 {
 
-    std::vector<unsigned char> ImageConverter::convert(const aron::data::VariantPtr& data)
+    std::pair<std::vector<unsigned char>, std::string> ImageConverter::convert(const aron::data::VariantPtr& data)
     {
         auto d = aron::data::NDArray::DynamicCastAndCheck(data);
         return _convert(d);
     }
 
-    aron::data::VariantPtr ImageConverter::convert(const std::vector<unsigned char>& data)
+    aron::data::VariantPtr ImageConverter::convert(const std::vector<unsigned char>& data, const std::string& m)
     {
-        auto d = _convert(data);
+        auto d = _convert(data, m);
         return d;
     }
 
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/Converter.h b/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/Converter.h
index 78ba28f4a..a2b2df045 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/Converter.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/Converter.h
@@ -14,17 +14,17 @@ namespace armarx::armem::server::ltm
     class ImageConverter : public Converter
     {
     public:
-        ImageConverter(const ConverterType t, const std::string& s):
-            Converter(t, s, aron::type::Descriptor::eImage)
+        ImageConverter(const ConverterType t, const std::string& id, const std::string& s):
+            Converter(t, id, s, aron::type::Descriptor::eImage)
         {}
 
         virtual ~ImageConverter() = default;
 
-        std::vector<unsigned char> convert(const aron::data::VariantPtr& data) final;
-        aron::data::VariantPtr convert(const std::vector<unsigned char>& data) final;
+        std::pair<std::vector<unsigned char>, std::string> convert(const aron::data::VariantPtr& data) final;
+        aron::data::VariantPtr convert(const std::vector<unsigned char>& data, const std::string&) final;
 
     protected:
-        virtual std::vector<unsigned char> _convert(const aron::data::NDArrayPtr& data) = 0;
-        virtual aron::data::NDArrayPtr _convert(const std::vector<unsigned char>& data) = 0;
+        virtual std::pair<std::vector<unsigned char>, std::string> _convert(const aron::data::NDArrayPtr& data) = 0;
+        virtual aron::data::NDArrayPtr _convert(const std::vector<unsigned char>& data, const std::string&) = 0;
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/exr/ExrConverter.cpp b/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/exr/ExrConverter.cpp
new file mode 100644
index 000000000..c5eee777b
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/exr/ExrConverter.cpp
@@ -0,0 +1,33 @@
+#include "ExrConverter.h"
+
+// ArmarX
+#include <RobotAPI/libraries/aron/converter/opencv/OpenCVConverter.h>
+
+#include <opencv2/opencv.hpp>
+#include <opencv2/imgcodecs.hpp>
+#include <opencv2/imgproc.hpp>
+
+
+namespace armarx::armem::server::ltm::converter::image
+{
+    std::pair<std::vector<unsigned char>, std::string> ExrConverter::_convert(const aron::data::NDArrayPtr& data)
+    {
+        ARMARX_CHECK_NOT_NULL(data);
+
+        auto img = aron::converter::AronOpenCVConverter::ConvertToMat(data);
+        std::vector<unsigned char> buffer;
+
+        auto shape = data->getShape(); // we know from the extraction that the shape has 3 elements
+        ARMARX_CHECK_EQUAL(shape.size(), 3);
+        ARMARX_CHECK_EQUAL(shape[2], 4);
+
+        cv::imencode(".exr", img, buffer);
+        return std::make_pair(buffer, "");
+    }
+
+    aron::data::NDArrayPtr ExrConverter::_convert(const std::vector<unsigned char>& data, const std::string& m)
+    {
+        cv::Mat img = cv::imdecode(data, cv::IMREAD_ANYDEPTH);
+        return aron::converter::AronOpenCVConverter::ConvertFromMat(img);
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/exr/ExrConverter.h b/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/exr/ExrConverter.h
new file mode 100644
index 000000000..ad4b1bfa2
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/exr/ExrConverter.h
@@ -0,0 +1,21 @@
+#pragma once
+
+// Base Class
+#include "../Converter.h"
+
+namespace armarx::armem::server::ltm::converter::image
+{
+    class ExrConverter : public ImageConverter
+    {
+    public:
+        ExrConverter() :
+            ImageConverter(ConverterType::Binary, "depthimage", ".exr")
+        {
+            enabled = true; // enabled by default
+        }
+
+    protected:
+        std::pair<std::vector<unsigned char>, std::string> _convert(const aron::data::NDArrayPtr& data) final;
+        aron::data::NDArrayPtr _convert(const std::vector<unsigned char>& data, const std::string&) final;
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/png/PngConverter.cpp b/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/png/PngConverter.cpp
index 24fc8be1f..e8536cf64 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/png/PngConverter.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/png/PngConverter.cpp
@@ -10,21 +10,52 @@
 
 namespace armarx::armem::server::ltm::converter::image
 {
-    std::vector<unsigned char> PngConverter::_convert(const aron::data::NDArrayPtr& data)
+    std::pair<std::vector<unsigned char>, std::string> PngConverter::_convert(const aron::data::NDArrayPtr& data)
     {
         ARMARX_CHECK_NOT_NULL(data);
 
         auto img = aron::converter::AronOpenCVConverter::ConvertToMat(data);
-        cv::cvtColor(img, img, CV_RGB2BGR);
         std::vector<unsigned char> buffer;
-        cv::imencode(".png", img, buffer);
-        return buffer;
+
+
+        auto shape = data->getShape(); // we know from the extraction that the shape has 3 elements
+        ARMARX_CHECK_EQUAL(shape.size(), 3);
+
+        if (shape[2] == 3) // its probably a rgb image
+        {
+            cv::cvtColor(img, img, CV_RGB2BGR);
+            cv::imencode(suffix, img, buffer);
+            return std::make_pair(buffer, ".rgb");
+        }
+
+        if (shape[2] == 1) // its probably a grayscale image
+        {
+            cv::imencode(suffix, img, buffer);
+            return std::make_pair(buffer, ".gs");
+        }
+
+        // try to export without conversion
+        cv::imencode(suffix, img, buffer);
+        return std::make_pair(buffer, "");
     }
 
-    aron::data::NDArrayPtr PngConverter::_convert(const std::vector<unsigned char>& data)
+    aron::data::NDArrayPtr PngConverter::_convert(const std::vector<unsigned char>& data, const std::string& m)
     {
-        cv::Mat img = cv::imdecode(data, cv::IMREAD_COLOR);
-        cv::cvtColor(img, img, CV_BGR2RGB);
+        if (m == ".rgb")
+        {
+            cv::Mat img = cv::imdecode(data, cv::IMREAD_COLOR);
+            cv::cvtColor(img, img, CV_BGR2RGB);
+            return aron::converter::AronOpenCVConverter::ConvertFromMat(img);
+        }
+
+        if (m == ".gs")
+        {
+            cv::Mat img = cv::imdecode(data, cv::IMREAD_GRAYSCALE);
+            return aron::converter::AronOpenCVConverter::ConvertFromMat(img);
+        }
+
+        // try to load without conversion
+        cv::Mat img = cv::imdecode(data, cv::IMREAD_ANYCOLOR);
         return aron::converter::AronOpenCVConverter::ConvertFromMat(img);
     }
 }
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/png/PngConverter.h b/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/png/PngConverter.h
index a2ba7f86c..5b6c80134 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/png/PngConverter.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/image/png/PngConverter.h
@@ -9,13 +9,13 @@ namespace armarx::armem::server::ltm::converter::image
     {
     public:
         PngConverter() :
-            ImageConverter(ConverterType::Binary, ".png")
+            ImageConverter(ConverterType::Binary, "image", ".png")
         {
             enabled = true; // enabled by default
         }
 
     protected:
-        std::vector<unsigned char> _convert(const aron::data::NDArrayPtr& data) final;
-        aron::data::NDArrayPtr _convert(const std::vector<unsigned char>& data) final;
+        std::pair<std::vector<unsigned char>, std::string> _convert(const aron::data::NDArrayPtr& data) final;
+        aron::data::NDArrayPtr _convert(const std::vector<unsigned char>& data, const std::string&) final;
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/Converter.cpp b/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/Converter.cpp
index 26b9ffac7..4f0808a6f 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/Converter.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/Converter.cpp
@@ -3,15 +3,15 @@
 namespace armarx::armem::server::ltm
 {
 
-    std::vector<unsigned char> ObjectConverter::convert(const aron::data::VariantPtr& data)
+    std::pair<std::vector<unsigned char>, std::string> ObjectConverter::convert(const aron::data::VariantPtr& data)
     {
         auto d = aron::data::Dict::DynamicCastAndCheck(data);
         return _convert(d);
     }
 
-    aron::data::VariantPtr ObjectConverter::convert(const std::vector<unsigned char>& data)
+    aron::data::VariantPtr ObjectConverter::convert(const std::vector<unsigned char>& data, const std::string& m)
     {
-        auto d = _convert(data);
+        auto d = _convert(data, m);
         return d;
     }
 
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/Converter.h b/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/Converter.h
index 3ae9dcfa2..e5c8e9f80 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/Converter.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/Converter.h
@@ -14,17 +14,17 @@ namespace armarx::armem::server::ltm
     class ObjectConverter : public Converter
     {
     public:
-        ObjectConverter(const ConverterType t, const std::string& s):
-            Converter(t, s, aron::type::Descriptor::eObject)
+        ObjectConverter(const ConverterType t, const std::string& id, const std::string& s):
+            Converter(t, id, s, aron::type::Descriptor::eObject)
         {}
 
         virtual ~ObjectConverter() = default;
 
-        std::vector<unsigned char> convert(const aron::data::VariantPtr& data) final;
-        aron::data::VariantPtr convert(const std::vector<unsigned char>& data) final;
+        std::pair<std::vector<unsigned char>, std::string> convert(const aron::data::VariantPtr& data) final;
+        aron::data::VariantPtr convert(const std::vector<unsigned char>& data, const std::string&) final;
 
     protected:
-        virtual std::vector<unsigned char> _convert(const aron::data::DictPtr& data) = 0;
-        virtual aron::data::DictPtr _convert(const std::vector<unsigned char>& data) = 0;
+        virtual std::pair<std::vector<unsigned char>, std::string> _convert(const aron::data::DictPtr& data) = 0;
+        virtual aron::data::DictPtr _convert(const std::vector<unsigned char>& data, const std::string&) = 0;
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/bson/BsonConverter.cpp b/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/bson/BsonConverter.cpp
index d483958fa..8465201f3 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/bson/BsonConverter.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/bson/BsonConverter.cpp
@@ -10,9 +10,9 @@ namespace armarx::armem::server::ltm::converter::object
     namespace bsoncxxbuilder = bsoncxx::builder::stream;
     namespace bsoncxxdoc = bsoncxx::document;
 
-    std::vector<unsigned char> BsonConverter::_convert(const aron::data::DictPtr& data)
+    std::pair<std::vector<unsigned char>, std::string> BsonConverter::_convert(const aron::data::DictPtr& data)
     {
-        std::vector<unsigned char> jsonVec = jsonConverter.convert(data);
+        auto [jsonVec, str] = jsonConverter.convert(data);
         std::string json(jsonVec.begin(), jsonVec.end());
         auto view = bsoncxx::from_json(json).view();
 
@@ -21,16 +21,16 @@ namespace armarx::armem::server::ltm::converter::object
         {
             std::memcpy(bson.data(), view.data(), view.length());
         }
-        return bson;
+        return std::make_pair(bson, str);
     }
 
-    aron::data::DictPtr BsonConverter::_convert(const std::vector<unsigned char>& data)
+    aron::data::DictPtr BsonConverter::_convert(const std::vector<unsigned char>& data, const std::string& m)
     {
         bsoncxx::document::view view(data.data(), data.size());
         nlohmann::json json = bsoncxx::to_json(view);
         std::string str = json.dump(2);
         std::vector<unsigned char> jsonVec(str.begin(), str.end());
-        auto v = jsonConverter.convert(jsonVec);
+        auto v = jsonConverter.convert(jsonVec, m);
         return aron::data::Dict::DynamicCast(v);
     }
 }
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/bson/BsonConverter.h b/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/bson/BsonConverter.h
index 2dbb293ab..6eb183be2 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/bson/BsonConverter.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/bson/BsonConverter.h
@@ -15,12 +15,12 @@ namespace armarx::armem::server::ltm::converter::object
     {
     public:
         BsonConverter() :
-            ObjectConverter(ConverterType::Binary, ".bson")
+            ObjectConverter(ConverterType::Binary, "dict", ".bson")
         {}
 
     protected:
-        std::vector<unsigned char> _convert(const aron::data::DictPtr& data) final;
-        aron::data::DictPtr _convert(const std::vector<unsigned char>& data) final;
+        std::pair<std::vector<unsigned char>, std::string> _convert(const aron::data::DictPtr& data) final;
+        aron::data::DictPtr _convert(const std::vector<unsigned char>& data, const std::string&) final;
 
     private:
         JsonConverter jsonConverter;
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/json/JsonConverter.cpp b/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/json/JsonConverter.cpp
index 55fe9fddb..f2baa4865 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/json/JsonConverter.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/json/JsonConverter.cpp
@@ -4,14 +4,14 @@
 
 namespace armarx::armem::server::ltm::converter::object
 {
-    std::vector<unsigned char> JsonConverter::_convert(const aron::data::DictPtr& data)
+    std::pair<std::vector<unsigned char>, std::string> JsonConverter::_convert(const aron::data::DictPtr& data)
     {
         nlohmann::json j = aron::converter::AronNlohmannJSONConverter::ConvertToNlohmannJSON(data);
         auto str = j.dump(2);
-        return std::vector<unsigned char>(str.begin(), str.end());
+        return std::make_pair(std::vector<unsigned char>(str.begin(), str.end()), "");
     }
 
-    aron::data::DictPtr JsonConverter::_convert(const std::vector<unsigned char>& data)
+    aron::data::DictPtr JsonConverter::_convert(const std::vector<unsigned char>& data, const std::string&)
     {
         std::string str(data.begin(), data.end());
         nlohmann::json j = nlohmann::json::parse(str);
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/json/JsonConverter.h b/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/json/JsonConverter.h
index 98be34661..1b9f86ee9 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/json/JsonConverter.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/converter/object/json/JsonConverter.h
@@ -12,13 +12,13 @@ namespace armarx::armem::server::ltm::converter::object
     {
     public:
         JsonConverter() :
-            ObjectConverter(ConverterType::Str, ".json")
+            ObjectConverter(ConverterType::Str, "dict", ".json")
         {
             enabled = true; // always true!
         }
 
     protected:
-        std::vector<unsigned char> _convert(const aron::data::DictPtr& data) final;
-        aron::data::DictPtr _convert(const std::vector<unsigned char>& data) final;
+        std::pair<std::vector<unsigned char>, std::string> _convert(const aron::data::DictPtr& data) final;
+        aron::data::DictPtr _convert(const std::vector<unsigned char>& data, const std::string&) final;
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/detail/MemoryBase.h b/source/RobotAPI/libraries/armem/server/ltm/base/detail/MemoryBase.h
index ce25bee41..386ce278b 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/detail/MemoryBase.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/detail/MemoryBase.h
@@ -9,7 +9,6 @@
 #include "CoreSegmentBase.h"
 
 // ArmarX
-#include <ArmarXCore/core/application/properties/Properties.h>
 #include <ArmarXCore/core/time/TimeUtil.h>
 #include <ArmarXCore/core/logging/LoggingUtil.h>
 
@@ -112,19 +111,7 @@ namespace armarx::armem::server::ltm
         /// parameters
         virtual void createPropertyDefinitions(PropertyDefinitionsPtr& defs, const std::string& prefix)
         {
-            // filters
-            defs->optional(processors->memFreqFilter.enabled, prefix + "memFreqFilter.Enabled");
-            defs->optional(processors->memFreqFilter.waitingTimeInMs, prefix + "memFreqFilter.WaitingTime", "Waiting time in MS after each LTM update.");
-            defs->optional(processors->snapFreqFilter.enabled, prefix + "snapFreqFilter.Enabled");
-            defs->optional(processors->snapFreqFilter.waitingTimeInMs, prefix + "snapFreqFilter.WaitingTime", "Waiting time in MS after each Entity update.");
-            defs->optional(processors->snapEqFilter.enabled, prefix + "snapEqFilter.Enabled");
-            defs->optional(processors->snapEqFilter.maxWaitingTimeInMs, prefix + "snapEqFilter.MaxWaitingTime", "Max Waiting time in MS after each Entity update.");
-
-            // extractors
-            defs->optional(processors->imageExtractor.enabled, prefix + "imageExtractor.Enabled");
-
-            // converters
-            defs->optional(processors->pngConverter.enabled, prefix + "pngConverter.Enabled");
+            processors->createPropertyDefinitions(defs, prefix);
         }
 
         /// get level name
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/detail/MemoryItem.h b/source/RobotAPI/libraries/armem/server/ltm/base/detail/MemoryItem.h
index 27b91fdb9..570231509 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/detail/MemoryItem.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/detail/MemoryItem.h
@@ -5,49 +5,10 @@
 #include <optional>
 #include <string>
 
-#include "../filter/frequencyFilter/FrequencyFilter.h"
-#include "../filter/equalityFilter/EqualityFilter.h"
-#include "../extractor/imageExtractor/ImageExtractor.h"
-#include "../converter/object/json/JsonConverter.h"
-#include "../converter/image/png/PngConverter.h"
-
-#include <RobotAPI/libraries/armem/core/MemoryID.h>
+#include "Processors.h"
 
 namespace armarx::armem::server::ltm
 {
-    /// all necessary classes to filter and convert an entry of the ltm to some other format(s)
-    struct Processors
-    {
-        // Unique Memory Filters
-        std::vector<MemoryFilter*> memFilters;
-        filter::MemoryFrequencyFilter memFreqFilter;
-
-        // Unique Snapshot filters
-        std::vector<SnapshotFilter*> snapFilters;
-        filter::SnapshotFrequencyFilter snapFreqFilter;
-        filter::SnapshotEqualityFilter snapEqFilter;
-
-        // Extractors
-        std::vector<Extractor*> extractors;
-        extractor::ImageExtractor imageExtractor;
-
-        // Converters
-        std::map<aron::type::Descriptor, Converter*> converters;
-        converter::object::JsonConverter jsonConverter;
-        converter::image::PngConverter pngConverter;
-
-        Processors()
-        {
-            // setup containers
-            memFilters.push_back(&memFreqFilter);
-            snapFilters.push_back(&snapFreqFilter);
-            snapFilters.push_back(&snapEqFilter);
-            extractors.push_back(&imageExtractor);
-            converters.insert({jsonConverter.convertsType, &jsonConverter});
-            converters.insert({pngConverter.convertsType, &pngConverter});
-        }
-    };
-
     /// @brief Interface functions for the longterm memory classes
     class MemoryItem
     {
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/detail/Processors.cpp b/source/RobotAPI/libraries/armem/server/ltm/base/detail/Processors.cpp
new file mode 100644
index 000000000..6e176bf79
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/detail/Processors.cpp
@@ -0,0 +1,35 @@
+#include "Processors.h"
+
+namespace armarx::armem::server::ltm
+{
+    Processors::Processors()
+    {
+        // setup containers
+        memFilters.push_back(&memFreqFilter);
+        snapFilters.push_back(&snapFreqFilter);
+        snapFilters.push_back(&snapEqFilter);
+        extractors.push_back(&imageExtractor);
+        extractors.push_back(&depthImageExtractor);
+        converters.insert({pngConverter.identifier, &pngConverter});
+        converters.insert({exrConverter.identifier, &exrConverter});
+    }
+
+    void Processors::createPropertyDefinitions(PropertyDefinitionsPtr& defs, const std::string& prefix)
+    {
+        // filters
+        defs->optional(memFreqFilter.enabled, prefix + "memFreqFilter.Enabled");
+        defs->optional(memFreqFilter.waitingTimeInMs, prefix + "memFreqFilter.WaitingTime", "Waiting time in MS after each LTM update.");
+        defs->optional(snapFreqFilter.enabled, prefix + "snapFreqFilter.Enabled");
+        defs->optional(snapFreqFilter.waitingTimeInMs, prefix + "snapFreqFilter.WaitingTime", "Waiting time in MS after each Entity update.");
+        defs->optional(snapEqFilter.enabled, prefix + "snapEqFilter.Enabled");
+        defs->optional(snapEqFilter.maxWaitingTimeInMs, prefix + "snapEqFilter.MaxWaitingTime", "Max Waiting time in MS after each Entity update.");
+
+        // extractors
+        defs->optional(imageExtractor.enabled, prefix + "imageExtractor.Enabled");
+        defs->optional(depthImageExtractor.enabled, prefix + "depthImageExtractor.Enabled");
+
+        // converters
+        defs->optional(pngConverter.enabled, prefix + "pngConverter.Enabled");
+        defs->optional(exrConverter.enabled, prefix + "exrConverter.Enabled");
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/detail/Processors.h b/source/RobotAPI/libraries/armem/server/ltm/base/detail/Processors.h
new file mode 100644
index 000000000..232e6f32b
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/detail/Processors.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#include <map>
+#include <mutex>
+#include <optional>
+#include <string>
+
+#include <ArmarXCore/core/application/properties/Properties.h>
+
+#include "../filter/frequencyFilter/FrequencyFilter.h"
+#include "../filter/equalityFilter/EqualityFilter.h"
+#include "../extractor/imageExtractor/ImageExtractor.h"
+#include "../extractor/imageExtractor/DepthImageExtractor.h"
+#include "../converter/object/json/JsonConverter.h"
+#include "../converter/image/png/PngConverter.h"
+#include "../converter/image/exr/ExrConverter.h"
+
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+
+namespace armarx::armem::server::ltm
+{
+    /// all necessary classes to filter and convert an entry of the ltm to some other format(s)
+    class Processors
+    {
+    public:
+        Processors();
+        void createPropertyDefinitions(PropertyDefinitionsPtr& defs, const std::string& prefix);
+
+    public:
+        // Unique Memory Filters
+        std::vector<MemoryFilter*> memFilters;
+        filter::MemoryFrequencyFilter memFreqFilter;
+
+        // Unique Snapshot filters
+        std::vector<SnapshotFilter*> snapFilters;
+        filter::SnapshotFrequencyFilter snapFreqFilter;
+        filter::SnapshotEqualityFilter snapEqFilter;
+
+        // Special Extractors
+        std::vector<Extractor*> extractors;
+        extractor::ImageExtractor imageExtractor;
+        extractor::DepthImageExtractor depthImageExtractor;
+
+        // Special Converters
+        std::map<std::string, Converter*> converters;
+        converter::image::PngConverter pngConverter;
+        converter::image::ExrConverter exrConverter;
+
+        // Default converter
+        converter::object::JsonConverter defaultObjectConverter;
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/extractor/Extractor.h b/source/RobotAPI/libraries/armem/server/ltm/base/extractor/Extractor.h
index 8fbedc484..0fd5ca5ad 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/extractor/Extractor.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/extractor/Extractor.h
@@ -18,13 +18,14 @@ namespace armarx::armem::server::ltm
             std::map<std::string, aron::data::VariantPtr> extraction;
         };
 
-        Extractor(const aron::type::Descriptor t) : extractsType(t) {};
+        Extractor(const aron::type::Descriptor t, const std::string& id) : extractsType(t), identifier(id) {};
         virtual ~Extractor() = default;
 
         virtual Extraction extract(aron::data::DictPtr& data) = 0;
         virtual aron::data::DictPtr merge(Extraction& encoding) = 0;
 
         const aron::type::Descriptor extractsType;
+        const std::string identifier;
         bool enabled = false;
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/DepthImageExtractor.cpp b/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/DepthImageExtractor.cpp
new file mode 100644
index 000000000..4640cca47
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/DepthImageExtractor.cpp
@@ -0,0 +1,48 @@
+#include "DepthImageExtractor.h"
+
+
+namespace armarx::armem::server::ltm::extractor
+{
+    void DepthImageExtractorVisitor::visitDictOnEnter(Input& data)
+    {
+        ARMARX_CHECK_NOT_NULL(data);
+
+        auto dict = aron::data::Dict::DynamicCastAndCheck(data);
+        for (const auto& [key, child] : dict->getElements())
+        {
+            if (child && child->getDescriptor() == aron::data::Descriptor::eNDArray)
+            {
+                auto ndarray = aron::data::NDArray::DynamicCastAndCheck(child);
+                auto shape = ndarray->getShape();
+                if (shape.size() == 3 && shape[2] == 4 && std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<int>()) > 200) // must be big enough to assume an image (instead of 4x4x4 poses)
+                {
+                    depthImages[key] = ndarray;
+                    dict->setElement(key, nullptr);
+                }
+            }
+        }
+    }
+
+    void DepthImageExtractorVisitor::visitUnknown(Input&)
+    {
+        // A member is null. Simply ignore...
+    }
+
+    Extractor::Extraction DepthImageExtractor::extract(aron::data::DictPtr& data)
+    {
+        DepthImageExtractorVisitor visitor;
+        aron::data::VariantPtr var = std::static_pointer_cast<aron::data::Variant>(data);
+        aron::data::VariantPtr p;
+        aron::data::visitRecursive(visitor, var);
+
+        Extraction encoding;
+        encoding.dataWithoutExtraction = data;
+        encoding.extraction = visitor.depthImages;
+        return encoding;
+    }
+
+    aron::data::DictPtr DepthImageExtractor::merge(Extraction& encoding)
+    {
+        return encoding.dataWithoutExtraction;
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/DepthImageExtractor.h b/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/DepthImageExtractor.h
new file mode 100644
index 000000000..09b305e3c
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/DepthImageExtractor.h
@@ -0,0 +1,31 @@
+#pragma once
+
+// Base Class
+#include "../Extractor.h"
+
+#include <RobotAPI/libraries/aron/core/data/visitor/variant/VariantVisitor.h>
+
+namespace armarx::armem::server::ltm::extractor
+{
+    class DepthImageExtractorVisitor : public aron::data::RecursiveVariantVisitor
+    {
+    public:
+        std::map<std::string, aron::data::VariantPtr> depthImages;
+
+        void visitDictOnEnter(Input& data);
+        void visitUnknown(Input& data);
+    };
+
+    class DepthImageExtractor : public Extractor
+    {
+    public:
+        DepthImageExtractor() :
+            Extractor(aron::type::Descriptor::eImage, "depthimage")
+        {
+            enabled = true;
+        };
+
+        virtual Extraction extract(aron::data::DictPtr& data) override;
+        virtual aron::data::DictPtr merge(Extraction& encoding) override;
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/ImageExtractor.cpp b/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/ImageExtractor.cpp
index ff86e0624..c646a4f47 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/ImageExtractor.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/ImageExtractor.cpp
@@ -14,7 +14,7 @@ namespace armarx::armem::server::ltm::extractor
             {
                 auto ndarray = aron::data::NDArray::DynamicCastAndCheck(child);
                 auto shape = ndarray->getShape();
-                if (shape.size() == 3 && std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<int>()) > 200) // must be big enough to assume an image (instead of 4x4x4 poses)
+                if (shape.size() == 3 && (shape[2] == 3 || shape[2] == 1 /* 3 channel color or grayscale */) && std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<int>()) > 200) // must be big enough to assume an image (instead of 4x4x4 poses)
                 {
                     images[key] = ndarray;
                     dict->setElement(key, nullptr);
diff --git a/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/ImageExtractor.h b/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/ImageExtractor.h
index 73a923579..be9c80ba7 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/ImageExtractor.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/base/extractor/imageExtractor/ImageExtractor.h
@@ -20,7 +20,7 @@ namespace armarx::armem::server::ltm::extractor
     {
     public:
         ImageExtractor() :
-            Extractor(aron::type::Descriptor::eImage)
+            Extractor(aron::type::Descriptor::eImage, "image")
         {
             enabled = true;
         };
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/CoreSegment.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/CoreSegment.cpp
index 14e8f31fa..ef68e7f01 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/CoreSegment.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/CoreSegment.cpp
@@ -91,6 +91,9 @@ namespace armarx::armem::server::ltm::disk
 
     void CoreSegment::_store(const armem::wm::CoreSegment& c)
     {
+        auto currentMaxExport = currentExport;
+        auto encodingModeOfPast = currentMode;
+
         if (id().coreSegmentName.empty())
         {
             ARMARX_WARNING << "During storage of segment '" << c.id().str() << "' I noticed that the corresponding LTM has no id set. " <<
@@ -110,7 +113,7 @@ namespace armarx::armem::server::ltm::disk
 
         c.forEachProviderSegment([&](const auto& prov)
         {
-            ProviderSegment c(memoryParentPath, id().withProviderSegmentName(prov.id().providerSegmentName), processors, currentMode, currentExport);
+            ProviderSegment c(memoryParentPath, id().withProviderSegmentName(prov.id().providerSegmentName), processors, encodingModeOfPast, currentMaxExport);
             util::ensureFolderExists(defaultMPath, c.getRelativePathForMode(defaultMode), true);
             c.store(prov);
         });
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/Entity.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/Entity.cpp
index a46aee88a..ac1703ac9 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/Entity.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/Entity.cpp
@@ -29,17 +29,47 @@ namespace armarx::armem::server::ltm::disk
             return false;
         }
 
-        for (const auto& subdirName : util::getAllDirectories(mPath, relPath))
+        for (const auto& hName : util::getAllDirectories(mPath, relPath))
         {
-            if (!util::isNumber(subdirName))
+            if (!util::isNumber(hName))
             {
-                ARMARX_WARNING << "Found a non-timestamp folder inside an entity '" << id().str() << "' with name '" << subdirName << "'. " <<
+                ARMARX_WARNING << "Found a non-timestamp folder inside an entity '" << id().str() << "' with name '" << hName << "'. " <<
                                   "Ignoring this folder, however this is a bad situation.";
                 continue;
             }
 
-            EntitySnapshot c(memoryParentPath, id().withTimestamp(timeFromStringMicroSeconds(subdirName)), processors, currentMode, currentExport);
-            func(c);
+            // check if this is already a microsec folder (legacy export support)
+            //if (std::stol(secName) > 1647524607 /* the time in us the new export was implemented */)
+            //{
+            //    EntitySnapshot c(memoryParentPath, id().withTimestamp(timeFromStringMicroSeconds(secName)), processors, currentMode, currentExport);
+            //    func(c);
+            //    continue;
+            //}
+
+            auto hRelPath = relPath / hName;
+            for (const auto& secName : util::getAllDirectories(mPath, hRelPath))
+            {
+                if (!util::isNumber(secName))
+                {
+                    ARMARX_WARNING << "Found a non-timestamp folder inside an entity '" << id().str() << "' with name '" << secName << "'. " <<
+                                      "Ignoring this folder, however this is a bad situation.";
+                    continue;
+                }
+
+                auto secRelPath = hRelPath / secName;
+                for (const auto& usecName : util::getAllDirectories(mPath, secRelPath))
+                {
+                    if (!util::isNumber(usecName))
+                    {
+                        ARMARX_WARNING << "Found a non-timestamp folder inside an entity '" << id().str() << "' with name '" << usecName << "'. " <<
+                                          "Ignoring this folder, however this is a bad situation.";
+                        continue;
+                    }
+
+                    EntitySnapshot c(memoryParentPath, id().withTimestamp(timeFromStringMicroSeconds(usecName)), processors, currentMode, currentExport);
+                    func(c);
+                }
+            }
         }
         return true;
     }
@@ -272,9 +302,12 @@ namespace armarx::armem::server::ltm::disk
 
         c.forEachSnapshot([&](const auto& snap)
         {
-            for (unsigned long i = 0; i < currentExport; ++i)
+            auto currentMaxExport = currentExport;
+            auto encodingModeOfPast = currentMode;
+
+            for (unsigned long i = 0; i < currentMaxExport; ++i)
             {
-                MemoryEncodingMode mode = i == 0 ? defaultMode : currentMode;
+                MemoryEncodingMode mode = i == 0 ? defaultMode : encodingModeOfPast;
                 auto mPath = getMemoryBasePathForMode(mode, i);
 
                 EntitySnapshot c(memoryParentPath, id().withTimestamp(snap.id().timestamp), processors, mode, i);
@@ -294,7 +327,7 @@ namespace armarx::armem::server::ltm::disk
                 }
             }
 
-            EntitySnapshot c(memoryParentPath, id().withTimestamp(snap.id().timestamp), processors, currentMode, currentExport);
+            EntitySnapshot c(memoryParentPath, id().withTimestamp(snap.id().timestamp), processors, encodingModeOfPast, currentMaxExport);
             util::ensureFolderExists(defaultMPath, c.getRelativePathForMode(defaultMode));
             c.store(snap);
         });
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/EntitySnapshot.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/EntitySnapshot.cpp
index 870292195..a4aece1fd 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/EntitySnapshot.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/EntitySnapshot.cpp
@@ -14,7 +14,7 @@ namespace armarx::armem::server::ltm::disk
 {
     EntitySnapshot::EntitySnapshot(const std::filesystem::path& p, const MemoryID& id, const std::shared_ptr<Processors>& filters, const DiskMemoryItem::MemoryEncodingMode mode, const unsigned long e) :
         EntitySnapshotBase(id, filters),
-        DiskMemoryItem(p, EscapeSegmentName(id.memoryName), std::filesystem::path(EscapeSegmentName(id.coreSegmentName)) / EscapeSegmentName(id.providerSegmentName) / EscapeSegmentName(id.entityName) / id.timestampStr()),
+        DiskMemoryItem(p, EscapeSegmentName(id.memoryName), std::filesystem::path(EscapeSegmentName(id.coreSegmentName)) / EscapeSegmentName(id.providerSegmentName) / EscapeSegmentName(id.entityName) / std::to_string(id.timestamp.toSeconds() / 3600 /* hours */) / std::to_string(id.timestamp.toSeconds()) / id.timestampStr()),
         currentMode(mode),
         currentExport(e)
     {
@@ -53,7 +53,7 @@ namespace armarx::armem::server::ltm::disk
             return;
         }
 
-        auto& dictConverter = processors->converters.at(aron::type::Descriptor::eObject);
+        auto& dictConverter = processors->defaultObjectConverter;
 
         // Get data from disk
         for (unsigned int i = 0; i < e.size(); ++i)
@@ -61,17 +61,22 @@ namespace armarx::armem::server::ltm::disk
             std::filesystem::path relIPath = relPath / std::to_string(i) / "";
             if (util::checkIfFolderExists(mPath, relIPath))
             {
-                std::filesystem::path relDataPath = relIPath / (constantes::DATA_FILENAME + dictConverter->suffix);
-                std::filesystem::path relMetadataPath = relIPath / (constantes::METADATA_FILENAME + dictConverter->suffix);
+                std::string dataFilename = (constantes::DATA_FILENAME + dictConverter.suffix);
+                std::string metadataFilename = (constantes::METADATA_FILENAME + dictConverter.suffix);
+                std::filesystem::path relDataPath = relIPath / dataFilename;
+                std::filesystem::path relMetadataPath = relIPath / metadataFilename;
 
                 auto& ins = e.getInstance(i);
                 aron::data::DictPtr datadict = nullptr;
                 aron::data::DictPtr metadatadict = nullptr;
 
-                if (util::checkIfFileExists(mPath, relDataPath))
+                // get list of all files. This ensures that we only have to call fs::exists once for each file
+                auto allFilesInIndexFolder = util::getAllFiles(mPath, relIPath);
+
+                if (std::find(allFilesInIndexFolder.begin(), allFilesInIndexFolder.end(), dataFilename) != allFilesInIndexFolder.end())
                 {
                     auto datafilecontent = util::readDataFromFile(mPath, relDataPath);
-                    auto dataaron = dictConverter->convert(datafilecontent);
+                    auto dataaron = dictConverter.convert(datafilecontent, "");
                     datadict = aron::data::Dict::DynamicCastAndCheck(dataaron);
 
                     // check for special members
@@ -79,18 +84,18 @@ namespace armarx::armem::server::ltm::disk
                     {
                         for (auto& [t, f] : processors->converters)
                         {
-                            if (t == aron::type::Descriptor::eObject)
-                            {
-                                continue;
-                            }
-
-                            std::filesystem::path relMemberPath = relIPath / (key + f->suffix);
-
-                            if (util::checkIfFileExists(mPath, relMemberPath))
+                            for (const auto& filename : allFilesInIndexFolder) // iterate over all files and search for matching ones
                             {
-                                auto memberfilecontent = util::readDataFromFile(mPath, relMemberPath);
-                                auto memberaron = f->convert(memberfilecontent);
-                                datadict->setElement(key, memberaron);
+                                if (simox::alg::starts_with(filename, key) and simox::alg::ends_with(filename, f->suffix))
+                                {
+                                    std::filesystem::path relMemberPath = relIPath / filename;
+                                    std::string mode = simox::alg::remove_suffix(simox::alg::remove_prefix(filename, key), f->suffix);
+
+                                    auto memberfilecontent = util::readDataFromFile(mPath, relMemberPath);
+                                    auto memberaron = f->convert(memberfilecontent, mode);
+                                    datadict->setElement(key, memberaron);
+                                    break;
+                                }
                             }
                         }
                     }
@@ -100,10 +105,10 @@ namespace armarx::armem::server::ltm::disk
                     ARMARX_ERROR << "Could not find the data file '" << relDataPath.string() << "'. Continuing without data.";
                 }
 
-                if (util::checkIfFileExists(mPath, relMetadataPath))
+                if (std::find(allFilesInIndexFolder.begin(), allFilesInIndexFolder.end(), metadataFilename) != allFilesInIndexFolder.end())
                 {
                     auto metadatafilecontent = util::readDataFromFile(mPath, relMetadataPath);
-                    auto metadataaron = dictConverter->convert(metadatafilecontent);
+                    auto metadataaron = dictConverter.convert(metadatafilecontent, "");
                     metadatadict = aron::data::Dict::DynamicCastAndCheck(metadataaron);
                 }
                 else
@@ -122,6 +127,9 @@ namespace armarx::armem::server::ltm::disk
 
     void EntitySnapshot::_store(const armem::wm::EntitySnapshot& e) const
     {
+        //auto currentMaxExport = currentExport;
+        //auto encodingModeOfPast = currentMode;
+
         if (id().timestampStr().empty())
         {
             ARMARX_WARNING << "During storage of segment '" << e.id().str() << "' I noticed that the corresponding LTM has no id set. " <<
@@ -131,7 +139,7 @@ namespace armarx::armem::server::ltm::disk
 
         auto defaultMode = MemoryEncodingMode::FILESYSTEM;
 
-        auto& dictConverter = processors->converters.at(aron::type::Descriptor::eObject);
+        auto& dictConverter = processors->defaultObjectConverter;
 
         auto defaultMPath = getMemoryBasePathForMode(defaultMode, 0);
         auto defaultRelPath = getRelativePathForMode(defaultMode);
@@ -152,8 +160,8 @@ namespace armarx::armem::server::ltm::disk
             {
                 util::ensureFolderExists(defaultMPath, defaultRelIPath);
 
-                std::filesystem::path relDataPath = defaultRelIPath / (constantes::DATA_FILENAME + dictConverter->suffix);
-                std::filesystem::path relMetadataPath = defaultRelIPath / (constantes::METADATA_FILENAME + dictConverter->suffix);
+                std::filesystem::path relDataPath = defaultRelIPath / (constantes::DATA_FILENAME + dictConverter.suffix);
+                std::filesystem::path relMetadataPath = defaultRelIPath / (constantes::METADATA_FILENAME + dictConverter.suffix);
 
                 auto& ins = e.getInstance(i);
 
@@ -167,7 +175,7 @@ namespace armarx::armem::server::ltm::disk
                 {
                     if (!x->enabled) continue;
 
-                    auto t = x->extractsType;
+                    const auto& t = x->identifier;
 
                     Converter* conv = nullptr; // find suitable converter
                     for (const auto& [ct, c] : processors->converters)
@@ -184,9 +192,11 @@ namespace armarx::armem::server::ltm::disk
                         for (const auto& [memberName, var] : dataExt.extraction)
                         {
                             ARMARX_CHECK_NOT_NULL(var);
-                            std::filesystem::path relMemberPath = defaultRelIPath / (memberName + conv->suffix);
-                            auto memberDataVec = conv->convert(var);
-                            util::writeDataToFile(defaultMPath, relMemberPath, memberDataVec);
+
+                            auto [memberDataVec, memberDataModeSuffix] = conv->convert(var);
+                            std::filesystem::path relMemberPath = defaultRelIPath / (memberName + memberDataModeSuffix + conv->suffix);
+
+                            util::writeDataToFileRepeated(defaultMPath, relMemberPath, memberDataVec);
                         }
 
                         dataAron = dataExt.dataWithoutExtraction;
@@ -195,10 +205,13 @@ namespace armarx::armem::server::ltm::disk
                 }
 
                 // convert dict and metadata
-                auto dataVec = dictConverter->convert(dataAron);
-                auto metadataVec = dictConverter->convert(metadataAron);
-                util::writeDataToFile(defaultMPath, relDataPath, dataVec);
-                util::writeDataToFile(defaultMPath, relMetadataPath, metadataVec);
+                auto [dataVec, dataVecModeSuffix] = dictConverter.convert(dataAron);
+                auto [metadataVec, metadataVecModeSuffix] = dictConverter.convert(metadataAron);
+                ARMARX_CHECK_EMPTY(dataVecModeSuffix);
+                ARMARX_CHECK_EMPTY(metadataVecModeSuffix);
+
+                util::writeDataToFileRepeated(defaultMPath, relDataPath, dataVec);
+                util::writeDataToFileRepeated(defaultMPath, relMetadataPath, metadataVec);
             }
             // Ignore if the full index already exists. Actually this should not happen since the existence of the ts folder is checked on entity level
         }
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.cpp
index c90cb8e33..50cde9d18 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.cpp
@@ -11,7 +11,7 @@ namespace armarx::armem::server::ltm::disk
     {
         Base::createPropertyDefinitions(properties, prefix);
         properties->optional(memoryParentPath, prefix + "storagepath", "The path to the memory storage (the memory will be stored in a seperate subfolder).");
-        properties->optional(sizeToCompressDataInBytes, prefix + "sizeToCompressDataInBytes", "The size in bytes to compress away the current export. Exports are numbered (lower number means newer).");
+        properties->optional(sizeToCompressDataInMegaBytes, prefix + "sizeToCompressDataInMegaBytes", "The size in MB to compress away the current export. Exports are numbered (lower number means newer).");
     }
 
     Memory::Memory() :
@@ -129,7 +129,7 @@ namespace armarx::armem::server::ltm::disk
         std::lock_guard l(ltm_mutex); // we cannot store a memory multiple times simultaneously
 
         MemoryEncodingMode defaultMode = MemoryEncodingMode::FILESYSTEM;
-        MemoryEncodingMode defaultEncodeMode = exportEncodingMode;
+        MemoryEncodingMode encodeModeOfPast = exportEncodingMode;
         // Storage will always be in filesystem mode!
         // Somehow, minizip was not able to write data to images. It always created a folder named xyz.png without any data in it...
         // Another problem is that storing data directly in compressed format will require a lot of time when the compressed file is big (>20MB)
@@ -143,31 +143,37 @@ namespace armarx::armem::server::ltm::disk
 
         auto defaultMPath = getMemoryBasePathForMode(defaultMode, 0);
 
-        // Check if we have to move the memory!
+        // Check if we have to compress the memory!
         // See above mentioned issues with directly compressing the data. Therefore we store data in plain text and compress from time to time
-        // using system calls. Also increase all old exports
+        // using system calls. Also increase the index of all old exports
         auto size = filesystem::util::getSizeOfDirectory(defaultMPath);
         //std::cout << "Current maxExportIndex is: " << maxExportIndex << std::endl;
-        if (size >= sizeToCompressDataInBytes)
+        if (size >= (sizeToCompressDataInMegaBytes * 1024 * 1024))
         {
-            // increase old memories
+            ARMARX_INFO << "Compressen of memory " + id().memoryName + " needed because the size of last export is " + std::to_string(size / 1024.f / 1024.f) + " (>= " + std::to_string(sizeToCompressDataInMegaBytes) + ")";
+
+            // increase index of old memories
             for (unsigned long i = maxExportIndex; i >= 1; --i)
             {
-                auto exportPath = getMemoryBasePathForMode(defaultEncodeMode, i);
-                auto newExportPath = getMemoryBasePathForMode(defaultEncodeMode, i+1);
+                ARMARX_INFO << "Increasing the index of old compressed memory " + id().memoryName + " (" + std::to_string(i) + " to " + std::to_string(i+1) + ")";
+                auto exportPath = getMemoryBasePathForMode(encodeModeOfPast, i);
+                auto newExportPath = getMemoryBasePathForMode(encodeModeOfPast, i+1);
                 std::string moveCommand = "mv " + exportPath.string() + " " + newExportPath.string();
                 //std::cout << "Exec command: " << moveCommand << std::endl;
                 int ret = system(moveCommand.c_str());
                 (void) ret;
             }
 
-            // zip current export
-            auto newExportPath = getMemoryBasePathForMode(defaultEncodeMode, 1); // 1 will be the new export
+            // zip away current export
+            ARMARX_INFO << "Compressing the last export of " + id().memoryName;
+            auto newExportPath = getMemoryBasePathForMode(encodeModeOfPast, 1); // 1 will be the new export
             std::string zipCommand = "cd " + memoryParentPath.string() + " && zip -r " + newExportPath.string() + " " + escapedMemoryName;
             //std::cout << "Exec command: " << zipCommand << std::endl;
             int ret = system(zipCommand.c_str());
             (void) ret;
 
+            // remove unzipped memory export
+            ARMARX_INFO << "Removing the last export of " + id().memoryName;
             std::string rmCommand = "rm -r " + defaultMPath.string();
             ret = system(rmCommand.c_str());
             (void) ret;
@@ -179,7 +185,7 @@ namespace armarx::armem::server::ltm::disk
 
         memory.forEachCoreSegment([&](const auto& core)
         {
-            CoreSegment c(memoryParentPath, id().withCoreSegmentName(core.id().coreSegmentName), processors, defaultEncodeMode, maxExportIndex);
+            CoreSegment c(memoryParentPath, id().withCoreSegmentName(core.id().coreSegmentName), processors, encodeModeOfPast, 0 /* how far to look back in past on enity level. For full lookup use maxExportIndex. */);
             util::ensureFolderExists(defaultMPath, c.getRelativePathForMode(defaultMode), true); // create subfolder
             c.store(core);
         });
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.h b/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.h
index e0b8a6551..085a56459 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.h
@@ -38,6 +38,9 @@ namespace armarx::armem::server::ltm::disk
     private:
         MemoryEncodingMode exportEncodingMode = MemoryEncodingMode::MINIZIP;
         unsigned long maxExportIndex = 0;
-        unsigned long sizeToCompressDataInBytes = long(5) * 1024 * 1024 * 1024; // 5GB
+        unsigned long sizeToCompressDataInMegaBytes = long(1) * 1024; // 1GB
+
+    public:
+        static const int DEPTH_TO_DATA_FILES = 7; // from memory folder = 1 (cseg) + 1 (pseg) + 1 (ent) + 3 (snap) + 1 (inst)
     };
 } // namespace armarx::armem::server::ltm::disk
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/ProviderSegment.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/ProviderSegment.cpp
index a056f85ce..067ff6bdd 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/ProviderSegment.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/ProviderSegment.cpp
@@ -93,6 +93,9 @@ namespace armarx::armem::server::ltm::disk
 
     void ProviderSegment::_store(const armem::wm::ProviderSegment& p)
     {
+        auto currentMaxExport = currentExport;
+        auto encodingModeOfPast = currentMode;
+
         if (id().providerSegmentName.empty())
         {
             ARMARX_WARNING << "During storage of segment '" << p.id().str() << "' I noticed that the corresponding LTM has no id set. " <<
@@ -112,7 +115,7 @@ namespace armarx::armem::server::ltm::disk
 
         p.forEachEntity([&](const auto& e)
         {
-            Entity c(memoryParentPath, id().withEntityName(e.id().entityName), processors, currentMode, currentExport);
+            Entity c(memoryParentPath, id().withEntityName(e.id().entityName), processors, encodingModeOfPast, currentMaxExport);
             util::ensureFolderExists(defaultMPath, c.getRelativePathForMode(defaultMode), true);
             c.store(e);
         });
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/detail/util/util.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/detail/util/util.cpp
index 701245811..8828dc595 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/detail/util/util.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/detail/util/util.cpp
@@ -1,5 +1,8 @@
 #include "util.h"
 
+#include <thread>
+#include <chrono>
+
 namespace armarx::armem::server::ltm::disk
 {
     namespace util
@@ -87,6 +90,26 @@ namespace armarx::armem::server::ltm::disk
             return filesystem::util::writeDataInFilesystemFile(mPath / p, data);
         }
 
+        void writeDataToFileRepeated(const std::filesystem::path& mPath, const std::filesystem::path& p, const std::vector<unsigned char>& data, const unsigned int maxTries, const unsigned int sleepTimeMs)
+        {
+            for (unsigned int i = 0; i < maxTries; ++i)
+            {
+                try
+                {
+                    writeDataToFile(mPath, p, data);
+                    return;
+                }
+                catch (const error::ArMemError&)
+                {
+                    // wait a bit to give the filesystem enough time to manage the workload
+                    std::this_thread::sleep_for(std::chrono::milliseconds(sleepTimeMs));
+                }
+            }
+
+            // even after all the tries we did not succeeded. This is very bad!
+            throw error::ArMemError("ATTENTION! Even after " + std::to_string(maxTries) + " tries, the memory was not able to store the instance at path '" + p.string() + "'. This means this instance will be lost!");
+        }
+
         std::vector<unsigned char> readDataFromFile(const std::filesystem::path& mPath, const std::filesystem::path& p)
         {
             if (mPath.extension() == minizip::util::MINIZIP_SUFFIX)
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/detail/util/util.h b/source/RobotAPI/libraries/armem/server/ltm/disk/detail/util/util.h
index 58dc28123..e260d7092 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/detail/util/util.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/detail/util/util.h
@@ -33,6 +33,8 @@ namespace armarx::armem::server::ltm::disk
 
         void writeDataToFile(const std::filesystem::path& mPath, const std::filesystem::path& p, const std::vector<unsigned char>& data);
 
+        void writeDataToFileRepeated(const std::filesystem::path& mPath, const std::filesystem::path& p, const std::vector<unsigned char>& data, const unsigned int maxTries = 100, const unsigned int sleepTimeMs = 10);
+
         std::vector<unsigned char> readDataFromFile(const std::filesystem::path& mPath, const std::filesystem::path& p);
 
         std::vector<std::string> getAllDirectories(const std::filesystem::path& mPath, const std::filesystem::path& p);
diff --git a/source/RobotAPI/libraries/armem_gui/disk/ControlWidget.cpp b/source/RobotAPI/libraries/armem_gui/disk/ControlWidget.cpp
index ff966676a..d8755bbfd 100644
--- a/source/RobotAPI/libraries/armem_gui/disk/ControlWidget.cpp
+++ b/source/RobotAPI/libraries/armem_gui/disk/ControlWidget.cpp
@@ -144,9 +144,9 @@ namespace armarx::armem::gui::disk
         bool isSingleMemory = false;
         for (auto i = std::filesystem::recursive_directory_iterator(path); i != std::filesystem::recursive_directory_iterator(); ++i)
         {
-            if (i.depth() > 7)
+            if (i.depth() > armem::server::ltm::disk::Memory::DEPTH_TO_DATA_FILES + 2)
             {
-                // After depth 7 we stop searching to not freeze GUI too long
+                // After some depth we stop searching to not freeze GUI too long
                 setStatus("Could not import a memory from " + path.string() + ". Data files were not found until max-depth 7. Skipping import.");
                 return memoryData;
             }
@@ -156,7 +156,7 @@ namespace armarx::armem::gui::disk
             // if one matches it is enough to check
             if (std::filesystem::is_regular_file(dir.path()) && simox::alg::starts_with(dir.path().filename(), "data.aron"))
             {
-                isSingleMemory = (i.depth() == 5);
+                isSingleMemory = (i.depth() == armem::server::ltm::disk::Memory::DEPTH_TO_DATA_FILES);
                 break;
             }
         }
@@ -168,7 +168,7 @@ namespace armarx::armem::gui::disk
         // const query::data::Input queryIce = queryInput.toIce();
 
         int numLoaded = 0;
-        auto loadMemory = [&](const std::filesystem::path& p){
+        auto loadMemory = [&](const std::filesystem::path& p) {
             if (std::filesystem::is_directory(p))
             {
                 armem::server::ltm::disk::Memory ltm(p.parent_path(), p.filename());
@@ -185,7 +185,7 @@ namespace armarx::armem::gui::disk
         }
         else
         {
-            // we load multiple memories
+            // we have to load multiple memories (each subfolder)
             for (const auto& dir : std::filesystem::directory_iterator(path))
             {
                 loadMemory(dir.path());
diff --git a/source/RobotAPI/libraries/armem_gui/instance/InstanceView.cpp b/source/RobotAPI/libraries/armem_gui/instance/InstanceView.cpp
index 708ba8739..61918cb20 100644
--- a/source/RobotAPI/libraries/armem_gui/instance/InstanceView.cpp
+++ b/source/RobotAPI/libraries/armem_gui/instance/InstanceView.cpp
@@ -696,7 +696,10 @@ namespace armarx::armem::gui::instance
         try
         {
             // TODO We cannot know what the str in the pixeltype belongs to (e.g. coming from java, python, c++ it may contain different values!
-            //pixelType = aron::type::Image::pixelTypeFromName(imageData->getType());
+            // pixelType = aron::type::Image::pixelTypeFromName(imageData->getType());
+
+            // For now we assume it comes from c++ where '5' means CV_32FC1 (=5)
+            pixelType = (imageData->getType() == "5" ? PixelType::depth32 : PixelType::rgb24);
         }
         catch (const aron::error::AronException&)
         {
-- 
GitLab