From d56da92bc6ec006df45dcd19b55ed13715f24376 Mon Sep 17 00:00:00 2001 From: Fabian Reister <fabian.reister@kit.edu> Date: Thu, 27 May 2021 08:12:56 +0200 Subject: [PATCH] RobotReader: implemented getRobotJointState() --- .../client/common/RobotReader.cpp | 140 +++++++++++------- 1 file changed, 85 insertions(+), 55 deletions(-) diff --git a/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.cpp b/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.cpp index 525365942..2d8319dc9 100644 --- a/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.cpp +++ b/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.cpp @@ -7,19 +7,23 @@ #include "ArmarXCore/core/logging/Logging.h" #include <ArmarXCore/core/PackagePath.h> -#include "RobotAPI/libraries/armem/core/Time.h" #include "RobotAPI/libraries/armem/client/query/Builder.h" -#include "RobotAPI/libraries/armem_robot/robot_conversions.h" +#include "RobotAPI/libraries/armem/core/Time.h" +#include "RobotAPI/libraries/armem/core/workingmemory/CoreSegment.h" #include "RobotAPI/libraries/armem_robot/aron_conversions.h" +#include "RobotAPI/libraries/armem_robot/robot_conversions.h" #include <RobotAPI/libraries/armem_robot/aron/Robot.aron.generated.h> - +#include <RobotAPI/libraries/armem_robot_state/aron/JointState.aron.generated.h> namespace fs = ::std::filesystem; namespace armarx::armem::robot_state { - RobotReader::RobotReader(armem::ClientReaderComponentPluginUser& component) : memoryClient(component), transformReader(component) {} + RobotReader::RobotReader(armem::ClientReaderComponentPluginUser& component) : + memoryClient(component), transformReader(component) + { + } void RobotReader::registerPropertyDefinitions(::armarx::PropertyDefinitionsPtr& def) { @@ -28,7 +32,8 @@ namespace armarx::armem::robot_state def->optional(properties.memoryName, propertyPrefix + "Memory"); def->optional(properties.descriptionCoreSegment, propertyPrefix + "descriptionSegment"); def->optional(properties.localizationCoreSegment, propertyPrefix + "localizationSegment"); - def->optional(properties.proprioceptionCoreSegment, propertyPrefix + "proprioceptionSegment"); + def->optional(properties.proprioceptionCoreSegment, + propertyPrefix + "proprioceptionSegment"); } void RobotReader::connect() @@ -36,8 +41,7 @@ namespace armarx::armem::robot_state transformReader.connect(); // Wait for the memory to become available and add it as dependency. - ARMARX_IMPORTANT << "RobotReader: Waiting for memory '" << properties.memoryName - << "' ..."; + ARMARX_IMPORTANT << "RobotReader: Waiting for memory '" << properties.memoryName << "' ..."; auto result = memoryClient.useMemory(properties.memoryName); if (not result.success) { @@ -50,7 +54,8 @@ namespace armarx::armem::robot_state memoryReader.setReadingMemory(result.proxy); } - std::optional<robot::Robot> RobotReader::get(const std::string& name, const armem::Time& timestamp) + std::optional<robot::Robot> RobotReader::get(const std::string& name, + const armem::Time& timestamp) { const auto description = queryDescription(name, timestamp); @@ -63,17 +68,13 @@ namespace armarx::armem::robot_state return get(*description, timestamp); } - robot::Robot RobotReader::get(const robot::RobotDescription& description, const armem::Time& timestamp) { - robot::Robot robot - { - .description = description, - .instance = "", // TODO(fabian.reister): - .config = {}, // will be populated by synchronize - .timestamp = timestamp - }; + robot::Robot robot{.description = description, + .instance = "", // TODO(fabian.reister): + .config = {}, // will be populated by synchronize + .timestamp = timestamp}; synchronize(robot, timestamp); @@ -94,7 +95,8 @@ namespace armarx::armem::robot_state return true; } - std::optional<robot::RobotDescription> RobotReader::queryDescription(const std::string& name, const armem::Time& timestamp) + std::optional<robot::RobotDescription> + RobotReader::queryDescription(const std::string& name, const armem::Time& timestamp) { // Query all entities from provider. armem::client::query::Builder qb; @@ -127,7 +129,6 @@ namespace armarx::armem::robot_state } return getRobotDescription(qResult.memory, name); - } catch (...) { @@ -135,32 +136,34 @@ namespace armarx::armem::robot_state } return std::nullopt; - } - std::optional<robot::RobotState> RobotReader::queryState(const robot::RobotDescription& description, const armem::Time& timestamp) + std::optional<robot::RobotState> + RobotReader::queryState(const robot::RobotDescription& description, + const armem::Time& timestamp) { const auto jointMap = queryJointState(description, timestamp); if (not jointMap) { + ARMARX_WARNING << "Failed to query joint state"; return std::nullopt; } const auto globalPose = queryGlobalPose(description, timestamp); if (not globalPose) { + ARMARX_WARNING << "Failed to query global pose"; return std::nullopt; } return robot::RobotState { - .timestamp = timestamp, - .globalPose = *globalPose, - .jointMap = *jointMap - }; + .timestamp = timestamp, .globalPose = *globalPose, .jointMap = *jointMap}; } - std::optional<robot::RobotState::JointMap> RobotReader::queryJointState(const robot::RobotDescription& description, const armem::Time& timestamp) const + std::optional<robot::RobotState::JointMap> + RobotReader::queryJointState(const robot::RobotDescription& description, + const armem::Time& timestamp) const { // TODO(fabian.reister): how to deal with multiple providers? @@ -181,13 +184,16 @@ namespace armarx::armem::robot_state if (not qResult.success) /* c++20 [[unlikely]] */ { + ARMARX_WARNING << qResult.errorMessage; return std::nullopt; } return getRobotJointState(qResult.memory, description.name); } - std::optional<robot::RobotState::Pose> RobotReader::queryGlobalPose(const robot::RobotDescription& description, const armem::Time& timestamp) const + std::optional<robot::RobotState::Pose> + RobotReader::queryGlobalPose(const robot::RobotDescription& description, + const armem::Time& timestamp) const { const auto result = transformReader.getGlobalPose(description.name, "root", timestamp); if (not result) @@ -198,8 +204,9 @@ namespace armarx::armem::robot_state return result.transform.transform; } - - std::optional<robot::RobotState> RobotReader::getRobotState(const armarx::armem::wm::Memory& memory, const std::string& name) const + std::optional<robot::RobotState> + RobotReader::getRobotState(const armarx::armem::wm::Memory& memory, + const std::string& name) const { // clang-format off const armem::wm::ProviderSegment& providerSegment = memory @@ -231,44 +238,67 @@ namespace armarx::armem::robot_state return robot::convertRobotState(instance); } + // FIXME remove this, use armem/util/util.h + template <typename AronClass> + std::optional<AronClass> tryCast(const wm::EntityInstance& item) + { + static_assert(std::is_base_of<armarx::aron::cppcodegenerator::AronCppClass, + AronClass>::value); + + try + { + AronClass t; + t.fromAron(item.data()); + return t; + } + catch (const armarx::aron::error::AronException&) + { + return std::nullopt; + } + } - std::optional<robot::RobotState::JointMap> RobotReader::getRobotJointState(const armarx::armem::wm::Memory& memory, const std::string& name) const + std::optional<robot::RobotState::JointMap> + RobotReader::getRobotJointState(const armarx::armem::wm::Memory& memory, + const std::string& name) const { - // // clang-format off - // const armem::wm::ProviderSegment& providerSegment = memory - // .getCoreSegment(properties.proprioceptionCoreSegment) - // .getProviderSegment(name); - // // clang-format on - // const auto entities = simox::alg::get_values(providerSegment.entities()); - // // TODO entitiesToRobotState() + robot::RobotState::JointMap jointMap; - // if (entities.empty()) - // { - // ARMARX_WARNING << "No entity found"; - // return std::nullopt; - // } + // clang-format off + const armem::wm::CoreSegment& coreSegment = memory + .getCoreSegment(properties.proprioceptionCoreSegment); + // clang-format on - // const auto entitySnapshots = simox::alg::get_values(entities.front().history()); + for (const auto &[_, providerSegment] : coreSegment.providerSegments()) + { - // if (entitySnapshots.empty()) - // { - // ARMARX_WARNING << "No entity snapshots found"; - // return std::nullopt; - // } + for (const auto &[name, entity] : providerSegment.entities()) + { + const auto& entityInstance = entity.getLatestSnapshot().getInstance(0); - // // TODO(fabian.reister): check if 0 available - // const armem::wm::EntityInstance& instance = entitySnapshots.front().getInstance(0); + const auto jointState = tryCast<::armarx::armem::arondto::JointState>(entityInstance); - // // Here, we access the RobotUnit streaming data stored in the proprioception segment. - // return robot::convertRobotState(instance); + if (not jointState) + { + // ARMARX_WARNING << "Could not convert entity instance to 'JointState'"; + continue; + } - return std::nullopt; // TODO implement - } + jointMap.emplace(jointState->name, jointState->position); + } + } + if (jointMap.empty()) + { + return std::nullopt; + } + return jointMap; + } - std::optional<robot::RobotDescription> RobotReader::getRobotDescription(const armarx::armem::wm::Memory& memory, const std::string& name) const + std::optional<robot::RobotDescription> + RobotReader::getRobotDescription(const armarx::armem::wm::Memory& memory, + const std::string& name) const { // clang-format off const armem::wm::ProviderSegment& providerSegment = memory @@ -297,4 +327,4 @@ namespace armarx::armem::robot_state return robot::convertRobotDescription(instance); } -} // namespace armarx::armem::robot_state \ No newline at end of file +} // namespace armarx::armem::robot_state \ No newline at end of file -- GitLab