diff --git a/scenarios/ArMemObjectMemory/config/ObjectMemory.cfg b/scenarios/ArMemObjectMemory/config/ObjectMemory.cfg index 77b3f690f0906f31315d4f51d744bc02ab0bfe8c..df483eb31778702f71c8a1ff6c13bf260f86c605 100644 --- a/scenarios/ArMemObjectMemory/config/ObjectMemory.cfg +++ b/scenarios/ArMemObjectMemory/config/ObjectMemory.cfg @@ -215,6 +215,22 @@ ArmarX.AdditionalPackages = ArmarXObjects # ArmarX.ObjectMemory.mem.articulated.inst.MaxHistorySize = -1 +# ArmarX.ObjectMemory.mem.attachments.CoreSegmentName: Name of the object instance core segment. +# Attributes: +# - Default: Attachments +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectMemory.mem.attachments.CoreSegmentName = Attachments + + +# ArmarX.ObjectMemory.mem.attachments.MaxHistorySize: Maximal size of object poses history (-1 for infinite). +# Attributes: +# - Default: -1 +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectMemory.mem.attachments.MaxHistorySize = -1 + + # ArmarX.ObjectMemory.mem.cls.CoreSegmentName: Name of the object clazz core segment. # Attributes: # - Default: Class @@ -303,10 +319,10 @@ ArmarX.AdditionalPackages = ArmarXObjects # ArmarX.ObjectMemory.mem.inst.MaxHistorySize: Maximal size of object poses history (-1 for infinite). # Attributes: -# - Default: -1 +# - Default: 25 # - Case sensitivity: yes # - Required: no -# ArmarX.ObjectMemory.mem.inst.MaxHistorySize = -1 +# ArmarX.ObjectMemory.mem.inst.MaxHistorySize = 25 # ArmarX.ObjectMemory.mem.inst.calibration.offset: Offset for the node to be calibrated. diff --git a/source/RobotAPI/components/ArViz/CMakeLists.txt b/source/RobotAPI/components/ArViz/CMakeLists.txt index 5a21a1cd4e02935799bdd4788aa7e2cac5ca12c8..d79d9a4ba4e3ee75d0860328997112e864c008d3 100644 --- a/source/RobotAPI/components/ArViz/CMakeLists.txt +++ b/source/RobotAPI/components/ArViz/CMakeLists.txt @@ -15,6 +15,7 @@ set(SOURCES Client/elements/Mesh.cpp Client/elements/Robot.cpp Client/elements/RobotHand.cpp + Client/drawer/ArVizDrawerBase.cpp Coin/ElementVisualizer.cpp @@ -75,6 +76,8 @@ set(HEADERS Client/elements/Robot.h Client/elements/RobotHand.h + Client/drawer/ArVizDrawerBase.h + Client/elements/point_cloud_type_traits.hpp Introspection/ElementJsonSerializers.h diff --git a/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.cpp b/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a19032cd088ccdf49e16af5ea394d73a92b30878 --- /dev/null +++ b/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.cpp @@ -0,0 +1,29 @@ +#include "ArVizDrawerBase.h" + +#include "RobotAPI/components/ArViz/Client/Client.h" +#include "RobotAPI/components/ArViz/Client/Layer.h" + +namespace armarx +{ + + ArVizDrawerBase::ArVizDrawerBase(armarx::viz::Client &arviz) : arvizClient(arviz) {} + + ArVizDrawerBase::~ArVizDrawerBase() = default; + + viz::Client &ArVizDrawerBase::arviz() { return arvizClient; } + + const viz::Client &ArVizDrawerBase::arviz() const { return arvizClient; } + + void ArVizDrawerBase::commit(const viz::Layer &layer) + { + std::lock_guard guard{layerMtx}; + arvizClient.commit(layer); + } + + void ArVizDrawerBase::commit(const std::vector<viz::Layer> &layers) + { + std::lock_guard guard{layerMtx}; + arvizClient.commit(layers); + } + +} // namespace armarx diff --git a/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.h b/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.h new file mode 100644 index 0000000000000000000000000000000000000000..f7c813be72283ec4899f402a1133c41ab5a381e2 --- /dev/null +++ b/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.h @@ -0,0 +1,62 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @author Fabian Reister ( fabian dot reister at kit dot edu ) + * @date 2021 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#pragma once + +#include <mutex> +#include <vector> + +namespace armarx +{ + // forward declaration + namespace viz + { + class Client; + struct Layer; + } // namespace viz + + /** + * @brief The ArVizDrawerBase class. Use this class to draw arbitrary objects. + * + * Instead of implementing arviz drawing in the component itself, this class helps to + * decouple drawing from "component / processing logic". + * + */ + class ArVizDrawerBase + { + public: + ArVizDrawerBase(armarx::viz::Client &arviz); + virtual ~ArVizDrawerBase(); + + protected: + viz::Client &arviz(); + const viz::Client &arviz() const; + + void commit(const viz::Layer &layer); + void commit(const std::vector<viz::Layer> &layers); + + private: + viz::Client &arvizClient; + + std::mutex layerMtx; + }; + +} // namespace armarx diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp index 90d9708139772ff7e9a1627db7bbe84209d2e49b..2a3d01143be737e9afb7ce5c27253e2cb6d4891e 100644 --- a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp +++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp @@ -23,36 +23,34 @@ #include "RobotStateMemory.h" // STD -#include <Eigen/src/Geometry/Transform.h> -#include <SimoxUtility/math/convert/rpy_to_mat3f.h> #include <algorithm> #include <iostream> #include <fstream> +#include <memory> -// Header -#include "ArmarXCore/core/logging/Logging.h" -#include "RobotAPI/libraries/armem/core/Time.h" -#include "RobotAPI/libraries/aron/core/navigator/data/AllNavigators.h" -#include "RobotAPI/libraries/core/Pose.h" +// Eigen +#include <Eigen/Core> +#include <Eigen/Geometry> // Simox #include <SimoxUtility/algorithm/string.h> +#include <SimoxUtility/math/convert/rpy_to_mat3f.h> // ArmarX +#include <ArmarXCore/core/logging/Logging.h> #include <ArmarXCore/core/exceptions/local/ExpressionException.h> #include <ArmarXCore/core/system/ArmarXDataPath.h> + #include <RobotAPI/libraries/armem/core/error.h> #include <RobotAPI/libraries/armem/server/MemoryRemoteGui.h> - #include <RobotAPI/libraries/aron/core/navigator/data/AllNavigators.h> #include <RobotAPI/libraries/aron/core/navigator/type/AllNavigators.h> - #include <RobotAPI/libraries/armem_robot_state/server/common/Visu.h> - #include <RobotAPI/libraries/armem_robot_state/aron/Transform.aron.generated.h> - #include <RobotAPI/libraries/core/FramedPose.h> -#include <memory> +#include <RobotAPI/libraries/armem/core/Time.h> +#include <RobotAPI/libraries/aron/core/navigator/data/primitive/Primitive.h> +#include <RobotAPI/libraries/core/Pose.h> namespace armarx::armem::server::robot_state { diff --git a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp index b80a0a07c82ac6ee452b7cab489cee1f12e11b3b..d11b7421313e4586e4347b31c9f8c79c09f169f5 100644 --- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp +++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp @@ -6,14 +6,13 @@ #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/core/Time.h" #include "RobotAPI/libraries/armem/core/workingmemory/CoreSegment.h" -#include "RobotAPI/libraries/armem_robot/robot_conversions.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> - namespace fs = ::std::filesystem; namespace armarx::armem::articulated_object @@ -38,7 +37,6 @@ namespace armarx::armem::articulated_object def->optional(properties.providerName, prefix + "ProviderName"); } - void Reader::connect() { // Wait for the memory to become available and add it as dependency. @@ -55,7 +53,7 @@ namespace armarx::armem::articulated_object memoryReader.setReadingMemory(result.proxy); armem::MemoryID id = armem::MemoryID(); - id.memoryName = properties.memoryName; + id.memoryName = properties.memoryName; id.coreSegmentName = properties.coreClassSegmentName; // listen to all provider segments! @@ -72,7 +70,8 @@ namespace armarx::armem::articulated_object // TODO(fabian.reister): implement } - void Reader::updateKnownObjects(const armem::MemoryID& subscriptionID, const std::vector<armem::MemoryID>& snapshotIDs) + void Reader::updateKnownObjects(const armem::MemoryID& subscriptionID, + const std::vector<armem::MemoryID>& snapshotIDs) { ARMARX_INFO << "New objects available!"; @@ -89,15 +88,14 @@ namespace armarx::armem::articulated_object // const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput()); - // std::for_each(snapshotIDs.begin(), snapshotIDs.end(), [&](const auto & snapshotID) // { // updateKnownObject(snapshotID); // }); } - - std::optional<ArticulatedObject> Reader::get(const std::string& name, const armem::Time& timestamp) + std::optional<ArticulatedObject> Reader::get(const std::string& name, + const armem::Time& timestamp) { const auto description = queryDescription(name, timestamp); @@ -110,17 +108,13 @@ namespace armarx::armem::articulated_object return get(*description, timestamp); } - ArticulatedObject Reader::get(const ArticulatedObjectDescription& description, const armem::Time& timestamp) { - ArticulatedObject obj - { - .description = description, - .instance = "", // TODO(fabian.reister): - .config = {}, // will be populated by synchronize - .timestamp = timestamp - }; + ArticulatedObject obj{.description = description, + .instance = "", // TODO(fabian.reister): + .config = {}, // will be populated by synchronize + .timestamp = timestamp}; synchronize(obj, timestamp); @@ -165,7 +159,8 @@ namespace armarx::armem::articulated_object return getRobotDescriptions(qResult.memory); } - std::optional<robot::RobotDescription> Reader::queryDescription(const std::string& name, const armem::Time& timestamp) + std::optional<robot::RobotDescription> Reader::queryDescription(const std::string& name, + const armem::Time& timestamp) { // Query all entities from provider. armem::client::query::Builder qb; @@ -174,8 +169,8 @@ namespace armarx::armem::articulated_object qb .coreSegments().withName(properties.coreClassSegmentName) .providerSegments().all() // TODO(fabian.reister): think about this: which authority is trustworthy? - .entities().withName(name) - .snapshots().atTime(timestamp); + .entities().all() // withName(name) + .snapshots().latest(); // clang-format on const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput()); @@ -184,13 +179,15 @@ namespace armarx::armem::articulated_object if (not qResult.success) /* c++20 [[unlikely]] */ { + ARMARX_WARNING << qResult.errorMessage; return std::nullopt; } return getRobotDescription(qResult.memory); } - std::optional<robot::RobotState> Reader::queryState(const robot::RobotDescription& description, const armem::Time& timestamp) + std::optional<robot::RobotState> Reader::queryState(const robot::RobotDescription& description, + const armem::Time& timestamp) { // TODO(fabian.reister): how to deal with multiple providers? @@ -200,9 +197,9 @@ namespace armarx::armem::articulated_object // clang-format off qb .coreSegments().withName(properties.coreInstanceSegmentName) - .providerSegments().withName(properties.providerName) // agent + .providerSegments().all() // withName(properties.providerName) // agent .entities().withName(description.name) - .snapshots().atTime(timestamp); + .snapshots().latest(); // clang-format on const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput()); @@ -217,76 +214,91 @@ namespace armarx::armem::articulated_object return getRobotState(qResult.memory); } - - std::optional<robot::RobotState> Reader::getRobotState(const armarx::armem::wm::Memory& memory) const + std::optional<robot::RobotState> + Reader::getRobotState(const armarx::armem::wm::Memory& memory) const { // clang-format off - const armem::wm::ProviderSegment& providerSegment = memory - .getCoreSegment(properties.coreInstanceSegmentName) - .getProviderSegment(properties.providerName); + const armem::wm::CoreSegment& coreSegment = memory + .getCoreSegment(properties.coreInstanceSegmentName); // clang-format on - const auto entities = simox::alg::get_values(providerSegment.entities()); - if (entities.empty()) + for (const auto &[_, providerSegment] : coreSegment.providerSegments()) { - ARMARX_WARNING << "No entity found"; - return std::nullopt; - } - const auto entitySnapshots = simox::alg::get_values(entities.front().history()); + const auto entities = simox::alg::get_values(providerSegment.entities()); - if (entitySnapshots.empty()) - { - ARMARX_WARNING << "No entity snapshots found"; - return std::nullopt; - } + if (entities.empty()) + { + ARMARX_WARNING << "No entity found"; + continue; + } - // TODO(fabian.reister): check if 0 available - const armem::wm::EntityInstance& instance = entitySnapshots.front().getInstance(0); + const auto entitySnapshots = simox::alg::get_values(entities.front().history()); - return robot::convertRobotState(instance); - } + if (entitySnapshots.empty()) + { + ARMARX_WARNING << "No entity snapshots found"; + continue; + } + // TODO(fabian.reister): check if 0 available + const armem::wm::EntityInstance& instance = entitySnapshots.front().getInstance(0); + return robot::convertRobotState(instance); + } + + return std::nullopt; + } - std::optional<robot::RobotDescription> Reader::getRobotDescription(const armarx::armem::wm::Memory& memory) const + std::optional<robot::RobotDescription> + Reader::getRobotDescription(const armarx::armem::wm::Memory& memory) const { // clang-format off - const armem::wm::ProviderSegment& providerSegment = memory - .getCoreSegment(properties.coreClassSegmentName) - .getProviderSegment(properties.providerName); // TODO(fabian.reister): all + const armem::wm::CoreSegment& coreSegment = memory + .getCoreSegment(properties.coreClassSegmentName); + // .getProviderSegment(properties.providerName); // TODO(fabian.reister): all // clang-format on - const auto entities = simox::alg::get_values(providerSegment.entities()); - if (entities.empty()) + for (const auto &[_, providerSegment] : coreSegment.providerSegments()) { - ARMARX_WARNING << "No entity found"; - return std::nullopt; - } + const auto entities = simox::alg::get_values(providerSegment.entities()); + + if (entities.empty()) + { + ARMARX_WARNING << "No entity found"; + continue; + // return std::nullopt; + } - const auto entitySnapshots = simox::alg::get_values(entities.front().history()); + const auto entitySnapshots = simox::alg::get_values(entities.front().history()); - if (entitySnapshots.empty()) - { - ARMARX_WARNING << "No entity snapshots found"; - return std::nullopt; - } + if (entitySnapshots.empty()) + { + ARMARX_WARNING << "No entity snapshots found"; + continue; + // return std::nullopt; + } + + // TODO(fabian.reister): check if 0 available + const armem::wm::EntityInstance& instance = entitySnapshots.front().getInstance(0); - // TODO(fabian.reister): check if 0 available - const armem::wm::EntityInstance& instance = entitySnapshots.front().getInstance(0); + return robot::convertRobotDescription(instance); + } - return robot::convertRobotDescription(instance); + return std::nullopt; } - std::vector<robot::RobotDescription> Reader::getRobotDescriptions(const armarx::armem::wm::Memory& memory) const + std::vector<robot::RobotDescription> + Reader::getRobotDescriptions(const armarx::armem::wm::Memory& memory) const { std::vector<robot::RobotDescription> descriptions; - const armem::wm::CoreSegment& coreSegment = memory.getCoreSegment(properties.coreClassSegmentName); + const armem::wm::CoreSegment& coreSegment = + memory.getCoreSegment(properties.coreClassSegmentName); - for (const auto& [providerName, providerSegment] : coreSegment.providerSegments()) + for (const auto &[providerName, providerSegment] : coreSegment.providerSegments()) { - for (const auto& [name, entity] : providerSegment.entities()) + for (const auto &[name, entity] : providerSegment.entities()) { if (entity.empty()) { @@ -309,5 +321,4 @@ namespace armarx::armem::articulated_object return descriptions; } - } // namespace armarx::armem::articulated_object \ No newline at end of file diff --git a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp index 703ef91aa2eea9d00ea09b88255b68ffacba68bc..9062747de124ac3db5ba37e3f14f2b8cdfc7b692 100644 --- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp +++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp @@ -34,7 +34,7 @@ namespace armarx::armem::articulated_object def->optional(properties.coreClassSegmentName, prefix + "CoreSegment", "Name of the memory core segment to use for object classes."); - def->optional(properties.providerName, prefix + "ProviderName"); + def->required(properties.providerName, prefix + "ProviderName", "Name of this provider"); } void Writer::connect() diff --git a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.h b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.h index 7e450b0464d1b571791392beb4622afc77444f5b..f2031dd402e546a21a80a17c28f8b2e4107f9059 100644 --- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.h +++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.h @@ -70,7 +70,7 @@ namespace armarx::armem::articulated_object std::string memoryName = "Object"; std::string coreInstanceSegmentName = "ArticulatedObjectInstance"; std::string coreClassSegmentName = "ArticulatedObjectClass"; - std::string providerName = "ArmarXObjects"; + std::string providerName; bool allowClassCreation = false; } properties; diff --git a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h index 54314054a38f5f104552c045fe37eb8b401651ae..5b7c268bb28530b82906bc07cee31431d6738f5c 100644 --- a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h +++ b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h @@ -159,7 +159,8 @@ namespace armarx::armem::server::obj::instance struct Properties { std::string coreSegmentName = "Instance"; - long maxHistorySize = -1; + // -1 would be infinite, but this can let the RAM grow quickly. + long maxHistorySize = 25; bool discardSnapshotsWhileAttached = true; }; Properties p; diff --git a/source/RobotAPI/libraries/armem_robot/robot_conversions.cpp b/source/RobotAPI/libraries/armem_robot/robot_conversions.cpp index 6c05e89e038c6f80f61e3e9c47f25bf8b2f1335f..3bf4171486e35c33a1cca23a666baac2233a8356 100644 --- a/source/RobotAPI/libraries/armem_robot/robot_conversions.cpp +++ b/source/RobotAPI/libraries/armem_robot/robot_conversions.cpp @@ -43,10 +43,10 @@ namespace armarx::armem::robot std::optional<RobotState> convertRobotState(const armem::wm::EntityInstance& instance) { - arondto::RobotState aronRobotState; + arondto::Robot aronRobot; try { - aronRobotState.fromAron(instance.data()); + aronRobot.fromAron(instance.data()); } catch (...) { @@ -55,7 +55,7 @@ namespace armarx::armem::robot } RobotState robotState; - fromAron(aronRobotState, robotState); + fromAron(aronRobot.state, robotState); return robotState; } diff --git a/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.cpp b/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.cpp index 108c8069178d9da7b1142d22e649dd80a7e03bd4..5ba879601c461906e546930b4ef3dacea7a78899 100644 --- a/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.cpp +++ b/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.cpp @@ -1,20 +1,27 @@ #include "Segment.h" -#include <Eigen/src/Geometry/Transform.h> -#include <IceUtil/Time.h> -#include <RobotAPI/libraries/armem_robot_state/aron/Transform.aron.generated.h> +// STL + #include <iterator> #include <sstream> -#include "ArmarXCore/core/logging/Logging.h" +// Ice +#include <IceUtil/Time.h> + +// Eigen +#include <Eigen/Core> +#include <Eigen/Geometry> + +#include <ArmarXCore/core/logging/Logging.h> #include <ArmarXCore/core/time/TimeUtil.h> -#include "RobotAPI/libraries/aron/common/aron_conversions.h" +#include <RobotAPI/libraries/core/FramedPose.h> + +#include <RobotAPI/libraries/aron/common/aron_conversions.h> -#include "RobotAPI/libraries/armem/core/MemoryID.h" -#include "RobotAPI/libraries/armem/core/Time.h" -#include "RobotAPI/libraries/armem_robot/robot_conversions.h" -#include "RobotAPI/libraries/core/FramedPose.h" +#include <RobotAPI/libraries/armem/core/aron_conversions.h> +#include <RobotAPI/libraries/armem/core/MemoryID.h> +#include <RobotAPI/libraries/armem/core/Time.h> #include <RobotAPI/libraries/armem/client/Writer.h> #include <RobotAPI/libraries/armem/client/query/Builder.h> #include <RobotAPI/libraries/armem/client/query/query_fns.h> @@ -22,12 +29,11 @@ #include <RobotAPI/libraries/armem/core/workingmemory/Visitor.h> #include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.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_conversions.h> - -#include <RobotAPI/libraries/armem/core/aron_conversions.h> -#include <RobotAPI/libraries/aron/common/aron_conversions.h> +#include <RobotAPI/libraries/armem_robot_state/aron/Transform.aron.generated.h> +#include <RobotAPI/libraries/armem_robot_state/aron_conversions.h> #include <RobotAPI/libraries/armem_robot_state/common/localization/types.h> #include <RobotAPI/libraries/armem_robot_state/common/localization/TransformHelper.h>