From c7e532b47fc435c63b00c01d5befcd66c625c8e6 Mon Sep 17 00:00:00 2001 From: Rainer Kartmann <rainer.kartmann@kit.edu> Date: Wed, 29 Nov 2023 16:54:05 +0100 Subject: [PATCH] Make configurable --- .../MemoryToDebugObserver/Component.cpp | 66 ++++++++----- .../client/MemoryToDebugObserver/Component.h | 6 +- .../client/util/MemoryToDebugObserver.cpp | 97 ++++++++++++++----- .../armem/client/util/MemoryToDebugObserver.h | 19 ++++ 4 files changed, 138 insertions(+), 50 deletions(-) diff --git a/source/RobotAPI/components/armem/client/MemoryToDebugObserver/Component.cpp b/source/RobotAPI/components/armem/client/MemoryToDebugObserver/Component.cpp index 6d42b4106..89782e6df 100644 --- a/source/RobotAPI/components/armem/client/MemoryToDebugObserver/Component.cpp +++ b/source/RobotAPI/components/armem/client/MemoryToDebugObserver/Component.cpp @@ -22,6 +22,8 @@ #include "Component.h" +#include <SimoxUtility/json.h> + #include <ArmarXCore/core/time/Frequency.h> #include <ArmarXCore/core/time/Metronome.h> @@ -34,6 +36,39 @@ namespace armarx::memory_to_debug_observer armarx::PropertyDefinitionsPtr defs = new ComponentPropertyDefinitions(getConfigIdentifier()); + { + armem::MemoryID robotEntityId{"RobotState", "Proprioception", "Armar7", "Armar7"}; + + std::vector<std::string> jointNames{ + "Neck_1_Yaw", + "Neck_2_Hemisphere_A", + "Neck_3_Hemisphere_B", + }; + + for (const std::string& jointName : jointNames) + { + std::vector<std::string> attributes{ + "position", + "velocity", + }; + for (const std::string& attribute : attributes) + { + properties.memoryToDebugObserver.plottedValues.push_back({ + .entityID = robotEntityId, + .aronPath = {{"joints", attribute, jointName}}, + }); + } + } + + simox::json::json j = properties.memoryToDebugObserver; + properties.memoryToDebugObserverJson = j.dump(); + } + defs->optional(properties.memoryToDebugObserverJson, + "p.memoryToDebugObserverJson", + "Configuration of MemoryToDebugObserver in JSON format."); + + defs->optional(properties.pollFrequencyHz, "p.pollFrequencyHz"); + return defs; } @@ -52,27 +87,9 @@ namespace armarx::memory_to_debug_observer { DebugObserverComponentPluginUser::setDebugObserverBatchModeEnabled(true); - armem::MemoryID robotEntityId{"RobotState", "Proprioception", "Armar7", "Armar7"}; - - std::vector<std::string> jointNames{ - "Neck_1_Yaw", - "Neck_2_Hemisphere_A", - "Neck_3_Hemisphere_B", - }; - - for (const std::string& jointName : jointNames) { - std::vector<std::string> attributes{ - "position", - "velocity", - }; - for (const std::string& attribute : attributes) - { - properties.memoryToDebugObserver.plottedValues.push_back({ - .entityID = robotEntityId, - .aronPath = {{"joints", attribute, jointName}}, - }); - } + simox::json::json j = simox::json::json::parse(properties.memoryToDebugObserverJson); + j.get_to(properties.memoryToDebugObserver); } } @@ -108,7 +125,7 @@ namespace armarx::memory_to_debug_observer armem::client::util::MemoryToDebugObserver memoryToDebugObserver{ properties.memoryToDebugObserver, services}; - Frequency frequency = Frequency::Hertz(30); + Frequency frequency = Frequency::Hertz(properties.pollFrequencyHz); Metronome metronome(frequency); while (task and not task->isStopped()) { @@ -122,11 +139,10 @@ namespace armarx::memory_to_debug_observer { using namespace armarx::RemoteGui::Client; - if (tab.queryResult) - { - } + tab.group = GroupBox(); + tab.group.setLabel("Todo ..."); - VBoxLayout root = {tab.queryResultGroup, VSpacer()}; + VBoxLayout root = {tab.group, VSpacer()}; RemoteGui_createTab(getName(), root, &tab); } diff --git a/source/RobotAPI/components/armem/client/MemoryToDebugObserver/Component.h b/source/RobotAPI/components/armem/client/MemoryToDebugObserver/Component.h index 02b4bb249..07965a053 100644 --- a/source/RobotAPI/components/armem/client/MemoryToDebugObserver/Component.h +++ b/source/RobotAPI/components/armem/client/MemoryToDebugObserver/Component.h @@ -81,6 +81,9 @@ namespace armarx::memory_to_debug_observer struct Properties { armem::client::util::MemoryToDebugObserver::Properties memoryToDebugObserver; + std::string memoryToDebugObserverJson; + + float pollFrequencyHz = 30; }; Properties properties; @@ -91,8 +94,7 @@ namespace armarx::memory_to_debug_observer { std::atomic_bool rebuild = false; - std::optional<armem::wm::Memory> queryResult; - RemoteGui::Client::GroupBox queryResultGroup; + RemoteGui::Client::GroupBox group; }; RemoteGuiTab tab; diff --git a/source/RobotAPI/libraries/armem/client/util/MemoryToDebugObserver.cpp b/source/RobotAPI/libraries/armem/client/util/MemoryToDebugObserver.cpp index 5e8f44930..89e2cf20c 100644 --- a/source/RobotAPI/libraries/armem/client/util/MemoryToDebugObserver.cpp +++ b/source/RobotAPI/libraries/armem/client/util/MemoryToDebugObserver.cpp @@ -23,6 +23,7 @@ #include "MemoryToDebugObserver.h" #include <RobotAPI/libraries/armem/core/error/mns.h> +#include <RobotAPI/libraries/armem/core/json_conversions.h> #include <RobotAPI/libraries/aron/core/data/variant/Variant.h> #include <RobotAPI/libraries/aron/core/data/variant/primitive/All.h> #include <RobotAPI/libraries/aron/core/data/visitor/variant/VariantVisitor.h> @@ -104,12 +105,20 @@ namespace armarx::armem::client::util Visitor visitor(services.debugObserver); std::stringstream log; + + // Group by memory segment to reduce number of queries. + std::map<MemoryID, std::vector<const MemoryValueID*>> valuesPerProviderSegment; for (const MemoryValueID& valueId : properties.plottedValues) + { + valuesPerProviderSegment[valueId.entityID.getProviderSegmentID()].push_back(&valueId); + } + + for (const auto& [providerSegmentID, values] : valuesPerProviderSegment) { armem::client::Reader* reader = nullptr; try { - reader = getReader(valueId.entityID); + reader = getReader(providerSegmentID); } catch (armem::error::CouldNotResolveMemoryServer& e) { @@ -118,35 +127,47 @@ namespace armarx::armem::client::util } ARMARX_CHECK_NOT_NULL(reader); - std::optional<armem::wm::EntitySnapshot> snapshot = - reader->getLatestSnapshotIn(valueId.entityID); - - if (not snapshot.has_value()) + const QueryResult result = reader->getLatestSnapshotsIn(providerSegmentID); + if (not result.success) { - log << "\nDid not find snapshot in entity " << valueId.entityID << "."; + log << "Query to provider segment " << providerSegmentID + << " failed: " << result.errorMessage; continue; } - aron::data::DictPtr data = snapshot->getInstance(0).data(); - aron::data::VariantPtr valueVariant = data->navigateAbsolute(valueId.aronPath); - if (not valueVariant) + for (const MemoryValueID* valueId : values) { - log << "\nDid not find " << valueId.aronPath.toString() << " in entity snapshot " - << snapshot->id() << "."; - continue; + const wm::Entity* entity = result.memory.findEntity(valueId->entityID); + if (entity == nullptr) + { + log << "\nDid not find entity " << valueId->entityID << " in provider segment " + << providerSegmentID << "."; + continue; + } + + const wm::EntityInstance& instance = entity->getLatestInstance(); + aron::data::VariantPtr valueVariant = + instance.data()->navigateAbsolute(valueId->aronPath); + if (not valueVariant) + { + log << "\nDid not find " << valueId->aronPath.toString() + << " in entity instance " << instance.id() << "."; + continue; + } + + visitor.channelName = makeChannelName(valueId->entityID); + visitor.datafieldName = makeDatafieldName(valueId->aronPath); + + aron::data::visit(visitor, valueVariant); } - - visitor.channelName = makeChannelName(valueId.entityID); - visitor.datafieldName = makeDatafieldName(valueId.aronPath); - - aron::data::visit(visitor, valueVariant); } services.debugObserver.sendDebugObserverBatch(); if (not log.str().empty()) { - ARMARX_INFO << "Encountered issues while sending memory values to the debug observer " + ARMARX_INFO << deactivateSpam(60) + << "Encountered issues while sending memory values to the debug observer " "for plotting: " << log.str(); } @@ -171,20 +192,50 @@ namespace armarx::armem::client::util Reader* MemoryToDebugObserver::getReader(const MemoryID& memoryID) { - armem::MemoryID key = memoryID.getProviderSegmentID(); - - auto it = memoryReaders.find(key); + auto it = memoryReaders.find(memoryID); if (it != memoryReaders.end()) { return &it->second; } else { - armem::client::Reader reader = services.memoryNameSystem.getReader(key); + armem::client::Reader reader = services.memoryNameSystem.getReader(memoryID); - auto [it, _] = memoryReaders.emplace(key, reader); + auto [it, _] = memoryReaders.emplace(memoryID, reader); return &it->second; } } } // namespace armarx::armem::client::util + +namespace armarx::armem::client +{ + + void + util::to_json(simox::json::json& j, const MemoryValueID& id) + { + j["entityID"] = id.entityID.getItems(); + j["aronPath"] = id.aronPath.getPath(); + } + + void + util::from_json(const simox::json::json& j, MemoryValueID& id) + { + id.entityID = MemoryID::fromItems(j.at("entityID").get<std::vector<std::string>>()); + id.aronPath = {j.at("aronPath").get<std::vector<std::string>>()}; + } + + void + util::to_json(simox::json::json& j, const MemoryToDebugObserver::Properties& p) + { + j["plottedValues"] = p.plottedValues; + } + + void + util::from_json(const simox::json::json& j, MemoryToDebugObserver::Properties& p) + { + j.at("plottedValues").get_to(p.plottedValues); + } + + +} // namespace armarx::armem::client diff --git a/source/RobotAPI/libraries/armem/client/util/MemoryToDebugObserver.h b/source/RobotAPI/libraries/armem/client/util/MemoryToDebugObserver.h index c254db3a3..918b78f90 100644 --- a/source/RobotAPI/libraries/armem/client/util/MemoryToDebugObserver.h +++ b/source/RobotAPI/libraries/armem/client/util/MemoryToDebugObserver.h @@ -22,6 +22,8 @@ #pragma once +#include <SimoxUtility/json/json.h> + #include <ArmarXCore/libraries/DebugObserverHelper/DebugObserverHelper.h> #include <RobotAPI/interface/armem/mns/MemoryNameSystemInterface.h> @@ -48,17 +50,28 @@ namespace armarx::armem::client::util class MemoryToDebugObserver { public: + /** + * @brief Configuration. + * + * Can be converted to and from JSON. + */ struct Properties { std::vector<MemoryValueID> plottedValues; }; + /** + * @brief Required services. + */ struct Services { MemoryNameSystem& memoryNameSystem; armarx::DebugObserverHelper& debugObserver; }; + /** + * @brief Constructor. + */ MemoryToDebugObserver(const Properties& properties, const Services& services); /** @@ -78,4 +91,10 @@ namespace armarx::armem::client::util std::map<armem::MemoryID, armem::client::Reader> memoryReaders; }; + void to_json(simox::json::json& j, const MemoryValueID& id); + void from_json(const simox::json::json& j, MemoryValueID& id); + + void to_json(simox::json::json& j, const MemoryToDebugObserver::Properties& p); + void from_json(const simox::json::json& j, MemoryToDebugObserver::Properties& p); + } // namespace armarx::armem::client::util -- GitLab