diff --git a/scenarios/ArMemObjectMemory/config/ArticulatedObjectExampleMemoryWriterClient.cfg b/scenarios/ArMemObjectMemory/config/ArticulatedObjectExampleMemoryWriterClient.cfg index bbfc7a0ca3a8eddd35f8c447efb327bbbe260c48..5082b0ffc78b15d395b64deb6f0ba3c14ac38ea9 100644 --- a/scenarios/ArMemObjectMemory/config/ArticulatedObjectExampleMemoryWriterClient.cfg +++ b/scenarios/ArMemObjectMemory/config/ArticulatedObjectExampleMemoryWriterClient.cfg @@ -75,6 +75,30 @@ ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.ArMemMemor ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.ProviderName = ExampleProvider +# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ArMemMemoryNameSystem: No Description +# Attributes: +# - Default: MemoryNameSystem +# - Case sensitivity: no +# - Required: no +ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ArMemMemoryNameSystem = MemoryNameSystem + + +# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.MemoryName: No Description +# Attributes: +# - Default: Object +# - Case sensitivity: no +# - Required: no +ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.MemoryName = Object + + +# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ProviderName: No Description +# Attributes: +# - Default: ExampleProvider +# - Case sensitivity: no +# - Required: no +ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ProviderName = ExampleProvider + + # ArmarX.ArticulatedObjectExampleMemoryWriterClient.tpc.pub.DebugObserver: Name of the `DebugObserver` topic to publish data to. # Attributes: # - Default: DebugObserver @@ -225,18 +249,3 @@ ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.ProviderNa # ArmarX.Verbosity = Info -# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ArMemMemoryNameSystem: -# Attributes: -ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ArMemMemoryNameSystem = MemoryNameSystem - - -# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.MemoryName: -# Attributes: -ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.MemoryName = Object - - -# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ProviderName: -# Attributes: -ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ProviderName = ExampleProvider - - diff --git a/scenarios/ArMemObjectMemory/config/ObjectMemory.cfg b/scenarios/ArMemObjectMemory/config/ObjectMemory.cfg index 88ad0e549f399971ccb3aecafa7d32ef7df4be42..67e86da4ae2afbacca3e22a5eb4bc878f801145f 100644 --- a/scenarios/ArMemObjectMemory/config/ObjectMemory.cfg +++ b/scenarios/ArMemObjectMemory/config/ObjectMemory.cfg @@ -166,6 +166,58 @@ # ArmarX.ObjectMemory.mem.MemoryName = Object +# ArmarX.ObjectMemory.mem.articulated.cls.CoreSegmentName: Name of the object instance core segment. +# Attributes: +# - Default: ArticulatedObjectClass +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectMemory.mem.articulated.cls.CoreSegmentName = ArticulatedObjectClass + + +# ArmarX.ObjectMemory.mem.articulated.cls.DiscardSnapshotsWhileAttached: If true, no new snapshots are stored while an object is attached to a robot node. +# If false, new snapshots are stored, but the attachment is kept in the new snapshots. +# Attributes: +# - Default: true +# - Case sensitivity: yes +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +# ArmarX.ObjectMemory.mem.articulated.cls.DiscardSnapshotsWhileAttached = true + + +# ArmarX.ObjectMemory.mem.articulated.cls.MaxHistorySize: Maximal size of object poses history (-1 for infinite). +# Attributes: +# - Default: -1 +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectMemory.mem.articulated.cls.MaxHistorySize = -1 + + +# ArmarX.ObjectMemory.mem.articulated.inst.CoreSegmentName: Name of the object instance core segment. +# Attributes: +# - Default: ArticulatedObjectInstance +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectMemory.mem.articulated.inst.CoreSegmentName = ArticulatedObjectInstance + + +# ArmarX.ObjectMemory.mem.articulated.inst.DiscardSnapshotsWhileAttached: If true, no new snapshots are stored while an object is attached to a robot node. +# If false, new snapshots are stored, but the attachment is kept in the new snapshots. +# Attributes: +# - Default: true +# - Case sensitivity: yes +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +# ArmarX.ObjectMemory.mem.articulated.inst.DiscardSnapshotsWhileAttached = true + + +# ArmarX.ObjectMemory.mem.articulated.inst.MaxHistorySize: Maximal size of object poses history (-1 for infinite). +# Attributes: +# - Default: -1 +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectMemory.mem.articulated.inst.MaxHistorySize = -1 + + # ArmarX.ObjectMemory.mem.cls.CoreSegmentName: Name of the object clazz core segment. # Attributes: # - Default: Class @@ -453,14 +505,6 @@ # ArmarX.ObjectMemory.tpc.pub.MemoryListener = MemoryUpdates -# ArmarX.ObjectMemory.tpc.sub.ArticulatedObjectTopic: Name of the `ArticulatedObjectTopic` topic to subscribe to. -# Attributes: -# - Default: ArticulatedObjectTopic -# - Case sensitivity: yes -# - Required: no -# ArmarX.ObjectMemory.tpc.sub.ArticulatedObjectTopic = ArticulatedObjectTopic - - # ArmarX.ObjectMemory.tpc.sub.ObjectPoseTopic: Name of the `ObjectPoseTopic` topic to subscribe to. # Attributes: # - Default: ObjectPoseTopic diff --git a/source/RobotAPI/components/armem/client/ArticulatedObjectExampleMemoryWriterClient/ArticulatedObjectExampleMemoryWriterClient.cpp b/source/RobotAPI/components/armem/client/ArticulatedObjectExampleMemoryWriterClient/ArticulatedObjectExampleMemoryWriterClient.cpp index 4d45a76b229a11ac6570fb519ff3b2eb0cadd048..efe2de65b74e5f4a06b76983b1b1ae3f2e5097c4 100644 --- a/source/RobotAPI/components/armem/client/ArticulatedObjectExampleMemoryWriterClient/ArticulatedObjectExampleMemoryWriterClient.cpp +++ b/source/RobotAPI/components/armem/client/ArticulatedObjectExampleMemoryWriterClient/ArticulatedObjectExampleMemoryWriterClient.cpp @@ -103,7 +103,7 @@ namespace armarx::articulated_object CycleUtil cycle(IceUtil::Time::milliSeconds(100)); IceUtil::Time start = TimeUtil::GetTime(); - CycleUtil c(1000); + CycleUtil c(100); while (not task->isStopped()) { @@ -113,11 +113,11 @@ namespace armarx::articulated_object const float t = float((now - start).toSecondsDouble()); // move joints at certain frequency - const float k = (1 + std::sin(t / (M_2_PIf32 * 0.2))) / 2; // in [0,1] + const float k = (1 + std::sin(t / (M_2_PIf32))) / 2; // in [0,1] const std::map<std::string, float> jointValues { - {"dishwasher_door_joint", 0.2 * k}, + {"dishwasher_door_joint", M_PIf32 / 2 * k}, {"drawer_joint", 350 * k} }; diff --git a/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.cpp b/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.cpp index 2d62c6c7e0b975e7729f989cb37ee3542905649f..338bdc68adb2918c40707048664c773447404fa4 100644 --- a/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.cpp +++ b/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.cpp @@ -54,6 +54,9 @@ namespace armarx::armem::server::obj classSegment.defineProperties(defs, prefix + "cls."); instance::SegmentAdapter::defineProperties(defs, prefix + "inst."); + articulatedObjectInstanceSegment.defineProperties(defs, prefix + "articulated.inst."); + articulatedObjectClassSegment.defineProperties(defs, prefix + "articulated.cls."); + return defs; } @@ -62,7 +65,11 @@ namespace armarx::armem::server::obj instance::SegmentAdapter(server::ComponentPluginUser::iceMemory, server::ComponentPluginUser::workingMemoryMutex), classSegment(server::ComponentPluginUser::iceMemory, - server::ComponentPluginUser::workingMemoryMutex) + server::ComponentPluginUser::workingMemoryMutex), + articulatedObjectClassSegment(server::ComponentPluginUser::iceMemory, + server::ComponentPluginUser::workingMemoryMutex), + articulatedObjectInstanceSegment(server::ComponentPluginUser::iceMemory, + server::ComponentPluginUser::workingMemoryMutex) { } @@ -77,6 +84,7 @@ namespace armarx::armem::server::obj instance::SegmentAdapter::init(); + // class segment try { classSegment.init(); @@ -93,6 +101,43 @@ namespace armarx::armem::server::obj { ARMARX_ERROR << "Failed to init class segment for unknown reason."; } + + // articulated object class segment + try + { + articulatedObjectClassSegment.init(); + } + catch (const LocalException& e) + { + ARMARX_ERROR << "Failed to init class segment. Reason: \n" << e.what(); + } + catch (const std::exception& e) + { + ARMARX_ERROR << "Failed to init class segment. Reason: \n" << e.what(); + } + catch (...) + { + ARMARX_ERROR << "Failed to init class segment for unknown reason."; + } + + // articulated object instance segment + try + { + articulatedObjectInstanceSegment.setArticulatedObjectClassSegment(articulatedObjectClassSegment); + articulatedObjectInstanceSegment.init(); + } + catch (const LocalException& e) + { + ARMARX_ERROR << "Failed to init class segment. Reason: \n" << e.what(); + } + catch (const std::exception& e) + { + ARMARX_ERROR << "Failed to init class segment. Reason: \n" << e.what(); + } + catch (...) + { + ARMARX_ERROR << "Failed to init class segment for unknown reason."; + } } void ObjectMemory::onConnectComponent() @@ -112,19 +157,27 @@ namespace armarx::armem::server::obj robotStateComponent, robot, kinematicUnitObserver, - ArVizComponentPluginUser::arviz, + ArVizComponentPluginUser::getArvizClient(), debugObserver ); classSegment.connect( - ArVizComponentPluginUser::arviz + ArVizComponentPluginUser::getArvizClient() ); + articulatedObjectClassSegment.connect( + ArVizComponentPluginUser::getArvizClient() + ); - { - std::lock_guard g(server::ComponentPluginUser::workingMemoryMutex); - server::ComponentPluginUser::workingMemory.addCoreSegment("ArticulatedObjectInstance"); // TODO , arondto::::toInitialAronType()); - server::ComponentPluginUser::workingMemory.addCoreSegment("ArticulatedObjectClass"); // TODO , arondto::::toInitialAronType()); - } + articulatedObjectInstanceSegment.connect( + ArVizComponentPluginUser::getArvizClient() + ); + + + // { + // std::lock_guard g(server::ComponentPluginUser::workingMemoryMutex); + // // server::ComponentPluginUser::workingMemory.addCoreSegment("ArticulatedObjectInstance"); // TODO , arondto::::toInitialAronType()); + // server::ComponentPluginUser::workingMemory.addCoreSegment("ArticulatedObjectClass"); // TODO , arondto::::toInitialAronType()); + // } createRemoteGuiTab(); RemoteGui_startRunningTask(); diff --git a/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.h b/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.h index 65bd9c472828faa2b8b7f58679c4922c1aef389d..822fabbe56fad5158337c81c9c0089aa5d7233c2 100644 --- a/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.h +++ b/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.h @@ -38,6 +38,8 @@ #include <RobotAPI/libraries/armem_objects/server/class/Segment.h> #include <RobotAPI/libraries/armem_objects/server/instance/SegmentAdapter.h> +#include <RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.h> +#include <RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.h> #define ICE_CURRENT_ARG const Ice::Current& = Ice::emptyCurrent @@ -108,6 +110,9 @@ namespace armarx::armem::server::obj clazz::Segment classSegment; + articulated_object_class::Segment articulatedObjectClassSegment; + articulated_object_instance::Segment articulatedObjectInstanceSegment; + struct RemoteGuiTab : armarx::RemoteGui::Client::Tab { @@ -118,6 +123,6 @@ namespace armarx::armem::server::obj }; -} +} // namespace armarx::armem::server::obj #undef ICE_CURRENT_ARG diff --git a/source/RobotAPI/libraries/armem/core/MemoryID.h b/source/RobotAPI/libraries/armem/core/MemoryID.h index 09415ec4abd73185f77050c89683b326f3c3e9d0..7ddf2130801767eabb60c01caba1d2dc427caba3 100644 --- a/source/RobotAPI/libraries/armem/core/MemoryID.h +++ b/source/RobotAPI/libraries/armem/core/MemoryID.h @@ -90,19 +90,19 @@ namespace armarx::armem bool hasMemoryName() const { - return memoryName.size() > 0; + return !memoryName.empty(); } bool hasCoreSegmentName() const { - return coreSegmentName.size() > 0; + return !coreSegmentName.empty(); } bool hasProviderSegmentName() const { - return providerSegmentName.size() > 0; + return !providerSegmentName.empty(); } bool hasEntityName() const { - return entityName.size() > 0; + return !entityName.empty(); } bool hasTimestamp() const { @@ -254,7 +254,7 @@ namespace armarx::armem */ bool contains(const MemoryID& general, const MemoryID& specific); -} +} // namespace armarx::armem namespace std diff --git a/source/RobotAPI/libraries/armem_objects/CMakeLists.txt b/source/RobotAPI/libraries/armem_objects/CMakeLists.txt index 47c5b78eafc5c9cded97c85ccd8f95ebf382670c..b491f16ce361bb4c5ca46b1f46104b6cb302711e 100644 --- a/source/RobotAPI/libraries/armem_objects/CMakeLists.txt +++ b/source/RobotAPI/libraries/armem_objects/CMakeLists.txt @@ -28,13 +28,17 @@ armarx_add_library( server/instance/RobotHeadMovement.h server/instance/Visu.h - # server/articulated_object/Segment.h + server/articulated_object_class/Segment.h + server/articulated_object_instance/Segment.h # server/articulated_object/SegmentAdapter.h server/articulated_object_instance/Visu.h client/articulated_object/Reader.cpp client/articulated_object/Writer.cpp + articulated_object_conversions.cpp + + SOURCES aron_conversions.cpp @@ -47,7 +51,9 @@ armarx_add_library( server/instance/RobotHeadMovement.cpp server/instance/Visu.cpp - # server/articulated_object/Segment.cpp + server/articulated_object_class/Segment.cpp + + server/articulated_object_instance/Segment.cpp # server/articulated_object/SegmentAdapter.cpp server/articulated_object_instance/Visu.cpp @@ -55,6 +61,8 @@ armarx_add_library( client/articulated_object/Writer.h client/articulated_object/interfaces.h + articulated_object_conversions.h + ) diff --git a/source/RobotAPI/libraries/armem_objects/aron/RobotDescription.xml b/source/RobotAPI/libraries/armem_objects/aron/RobotDescription.xml index 84ab00dc170c94880205ce0f9d1327eaf98b0aac..edce8c802a4e77cb571492700422b7c04eb7e1a1 100644 --- a/source/RobotAPI/libraries/armem_objects/aron/RobotDescription.xml +++ b/source/RobotAPI/libraries/armem_objects/aron/RobotDescription.xml @@ -1,13 +1,12 @@ <!--This class cotains information on how to create a VirtualRobot::Robot --> <?xml version="1.0" encoding="UTF-8" ?> <AronTypeDefinition> - <AronIncludes> - <Include include="<RobotAPI/libraries/aron/common/aron/PackagePath.xml>" /> - </AronIncludes> <CodeIncludes> <Include include="<RobotAPI/libraries/aron/common/aron/PackagePath.aron.generated.h>" /> </CodeIncludes> - + <AronIncludes> + <Include include="<RobotAPI/libraries/aron/common/aron/PackagePath.xml>" /> + </AronIncludes> <GenerateTypes> <Object name='armarx::armem::arondto::RobotDescription'> diff --git a/source/RobotAPI/libraries/armem_objects/articulated_object_conversions.cpp b/source/RobotAPI/libraries/armem_objects/articulated_object_conversions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03cac43717941e8da1a3a738d6c15aad1aa8987d --- /dev/null +++ b/source/RobotAPI/libraries/armem_objects/articulated_object_conversions.cpp @@ -0,0 +1,65 @@ +#include "articulated_object_conversions.h" + +#include <filesystem> + +#include <RobotAPI/libraries/aron/common/aron_conversions.h> + +#include "RobotAPI/libraries/armem/core/workingmemory/EntityInstance.h" +#include <RobotAPI/libraries/armem/core/aron_conversions.h> + +#include <RobotAPI/libraries/armem_objects/aron_conversions.h> + +#include <RobotAPI/libraries/ArmarXObjects/aron_conversions.h> + + +namespace fs = ::std::filesystem; + +namespace armarx::armem::articulated_object +{ + + std::optional<RobotDescription> convertRobotDescription(const armem::wm::EntityInstance& instance) + { + arondto::RobotDescription aronRobotDescription; + try + { + aronRobotDescription.fromAron(instance.data()); + } + catch (...) + { + ARMARX_WARNING << "Conversion to RobotDescription failed!"; + return std::nullopt; + } + + + RobotDescription robotDescription + { + .name = "", + .xml = ::armarx::PackagePath("", fs::path("")) // initialize empty, no default c'tor + }; + + fromAron(aronRobotDescription, robotDescription); + + return robotDescription; + } + + + std::optional<RobotState> convertRobotState(const armem::wm::EntityInstance& instance) + { + arondto::RobotState aronRobotState; + try + { + aronRobotState.fromAron(instance.data()); + } + catch (...) + { + ARMARX_WARNING << "Conversion to RobotState failed!"; + return std::nullopt; + } + + RobotState robotState; + fromAron(aronRobotState, robotState); + + return robotState; + } + +} diff --git a/source/RobotAPI/libraries/armem_objects/articulated_object_conversions.h b/source/RobotAPI/libraries/armem_objects/articulated_object_conversions.h new file mode 100644 index 0000000000000000000000000000000000000000..ab29163c347bca6cfa78aa1b10581955140a3fc1 --- /dev/null +++ b/source/RobotAPI/libraries/armem_objects/articulated_object_conversions.h @@ -0,0 +1,16 @@ +#pragma once + +#include <optional> + +#include "types.h" + +namespace armarx::armem::wm +{ + class EntityInstance; +} + +namespace armarx::armem::articulated_object +{ + std::optional<RobotDescription> convertRobotDescription(const armem::wm::EntityInstance& instance); + std::optional<RobotState> convertRobotState(const armem::wm::EntityInstance& instance); +} // namespace armarx::armem::articulated_object 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 3d2fd18ddb5c3591da7ce3dafe5394815eedd360..19359fabc2dfd68c475b31241cd8f2b24b2b9fa0 100644 --- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp +++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp @@ -1,15 +1,17 @@ #include "Reader.h" #include <mutex> +#include <optional> #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_objects/aron_conversions.h" #include <RobotAPI/libraries/armem_objects/aron/Robot.aron.generated.h> -#include <optional> -#include <ArmarXCore/core/PackagePath.h> +#include "RobotAPI/libraries/armem_objects/articulated_object_conversions.h" namespace fs = ::std::filesystem; @@ -113,24 +115,6 @@ namespace armarx::armem::articulated_object return getRobotState(qResult.memory); } - std::optional<RobotState> convertRobotState(const armem::wm::EntityInstance& instance) - { - arondto::RobotState aronRobotState; - try - { - aronRobotState.fromAron(instance.data()); - } - catch (...) - { - ARMARX_WARNING << "Conversion failed!"; - return std::nullopt; - } - - RobotState robotState; - fromAron(aronRobotState, robotState); - - return robotState; - } std::optional<RobotState> Reader::getRobotState(const armarx::armem::wm::Memory& memory) const { @@ -161,30 +145,6 @@ namespace armarx::armem::articulated_object return convertRobotState(instance); } - std::optional<RobotDescription> convertRobotDescription(const armem::wm::EntityInstance& instance) - { - arondto::RobotDescription aronRobotDescription; - try - { - aronRobotDescription.fromAron(instance.data()); - } - catch (...) - { - ARMARX_WARNING << "Conversion failed!"; - return std::nullopt; - } - - - RobotDescription robotDescription - { - .name = "", - .xml = ::armarx::PackagePath("", fs::path("")) // initialize empty, no default c'tor - }; - - fromAron(aronRobotDescription, robotDescription); - - return robotDescription; - } std::optional<RobotDescription> Reader::getRobotDescription(const armarx::armem::wm::Memory& memory) const @@ -216,6 +176,4 @@ namespace armarx::armem::articulated_object return convertRobotDescription(instance); } - - } // namespace armarx::armem::articulated_object \ No newline at end of file diff --git a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h index c81775c85945249ce762443038fe5a6cf292257e..cd047cf6cc81dca29061f679537d787935ebfa75 100644 --- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h +++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h @@ -1,3 +1,24 @@ +/* + * 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> 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 74ec9a1de548eba30b470271080c0721eb43fb7d..9e9b2075846219ca9390f56f3474c839d169dc52 100644 --- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.h +++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.h @@ -1,3 +1,24 @@ +/* + * 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> diff --git a/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2babe5079ff5a0e00d07317d163c089644db77b --- /dev/null +++ b/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.cpp @@ -0,0 +1,127 @@ +#include "Segment.h" + +#include <sstream> + +#include <ArmarXCore/core/time/TimeUtil.h> +#include "ArmarXCore/core/logging/Logging.h" + +#include "RobotAPI/libraries/aron/common/aron_conversions.h" + +#include <RobotAPI/libraries/armem/core/aron_conversions.h> +#include <RobotAPI/libraries/armem/core/workingmemory/Visitor.h> +#include "RobotAPI/libraries/armem/core/MemoryID.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> +#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h> + +#include <RobotAPI/libraries/armem_objects/aron/Robot.aron.generated.h> +#include <RobotAPI/libraries/armem_objects/aron_conversions.h> +#include "RobotAPI/libraries/armem_objects/articulated_object_conversions.h" + + +namespace armarx::armem::server::obj::articulated_object_class +{ + + Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter, std::mutex& memoryMutex) : + iceMemory(memoryToIceAdapter), + memoryMutex(memoryMutex) + { + Logging::setTag("ArticulatedObjectInstanceSegment"); + } + + Segment::~Segment() = default; + + void Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix) + { + defs->optional(p.coreClassSegmentName, prefix + "CoreSegmentName", "Name of the object instance core segment."); + defs->optional(p.maxHistorySize, prefix + "MaxHistorySize", "Maximal size of object poses history (-1 for infinite)."); + } + + void Segment::init() + { + ARMARX_CHECK_NOT_NULL(iceMemory.workingMemory); + + coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreClassSegmentName, arondto::Robot::toInitialAronType()); + coreSegment->setMaxHistorySize(p.maxHistorySize); + } + + void Segment::connect(viz::Client arviz) + { + // this->visu = std::make_unique<Visu>(arviz, *this); + } + + + std::unordered_map<armem::MemoryID, ::armarx::armem::articulated_object::ArticulatedObjectDescription> Segment::getKnownObjectClasses() const + { + std::unordered_map<armem::MemoryID, ::armarx::armem::articulated_object::ArticulatedObjectDescription> objects; + + for (const auto& [_, provSeg] : iceMemory.workingMemory->getCoreSegment(p.coreClassSegmentName)) + { + for (const auto& [name, entity] : provSeg.entities()) + { + const auto& entityInstance = entity.getLatestSnapshot().getInstance(0); + const auto description = articulated_object::convertRobotDescription(entityInstance); + + if (not description) + { + ARMARX_WARNING << "Could not convert entity instance to 'RobotDescription'"; + continue; + } + + ARMARX_INFO << "Key is " << armem::MemoryID(entity.id()); + + objects.emplace(armem::MemoryID(entity.id()), *description); + } + } + + ARMARX_IMPORTANT << "Number of known articulated object classes: " << objects.size(); + + return objects; + } + + + + // void Segment::RemoteGui::setup(const Segment& data) + // { + // using namespace armarx::RemoteGui::Client; + + // maxHistorySize.setValue(std::max(1, int(data.p.maxHistorySize))); + // maxHistorySize.setRange(1, 1e6); + // infiniteHistory.setValue(data.p.maxHistorySize == -1); + // discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached); + + // GridLayout grid; + // int row = 0; + // grid.add(Label("Max History Size"), {row, 0}).add(maxHistorySize, {row, 1}); + // row++; + // grid.add(Label("Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1}); + // row++; + // grid.add(Label("Discard Snapshots while Attached"), {row, 0}).add(discardSnapshotsWhileAttached, {row, 1}); + // row++; + + // group.setLabel("Data"); + // group.addChild(grid); + // } + + // void Segment::RemoteGui::update(Segment& data) + // { + // if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged() + // || discardSnapshotsWhileAttached.hasValueChanged()) + // { + // std::scoped_lock lock(data.memoryMutex); + + // if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged()) + // { + // data.p.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue(); + // if (data.coreSegment) + // { + // data.coreSegment->setMaxHistorySize(long(data.p.maxHistorySize)); + // } + // } + + // data.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue(); + // } + // } + +} // namespace armarx::armem::server::obj::articulated_object_class diff --git a/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.h b/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.h new file mode 100644 index 0000000000000000000000000000000000000000..3c17b51f3ac00db12123e3bd0b0dcb61e77c11a7 --- /dev/null +++ b/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.h @@ -0,0 +1,105 @@ +/* + * 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 <string> +#include <optional> +#include <mutex> +#include <unordered_map> + +#include <ArmarXCore/core/logging/Logging.h> +#include "ArmarXCore/core/application/properties/PropertyDefinitionContainer.h" + +// #include "ArmarXGui/libraries/RemoteGui/Client/Widgets.h" + +#include "RobotAPI/components/ArViz/Client/Client.h" + +#include "RobotAPI/libraries/armem/core/MemoryID.h" +#include "RobotAPI/libraries/armem_objects/types.h" + +namespace armarx::armem +{ + namespace server + { + class MemoryToIceAdapter; + } + + namespace wm + { + class CoreSegment; + } +} // namespace armarx::armem + + +namespace armarx::armem::server::obj::articulated_object_class +{ + class Visu; + + class Segment : public armarx::Logging + { + public: + Segment(server::MemoryToIceAdapter& iceMemory, + std::mutex& memoryMutex); + + virtual ~Segment(); + + void connect(viz::Client arviz); + + void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = ""); + + void init(); + + std::unordered_map<armem::MemoryID, ::armarx::armem::articulated_object::ArticulatedObjectDescription> getKnownObjectClasses() const; + + + private: + + server::MemoryToIceAdapter& iceMemory; + wm::CoreSegment* coreSegment = nullptr; + std::mutex& memoryMutex; + + struct Properties + { + std::string coreClassSegmentName = "ArticulatedObjectClass"; + int64_t maxHistorySize = -1; + }; + Properties p; + + // std::unique_ptr<Visu> visu; + + public: + + // struct RemoteGui + // { + // armarx::RemoteGui::Client::GroupBox group; + + // armarx::RemoteGui::Client::IntSpinBox maxHistorySize; + // armarx::RemoteGui::Client::CheckBox infiniteHistory; + // armarx::RemoteGui::Client::CheckBox discardSnapshotsWhileAttached; + + // void setup(const Segment& data); + // void update(Segment& data); + // }; + + }; + +} // namespace armarx::armem::server::obj::articulated_object_class diff --git a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.cpp index 67623c29d02f519f812a5f9ebc65e08a6a955562..b542e7a544e45b50cf148a3318c52c9a9ba91ba7 100644 --- a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.cpp +++ b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.cpp @@ -1,449 +1,182 @@ #include "Segment.h" -#include <RobotAPI/libraries/armem_objects/aron_conversions.h> +#include <sstream> + +#include <SimoxUtility/algorithm/get_map_keys_values.h> + +#include <ArmarXCore/core/time/TimeUtil.h> +#include <ArmarXCore/core/exceptions/local/ExpressionException.h> + +#include <RobotAPI/libraries/core/remoterobot/RemoteRobot.h> + +#include <RobotAPI/libraries/aron/common/aron_conversions.h> #include <RobotAPI/libraries/armem/core/aron_conversions.h> -#include <RobotAPI/libraries/armem/core/workingmemory/Visitor.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> +#include <RobotAPI/libraries/armem/aron/MemoryID.aron.generated.h> -#include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h> -#include <RobotAPI/libraries/ArmarXObjects/aron_conversions.h> -#include <RobotAPI/libraries/ArmarXObjects/ice_conversions.h> -#include <RobotAPI/libraries/aron/common/aron/Robot.aron.generated.h> - -#include <RobotAPI/libraries/core/FramedPose.h> -#include <RobotAPI/libraries/core/remoterobot/RemoteRobot.h> - -#include <ArmarXCore/core/time/TimeUtil.h> +#include <RobotAPI/libraries/armem_objects/aron/Robot.aron.generated.h> +#include <RobotAPI/libraries/armem_objects/aron/RobotDescription.aron.generated.h> +#include <RobotAPI/libraries/armem_objects/aron_conversions.h> +#include <RobotAPI/libraries/armem_objects/articulated_object_conversions.h> +#include <RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.h> -#include <sstream> +#include "Visu.h" -#include "RobotAPI/libraries/aron/common/aron_conversions.h" +namespace simox::alg +{ + /// Get the keys of `map` in a vector. + template <class K, class V, template<class...> class MapT = std::unordered_map, class...Ts> + std::vector<K> get_keys2(const MapT<K, V, Ts...>& map) + { + std::vector<K> keys; + if constexpr(std::is_same_v<std::unordered_map<K, V, Ts...>, MapT<K, V, Ts...>>) + { + keys.reserve(map.size()); + } + for (const auto& [k, v] : map) + { + keys.emplace_back(k); + } + return keys; + } +} -namespace armarx::armem::server::obj::articulated_object +namespace armarx::armem::server::obj::articulated_object_instance { Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter, std::mutex& memoryMutex) : iceMemory(memoryToIceAdapter), memoryMutex(memoryMutex) { - Logging::setTag("InstanceSegment"); - - // oobbCache.setFetchFn([this](const ObjectID & id) -> std::optional<simox::OrientedBoxf> - // { - // // Try to get OOBB from repository. - // if (std::optional<ObjectInfo> objectInfo = objectFinder.findObject(id)) - // { - // try - // { - // return objectInfo->loadOOBB(); - // } - // catch (const std::ios_base::failure& e) - // { - // // Give up - no OOBB information. - // ARMARX_WARNING << "Could not get OOBB of object " << id << ".\n- " << e.what(); - // return std::nullopt; - // } - // } - // else - // { - // return std::nullopt; - // } - // }); - - // classNameToDatasetCache.setFetchFn([this](const std::string & className) - // { - // std::optional<ObjectInfo> objectInfo = objectFinder.findObject(className); - // return objectInfo ? objectInfo->dataset() : ""; - // }); + Logging::setTag("ArticulatedObjectInstanceSegment"); } - void Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix) + Segment::~Segment() = default; + + void Segment::defineProperties(armarx::PropertyDefinitionsPtr& defs, const std::string& prefix) { - defs->optional(p.coreSegmentName, prefix + "CoreSegmentName", "Name of the object instance core segment."); + defs->optional(p.coreInstanceSegmentName, prefix + "CoreSegmentName", "Name of the object instance core segment."); defs->optional(p.maxHistorySize, prefix + "MaxHistorySize", "Maximal size of object poses history (-1 for infinite)."); - defs->optional(p.discardSnapshotsWhileAttached, prefix + "DiscardSnapshotsWhileAttached", - "If true, no new snapshots are stored while an object is attached to a robot node.\n" - "If false, new snapshots are stored, but the attachment is kept in the new snapshots."); - - // decay.defineProperties(defs, prefix + "decay."); } void Segment::init() { ARMARX_CHECK_NOT_NULL(iceMemory.workingMemory); - coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreSegmentName, arondto::ObjectInstance::toInitialAronType()); + coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreInstanceSegmentName, arondto::Robot::toInitialAronType()); coreSegment->setMaxHistorySize(p.maxHistorySize); - } + } - Segment::CommitStats Segment::commitArticulatedObjects( - const std::string& providerName, - const ::armarx::articulated_object::data::ArticulatedObjects& objects) + void Segment::connect(viz::Client arviz) { - Segment::CommitStats stats; - - ::armarx::articulated_object::ArticulatedObjects boObjects; - fromIce(objects, boObjects); - - commitArticulatedObjects(providerName, boObjects); + this->visu = std::make_unique<Visu>(arviz, *this); + visu->init(); + } - return stats; + void Segment::setArticulatedObjectClassSegment(const articulated_object_class::Segment& segment) + { + classSegment = &segment; } - void Segment::commitArticulatedObjects( - const std::string& providerName, - const ::armarx::articulated_object::ArticulatedObjects& objects) + ::armarx::armem::articulated_object::ArticulatedObjects Segment::getArticulatedObjects() const { - ARMARX_CHECK_NOT_NULL(coreSegment); + ARMARX_CHECK_NOT_NULL(classSegment); + const auto knownObjectClasses = classSegment->getKnownObjectClasses(); - // Update memory. - const MemoryID providerSegmentID = coreSegment->id().withProviderSegmentName(providerName); - if (!coreSegment->hasProviderSegment(providerSegmentID.providerSegmentName)) + const auto resolveDescriptionLink = [&](auto & articulatedObject, const auto & aronDescriptionLink) -> bool { - coreSegment->addProviderSegment(providerSegmentID.providerSegmentName); - } + armem::MemoryID descriptionLink; + fromAron(aronDescriptionLink, descriptionLink); - Commit commit; - for (const Robot &object : objects) - { - EntityUpdate &update = commit.updates.emplace_back(); - { - update.entityID = providerSegmentID.withEntityName(object.description.str()); - update.timeArrived = TimeUtil::GetTime(); - update.timeCreated = object.timestamp; - - armarx::arondto::Robot dto; - toAron(dto, object); - // Search for object class. + ARMARX_DEBUG << "Lookup key is " << descriptionLink; + const auto keys = simox::alg::get_keys(knownObjectClasses); + ARMARX_DEBUG << "Known keys " << keys; - update.instancesData.push_back(dto.toAron()); - } + const auto it = knownObjectClasses.find(descriptionLink); + if (it == knownObjectClasses.end()) + { + ARMARX_WARNING << "Unknown object class " ; //<< aronArticulatedObject.description; + return false; } - // TODO check if this should be inside loop - iceMemory.commit(commit); - } - - + articulatedObject.description = it->second; + return true; + }; - // Segment::CommitStats Segment::commitObjectPoses( - // const std::string& providerName, - // const objpose::data::ProvidedObjectPoseSeq& providedPoses, - // std::optional<armem::Time> discardUpdatesUntil) - // { - // CommitStats stats; - - // // Build new poses. - // objpose::ObjectPoseSeq newObjectPoses; - // stats.numUpdated = 0; - // for (const objpose::data::ProvidedObjectPose& provided : providedPoses) - // { - // const IceUtil::Time timestamp = IceUtil::Time::microSeconds(provided.timestampMicroSeconds); - - // // Check whether we have an old snapshot for this object. - // std::optional<objpose::ObjectPose> previousPose; - // const armem::wm::Entity* entity = findObjectEntity(armarx::fromIce(provided.objectID), providerName); - // if (entity) - // { - // const arondto::ObjectInstance data = getLatestInstanceData(*entity); - - // previousPose = objpose::ObjectPose(); - // fromAron(data, *previousPose); - // } - - // bool discard = false; - // if (discardUpdatesUntil && timestamp < discardUpdatesUntil.value()) - // { - // // Dicard updates temporarily (e.g. due to head movement). - // discard = true; - // } - // else if (previousPose) - // { - // if (p.discardSnapshotsWhileAttached && previousPose->attachment) - // { - // // Discard update due to active attachemnt. - // discard = true; - // } - // else if (timestamp == previousPose->timestamp) - // { - // // Discard update as it is not new. - // discard = true; - // } - // } - - // if (!discard) - // { - // // Update the entity. - // stats.numUpdated++; - - // objpose::ObjectPose& newPose = newObjectPoses.emplace_back(); - // newPose.fromProvidedPose(provided, robot); - - // if (previousPose && previousPose->attachment) - // { - // // Keep current attachment. - // ARMARX_CHECK(!p.discardSnapshotsWhileAttached); - // newPose.attachment = previousPose->attachment; - // } - - // if (newPose.objectID.dataset().empty()) - // { - // // Try to find the data set. - // const std::string dataset = classNameToDatasetCache.get(newPose.objectID.className()); - // if (!dataset.empty()) - // { - // newPose.objectID = { dataset, newPose.objectID.className(), newPose.objectID.instanceName() }; - // } - // } - // if (!provided.localOOBB) - // { - // // Try to load oobb from disk. - // newPose.localOOBB = getObjectOOBB(newPose.objectID); - // } - // } - // } - - // commitObjectPoses(providerName, newObjectPoses); - - // return stats; - // } - - // void Segment::commitObjectPoses(const std::string& providerName, const ObjectPoseSeq& objectPoses) - // { - // ARMARX_CHECK_NOT_NULL(coreSegment); - - // // Update memory. - // const MemoryID providerSegmentID = coreSegment->id().withProviderSegmentName(providerName); - // if (!coreSegment->hasProviderSegment(providerSegmentID.providerSegmentName)) - // { - // coreSegment->addProviderSegment(providerSegmentID.providerSegmentName); - // } + ::armarx::armem::articulated_object::ArticulatedObjects objects; + for (const auto& [_, provSeg] : iceMemory.workingMemory->getCoreSegment(p.coreInstanceSegmentName)) + { + for (const auto& [_, entity] : provSeg.entities()) + { + const auto& entityInstance = entity.getLatestSnapshot().getInstance(0); - // Commit commit; - // for (const objpose::ObjectPose& pose : objectPoses) - // { - // EntityUpdate& update = commit.updates.emplace_back(); - // { - // update.entityID = providerSegmentID.withEntityName(pose.objectID.str()); - // update.timeArrived = TimeUtil::GetTime(); - // update.timeCreated = pose.timestamp; - // update.confidence = pose.confidence; - - // arondto::ObjectInstance dto; - // toAron(dto, pose); - // // Search for object class. - // if (auto instance = findClassInstance(pose.objectID)) - // { - // toAron(dto.classID, instance->id()); - // } - // update.instancesData.push_back(dto.toAron()); - // } + arondto::Robot aronArticulatedObject; + aronArticulatedObject.fromAron(entityInstance.data()); - // iceMemory.commit(commit); - // } - // } + armem::articulated_object::ArticulatedObject articulatedObject; + fromAron(aronArticulatedObject, articulatedObject); + // resolve memory link for description + const arondto::MemoryID& aronDescriptionLink = aronArticulatedObject.description; + if (not resolveDescriptionLink(articulatedObject, aronDescriptionLink)) + { + continue; + } - wm::CoreSegment& Segment::getCoreSegment() - { - ARMARX_CHECK_NOT_NULL(coreSegment); - return *coreSegment; - } + objects.push_back(articulatedObject); + } + } - const wm::CoreSegment& Segment::getCoreSegment() const - { - ARMARX_CHECK_NOT_NULL(coreSegment); - return *coreSegment; + return objects; } - // objpose::ObjectPoseSeq Segment::getObjectPoses(IceUtil::Time now) - // { - // ObjectPoseSeq objectPoses = getLatestObjectPoses(); - // updateObjectPoses(objectPoses, now); - // return filterObjectPoses(objectPoses); - // } - // objpose::ObjectPoseSeq Segment::getObjectPosesByProvider( - // const std::string& providerName, - // IceUtil::Time now) + // void Segment::RemoteGui::setup(const Segment& data) // { - // ARMARX_CHECK_NOT_NULL(coreSegment); - // ObjectPoseSeq objectPoses = getLatestObjectPoses(coreSegment->getProviderSegment(providerName)); - // updateObjectPoses(objectPoses, now); - // return filterObjectPoses(objectPoses); + // using namespace armarx::RemoteGui::Client; + + // maxHistorySize.setValue(std::max(1, int(data.p.maxHistorySize))); + // maxHistorySize.setRange(1, 1e6); + // infiniteHistory.setValue(data.p.maxHistorySize == -1); + // discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached); + + // GridLayout grid; + // int row = 0; + // grid.add(Label("Max History Size"), {row, 0}).add(maxHistorySize, {row, 1}); + // row++; + // grid.add(Label("Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1}); + // row++; + // grid.add(Label("Discard Snapshots while Attached"), {row, 0}).add(discardSnapshotsWhileAttached, {row, 1}); + // row++; + + // group.setLabel("Data"); + // group.addChild(grid); // } - // armem::wm::Entity* Segment::findObjectEntity(const ObjectID& objectID, const std::string& providerName) + // void Segment::RemoteGui::update(Segment& data) // { - // ARMARX_CHECK_NOT_NULL(coreSegment); - // armem::MemoryID entityID = armem::MemoryID().withEntityName(objectID.str()); - // if (providerName.empty()) + // if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged() + // || discardSnapshotsWhileAttached.hasValueChanged()) // { - // for (auto& [_, prov] : *coreSegment) + // std::scoped_lock lock(data.memoryMutex); + + // if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged()) // { - // if (prov.hasEntity(entityID.entityName)) + // data.p.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue(); + // if (data.coreSegment) // { - // return &prov.getEntity(entityID); + // data.coreSegment->setMaxHistorySize(long(data.p.maxHistorySize)); // } // } - // return nullptr; - // } - // else - // { - // entityID.providerSegmentName = providerName; - // if (coreSegment->hasProviderSegment(providerName)) - // { - // armem::wm::ProviderSegment& prov = coreSegment->getProviderSegment(providerName); - // return prov.hasEntity(entityID.entityName) ? &prov.getEntity(entityID) : nullptr; - // } - // else - // { - // return nullptr; - // } - // } - // } - - // void Segment::updateObjectPoses(ObjectPoseSeq& objectPoses, IceUtil::Time now) - // { - // bool agentSynchronized = false; - - // for (ObjectPose& objectPose : objectPoses) - // { - // updateObjectPose(objectPose, now, robot, agentSynchronized); + // data.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue(); // } // } - - // void Segment::updateObjectPoses( - // ObjectPoseSeq& objectPoses, - // IceUtil::Time now, - // VirtualRobot::RobotPtr agent, - // bool& agentSynchronized) const - // { - // for (ObjectPose& pose : objectPoses) - // { - // updateObjectPose(pose, now, agent, agentSynchronized); - // } - // } - - - // void Segment::updateObjectPose( - // ObjectPose& objectPose, - // IceUtil::Time now, - // VirtualRobot::RobotPtr agent, - // bool& agentSynchronized) const - // { - // updateAttachement(objectPose, agent, agentSynchronized); - - // if (decay.enabled) - // { - // decay.updateConfidence(objectPose, now); - // } - // } - - - // objpose::ObjectPoseSeq Segment::filterObjectPoses(const ObjectPoseSeq& objectPoses) const - // { - // ObjectPoseSeq result; - // for (const ObjectPose& objectPose : objectPoses) - // { - // if (!(decay.enabled && objectPose.confidence < decay.removeObjectsBelowConfidence)) - // { - // result.push_back(objectPose); - // } - // } - // return result; - // } - - - - ::armarx::articulated_object::provider::ProviderInfo Segment::getProviderInfo(const std::string& providerName) - { - try - { - return providers.at(providerName); - } - catch (const std::out_of_range&) - { - std::stringstream ss; - ss << "No provider with name '" << providerName << "' available.\n"; - ss << "Available are:\n"; - for (const auto& [name, _] : providers) - { - ss << "- '" << name << "'\n"; - } - throw std::out_of_range(ss.str()); - } - } - - - std::optional<wm::EntityInstance> Segment::findClassInstance(const ObjectID& objectID) - { - const ObjectID classID = { objectID.dataset(), objectID.className() }; - try - { - for (const auto& [_, provSeg] : iceMemory.workingMemory->getCoreSegment("Class")) - { - return provSeg.getEntity(classID.str()).getLatestSnapshot().getInstance(0); - } - return std::nullopt; - } - catch (const armem::error::ArMemError&) - { - // Some segment or entity did not exist. - return std::nullopt; - } - } - - - - void Segment::RemoteGui::setup(const Segment& data) - { - using namespace armarx::RemoteGui::Client; - - maxHistorySize.setValue(std::max(1, int(data.p.maxHistorySize))); - maxHistorySize.setRange(1, 1e6); - infiniteHistory.setValue(data.p.maxHistorySize == -1); - discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached); - - GridLayout grid; - int row = 0; - grid.add(Label("Max History Size"), {row, 0}).add(maxHistorySize, {row, 1}); - row++; - grid.add(Label("Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1}); - row++; - grid.add(Label("Discard Snapshots while Attached"), {row, 0}).add(discardSnapshotsWhileAttached, {row, 1}); - row++; - - group.setLabel("Data"); - group.addChild(grid); - } - - void Segment::RemoteGui::update(Segment& data) - { - if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged() - || discardSnapshotsWhileAttached.hasValueChanged()) - { - std::scoped_lock lock(data.memoryMutex); - - if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged()) - { - data.p.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue(); - if (data.coreSegment) - { - data.coreSegment->setMaxHistorySize(long(data.p.maxHistorySize)); - } - } - - data.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue(); - } - } - -} +} // namespace armarx::armem::server::obj::articulated_object_instance diff --git a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.h b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.h index caa3c3ff2d3009fda7343b051c8536f22cea1e49..2d50be817effddb795e8cd6adf1bda992d177e87 100644 --- a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.h +++ b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.h @@ -1,33 +1,54 @@ +/* + * 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 "ArmarXCore/core/application/properties/PropertyDefinitionContainer.h" -#include "ArmarXGui/libraries/RemoteGui/Client/Widgets.h" -#include <RobotAPI/interface/core/articulated_object/provider.h> +#include <cstdint> #include <map> #include <string> #include <optional> #include <mutex> -#include <SimoxUtility/caching/CacheMap.h> -#include <SimoxUtility/shapes/OrientedBox.h> +#include "ArmarXCore/core/application/properties/PropertyDefinitionContainer.h" -#include <ArmarXCore/core/logging/Logging.h> +#include "ArmarXGui/libraries/RemoteGui/Client/Widgets.h" #include <RobotAPI/interface/core/RobotState.h> -#include <RobotAPI/libraries/ArmarXObjects/ObjectID.h> -#include <RobotAPI/libraries/ArmarXObjects/ObjectPose.h> -#include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h> - #include <RobotAPI/libraries/armem/core/workingmemory/Memory.h> #include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h> -#include <RobotAPI/libraries/armem_objects/aron/ObjectInstance.aron.generated.h> -#include <RobotAPI/libraries/aron/common/aron/new_types.h> -#include <RobotAPI/interface/core/articulated_object/types.h> +#include "RobotAPI/components/ArViz/Client/Client.h" + +#include "RobotAPI/libraries/armem_objects/types.h" -namespace armarx::armem::server::obj::articulated_object + +namespace armarx::armem::server::obj::articulated_object_class +{ + class Segment; +} + +namespace armarx::armem::server::obj::articulated_object_instance { + class Visu; class Segment : public armarx::Logging { @@ -37,106 +58,22 @@ namespace armarx::armem::server::obj::articulated_object { int numUpdated = 0; }; - using ObjectPose = objpose::ObjectPose; - using ObjectPoseSeq = objpose::ObjectPoseSeq; - public: - Segment(server::MemoryToIceAdapter& iceMemory, std::mutex& memoryMutex); + virtual ~Segment(); - void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = ""); - - void init(); - - - CommitStats commitArticulatedObjects( - const std::string& providerName, - const ::armarx::articulated_object::data::ArticulatedObjects& objects); - - void commitArticulatedObjects( - const std::string& providerName, - const ::armarx::articulated_object::ArticulatedObjects& objects - ); - - wm::CoreSegment& getCoreSegment(); - const wm::CoreSegment& getCoreSegment() const; - - - // objpose::ObjectPoseSeq getObjectPoses(IceUtil::Time now); - // objpose::ObjectPoseSeq getObjectPosesByProvider(const std::string& providerName, IceUtil::Time now); + void connect(viz::Client arviz); - // wm::Entity* findObjectEntity(const ObjectID& objectID, const std::string& providerName = ""); - // std::optional<simox::OrientedBoxf> getObjectOOBB(const ObjectID& id); + void defineProperties(armarx::PropertyDefinitionsPtr& defs, const std::string& prefix = ""); - ::armarx::articulated_object::provider::ProviderInfo getProviderInfo(const std::string& providerName); - - - // static ObjectPoseSeq getLatestObjectPoses(const wm::CoreSegment& coreSeg); - // static ObjectPoseSeq getLatestObjectPoses(const wm::ProviderSegment& provSeg); - // static ObjectPose getLatestObjectPose(const wm::Entity& entity); - - // static void getLatestObjectPoses(const wm::CoreSegment& coreSeg, ObjectPoseSeq& out); - // static void getLatestObjectPoses(const wm::ProviderSegment& provSeg, ObjectPoseSeq& out); - // static void getLatestObjectPose(const wm::Entity& entity, ObjectPose& out); - - // static arondto::ObjectInstance getLatestInstanceData(const wm::Entity& entity); - - - private: - - ObjectPoseSeq getLatestObjectPoses() const; - - void updateObjectPoses( - ObjectPoseSeq& objectPoses, - IceUtil::Time now); - void updateObjectPoses( - ObjectPoseSeq& objectPoses, - IceUtil::Time now, - VirtualRobot::RobotPtr agent, - bool& agentSynchronized - ) const; - void updateObjectPose( - ObjectPose& objectPose, - IceUtil::Time now, - VirtualRobot::RobotPtr agent, - bool& agentSynchronized - ) const; - - - ObjectPoseSeq filterObjectPoses(const ObjectPoseSeq& objectPoses) const; - - - void storeDetachedSnapshot( - wm::Entity& entity, - const arondto::ObjectInstance& data, - Time now, - bool commitAttachedPose); - - - std::optional<wm::EntityInstance> findClassInstance(const ObjectID& objectID); - - - friend struct DetachVisitor; - - - public: - - RobotStateComponentInterfacePrx robotStateComponent; - VirtualRobot::RobotPtr robot; - - using ProviderMap = std::map<std::string, ::armarx::articulated_object::provider::ProviderInfo>; - - ProviderMap providers; - - - // ObjectFinder objectFinder; + void init(); - /// Decay model. - // Decay decay; + void setArticulatedObjectClassSegment(const articulated_object_class::Segment& segment); + ::armarx::armem::articulated_object::ArticulatedObjects getArticulatedObjects() const; private: @@ -144,37 +81,32 @@ namespace armarx::armem::server::obj::articulated_object wm::CoreSegment* coreSegment = nullptr; std::mutex& memoryMutex; + articulated_object_class::Segment const* classSegment; + struct Properties { - std::string coreSegmentName = "ArticulatedObjectInstance"; - long maxHistorySize = -1; - bool discardSnapshotsWhileAttached = true; + std::string coreInstanceSegmentName = "ArticulatedObjectInstance"; + int64_t maxHistorySize = -1; }; Properties p; - - /// Caches results of attempts to retrieve the OOBB from ArmarXObjects. - simox::caching::CacheMap<ObjectID, std::optional<simox::OrientedBoxf>> oobbCache; - - /// Class name -> dataset name. - simox::caching::CacheMap<std::string, std::string> classNameToDatasetCache; - + std::unique_ptr<Visu> visu; public: - struct RemoteGui - { - armarx::RemoteGui::Client::GroupBox group; + // struct RemoteGui + // { + // armarx::RemoteGui::Client::GroupBox group; - armarx::RemoteGui::Client::IntSpinBox maxHistorySize; - armarx::RemoteGui::Client::CheckBox infiniteHistory; - armarx::RemoteGui::Client::CheckBox discardSnapshotsWhileAttached; + // armarx::RemoteGui::Client::IntSpinBox maxHistorySize; + // armarx::RemoteGui::Client::CheckBox infiniteHistory; + // armarx::RemoteGui::Client::CheckBox discardSnapshotsWhileAttached; - void setup(const Segment& data); - void update(Segment& data); - }; + // void setup(const Segment& data); + // void update(Segment& data); + // }; }; -} // namespace armarx::armem::server::obj::articulated_object +} // namespace armarx::armem::server::obj::articulated_object_instance diff --git a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/SegmentAdapter.cpp b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/SegmentAdapter.cpp deleted file mode 100644 index 622b358cbffcd51b752185ab81654ade9725de93..0000000000000000000000000000000000000000 --- a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/SegmentAdapter.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * 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/>. - * - * @package RobotAPI::armem_objects::SegmentAdapter - * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu ) - * @date 2021 - * @copyright http://www.gnu.org/licenses/gpl-2.0.txt - * GNU General Public License - */ - -#include "SegmentAdapter.h" - -#include <RobotAPI/libraries/core/remoterobot/RemoteRobot.h> -#include <RobotAPI/libraries/ArmarXObjects/aron_conversions.h> -#include <RobotAPI/libraries/ArmarXObjects/ice_conversions.h> - -#include <ArmarXCore/core/time/CycleUtil.h> -#include <ArmarXCore/observers/variant/Variant.h> - -#include <VirtualRobot/Robot.h> - -#include <SimoxUtility/algorithm/get_map_keys_values.h> - - -namespace armarx::armem::server::obj::instance -{ - - SegmentAdapter::SegmentAdapter(MemoryToIceAdapter& iceMemory, std::mutex& memoryMutex) : - segment(iceMemory, memoryMutex), - memoryMutex(memoryMutex) - { - } - - std::string SegmentAdapter::getName() const - { - return Logging::tag.tagName; - } - - void SegmentAdapter::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix) - { - calibration.defineProperties(defs, prefix + "calibration."); - segment.defineProperties(defs, prefix); - robotHead.defineProperties(defs, prefix + "head."); - visu.defineProperties(defs, prefix + "visu."); - } - - void SegmentAdapter::init() - { - segment.setTag(getName()); - segment.decay.setTag(getName()); - robotHead.setTag(getName()); - visu.setTag(getName()); - - segment.init(); - } - - void SegmentAdapter::connect( - RobotStateComponentInterfacePrx robotStateComponent, - VirtualRobot::RobotPtr robot, - KinematicUnitObserverInterfacePrx kinematicUnitObserver, - viz::Client arviz, - DebugObserverInterfacePrx debugObserver - ) - { - this->debugObserver = debugObserver; - this->arviz = arviz; - - segment.robot = robot; - segment.robotStateComponent = robotStateComponent; - - robotHead.kinematicUnitObserver = kinematicUnitObserver; - robotHead.debugObserver = debugObserver; - robotHead.fetchDatafields(); - - visu.arviz = arviz; - if (!visu.updateTask) - { - visu.updateTask = new SimpleRunningTask<>([this]() - { - this->visualizeRun(); - }); - visu.updateTask->start(); - } - } - - void SegmentAdapter::reportProviderAvailable(const std::string& providerName, const objpose::ProviderInfo& info, const Ice::Current&) - { - updateProviderInfo(providerName, info); - } - - - void SegmentAdapter::reportObjectPoses( - const std::string& providerName, const objpose::data::ProvidedObjectPoseSeq& providedPoses, const Ice::Current&) - { - ARMARX_VERBOSE << "Received object " << providedPoses.size() << " poses from provider '" << providerName << "'."; - updateObjectPoses(providerName, providedPoses); - } - - - - void SegmentAdapter::reportArticulatedObjects( - const std::string& providerName, const articulated_object::data::ArticulatedObjects& objects, const Ice::Current&) - { - ARMARX_INFO << "Received articulated objects " << objects.size() << " poses from provider '" << providerName << "'."; - updateArticulatedObjects(providerName, objects); - } - - void SegmentAdapter::updateProviderInfo(const std::string& providerName, const objpose::ProviderInfo& info) - { - if (!info.proxy) - { - ARMARX_WARNING << "Received availability signal by provider '" << providerName << "' " - << "with invalid provider proxy.\nIgnoring provider '" << providerName << "'."; - return; - } - { - std::scoped_lock lock(memoryMutex); - std::stringstream ss; - for (const auto& id : info.supportedObjects) - { - ss << "- " << id << "\n"; - } - ARMARX_VERBOSE << "Provider '" << providerName << "' available.\n" - << "Supported objects: \n" << ss.str(); - segment.providers[providerName] = info; - } - } - - void SegmentAdapter::updateArticulatedObjects( - const std::string& providerName, const articulated_object::data::ArticulatedObjects& objects) - { - - - } - - void SegmentAdapter::updateObjectPoses( - const std::string& providerName, - const objpose::data::ProvidedObjectPoseSeq& providedPoses) - { - TIMING_START(tReportObjectPoses); - - RobotHeadMovement::Discard discard; - { - std::scoped_lock lock(robotHeadMutex); - discard = robotHead.getDiscard(); - } - if (debugObserver) - { - StringVariantBaseMap map; - map["Discarding All Updates"] = new Variant(discard.all ? 1.f : 0.f); - if (discard.all) - { - map["Proportion Updated Poses"] = new Variant(0.f); - } - debugObserver->setDebugChannel(getName(), map); - } - - if (discard.all) - { - return; - } - - { - std::scoped_lock lock(memoryMutex); - RemoteRobot::synchronizeLocalClone(segment.robot, segment.robotStateComponent); - - if (segment.robot->hasRobotNode(calibration.robotNode)) - { - VirtualRobot::RobotNodePtr robotNode = segment.robot->getRobotNode(calibration.robotNode); - float value = robotNode->getJointValue(); - robotNode->setJointValue(value + calibration.offset); - } - - TIMING_START(tCommitObjectPoses); - Segment::CommitStats stats = - segment.commitObjectPoses(providerName, providedPoses, discard.updatesUntil); - TIMING_END_STREAM(tCommitObjectPoses, ARMARX_VERBOSE); - - if (debugObserver) - { - debugObserver->setDebugChannel(getName(), - { - { "Discarding All Updates", new Variant(discard.all ? 1 : 0) }, - { "Proportion Updated Poses", new Variant(static_cast<float>(stats.numUpdated) / providedPoses.size()) } - }); - } - - handleProviderUpdate(providerName); - - TIMING_END_STREAM(tReportObjectPoses, ARMARX_VERBOSE); - if (debugObserver) - { - debugObserver->setDebugChannel(getName(), - { - { "t ReportObjectPoses [ms]", new Variant(tReportObjectPoses.toMilliSecondsDouble()) }, - { "t MemorySetObjectPoses [ms]", new Variant(tCommitObjectPoses.toMilliSecondsDouble()) }, - }); - } - } - } - - - void SegmentAdapter::handleProviderUpdate(const std::string& providerName) - { - // Initialized to 0 on first access. - if (segment.providers.count(providerName) == 0) - { - segment.providers[providerName] = objpose::ProviderInfo(); - } - } - - - objpose::data::ObjectPoseSeq SegmentAdapter::getObjectPoses(const Ice::Current&) - { - TIMING_START(tGetObjectPoses); - - TIMING_START(tGetObjectPosesLock); - std::scoped_lock lock(memoryMutex); - TIMING_END_STREAM(tGetObjectPosesLock, ARMARX_VERBOSE); - - const IceUtil::Time now = TimeUtil::GetTime(); - const objpose::data::ObjectPoseSeq result = objpose::toIce(segment.getObjectPoses(now)); - - TIMING_END_STREAM(tGetObjectPoses, ARMARX_VERBOSE); - - if (debugObserver) - { - debugObserver->setDebugChannel(getName(), - { - { "t GetObjectPoses() [ms]", new Variant(tGetObjectPoses.toMilliSecondsDouble()) }, - { "t GetObjectPoses() lock [ms]", new Variant(tGetObjectPosesLock.toMilliSecondsDouble()) } - }); - } - - return result; - } - - objpose::data::ObjectPoseSeq SegmentAdapter::getObjectPosesByProvider(const std::string& providerName, const Ice::Current&) - { - TIMING_START(GetObjectPoses); - - TIMING_START(GetObjectPosesLock); - std::scoped_lock lock(memoryMutex); - TIMING_END_STREAM(GetObjectPosesLock, ARMARX_VERBOSE); - - const IceUtil::Time now = TimeUtil::GetTime(); - const objpose::data::ObjectPoseSeq result = objpose::toIce(segment.getObjectPosesByProvider(providerName, now)); - - TIMING_END_STREAM(GetObjectPoses, ARMARX_VERBOSE); - - if (debugObserver) - { - debugObserver->setDebugChannel(getName(), - { - { "t GetObjectPosesByProvider() [ms]", new Variant(GetObjectPoses.toMilliSecondsDouble()) }, - { "t GetObjectPosesByProvider() lock [ms]", new Variant(GetObjectPosesLock.toMilliSecondsDouble()) } - }); - } - - return result; - } - - - objpose::observer::RequestObjectsOutput SegmentAdapter::requestObjects( - const objpose::observer::RequestObjectsInput& input, const Ice::Current&) - { - std::map<std::string, objpose::provider::RequestObjectsInput> providerRequests; - std::map<std::string, objpose::ObjectPoseProviderPrx> proxies; - - objpose::observer::RequestObjectsOutput output; - - auto updateProxy = [&](const std::string & providerName) - { - if (proxies.count(providerName) == 0) - { - if (auto it = segment.providers.find(providerName); it != segment.providers.end()) - { - proxies[providerName] = it->second.proxy; - } - else - { - ARMARX_ERROR << "No proxy for provider ' " << providerName << "'."; - proxies[providerName] = nullptr; - } - } - }; - - if (input.provider.size() > 0) - { - providerRequests[input.provider] = input.request; - updateProxy(input.provider); - } - else - { - std::scoped_lock lock(memoryMutex); - for (const auto& objectID : input.request.objectIDs) - { - bool found = true; - for (const auto& [providerName, info] : segment.providers) - { - // ToDo: optimize look up. - if (std::find(info.supportedObjects.begin(), info.supportedObjects.end(), objectID) != info.supportedObjects.end()) - { - providerRequests[providerName].objectIDs.push_back(objectID); - updateProxy(providerName); - break; - } - } - if (!found) - { - ARMARX_ERROR << "Did not find a provider for " << objectID << "."; - output.results[objectID].providerName = ""; - } - } - } - - for (const auto& [providerName, request] : providerRequests) - { - if (objpose::ObjectPoseProviderPrx proxy = proxies.at(providerName); proxy) - { - ARMARX_INFO << "Requesting " << request.objectIDs.size() << " objects by provider '" - << providerName << "' for " << request.relativeTimeoutMS << " ms."; - objpose::provider::RequestObjectsOutput providerOutput = proxy->requestObjects(request); - - int successful = 0; - for (const auto& [objectID, result] : providerOutput.results) - { - objpose::observer::ObjectRequestResult& res = output.results[objectID]; - res.providerName = providerName; - res.result = result; - successful += int(result.success); - } - ARMARX_INFO << successful << " of " << request.objectIDs.size() << " object requests successful."; - } - } - return output; - } - - objpose::ProviderInfoMap SegmentAdapter::getAvailableProvidersInfo(const Ice::Current&) - { - std::scoped_lock lock(memoryMutex); - return segment.providers; - } - - Ice::StringSeq SegmentAdapter::getAvailableProviderNames(const Ice::Current&) - { - std::scoped_lock lock(memoryMutex); - return simox::alg::get_keys(segment.providers); - } - - objpose::ProviderInfo SegmentAdapter::getProviderInfo(const std::string& providerName, const Ice::Current&) - { - std::scoped_lock lock(memoryMutex); - return segment.getProviderInfo(providerName); - } - - bool SegmentAdapter::hasProvider(const std::string& providerName, const Ice::Current&) - { - std::scoped_lock lock(memoryMutex); - return segment.providers.count(providerName) > 0; - } - - - objpose::AttachObjectToRobotNodeOutput SegmentAdapter::attachObjectToRobotNode( - const objpose::AttachObjectToRobotNodeInput& input, const Ice::Current&) - { - std::scoped_lock lock(memoryMutex); - return segment.attachObjectToRobotNode(input); - } - - objpose::DetachObjectFromRobotNodeOutput SegmentAdapter::detachObjectFromRobotNode( - const objpose::DetachObjectFromRobotNodeInput& input, const Ice::Current&) - { - std::scoped_lock lock(memoryMutex); - return segment.detachObjectFromRobotNode(input); - } - - objpose::DetachAllObjectsFromRobotNodesOutput SegmentAdapter::detachAllObjectsFromRobotNodes( - const objpose::DetachAllObjectsFromRobotNodesInput& input, const Ice::Current&) - { - std::scoped_lock lock(memoryMutex); - return segment.detachAllObjectsFromRobotNodes(input); - } - - - objpose::AgentFramesSeq SegmentAdapter::getAttachableFrames(const Ice::Current&) - { - std::scoped_lock lock(memoryMutex); - - objpose::AgentFramesSeq output; - std::vector<VirtualRobot::RobotPtr> agents = { segment.robot }; - for (VirtualRobot::RobotPtr agent : agents) - { - objpose::AgentFrames& frames = output.emplace_back(); - frames.agent = agent->getName(); - frames.frames = agent->getRobotNodeNames(); - } - return output; - } - - objpose::SignalHeadMovementOutput - SegmentAdapter::signalHeadMovement(const objpose::SignalHeadMovementInput& input, const Ice::Current&) - { - std::scoped_lock lock(robotHeadMutex); - return robotHead.signalHeadMovement(input); - } - - - void SegmentAdapter::visualizeRun() - { - CycleUtil cycle(static_cast<int>(1000 / visu.frequencyHz)); - while (visu.updateTask && !visu.updateTask->isStopped()) - { - { - std::scoped_lock lock(visuMutex); - - if (visu.enabled) - { - TIMING_START(Visu); - - objpose::ObjectPoseSeq objectPoses; - ObjectFinder objectFinder; - visu.minConfidence = -1; - { - std::scoped_lock lock(memoryMutex); - - const IceUtil::Time now = TimeUtil::GetTime(); - objectPoses = segment.getObjectPoses(now); - objectFinder = segment.objectFinder; - if (segment.decay.enabled) - { - visu.minConfidence = segment.decay.removeObjectsBelowConfidence; - } - } - const std::vector<viz::Layer> layers = visu.visualizeCommit(objectPoses, objectFinder); - arviz.commit(layers); - - TIMING_END_STREAM(Visu, ARMARX_VERBOSE); - - if (debugObserver) - { - debugObserver->setDebugChannel(getName(), - { - { "t Visualize [ms]", new Variant(Visu.toMilliSecondsDouble()) }, - }); - } - } - } - cycle.waitForCycleDuration(); - } - } - - - void SegmentAdapter::Calibration::defineProperties(PropertyDefinitionsPtr defs, const std::string& prefix) - { - defs->optional(robotNode, prefix + "robotNode", "Robot node which can be calibrated."); - defs->optional(offset, prefix + "offset", "Offset for the node to be calibrated."); - } - - - - void SegmentAdapter::RemoteGui::setup(const SegmentAdapter& adapter) - { - using namespace armarx::RemoteGui::Client; - - this->visu.setup(adapter.visu); - this->segment.setup(adapter.segment); - this->decay.setup(adapter.segment.decay); - this->robotHead.setup(adapter.robotHead); - - layout = VBoxLayout - { - this->visu.group, this->segment.group, this->decay.group, this->robotHead.group, - VSpacer() - }; - - group.setLabel("Instance"); - group.addChild(layout); - } - - void SegmentAdapter::RemoteGui::update(SegmentAdapter& adapter) - { - // Non-atomic variables need to be guarded by a mutex if accessed by multiple threads - { - std::scoped_lock lock(adapter.visuMutex); - this->visu.update(adapter.visu); - } - { - std::scoped_lock lock(adapter.memoryMutex); - this->segment.update(adapter.segment); - this->decay.update(adapter.segment.decay); - } - { - std::scoped_lock lock(adapter.robotHeadMutex); - this->robotHead.update(adapter.robotHead); - } - } - -} - diff --git a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/SegmentAdapter.h b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/SegmentAdapter.h deleted file mode 100644 index bf152eb74ecdd7961db56a34bfb9df1855d9e5a9..0000000000000000000000000000000000000000 --- a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/SegmentAdapter.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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/>. - * - * @package RobotAPI::armem_objects::Adapter - * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu ) - * @date 2021 - * @copyright http://www.gnu.org/licenses/gpl-2.0.txt - * GNU General Public License - */ - -#pragma once - -#include <RobotAPI/interface/core/articulated_object/types.h> -#include <mutex> - -#include <VirtualRobot/VirtualRobot.h> - -#include <ArmarXGui/libraries/RemoteGui/Client/Widgets.h> - -#include <RobotAPI/interface/armem/server/ObjectMemoryInterface.h> -#include <RobotAPI/interface/core/RobotState.h> - -#include <RobotAPI/components/ArViz/Client/Client.h> - -#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h> -#include <RobotAPI/libraries/armem_objects/server/articulated_object/Segment.h> -// #include <RobotAPI/libraries/armem_objects/server/articulated_object/Decay.h> -// #include <RobotAPI/libraries/armem_objects/server/articulated_object/Visu.h> -// #include <RobotAPI/libraries/armem_objects/server/articulated_object/RobotHeadMovement.h> - - -#define ICE_CURRENT_ARG const Ice::Current& = Ice::emptyCurrent - - -namespace armarx::armem::server::obj::articulated_object -{ - - /** - * @brief Helps implementing the `armarx::armem::server::ObjectInstanceSegmentInterface`. - */ - class SegmentAdapter : - virtual public armarx::Logging - // , virtual public armarx::armem::server::ArticulatedObjectInstanceSegment - { - public: - - SegmentAdapter(MemoryToIceAdapter& iceMemory, std::mutex& memoryMutex); - - std::string getName() const; - void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = ""); - - void init(); - void connect( - viz::Client arviz, - DebugObserverInterfacePrx debugObserver - ); - - // ARTICULATED OBJECTS - void reportArticulatedObjects(const std::string& providerName, const ::armarx::articulated_object::data::ArticulatedObjects& objects, ICE_CURRENT_ARG) override; - - private: - - void updateProviderInfo(const std::string& providerName, const objpose::ProviderInfo& info); - - void updateObjectPoses(const std::string& providerName, const objpose::data::ProvidedObjectPoseSeq& providedPoses); - void handleProviderUpdate(const std::string& providerName); - - - void updateArticulatedObjects(const std::string& providerName, const ::armarx::articulated_object::data::ArticulatedObjects& objects); - - // Visualization - - void visualizeRun(); - - - private: - - viz::Client arviz; - DebugObserverInterfacePrx debugObserver; - - articulated_object::Segment segment; - std::mutex& memoryMutex; - - // articulated_object::Visu visu; - // std::mutex visuMutex; - - public: - - struct RemoteGui - { - armarx::RemoteGui::Client::GroupBox group; - armarx::RemoteGui::Client::VBoxLayout layout; - - // articulated_object::Visu::RemoteGui visu; - articulated_object::Segment::RemoteGui segment; - - void setup(const SegmentAdapter& adapter); - void update(SegmentAdapter& adapter); - }; - - }; - -} - -#undef ICE_CURRENT_ARG diff --git a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Visu.cpp b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Visu.cpp index 40ac1f359ecbb274180de2b61265e8c442420d92..385866ce9453fd8db576da3f3b26965c7f36549a 100644 --- a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Visu.cpp +++ b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Visu.cpp @@ -1,4 +1,6 @@ #include "Visu.h" +#include "ArmarXCore/core/logging/Logging.h" +#include "ArmarXCore/core/time/CycleUtil.h" #include <algorithm> @@ -8,28 +10,17 @@ #include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h> +#include "Segment.h" namespace armarx::armem::server::obj::articulated_object_instance { void Visu::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix) { - defs->optional(enabled, prefix + "enabled", + defs->optional(p.enabled, prefix + "enabled", "Enable or disable visualization of objects."); - defs->optional(frequencyHz, prefix + "frequenzyHz", + defs->optional(p.frequencyHz, prefix + "frequenzyHz", "Frequency of visualization."); - defs->optional(inGlobalFrame, prefix + "inGlobalFrame", - "If true, show global poses. If false, show poses in robot frame."); - defs->optional(alpha, prefix + "alpha", - "Alpha of objects (1 = solid, 0 = transparent)."); - defs->optional(alphaByConfidence, prefix + "alphaByConfidence", - "If true, use the pose confidence as alpha (if < 1.0)."); - defs->optional(oobbs, prefix + "oobbs", - "Enable showing oriented bounding boxes."); - defs->optional(objectFrames, prefix + "objectFrames", - "Enable showing object frames."); - defs->optional(objectFramesScale, prefix + "objectFramesScale", - "Scaling of object frames."); } @@ -47,6 +38,7 @@ namespace armarx::armem::server::obj::articulated_object_instance void Visu::visualizeObjects(viz::Layer& layer, const armarx::armem::articulated_object::ArticulatedObjects& objects) const { + ARMARX_INFO << "Entering visualizeObjects"; const auto visualizeObject = [&](const armarx::armem::articulated_object::ArticulatedObject & obj) { @@ -54,66 +46,127 @@ namespace armarx::armem::server::obj::articulated_object_instance // clang-format off auto robot = viz::Robot(obj.description.name) - .file(xmlPath.package, xmlPath.path) + // .file(xmlPath.package, xmlPath.path) + .file("ArmarXObjects", "./data/ArmarXObjects/Environment/mobile-kitchen/dishwasher-only/dishwasher.xml") .joints(obj.config.jointMap) .pose(obj.config.globalPose); + + robot.useFullModel(); // clang-format on layer.add(robot); }; std::for_each(objects.begin(), objects.end(), visualizeObject); - } + ARMARX_INFO << "Done visualizeObjects"; + } - void Visu::RemoteGui::setup(const Visu& visu) + void Visu::init() { - using namespace armarx::RemoteGui::Client; - - enabled.setValue(visu.enabled); - inGlobalFrame.setValue(visu.inGlobalFrame); - alpha.setRange(0, 1.0); - alpha.setValue(visu.alpha); - alphaByConfidence.setValue(visu.alphaByConfidence); - oobbs.setValue(visu.oobbs); - objectFrames.setValue(visu.objectFrames); + updateTask = new SimpleRunningTask<>([this]() { - float max = 10000; - objectFramesScale.setRange(0, max); - objectFramesScale.setDecimals(2); - objectFramesScale.setSteps(int(10 * max)); - objectFramesScale.setValue(visu.objectFramesScale); - } - - GridLayout grid; - int row = 0; - grid.add(Label("Enabled"), {row, 0}).add(enabled, {row, 1}); - row++; - grid.add(Label("Global Frame"), {row, 0}).add(inGlobalFrame, {row, 1}); - row++; - grid.add(Label("Alpha"), {row, 0}).add(alpha, {row, 1}, {1, 3}); - row++; - grid.add(Label("Alpha by Confidence"), {row, 0}).add(alphaByConfidence, {row, 1}); - row++; - grid.add(Label("OOBB"), {row, 0}).add(oobbs, {row, 1}); - row++; - grid.add(Label("Object Frames"), {row, 0}).add(objectFrames, {row, 1}); - grid.add(Label("Scale:"), {row, 2}).add(objectFramesScale, {row, 3}); - row++; - - group.setLabel("Visualization"); - group.addChild(grid); + this->visualizeRun(); + }); + updateTask->start(); } - void Visu::RemoteGui::update(Visu& visu) + + // void Visu::RemoteGui::setup(const Visu& visu) + // { + // using namespace armarx::RemoteGui::Client; + + // enabled.setValue(visu.enabled); + // inGlobalFrame.setValue(visu.inGlobalFrame); + // alpha.setRange(0, 1.0); + // alpha.setValue(visu.alpha); + // alphaByConfidence.setValue(visu.alphaByConfidence); + // oobbs.setValue(visu.oobbs); + // objectFrames.setValue(visu.objectFrames); + // { + // float max = 10000; + // objectFramesScale.setRange(0, max); + // objectFramesScale.setDecimals(2); + // objectFramesScale.setSteps(int(10 * max)); + // objectFramesScale.setValue(visu.objectFramesScale); + // } + + // GridLayout grid; + // int row = 0; + // grid.add(Label("Enabled"), {row, 0}).add(enabled, {row, 1}); + // row++; + // grid.add(Label("Global Frame"), {row, 0}).add(inGlobalFrame, {row, 1}); + // row++; + // grid.add(Label("Alpha"), {row, 0}).add(alpha, {row, 1}, {1, 3}); + // row++; + // grid.add(Label("Alpha by Confidence"), {row, 0}).add(alphaByConfidence, {row, 1}); + // row++; + // grid.add(Label("OOBB"), {row, 0}).add(oobbs, {row, 1}); + // row++; + // grid.add(Label("Object Frames"), {row, 0}).add(objectFrames, {row, 1}); + // grid.add(Label("Scale:"), {row, 2}).add(objectFramesScale, {row, 3}); + // row++; + + // group.setLabel("Visualization"); + // group.addChild(grid); + // } + + // void Visu::RemoteGui::update(Visu& visu) + // { + // visu.enabled = enabled.getValue(); + // visu.inGlobalFrame = inGlobalFrame.getValue(); + // visu.alpha = alpha.getValue(); + // visu.alphaByConfidence = alphaByConfidence.getValue(); + // visu.oobbs = oobbs.getValue(); + // visu.objectFrames = objectFrames.getValue(); + // visu.objectFramesScale = objectFramesScale.getValue(); + // } + + + void Visu::visualizeRun() { - visu.enabled = enabled.getValue(); - visu.inGlobalFrame = inGlobalFrame.getValue(); - visu.alpha = alpha.getValue(); - visu.alphaByConfidence = alphaByConfidence.getValue(); - visu.oobbs = oobbs.getValue(); - visu.objectFrames = objectFrames.getValue(); - visu.objectFramesScale = objectFramesScale.getValue(); + CycleUtil cycle(static_cast<int>(1000 / p.frequencyHz)); + while (updateTask && not updateTask->isStopped()) + { + { + // std::scoped_lock lock(visuMutex); + ARMARX_IMPORTANT << "Update task"; + + if (p.enabled) + { + // TIMING_START(Visu); + + const auto articulatedObjects = segment.getArticulatedObjects(); + + ARMARX_INFO << "Found " << articulatedObjects.size() << " articulated objects"; + + viz::Layer layer = arviz.layer("ArticulatedObjectInstances"); + + ARMARX_INFO << "visualizing objects"; + visualizeObjects(layer, articulatedObjects); + + ARMARX_INFO << "Committing objects"; + + arviz.commit({layer}); + + ARMARX_INFO << "Done committing"; + + + // TIMING_END_STREAM(Visu, ARMARX_VERBOSE); + + // if (debugObserver) + // { + // debugObserver->setDebugChannel(getName(), + // { + // { "t Visualize [ms]", new Variant(Visu.toMilliSecondsDouble()) }, + // }); + // } + } + } + cycle.waitForCycleDuration(); + } } -} + + +} // namespace armarx::armem::server::obj::articulated_object_instance diff --git a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Visu.h b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Visu.h index 9ef5548a9230d999fbe70b46041c912089763786..54aea5e09f0d3000596c83d2eb8ffbafcbf8b81e 100644 --- a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Visu.h +++ b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Visu.h @@ -1,17 +1,35 @@ -#pragma once +/* + * 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 <ArmarXCore/core/logging/Logging.h> #include <ArmarXCore/core/services/tasks/TaskUtil.h> -#include <ArmarXGui/libraries/RemoteGui/Client/Widgets.h> +// #include <ArmarXGui/libraries/RemoteGui/Client/Widgets.h> #include <RobotAPI/components/ArViz/Client/Client.h> -#include <RobotAPI/libraries/ArmarXObjects/ObjectPose.h> #include <RobotAPI/libraries/armem_objects/types.h> -#include <VirtualRobot/VirtualRobot.h> namespace armarx { @@ -19,6 +37,7 @@ namespace armarx } namespace armarx::armem::server::obj::articulated_object_instance { + class Segment; /** * @brief Models decay of object localizations by decreasing the confidence @@ -28,70 +47,55 @@ namespace armarx::armem::server::obj::articulated_object_instance { public: - void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "visu."); + Visu(const viz::Client& arviz, const Segment& segment): arviz(arviz), segment(segment) {} - // std::vector<viz::Layer> visualizeCommit( - // const std::map<std::string, objpose::ObjectPoseSeq>& objectPoses, - // const ObjectFinder& objectFinder - // ) const; + void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "visu."); - // /// Visualize the given object poses, with one layer per provider. - // std::vector<viz::Layer> visualizeCommit( - // const objpose::ObjectPoseSeq& objectPoses, - // const ObjectFinder& objectFinder - // ) const; + void init(); + protected: viz::Layer visualizeProvider( const std::string& providerName, const armarx::armem::articulated_object::ArticulatedObjects& objects ) const; - void visualizeObjects(viz::Layer& layer, const armarx::armem::articulated_object::ArticulatedObjects& objects) const; - - - - // void visualizeArticulatedObjects( - // viz::Layer& layer, - // const objpose::ObjectPose& objectPose, - // const ObjectFinder& objectFinder - // ) const; - + void visualizeObjects( + viz::Layer& layer, + const armarx::armem::articulated_object::ArticulatedObjects& objects + ) const; - public: + private: viz::Client arviz; + const Segment& segment; - bool enabled = true; - float frequencyHz = 25; + struct Properties + { + bool enabled = true; + float frequencyHz = 25; + } p; - bool inGlobalFrame = true; - float minConfidence = -1; - float alpha = 1.0; - bool alphaByConfidence = false; - bool oobbs = false; - bool objectFrames = false; - float objectFramesScale = 1.0; SimpleRunningTask<>::pointer_type updateTask; + void visualizeRun(); + // struct RemoteGui + // { + // armarx::RemoteGui::Client::GroupBox group; - struct RemoteGui - { - armarx::RemoteGui::Client::GroupBox group; - - armarx::RemoteGui::Client::CheckBox enabled; + // armarx::RemoteGui::Client::CheckBox enabled; - armarx::RemoteGui::Client::CheckBox inGlobalFrame; - armarx::RemoteGui::Client::FloatSlider alpha; - armarx::RemoteGui::Client::CheckBox alphaByConfidence; - armarx::RemoteGui::Client::CheckBox oobbs; - armarx::RemoteGui::Client::CheckBox objectFrames; - armarx::RemoteGui::Client::FloatSpinBox objectFramesScale; + // armarx::RemoteGui::Client::CheckBox inGlobalFrame; + // armarx::RemoteGui::Client::FloatSlider alpha; + // armarx::RemoteGui::Client::CheckBox alphaByConfidence; + // armarx::RemoteGui::Client::CheckBox oobbs; + // armarx::RemoteGui::Client::CheckBox objectFrames; + // armarx::RemoteGui::Client::FloatSpinBox objectFramesScale; - void setup(const Visu& visu); - void update(Visu& visu); - }; + // // void setup(const Visu& visu); + // // void update(Visu& visu); + // }; }; -} +} // namespace armarx::armem::server::obj::articulated_object_instance diff --git a/source/RobotAPI/libraries/armem_objects/types.h b/source/RobotAPI/libraries/armem_objects/types.h index a127850fe89fde6a635e360aba51e4a13f7d95b7..5d2b4f76c83fa5ed3e823cc2d1528d941dcad6f5 100644 --- a/source/RobotAPI/libraries/armem_objects/types.h +++ b/source/RobotAPI/libraries/armem_objects/types.h @@ -4,6 +4,7 @@ #include <map> #include <vector> +#include <filesystem> #include <Eigen/Geometry> @@ -19,7 +20,7 @@ namespace armarx::armem // IceUtil::Time timestamp; std::string name; - PackagePath xml; + PackagePath xml{"", std::filesystem::path("")}; };