From e732c5fc19a8b3abd9ca359f01a93ef3ecace552 Mon Sep 17 00:00:00 2001 From: armar-user <armar-user@kit.edu> Date: Wed, 28 Jul 2021 14:58:38 +0200 Subject: [PATCH] fixed ltm query and consollidation --- .../RobotStateMemory/RobotUnitReader.cpp | 9 ++-- .../RobotAPI/libraries/armem/client/Query.h | 32 +++++++++++++ .../libraries/armem/core/base/MemoryBase.h | 19 ++++++++ .../armem/core/longtermmemory/CoreSegment.cpp | 8 ++-- .../armem/core/longtermmemory/Entity.cpp | 8 ++-- .../core/longtermmemory/EntitySnapshot.cpp | 8 +--- .../armem/core/longtermmemory/Memory.cpp | 48 +++++++++++++++---- .../armem/core/longtermmemory/Memory.h | 5 +- .../core/longtermmemory/ProviderSegment.cpp | 9 ++-- .../armem/server/MemoryToIceAdapter.cpp | 23 ++++++++- 10 files changed, 130 insertions(+), 39 deletions(-) diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitReader.cpp b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitReader.cpp index 58b688557..94dc94f8b 100644 --- a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitReader.cpp +++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitReader.cpp @@ -116,12 +116,13 @@ namespace armarx::armem::server::robot_state for (const auto& [nameEntry, dataEntry] : description.entries) { std::string name = nameEntry; - std::string jointOrWhateverName; + std::string jointOrWhateverName = nameEntry; std::string groupName = ""; if (auto it = configSensorMapping.find(name); it != configSensorMapping.end()) { groupName = it->second; + jointOrWhateverName = it->second; // ??? } else { @@ -134,10 +135,9 @@ namespace armarx::armem::server::robot_state << "and Y is the actual sensor. Ignoring this sensor."; continue; } - groupName = name.substr(0, second_dot_pos); + groupName = name.substr(0, second_dot_pos); jointOrWhateverName = name.substr(first_dot_pos + 1, second_dot_pos - first_dot_pos - 1); - name = name.substr(second_dot_pos + 1); // remove the groupName, TODO check if +1 is valid } @@ -161,7 +161,8 @@ namespace armarx::armem::server::robot_state } RobotUnitData::RobotUnitDataGroup& group = it->second; - group.data->addElement(name, RobotUnitDataStreaming::toAron(data.value(), dataEntry)); + const std::string escapedName = simox::alg::replace_all(name, ".", "/"); + group.data->addElement(escapedName, RobotUnitDataStreaming::toAron(data.value(), dataEntry)); } auto stop = std::chrono::high_resolution_clock::now(); diff --git a/source/RobotAPI/libraries/armem/client/Query.h b/source/RobotAPI/libraries/armem/client/Query.h index 916278a8f..c6bb445bf 100644 --- a/source/RobotAPI/libraries/armem/client/Query.h +++ b/source/RobotAPI/libraries/armem/client/Query.h @@ -60,6 +60,38 @@ namespace armarx::armem::client } } + void replaceQueryTarget(const armem::query::data::QueryTarget search, const armem::query::data::QueryTarget replace) + { + for (const auto& memoryQuery : memoryQueries) + { + if (auto it = std::find(memoryQuery->targets.begin(), memoryQuery->targets.end(), search); it != memoryQuery->targets.end()) + { + memoryQuery->targets.push_back(replace); + } + for (const auto& coreSegmentQuery : memoryQuery->coreSegmentQueries) + { + if (auto it = std::find(coreSegmentQuery->targets.begin(), coreSegmentQuery->targets.end(), search); it != coreSegmentQuery->targets.end()) + { + coreSegmentQuery->targets.push_back(replace); + } + for (const auto& providerSegmentQuery : coreSegmentQuery->providerSegmentQueries) + { + if (auto it = std::find(providerSegmentQuery->targets.begin(), providerSegmentQuery->targets.end(), search); it != providerSegmentQuery->targets.end()) + { + providerSegmentQuery->targets.push_back(replace); + } + for (const auto& entityQuery : providerSegmentQuery->entityQueries) + { + if (auto it = std::find(entityQuery->targets.begin(), entityQuery->targets.end(), search); it != entityQuery->targets.end()) + { + entityQuery->targets.push_back(replace); + } + } + } + } + } + } + static QueryInput fromIce(const armem::query::data::Input& ice); armem::query::data::Input toIce() const; }; diff --git a/source/RobotAPI/libraries/armem/core/base/MemoryBase.h b/source/RobotAPI/libraries/armem/core/base/MemoryBase.h index 781322b54..1bc42b0cc 100644 --- a/source/RobotAPI/libraries/armem/core/base/MemoryBase.h +++ b/source/RobotAPI/libraries/armem/core/base/MemoryBase.h @@ -336,6 +336,25 @@ namespace armarx::armem::base return this->name(); } + std::string dump() const + { + std::stringstream ss; + ss << "Memory: " << this->name() << "\n"; + for (const auto& [ckey, cseg] : this->container()) + { + ss << " |- Found core seg: " << ckey << "\n"; + for (const auto& [pkey, pseg] : cseg.container()) + { + ss << " | |- Found prov seg: " << pkey << "\n"; + for (const auto& [ekey, eseg] : pseg.container()) + { + ss << " | | |- Found entity: " << ekey << "\n"; + } + } + } + return ss.str(); + } + protected: virtual void _copySelf(DerivedT& other) const override diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/CoreSegment.cpp b/source/RobotAPI/libraries/armem/core/longtermmemory/CoreSegment.cpp index a64a5982e..d47dc46cb 100644 --- a/source/RobotAPI/libraries/armem/core/longtermmemory/CoreSegment.cpp +++ b/source/RobotAPI/libraries/armem/core/longtermmemory/CoreSegment.cpp @@ -10,8 +10,6 @@ namespace armarx::armem::ltm wm::CoreSegment CoreSegment::convert() const { - ARMARX_INFO << "CoreSegment: Converting with connection to: " << dbsettings.toString(); - wm::CoreSegment m(id()); for (const auto& [_, s] : _container) { @@ -24,8 +22,6 @@ namespace armarx::armem::ltm { _container.clear(); - ARMARX_INFO << "CoreSegment: (Re)Establishing connection to: " << dbsettings.toString(); - mongocxx::client& client = MongoDBConnectionManager::EstablishConnection(dbsettings); mongocxx::database db = client[dbsettings.database]; mongocxx::collection coll = db[id().str()]; @@ -47,7 +43,7 @@ namespace armarx::armem::ltm if (const auto& it = _container.find(k); it != _container.end()) { - throw error::ArMemError("Somehow after clearing the container a key k = " + k + " was found. Do you have double entries in mongodb?"); + throw error::ArMemError("Somehow after clearing the (core) container a key k = " + k + " was found. Do you have double entries in mongodb?"); } else { @@ -56,6 +52,8 @@ namespace armarx::armem::ltm wms.first->second.reload(); } } + + ARMARX_INFO << "After reload has core segment " << id().str() << " size: " << _container.size(); } void CoreSegment::append(const wm::CoreSegment& m) diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.cpp b/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.cpp index aeb2be76e..bccb79c9d 100644 --- a/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.cpp +++ b/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.cpp @@ -6,8 +6,6 @@ namespace armarx::armem::ltm wm::Entity Entity::convert() const { - ARMARX_INFO << "Entity: Converting with connection to: " << dbsettings.toString(); - wm::Entity m(id()); for (const auto& [_, s] : _container) { @@ -20,8 +18,6 @@ namespace armarx::armem::ltm { _container.clear(); - ARMARX_INFO << "Entity: (Re)Establishing connection to: " << dbsettings.toString(); - mongocxx::client& client = MongoDBConnectionManager::EstablishConnection(dbsettings); mongocxx::database db = client[dbsettings.database]; mongocxx::collection coll = db[id().str()]; @@ -42,7 +38,7 @@ namespace armarx::armem::ltm if (const auto& it = _container.find(k); it != _container.end()) { - throw error::ArMemError("Somehow after clearing the container a key k = " + std::to_string(k.toMicroSeconds()) + " was found. Do you have double entries in mongodb?"); + throw error::ArMemError("Somehow after clearing the (entity) container a key k = " + std::to_string(k.toMicroSeconds()) + " was found. Do you have double entries in mongodb?"); } else { @@ -52,6 +48,8 @@ namespace armarx::armem::ltm } ++i; } + + ARMARX_INFO << "After reload has entity " << id().str() << " size: " << _container.size(); } void Entity::append(const wm::Entity& m) diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/EntitySnapshot.cpp b/source/RobotAPI/libraries/armem/core/longtermmemory/EntitySnapshot.cpp index 47a680731..aae8a6d32 100644 --- a/source/RobotAPI/libraries/armem/core/longtermmemory/EntitySnapshot.cpp +++ b/source/RobotAPI/libraries/armem/core/longtermmemory/EntitySnapshot.cpp @@ -13,8 +13,6 @@ namespace armarx::armem::ltm wm::EntitySnapshot EntitySnapshot::convert(const aron::typenavigator::NavigatorPtr& expectedStructure) const { - ARMARX_INFO << "EntitySnapshot: Converting with connection to: " << dbsettings.toString(); - mongocxx::client& client = MongoDBConnectionManager::EstablishConnection(dbsettings); mongocxx::database db = client[dbsettings.database]; mongocxx::collection coll = db[id().getEntityID().str()]; @@ -52,8 +50,6 @@ namespace armarx::armem::ltm { _container.clear(); - ARMARX_INFO << "EntitySnapshot: (Re)Establishing connection to: " << dbsettings.toString(); - mongocxx::client& client = MongoDBConnectionManager::EstablishConnection(dbsettings); mongocxx::database db = client[dbsettings.database]; mongocxx::collection coll = db[id().getEntityID().str()]; @@ -68,10 +64,8 @@ namespace armarx::armem::ltm nlohmann::json json = nlohmann::json::parse(bsoncxx::to_json(*res)); for (unsigned int i = 0; i < json.at("instances").size(); ++i) { - auto wms = _container.emplace_back(id().withInstanceIndex(i)); + _container.emplace_back(id().withInstanceIndex(i)); } - - ARMARX_INFO << "Entity '" + id().str() + "': Found instances in LTM: " << json.at("instances").size(); } void EntitySnapshot::setTo(const wm::EntitySnapshot& m, const armem::Time& t) diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.cpp b/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.cpp index 95ad5af75..2080879c5 100644 --- a/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.cpp +++ b/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.cpp @@ -27,7 +27,8 @@ namespace armarx::armem::ltm dbsettings(other.dbsettings), alwaysTransferSettings(other.alwaysTransferSettings), periodicTransferSettings(other.periodicTransferSettings), - onFullTransferSettings(other.onFullTransferSettings) + onFullTransferSettings(other.onFullTransferSettings), + reloaded(other.reloaded) { // Do not move _mutex. } @@ -53,6 +54,7 @@ namespace armarx::armem::ltm alwaysTransferSettings = std::move(other.alwaysTransferSettings); periodicTransferSettings = std::move(other.periodicTransferSettings); onFullTransferSettings = std::move(other.onFullTransferSettings); + reloaded = other.reloaded; // Don't move _mutex. return *this; @@ -88,13 +90,14 @@ namespace armarx::armem::ltm wm::Memory Memory::convert() const { + std::lock_guard l(mongoDBMutex); if (!checkConnection()) { wm::Memory m(id()); return m; } - ARMARX_INFO << "Converting with connection to: " << dbsettings.toString(); + ARMARX_INFO << "Converting Memory with connection to: " << dbsettings.toString(); TIMING_START(LTM_Convert); @@ -110,18 +113,20 @@ namespace armarx::armem::ltm void Memory::reload() { + std::lock_guard l(mongoDBMutex); + reloaded = false; + if (!checkConnection()) { return; } - std::scoped_lock l(mongoDBMutex); ARMARX_INFO << "(Re)Establishing connection to: " << dbsettings.toString(); + + TIMING_START(LTM_Reload); _container.clear(); - ARMARX_TRACE; mongocxx::client& client = MongoDBConnectionManager::EstablishConnection(dbsettings); - ARMARX_TRACE; if (!client) { ARMARX_ERROR << "A client has died. Could not reload."; @@ -139,6 +144,8 @@ namespace armarx::armem::ltm ARMARX_INFO << "Getting collection for id: " << id().str(); mongocxx::collection coll = db[id().str()]; + ARMARX_IMPORTANT << "Memory Container size is: " << _container.size(); + mongocxx::cursor cursor = coll.find({}); for (const auto& doc : cursor) { @@ -155,7 +162,7 @@ namespace armarx::armem::ltm if (const auto& it = _container.find(k); it != _container.end()) { - throw error::ArMemError("Somehow after clearing the container a key k = " + k + " was found. Do you have double entries in mongodb?"); + throw error::ArMemError("Somehow after clearing the (memory) container a key k = " + k + " was found. Do you have double entries in mongodb?"); } else { @@ -164,17 +171,26 @@ namespace armarx::armem::ltm wms.first->second.reload(); } } + + reloaded = true; + for (const auto& m : toAppendQueue) + { + _append(m); + } + + TIMING_END(LTM_Reload); + ARMARX_INFO << "After reload memory " << id().str() << " size: " << _container.size() << ". Setting reloaded: " << reloaded; } - void Memory::append(const wm::Memory& m) + void Memory::_append(const wm::Memory& m) { - if (!checkConnection()) + if (!checkConnection() || !reloaded) { + // We ignore if not fully loaded yet return; } - std::scoped_lock l(mongoDBMutex); - ARMARX_INFO << "Merge memory with name '" << m.name() << "' into the LTM with name '" << name() << "'"; + //ARMARX_INFO << "Merge memory with name '" << m.name() << "' into the LTM with name '" << name() << "'"; TIMING_START(LTM_Append); @@ -205,4 +221,16 @@ namespace armarx::armem::ltm TIMING_END(LTM_Append); } + + void Memory::append(const wm::Memory& m) + { + std::lock_guard l(mongoDBMutex); + if (!checkConnection() || !reloaded) + { + toAppendQueue.push_back(m); + return; + } + + _append(m); + } } diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.h b/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.h index 43b67c82c..b24f4a7a6 100644 --- a/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.h +++ b/source/RobotAPI/libraries/armem/core/longtermmemory/Memory.h @@ -87,6 +87,8 @@ namespace armarx::armem::ltm private: bool checkConnection() const; + void _append(const wm::Memory&); + public: MongoDBConnectionManager::MongoDBSettings dbsettings; @@ -95,8 +97,9 @@ namespace armarx::armem::ltm OnFullTransferSettings onFullTransferSettings; private: + bool reloaded = false; mutable std::mutex mongoDBMutex; - + std::vector<wm::Memory> toAppendQueue; }; } diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/ProviderSegment.cpp b/source/RobotAPI/libraries/armem/core/longtermmemory/ProviderSegment.cpp index aac804599..5fcf4a135 100644 --- a/source/RobotAPI/libraries/armem/core/longtermmemory/ProviderSegment.cpp +++ b/source/RobotAPI/libraries/armem/core/longtermmemory/ProviderSegment.cpp @@ -10,8 +10,6 @@ namespace armarx::armem::ltm wm::ProviderSegment ProviderSegment::convert() const { - ARMARX_INFO << "ProviderSegment: Converting with connection to: " << dbsettings.toString(); - wm::ProviderSegment m(id()); for (const auto& [_, s] : _container) { @@ -24,8 +22,6 @@ namespace armarx::armem::ltm { _container.clear(); - ARMARX_INFO << "ProviderSegment: (Re)Establishing connection to: " << dbsettings.toString(); - mongocxx::client& client = MongoDBConnectionManager::EstablishConnection(dbsettings); mongocxx::database db = client[dbsettings.database]; mongocxx::collection coll = db[id().str()]; @@ -34,7 +30,6 @@ namespace armarx::armem::ltm for (auto doc : cursor) { nlohmann::json json = nlohmann::json::parse(bsoncxx::to_json(doc)); - ARMARX_INFO << "ProviderSegment: Found foreign key: " << json.at("foreign_key"); MemoryID i((std::string) json.at("foreign_key")); if (i.providerSegmentName != id().providerSegmentName) @@ -46,7 +41,7 @@ namespace armarx::armem::ltm if (const auto& it = _container.find(k); it != _container.end()) { - throw error::ArMemError("Somehow after clearing the container a key k = " + k + " was found. Do you have double entries in mongodb?"); + throw error::ArMemError("Somehow after clearing the (provvider) container a key k = " + k + " was found. Do you have double entries in mongodb?"); } else { @@ -55,6 +50,8 @@ namespace armarx::armem::ltm wms.first->second.reload(); } } + + ARMARX_INFO << "After reload has provider segment " << id().str() << " size: " << _container.size(); } void ProviderSegment::append(const wm::ProviderSegment& m) diff --git a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp index 801536883..6b0761f53 100644 --- a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp +++ b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp @@ -173,6 +173,7 @@ namespace armarx::armem::server result.timeArrived = update.timeArrived; // also store in ltm if transfermode is set to always + // TODO: Move outside of loop? if (longtermMemory) { if (longtermMemory->alwaysTransferSettings.enabled) @@ -243,16 +244,35 @@ namespace armarx::armem::server armem::query::data::Result result; if (ltmResult.hasData()) { + ARMARX_INFO << "The LTM returned data after query"; + // ATTENTION: This code block moves data from LTM back into WM. // However, since some segments are constrained, the WM might send data back to LTM. // This may also affect the data returned by the current query. // However, this is expected behavior, since we copy the data in the processor (copyEmpty) we can safely return the copy and // remove the original memory reference from WM here. wm::Memory ltmConverted = ltmResult.convert(); + if (!ltmConverted.hasData()) + { + ARMARX_ERROR << "A converted memory contains no data although the original memory contained data. This indicates that something is wrong."; + } + wmResult.append(ltmConverted); + if (!wmResult.hasData()) + { + ARMARX_ERROR << "A merged Memory has no data although at least the LTM result contains data. This indicates that something is wrong."; + } // query again to limit output size (TODO: Skip if querytype is all) - wm::Memory merged_result = wmProcessor.process(input, wmResult); + auto queryInput = armem::client::QueryInput::fromIce(input); + queryInput.replaceQueryTarget(query::data::QueryTarget::LTM, query::data::QueryTarget::WM); + + wm::Memory merged_result = wmProcessor.process(queryInput.toIce(), wmResult, /* execute if: */ { query::data::QueryTarget::WM }); + if (!merged_result.hasData()) + { + ARMARX_ERROR << "A merged and postprocessed Memory has no data although at least the LTM result contains data. This indicates that something is wrong."; + } + result.memory = toIce<data::MemoryPtr>(merged_result); // also move results of ltm to wm @@ -263,6 +283,7 @@ namespace armarx::armem::server } else { + ARMARX_INFO << "The LTM did not return data after query"; result.memory = toIce<data::MemoryPtr>(wmResult); } -- GitLab