diff --git a/source/RobotAPI/libraries/armem/client/util/SimpleReaderBase.cpp b/source/RobotAPI/libraries/armem/client/util/SimpleReaderBase.cpp
index ce25109502b1da09cb01399396a5c7bca92ed50f..b0bbf2869134f92cdf15e45bde4dd264dda2d1b0 100644
--- a/source/RobotAPI/libraries/armem/client/util/SimpleReaderBase.cpp
+++ b/source/RobotAPI/libraries/armem/client/util/SimpleReaderBase.cpp
@@ -20,6 +20,8 @@ namespace armarx::armem::client::util
 
         const std::string prefix = propertyPrefix();
 
+        props = defaultProperties();
+
         def->optional(props.memoryName, prefix + "Memory");
         def->optional(props.coreSegmentName, prefix + "CoreSegment");
     }
diff --git a/source/RobotAPI/libraries/armem_vision/CMakeLists.txt b/source/RobotAPI/libraries/armem_vision/CMakeLists.txt
index cc81788baa40cf3089de08f3699ac8e9cf026c36..f8bbe5ec1db7641c9f634ff51ba6416e1d2dbb81 100644
--- a/source/RobotAPI/libraries/armem_vision/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem_vision/CMakeLists.txt
@@ -19,13 +19,18 @@ armarx_add_library(
         ./client/laser_scans/Writer.h
         ./client/occupancy_grid/Reader.h
         ./client/occupancy_grid/Writer.h
+        ./client/laser_scanner_features/Reader.h
+        ./client/laser_scanner_features/Writer.h
         ./OccupancyGridHelper.h
+        constants.h
     SOURCES
         ./aron_conversions.cpp
         ./client/laser_scans/Reader.cpp
         ./client/laser_scans/Writer.cpp
         ./client/occupancy_grid/Reader.cpp
         ./client/occupancy_grid/Writer.cpp
+        ./client/laser_scanner_features/Reader.cpp
+        ./client/laser_scanner_features/Writer.cpp
         ./OccupancyGridHelper.cpp
 )
 
@@ -34,6 +39,7 @@ armarx_enable_aron_file_generation_for_target(
         "${LIB_NAME}"
     ARON_FILES
         aron/LaserScan.xml
+        aron/LaserScannerFeatures.xml
         aron/OccupancyGrid.xml
 )
 
diff --git a/source/RobotAPI/libraries/armem_vision/OccupancyGridHelper.h b/source/RobotAPI/libraries/armem_vision/OccupancyGridHelper.h
index 4b936b6e5bbc7de8141ea380efdac63f3e8d14ad..89ee1de1132faa3298765bd1c28fda208ca164a7 100644
--- a/source/RobotAPI/libraries/armem_vision/OccupancyGridHelper.h
+++ b/source/RobotAPI/libraries/armem_vision/OccupancyGridHelper.h
@@ -2,14 +2,14 @@
 
 #include <Eigen/Core>
 
-namespace armarx::armem
+namespace armarx::armem::vision
 {
     struct OccupancyGrid;
 }
 
 namespace armarx
 {
-    using armarx::armem::OccupancyGrid;
+    using armarx::armem::vision::OccupancyGrid;
 
     namespace detail
     {
diff --git a/source/RobotAPI/libraries/armem_vision/aron/LaserScan.xml b/source/RobotAPI/libraries/armem_vision/aron/LaserScan.xml
index f2d11c2e4111dfd0c24896ba807aef6435b7014b..9ad92092e4f2fde9a14450e0bf36bacb8cc84326 100644
--- a/source/RobotAPI/libraries/armem_vision/aron/LaserScan.xml
+++ b/source/RobotAPI/libraries/armem_vision/aron/LaserScan.xml
@@ -8,7 +8,7 @@
 
     <GenerateTypes>
 
-        <Object name='armarx::armem::arondto::LaserScannerInfo'>
+        <Object name='armarx::armem::vision::arondto::LaserScannerInfo'>
             <ObjectChild key='device'>
                 <string />
             </ObjectChild>
@@ -26,7 +26,7 @@
             </ObjectChild>
         </Object>
 
-        <Object name="armarx::armem::arondto::SensorHeader">
+        <Object name="armarx::armem::vision::arondto::SensorHeader">
             <ObjectChild key="agent">
                 <string/>
             </ObjectChild>
@@ -39,9 +39,9 @@
         </Object>
 
 
-        <Object name='armarx::armem::arondto::LaserScanStamped'>
+        <Object name='armarx::armem::vision::arondto::LaserScanStamped'>
             <ObjectChild key="header">
-                <armarx::armem::arondto::SensorHeader />
+                <armarx::armem::vision::arondto::SensorHeader />
             </ObjectChild>
 
             <!-- 
@@ -51,4 +51,4 @@
         </Object>
 
     </GenerateTypes>
-</AronTypeDefinition> 
\ No newline at end of file
+</AronTypeDefinition> 
diff --git a/source/RobotAPI/libraries/armem_vision/aron/LaserScannerFeatures.xml b/source/RobotAPI/libraries/armem_vision/aron/LaserScannerFeatures.xml
new file mode 100644
index 0000000000000000000000000000000000000000..32600d7d19eef8f3969bde99c4a66d60635cf4c6
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_vision/aron/LaserScannerFeatures.xml
@@ -0,0 +1,67 @@
+<!--Some fancy comment -->
+<?xml version="1.0" encoding="UTF-8" ?>
+<AronTypeDefinition>
+    <CodeIncludes>
+    </CodeIncludes>
+    <AronIncludes>
+    </AronIncludes>
+
+    <GenerateTypes>
+
+        <Object name='armarx::armem::vision::arondto::Ellipsoid'>
+            <ObjectChild key='globalPose'>
+                <Pose />
+            </ObjectChild>
+            <ObjectChild key='radii'>
+                <Matrix rows="2" cols="1" type="float32" />
+            </ObjectChild>
+        </Object>
+
+        <Object name='armarx::armem::vision::arondto::Circle'>
+            <ObjectChild key='center'>
+                <Matrix rows="2" cols="1" type="float32" />
+            </ObjectChild>
+            <ObjectChild key='radius'>
+                <float />
+            </ObjectChild>
+        </Object>
+
+        <Object name="armarx::armem::vision::arondto::LaserScannerFeature">
+            <ObjectChild key="convexHull">
+                <List>
+                    <Matrix rows="2" cols="1" type="float32" />
+                </List>
+            </ObjectChild>
+            <ObjectChild key="circle">
+                <armarx::armem::vision::arondto::Circle/>
+            </ObjectChild>
+            <ObjectChild key="ellipsoid">
+                <armarx::armem::vision::arondto::Ellipsoid/>
+            </ObjectChild>
+            <!-- <ObjectChild key="chain">
+                <armarx::armem::vision::arondto::Chain/>
+            </ObjectChild> -->
+            <ObjectChild key="points">
+                <List>
+                    <Matrix rows="2" cols="1" type="float32" />
+                </List>
+            </ObjectChild>
+        </Object>
+
+         <Object name="armarx::armem::vision::arondto::LaserScannerFeatures">
+            <ObjectChild key="frame">
+                <String/>
+            </ObjectChild>
+            <ObjectChild key="frameGlobalPose">
+                <Pose/>
+            </ObjectChild>
+            <ObjectChild key="features">
+                <List>
+                    <armarx::armem::vision::arondto::LaserScannerFeature />
+                </List>
+            </ObjectChild>
+        </Object>
+
+
+    </GenerateTypes>
+</AronTypeDefinition> 
diff --git a/source/RobotAPI/libraries/armem_vision/aron/OccupancyGrid.xml b/source/RobotAPI/libraries/armem_vision/aron/OccupancyGrid.xml
index 0c508a4e2138b4b04c126287bf46d8826fb3da6f..3f273cded23f6942d6be82f76521f929146fb21e 100644
--- a/source/RobotAPI/libraries/armem_vision/aron/OccupancyGrid.xml
+++ b/source/RobotAPI/libraries/armem_vision/aron/OccupancyGrid.xml
@@ -8,7 +8,7 @@
 
     <GenerateTypes>
 
-        <Object name='armarx::armem::arondto::OccupancyGrid'>
+        <Object name='armarx::armem::vision::arondto::OccupancyGrid'>
             <ObjectChild key='resolution'>
                 <float />
             </ObjectChild>
@@ -27,4 +27,4 @@
 
 
     </GenerateTypes>
-</AronTypeDefinition> 
\ No newline at end of file
+</AronTypeDefinition> 
diff --git a/source/RobotAPI/libraries/armem_vision/aron_conversions.cpp b/source/RobotAPI/libraries/armem_vision/aron_conversions.cpp
index 4819a27abc53f7b10696da6d452bb2d133a82fd4..cadb4fdcda9f18695833a462e0bef2acfe91451d 100644
--- a/source/RobotAPI/libraries/armem_vision/aron_conversions.cpp
+++ b/source/RobotAPI/libraries/armem_vision/aron_conversions.cpp
@@ -5,8 +5,9 @@
 #include <iterator>
 
 #include <RobotAPI/interface/units/LaserScannerUnit.h>
-#include <RobotAPI/libraries/armem_vision/aron/LaserScan.aron.generated.h>
 #include <RobotAPI/libraries/armem/core/aron_conversions.h>
+#include <RobotAPI/libraries/armem_vision/aron/LaserScan.aron.generated.h>
+#include <RobotAPI/libraries/armem_vision/aron/LaserScannerFeatures.aron.generated.h>
 #include <RobotAPI/libraries/aron/common/aron_conversions.h>
 #include <RobotAPI/libraries/aron/converter/common/Converter.h>
 #include <RobotAPI/libraries/aron/core/data/variant/complex/NDArray.h>
@@ -14,36 +15,38 @@
 #include "types.h"
 
 
-namespace armarx::armem
+namespace armarx::armem::vision
 {
 
     /************ fromAron ************/
-    SensorHeader fromAron(const arondto::SensorHeader& aronSensorHeader)
+    SensorHeader
+    fromAron(const arondto::SensorHeader& aronSensorHeader)
     {
-        return {.agent     = aronSensorHeader.agent,
-                .frame     = aronSensorHeader.frame,
+        return {.agent = aronSensorHeader.agent,
+                .frame = aronSensorHeader.frame,
                 .timestamp = aron::fromAron<Time>(aronSensorHeader.timestamp)};
     }
 
-    void fromAron(const arondto::LaserScanStamped& aronLaserScan,
-                  LaserScanStamped& laserScan)
+    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)
+    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.toMicroSecondsSinceEpoch();
-        frame     = header.frame;
+        frame = header.frame;
         agentName = header.agent;
     }
 
@@ -54,46 +57,48 @@ namespace armarx::armem
     //     aronLaserScan.scan = toAron(laserScan);
     // }
 
-    int64_t toAron(const armem::Time& timestamp)
+    int64_t
+    toAron(const armem::Time& timestamp)
     {
         return timestamp.toMicroSecondsSinceEpoch();
     }
 
-    arondto::SensorHeader toAron(const SensorHeader& sensorHeader)
+    arondto::SensorHeader
+    toAron(const SensorHeader& sensorHeader)
     {
         arondto::SensorHeader aronSensorHeader;
 
-        aronSensorHeader.agent     = sensorHeader.agent;
-        aronSensorHeader.frame     = sensorHeader.frame;
+        aronSensorHeader.agent = sensorHeader.agent;
+        aronSensorHeader.frame = sensorHeader.frame;
         toAron(aronSensorHeader.timestamp, sensorHeader.timestamp);
 
         return aronSensorHeader;
     }
 
-    void toAron(const LaserScanStamped& laserScanStamped,
-                arondto::LaserScanStamped& aronLaserScanStamped)
+    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)
+    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 SensorHeader header{.agent = agentName, .frame = frame, .timestamp = timestamp};
 
-        const LaserScanStamped laserScanStamped{.header = header,
-                                                .data   = laserScan};
+        const LaserScanStamped laserScanStamped{.header = header, .data = laserScan};
 
         toAron(laserScanStamped, aronLaserScanStamped);
     }
 
-    void toAron(arondto::OccupancyGrid& dto, const OccupancyGrid& bo)
+    void
+    toAron(arondto::OccupancyGrid& dto, const OccupancyGrid& bo)
     {
         aron::toAron(dto.frame, bo.frame);
         aron::toAron(dto.pose, bo.pose);
@@ -101,7 +106,8 @@ namespace armarx::armem
         // bo.grid is NdArray -> need special handling.
     }
 
-    void fromAron(const arondto::OccupancyGrid& dto, OccupancyGrid& bo)
+    void
+    fromAron(const arondto::OccupancyGrid& dto, OccupancyGrid& bo)
     {
         aron::fromAron(dto.frame, bo.frame);
         aron::fromAron(dto.pose, bo.pose);
@@ -109,4 +115,70 @@ namespace armarx::armem
         // bo.grid is NdArray -> need special handling.
     }
 
-} // namespace armarx::armem
+    // LaserScannerFeatures
+
+
+    void
+    toAron(arondto::Circle& dto, const Circle& bo)
+    {
+        dto.center = bo.center;
+        dto.radius = bo.radius;
+    }
+
+    void
+    toAron(arondto::Ellipsoid& dto, const Ellipsoid& bo)
+    {
+        dto.globalPose = bo.pose.matrix();
+        dto.radii = bo.radii;
+    }
+
+    void
+    toAron(arondto::LaserScannerFeature& dto, const LaserScannerFeature& bo)
+    {
+        toAron(dto.circle, bo.circle);
+        dto.convexHull = bo.convexHull;
+        toAron(dto.ellipsoid, bo.ellipsoid);
+        dto.points = bo.points;
+    }
+
+    void
+    toAron(arondto::LaserScannerFeatures& dto, const LaserScannerFeatures& bo)
+    {
+        aron::toAron(dto.frame, bo.frame);
+        aron::toAron(dto.frameGlobalPose, bo.frameGlobalPose);
+        aron::toAron(dto.features, bo.features);
+    }
+
+    void
+    fromAron(const arondto::Circle& dto, Circle& bo)
+    {
+        bo.center = dto.center;
+        bo.radius = dto.radius;
+    }
+    void
+    fromAron(const arondto::Ellipsoid& dto, Ellipsoid& bo)
+    {
+        bo.pose = dto.globalPose;
+        bo.radii = dto.radii;
+    }
+
+    void
+    fromAron(const arondto::LaserScannerFeature& dto, LaserScannerFeature& bo)
+    {
+        bo.convexHull = dto.convexHull;
+        fromAron(dto.circle, bo.circle);
+        fromAron(dto.ellipsoid, bo.ellipsoid);
+
+        // bo.chain = dto.chain;
+        bo.points = dto.points;
+    }
+
+    void
+    fromAron(const arondto::LaserScannerFeatures& dto, LaserScannerFeatures& bo)
+    {
+        aron::fromAron(dto.frame, bo.frame);
+        aron::fromAron(dto.frameGlobalPose, bo.frameGlobalPose);
+        aron::fromAron(dto.features, bo.features);
+    }
+
+} // namespace armarx::armem::vision
diff --git a/source/RobotAPI/libraries/armem_vision/aron_conversions.h b/source/RobotAPI/libraries/armem_vision/aron_conversions.h
index 681049dac2250e30ad6a3ccee5f25cc6412b074e..bb1e525344c71ac33fabc7d8eda2102f69777107 100644
--- a/source/RobotAPI/libraries/armem_vision/aron_conversions.h
+++ b/source/RobotAPI/libraries/armem_vision/aron_conversions.h
@@ -21,15 +21,16 @@
 
 #pragma once
 
-#include <RobotAPI/libraries/armem_vision/types.h>
 #include <RobotAPI/interface/units/LaserScannerUnit.h>
 #include <RobotAPI/libraries/armem/core/Time.h>
+#include <RobotAPI/libraries/armem_vision/aron/LaserScannerFeatures.aron.generated.h>
 #include <RobotAPI/libraries/armem_vision/aron/OccupancyGrid.aron.generated.h>
+#include <RobotAPI/libraries/armem_vision/types.h>
 #include <RobotAPI/libraries/aron/converter/common/VectorConverter.h>
 #include <RobotAPI/libraries/aron/converter/eigen/EigenConverter.h>
 #include <RobotAPI/libraries/aron/core/data/variant/complex/NDArray.h>
 
-namespace armarx::armem
+namespace armarx::armem::vision
 {
 
     namespace arondto
@@ -47,14 +48,13 @@ namespace armarx::armem
                   std::string& agentName);
 
     template <typename T>
-    auto fromAron(const aron::data::NDArrayPtr& navigator)
+    auto
+    fromAron(const aron::data::NDArrayPtr& navigator)
     {
-        return aron::converter::AronVectorConverter::ConvertToVector<T>(
-                   navigator);
+        return aron::converter::AronVectorConverter::ConvertToVector<T>(navigator);
     }
 
-    void fromAron(const arondto::LaserScanStamped& aronLaserScan,
-                  LaserScanStamped& laserScan);
+    void fromAron(const arondto::LaserScanStamped& aronLaserScan, LaserScanStamped& laserScan);
 
     void toAron(const LaserScan& laserScan,
                 const armem::Time& timestamp,
@@ -79,4 +79,8 @@ namespace armarx::armem
         return aron::converter::AronEigenConverter::ConvertFromArray(grid);
     }
 
-} // namespace armarx::armem
+    // LaserScannerFeatures
+    void toAron(arondto::LaserScannerFeatures& dto, const LaserScannerFeatures& bo);
+    void fromAron(const arondto::LaserScannerFeatures& dto, LaserScannerFeatures& bo);
+
+} // namespace armarx::armem::vision
diff --git a/source/RobotAPI/libraries/armem_vision/client/laser_scanner_features/Reader.cpp b/source/RobotAPI/libraries/armem_vision/client/laser_scanner_features/Reader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e9cf78c698b31345a9fcc17262bb7a23a25cd7fc
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_vision/client/laser_scanner_features/Reader.cpp
@@ -0,0 +1,218 @@
+#include "Reader.h"
+
+// STD / STL
+#include <algorithm>
+#include <cstring>
+#include <map>
+#include <optional>
+#include <ostream>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// ICE
+#include <IceUtil/Handle.h>
+#include <IceUtil/Time.h>
+
+// Simox
+#include <SimoxUtility/algorithm/get_map_keys_values.h>
+
+// ArmarXCore
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+#include <ArmarXCore/core/logging/LogSender.h>
+#include <ArmarXCore/core/logging/Logging.h>
+
+// RobotAPI Interfaces
+#include <RobotAPI/interface/armem/mns/MemoryNameSystemInterface.h>
+#include <RobotAPI/interface/armem/server/ReadingMemoryInterface.h>
+#include <RobotAPI/interface/units/LaserScannerUnit.h>
+
+// RobotAPI Aron
+#include <RobotAPI/libraries/armem_vision/aron/LaserScannerFeatures.aron.generated.h>
+#include <RobotAPI/libraries/aron/core/Exception.h>
+#include <RobotAPI/libraries/aron/core/data/variant/complex/NDArray.h>
+
+// RobotAPI Armem
+#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/error.h>
+#include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
+#include <RobotAPI/libraries/armem/util/util.h>
+#include <RobotAPI/libraries/armem_vision/aron/LaserScan.aron.generated.h>
+#include <RobotAPI/libraries/armem_vision/aron_conversions.h>
+#include <RobotAPI/libraries/armem_vision/types.h>
+
+
+namespace armarx::armem::vision::laser_scanner_features::client
+{
+
+    Reader::Reader(armem::client::MemoryNameSystem& memoryNameSystem) :
+        memoryNameSystem(memoryNameSystem)
+    {
+    }
+    Reader::~Reader() = default;
+
+
+    void
+    Reader::registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def)
+    {
+        // ARMARX_DEBUG << "TransformReader: registerPropertyDefinitions";
+        // registerPropertyDefinitions(def);
+
+        const std::string prefix = propertyPrefix;
+
+        def->optional(properties.coreSegmentName,
+                      prefix + "CoreSegment",
+                      "Name of the mapping memory core segment to use.");
+
+        def->optional(properties.memoryName, prefix + "MemoryName");
+    }
+
+    void
+    Reader::connect()
+    {
+        // Wait for the memory to become available and add it as dependency.
+        ARMARX_IMPORTANT << "MappingDataReader: Waiting for memory '" << properties.memoryName
+                         << "' ...";
+        try
+        {
+            memoryReader =
+                memoryNameSystem.useReader(MemoryID().withMemoryName(properties.memoryName));
+            ARMARX_IMPORTANT << "MappingDataReader: Connected to memory '" << properties.memoryName
+                             << "'";
+        }
+        catch (const armem::error::CouldNotResolveMemoryServer& e)
+        {
+            ARMARX_ERROR << e.what();
+            return;
+        }
+    }
+
+    armarx::armem::client::query::Builder
+    Reader::buildQuery(const Query& query) const
+    {
+        armarx::armem::client::query::Builder qb;
+
+        qb.coreSegments()
+                       .withName(properties.coreSegmentName)
+                       .providerSegments()
+                       .withName(query.providerName)
+                       .entities()
+                       .all()
+                       .snapshots()
+                       .beforeOrAtTime(query.timestamp);
+
+        // auto entitySel = [&]()
+        // {
+        //     if (query.name.empty())
+        //     {
+        //         ARMARX_INFO << "querying all entities";
+        //         return sel.entities().all();
+        //     }
+        //     return sel.entities().withName(query.name);
+        // }();
+
+        // entitySel.snapshots().beforeOrAtTime(query.timestamp);
+
+        return qb;
+    }
+
+    std::vector<LaserScannerFeatures>
+    asFeaturesList(const wm::ProviderSegment& providerSegment)
+    {
+        if (providerSegment.empty())
+        {
+            ARMARX_WARNING << "No entities!";
+            return {};
+        }
+
+        // const auto convert = [](const auto& aronLaserScanStamped,
+        //                         const wm::EntityInstance& ei) -> LaserScanStamped
+        // {
+        //     LaserScanStamped laserScanStamped;
+        //     fromAron(aronLaserScanStamped, laserScanStamped);
+
+        //     const auto ndArrayNavigator =
+        //         aron::data::NDArray::DynamicCast(ei.data()->getElement("scan"));
+
+        //     ARMARX_CHECK_NOT_NULL(ndArrayNavigator);
+
+        //     laserScanStamped.data = fromAron<LaserScanStep>(ndArrayNavigator);
+        //     ARMARX_IMPORTANT << "4";
+
+        //     return laserScanStamped;
+        // };
+
+        std::vector<LaserScannerFeatures> laserScannerFeatures;
+
+        // loop over all entities and their snapshots
+        providerSegment.forEachEntity(
+            [&](const wm::Entity& entity)
+            {
+                // If we don't need this warning, we could directly iterate over the snapshots.
+                if (entity.empty())
+                {
+                    ARMARX_WARNING << "Empty history for " << entity.id();
+                }
+                ARMARX_DEBUG << "History size: " << entity.size();
+
+                entity.forEachInstance(
+                    [&](const wm::EntityInstance& entityInstance)
+                    {
+                        if (const auto o = tryCast<arondto::LaserScannerFeatures>(entityInstance))
+                        {
+                            LaserScannerFeatures& f = laserScannerFeatures.emplace_back();
+                            fromAron(o.value(), f);
+                        }
+                        return true;
+                    });
+                return true;
+            });
+
+        return laserScannerFeatures;
+    }
+
+    Reader::Result
+    Reader::queryData(const Query& query) const
+    {
+        const auto qb = buildQuery(query);
+
+        ARMARX_DEBUG << "[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 {.features = {},
+                    .status = Result::Status::Error,
+                    .errorMessage = qResult.errorMessage};
+        }
+
+        // now create result from memory
+        const wm::ProviderSegment& providerSegment =
+            qResult.memory.getCoreSegment(properties.coreSegmentName)
+                .getProviderSegment(query.providerName);
+
+        const auto features = asFeaturesList(providerSegment);
+
+        // const auto laserScans = asLaserScans(providerSegment);
+        // std::vector<std::string> sensors;
+        // providerSegment.forEachEntity(
+        //     [&sensors](const wm::Entity& entity)
+        //     {
+        //         sensors.push_back(entity.name());
+        //         return true;
+        //     });
+
+        return {.features = features,
+                // .sensors = sensors,
+                .status = Result::Status::Success,
+                .errorMessage = ""};
+    }
+
+} // namespace armarx::armem::vision::laser_scanner_features::client
diff --git a/source/RobotAPI/libraries/armem_vision/client/laser_scanner_features/Reader.h b/source/RobotAPI/libraries/armem_vision/client/laser_scanner_features/Reader.h
new file mode 100644
index 0000000000000000000000000000000000000000..4752ca85cf3df286b3d1378c2a0526f5a89f1a31
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_vision/client/laser_scanner_features/Reader.h
@@ -0,0 +1,113 @@
+/*
+ * 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 <string>
+#include <vector>
+
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
+#include <ArmarXCore/core/time/DateTime.h>
+
+#include <RobotAPI/libraries/armem/client.h>
+#include <RobotAPI/libraries/armem/client/MemoryNameSystem.h>
+#include <RobotAPI/libraries/armem/client/Reader.h>
+#include <RobotAPI/libraries/armem/client/query/Builder.h>
+#include <RobotAPI/libraries/armem_vision/types.h>
+
+
+namespace armarx
+{
+    class ManagedIceObject;
+}
+
+namespace armarx::armem::vision::laser_scanner_features::client
+{
+
+
+    /**
+    * @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 Reader
+    {
+    public:
+        Reader(armem::client::MemoryNameSystem& memoryNameSystem);
+        virtual ~Reader();
+
+        void connect();
+
+        struct Query
+        {
+            std::string providerName;
+
+            std::string name; // sensor name
+
+            armarx::core::time::DateTime timestamp;
+
+            // std::vector<std::string> sensorList;
+        };
+
+        struct Result
+        {
+            std::vector<LaserScannerFeatures> features;
+
+            // std::vector<std::string> sensors;
+
+            enum Status
+            {
+                Error,
+                Success
+            } status;
+
+            std::string errorMessage;
+        };
+
+        Result queryData(const Query& query) const;
+
+        void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def);
+
+
+    protected:
+        armarx::armem::client::query::Builder buildQuery(const Query& query) const;
+
+    private:
+        armem::client::MemoryNameSystem& memoryNameSystem;
+        armem::client::Reader memoryReader;
+
+        // Properties
+        struct Properties
+        {
+            std::string memoryName = "Vision";
+            std::string coreSegmentName = "LaserScannerFeatures";
+        } properties;
+
+        const std::string propertyPrefix = "mem.vision.laser_scanner_features.";
+    };
+
+} // namespace armarx::armem::vision::laser_scanner_features::client
diff --git a/source/RobotAPI/libraries/armem_vision/client/laser_scanner_features/Writer.cpp b/source/RobotAPI/libraries/armem_vision/client/laser_scanner_features/Writer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5746bffa1880c3031e183acf5cecd74f2d6d515a
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_vision/client/laser_scanner_features/Writer.cpp
@@ -0,0 +1,111 @@
+#include "Writer.h"
+
+#include "RobotAPI/libraries/armem_vision/constants.h"
+#include <RobotAPI/libraries/armem/core/error.h>
+#include <RobotAPI/libraries/armem_vision/aron/LaserScan.aron.generated.h>
+#include <RobotAPI/libraries/armem_vision/aron/LaserScannerFeatures.aron.generated.h>
+#include <RobotAPI/libraries/armem_vision/aron_conversions.h>
+
+
+namespace armarx::armem::vision::laser_scanner_features::client
+{
+
+    Writer::Writer(armem::client::MemoryNameSystem& memoryNameSystem) :
+        memoryNameSystem(memoryNameSystem)
+    {
+    }
+    Writer::~Writer() = default;
+
+
+    void
+    Writer::registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def)
+    {
+        ARMARX_DEBUG << "LaserScansWriter: registerPropertyDefinitions";
+
+        const std::string prefix = propertyPrefix;
+
+        // def->optional(properties.coreSegmentName,
+        //               prefix + "CoreSegment",
+        //               "Name of the mapping memory core segment to use.");
+
+        // def->optional(properties.memoryName, prefix + "MemoryName");
+    }
+
+    void
+    Writer::connect()
+    {
+        // Wait for the memory to become available and add it as dependency.
+        ARMARX_IMPORTANT << "LaserScansWriter: Waiting for memory '" << constants::memoryName
+                         << "' ...";
+        try
+        {
+            memoryWriter =
+                memoryNameSystem.useWriter(MemoryID().withMemoryName(constants::memoryName));
+            ARMARX_IMPORTANT << "MappingDataWriter: Connected to memory '" << constants::memoryName
+                             << "'";
+        }
+        catch (const armem::error::CouldNotResolveMemoryServer& e)
+        {
+            ARMARX_ERROR << e.what();
+            return;
+        }
+
+        ARMARX_IMPORTANT << "LaserScansWriter: Connected to memory '" << constants::memoryName;
+    }
+
+    bool
+    Writer::store(const LaserScannerFeatures& features,
+                  const std::string& providerName,
+                  const Time& timestamp)
+    {
+        std::lock_guard g{memoryWriterMutex};
+
+        // const auto result = memoryWriter.addSegment(constants::memoryName,
+        //                                             constants::laserScannerFeaturesCoreSegment);
+
+        // if (not result.success)
+        // {
+        //     ARMARX_ERROR << result.errorMessage;
+
+        //     // TODO(fabian.reister): message
+        //     return false;
+        // }
+
+        const auto entityID = armem::MemoryID()
+                                    .withMemoryName(constants::memoryName)
+                                    .withCoreSegmentName(constants::laserScannerFeaturesCoreSegment)
+                                    .withProviderSegmentName(providerName)
+                                    .withEntityName(features.frame)
+                                    .withTimestamp(timestamp);
+
+        ARMARX_VERBOSE << "Memory id is " << entityID.str();
+
+        armem::EntityUpdate update;
+        update.entityID = entityID;
+
+        ARMARX_TRACE;
+
+        arondto::LaserScannerFeatures dto;
+        toAron(dto, features);
+
+        ARMARX_TRACE;
+
+        update.instancesData = {dto.toAron()};
+        update.timeCreated = timestamp;
+
+        ARMARX_DEBUG << "Committing " << update << " at time " << timestamp;
+
+        ARMARX_TRACE;
+        armem::EntityUpdateResult updateResult = memoryWriter.commit(update);
+
+        ARMARX_DEBUG << updateResult;
+
+        if (not updateResult.success)
+        {
+            ARMARX_ERROR << updateResult.errorMessage;
+        }
+
+        return updateResult.success;
+    }
+
+} // namespace armarx::armem::vision::laser_scanner_features::client
diff --git a/source/RobotAPI/libraries/armem_vision/client/laser_scanner_features/Writer.h b/source/RobotAPI/libraries/armem_vision/client/laser_scanner_features/Writer.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca58005772268d70f7eedf06189c02250c75fef6
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_vision/client/laser_scanner_features/Writer.h
@@ -0,0 +1,85 @@
+/*
+ * 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 <mutex>
+
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
+
+#include "RobotAPI/libraries/armem_vision/types.h"
+#include <RobotAPI/interface/units/LaserScannerUnit.h>
+#include <RobotAPI/libraries/armem/client/MemoryNameSystem.h>
+#include <RobotAPI/libraries/armem/client/Writer.h>
+
+
+namespace armarx::armem::vision::laser_scanner_features::client
+{
+
+    /**
+    * @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 Writer
+    {
+    public:
+        Writer(armem::client::MemoryNameSystem& memoryNameSystem);
+        virtual ~Writer();
+
+
+        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 store(const LaserScannerFeatures& features,
+                   const std::string& providerName,
+                   const Time& timestamp);
+
+    private:
+        armem::client::MemoryNameSystem& memoryNameSystem;
+        armem::client::Writer memoryWriter;
+
+        // Properties
+        struct Properties
+        {
+            // std::string memoryName = "Vision";
+            // std::string coreSegmentName = "LaserScannerFeatures";
+        } properties;
+
+        std::mutex memoryWriterMutex;
+
+        const std::string propertyPrefix = "mem.vision.laser_scanner_features.";
+    };
+
+} // namespace armarx::armem::vision::laser_scanner_features::client
diff --git a/source/RobotAPI/libraries/armem_vision/client/laser_scans/Reader.cpp b/source/RobotAPI/libraries/armem_vision/client/laser_scans/Reader.cpp
index 5faf563cfab3c4c380258268671f5c7268fe9dd1..396dd1bd8b4f40cfef062fa963e87c97f52f45b4 100644
--- a/source/RobotAPI/libraries/armem_vision/client/laser_scans/Reader.cpp
+++ b/source/RobotAPI/libraries/armem_vision/client/laser_scans/Reader.cpp
@@ -131,7 +131,7 @@ namespace armarx::armem::vision::laser_scans::client
         }
 
         const auto convert =
-            [](const arondto::LaserScanStamped & aronLaserScanStamped,
+            [](const auto& aronLaserScanStamped,
                const wm::EntityInstance & ei) -> LaserScanStamped
         {
             LaserScanStamped laserScanStamped;
@@ -177,7 +177,7 @@ namespace armarx::armem::vision::laser_scans::client
     {
         const auto qb = buildQuery(query);
 
-        ARMARX_IMPORTANT << "[MappingDataReader] query ... ";
+        ARMARX_DEBUG << "[MappingDataReader] query ... ";
 
         const armem::client::QueryResult qResult =
             memoryReader.query(qb.buildQueryInput());
diff --git a/source/RobotAPI/libraries/armem_vision/client/laser_scans/Reader.h b/source/RobotAPI/libraries/armem_vision/client/laser_scans/Reader.h
index 138717c42257e02275a15785940783330126ee4d..349b65a5af3bea2fc6acb17324a42b87fbb3bf8d 100644
--- a/source/RobotAPI/libraries/armem_vision/client/laser_scans/Reader.h
+++ b/source/RobotAPI/libraries/armem_vision/client/laser_scans/Reader.h
@@ -113,7 +113,7 @@ namespace armarx::armem::vision::laser_scans::client
             std::string coreSegmentName = "LaserScans";
         } properties;
 
-        const std::string propertyPrefix = "mem.vision.";
+        const std::string propertyPrefix = "mem.vision.laser_scans.";
 
     };
 
diff --git a/source/RobotAPI/libraries/armem_vision/client/laser_scans/Writer.h b/source/RobotAPI/libraries/armem_vision/client/laser_scans/Writer.h
index afc383634b87a31fc84a841a5658f83ec845ee27..b4f7502ef9493692fc82bf79740d2367fe165d4a 100644
--- a/source/RobotAPI/libraries/armem_vision/client/laser_scans/Writer.h
+++ b/source/RobotAPI/libraries/armem_vision/client/laser_scans/Writer.h
@@ -81,7 +81,7 @@ namespace armarx::armem::vision::laser_scans::client
 
         std::mutex memoryWriterMutex;
 
-        const std::string propertyPrefix = "mem.vision.";
+        const std::string propertyPrefix = "mem.vision.laser_scans.";
 
     };
 
diff --git a/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Reader.cpp b/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Reader.cpp
index bb3bdf5546650f2bb8c45db39b092c0f601c2c9a..91505d40e5ea0046fc2419ac532db85010062011 100644
--- a/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Reader.cpp
+++ b/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Reader.cpp
@@ -115,7 +115,7 @@ namespace armarx::armem::vision::occupancy_grid::client
     {
         const auto qb = buildQuery(query);
 
-        ARMARX_IMPORTANT << "[MappingDataReader] query ... ";
+        ARMARX_DEBUG << "[MappingDataReader] query ... ";
 
         const armem::client::QueryResult qResult =
             memoryReader().query(qb.buildQueryInput());
diff --git a/source/RobotAPI/libraries/armem_vision/constants.h b/source/RobotAPI/libraries/armem_vision/constants.h
new file mode 100644
index 0000000000000000000000000000000000000000..653d6fda6fc9e787d00f570af5440a6c81c6108b
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_vision/constants.h
@@ -0,0 +1,33 @@
+/**
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <string>
+
+namespace armarx::armem::vision::constants
+{
+    const inline std::string memoryName = "Vision";
+
+    // core segments
+    const inline std::string laserScannerFeaturesCoreSegment = "LaserScannerFeatures";
+
+} // namespace armarx::armem::vision::constants
diff --git a/source/RobotAPI/libraries/armem_vision/types.h b/source/RobotAPI/libraries/armem_vision/types.h
index 00fb545a104afb19c38c9d7b01fd864ed6ba1fe6..85322d188ce8fdbd9b065ce476e281408d38f254 100644
--- a/source/RobotAPI/libraries/armem_vision/types.h
+++ b/source/RobotAPI/libraries/armem_vision/types.h
@@ -23,10 +23,12 @@
 
 #include <vector>
 
+#include <VirtualRobot/MathTools.h>
+
 #include <RobotAPI/interface/units/LaserScannerUnit.h>
 #include <RobotAPI/libraries/armem/core/Time.h>
 
-namespace armarx::armem
+namespace armarx::armem::vision
 {
 
     struct SensorHeader
@@ -52,10 +54,50 @@ namespace armarx::armem
 
         // using ValueType = _ValueT;
         using CellType = float;
-        using Grid     = Eigen::Array<CellType, Eigen::Dynamic, Eigen::Dynamic>;
+        using Grid = Eigen::Array<CellType, Eigen::Dynamic, Eigen::Dynamic>;
 
         Grid grid;
     };
 
+    struct Ellipsoid
+    {
+        Eigen::Isometry3f pose = Eigen::Isometry3f::Identity();
+
+        Eigen::Vector2f radii = Eigen::Vector2f::Zero();
+    };
+
+    struct Circle
+    {
+        Eigen::Vector2f center = Eigen::Vector2f::Zero();
+        float radius = 0.F;
+    };
+
+    struct LaserScannerFeature
+    {
+        using Points = std::vector<Eigen::Vector2f>;
+        using Chain = Points;
+
+        Points convexHull;
+
+        Circle circle;
+        Ellipsoid ellipsoid;
+
+        Chain chain;
+
+        Points points;
+    };
+
+    struct LaserScannerFeatures
+    {
+        // TODO(fabian.reister): framed pose
+        std::string frame;
+        Eigen::Isometry3f frameGlobalPose;
+
+        std::vector<LaserScannerFeature> features;
+
+
+        // std::vector<Ellipsoid> linesAsEllipsoids(float axisLength) const;
+    };
+
 
-} // namespace armarx::armem
+} // namespace armarx::armem::vision
diff --git a/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.cpp b/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.cpp
index 0bf14ec90439e50a4869234b81449adaf068d173..deed74c9ada113f05d10286a370b703d6a712642 100644
--- a/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.cpp
+++ b/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.cpp
@@ -14,4 +14,14 @@ namespace armarx::aron
         dto = bo.matrix();
     }
 
+    void fromAron(const AronPose& dto, Eigen::Isometry3f& bo)
+    {
+        bo.matrix() = dto;
+    }
+
+    void toAron(AronPose& dto, const Eigen::Isometry3f& bo)
+    {
+        dto = bo.matrix();
+    }
+
 }  // namespace armarx::aron
diff --git a/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.h b/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.h
index 3f091dbfc40ee8e91b8d2922687273269ce790a8..3520b2dedd7c10f2d358cb7997269871979b52ed 100644
--- a/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.h
+++ b/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.h
@@ -9,4 +9,7 @@ namespace armarx::aron
     void fromAron(const AronPose& dto, Eigen::Affine3f& bo);
     void toAron(AronPose& dto, const Eigen::Affine3f& bo);
 
+    void fromAron(const AronPose& dto, Eigen::Isometry3f& bo);
+    void toAron(AronPose& dto, const Eigen::Isometry3f& bo);
+
 }  // namespace armarx
diff --git a/source/RobotAPI/libraries/aron/converter/eigen/EigenConverter.h b/source/RobotAPI/libraries/aron/converter/eigen/EigenConverter.h
index e1213b86b1f2f6386fb22d318f4ed798a72eb040..8d6ccf594f8d0adcd168a066111b1ad2fecdcf39 100644
--- a/source/RobotAPI/libraries/aron/converter/eigen/EigenConverter.h
+++ b/source/RobotAPI/libraries/aron/converter/eigen/EigenConverter.h
@@ -111,8 +111,9 @@ namespace armarx::aron::converter
 
             using MatrixT = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
 
-            MatrixT ret;
-            memcpy(reinterpret_cast<unsigned char*>(ret.data()), nav.getData(), std::accumulate(std::begin(dims), std::end(dims), 1, std::multiplies<>()));
+            ARMARX_CHECK_EQUAL(dims.size(), 2); // for now ...
+            MatrixT ret(dims.at(0), dims.at(1));
+            memcpy(reinterpret_cast<unsigned char*>(ret.data()), nav.getData(), std::accumulate(std::begin(dims), std::end(dims), sizeof(T), std::multiplies<>()));
             return ret;
         }
 
@@ -128,7 +129,7 @@ namespace armarx::aron::converter
             auto dims = nav.getShape();
 
             Eigen::Matrix<T, Rows, Cols> ret;
-            memcpy(reinterpret_cast<unsigned char*>(ret.data()), nav.getData(), std::accumulate(std::begin(dims), std::end(dims), 1, std::multiplies<int>()));
+            memcpy(reinterpret_cast<unsigned char*>(ret.data()), nav.getData(), std::accumulate(std::begin(dims), std::end(dims), sizeof(T), std::multiplies<int>()));
             return ret;
         }