diff --git a/source/RobotAPI/components/ArViz/ArVizStorage.cpp b/source/RobotAPI/components/ArViz/ArVizStorage.cpp index decbf95c39a16482ee3bc6975396812397c3d37e..434310e1d26d935d5bd8b5c15444960518a41a28 100644 --- a/source/RobotAPI/components/ArViz/ArVizStorage.cpp +++ b/source/RobotAPI/components/ArViz/ArVizStorage.cpp @@ -22,19 +22,23 @@ #include "ArVizStorage.h" -#include <ArmarXCore/core/logging/Logging.h> -#include <ArmarXCore/core/util/IceBlobToObject.h> -#include <ArmarXCore/core/util/ObjectToIceBlob.h> -#include <ArmarXCore/core/system/ArmarXDataPath.h> +#include <algorithm> +#include <optional> #include <SimoxUtility/json/json.hpp> -#include <iomanip> -#include <optional> +#include <ArmarXCore/core/logging/Logging.h> +#include <ArmarXCore/core/system/ArmarXDataPath.h> +#include <ArmarXCore/core/time.h> +#include <ArmarXCore/core/time/DateTime.h> +#include <ArmarXCore/core/time/Duration.h> +#include <ArmarXCore/core/util/IceBlobToObject.h> +#include <ArmarXCore/core/util/ObjectToIceBlob.h> namespace armarx { - static std::filesystem::path getAbsolutePath(const std::filesystem::path& path) + static std::filesystem::path + getAbsolutePath(const std::filesystem::path& path) { if (path.is_absolute()) { @@ -56,53 +60,53 @@ namespace armarx } } - - std::string ArVizStorage::getDefaultName() const + std::string + ArVizStorage::getDefaultName() const { return "ArVizStorage"; } - - armarx::PropertyDefinitionsPtr ArVizStorage::createPropertyDefinitions() + armarx::PropertyDefinitionsPtr + ArVizStorage::createPropertyDefinitions() { - armarx::PropertyDefinitionsPtr defs(new ComponentPropertyDefinitions(getConfigIdentifier())); + armarx::PropertyDefinitionsPtr defs( + new ComponentPropertyDefinitions(getConfigIdentifier())); - defs->optional(topicName, "TopicName", - "Layer updates are sent over this topic."); + defs->optional( + properties_.topicName, "TopicName", "Layer updates are sent over this topic."); - defs->optional(maxHistorySize, "MaxHistorySize", + defs->optional(properties_.maxHistorySize, + "MaxHistorySize", "How many layer updates are saved in the history until they are compressed") - .setMin(0); + .setMin(0); - defs->defineOptionalProperty<std::string>( - "HistoryPath", "RobotAPI/ArVizStorage", - "Destination path where the history is serialized to"); + defs->optional(properties_.historyPath, + "HistoryPath", + "Destination path where the history is serialized to"); return defs; } - - void ArVizStorage::onInitComponent() + void + ArVizStorage::onInitComponent() { - std::filesystem::path historyPathProp = getProperty<std::string>("HistoryPath").getValue(); - historyPath = getAbsolutePath(historyPathProp); - if (!std::filesystem::exists(historyPath)) + properties_.historyPath = getAbsolutePath(properties_.historyPath); + if (!std::filesystem::exists(properties_.historyPath)) { - ARMARX_INFO << "Creating history path: " << historyPath; + ARMARX_INFO << "Creating history path: " << properties_.historyPath; std::error_code error; - std::filesystem::create_directory(historyPath, error); + std::filesystem::create_directory(properties_.historyPath, error); if (error) { - ARMARX_WARNING << "Could not create directory for history: \n" - << error.message(); + ARMARX_WARNING << "Could not create directory for history: \n" << error.message(); } } - usingTopic(topicName); + usingTopic(properties_.topicName); } - - void ArVizStorage::onConnectComponent() + void + ArVizStorage::onConnectComponent() { revision = 0; currentState.clear(); @@ -113,8 +117,8 @@ namespace armarx recordingMetaData.id = ""; } - - void ArVizStorage::onDisconnectComponent() + void + ArVizStorage::onDisconnectComponent() { if (recordingTask) { @@ -123,20 +127,51 @@ namespace armarx } } - - void ArVizStorage::onExitComponent() + void + ArVizStorage::onExitComponent() { } - - void ArVizStorage::updateLayers(viz::data::LayerUpdateSeq const& updates, const Ice::Current&) + void + ArVizStorage::updateLayers(viz::data::LayerUpdateSeq const& updates, const Ice::Current&) { std::unique_lock<std::mutex> lock(historyMutex); revision += 1; + IceUtil::Time now = IceUtil::Time::now(); long nowInMicroSeconds = now.toMicroSeconds(); + if (not updates.empty()) + { + const std::string& componentName = updates.front().component; + + auto& history = updateHistoryForComponents[componentName]; + history.push_back(armarx::Clock::Now()); + + const auto maxHistoryDur = armarx::Duration::SecondsDouble(1); + + const DateTime referenceNow = Clock::Now(); + const auto isOutdated = [&referenceNow, + &maxHistoryDur](const DateTime& timestamp) -> bool + { return (referenceNow - timestamp) > maxHistoryDur; }; + + // trim history + history.erase(std::remove_if(history.begin(), history.end(), isOutdated), + history.end()); + + ARMARX_VERBOSE << deactivateSpam(1, componentName) << componentName << ": " + << history.size() / maxHistoryDur.toSecondsDouble() << " Hz"; + + if (history.size() > properties_.componentWarnFrequency) + { + ARMARX_WARNING << "Component `" << componentName << "`" + << "sends data at a too high rate (" + << history.size() / maxHistoryDur.toSecondsDouble() << ")"; + } + } + + for (auto& update : updates) { if (update.component.empty()) @@ -157,8 +192,7 @@ namespace armarx bool found = false; for (auto& layer : currentState) { - if (layer.update.component == update.component - && layer.update.name == update.name) + if (layer.update.component == update.component && layer.update.name == update.name) { layer = historyEntry; found = true; @@ -172,7 +206,7 @@ namespace armarx } long currentHistorySize = history.size(); - if (currentHistorySize >= maxHistorySize) + if (currentHistorySize >= properties_.maxHistorySize) { { std::unique_lock<std::mutex> lock(recordingMutex); @@ -190,7 +224,9 @@ namespace armarx } } - viz::data::CommitResult ArVizStorage::commitAndReceiveInteractions(viz::data::CommitInput const& input, const Ice::Current&) + viz::data::CommitResult + ArVizStorage::commitAndReceiveInteractions(viz::data::CommitInput const& input, + const Ice::Current&) { viz::data::CommitResult result; @@ -215,8 +251,8 @@ namespace armarx bool found = false; for (viz::data::TimestampedLayerUpdate& layer : currentState) { - if (layer.update.component == update.component - && layer.update.name == update.name) + if (layer.update.component == update.component && + layer.update.name == update.name) { layer = historyEntry; found = true; @@ -231,7 +267,7 @@ namespace armarx // Trim the history if max size has been exceeded long currentHistorySize = history.size(); - if (currentHistorySize >= maxHistorySize) + if (currentHistorySize >= properties_.maxHistorySize) { { std::unique_lock<std::mutex> lock(recordingMutex); @@ -252,21 +288,23 @@ namespace armarx if (input.interactionComponent.size() > 0) { auto interactionsEnd = interactionBuffer.end(); - auto foundInteractionsBegin = std::partition(interactionBuffer.begin(), interactionsEnd, - [&input](viz::data::InteractionFeedback const& interaction) - { - if (interaction.component == input.interactionComponent) - { - for (std::string const& layer : input.interactionLayers) - { - if (interaction.layer == layer) - { - return false; - } - } - } - return true; - }); + auto foundInteractionsBegin = + std::partition(interactionBuffer.begin(), + interactionsEnd, + [&input](viz::data::InteractionFeedback const& interaction) + { + if (interaction.component == input.interactionComponent) + { + for (std::string const& layer : input.interactionLayers) + { + if (interaction.layer == layer) + { + return false; + } + } + } + return true; + }); result.interactions.assign(foundInteractionsBegin, interactionsEnd); interactionBuffer.erase(foundInteractionsBegin, interactionsEnd); @@ -276,9 +314,8 @@ namespace armarx return result; } - - - viz::data::LayerUpdates ArVizStorage::pullUpdatesSince(Ice::Long revision, const Ice::Current&) + viz::data::LayerUpdates + ArVizStorage::pullUpdatesSince(Ice::Long revision, const Ice::Current&) { viz::data::LayerUpdates result; @@ -297,12 +334,16 @@ namespace armarx return result; } - static const int ALL_TRANSFORM_FLAGS = viz::data::InteractionFeedbackType::TRANSFORM_BEGIN_FLAG - | viz::data::InteractionFeedbackType::TRANSFORM_DURING_FLAG - | viz::data::InteractionFeedbackType::TRANSFORM_END_FLAG; + static const int ALL_TRANSFORM_FLAGS = + viz::data::InteractionFeedbackType::TRANSFORM_BEGIN_FLAG | + viz::data::InteractionFeedbackType::TRANSFORM_DURING_FLAG | + viz::data::InteractionFeedbackType::TRANSFORM_END_FLAG; - viz::data::LayerUpdates ArVizStorage::pullUpdatesSinceAndSendInteractions( - Ice::Long revision, viz::data::InteractionFeedbackSeq const& interactions, const Ice::Current& c) + viz::data::LayerUpdates + ArVizStorage::pullUpdatesSinceAndSendInteractions( + Ice::Long revision, + viz::data::InteractionFeedbackSeq const& interactions, + const Ice::Current& c) { viz::data::LayerUpdates result; @@ -312,9 +353,8 @@ namespace armarx { for (viz::data::InteractionFeedback& entry : interactionBuffer) { - if (entry.component == interaction.component - && entry.layer == interaction.layer - && entry.element == interaction.element) + if (entry.component == interaction.component && entry.layer == interaction.layer && + entry.element == interaction.element) { int previousTransformFlags = entry.type & ALL_TRANSFORM_FLAGS; int interactionTransformFlags = interaction.type & ALL_TRANSFORM_FLAGS; @@ -333,7 +373,7 @@ namespace armarx // Interaction did not exist, add it to the buffer interactionBuffer.push_back(interaction); - for_end: ; + for_end:; } result.updates.reserve(currentState.size()); @@ -349,7 +389,8 @@ namespace armarx return result; } - void ArVizStorage::record() + void + ArVizStorage::record() { while (!recordingTask->isStopped()) { @@ -365,12 +406,13 @@ namespace armarx recordingBuffer.clear(); } } -} +} // namespace armarx namespace armarx::viz::data { - void to_json(nlohmann::json& j, RecordingBatchHeader const& batch) + void + to_json(nlohmann::json& j, RecordingBatchHeader const& batch) { j["index"] = batch.index; j["firstRevision"] = batch.firstRevision; @@ -379,16 +421,18 @@ namespace armarx::viz::data j["lastTimestampInMicroSeconds"] = batch.lastTimestampInMicroSeconds; } - void from_json(nlohmann::json const& j, RecordingBatchHeader& batch) + void + from_json(nlohmann::json const& j, RecordingBatchHeader& batch) { - batch.index = j["index"] ; + batch.index = j["index"]; batch.firstRevision = j["firstRevision"]; batch.lastRevision = j["lastRevision"]; batch.firstTimestampInMicroSeconds = j["firstTimestampInMicroSeconds"]; batch.lastTimestampInMicroSeconds = j["lastTimestampInMicroSeconds"]; } - void to_json(nlohmann::json& j, Recording const& recording) + void + to_json(nlohmann::json& j, Recording const& recording) { j["id"] = recording.id; j["firstRevision"] = recording.firstRevision; @@ -398,7 +442,8 @@ namespace armarx::viz::data j["batchHeaders"] = recording.batchHeaders; } - void from_json(nlohmann::json const& j, Recording& recording) + void + from_json(nlohmann::json const& j, Recording& recording) { recording.id = j["id"]; recording.firstRevision = j["firstRevision"]; @@ -408,10 +453,10 @@ namespace armarx::viz::data j["batchHeaders"].get_to(recording.batchHeaders); } -} +} // namespace armarx::viz::data -static bool writeCompleteFile(std::string const& filename, - const void* data, std::size_t size) +static bool +writeCompleteFile(std::string const& filename, const void* data, std::size_t size) { FILE* file = fopen(filename.c_str(), "wb"); if (!file) @@ -427,12 +472,13 @@ static bool writeCompleteFile(std::string const& filename, return true; } -static std::string readCompleteFile(std::filesystem::path const& path) +static std::string +readCompleteFile(std::filesystem::path const& path) { FILE* f = fopen(path.string().c_str(), "rb"); fseek(f, 0, SEEK_END); long fsize = ftell(f); - fseek(f, 0, SEEK_SET); /* same as rewind(f); */ + fseek(f, 0, SEEK_SET); /* same as rewind(f); */ std::string result(fsize, '\0'); std::size_t read = fread(result.data(), 1, fsize, f); @@ -442,7 +488,8 @@ static std::string readCompleteFile(std::filesystem::path const& path) return result; } -static std::optional<armarx::viz::data::Recording> readRecordingInfo(std::filesystem::path const& recordingDirectory) +static std::optional<armarx::viz::data::Recording> +readRecordingInfo(std::filesystem::path const& recordingDirectory) { std::optional<::armarx::viz::data::Recording> result; @@ -472,12 +519,14 @@ static std::optional<armarx::viz::data::Recording> readRecordingInfo(std::filesy } } -static std::string batchFileName(armarx::viz::data::RecordingBatchHeader const& batchHeader) +static std::string +batchFileName(armarx::viz::data::RecordingBatchHeader const& batchHeader) { return std::to_string(batchHeader.firstRevision) + ".bin"; } -void armarx::ArVizStorage::recordBatch(armarx::viz::data::RecordingBatch& batch) +void +armarx::ArVizStorage::recordBatch(armarx::viz::data::RecordingBatch& batch) { if (batch.updates.empty()) { @@ -492,7 +541,7 @@ void armarx::ArVizStorage::recordBatch(armarx::viz::data::RecordingBatch& batch) batch.header.lastRevision = last.revision; batch.header.firstTimestampInMicroSeconds = first.timestampInMicroseconds; batch.header.lastTimestampInMicroSeconds = last.timestampInMicroseconds; - if (firstBatch) + if (firstBatch) { batch.initialState = currentState; firstBatch = false; @@ -523,7 +572,8 @@ void armarx::ArVizStorage::recordBatch(armarx::viz::data::RecordingBatch& batch) } recordingMetaData.lastTimestampInMicroSeconds = last.timestampInMicroseconds; - armarx::viz::data::RecordingBatchHeader& newBatch = recordingMetaData.batchHeaders.emplace_back(); + armarx::viz::data::RecordingBatchHeader& newBatch = + recordingMetaData.batchHeaders.emplace_back(); newBatch.index = recordingMetaData.batchHeaders.size() - 1; newBatch.firstRevision = first.revision; newBatch.lastRevision = last.revision; @@ -543,26 +593,26 @@ void armarx::ArVizStorage::recordBatch(armarx::viz::data::RecordingBatch& batch) ARMARX_INFO << "Recorded ArViz batch to: " << filePath; } -std::string armarx::ArVizStorage::startRecording(std::string const& newRecordingPrefix, const Ice::Current&) +std::string +armarx::ArVizStorage::startRecording(std::string const& newRecordingPrefix, const Ice::Current&) { { std::unique_lock<std::mutex> lock(recordingMutex); if (recordingMetaData.id.size() > 0) { - ARMARX_WARNING << "Could not start recording with prefix " << newRecordingPrefix - << "\nbecause there is already a recording running for the recording ID: " - << recordingMetaData.id; + ARMARX_WARNING + << "Could not start recording with prefix " << newRecordingPrefix + << "\nbecause there is already a recording running for the recording ID: " + << recordingMetaData.id; return recordingMetaData.id; } IceUtil::Time now = IceUtil::Time::now(); std::ostringstream id; - id << newRecordingPrefix - << '_' - << now.toString("%Y-%m-%d_%H-%M-%S"); + id << newRecordingPrefix << '_' << now.toString("%Y-%m-%d_%H-%M-%S"); std::string newRecordingID = id.str(); - recordingPath = historyPath / newRecordingID; + recordingPath = properties_.historyPath / newRecordingID; if (!std::filesystem::exists(recordingPath)) { ARMARX_INFO << "Creating directory for recording with ID '" << newRecordingID @@ -594,7 +644,8 @@ std::string armarx::ArVizStorage::startRecording(std::string const& newRecording return ""; } -void armarx::ArVizStorage::stopRecording(const Ice::Current&) +void +armarx::ArVizStorage::stopRecording(const Ice::Current&) { if (!recordingTask) { @@ -616,12 +667,14 @@ void armarx::ArVizStorage::stopRecording(const Ice::Current&) recordingMetaData.firstTimestampInMicroSeconds = -1; } -armarx::viz::data::RecordingsInfo armarx::ArVizStorage::getAllRecordings(const Ice::Current&) +armarx::viz::data::RecordingsInfo +armarx::ArVizStorage::getAllRecordings(const Ice::Current&) { viz::data::RecordingsInfo recordingsInfo; viz::data::RecordingSeq result; - for (std::filesystem::directory_entry const& entry : std::filesystem::directory_iterator(historyPath)) + for (std::filesystem::directory_entry const& entry : + std::filesystem::directory_iterator(properties_.historyPath)) { ARMARX_DEBUG << "Checking: " << entry.path(); @@ -638,17 +691,20 @@ armarx::viz::data::RecordingsInfo armarx::ArVizStorage::getAllRecordings(const I } recordingsInfo.recordings = result; - recordingsInfo.recordingsPath = historyPath; + recordingsInfo.recordingsPath = properties_.historyPath; return recordingsInfo; } -armarx::viz::data::RecordingBatch armarx::ArVizStorage::getRecordingBatch(std::string const& recordingID, Ice::Long batchIndex, const Ice::Current&) +armarx::viz::data::RecordingBatch +armarx::ArVizStorage::getRecordingBatch(std::string const& recordingID, + Ice::Long batchIndex, + const Ice::Current&) { viz::data::RecordingBatch result; result.header.index = -1; - std::filesystem::path recordingPath = historyPath / recordingID; + std::filesystem::path recordingPath = properties_.historyPath / recordingID; std::optional<viz::data::Recording> recording = readRecordingInfo(recordingPath); if (!recording) { @@ -669,8 +725,7 @@ armarx::viz::data::RecordingBatch armarx::ArVizStorage::getRecordingBatch(std::s if (!std::filesystem::exists(batchFile)) { ARMARX_WARNING << "Could not find batch file for recording '" << recordingID - << "' with index " << batchIndex - << "\nPath: " << batchFile; + << "' with index " << batchIndex << "\nPath: " << batchFile; return result; } diff --git a/source/RobotAPI/components/ArViz/ArVizStorage.h b/source/RobotAPI/components/ArViz/ArVizStorage.h index 36d4d85564f5817d042b7607c11295cd527e2d69..60305bfd987fe1c75e04f86ab0665095a788447f 100644 --- a/source/RobotAPI/components/ArViz/ArVizStorage.h +++ b/source/RobotAPI/components/ArViz/ArVizStorage.h @@ -22,15 +22,16 @@ #pragma once -#include <RobotAPI/interface/ArViz.h> -#include <ArmarXCore/core/Component.h> -#include <ArmarXCore/core/services/tasks/RunningTask.h> - -#include <mutex> #include <atomic> #include <condition_variable> #include <filesystem> +#include <mutex> +#include "ArmarXCore/core/time/DateTime.h" +#include <ArmarXCore/core/Component.h> +#include <ArmarXCore/core/services/tasks/RunningTask.h> + +#include <RobotAPI/interface/ArViz.h> namespace armarx { @@ -53,12 +54,11 @@ namespace armarx * @brief Stores visualization elements drawn by ArViz clients. * */ - class ArVizStorage - : virtual public armarx::Component - , virtual public armarx::viz::StorageAndTopicInterface + class ArVizStorage : + virtual public armarx::Component, + virtual public armarx::viz::StorageAndTopicInterface { public: - /// armarx::ManagedIceObject::getDefaultName() std::string getDefaultName() const override; @@ -83,17 +83,19 @@ namespace armarx void updateLayers(viz::data::LayerUpdateSeq const& updates, const Ice::Current&) override; // StorageInterface interface - viz::data::CommitResult commitAndReceiveInteractions(viz::data::CommitInput const& input, const Ice::Current&) override; + viz::data::CommitResult commitAndReceiveInteractions(viz::data::CommitInput const& input, + const Ice::Current&) override; viz::data::LayerUpdates pullUpdatesSince(Ice::Long revision, const Ice::Current&) override; - viz::data::LayerUpdates pullUpdatesSinceAndSendInteractions( - Ice::Long revision, - viz::data::InteractionFeedbackSeq const& interactions, - const Ice::Current&) override; + viz::data::LayerUpdates + pullUpdatesSinceAndSendInteractions(Ice::Long revision, + viz::data::InteractionFeedbackSeq const& interactions, + const Ice::Current&) override; std::string startRecording(std::string const& prefix, const Ice::Current&) override; void stopRecording(const Ice::Current&) override; viz::data::RecordingsInfo getAllRecordings(const Ice::Current&) override; - viz::data::RecordingBatch getRecordingBatch(const std::string&, Ice::Long, const Ice::Current&) override; + viz::data::RecordingBatch + getRecordingBatch(const std::string&, Ice::Long, const Ice::Current&) override; private: void record(); @@ -101,9 +103,15 @@ namespace armarx void recordBatch(viz::data::RecordingBatch& batch); private: - std::string topicName = "ArVizTopic"; - int maxHistorySize = 1000; - std::filesystem::path historyPath; + struct Properties + { + std::string topicName = "ArVizTopic"; + int maxHistorySize = 1000; + std::filesystem::path historyPath = "RobotAPI/ArVizStorage"; + + float componentWarnFrequency = 25; + + } properties_; std::mutex historyMutex; @@ -124,5 +132,8 @@ namespace armarx viz::data::Recording recordingMetaData; std::condition_variable recordingCondition; RunningTask<ArVizStorage>::pointer_type recordingTask; + + + std::map<std::string, std::vector<armarx::DateTime>> updateHistoryForComponents; }; -} +} // namespace armarx diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.cpp b/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.cpp index 12dc68399fc92b3d32816dd212d75fc4b0cdab8c..71dad203ab70fab4b411ad891b55b781b9fc7e39 100644 --- a/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.cpp +++ b/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.cpp @@ -1,12 +1,11 @@ #include "VisualizationRobot.h" -#include <fstream> -#include <regex> - #include <VirtualRobot/SceneObject.h> #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualization.h> #include <VirtualRobot/XML/RobotIO.h> +#include <ArmarXCore/core/time/Duration.h> +#include <ArmarXCore/core/time/ScopedStopWatch.h> #include <ArmarXCore/core/logging/Logging.h> #include <ArmarXCore/core/system/ArmarXDataPath.h> #include <ArmarXCore/core/system/cmake/CMakePackageFinder.h> @@ -114,17 +113,23 @@ namespace armarx::viz::coin else { // 2) We do not have unused instances in the pool ==> Clone one - ARMARX_DEBUG << "Cloning robot from cache " << VAROUT(project) << ", " + ARMARX_INFO << "Cloning robot from cache " << VAROUT(project) << ", " << VAROUT(filename); - if (instancePool.robots.size() > 0) + if (!instancePool.robots.empty()) { VirtualRobot::RobotPtr const& robotToClone = instancePool.robots.front(); float scaling = 1.0f; bool preventCloningMeshesIfScalingIs1 = true; - result.robot = robotToClone->clone( + + { + armarx::core::time::ScopedStopWatch sw([](const armarx::Duration& duration){ + ARMARX_DEBUG << "Cloning took " << duration.toSecondsDouble() << " seconds."; + }); + result.robot = robotToClone->clone( nullptr, scaling, preventCloningMeshesIfScalingIs1); + } // Insert the cloned robot into the instance pool instancePool.robots.push_back(result.robot); diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.cpp b/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.cpp index e577eb166ebc77bbbb66dc4ecfe47b9728b2a2be..f6c3146f7877990053cc372670f9fb5800c047bc 100644 --- a/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.cpp +++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.cpp @@ -72,6 +72,20 @@ namespace armarx::objpose return std::nullopt; } + + std::optional<ObjectPose> + ObjectPoseClient::fetchObjectPoseFromProvider(const ObjectID& objectID, const std::string& providerName) const + { + const auto objectPoses = fetchObjectPosesFromProvider(providerName); + const auto *object = findObjectPoseByID(objectPoses, objectID); + + if(object != nullptr) + { + return *object; + } + + return std::nullopt; + } ObjectPoseSeq diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.h b/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.h index 8a1cb31f23f30b37724177aaff7ba30e77ec5604..f2bfb04410bd1d0ba0a3cec4bc9eed14edd26dfb 100644 --- a/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.h +++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.h @@ -76,7 +76,19 @@ namespace armarx::objpose * @return The object's pose, if known. */ std::optional<ObjectPose> - fetchObjectPose(const ObjectID& objectID) const; + fetchObjectPose(const ObjectID& objectID) const; + + /** + * @brief Fetch the pose of a single object and a single provider. + * + * This is a network call. If you need multiple object poses, use + * `fetchObjectPoses()` instead. + * + * @param objectID The object's ID. + * @return The object's pose, if known. + */ + std::optional<ObjectPose> + fetchObjectPoseFromProvider(const ObjectID& objectID, const std::string& providerName) const; /** * @brief Fetch object poses from a specific provider. diff --git a/source/RobotAPI/libraries/armem_robot_state/server/proprioception/converters/ConverterRegistry.cpp b/source/RobotAPI/libraries/armem_robot_state/server/proprioception/converters/ConverterRegistry.cpp index 0c6baa3b770e2136543be7885b1e856a7e93bb78..4c2d920267eb05f799f66e08f26d3ae48b1ee811 100644 --- a/source/RobotAPI/libraries/armem_robot_state/server/proprioception/converters/ConverterRegistry.cpp +++ b/source/RobotAPI/libraries/armem_robot_state/server/proprioception/converters/ConverterRegistry.cpp @@ -13,6 +13,7 @@ namespace armarx::armem::server::robot_state::proprioception add<Armar6Converter>("Armar6"); add<Armar6Converter>("ArmarDE"); add<Armar6Converter>("Armar7"); + add<Armar6Converter>("Frankie"); }