From cd56109a0be029085a374c706b1e7d590d510c63 Mon Sep 17 00:00:00 2001
From: Fabian Reister <fabian.reister@kit.edu>
Date: Mon, 26 Apr 2021 08:27:15 +0200
Subject: [PATCH] armem robot mapping: performance improvements: laser scans
 are now ndarrays

---
 .../armem_robot_mapping/MappingDataReader.cpp | 100 +++++++++++++++---
 .../armem_robot_mapping/MappingDataReader.h   |  11 +-
 .../armem_robot_mapping/MappingDataWriter.cpp |  99 +++++++++--------
 .../armem_robot_mapping/aron/LaserScan.xml    |  28 +----
 .../armem_robot_mapping/aron_conversions.cpp  |  71 ++-----------
 .../armem_robot_mapping/aron_conversions.h    |  17 ++-
 .../libraries/armem_robot_mapping/types.h     |   1 -
 7 files changed, 176 insertions(+), 151 deletions(-)

diff --git a/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.cpp b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.cpp
index 6f57909c6..e9fe167f3 100644
--- a/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.cpp
+++ b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.cpp
@@ -1,21 +1,46 @@
 #include "MappingDataReader.h"
 
+#include <cstring>
 #include <vector>
+#include <algorithm>
+#include <map>
+#include <optional>
+#include <ostream>
+#include <type_traits>
+#include <utility>
 
 #include <IceUtil/Time.h>
-
-#include <SimoxUtility/algorithm/get_map_keys_values.h>
+#include <IceUtil/Handle.h>
 
 #include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/logging/LogSender.h>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include <SimoxUtility/algorithm/get_map_keys_values.h>
 
+#include <RobotAPI/libraries/armem_robot_localization/MemoryConnector.h>
+#include <RobotAPI/libraries/armem/client/Query.h>
+#include <RobotAPI/libraries/armem/client/Reader.h>
+#include <RobotAPI/libraries/armem/client/query/Builder.h>
+#include <RobotAPI/libraries/armem/client/query/selectors.h>
+#include <RobotAPI/libraries/armem/core/CoreSegment.h>
+#include <RobotAPI/libraries/armem/core/Memory.h>
+#include <RobotAPI/libraries/armem/core/ProviderSegment.h>
+#include <RobotAPI/libraries/aron/core/Exception.h>
+#include <RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.h>
+#include <RobotAPI/interface/armem/mns/MemoryNameSystemInterface.h>
+#include <RobotAPI/interface/armem/server/ReadingMemoryInterface.h>
+#include <RobotAPI/interface/units/LaserScannerUnit.h>
 #include <RobotAPI/libraries/armem/core/EntityInstance.h>
-#include <RobotAPI/libraries/armem/core/EntitySnapshot.h>
 #include <RobotAPI/libraries/armem/util/util.h>
 #include <RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.aron.generated.h>
 #include <RobotAPI/libraries/armem_robot_mapping/aron_conversions.h>
 #include <RobotAPI/libraries/armem_robot_mapping/types.h>
-#include <RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/AronCppClass.h>
-#include "RobotAPI/libraries/armem_robot_localization/MemoryConnector.h"
+
+namespace armarx::armem
+{
+    class Entity;
+}  // namespace armarx
 
 namespace armarx::armem
 {
@@ -94,6 +119,59 @@ namespace armarx::armem
 
     }
 
+    std::vector<LaserScanStamped> asLaserScans(const std::map<std::string, Entity>& entities)
+    {
+        std::vector<LaserScanStamped> outV;
+
+        if (entities.empty())
+        {
+            ARMARX_WARNING << "No entities!";
+        }
+
+        const auto convert = [](const aron::LaserScanStamped & aronLaserScanStamped, const EntityInstance & ei) -> LaserScanStamped
+        {
+            LaserScanStamped laserScanStamped;
+            fromAron(aronLaserScanStamped, laserScanStamped);
+
+            const auto ndArrayNavigator = aron::datanavigator::NDArrayNavigator::DynamicCast(ei.data()->getElement("scan"));
+
+            ARMARX_CHECK_NOT_NULL(ndArrayNavigator);
+
+            laserScanStamped.data = fromAron<LaserScanStep>(ndArrayNavigator);
+            ARMARX_IMPORTANT << "4";
+
+
+            return laserScanStamped;
+
+        };
+
+        // loop over all entities and their snapshots
+        for (const auto &[s, entity] : entities)
+        {
+            if (entity.history.empty())
+            {
+                ARMARX_WARNING << "Empty history for " << s;
+            }
+
+            ARMARX_INFO << "History size: " << entity.history.size();
+
+            for (const auto &[ss, entitySnapshot] : entity.history)
+            {
+                for (const auto& entityInstance : entitySnapshot.instances)
+                {
+                    const auto o = tryCast<aron::LaserScanStamped>(entityInstance);
+
+                    if (o)
+                    {
+                        outV.push_back(convert(*o, entityInstance));
+                    }
+                }
+            }
+        }
+
+        return outV;
+    }
+
     MappingDataReader::Result
     MappingDataReader::queryData(const Query& query) const
     {
@@ -122,18 +200,10 @@ namespace armarx::armem
             .getProviderSegment(query.agent)
             .entities;
 
-        auto laserScans = transformAllOfType<aron::LaserScanStamped>(
-                              entities,
-                              [](const aron::LaserScanStamped & aronLaserScan) -> LaserScanStamped
-        {
-            LaserScanStamped laserScan;
-            fromAron(aronLaserScan, laserScan);
-            return laserScan;
-        });
-
+        const auto laserScans = asLaserScans(entities);
         const auto sensors = simox::alg::get_keys(entities);
 
-        return {.laserScans = std::move(laserScans),
+        return {.laserScans = laserScans,
                 .sensors = sensors,
                 .status = Result::Status::Success,
                 .errorMessage = ""};
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.h b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.h
index 3c700703e..da3bcc6ee 100644
--- a/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.h
+++ b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataReader.h
@@ -13,7 +13,6 @@
  * 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
@@ -22,12 +21,18 @@
 
 #pragma once
 
-#include "RobotAPI/libraries/armem_robot_mapping/types.h"
-#include <RobotAPI/libraries/armem/client/Reader.h>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
 
+#include <RobotAPI/libraries/armem/client/Reader.h>
 // TODO(fabian.reister): move MemoryConnector to armem library
 #include <RobotAPI/libraries/armem_robot_localization/MemoryConnector.h>
 #include <RobotAPI/libraries/armem/client/query/Builder.h>
+#include <RobotAPI/libraries/armem_robot_mapping/types.h>
+
 
 
 namespace armarx
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/MappingDataWriter.cpp b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataWriter.cpp
index 37f85182f..86e203cce 100644
--- a/source/RobotAPI/libraries/armem_robot_mapping/MappingDataWriter.cpp
+++ b/source/RobotAPI/libraries/armem_robot_mapping/MappingDataWriter.cpp
@@ -4,28 +4,30 @@
 #include <RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.aron.generated.h>
 
 
-namespace armarx::armem {
+namespace armarx::armem
+{
 
-MappingDataWriter::MappingDataWriter(ManagedIceObject &component)
-    : MemoryConnector(component) {}
+    MappingDataWriter::MappingDataWriter(ManagedIceObject& component)
+        : MemoryConnector(component) {}
 
-MappingDataWriter::~MappingDataWriter() = default;
+    MappingDataWriter::~MappingDataWriter() = default;
 
-void MappingDataWriter::registerPropertyDefinitions(
-    armarx::PropertyDefinitionsPtr &def) {
-  ARMARX_DEBUG << "TransformWriter: registerPropertyDefinitions";
+    void MappingDataWriter::registerPropertyDefinitions(
+        armarx::PropertyDefinitionsPtr& def)
+    {
+        ARMARX_DEBUG << "TransformWriter: registerPropertyDefinitions";
 
-  MemoryConnector::registerPropertyDefinitions(def);
+        MemoryConnector::registerPropertyDefinitions(def);
 
-  const std::string prefix = getPropertyPrefix();
+        const std::string prefix = getPropertyPrefix();
 
-  def->optional(properties.mappingMemoryName, prefix + "MappingMemoryName",
-                "Name of the mapping memory core segment to use.");
+        def->optional(properties.mappingMemoryName, prefix + "MappingMemoryName",
+                      "Name of the mapping memory core segment to use.");
 
-  def->optional(properties.memoryName, prefix + "MemoryName");
-}
+        def->optional(properties.memoryName, prefix + "MemoryName");
+    }
 
- void MappingDataWriter::connect()
+    void MappingDataWriter::connect()
     {
         // Wait for the memory to become available and add it as dependency.
         ARMARX_IMPORTANT << "MappingDataWriter: Waiting for memory '" << properties.memoryName
@@ -43,48 +45,55 @@ void MappingDataWriter::registerPropertyDefinitions(
     }
 
 
-bool MappingDataWriter::storeSensorData(const LaserScan &laserScan,
-                                        const std::string &frame,
-                                        const std::string &agentName,
-                                        const std::int64_t &timestamp) {
-  std::lock_guard g{memoryWriterMutex};
+    bool MappingDataWriter::storeSensorData(const LaserScan& laserScan,
+                                            const std::string& frame,
+                                            const std::string& agentName,
+                                            const std::int64_t& timestamp)
+    {
+        std::lock_guard g{memoryWriterMutex};
 
-  const auto result =
-      memoryWriter.addSegment(properties.mappingMemoryName, agentName);
+        const auto result =
+            memoryWriter.addSegment(properties.mappingMemoryName, agentName);
 
-  if (not result.success) {
-    ARMARX_ERROR << result.errorMessage;
+        if (not result.success)
+        {
+            ARMARX_ERROR << result.errorMessage;
 
-    // TODO(fabian.reister): message
-    return false;
-  }
+            // TODO(fabian.reister): message
+            return false;
+        }
 
-  const auto iceTimestamp = IceUtil::Time::microSeconds(timestamp);
+        const auto iceTimestamp = IceUtil::Time::microSeconds(timestamp);
 
-  const auto providerId = armem::MemoryID(result.segmentID);
-  const auto entityID =
-      providerId.withEntityName(frame).withTimestamp(iceTimestamp);
+        const auto providerId = armem::MemoryID(result.segmentID);
+        const auto entityID =
+            providerId.withEntityName(frame).withTimestamp(iceTimestamp);
 
-  armem::EntityUpdate update;
-  update.entityID = entityID;
-  update.timeCreated = armem::Time::now();
+        armem::EntityUpdate update;
+        update.entityID = entityID;
+        update.timeCreated = armem::Time::now();
 
-  aron::LaserScanStamped aronSensorData;
-  toAron(laserScan, timestamp, frame, agentName, aronSensorData);
+        aron::LaserScanStamped aronSensorData;
+        // currently only sets the header
+        toAron(laserScan, timestamp, frame, agentName, aronSensorData);
 
-  update.instancesData = {aronSensorData.toAron()};
-  update.timeCreated = iceTimestamp;
+        auto dict = aronSensorData.toAron();
+        dict->addElement("scan", toAron(laserScan));
 
-  ARMARX_DEBUG << "Committing " << update << " at time " << iceTimestamp;
-  armem::EntityUpdateResult updateResult = memoryWriter.commit(update);
+        update.instancesData = {dict};
+        update.timeCreated = iceTimestamp;
 
-  ARMARX_DEBUG << updateResult;
+        ARMARX_DEBUG << "Committing " << update << " at time " << iceTimestamp;
+        armem::EntityUpdateResult updateResult = memoryWriter.commit(update);
 
-  if (not updateResult.success) {
-    ARMARX_ERROR << updateResult.errorMessage;
-  }
+        ARMARX_DEBUG << updateResult;
 
-  return updateResult.success;
-}
+        if (not updateResult.success)
+        {
+            ARMARX_ERROR << updateResult.errorMessage;
+        }
+
+        return updateResult.success;
+    }
 
 } // namespace armarx::armem
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.xml b/source/RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.xml
index 140e2aab8..860726583 100644
--- a/source/RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.xml
+++ b/source/RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.xml
@@ -8,21 +8,6 @@
 
     <GenerateTypes>
 
-        <Object name='armarx::aron::LaserScanStep'>
-            <ObjectChild key='distance'>
-                <float />
-            </ObjectChild>
-            <ObjectChild key='angle'>
-                <float />
-            </ObjectChild>
-            <!--ObjectChild key='relativeTime'>
-                <float />
-            </ObjectChild-->
-            <!--ObjectChild key='intensity'>
-                <float />
-            </ObjectChild-->
-        </Object>
-
         <Object name='armarx::aron::LaserScannerInfo'>
             <ObjectChild key='device'>
                 <string />
@@ -53,21 +38,16 @@
             </ObjectChild>
         </Object>
 
-        <Object name="armarx::aron::LaserScan">
-            <ObjectChild key='scan'>
-                <List>
-                    <armarx::aron::LaserScanStep />
-                </List>
-            </ObjectChild>
-        </Object>
 
         <Object name='armarx::aron::LaserScanStamped'>
             <ObjectChild key="header">
                 <armarx::aron::SensorHeader />
             </ObjectChild>
+
+            <!-- 
             <ObjectChild key='data'>
-                <armarx::aron::LaserScan />
-            </ObjectChild>
+                <NdArray />
+            </ObjectChild> -->
         </Object>
 
     </GenerateTypes>
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.cpp b/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.cpp
index a7b8277c3..57cb0873c 100644
--- a/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.cpp
+++ b/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.cpp
@@ -5,44 +5,17 @@
 
 #include <RobotAPI/interface/units/LaserScannerUnit.h>
 #include <RobotAPI/libraries/armem_robot_mapping/aron/LaserScan.aron.generated.h>
+#include <RobotAPI/libraries/aron/converter/common/Converter.h>
+#include <RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.h>
 
 #include "types.h"
 
+
 namespace armarx
 {
 
     /************ fromAron ************/
 
-
-    LaserScanStep fromAron(const aron::LaserScanStep& aronLaserScanStep)
-    {
-        LaserScanStep laserScanStep;
-
-        laserScanStep.angle = aronLaserScanStep.angle;
-        laserScanStep.distance = aronLaserScanStep.distance;
-
-        return laserScanStep;
-    }
-
-    template <typename T> auto fromAron(const std::vector<T>& v)
-    {
-        std::vector<decltype(fromAron(T()))> r;
-        r.reserve(v.size());
-
-        std::transform(v.begin(), v.end(), std::back_inserter(r),
-                       [](const T & t)
-        {
-            return fromAron(t);
-        });
-
-        return r;
-    }
-
-    auto fromAron(const aron::LaserScan& aronLaserScan)
-    {
-        return fromAron(aronLaserScan.scan);
-    }
-
     SensorHeader fromAron(const aron::SensorHeader& aronSensorHeader)
     {
         return {.agent = aronSensorHeader.agent,
@@ -54,7 +27,7 @@ namespace armarx
                   LaserScanStamped& laserScan)
     {
         laserScan.header = fromAron(aronLaserScan.header);
-        laserScan.data = fromAron(aronLaserScan.data);
+        // laserScan.data = fromAron(aronLaserScan.data);
     }
 
     void fromAron(const aron::LaserScanStamped& aronLaserScan, LaserScan& laserScan,
@@ -63,7 +36,7 @@ namespace armarx
     {
         const auto header = fromAron(aronLaserScan.header);
 
-        laserScan = fromAron(aronLaserScan.data);
+        // laserScan = fromAron(aronLaserScan.data);
 
         timestamp = header.timestamp;
         frame = header.frame;
@@ -74,34 +47,10 @@ namespace armarx
     /************ toAron ************/
 
 
-    template <typename T> auto toAron(const std::vector<T>& v)
-    {
-        std::vector<decltype(toAron(T()))> r;
-        r.reserve(v.size());
-
-        std::transform(v.begin(), v.end(), std::back_inserter(r),
-                       [](const T & t)
-        {
-            return toAron(t);
-        });
-
-        return r;
-    }
-
-    aron::LaserScanStep toAron(const LaserScanStep& laserScanStep)
-    {
-        aron::LaserScanStep aronLaserScan;
-
-        aronLaserScan.angle = laserScanStep.angle;
-        aronLaserScan.distance = laserScanStep.distance;
-
-        return aronLaserScan;
-    }
-
-    auto toAron(const LaserScan& laserScan, aron::LaserScan& aronLaserScan)
-    {
-        aronLaserScan.scan = toAron(laserScan);
-    }
+    // auto toAron(const LaserScan& laserScan, aron::LaserScan& aronLaserScan)
+    // {
+    //     aronLaserScan.scan = toAron(laserScan);
+    // }
 
     aron::SensorHeader toAron(const SensorHeader& sensorHeader)
     {
@@ -118,7 +67,7 @@ namespace armarx
                 aron::LaserScanStamped& aronLaserScanStamped)
     {
         aronLaserScanStamped.header = toAron(laserScanStamped.header);
-        toAron(laserScanStamped.data, aronLaserScanStamped.data);
+        // toAron(laserScanStamped.data, aronLaserScanStamped.data);
     }
 
     void toAron(const LaserScan& laserScan,
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.h b/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.h
index 865e054b1..a7b686fdb 100644
--- a/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.h
+++ b/source/RobotAPI/libraries/armem_robot_mapping/aron_conversions.h
@@ -13,7 +13,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
- * @package    RobotComponents::ArmarXObjects::
  * @author     Fabian Reister ( fabian dot reister at kit dot edu )
  * @date       2021
  * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
@@ -24,7 +23,8 @@
 #pragma once
 
 #include <RobotAPI/interface/units/LaserScannerUnit.h>
-
+#include <RobotAPI/libraries/aron/converter/common/VectorConverter.h>
+#include <RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.h>
 
 namespace armarx
 {
@@ -44,6 +44,13 @@ namespace armarx
         std::string& frame,
         std::string& agentName);
 
+
+    template<typename T>
+    auto fromAron(const aron::datanavigator::NDArrayNavigatorPtr& navigator)
+    {
+        return aron::converter::AronVectorConverter::ConvertToVector<T>(navigator);
+    }
+
     void fromAron(const aron::LaserScanStamped& aronLaserScan, LaserScanStamped& laserScan);
 
     void toAron(
@@ -53,4 +60,10 @@ namespace armarx
         const std::string& agentName,
         aron::LaserScanStamped& aronLaserScan);
 
+    inline aron::datanavigator::NDArrayNavigatorPtr toAron(const LaserScan& laserScan)
+    {
+        return aron::datanavigator::NDArrayNavigator::FromVector(laserScan);
+    }
+
+
 } // namespace armarx
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/types.h b/source/RobotAPI/libraries/armem_robot_mapping/types.h
index f3bfa33b7..6e8a08414 100644
--- a/source/RobotAPI/libraries/armem_robot_mapping/types.h
+++ b/source/RobotAPI/libraries/armem_robot_mapping/types.h
@@ -13,7 +13,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
- * @package    RobotComponents::ArmarXObjects::
  * @author     Fabian Reister ( fabian dot reister at kit dot edu )
  * @date       2021
  * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
-- 
GitLab