diff --git a/scenarios/ArmemGraspMemory/ArmemGraspMemory.scx b/scenarios/ArmemGraspMemory/ArmemGraspMemory.scx
new file mode 100644
index 0000000000000000000000000000000000000000..7dee5334bc635e927fe9d020c16b0363dfb53a68
--- /dev/null
+++ b/scenarios/ArmemGraspMemory/ArmemGraspMemory.scx
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scenario name="ArmemGraspMemory" creation="2021-05-07.14:40:52" globalConfigName="./config/global.cfg" package="RobotAPI" deploymentType="local" nodeName="NodeMain">
+	<application name="MemoryNameSystem" instance="" package="RobotAPI" nodeName="" enabled="true" iceAutoRestart="false"/>
+	<application name="GraspMemory" instance="" package="RobotAPI" nodeName="" enabled="true" iceAutoRestart="false"/>
+	<application name="DebugObserver" instance="" package="ArmarXCore" nodeName="" enabled="true" iceAutoRestart="false"/>
+	<application name="RemoteGuiProviderApp" instance="" package="ArmarXGui" nodeName="" enabled="true" iceAutoRestart="false"/>
+	<application name="GraspProviderExample" instance="" package="RobotAPI" nodeName="" enabled="true" iceAutoRestart="false"/>
+</scenario>
+
diff --git a/scenarios/ArmemGraspMemory/config/DebugObserver.cfg b/scenarios/ArmemGraspMemory/config/DebugObserver.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..4a0b9dac036cd4d103efd7d1b718d508f285d85a
--- /dev/null
+++ b/scenarios/ArmemGraspMemory/config/DebugObserver.cfg
@@ -0,0 +1,221 @@
+# ==================================================================
+# DebugObserver properties
+# ==================================================================
+
+# ArmarX.AdditionalPackages:  List of additional ArmarX packages which should be in the list of default packages. If you have custom packages, which should be found by the gui or other apps, specify them here. Comma separated List.
+#  Attributes:
+#  - Default:            Default value not mapped.
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.AdditionalPackages = Default value not mapped.
+
+
+# ArmarX.ApplicationName:  Application name
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.ApplicationName = ""
+
+
+# ArmarX.CachePath:  Path for cache files. If relative path AND env. variable ARMARX_USER_CONFIG_DIR is set, the cache path will be made relative to ARMARX_USER_CONFIG_DIR. Otherwise if relative it will be relative to the default ArmarX config dir (${HOME}/.armarx)
+#  Attributes:
+#  - Default:            mongo/.cache
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.CachePath = mongo/.cache
+
+
+# ArmarX.Config:  Comma-separated list of configuration files 
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.Config = ""
+
+
+# ArmarX.DataPath:  Semicolon-separated search list for data files
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DataPath = ""
+
+
+# ArmarX.DebugObserver.CreateUpdateFrequenciesChannel:  If true, an additional channel is created that shows the update frequency of every other channel in that observer.
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.DebugObserver.CreateUpdateFrequenciesChannel = false
+
+
+# ArmarX.DebugObserver.DebugObserverTopicName:  Name of the topic the DebugObserver listens on
+#  Attributes:
+#  - Default:            DebugObserver
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DebugObserver.DebugObserverTopicName = DebugObserver
+
+
+# ArmarX.DebugObserver.EnableProfiling:  enable profiler which is used for logging performance events
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.DebugObserver.EnableProfiling = false
+
+
+# ArmarX.DebugObserver.MaxHistoryRecordFrequency:  The Observer history is written with this maximum frequency. Everything faster is being skipped.
+#  Attributes:
+#  - Default:            50
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DebugObserver.MaxHistoryRecordFrequency = 50
+
+
+# ArmarX.DebugObserver.MaxHistorySize:  Maximum number of entries in the Observer history
+#  Attributes:
+#  - Default:            5000
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DebugObserver.MaxHistorySize = 5000
+
+
+# ArmarX.DebugObserver.MinimumLoggingLevel:  Local logging level only for this component
+#  Attributes:
+#  - Default:            Undefined
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning}
+# ArmarX.DebugObserver.MinimumLoggingLevel = Undefined
+
+
+# ArmarX.DebugObserver.ObjectName:  Name of IceGrid well-known object
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DebugObserver.ObjectName = ""
+
+
+# ArmarX.DefaultPackages:  List of ArmarX packages which are accessible by default. Comma separated List. If you want to add your own packages and use all default ArmarX packages, use the property 'AdditionalPackages'.
+#  Attributes:
+#  - Default:            Default value not mapped.
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DefaultPackages = Default value not mapped.
+
+
+# ArmarX.DependenciesConfig:  Path to the (usually generated) config file containing all data paths of all dependent projects. This property usually does not need to be edited.
+#  Attributes:
+#  - Default:            ./config/dependencies.cfg
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DependenciesConfig = ./config/dependencies.cfg
+
+
+# ArmarX.DisableLogging:  Turn logging off in whole application
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.DisableLogging = false
+
+
+# ArmarX.EnableProfiling:  Enable profiling of CPU load produced by this application
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.EnableProfiling = false
+
+
+# ArmarX.LoadLibraries:  Libraries to load at start up of the application. Must be enabled by the Application with enableLibLoading(). Format: PackageName:LibraryName;... or /absolute/path/to/library;...
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.LoadLibraries = ""
+
+
+# ArmarX.LoggingGroup:  The logging group is transmitted with every ArmarX log message over Ice in order to group the message in the GUI.
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.LoggingGroup = ""
+
+
+# ArmarX.RedirectStdout:  Redirect std::cout and std::cerr to ArmarXLog
+#  Attributes:
+#  - Default:            true
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.RedirectStdout = true
+
+
+# ArmarX.RemoteHandlesDeletionTimeout:  The timeout (in ms) before a remote handle deletes the managed object after the use count reached 0. This time can be used by a client to increment the count again (may be required when transmitting remote handles)
+#  Attributes:
+#  - Default:            3000
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.RemoteHandlesDeletionTimeout = 3000
+
+
+# ArmarX.SecondsStartupDelay:  The startup will be delayed by this number of seconds (useful for debugging)
+#  Attributes:
+#  - Default:            0
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.SecondsStartupDelay = 0
+
+
+# ArmarX.StartDebuggerOnCrash:  If this application crashes (segmentation fault) qtcreator will attach to this process and start the debugger.
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.StartDebuggerOnCrash = false
+
+
+# ArmarX.ThreadPoolSize:  Size of the ArmarX ThreadPool that is always running.
+#  Attributes:
+#  - Default:            1
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.ThreadPoolSize = 1
+
+
+# ArmarX.TopicSuffix:  Suffix appended to all topic names for outgoing topics. This is mainly used to direct all topics to another name for TopicReplaying purposes.
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.TopicSuffix = ""
+
+
+# ArmarX.UseTimeServer:  Enable using a global Timeserver (e.g. from ArmarXSimulator)
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.UseTimeServer = false
+
+
+# ArmarX.Verbosity:  Global logging level for whole application
+#  Attributes:
+#  - Default:            Info
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning}
+# ArmarX.Verbosity = Info
+
+
diff --git a/scenarios/ArmemGraspMemory/config/GraspMemory.cfg b/scenarios/ArmemGraspMemory/config/GraspMemory.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..7bd56e9fa827996e3c78f217b2421489af0a748d
--- /dev/null
+++ b/scenarios/ArmemGraspMemory/config/GraspMemory.cfg
@@ -0,0 +1,263 @@
+# ==================================================================
+# GraspMemory properties
+# ==================================================================
+
+# ArmarX.AdditionalPackages:  List of additional ArmarX packages which should be in the list of default packages. If you have custom packages, which should be found by the gui or other apps, specify them here. Comma separated List.
+#  Attributes:
+#  - Default:            Default value not mapped.
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.AdditionalPackages = Default value not mapped.
+
+
+# ArmarX.ApplicationName:  Application name
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.ApplicationName = ""
+
+
+# ArmarX.CachePath:  Path for cache files. If relative path AND env. variable ARMARX_USER_CONFIG_DIR is set, the cache path will be made relative to ARMARX_USER_CONFIG_DIR. Otherwise if relative it will be relative to the default ArmarX config dir (${HOME}/.armarx)
+#  Attributes:
+#  - Default:            mongo/.cache
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.CachePath = mongo/.cache
+
+
+# ArmarX.Config:  Comma-separated list of configuration files 
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.Config = ""
+
+
+# ArmarX.DataPath:  Semicolon-separated search list for data files
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DataPath = ""
+
+
+# ArmarX.DefaultPackages:  List of ArmarX packages which are accessible by default. Comma separated List. If you want to add your own packages and use all default ArmarX packages, use the property 'AdditionalPackages'.
+#  Attributes:
+#  - Default:            Default value not mapped.
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DefaultPackages = Default value not mapped.
+
+
+# ArmarX.DependenciesConfig:  Path to the (usually generated) config file containing all data paths of all dependent projects. This property usually does not need to be edited.
+#  Attributes:
+#  - Default:            ./config/dependencies.cfg
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DependenciesConfig = ./config/dependencies.cfg
+
+
+# ArmarX.DisableLogging:  Turn logging off in whole application
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.DisableLogging = false
+
+
+# ArmarX.EnableProfiling:  Enable profiling of CPU load produced by this application
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.EnableProfiling = false
+
+
+# ArmarX.GraspMemory.ArVizTopicName:  Name of the ArViz topic
+#  Attributes:
+#  - Default:            ArVizTopic
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.GraspMemory.ArVizTopicName = ArVizTopic
+
+
+# ArmarX.GraspMemory.EnableProfiling:  enable profiler which is used for logging performance events
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.GraspMemory.EnableProfiling = false
+
+
+# ArmarX.GraspMemory.MinimumLoggingLevel:  Local logging level only for this component
+#  Attributes:
+#  - Default:            Undefined
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning}
+# ArmarX.GraspMemory.MinimumLoggingLevel = Undefined
+
+
+# ArmarX.GraspMemory.ObjectName:  Name of IceGrid well-known object
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.GraspMemory.ObjectName = ""
+
+
+# ArmarX.GraspMemory.RemoteGuiName:  Name of the remote gui provider
+#  Attributes:
+#  - Default:            RemoteGuiProvider
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.GraspMemory.RemoteGuiName = RemoteGuiProvider
+
+
+# ArmarX.GraspMemory.mem.ltm.00_enabled:  
+#  Attributes:
+#  - Default:            true
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.GraspMemory.mem.ltm.00_enabled = true
+
+
+# ArmarX.GraspMemory.memory.Name:  Name of this memory server.
+#  Attributes:
+#  - Default:            Grasp
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.GraspMemory.memory.Name = Grasp
+
+
+# ArmarX.GraspMemory.mns.MemoryNameSystemEnabled:  Whether to use (and depend on) the Memory Name System (MNS).
+# Set to false to use this memory as a stand-alone.
+#  Attributes:
+#  - Default:            true
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.GraspMemory.mns.MemoryNameSystemEnabled = true
+
+
+# ArmarX.GraspMemory.mns.MemoryNameSystemName:  Name of the Memory Name System (MNS) component.
+#  Attributes:
+#  - Default:            MemoryNameSystem
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.GraspMemory.mns.MemoryNameSystemName = MemoryNameSystem
+
+
+# ArmarX.GraspMemory.tpc.pub.DebugObserver:  Name of the `DebugObserver` topic to publish data to.
+#  Attributes:
+#  - Default:            DebugObserver
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.GraspMemory.tpc.pub.DebugObserver = DebugObserver
+
+
+# ArmarX.GraspMemory.tpc.pub.MemoryListener:  Name of the `MemoryListener` topic to publish data to.
+#  Attributes:
+#  - Default:            MemoryUpdates
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.GraspMemory.tpc.pub.MemoryListener = MemoryUpdates
+
+
+# ArmarX.GraspMemory.tpc.sub.MemoryListener:  Name of the `MemoryListener` topic to subscribe to.
+#  Attributes:
+#  - Default:            MemoryUpdates
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.GraspMemory.tpc.sub.MemoryListener = MemoryUpdates
+
+
+# ArmarX.LoadLibraries:  Libraries to load at start up of the application. Must be enabled by the Application with enableLibLoading(). Format: PackageName:LibraryName;... or /absolute/path/to/library;...
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.LoadLibraries = ""
+
+
+# ArmarX.LoggingGroup:  The logging group is transmitted with every ArmarX log message over Ice in order to group the message in the GUI.
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.LoggingGroup = ""
+
+
+# ArmarX.RedirectStdout:  Redirect std::cout and std::cerr to ArmarXLog
+#  Attributes:
+#  - Default:            true
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.RedirectStdout = true
+
+
+# ArmarX.RemoteHandlesDeletionTimeout:  The timeout (in ms) before a remote handle deletes the managed object after the use count reached 0. This time can be used by a client to increment the count again (may be required when transmitting remote handles)
+#  Attributes:
+#  - Default:            3000
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.RemoteHandlesDeletionTimeout = 3000
+
+
+# ArmarX.SecondsStartupDelay:  The startup will be delayed by this number of seconds (useful for debugging)
+#  Attributes:
+#  - Default:            0
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.SecondsStartupDelay = 0
+
+
+# ArmarX.StartDebuggerOnCrash:  If this application crashes (segmentation fault) qtcreator will attach to this process and start the debugger.
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.StartDebuggerOnCrash = false
+
+
+# ArmarX.ThreadPoolSize:  Size of the ArmarX ThreadPool that is always running.
+#  Attributes:
+#  - Default:            1
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.ThreadPoolSize = 1
+
+
+# ArmarX.TopicSuffix:  Suffix appended to all topic names for outgoing topics. This is mainly used to direct all topics to another name for TopicReplaying purposes.
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.TopicSuffix = ""
+
+
+# ArmarX.UseTimeServer:  Enable using a global Timeserver (e.g. from ArmarXSimulator)
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.UseTimeServer = false
+
+
+# ArmarX.Verbosity:  Global logging level for whole application
+#  Attributes:
+#  - Default:            Info
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning}
+# ArmarX.Verbosity = Info
+
+
diff --git a/scenarios/ArmemGraspMemory/config/GraspProviderExample.cfg b/scenarios/ArmemGraspMemory/config/GraspProviderExample.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..9df508c17697c16e196f1194f847d1f532ee61b9
--- /dev/null
+++ b/scenarios/ArmemGraspMemory/config/GraspProviderExample.cfg
@@ -0,0 +1,222 @@
+# ==================================================================
+# GraspProviderExample properties
+# ==================================================================
+
+# ArmarX.AdditionalPackages:  List of additional ArmarX packages which should be in the list of default packages. If you have custom packages, which should be found by the gui or other apps, specify them here. Comma separated List.
+#  Attributes:
+#  - Default:            Default value not mapped.
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.AdditionalPackages = Default value not mapped.
+
+
+# ArmarX.ApplicationName:  Application name
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.ApplicationName = ""
+
+
+# ArmarX.CachePath:  Path for cache files. If relative path AND env. variable ARMARX_USER_CONFIG_DIR is set, the cache path will be made relative to ARMARX_USER_CONFIG_DIR. Otherwise if relative it will be relative to the default ArmarX config dir (${HOME}/.armarx)
+#  Attributes:
+#  - Default:            mongo/.cache
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.CachePath = mongo/.cache
+
+
+# ArmarX.Config:  Comma-separated list of configuration files 
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.Config = ""
+
+
+# ArmarX.DataPath:  Semicolon-separated search list for data files
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DataPath = ""
+
+
+# ArmarX.DefaultPackages:  List of ArmarX packages which are accessible by default. Comma separated List. If you want to add your own packages and use all default ArmarX packages, use the property 'AdditionalPackages'.
+#  Attributes:
+#  - Default:            Default value not mapped.
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DefaultPackages = Default value not mapped.
+
+
+# ArmarX.DependenciesConfig:  Path to the (usually generated) config file containing all data paths of all dependent projects. This property usually does not need to be edited.
+#  Attributes:
+#  - Default:            ./config/dependencies.cfg
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DependenciesConfig = ./config/dependencies.cfg
+
+
+# ArmarX.DisableLogging:  Turn logging off in whole application
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.DisableLogging = false
+
+
+# ArmarX.EnableProfiling:  Enable profiling of CPU load produced by this application
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.EnableProfiling = false
+
+
+# ArmarX.GraspProviderExample.EnableProfiling:  enable profiler which is used for logging performance events
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.GraspProviderExample.EnableProfiling = false
+
+
+# ArmarX.GraspProviderExample.MinimumLoggingLevel:  Local logging level only for this component
+#  Attributes:
+#  - Default:            Undefined
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning}
+# ArmarX.GraspProviderExample.MinimumLoggingLevel = Undefined
+
+
+# ArmarX.GraspProviderExample.ObjectName:  Name of IceGrid well-known object
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.GraspProviderExample.ObjectName = ""
+
+
+# ArmarX.GraspProviderExample.mem.MemoryName:  Name of the memory to use.
+#  Attributes:
+#  - Default:            Grasp
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.GraspProviderExample.mem.MemoryName = Grasp
+
+
+# ArmarX.GraspProviderExample.mns.MemoryNameSystemEnabled:  Whether to use (and depend on) the Memory Name System (MNS).
+# Set to false to use this memory as a stand-alone.
+#  Attributes:
+#  - Default:            true
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.GraspProviderExample.mns.MemoryNameSystemEnabled = true
+
+
+# ArmarX.GraspProviderExample.mns.MemoryNameSystemName:  Name of the Memory Name System (MNS) component.
+#  Attributes:
+#  - Default:            MemoryNameSystem
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.GraspProviderExample.mns.MemoryNameSystemName = MemoryNameSystem
+
+
+# ArmarX.GraspProviderExample.tpc.pub.DebugObserver:  Name of the `DebugObserver` topic to publish data to.
+#  Attributes:
+#  - Default:            DebugObserver
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.GraspProviderExample.tpc.pub.DebugObserver = DebugObserver
+
+
+# ArmarX.LoadLibraries:  Libraries to load at start up of the application. Must be enabled by the Application with enableLibLoading(). Format: PackageName:LibraryName;... or /absolute/path/to/library;...
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.LoadLibraries = ""
+
+
+# ArmarX.LoggingGroup:  The logging group is transmitted with every ArmarX log message over Ice in order to group the message in the GUI.
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.LoggingGroup = ""
+
+
+# ArmarX.RedirectStdout:  Redirect std::cout and std::cerr to ArmarXLog
+#  Attributes:
+#  - Default:            true
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.RedirectStdout = true
+
+
+# ArmarX.RemoteHandlesDeletionTimeout:  The timeout (in ms) before a remote handle deletes the managed object after the use count reached 0. This time can be used by a client to increment the count again (may be required when transmitting remote handles)
+#  Attributes:
+#  - Default:            3000
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.RemoteHandlesDeletionTimeout = 3000
+
+
+# ArmarX.SecondsStartupDelay:  The startup will be delayed by this number of seconds (useful for debugging)
+#  Attributes:
+#  - Default:            0
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.SecondsStartupDelay = 0
+
+
+# ArmarX.StartDebuggerOnCrash:  If this application crashes (segmentation fault) qtcreator will attach to this process and start the debugger.
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.StartDebuggerOnCrash = false
+
+
+# ArmarX.ThreadPoolSize:  Size of the ArmarX ThreadPool that is always running.
+#  Attributes:
+#  - Default:            1
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.ThreadPoolSize = 1
+
+
+# ArmarX.TopicSuffix:  Suffix appended to all topic names for outgoing topics. This is mainly used to direct all topics to another name for TopicReplaying purposes.
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.TopicSuffix = ""
+
+
+# ArmarX.UseTimeServer:  Enable using a global Timeserver (e.g. from ArmarXSimulator)
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.UseTimeServer = false
+
+
+# ArmarX.Verbosity:  Global logging level for whole application
+#  Attributes:
+#  - Default:            Info
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning}
+# ArmarX.Verbosity = Info
+
+
diff --git a/scenarios/ArmemGraspMemory/config/MemoryNameSystem.cfg b/scenarios/ArmemGraspMemory/config/MemoryNameSystem.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..7dd22218243ca4f9e67e843da8b42916f3b8568a
--- /dev/null
+++ b/scenarios/ArmemGraspMemory/config/MemoryNameSystem.cfg
@@ -0,0 +1,196 @@
+# ==================================================================
+# MemoryNameSystem properties
+# ==================================================================
+
+# ArmarX.AdditionalPackages:  List of additional ArmarX packages which should be in the list of default packages. If you have custom packages, which should be found by the gui or other apps, specify them here. Comma separated List.
+#  Attributes:
+#  - Default:            Default value not mapped.
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.AdditionalPackages = Default value not mapped.
+
+
+# ArmarX.ApplicationName:  Application name
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.ApplicationName = ""
+
+
+# ArmarX.CachePath:  Path for cache files. If relative path AND env. variable ARMARX_USER_CONFIG_DIR is set, the cache path will be made relative to ARMARX_USER_CONFIG_DIR. Otherwise if relative it will be relative to the default ArmarX config dir (${HOME}/.armarx)
+#  Attributes:
+#  - Default:            mongo/.cache
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.CachePath = mongo/.cache
+
+
+# ArmarX.Config:  Comma-separated list of configuration files 
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.Config = ""
+
+
+# ArmarX.DataPath:  Semicolon-separated search list for data files
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DataPath = ""
+
+
+# ArmarX.DefaultPackages:  List of ArmarX packages which are accessible by default. Comma separated List. If you want to add your own packages and use all default ArmarX packages, use the property 'AdditionalPackages'.
+#  Attributes:
+#  - Default:            Default value not mapped.
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DefaultPackages = Default value not mapped.
+
+
+# ArmarX.DependenciesConfig:  Path to the (usually generated) config file containing all data paths of all dependent projects. This property usually does not need to be edited.
+#  Attributes:
+#  - Default:            ./config/dependencies.cfg
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DependenciesConfig = ./config/dependencies.cfg
+
+
+# ArmarX.DisableLogging:  Turn logging off in whole application
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.DisableLogging = false
+
+
+# ArmarX.EnableProfiling:  Enable profiling of CPU load produced by this application
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.EnableProfiling = false
+
+
+# ArmarX.LoadLibraries:  Libraries to load at start up of the application. Must be enabled by the Application with enableLibLoading(). Format: PackageName:LibraryName;... or /absolute/path/to/library;...
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.LoadLibraries = ""
+
+
+# ArmarX.LoggingGroup:  The logging group is transmitted with every ArmarX log message over Ice in order to group the message in the GUI.
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.LoggingGroup = ""
+
+
+# ArmarX.MemoryNameSystem.EnableProfiling:  enable profiler which is used for logging performance events
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.MemoryNameSystem.EnableProfiling = false
+
+
+# ArmarX.MemoryNameSystem.MinimumLoggingLevel:  Local logging level only for this component
+#  Attributes:
+#  - Default:            Undefined
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning}
+# ArmarX.MemoryNameSystem.MinimumLoggingLevel = Undefined
+
+
+# ArmarX.MemoryNameSystem.ObjectName:  Name of IceGrid well-known object
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.MemoryNameSystem.ObjectName = ""
+
+
+# ArmarX.MemoryNameSystem.RemoteGuiName:  Name of the remote gui provider
+#  Attributes:
+#  - Default:            RemoteGuiProvider
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.MemoryNameSystem.RemoteGuiName = RemoteGuiProvider
+
+
+# ArmarX.RedirectStdout:  Redirect std::cout and std::cerr to ArmarXLog
+#  Attributes:
+#  - Default:            true
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.RedirectStdout = true
+
+
+# ArmarX.RemoteHandlesDeletionTimeout:  The timeout (in ms) before a remote handle deletes the managed object after the use count reached 0. This time can be used by a client to increment the count again (may be required when transmitting remote handles)
+#  Attributes:
+#  - Default:            3000
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.RemoteHandlesDeletionTimeout = 3000
+
+
+# ArmarX.SecondsStartupDelay:  The startup will be delayed by this number of seconds (useful for debugging)
+#  Attributes:
+#  - Default:            0
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.SecondsStartupDelay = 0
+
+
+# ArmarX.StartDebuggerOnCrash:  If this application crashes (segmentation fault) qtcreator will attach to this process and start the debugger.
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.StartDebuggerOnCrash = false
+
+
+# ArmarX.ThreadPoolSize:  Size of the ArmarX ThreadPool that is always running.
+#  Attributes:
+#  - Default:            1
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.ThreadPoolSize = 1
+
+
+# ArmarX.TopicSuffix:  Suffix appended to all topic names for outgoing topics. This is mainly used to direct all topics to another name for TopicReplaying purposes.
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.TopicSuffix = ""
+
+
+# ArmarX.UseTimeServer:  Enable using a global Timeserver (e.g. from ArmarXSimulator)
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.UseTimeServer = false
+
+
+# ArmarX.Verbosity:  Global logging level for whole application
+#  Attributes:
+#  - Default:            Info
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning}
+# ArmarX.Verbosity = Info
+
+
diff --git a/scenarios/ArmemGraspMemory/config/RemoteGuiProviderApp.cfg b/scenarios/ArmemGraspMemory/config/RemoteGuiProviderApp.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..4fd690cefd94559b207493cf40e346a3e47f3b12
--- /dev/null
+++ b/scenarios/ArmemGraspMemory/config/RemoteGuiProviderApp.cfg
@@ -0,0 +1,196 @@
+# ==================================================================
+# RemoteGuiProviderApp properties
+# ==================================================================
+
+# ArmarX.AdditionalPackages:  List of additional ArmarX packages which should be in the list of default packages. If you have custom packages, which should be found by the gui or other apps, specify them here. Comma separated List.
+#  Attributes:
+#  - Default:            Default value not mapped.
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.AdditionalPackages = Default value not mapped.
+
+
+# ArmarX.ApplicationName:  Application name
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.ApplicationName = ""
+
+
+# ArmarX.CachePath:  Path for cache files. If relative path AND env. variable ARMARX_USER_CONFIG_DIR is set, the cache path will be made relative to ARMARX_USER_CONFIG_DIR. Otherwise if relative it will be relative to the default ArmarX config dir (${HOME}/.armarx)
+#  Attributes:
+#  - Default:            mongo/.cache
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.CachePath = mongo/.cache
+
+
+# ArmarX.Config:  Comma-separated list of configuration files 
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.Config = ""
+
+
+# ArmarX.DataPath:  Semicolon-separated search list for data files
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DataPath = ""
+
+
+# ArmarX.DefaultPackages:  List of ArmarX packages which are accessible by default. Comma separated List. If you want to add your own packages and use all default ArmarX packages, use the property 'AdditionalPackages'.
+#  Attributes:
+#  - Default:            Default value not mapped.
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DefaultPackages = Default value not mapped.
+
+
+# ArmarX.DependenciesConfig:  Path to the (usually generated) config file containing all data paths of all dependent projects. This property usually does not need to be edited.
+#  Attributes:
+#  - Default:            ./config/dependencies.cfg
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.DependenciesConfig = ./config/dependencies.cfg
+
+
+# ArmarX.DisableLogging:  Turn logging off in whole application
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.DisableLogging = false
+
+
+# ArmarX.EnableProfiling:  Enable profiling of CPU load produced by this application
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.EnableProfiling = false
+
+
+# ArmarX.LoadLibraries:  Libraries to load at start up of the application. Must be enabled by the Application with enableLibLoading(). Format: PackageName:LibraryName;... or /absolute/path/to/library;...
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.LoadLibraries = ""
+
+
+# ArmarX.LoggingGroup:  The logging group is transmitted with every ArmarX log message over Ice in order to group the message in the GUI.
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.LoggingGroup = ""
+
+
+# ArmarX.RedirectStdout:  Redirect std::cout and std::cerr to ArmarXLog
+#  Attributes:
+#  - Default:            true
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.RedirectStdout = true
+
+
+# ArmarX.RemoteGuiProvider.EnableProfiling:  enable profiler which is used for logging performance events
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.RemoteGuiProvider.EnableProfiling = false
+
+
+# ArmarX.RemoteGuiProvider.MinimumLoggingLevel:  Local logging level only for this component
+#  Attributes:
+#  - Default:            Undefined
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning}
+# ArmarX.RemoteGuiProvider.MinimumLoggingLevel = Undefined
+
+
+# ArmarX.RemoteGuiProvider.ObjectName:  Name of IceGrid well-known object
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.RemoteGuiProvider.ObjectName = ""
+
+
+# ArmarX.RemoteGuiProvider.TopicName:  Name of the topic on which updates to the remote state are reported.
+#  Attributes:
+#  - Default:            RemoteGuiTopic
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.RemoteGuiProvider.TopicName = RemoteGuiTopic
+
+
+# ArmarX.RemoteHandlesDeletionTimeout:  The timeout (in ms) before a remote handle deletes the managed object after the use count reached 0. This time can be used by a client to increment the count again (may be required when transmitting remote handles)
+#  Attributes:
+#  - Default:            3000
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.RemoteHandlesDeletionTimeout = 3000
+
+
+# ArmarX.SecondsStartupDelay:  The startup will be delayed by this number of seconds (useful for debugging)
+#  Attributes:
+#  - Default:            0
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.SecondsStartupDelay = 0
+
+
+# ArmarX.StartDebuggerOnCrash:  If this application crashes (segmentation fault) qtcreator will attach to this process and start the debugger.
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.StartDebuggerOnCrash = false
+
+
+# ArmarX.ThreadPoolSize:  Size of the ArmarX ThreadPool that is always running.
+#  Attributes:
+#  - Default:            1
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.ThreadPoolSize = 1
+
+
+# ArmarX.TopicSuffix:  Suffix appended to all topic names for outgoing topics. This is mainly used to direct all topics to another name for TopicReplaying purposes.
+#  Attributes:
+#  - Default:            ""
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.TopicSuffix = ""
+
+
+# ArmarX.UseTimeServer:  Enable using a global Timeserver (e.g. from ArmarXSimulator)
+#  Attributes:
+#  - Default:            false
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {0, 1, false, no, true, yes}
+# ArmarX.UseTimeServer = false
+
+
+# ArmarX.Verbosity:  Global logging level for whole application
+#  Attributes:
+#  - Default:            Info
+#  - Case sensitivity:   yes
+#  - Required:           no
+#  - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning}
+# ArmarX.Verbosity = Info
+
+
diff --git a/scenarios/ArmemGraspMemory/config/global.cfg b/scenarios/ArmemGraspMemory/config/global.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..39c0afa137c7362bbb2a5f82234b53de3744ec8c
--- /dev/null
+++ b/scenarios/ArmemGraspMemory/config/global.cfg
@@ -0,0 +1,4 @@
+# ==================================================================
+# Global Config from Scenario ArmemGraspMemory
+# ==================================================================
+
diff --git a/source/RobotAPI/components/ArViz/Client/Elements.h b/source/RobotAPI/components/ArViz/Client/Elements.h
index 858bff26243d0580d88d158adddb3fc6222e696f..7b65e66ff7b273110366efa1da21ea7eff3412d5 100644
--- a/source/RobotAPI/components/ArViz/Client/Elements.h
+++ b/source/RobotAPI/components/ArViz/Client/Elements.h
@@ -296,7 +296,7 @@ namespace armarx::viz
             return *this;
         }
 
-        Arrow& fromTo(Eigen::Vector3f from, Eigen::Vector3f to)
+        Arrow& fromTo(const Eigen::Vector3f& from, const Eigen::Vector3f& to)
         {
             position(from);
             direction((to - from).normalized());
diff --git a/source/RobotAPI/components/ArViz/Introspection/json_elements.cpp b/source/RobotAPI/components/ArViz/Introspection/json_elements.cpp
index 837e3903004375e41ba0268ea1712682604a151f..39200985c55a98e19f119c6e08e0d45565ca2f9a 100644
--- a/source/RobotAPI/components/ArViz/Introspection/json_elements.cpp
+++ b/source/RobotAPI/components/ArViz/Introspection/json_elements.cpp
@@ -3,6 +3,7 @@
 #include <SimoxUtility/algorithm/string.h>
 
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+#include <ArmarXCore/interface/core/BasicVectorTypes.h>
 
 #include "json_base.h"
 
@@ -194,6 +195,18 @@ namespace armarx::viz
         json::from_json_base(j, pose);
     }
 
+    void data::to_json(nlohmann::json& j, const ElementPath& path)
+    {
+        json::to_json_base(j, path);
+        j["points"] = path.points;
+    }
+
+    void data::from_json(const nlohmann::json& j, ElementPath& path)
+    {
+        json::from_json_base(j, path);
+        path.points = j.at("points").get<armarx::Vector3fSeq>();
+    }
+
 
     void data::to_json(nlohmann::json& j, const ElementSphere& sphere)
     {
@@ -301,4 +314,3 @@ namespace armarx::viz
     }
 
 }
-
diff --git a/source/RobotAPI/components/ArViz/Introspection/json_elements.h b/source/RobotAPI/components/ArViz/Introspection/json_elements.h
index 160948cb459fa8531f005743700c6a44de3fabb0..5e41dc0df1c60d71ec11dafed535e3ec35126603 100644
--- a/source/RobotAPI/components/ArViz/Introspection/json_elements.h
+++ b/source/RobotAPI/components/ArViz/Introspection/json_elements.h
@@ -70,6 +70,10 @@ namespace armarx::viz::data
     void from_json(const nlohmann::json& j, ElementPose& pose);
 
 
+    void to_json(nlohmann::json& j, const ElementPath& path);
+    void from_json(const nlohmann::json& j, ElementPath& path);
+
+
     void to_json(nlohmann::json& j, const ElementRobot& robot);
     void from_json(const nlohmann::json& j, ElementRobot& robot);
 
diff --git a/source/RobotAPI/components/ArViz/Introspection/register_element_json_serializers.cpp b/source/RobotAPI/components/ArViz/Introspection/register_element_json_serializers.cpp
index 5dd43185aecb485da85a7372f096b62c79bef10f..48228263d42465bf3a219488ba012437aae93001 100644
--- a/source/RobotAPI/components/ArViz/Introspection/register_element_json_serializers.cpp
+++ b/source/RobotAPI/components/ArViz/Introspection/register_element_json_serializers.cpp
@@ -1,3 +1,4 @@
+#include <RobotAPI/interface/ArViz/Elements.h>
 #include "ElementJsonSerializers.h"
 #include "json_elements.h"
 
@@ -15,6 +16,7 @@ void armarx::viz::json::ElementJsonSerializers::registerElements()
     registerSerializer<data::ElementPointCloud>(viz::data::to_json, viz::data::from_json);
     registerSerializer<data::ElementPolygon>(viz::data::to_json, viz::data::from_json);
     registerSerializer<data::ElementPose>(viz::data::to_json, viz::data::from_json);
+    registerSerializer<data::ElementPath>(viz::data::to_json, viz::data::from_json);
     registerSerializer<data::ElementRobot>(viz::data::to_json, viz::data::from_json);
     registerSerializer<data::ElementSphere>(viz::data::to_json, viz::data::from_json);
     registerSerializer<data::ElementEllipsoid>(viz::data::to_json, viz::data::from_json);
diff --git a/source/RobotAPI/components/ObjectPoseProviderExample/ObjectPoseProviderExample.cpp b/source/RobotAPI/components/ObjectPoseProviderExample/ObjectPoseProviderExample.cpp
index a87d465a301b423defc89260a52cb15164bcd37d..7bd52aec0ffcf6e423cd959f1a8399ba107045ac 100644
--- a/source/RobotAPI/components/ObjectPoseProviderExample/ObjectPoseProviderExample.cpp
+++ b/source/RobotAPI/components/ObjectPoseProviderExample/ObjectPoseProviderExample.cpp
@@ -61,7 +61,7 @@ namespace armarx
         }
 
         {
-            providerInfo.objectType = objpose::ObjectTypeEnum::KnownObject;
+            providerInfo.objectType = objpose::ObjectType::KnownObject;
             std::vector<ObjectInfo> objects = objectFinder.findAllObjectsOfDataset("KIT");
             for (const auto& obj : objects)
             {
@@ -154,7 +154,7 @@ namespace armarx
 
                 armarx::objpose::data::ProvidedObjectPose& pose = poses.emplace_back();
                 pose.providerName = getName();
-                pose.objectType = objpose::ObjectTypeEnum::KnownObject;
+                pose.objectType = objpose::ObjectType::KnownObject;
 
                 pose.objectID.dataset = info.id().dataset();
                 pose.objectID.className = info.id().className();
diff --git a/source/RobotAPI/components/armem/client/CMakeLists.txt b/source/RobotAPI/components/armem/client/CMakeLists.txt
index de02c9f4e7ef45534c2675db6173205436b4475c..c09dd6f9784a4fa0c05812a0e84d22abe4984e1a 100644
--- a/source/RobotAPI/components/armem/client/CMakeLists.txt
+++ b/source/RobotAPI/components/armem/client/CMakeLists.txt
@@ -1,2 +1,6 @@
 add_subdirectory(ExampleMemoryClient)
+
+add_subdirectory(GraspProviderExample)
+
 add_subdirectory(VirtualRobotReaderExampleClient)
+
diff --git a/source/RobotAPI/components/armem/client/GraspProviderExample/CMakeLists.txt b/source/RobotAPI/components/armem/client/GraspProviderExample/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..18ea059105a516dbafffaba07b3d4c322dabdc11
--- /dev/null
+++ b/source/RobotAPI/components/armem/client/GraspProviderExample/CMakeLists.txt
@@ -0,0 +1,32 @@
+armarx_component_set_name("GraspProviderExample")
+
+find_package(IVT QUIET)
+armarx_build_if(IVT_FOUND "IVT not available")
+
+set(COMPONENT_LIBS
+    ArmarXCore ArmarXCoreInterfaces  # for DebugObserverInterface
+    ArmarXGuiComponentPlugins
+    RobotAPICore RobotAPIInterfaces armem
+    GraspingUtility
+    ${IVT_LIBRARIES}
+)
+
+set(SOURCES
+    GraspProviderExample.cpp
+)
+
+set(HEADERS
+    GraspProviderExample.h
+)
+
+armarx_add_component("${SOURCES}" "${HEADERS}")
+if (IVT_FOUND)
+    target_include_directories(${ARMARX_COMPONENT_NAME} PUBLIC ${IVT_INCLUDE_DIRS})
+endif()
+
+
+# add unit tests
+# add_subdirectory(test)
+
+#generate the application
+armarx_generate_and_add_component_executable()
diff --git a/source/RobotAPI/components/armem/client/GraspProviderExample/GraspProviderExample.cpp b/source/RobotAPI/components/armem/client/GraspProviderExample/GraspProviderExample.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8f98b2383da3556f459ae6fa01a7f3ec190b29e2
--- /dev/null
+++ b/source/RobotAPI/components/armem/client/GraspProviderExample/GraspProviderExample.cpp
@@ -0,0 +1,170 @@
+#include "GraspProviderExample.h"
+
+#include <SimoxUtility/color/cmaps.h>
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+#include <ArmarXCore/core/time/CycleUtil.h>
+
+#include <RobotAPI/libraries/core/Pose.h>
+
+#include <RobotAPI/libraries/armem/server/MemoryRemoteGui.h>
+#include <RobotAPI/libraries/armem/client/query/Builder.h>
+#include <RobotAPI/libraries/armem/client/query/query_fns.h>
+#include <RobotAPI/libraries/armem/core/ice_conversions.h>
+
+#include <RobotAPI/libraries/GraspingUtility/aron/GraspCandidate.aron.generated.h>
+
+
+namespace armarx
+{
+    GraspProviderExamplePropertyDefinitions::GraspProviderExamplePropertyDefinitions(std::string prefix) :
+        armarx::ComponentPropertyDefinitions(prefix)
+    {
+    }
+
+    armarx::PropertyDefinitionsPtr GraspProviderExample::createPropertyDefinitions()
+    {
+        ARMARX_IMPORTANT << "Prperty defs";
+        armarx::PropertyDefinitionsPtr defs = new GraspProviderExamplePropertyDefinitions(getConfigIdentifier());
+
+        defs->topic(debugObserver);
+
+        defs->optional(memoryName, "mem.MemoryName", "Name of the memory to use.");
+
+        return defs;
+
+    }
+
+    std::string GraspProviderExample::getDefaultName() const
+    {
+        return "GraspProviderExample";
+    }
+
+    GraspProviderExample::GraspProviderExample() : writer(memoryNameSystem()), reader(memoryNameSystem())
+    {
+
+    }
+
+
+    void GraspProviderExample::onInitComponent()
+    {
+        ARMARX_IMPORTANT << "Init";
+    }
+
+
+    void GraspProviderExample::onConnectComponent()
+    {
+        writer.connect();
+        reader.connect();
+        task = new RunningTask<GraspProviderExample>(this, &GraspProviderExample::run);
+        task->start();
+    }
+
+
+    void GraspProviderExample::onDisconnectComponent()
+    {
+        task->stop();
+    }
+
+
+    void GraspProviderExample::onExitComponent()
+    {
+    }
+
+
+    void GraspProviderExample::run()
+    {
+        ARMARX_IMPORTANT << "Running example.";
+
+        CycleUtil c(1000);
+        int i = 0;
+
+
+        while (!task->isStopped() && i++ < 100)
+        {
+            // initialize all necessary fields of a grasp candidate and use writer to commit it to memory
+
+            armarx::grasping::GraspCandidate candidate = armarx::grasping::GraspCandidate();
+            candidate.groupNr = i; //non-necessary field, but used to commit different candidates
+            candidate.approachVector = Vector3BasePtr(toIce(Eigen::Vector3f()));
+            candidate.graspPose = PoseBasePtr(toIce(Eigen::Matrix4f()));
+            candidate.providerName = "Example";
+            candidate.robotPose = PoseBasePtr(toIce(Eigen::Matrix4f()));
+            candidate.tcpPoseInHandRoot = PoseBasePtr(toIce(Eigen::Matrix4f()));
+            // source Info is also not necessary, but reference object name is used as entity name
+            // "UnknownObject" if none is provided
+            candidate.sourceInfo = new grasping::GraspCandidateSourceInfo();
+            candidate.sourceInfo->referenceObjectName = "Box";
+            candidate.sourceInfo->bbox = new grasping::BoundingBox();
+            candidate.sourceInfo->bbox->center = Vector3BasePtr(toIce(Eigen::Vector3f()));
+            candidate.sourceInfo->bbox->ha1 = Vector3BasePtr(toIce(Eigen::Vector3f()));
+            candidate.sourceInfo->bbox->ha2 = Vector3BasePtr(toIce(Eigen::Vector3f()));
+            candidate.sourceInfo->bbox->ha3 = Vector3BasePtr(toIce(Eigen::Vector3f()));
+            candidate.sourceInfo->referenceObjectPose = PoseBasePtr(toIce(Eigen::Matrix4f()));
+
+            writer.commitGraspCandidate(candidate, armem::Time::now(), "provider1");
+            // initialize all necessary fields of a bimanual grasp candidate and use writer to commit it to memory
+            armarx::grasping::BimanualGraspCandidate bimanualCandidate = armarx::grasping::BimanualGraspCandidate();
+            bimanualCandidate.groupNr = i; //non-necessary field, but used to commit different candidates
+            bimanualCandidate.approachVectorLeft = Vector3BasePtr(toIce(Eigen::Vector3f()));
+            bimanualCandidate.approachVectorRight = Vector3BasePtr(toIce(Eigen::Vector3f()));
+            bimanualCandidate.graspPoseLeft = PoseBasePtr(toIce(Eigen::Matrix4f()));
+            bimanualCandidate.graspPoseRight = PoseBasePtr(toIce(Eigen::Matrix4f()));
+            bimanualCandidate.providerName = "BimanualExample";
+            bimanualCandidate.robotPose = PoseBasePtr(toIce(Eigen::Matrix4f()));
+            bimanualCandidate.tcpPoseInHandRootRight = PoseBasePtr(toIce(Eigen::Matrix4f()));
+            bimanualCandidate.tcpPoseInHandRootLeft = PoseBasePtr(toIce(Eigen::Matrix4f()));
+            bimanualCandidate.inwardsVectorLeft = Vector3BasePtr(toIce(Eigen::Vector3f()));
+            bimanualCandidate.inwardsVectorRight = Vector3BasePtr(toIce(Eigen::Vector3f()));
+
+            writer.commitBimanualGraspCandidate(bimanualCandidate, armem::Time::now(), "provider2");
+
+            //test for writing Seqs, candidates from the same object appear as instances of the same snapshot
+            grasping::GraspCandidateSeq candidatesToWrite;
+            candidatesToWrite.push_back(new grasping::GraspCandidate(candidate));
+            candidate.side = "Left";
+
+            candidatesToWrite.push_back(new grasping::GraspCandidate(candidate));
+
+            writer.commitGraspCandidateSeq(candidatesToWrite, armem::Time::now(), "provider1");
+
+            // test reader and debug by logging the group number of the candidate
+
+            std::map<std::string, grasping::GraspCandidatePtr> candidates;
+
+            try
+            {
+                candidates = reader.queryLatestGraspCandidates();
+            }
+            catch (armem::error::QueryFailed &e)
+            {
+                ARMARX_ERROR << e.makeMsg(memoryName);
+            }
+
+
+            for (auto [id, ca] : candidates)
+            {
+                ARMARX_INFO << "candidate with ID " << id << " has group number " <<  ca->groupNr ;
+            }
+
+            std::map<std::string, grasping::BimanualGraspCandidatePtr> bimanualCandidates;
+
+            try
+            {
+                bimanualCandidates = reader.queryLatestBimanualGraspCandidates();
+            }
+            catch (armem::error::QueryFailed &e)
+            {
+                ARMARX_ERROR << e.makeMsg(memoryName);
+            }
+
+            for (auto [id, ca] : bimanualCandidates)
+            {
+                ARMARX_INFO << "bimanual candidate with ID " << id << " has group number " <<  ca->groupNr ;
+            }
+
+            c.waitForCycleDuration();
+        }
+    }
+
+}
diff --git a/source/RobotAPI/components/armem/client/GraspProviderExample/GraspProviderExample.h b/source/RobotAPI/components/armem/client/GraspProviderExample/GraspProviderExample.h
new file mode 100644
index 0000000000000000000000000000000000000000..efab1f49318c722eaa52302ae662814dc888addc
--- /dev/null
+++ b/source/RobotAPI/components/armem/client/GraspProviderExample/GraspProviderExample.h
@@ -0,0 +1,56 @@
+#include <ArmarXCore/core/Component.h>
+#include <ArmarXCore/interface/observers/ObserverInterface.h>
+#include <ArmarXCore/util/tasks.h>
+#include <RobotAPI/libraries/GraspingUtility/GraspCandidateReader.h>
+#include <RobotAPI/libraries/GraspingUtility/GraspCandidateWriter.h>
+
+#include <RobotAPI/libraries/armem/client/plugins/PluginUser.h>
+
+#pragma once
+
+
+namespace armarx
+{
+
+
+    class GraspProviderExamplePropertyDefinitions :
+        public armarx::ComponentPropertyDefinitions
+    {
+    public:
+        GraspProviderExamplePropertyDefinitions(std::string prefix);
+    };
+
+
+    class GraspProviderExample :
+        virtual public armarx::Component,
+        virtual public armarx::armem::ClientPluginUser
+    {
+    public:
+
+        /// @see armarx::ManagedIceObject::getDefaultName()
+        std::string getDefaultName() const override;
+        GraspProviderExample();
+
+
+    protected:
+
+        armarx::PropertyDefinitionsPtr createPropertyDefinitions() override;
+        void onInitComponent() override;
+        void onConnectComponent() override;
+        void onDisconnectComponent() override;
+        void onExitComponent() override;
+
+        void run();
+
+
+    private:
+
+        armarx::RunningTask<GraspProviderExample>::pointer_type task;
+
+        armarx::DebugObserverInterfacePrx debugObserver;
+
+        std::string memoryName = "Grasp";
+        armarx::armem::GraspCandidateWriter writer;
+        armarx::armem::GraspCandidateReader reader;
+    };
+}
diff --git a/source/RobotAPI/components/armem/server/CMakeLists.txt b/source/RobotAPI/components/armem/server/CMakeLists.txt
index 824eaa4937df6f7f06fa2d5ce7144020feb6097f..4fd2a92cb219cd738cc7e4b33d946e88a5a1ad74 100644
--- a/source/RobotAPI/components/armem/server/CMakeLists.txt
+++ b/source/RobotAPI/components/armem/server/CMakeLists.txt
@@ -3,5 +3,7 @@ add_subdirectory(GeneralPurposeMemory)
 add_subdirectory(ObjectMemory)
 add_subdirectory(RobotStateMemory)
 add_subdirectory(SkillsMemory)
+add_subdirectory(GraspMemory)
 #add_subdirectory(SubjectMemory)
 add_subdirectory(MotionMemory)
+
diff --git a/source/RobotAPI/components/armem/server/GraspMemory/CMakeLists.txt b/source/RobotAPI/components/armem/server/GraspMemory/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7bac572cd11bae463d2349529691f2ff5d6b79b2
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/GraspMemory/CMakeLists.txt
@@ -0,0 +1,28 @@
+armarx_component_set_name("GraspMemory")
+
+
+set(COMPONENT_LIBS
+    ArmarXCore ArmarXCoreInterfaces  # for DebugObserverInterface
+    ArmarXGuiComponentPlugins
+    RobotAPICore RobotAPIInterfaces armem
+    RobotAPIComponentPlugins  # for ArViz and other plugins
+
+    ${IVT_LIBRARIES}
+)
+
+set(SOURCES
+    GraspMemory.cpp
+)
+set(HEADERS
+    GraspMemory.h
+)
+
+armarx_add_component("${SOURCES}" "${HEADERS}")
+
+#generate the application
+armarx_generate_and_add_component_executable(
+    COMPONENT_NAMESPACE ::armarx::armem::server::grasp
+)
+
+
+
diff --git a/source/RobotAPI/components/armem/server/GraspMemory/GraspMemory.cpp b/source/RobotAPI/components/armem/server/GraspMemory/GraspMemory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b50b214509fb791a4b9f0394bd2c82867ee192ff
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/GraspMemory/GraspMemory.cpp
@@ -0,0 +1,101 @@
+
+#include "GraspMemory.h"
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include <SimoxUtility/algorithm/string.h>
+
+#include <RobotAPI/libraries/armem/core/error.h>
+#include <RobotAPI/libraries/armem/server/MemoryRemoteGui.h>
+
+#include <RobotAPI/libraries/GraspingUtility/aron/GraspCandidate.aron.generated.h>
+
+namespace armarx::armem::server::grasp
+{
+    armarx::PropertyDefinitionsPtr GraspMemory::createPropertyDefinitions()
+    {
+        armarx::PropertyDefinitionsPtr defs = new ComponentPropertyDefinitions(getConfigIdentifier());
+
+        defs->topic(debugObserver);
+
+        defs->optional(memoryName, "memory.Name", "Name of this memory server.");
+
+        return defs;
+    }
+
+
+    std::string GraspMemory::getDefaultName() const
+    {
+        return "GraspMemory";
+    }
+
+    void GraspMemory::onInitComponent()
+    {
+        workingMemory().name() = memoryName;
+
+        workingMemory().addCoreSegment("GraspCandidate",
+                                     armarx::grasping::arondto::GraspCandidate::toAronType());
+        workingMemory().addCoreSegment("BimanualGraspCandidate",
+                                     armarx::grasping::arondto::BimanualGraspCandidate::toAronType());
+    }
+
+    void GraspMemory::onConnectComponent()
+    {
+
+        createRemoteGuiTab();
+        RemoteGui_startRunningTask();
+
+    }
+
+    void GraspMemory::onDisconnectComponent()
+    {
+    }
+
+    void GraspMemory::onExitComponent()
+    {
+    }
+
+
+
+    // WRITING
+
+    armem::data::CommitResult GraspMemory::commit(const armem::data::Commit& commit, const Ice::Current&)
+    {
+        // This function is overloaded to trigger the remote gui rebuild.
+        armem::data::CommitResult result = ReadWritePluginUser::commit(commit);
+        tab.rebuild = true;
+        return result;
+    }
+
+
+    // READING
+
+    // Inherited from Plugin
+
+
+
+    // REMOTE GUI
+
+    void GraspMemory::createRemoteGuiTab()
+    {
+        using namespace armarx::RemoteGui::Client;
+
+        {
+
+            tab.memoryGroup = armem::server::MemoryRemoteGui().makeGroupBox(workingMemory());
+        }
+
+        VBoxLayout root = {tab.memoryGroup, VSpacer()};
+        RemoteGui_createTab(getName(), root, &tab);
+    }
+
+
+    void GraspMemory::RemoteGui_update()
+    {
+        if (tab.rebuild.exchange(false))
+        {
+            createRemoteGuiTab();
+        }
+    }
+
+}
diff --git a/source/RobotAPI/components/armem/server/GraspMemory/GraspMemory.h b/source/RobotAPI/components/armem/server/GraspMemory/GraspMemory.h
new file mode 100644
index 0000000000000000000000000000000000000000..a6cf94b3a961e53c179c14132e5d3aaa3a11ba5b
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/GraspMemory/GraspMemory.h
@@ -0,0 +1,73 @@
+#pragma once
+
+
+#include <memory>
+
+#include <ArmarXCore/interface/observers/ObserverInterface.h>
+#include <ArmarXGui/libraries/ArmarXGuiComponentPlugins/LightweightRemoteGuiComponentPlugin.h>
+#include <RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.h>
+#include <RobotAPI/libraries/armem/server/plugins/ReadWritePluginUser.h>
+
+namespace armarx::armem::server::grasp
+{
+    /**
+     * @defgroup Component-GraspMemory GraspMemory
+     * @ingroup RobotAPI-Components
+     * A description of the component GraspMemory.
+     *
+     * @class GraspMemory
+     * @ingroup Component-GraspMemory
+     * @brief Brief description of class GraspMemory.
+     *
+     * Detailed description of class GraspMemory.
+     */
+    class GraspMemory :
+        virtual public armarx::Component
+        , virtual public armem::server::ReadWritePluginUser
+        , virtual public armarx::LightweightRemoteGuiComponentPluginUser
+        , virtual public armarx::ArVizComponentPluginUser
+    {
+    public:
+
+        /// @see armarx::ManagedIceObject::getDefaultName()
+        std::string getDefaultName() const override;
+
+
+    public:
+        armem::data::CommitResult commit(const armem::data::Commit& commit, const Ice::Current&) override;
+
+
+    public:
+        void createRemoteGuiTab();
+        void RemoteGui_update() override;
+
+
+    protected:
+
+        PropertyDefinitionsPtr createPropertyDefinitions() override;
+
+        void onInitComponent() override;
+        void onConnectComponent() override;
+        void onDisconnectComponent() override;
+        void onExitComponent() override;
+
+
+    private:
+
+        DebugObserverInterfacePrx debugObserver;
+
+
+        std::string memoryName = "Grasp";
+
+
+
+        struct RemoteGuiTab : RemoteGui::Client::Tab
+        {
+            std::atomic_bool rebuild = false;
+
+            RemoteGui::Client::GroupBox memoryGroup;
+        };
+        RemoteGuiTab tab;
+
+    };
+}
diff --git a/source/RobotAPI/components/units/GraspCandidateObserver.cpp b/source/RobotAPI/components/units/GraspCandidateObserver.cpp
index 8e0bf788792e67933850982bb8f51817d9d791eb..8b3f0299ee9732265b757d6c5b375a08e72d554b 100644
--- a/source/RobotAPI/components/units/GraspCandidateObserver.cpp
+++ b/source/RobotAPI/components/units/GraspCandidateObserver.cpp
@@ -79,27 +79,28 @@ bool GraspCandidateObserver::FilterMatches(const CandidateFilterConditionPtr& fi
     {
         return false;
     }
-    if (filter->objectType != AnyObject && filter->objectType != candidate->objectType)
+    if (filter->objectType != objpose::AnyObject && filter->objectType != candidate->objectType)
     {
         return false;
     }
     return true;
 }
 
-std::string GraspCandidateObserver::ObjectTypeToString(ObjectTypeEnum type)
+std::string GraspCandidateObserver::ObjectTypeToString(objpose::ObjectType type)
 {
     switch (type)
     {
-        case grasping::AnyObject:
+        case objpose::AnyObject:
             return "AnyObject";
-        case grasping::KnownObject:
+        case objpose::KnownObject:
             return "KnownObject";
-        case grasping::UnknownObject:
+        case objpose::UnknownObject:
             return "UnknownObject";
         default:
             return "ERROR";
     }
 }
+
 void GraspCandidateObserver::handleProviderUpdate(const std::string& providerName, int candidateCount)
 {
     if (updateCounters.count(providerName) == 0)
diff --git a/source/RobotAPI/components/units/GraspCandidateObserver.h b/source/RobotAPI/components/units/GraspCandidateObserver.h
index 67adec25eb5d4ad23b59d8833a5836a4ce65edda..f4bb0ba3e7886d970cd33a82a03fe9525057b6c9 100644
--- a/source/RobotAPI/components/units/GraspCandidateObserver.h
+++ b/source/RobotAPI/components/units/GraspCandidateObserver.h
@@ -72,7 +72,7 @@ namespace armarx
 
     public:
         static bool FilterMatches(const grasping::CandidateFilterConditionPtr& filter, const std::string& providerName, const grasping::GraspCandidatePtr& candidate);
-        static std::string ObjectTypeToString(grasping::ObjectTypeEnum type);
+        static std::string ObjectTypeToString(objpose::ObjectType type);
 
         // GraspCandidateProviderListener interface
     public:
diff --git a/source/RobotAPI/gui-plugins/GraspCandidateViewer/GraspCandidateViewerWidgetController.cpp b/source/RobotAPI/gui-plugins/GraspCandidateViewer/GraspCandidateViewerWidgetController.cpp
index a46e191dcc34615698951568a86ceddac3231ac3..0cddd8405f669bf3b65ddd1e3c56d40317a4ff5d 100644
--- a/source/RobotAPI/gui-plugins/GraspCandidateViewer/GraspCandidateViewerWidgetController.cpp
+++ b/source/RobotAPI/gui-plugins/GraspCandidateViewer/GraspCandidateViewerWidgetController.cpp
@@ -260,13 +260,13 @@ namespace armarx
         _ui.labelGraspgroupNr     ->setText(QString::number(e->gc->groupNr));
         switch (e->gc->objectType)
         {
-            case grasping::ObjectTypeEnum::AnyObject :
+            case objpose::ObjectType::AnyObject :
                 _ui.labelGraspObjType->setText("AnyObject");
                 break;
-            case grasping::ObjectTypeEnum::KnownObject :
+            case objpose::ObjectType::KnownObject :
                 _ui.labelGraspObjType->setText("KnownObject");
                 break;
-            case grasping::ObjectTypeEnum::UnknownObject :
+            case objpose::ObjectType::UnknownObject :
                 _ui.labelGraspObjType->setText("UnknownObject");
                 break;
         }
diff --git a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.cpp b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.cpp
index adb7c77bd1e04491b7e16ecb1599119df0ee2ce6..c5f588adf750b8b2eda12375c798b7d80c741dfa 100644
--- a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.cpp
+++ b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.cpp
@@ -216,7 +216,7 @@ namespace armarx
                 int col = 0;
                 item->setText(col++, QString::fromStdString(pose.objectID.str()));
                 item->setText(col++, QString::fromStdString(pose.providerName));
-                item->setText(col++, QString::fromStdString(objpose::ObjectTypeEnumNames.to_name(pose.objectType)));
+                item->setText(col++, QString::fromStdString(objpose::ObjectTypeNames.to_name(pose.objectType)));
 
                 {
                     std::stringstream ss;
diff --git a/source/RobotAPI/interface/CMakeLists.txt b/source/RobotAPI/interface/CMakeLists.txt
index a026e17c6b4a4f036aa600c4b37d6f4e2aadd1c4..a7cc9ca79c5ecc5f99f294065709cc3daa0e2790 100644
--- a/source/RobotAPI/interface/CMakeLists.txt
+++ b/source/RobotAPI/interface/CMakeLists.txt
@@ -26,6 +26,7 @@ set(SLICE_FILES
     core/CartesianNaturalPositionControllerConfig.ice
     core/TopicTimingTest.ice
     core/FTSensorValue.ice
+    core/NameValueMap.ice
 
     selflocalisation/SelfLocalisationProcess.ice
 
diff --git a/source/RobotAPI/interface/core/NameValueMap.ice b/source/RobotAPI/interface/core/NameValueMap.ice
new file mode 100644
index 0000000000000000000000000000000000000000..b15090a586f47458bc3ed9a158a107dbfd258810
--- /dev/null
+++ b/source/RobotAPI/interface/core/NameValueMap.ice
@@ -0,0 +1,32 @@
+/**
+* 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 as
+* published by the Free Software Foundation; either version 2 of
+* the License, or (at your option) any later version.
+*
+* 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 Lesser 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
+* @author     Christoph Pohl
+* @copyright  2020 Humanoids Group, H2T, KIT
+* @license    http://www.gnu.org/licenses/gpl-2.0.txt
+*             GNU General Public License
+*/
+
+#pragma once
+
+module armarx
+{
+    /**
+	* [NameValueMap] defined. This data container is mostly used to assign values to e.g. joints which are identified by name.
+	**/
+    dictionary<string, float> NameValueMap;
+}
\ No newline at end of file
diff --git a/source/RobotAPI/interface/objectpose/ObjectPoseProvider.ice b/source/RobotAPI/interface/objectpose/ObjectPoseProvider.ice
index 18201e65d3c652bd02c6957bbaff50cb9e8f46cc..7eef5984e466173433e340cf45711be4fd187c95 100644
--- a/source/RobotAPI/interface/objectpose/ObjectPoseProvider.ice
+++ b/source/RobotAPI/interface/objectpose/ObjectPoseProvider.ice
@@ -37,7 +37,7 @@ module armarx
         struct ProviderInfo
         {
             ObjectPoseProvider* proxy;
-            ObjectTypeEnum objectType = AnyObject;
+            ObjectType objectType = AnyObject;
             armarx::data::ObjectIDSeq supportedObjects;
         };
         dictionary<string, ProviderInfo> ProviderInfoMap;
diff --git a/source/RobotAPI/interface/objectpose/object_pose_types.ice b/source/RobotAPI/interface/objectpose/object_pose_types.ice
index 0dc650c9b7bb6bf9b139714015ea55120a409f0d..7ce071730ed3f35b8f2e526c6bf585d000af73f8 100644
--- a/source/RobotAPI/interface/objectpose/object_pose_types.ice
+++ b/source/RobotAPI/interface/objectpose/object_pose_types.ice
@@ -24,23 +24,23 @@
 #pragma once
 
 #include <RobotAPI/interface/core/PoseBase.ice>
+#include <RobotAPI/interface/core/NameValueMap.ice>
 #include <RobotAPI/interface/ArmarXObjects/ArmarXObjectsTypes.ice>
 
 
 module armarx
 {
-    // Originally defined in <RobotAPI/interface/units/KinematicUnitInterface.ice>
-    dictionary<string, float> NameValueMap;
-
-
     // A struct's name cannot cannot differ only in capitalization from its immediately enclosing module name.
     module objpose
     {
-        enum ObjectTypeEnum
+        // ObjectTypeEnum is now renamed to ObjectType
+        enum ObjectType
         {
             AnyObject, KnownObject, UnknownObject
         };
 
+
+
         class AABB
         {
             Vector3Base center;
@@ -67,7 +67,7 @@ module armarx
                 /// Name of the providing component.
                 string providerName;
                 /// Known or unknown object.
-                ObjectTypeEnum objectType = AnyObject;
+                ObjectType objectType = AnyObject;
                 /// Whether object is static. Static objects don't decay.
                 bool isStatic = false;
 
@@ -100,7 +100,7 @@ module armarx
                 /// Name of the providing component.
                 string providerName;
                 /// Known or unknown object.
-                ObjectTypeEnum objectType = AnyObject;
+                ObjectType objectType = AnyObject;
                 /// Whether object is static. Static objects don't decay.
                 bool isStatic = false;
 
diff --git a/source/RobotAPI/interface/observers/GraspCandidateObserverInterface.ice b/source/RobotAPI/interface/observers/GraspCandidateObserverInterface.ice
index 5a59f5b4432e83a28977ca234b98bb9a5e07ddd6..b60aa19c3db3bd5d7f1a68937758e401745f3ef0 100644
--- a/source/RobotAPI/interface/observers/GraspCandidateObserverInterface.ice
+++ b/source/RobotAPI/interface/observers/GraspCandidateObserverInterface.ice
@@ -35,7 +35,7 @@ module armarx
         {
             string providerName = "*";
             float minimumSuccessProbability = 0;
-            ObjectTypeEnum objectType = AnyObject;
+            armarx::objpose::ObjectType objectType = AnyObject;
             ApertureType preshape = AnyAperture;
             ApproachType approach = AnyApproach;
 
diff --git a/source/RobotAPI/interface/units/GraspCandidateProviderInterface.ice b/source/RobotAPI/interface/units/GraspCandidateProviderInterface.ice
index ac4da1da07d1ac2c75526a2f98c32c547aa3d88d..6b45362c42cdc04ae6b02715112a2173483d91af 100644
--- a/source/RobotAPI/interface/units/GraspCandidateProviderInterface.ice
+++ b/source/RobotAPI/interface/units/GraspCandidateProviderInterface.ice
@@ -27,14 +27,17 @@
 #include <RobotAPI/interface/core/FramedPoseBase.ice>
 #include <ArmarXCore/interface/observers/VariantBase.ice>
 #include <ArmarXCore/interface/observers/RequestableService.ice>
+#include <RobotAPI/interface/objectpose/object_pose_types.ice>
 
 module armarx
 {
     module grasping
     {
-        enum ObjectTypeEnum {
+        // Grasping will now use ObjectType from armarx::objpose in <RobotAPI/interface/objectpose/object_pose_types.ice>
+        /*enum ObjectTypeEnum {
             AnyObject, KnownObject, UnknownObject
-        };
+        };*/
+
         enum ApproachType {
             AnyApproach, TopApproach, SideApproach
         };
@@ -79,6 +82,7 @@ module armarx
         {
             PoseBase graspPose;
             PoseBase robotPose;
+            PoseBase tcpPoseInHandRoot;
             Vector3Base approachVector;
 
             string sourceFrame;  // frame where graspPose is located
@@ -87,7 +91,7 @@ module armarx
 
             float graspSuccessProbability;
 
-            ObjectTypeEnum objectType = AnyObject;
+            armarx::objpose::ObjectType objectType = AnyObject;
             int groupNr = -1; // used to match candidates that belog together, e.g. from the same object or point cloud segment
             string providerName;
 
@@ -101,6 +105,8 @@ module armarx
             PoseBase graspPoseRight;
             PoseBase graspPoseLeft;
             PoseBase robotPose;
+            PoseBase tcpPoseInHandRootRight;
+            PoseBase tcpPoseInHandRootLeft;
 
             Vector3Base approachVectorRight;
             Vector3Base approachVectorLeft;
@@ -113,7 +119,7 @@ module armarx
 
             //float graspSuccessProbability;
 
-            ObjectTypeEnum objectType = AnyObject;
+            armarx::objpose::ObjectType objectType = AnyObject;
             int groupNr = -1; // used to match candidates that belog together, e.g. from the same object or point cloud segment
             string providerName;
 
@@ -130,7 +136,7 @@ module armarx
 
         class ProviderInfo
         {
-            ObjectTypeEnum objectType = AnyObject;
+            armarx::objpose::ObjectType objectType = AnyObject;
             StringVariantBaseMap currentConfig;
         };
 
diff --git a/source/RobotAPI/interface/units/KinematicUnitInterface.ice b/source/RobotAPI/interface/units/KinematicUnitInterface.ice
index 85edf827c17242010d6747f383a5aaac6d7eccc8..5321b009b55f944df51ba9d2e0b826eacd15e903 100644
--- a/source/RobotAPI/interface/units/KinematicUnitInterface.ice
+++ b/source/RobotAPI/interface/units/KinematicUnitInterface.ice
@@ -29,6 +29,7 @@
 #include <ArmarXCore/interface/core/UserException.ice>
 #include <ArmarXCore/interface/core/BasicTypes.ice>
 
+#include <RobotAPI/interface/core/NameValueMap.ice>
 #include <RobotAPI/interface/skills/SkillObserverInterface.ice>
 
 module armarx
@@ -124,10 +125,7 @@ module armarx
     {
         Ice::StringSeq nodes;
     };
-	/**
-	* [NameValueMap] defined. This data container is mostly used to assign values to e.g. joints which are identified by name.
-	**/
-    dictionary<string, float> NameValueMap;
+
     /**
     * [NameControlModeMap] defined. This data container is mostly used to assign control modes to e.g. joints which are identified by name.
     **/
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectPose.h b/source/RobotAPI/libraries/ArmarXObjects/ObjectPose.h
index 23d54901fbf7fa5db2c222a09c268da111a22512..ca5754aa0dff87780e913f7c255bf2b9067e2258 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/ObjectPose.h
+++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectPose.h
@@ -50,7 +50,7 @@ namespace armarx::objpose
         /// Name of the providing component.
         std::string providerName;
         /// Known or unknown object.
-        ObjectTypeEnum objectType = AnyObject;
+        ObjectType objectType = AnyObject;
         /// Whether object is static. Static objects don't decay.
         bool isStatic = false;
 
diff --git a/source/RobotAPI/libraries/ArmarXObjects/aron_conversions/objpose.cpp b/source/RobotAPI/libraries/ArmarXObjects/aron_conversions/objpose.cpp
index a639223a050b5473c69302816ee1a46adceb505a..5fc8ebdea395c6b8bcd149c14fcb2fe567a4ace8 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/aron_conversions/objpose.cpp
+++ b/source/RobotAPI/libraries/ArmarXObjects/aron_conversions/objpose.cpp
@@ -24,33 +24,33 @@ void armarx::objpose::toAron(arondto::ObjectAttachmentInfo& dto, const ObjectAtt
     dto.poseInFrame = bo.poseInFrame;
 }
 
-void armarx::objpose::fromAron(const arondto::ObjectType& dto, ObjectTypeEnum& bo)
+void armarx::objpose::fromAron(const arondto::ObjectType& dto, ObjectType& bo)
 {
     switch (dto.value)
     {
         case arondto::ObjectType::AnyObject:
-            bo = ObjectTypeEnum::AnyObject;
+            bo = ObjectType::AnyObject;
             return;
         case arondto::ObjectType::KnownObject:
-            bo = ObjectTypeEnum::KnownObject;
+            bo = ObjectType::KnownObject;
             return;
         case arondto::ObjectType::UnknownObject:
-            bo = ObjectTypeEnum::UnknownObject;
+            bo = ObjectType::UnknownObject;
             return;
     }
     ARMARX_UNEXPECTED_ENUM_VALUE(arondto::ObjectType, dto.value);
 }
-void armarx::objpose::toAron(arondto::ObjectType& dto, const ObjectTypeEnum& bo)
+void armarx::objpose::toAron(arondto::ObjectType& dto, const ObjectType& bo)
 {
     switch (bo)
     {
-        case ObjectTypeEnum::AnyObject:
+        case ObjectType::AnyObject:
             dto.value = arondto::ObjectType::AnyObject;
             return;
-        case ObjectTypeEnum::KnownObject:
+        case ObjectType::KnownObject:
             dto.value = arondto::ObjectType::KnownObject;
             return;
-        case ObjectTypeEnum::UnknownObject:
+        case ObjectType::UnknownObject:
             dto.value = arondto::ObjectType::UnknownObject;
             return;
     }
diff --git a/source/RobotAPI/libraries/ArmarXObjects/aron_conversions/objpose.h b/source/RobotAPI/libraries/ArmarXObjects/aron_conversions/objpose.h
index 2e3f5901bfaf45f0cf131f609d46a18d67ace532..6117009c5ca366ad0fa0082161f3ee67d39c2892 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/aron_conversions/objpose.h
+++ b/source/RobotAPI/libraries/ArmarXObjects/aron_conversions/objpose.h
@@ -18,8 +18,8 @@ namespace armarx::objpose
     void fromAron(const arondto::ObjectAttachmentInfo& dto, ObjectAttachmentInfo& bo);
     void toAron(arondto::ObjectAttachmentInfo& dto, const ObjectAttachmentInfo& bo);
 
-    void fromAron(const arondto::ObjectType& dto, ObjectTypeEnum& bo);
-    void toAron(arondto::ObjectType& dto, const ObjectTypeEnum& bo);
+    void fromAron(const arondto::ObjectType& dto, ObjectType& bo);
+    void toAron(arondto::ObjectType& dto, const ObjectType& bo);
 
     void fromAron(const arondto::ObjectPose& dto, ObjectPose& bo);
     void toAron(arondto::ObjectPose& dto, const ObjectPose& bo);
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.cpp b/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.cpp
index 6715760410010d3817c52d677a0a64036fb828c6..ccbae7e21c426f92d946dd6744168a04f2c70e7c 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.cpp
+++ b/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.cpp
@@ -82,11 +82,11 @@ armarx::data::ObjectIDSeq armarx::toIce(const std::vector<ObjectID>& ids)
 
 namespace armarx
 {
-    const simox::meta::EnumNames<objpose::ObjectTypeEnum> objpose::ObjectTypeEnumNames =
+    const simox::meta::EnumNames<objpose::ObjectType> objpose::ObjectTypeNames =
     {
-        { objpose::ObjectTypeEnum::AnyObject, "AnyObject" },
-        { objpose::ObjectTypeEnum::KnownObject, "KnownObject" },
-        { objpose::ObjectTypeEnum::UnknownObject, "UnknownObject" }
+        { objpose::ObjectType::AnyObject, "AnyObject" },
+        { objpose::ObjectType::KnownObject, "KnownObject" },
+        { objpose::ObjectType::UnknownObject, "UnknownObject" }
     };
 
     objpose::AABB objpose::toIce(const simox::AxisAlignedBoundingBox& aabb)
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.h b/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.h
index 39ebc20500722518472c9c755a3238d581916fd0..429d6246c18f7a36769d6c3d686c12c175cd8b8f 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.h
+++ b/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.h
@@ -41,7 +41,7 @@ namespace armarx
 
 namespace armarx::objpose
 {
-    extern const simox::meta::EnumNames<objpose::ObjectTypeEnum> ObjectTypeEnumNames;
+    extern const simox::meta::EnumNames<objpose::ObjectType> ObjectTypeNames;
 
     objpose::AABB toIce(const simox::AxisAlignedBoundingBox& aabb);
 
diff --git a/source/RobotAPI/libraries/ArmarXObjects/json_conversions.cpp b/source/RobotAPI/libraries/ArmarXObjects/json_conversions.cpp
index 389aae5e2ddc59fdf533bf0a43309f89536c1b6e..3888855892a95cecb6ea5fecc55e63763c894f6a 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/json_conversions.cpp
+++ b/source/RobotAPI/libraries/ArmarXObjects/json_conversions.cpp
@@ -26,7 +26,7 @@ void armarx::from_json(const nlohmann::json& j, ObjectID& id)
 void armarx::objpose::to_json(nlohmann::json& j, const ObjectPose& op)
 {
     j["providerName"] = op.providerName;
-    j["objectType"] = ObjectTypeEnumNames.to_name(op.objectType);
+    j["objectType"] = ObjectTypeNames.to_name(op.objectType);
 
     j["objectID"] = op.objectID;
 
@@ -51,7 +51,7 @@ void armarx::objpose::to_json(nlohmann::json& j, const ObjectPose& op)
 void armarx::objpose::from_json(const nlohmann::json& j, ObjectPose& op)
 {
     op.providerName = j.at("providerName");
-    op.objectType = ObjectTypeEnumNames.from_name(j.at("objectType"));
+    op.objectType = ObjectTypeNames.from_name(j.at("objectType"));
 
     op.objectID = j.at("objectID");
 
diff --git a/source/RobotAPI/libraries/GraspingUtility/CMakeLists.txt b/source/RobotAPI/libraries/GraspingUtility/CMakeLists.txt
index e88102be2b34c52d63b73ff876ab6ba8e778f1f5..cce3efe6d385799d6496d39d0d0ca4362177403e 100644
--- a/source/RobotAPI/libraries/GraspingUtility/CMakeLists.txt
+++ b/source/RobotAPI/libraries/GraspingUtility/CMakeLists.txt
@@ -6,15 +6,30 @@ armarx_set_target("Library: ${LIB_NAME}")
 armarx_add_library(
     LIBS     RobotAPICore
              RobotStatechartHelpers # Contains RobotNameHelper
+             RobotAPI::armem
+             RobotAPI::ArmarXObjects
     SOURCES  box_to_grasp_candidates.cpp
              grasp_candidate_drawer.cpp
              GraspCandidateHelper.cpp
              BimanualGraspCandidateHelper.cpp
+             aron_conversions.cpp
+             GraspCandidateWriter.cpp
+             GraspCandidateReader.cpp
     HEADERS  box_to_grasp_candidates.h
              box_to_grasp_candidates.ipp
              grasp_candidate_drawer.h
              GraspCandidateHelper.h
              BimanualGraspCandidateHelper.h
+             aron_conversions.h
+             GraspCandidateWriter.h
+             GraspCandidateReader.h
 )
+armarx_enable_aron_file_generation_for_target(
+    TARGET_NAME
+        "${LIB_NAME}"
+    ARON_FILES
+        aron/GraspCandidate.xml
+)
+
 
 
diff --git a/source/RobotAPI/libraries/GraspingUtility/GraspCandidateReader.cpp b/source/RobotAPI/libraries/GraspingUtility/GraspCandidateReader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9ff7402b4b2db5b833adabcb48f6d5ffb554ec39
--- /dev/null
+++ b/source/RobotAPI/libraries/GraspingUtility/GraspCandidateReader.cpp
@@ -0,0 +1,301 @@
+#include "GraspCandidateReader.h"
+
+#include <RobotAPI/libraries/GraspingUtility/aron/GraspCandidate.aron.generated.h>
+#include <RobotAPI/libraries/GraspingUtility/aron_conversions.h>
+#include <RobotAPI/libraries/armem/core/error/mns.h>
+#include <RobotAPI/libraries/armem/util/util.h>
+#include <RobotAPI/libraries/armem/core/wm/visitor/FunctionalVisitor.h>
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
+
+namespace armarx::armem
+{
+    GraspCandidateReader::GraspCandidateReader(armem::client::MemoryNameSystem& memoryNameSystem)
+        : memoryNameSystem(memoryNameSystem)
+    {
+    }
+
+    void GraspCandidateReader::connect()
+    {
+        // Wait for the memory to become available and add it as dependency.
+        ARMARX_IMPORTANT << "GraspCandidateReader: Waiting for memory '"
+                         << properties.memoryName << "' ...";
+        try
+        {
+            memoryReader = memoryNameSystem.useReader(properties.memoryName);
+            ARMARX_IMPORTANT << "GraspCandidateReader: Connected to memory '"
+                             << properties.memoryName;
+        }
+        catch (const armem::error::CouldNotResolveMemoryServer& e)
+        {
+            ARMARX_ERROR << e.what();
+            return;
+        }
+
+
+    }
+
+
+
+
+    armarx::grasping::GraspCandidate asGraspCandidate(const armem::wm::EntityInstance& instance)
+    {
+        armarx::grasping::GraspCandidate candidate;
+
+        grasping::arondto::GraspCandidate aronTransform;
+
+        aronTransform.fromAron(instance.data());
+
+        fromAron(aronTransform, candidate);
+
+        return candidate;
+    }
+
+    armarx::grasping::BimanualGraspCandidate asBimanualGraspCandidate(const armem::wm::EntityInstance& instance)
+    {
+        armarx::grasping::BimanualGraspCandidate candidate;
+
+        grasping::arondto::BimanualGraspCandidate aronTransform;
+        aronTransform.fromAron(instance.data());
+
+        fromAron(aronTransform, candidate);
+
+        return candidate;
+    }
+
+
+    grasping::GraspCandidatePtr GraspCandidateReader::queryGraspCandidateInstanceByID(const armem::MemoryID& id) const
+    {
+        armem::client::query::Builder qb;
+
+        ARMARX_DEBUG << "Query for memory name: " << properties.memoryName;
+
+        qb.singleEntitySnapshot(id.getEntitySnapshotID());
+
+        const armem::client::QueryResult qResult =
+            memoryReader.query(qb.buildQueryInput());
+
+        if (!qResult.success)
+        {
+            // todo catch in provider
+            throw armem::error::QueryFailed(properties.memoryName, qResult.errorMessage);
+        }
+
+
+        armarx::grasping::GraspCandidatePtr candidate;
+
+        armem::wm::FunctionalVisitor visitor;
+        visitor.instanceConstFn = [id, &candidate](armem::wm::EntityInstance const & instance)
+        {
+            if (instance.id() == id)
+            {
+                candidate = new grasping::GraspCandidate(asGraspCandidate(instance));
+            }
+            return true;
+        };
+
+        visitor.applyTo(qResult.memory);
+
+        return candidate;
+    }
+
+    grasping::BimanualGraspCandidatePtr GraspCandidateReader::queryBimanualGraspCandidateInstanceByID(
+            const armem::MemoryID& id) const
+    {
+        armem::client::query::Builder qb;
+
+        ARMARX_DEBUG << "Query for memory name: " << properties.memoryName;
+
+        qb.singleEntitySnapshot(id.getEntitySnapshotID());
+
+        const armem::client::QueryResult qResult =
+            memoryReader.query(qb.buildQueryInput());
+
+        if (!qResult.success)
+        {
+            // todo catch in provider
+            throw armem::error::QueryFailed(properties.memoryName, qResult.errorMessage);
+        }
+
+
+        armarx::grasping::BimanualGraspCandidatePtr candidate;
+
+        armem::wm::FunctionalVisitor visitor;
+        visitor.instanceConstFn = [id, &candidate](armem::wm::EntityInstance const & instance)
+        {
+            if (instance.id() == id)
+            {
+                candidate = new grasping::BimanualGraspCandidate(asBimanualGraspCandidate(instance));
+            }
+            return true;
+        };
+
+        visitor.applyTo(qResult.memory);
+
+        return candidate;
+    }
+
+    std::map<std::string, grasping::GraspCandidatePtr> GraspCandidateReader::queryLatestGraspCandidateEntity(
+            const std::string& provider, const std::string& entity) const
+    {
+        armem::client::query::Builder qb;
+
+        ARMARX_DEBUG << "Query for memory name: " << properties.memoryName;
+
+        qb
+        .coreSegments().withName(properties.graspCandidateMemoryName)
+        .providerSegments().withName(provider)
+        .entities().withName(entity)
+        .snapshots().latest();
+
+        const armem::client::QueryResult qResult =
+            memoryReader.query(qb.buildQueryInput());
+
+        return getGraspCandidatesFromResultSet(qResult);
+    }
+
+    std::map<std::string, grasping::BimanualGraspCandidatePtr> GraspCandidateReader::queryLatestBimanualGraspCandidateEntity(
+            const std::string& provider, const std::string& entity) const
+    {
+        armem::client::query::Builder qb;
+
+        ARMARX_DEBUG << "Query for memory name: " << properties.memoryName;
+
+        qb
+        .coreSegments().withName(properties.bimanualGraspCandidateMemoryName)
+        .providerSegments().withName(provider)
+        .entities().withName(entity)
+        .snapshots().latest();
+
+        const armem::client::QueryResult qResult =
+            memoryReader.query(qb.buildQueryInput());
+
+        return getBimanualGraspCandidatesFromResultSet(qResult);
+    }
+
+    std::map<std::string, grasping::GraspCandidatePtr> GraspCandidateReader::queryLatestGraspCandidates(
+            const std::string& provider) const
+    {
+
+        armem::client::query::Builder qb;
+
+        ARMARX_DEBUG << "Query for memory name: " << properties.memoryName;
+
+
+        if (provider != "")
+        {
+            qb
+            .coreSegments().withName(properties.graspCandidateMemoryName)
+            .providerSegments().withName(provider)
+            .entities().all()
+            .snapshots().latest();
+        }
+        else
+        {
+            qb
+            .coreSegments().withName(properties.graspCandidateMemoryName)
+            .providerSegments().all()
+            .entities().all()
+            .snapshots().latest();
+        }
+
+        const armem::client::QueryResult qResult =
+            memoryReader.query(qb.buildQueryInput());
+
+        return getGraspCandidatesFromResultSet(qResult);
+    }
+
+    std::map<std::string, grasping::BimanualGraspCandidatePtr> GraspCandidateReader::queryLatestBimanualGraspCandidates(
+            const std::string& provider) const
+    {
+        armem::client::query::Builder qb;
+
+        ARMARX_DEBUG << "Query for memory name: " << properties.memoryName;
+
+
+        if (provider != "")
+        {
+            qb
+            .coreSegments().withName(properties.bimanualGraspCandidateMemoryName)
+            .providerSegments().withName(provider)
+            .entities().all()
+            .snapshots().latest();
+        }
+        else
+        {
+            qb
+            .coreSegments().withName(properties.bimanualGraspCandidateMemoryName)
+            .providerSegments().all()
+            .entities().all()
+            .snapshots().latest();
+        }
+
+        const armem::client::QueryResult qResult =
+            memoryReader.query(qb.buildQueryInput());
+
+        return getBimanualGraspCandidatesFromResultSet(qResult);
+    }
+
+
+    void GraspCandidateReader::registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def)
+    {
+        ARMARX_DEBUG << "GraspCandidateReader: registerPropertyDefinitions";
+        registerPropertyDefinitions(def);
+
+        const std::string prefix = propertyPrefix;
+
+        def->optional(properties.graspCandidateMemoryName, prefix + "GraspCandidateMemoryName",
+                      "Name of the grasping memory core segment to use.");
+
+        def->optional(properties.memoryName, prefix + "MemoryName");
+    }
+
+    std::map<std::string, grasping::GraspCandidatePtr> GraspCandidateReader::getGraspCandidatesFromResultSet(
+            const armem::client::QueryResult& qResult) const
+    {
+        if (!qResult.success)
+        {
+            throw armem::error::QueryFailed(properties.memoryName, qResult.errorMessage);
+        }
+
+
+        std::map<std::string, armarx::grasping::GraspCandidatePtr> candidates;
+
+        armem::wm::FunctionalVisitor visitor;
+        visitor.instanceConstFn = [&candidates](armem::wm::EntityInstance const & instance)
+        {
+            candidates[instance.id().str()] = new grasping::GraspCandidate(asGraspCandidate(instance));
+            return true;
+        };
+
+        visitor.applyTo(qResult.memory);
+
+
+        return candidates;
+    }
+
+    std::map<std::string, grasping::BimanualGraspCandidatePtr> GraspCandidateReader::getBimanualGraspCandidatesFromResultSet(
+            const armem::client::QueryResult& qResult) const
+    {
+        if (!qResult.success)
+        {
+            throw armem::error::QueryFailed(properties.memoryName, qResult.errorMessage);
+        }
+
+
+        std::map<std::string, armarx::grasping::BimanualGraspCandidatePtr> candidates;
+
+        armem::wm::FunctionalVisitor visitor;
+        visitor.instanceConstFn = [&candidates](armem::wm::EntityInstance const & instance)
+        {
+            candidates[instance.id().str()] = new grasping::BimanualGraspCandidate(asBimanualGraspCandidate(instance));
+            return true;
+        };
+
+        visitor.applyTo(qResult.memory);
+
+
+        return candidates;
+    }
+
+
+}
diff --git a/source/RobotAPI/libraries/GraspingUtility/GraspCandidateReader.h b/source/RobotAPI/libraries/GraspingUtility/GraspCandidateReader.h
new file mode 100644
index 0000000000000000000000000000000000000000..0a1604afdb9ca58c93ce52628cee61e7ee647dcc
--- /dev/null
+++ b/source/RobotAPI/libraries/GraspingUtility/GraspCandidateReader.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <RobotAPI/libraries/armem/client/Reader.h>
+#include <RobotAPI/libraries/armem/client.h>
+#include <RobotAPI/interface/units/GraspCandidateProviderInterface.h>
+
+namespace armarx::armem
+{
+
+    class GraspCandidateReader
+    {
+    public:
+        GraspCandidateReader(armem::client::MemoryNameSystem& memoryNameSystem);
+
+        void connect();
+
+        grasping::GraspCandidatePtr queryGraspCandidateInstanceByID(armem::MemoryID const& id) const;
+
+        grasping::BimanualGraspCandidatePtr queryBimanualGraspCandidateInstanceByID(armem::MemoryID const& id) const;
+
+        std::map<std::string, grasping::GraspCandidatePtr> queryLatestGraspCandidateEntity(
+                std::string const& provider, std::string const& entity) const;
+
+        std::map<std::string, grasping::BimanualGraspCandidatePtr> queryLatestBimanualGraspCandidateEntity(
+                std::string const& provider, std::string const& entity) const;
+
+        std::map<std::string, grasping::GraspCandidatePtr> queryLatestGraspCandidates(
+                std::string const& provider = "") const;
+
+        std::map<std::string, grasping::BimanualGraspCandidatePtr> queryLatestBimanualGraspCandidates(
+                std::string const& provider = "") const;
+
+
+
+        void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def);
+
+
+    private:
+
+        std::map<std::string, grasping::GraspCandidatePtr> getGraspCandidatesFromResultSet(
+                armem::client::QueryResult const& qResult) const;
+
+        std::map<std::string, grasping::BimanualGraspCandidatePtr> getBimanualGraspCandidatesFromResultSet(
+                armem::client::QueryResult const& qResult) const;
+
+        armem::client::Reader memoryReader;
+
+        // Properties
+        struct Properties
+        {
+            std::string memoryName = "Grasp";
+            std::string graspCandidateMemoryName = "GraspCandidate";
+            std::string bimanualGraspCandidateMemoryName = "BimanualGraspCandidate";
+        } properties;
+
+
+        const std::string propertyPrefix = "mem.grasping.";
+
+        armem::client::MemoryNameSystem& memoryNameSystem;
+
+    };
+
+}
diff --git a/source/RobotAPI/libraries/GraspingUtility/GraspCandidateWriter.cpp b/source/RobotAPI/libraries/GraspingUtility/GraspCandidateWriter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9c998ec1bcf43e235a8eee2706205ea15efe9964
--- /dev/null
+++ b/source/RobotAPI/libraries/GraspingUtility/GraspCandidateWriter.cpp
@@ -0,0 +1,190 @@
+#include "GraspCandidateWriter.h"
+#include <RobotAPI/libraries/GraspingUtility/aron/GraspCandidate.aron.generated.h>
+#include <RobotAPI/libraries/GraspingUtility/aron_conversions.h>
+#include <RobotAPI/libraries/armem/core/error/mns.h>
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
+
+namespace armarx::armem
+{
+
+
+    GraspCandidateWriter::GraspCandidateWriter(armem::client::MemoryNameSystem& memoryNameSystem)
+        : memoryNameSystem(memoryNameSystem)
+    {
+    }
+
+    void GraspCandidateWriter::connect()
+    {
+        // Wait for the memory to become available and add it as dependency.
+        ARMARX_IMPORTANT << "GraspCandidateWriter: Waiting for memory '" << properties.memoryName
+                         << "' ...";
+        try
+        {
+            memoryWriter = memoryNameSystem.useWriter(properties.memoryName);
+            ARMARX_IMPORTANT << "GraspCandidateWriter: Connected to memory '" << properties.memoryName << "'";
+        }
+        catch (const armem::error::CouldNotResolveMemoryServer& e)
+        {
+            ARMARX_ERROR << e.what();
+            return;
+        }
+
+    }
+
+    void GraspCandidateWriter::registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def)
+    {
+        ARMARX_DEBUG << "GraspCandidateWriter: registerPropertyDefinitions";
+
+        const std::string prefix = propertyPrefix;
+
+        def->optional(properties.graspMemoryName, prefix + "GraspMemoryName",
+                      "Name of the grasping memory core segment to use.");
+        def->optional(properties.bimanualGraspMemoryName, prefix + "BimanualGraspMemoryName",
+                      "Name of the bimanual grasping memory core segment to use.");
+
+        def->optional(properties.memoryName, prefix + "MemoryName");
+
+    }
+
+    bool GraspCandidateWriter::commitGraspCandidate(const armarx::grasping::GraspCandidate& candidate,
+            const armem::Time& timestamp, const std::string& provider)
+    {
+        armarx::grasping::arondto::GraspCandidate aronGraspCandidate;
+        std::string objectName = "UnknownObject";
+        if (candidate.sourceInfo)
+        {
+            objectName = candidate.sourceInfo->referenceObjectName;
+        }
+
+
+        toAron(aronGraspCandidate, candidate);
+        auto dict = aronGraspCandidate.toAron();
+
+        return commitToMemory({dict}, provider, objectName, timestamp, properties.graspMemoryName);
+    }
+
+    bool GraspCandidateWriter::commitBimanualGraspCandidate(const armarx::grasping::BimanualGraspCandidate& candidate,
+            const armem::Time& timestamp, const std::string& provider)
+    {
+        armarx::grasping::arondto::BimanualGraspCandidate aronGraspCandidate;
+
+        std::string objectName = "UnknownObject";
+        if (candidate.sourceInfo)
+        {
+            objectName = candidate.sourceInfo->referenceObjectName;
+        }
+
+        toAron(aronGraspCandidate, candidate);
+
+        auto dict = aronGraspCandidate.toAron();
+
+        return commitToMemory({dict}, provider, objectName, timestamp, properties.bimanualGraspMemoryName);
+    }
+
+    bool GraspCandidateWriter::commitGraspCandidateSeq(const armarx::grasping::GraspCandidateSeq& candidates,
+            const armem::Time& timestamp, const std::string& provider)
+    {
+
+        bool success = true;
+
+        std::map<std::string, std::vector<armarx::aron::datanavigator::DictNavigatorPtr>> updates = {};
+        armarx::grasping::arondto::GraspCandidate aronGraspCandidate;
+
+        for (armarx::grasping::GraspCandidatePtr candidate : candidates)
+        {
+            std::string objectName = "UnknownObject";
+            if (candidate->sourceInfo)
+            {
+                objectName = candidate->sourceInfo->referenceObjectName;
+            }
+            toAron(aronGraspCandidate, *candidate);
+
+            updates[objectName].push_back(aronGraspCandidate.toAron());
+        }
+
+        for (std::pair<std::string, std::vector<armarx::aron::datanavigator::DictNavigatorPtr>> update : updates)
+        {
+
+            if (! commitToMemory(update.second, provider, update.first, timestamp, properties.graspMemoryName))
+            {
+                success = false;
+            }
+        }
+        return success;
+    }
+
+    bool GraspCandidateWriter::commitBimanualGraspCandidateSeq(
+        const armarx::grasping::BimanualGraspCandidateSeq& candidates, const armem::Time& timestamp,
+        const std::string& provider)
+    {
+        bool success = true;
+
+        std::map<std::string, std::vector<armarx::aron::datanavigator::DictNavigatorPtr>> updates = {};
+        armarx::grasping::arondto::BimanualGraspCandidate aronGraspCandidate;
+
+        for (armarx::grasping::BimanualGraspCandidatePtr candidate : candidates)
+        {
+            std::string objectName = "UnknownObject";
+            if (candidate->sourceInfo)
+            {
+                objectName = candidate->sourceInfo->referenceObjectName;
+            }
+            toAron(aronGraspCandidate, *candidate);
+            updates[objectName].push_back(aronGraspCandidate.toAron());
+        }
+
+        for (std::pair<std::string, std::vector<armarx::aron::datanavigator::DictNavigatorPtr>> update : updates)
+        {
+
+            if (! commitToMemory(update.second, provider, update.first, timestamp, properties.bimanualGraspMemoryName))
+            {
+                success = false;
+            }
+        }
+        return success;
+    }
+
+    bool GraspCandidateWriter::commitToMemory(const std::vector<armarx::aron::datanavigator::DictNavigatorPtr>& instances,
+            const std::string& providerName, const std::string& entityName, const armem::Time& timestamp,
+            const std::string& coreMemoryName)
+    {
+        std::lock_guard g{memoryWriterMutex};
+
+        const auto result =
+            memoryWriter.addSegment(coreMemoryName, providerName);
+
+        if (not result.success)
+        {
+            ARMARX_ERROR << result.errorMessage;
+
+            // TODO(fabian.reister): message
+            return false;
+        }
+
+        const auto iceTimestamp = Time::microSeconds(timestamp.toMicroSeconds());
+
+        const auto providerId = armem::MemoryID(result.segmentID);
+        const auto entityID =
+            providerId.withEntityName(entityName).withTimestamp(iceTimestamp);
+
+        armem::EntityUpdate update;
+        update.entityID = entityID;
+
+
+
+        update.instancesData = instances;
+        update.timeCreated = iceTimestamp;
+
+        ARMARX_DEBUG << "Committing " << update << " at time " << iceTimestamp;
+        armem::EntityUpdateResult updateResult = memoryWriter.commit(update);
+
+        ARMARX_DEBUG << updateResult;
+
+        if (not updateResult.success)
+        {
+            ARMARX_ERROR << updateResult.errorMessage;
+        }
+
+        return updateResult.success;
+    }
+}
diff --git a/source/RobotAPI/libraries/GraspingUtility/GraspCandidateWriter.h b/source/RobotAPI/libraries/GraspingUtility/GraspCandidateWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..10dc74821d92d7f7d8005e5ad347df67be9da777
--- /dev/null
+++ b/source/RobotAPI/libraries/GraspingUtility/GraspCandidateWriter.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <RobotAPI/libraries/armem/client/Writer.h>
+#include <RobotAPI/libraries/armem/client.h>
+#include <mutex>
+
+#include <RobotAPI/interface/units/GraspCandidateProviderInterface.h>
+#include <ArmarXCore/core/application/properties/forward_declarations.h>
+
+namespace armarx::armem
+{
+    class GraspCandidateWriter
+    {
+    public:
+        GraspCandidateWriter(armem::client::MemoryNameSystem& memoryNameSystem);
+
+        void connect();
+
+        void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def);
+
+        bool commitGraspCandidate(const armarx::grasping::GraspCandidate& candidate,
+                                  const armem::Time& timestamp, const std::string& provider);
+        bool commitBimanualGraspCandidate(const armarx::grasping::BimanualGraspCandidate& candidate,
+                                          const armem::Time& timestamp, const std::string& provider);
+
+        bool commitGraspCandidateSeq(const armarx::grasping::GraspCandidateSeq& candidates,
+                                     const armem::Time& timestamp, const std::string& provider);
+        bool commitBimanualGraspCandidateSeq(const armarx::grasping::BimanualGraspCandidateSeq& candidates,
+                                             const armem::Time& timestamp, const std::string& provider);
+
+
+
+    private:
+
+        bool commitToMemory(const std::vector<armarx::aron::datanavigator::DictNavigatorPtr>& instances,
+                            const std::string& providerName, const std::string& entityName, const armem::Time& timestamp,
+                            const std::string& coreMemoryName);
+
+        armem::client::MemoryNameSystem& memoryNameSystem;
+
+        armem::client::Writer memoryWriter;
+
+        struct Properties
+        {
+            std::string memoryName         = "Grasp";
+            std::string graspMemoryName  = "GraspCandidate";
+            std::string bimanualGraspMemoryName = "BimanualGraspCandidate";
+        } properties;
+
+
+        std::mutex memoryWriterMutex;
+
+        const std::string propertyPrefix = "mem.grasping.";
+
+    };
+
+
+}
diff --git a/source/RobotAPI/libraries/GraspingUtility/aron/GraspCandidate.xml b/source/RobotAPI/libraries/GraspingUtility/aron/GraspCandidate.xml
new file mode 100644
index 0000000000000000000000000000000000000000..592c9fe677ecb0e8ad9b4e55c59a9560f336f439
--- /dev/null
+++ b/source/RobotAPI/libraries/GraspingUtility/aron/GraspCandidate.xml
@@ -0,0 +1,258 @@
+<!-- ARON DTO of armarx::objpose::ObjectPose. -->
+<?xml version="1.0" encoding="UTF-8" ?>
+<AronTypeDefinition>
+    <CodeIncludes>
+        <Include include="<Eigen/Core>" />
+        <Include include="<RobotAPI/libraries/ArmarXObjects/aron/ObjectType.aron.generated.h>" />
+    </CodeIncludes>
+    <AronIncludes>
+        <Include include="<RobotAPI/libraries/ArmarXObjects/aron/ObjectType.xml>" />
+    </AronIncludes>
+    <GenerateTypes>
+
+        <IntEnum name="armarx::grasping::arondto::ApproachType">
+            <EnumValue key="AnyApproach" value="0" />
+            <EnumValue key="TopApproach" value="1" />
+            <EnumValue key="SideApproach" value="2" />
+        </IntEnum>
+
+        <IntEnum name="armarx::grasping::arondto::ApertureType">
+            <EnumValue key="AnyAperture" value="0" />
+            <EnumValue key="OpenAperture" value="1" />
+            <EnumValue key="PreshapedAperture" value="2" />
+        </IntEnum>
+
+
+        <Object name="armarx::grasping::arondto::BoundingBox">
+            <ObjectChild key='center'>
+                <Position />
+            </ObjectChild>
+            <ObjectChild key='ha1'>
+                <Position />
+            </ObjectChild>
+            <ObjectChild key='ha2'>
+                <Position />
+            </ObjectChild>
+            <ObjectChild key='ha3'>
+                <Position />
+            </ObjectChild>
+        </Object>
+
+        <Object name="armarx::grasping::arondto::GraspCandidateSourceInfo">
+            <ObjectChild key='referenceObjectPose'>
+                <Pose />
+            </ObjectChild>
+            <ObjectChild key='referenceObjectName'>
+                <string />
+            </ObjectChild>
+            <ObjectChild key='segmentationLabelID'>
+                <int />
+            </ObjectChild>
+            <ObjectChild key='bbox'>
+                <armarx::grasping::arondto::BoundingBox />
+            </ObjectChild>
+        </Object>
+
+        <Object name="armarx::grasping::arondto::GraspCandidateExecutionHints">
+            <ObjectChild key='preshape'>
+                <armarx::grasping::arondto::ApertureType />
+            </ObjectChild>
+            <ObjectChild key='approach'>
+                <armarx::grasping::arondto::ApproachType />
+            </ObjectChild>
+            <ObjectChild key='graspTrajectoryName'>
+                <string />
+            </ObjectChild>
+        </Object>
+
+        <Object name="armarx::grasping::arondto::GraspCandidateReachabilityInfo">
+            <ObjectChild key='reachable'>
+                <bool />
+            </ObjectChild>
+            <ObjectChild key='minimumJointLimitMargin'>
+                <float />
+            </ObjectChild>
+            <ObjectChild key='jointLimitMargins'>
+                <List>
+                    <Float />
+                </List>
+            </ObjectChild>
+            <ObjectChild key='maxPosError'>
+                <float />
+            </ObjectChild>
+            <ObjectChild key='maxOriError'>
+                <float />
+            </ObjectChild>
+        </Object>
+
+        <Object name='armarx::grasping::arondto::GraspCandidate'>
+
+            <ObjectChild key='graspPose'>
+                <Pose />
+            </ObjectChild>
+
+            <ObjectChild key='robotPose'>
+                <Pose />
+            </ObjectChild>
+
+            <ObjectChild key='tcpPoseInHandRoot'>
+                <Pose />
+            </ObjectChild>
+
+            <ObjectChild key='approachVector'>
+                <Position />
+            </ObjectChild>
+
+            <ObjectChild key='sourceFrame'>
+                <string />
+            </ObjectChild>
+
+            <ObjectChild key='targetFrame'>
+                <string />
+            </ObjectChild>
+
+            <ObjectChild key='side'>
+                <string />
+            </ObjectChild>
+
+            <ObjectChild key='graspSuccessProbability'>
+                <float />
+            </ObjectChild>
+
+            <ObjectChild key='objectType'>
+               <armarx::objpose::arondto::ObjectType />
+            </ObjectChild>
+
+            <ObjectChild key='groupNr'>
+                <int />
+            </ObjectChild>
+
+            <ObjectChild key='providerName'>
+                <string />
+            </ObjectChild>
+
+            <ObjectChild key='sourceInfoValid'>
+                <bool />
+            </ObjectChild>
+            <ObjectChild key='sourceInfo'>
+                <armarx::grasping::arondto::GraspCandidateSourceInfo />
+            </ObjectChild>
+
+            <ObjectChild key='executionHintsValid'>
+                <bool />
+            </ObjectChild>
+            <ObjectChild key='executionHints'>
+                <armarx::grasping::arondto::GraspCandidateExecutionHints />
+            </ObjectChild>
+
+            <ObjectChild key='reachabilityInfoValid'>
+                <bool />
+            </ObjectChild>
+            <ObjectChild key='reachabilityInfo'>
+                <armarx::grasping::arondto::GraspCandidateReachabilityInfo />
+            </ObjectChild>
+
+        </Object>
+
+        <Object name='armarx::grasping::arondto::BimanualGraspCandidate'>
+
+            <ObjectChild key='graspPoseRight'>
+                <Pose />
+            </ObjectChild>
+
+            <ObjectChild key='graspPoseLeft'>
+                <Pose />
+            </ObjectChild>
+
+            <ObjectChild key='robotPose'>
+                <Pose />
+            </ObjectChild>
+
+            <ObjectChild key='tcpPoseInHandRootRight'>
+                <Pose />
+            </ObjectChild>
+
+            <ObjectChild key='tcpPoseInHandRootLeft'>
+                <Pose />
+            </ObjectChild>
+
+            <ObjectChild key='approachVectorRight'>
+                <Position />
+            </ObjectChild>
+
+            <ObjectChild key='approachVectorLeft'>
+                <Position />
+            </ObjectChild>
+
+            <ObjectChild key='inwardsVectorRight'>
+                <Position />
+            </ObjectChild>
+
+            <ObjectChild key='inwardsVectorLeft'>
+                <Position />
+            </ObjectChild>
+
+            <ObjectChild key='sourceFrame'>
+                <string />
+            </ObjectChild>
+
+            <ObjectChild key='targetFrame'>
+                <string />
+            </ObjectChild>
+
+            <ObjectChild key='objectType'>
+               <armarx::objpose::arondto::ObjectType />
+            </ObjectChild>
+
+            <ObjectChild key='groupNr'>
+                <int />
+            </ObjectChild>
+
+            <ObjectChild key='providerName'>
+                <string />
+            </ObjectChild>
+
+            <ObjectChild key='sourceInfoValid'>
+                <bool />
+            </ObjectChild>
+            <ObjectChild key='sourceInfo'>
+                <armarx::grasping::arondto::GraspCandidateSourceInfo />
+            </ObjectChild>
+
+            <ObjectChild key='executionHintsRightValid'>
+                <bool />
+            </ObjectChild>
+            <ObjectChild key='executionHintsRight'>
+                <armarx::grasping::arondto::GraspCandidateExecutionHints />
+            </ObjectChild>
+
+            <ObjectChild key='executionHintsLeftValid'>
+                <bool />
+            </ObjectChild>
+            <ObjectChild key='executionHintsLeft'>
+                <armarx::grasping::arondto::GraspCandidateExecutionHints />
+            </ObjectChild>
+
+            <ObjectChild key='reachabilityInfoRightValid'>
+                <bool />
+            </ObjectChild>
+            <ObjectChild key='reachabilityInfoRight'>
+                <armarx::grasping::arondto::GraspCandidateReachabilityInfo />
+            </ObjectChild>
+
+            <ObjectChild key='reachabilityInfoLeftValid'>
+                <bool />
+            </ObjectChild>
+            <ObjectChild key='reachabilityInfoLeft'>
+                <armarx::grasping::arondto::GraspCandidateReachabilityInfo />
+            </ObjectChild>
+
+            <ObjectChild key='graspName'>
+                <string />
+            </ObjectChild>
+
+        </Object>
+
+
+    </GenerateTypes>
+</AronTypeDefinition>
diff --git a/source/RobotAPI/libraries/GraspingUtility/aron_conversions.cpp b/source/RobotAPI/libraries/GraspingUtility/aron_conversions.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..01f6adc1a9fe479580104e9e7de110de6b09aaef
--- /dev/null
+++ b/source/RobotAPI/libraries/GraspingUtility/aron_conversions.cpp
@@ -0,0 +1,377 @@
+#include "aron_conversions.h"
+
+#include <RobotAPI/libraries/aron/common/aron_conversions.h>
+#include <RobotAPI/libraries/armem_objects/aron_conversions.h>
+#include <RobotAPI/libraries/core/Pose.h>
+#include <RobotAPI/libraries/ArmarXObjects/aron_conversions.h>
+#include <ArmarXCore/core/exceptions/local/UnexpectedEnumValueException.h>
+
+
+
+void armarx::grasping::fromAron(const armarx::grasping::arondto::BoundingBox& dto,
+                                armarx::grasping::BoundingBox& bo)
+{
+    bo = BoundingBox(toIce(dto.center), toIce(dto.ha1), toIce(dto.ha2), toIce(dto.ha3));
+}
+
+void armarx::grasping::toAron(armarx::grasping::arondto::BoundingBox& dto,
+                              const armarx::grasping::BoundingBox& bo)
+{
+    dto.center = fromIce(bo.center);
+    dto.ha1 = fromIce(bo.ha1);
+    dto.ha2 = fromIce(bo.ha2);
+    dto.ha3 = fromIce(bo.ha3);
+}
+
+void armarx::grasping::fromAron(const armarx::grasping::arondto::GraspCandidateSourceInfo& dto,
+                                armarx::grasping::GraspCandidateSourceInfo& bo)
+{
+    bo.bbox = new BoundingBox();
+    fromAron(dto.bbox, *bo.bbox);
+    bo.referenceObjectName = dto.referenceObjectName;
+    bo.referenceObjectPose = toIce(dto.referenceObjectPose);
+    bo.segmentationLabelID = dto.segmentationLabelID;
+}
+
+void armarx::grasping::toAron(armarx::grasping::arondto::GraspCandidateSourceInfo& dto,
+                              const armarx::grasping::GraspCandidateSourceInfo& bo)
+{
+    toAron(dto.bbox, *bo.bbox);
+    dto.referenceObjectName = bo.referenceObjectName;
+    dto.referenceObjectPose = fromIce(bo.referenceObjectPose);
+    dto.segmentationLabelID = bo.segmentationLabelID;
+
+}
+
+void armarx::grasping::fromAron(const armarx::grasping::arondto::GraspCandidateReachabilityInfo& dto,
+                                armarx::grasping::GraspCandidateReachabilityInfo& bo)
+{
+    bo = GraspCandidateReachabilityInfo(dto.reachable, dto.minimumJointLimitMargin, dto.jointLimitMargins,
+                                        dto.maxPosError, dto.maxOriError);
+}
+
+void armarx::grasping::toAron(armarx::grasping::arondto::GraspCandidateReachabilityInfo& dto,
+                              const armarx::grasping::GraspCandidateReachabilityInfo& bo)
+{
+    dto.jointLimitMargins = bo.jointLimitMargins;
+    dto.maxOriError = bo.maxOriError;
+    dto.maxPosError = bo.maxPosError;
+    dto.minimumJointLimitMargin = bo.minimumJointLimitMargin;
+    dto.reachable = bo.reachable;
+}
+
+void armarx::grasping::fromAron(const armarx::grasping::arondto::GraspCandidate& dto,
+                                armarx::grasping::GraspCandidate& bo)
+{
+    bo = GraspCandidate();
+    bo.graspPose = toIce(dto.graspPose);
+    bo.robotPose = toIce(dto.robotPose);
+    bo.tcpPoseInHandRoot = toIce(dto.tcpPoseInHandRoot);
+    bo.approachVector = toIce(dto.approachVector);
+    bo.sourceFrame = dto.sourceFrame;
+    bo.targetFrame = dto.targetFrame;
+    bo.side = dto.side;
+    bo.graspSuccessProbability = dto.graspSuccessProbability;
+    fromAron(dto.objectType, bo.objectType);
+    if (dto.executionHintsValid)
+    {
+        bo.executionHints = new GraspCandidateExecutionHints();
+        fromAron(dto.executionHints, *bo.executionHints);
+    }
+    else
+    {
+        bo.executionHints = nullptr;
+    }
+    bo.groupNr = dto.groupNr;
+    bo.providerName = dto.providerName;
+    if (dto.reachabilityInfoValid)
+    {
+        bo.reachabilityInfo = new GraspCandidateReachabilityInfo();
+        fromAron(dto.reachabilityInfo, *bo.reachabilityInfo);
+    }
+    else
+    {
+        bo.reachabilityInfo = nullptr;
+    }
+    if (dto.sourceInfoValid)
+    {
+        bo.sourceInfo = new GraspCandidateSourceInfo();
+        fromAron(dto.sourceInfo, *bo.sourceInfo);
+    }
+    else
+    {
+        bo.sourceInfo = nullptr;
+    }
+}
+
+void armarx::grasping::toAron(armarx::grasping::arondto::GraspCandidate& dto,
+                              const armarx::grasping::GraspCandidate& bo)
+{
+    dto.approachVector = fromIce(bo.approachVector);
+    if (bo.executionHints)
+    {
+        dto.executionHintsValid = true;
+        toAron(dto.executionHints, *bo.executionHints);
+    }
+    else
+    {
+        dto.executionHintsValid = false;
+        dto.executionHints.toAron();
+    }
+    dto.graspPose = fromIce(bo.graspPose);
+    dto.graspSuccessProbability = bo.graspSuccessProbability;
+    dto.groupNr = bo.groupNr;
+    toAron(dto.objectType, bo.objectType);
+    dto.providerName = bo.providerName;
+    if (bo.reachabilityInfo)
+    {
+        dto.reachabilityInfoValid = true;
+        toAron(dto.reachabilityInfo, *bo.reachabilityInfo);
+    }
+    else
+    {
+        dto.reachabilityInfoValid = false;
+        dto.reachabilityInfo.toAron();
+    }
+    dto.robotPose = fromIce(bo.robotPose);
+    dto.tcpPoseInHandRoot = fromIce(bo.tcpPoseInHandRoot);
+    dto.side = bo.side;
+    dto.sourceFrame = bo.sourceFrame;
+    if (bo.sourceInfo)
+    {
+        dto.sourceInfoValid = true;
+        toAron(dto.sourceInfo, *bo.sourceInfo);
+    }
+    else
+    {
+        dto.sourceInfoValid = false;
+        dto.sourceInfo.toAron();
+    }
+    dto.targetFrame = bo.targetFrame;
+}
+
+void armarx::grasping::fromAron(const armarx::grasping::arondto::BimanualGraspCandidate& dto,
+                                armarx::grasping::BimanualGraspCandidate& bo)
+{
+    bo = BimanualGraspCandidate();
+    bo.graspPoseRight = toIce(dto.graspPoseRight);
+    bo.graspPoseLeft = toIce(dto.graspPoseLeft);
+    bo.robotPose = toIce(dto.robotPose);
+    bo.tcpPoseInHandRootRight = toIce(dto.tcpPoseInHandRootRight);
+    bo.tcpPoseInHandRootLeft = toIce(dto.tcpPoseInHandRootLeft);
+    bo.approachVectorRight = toIce(dto.approachVectorRight);
+    bo.approachVectorLeft = toIce(dto.approachVectorLeft);
+    bo.inwardsVectorRight = toIce(dto.inwardsVectorRight);
+    bo.inwardsVectorLeft = toIce(dto.inwardsVectorLeft);
+    bo.sourceFrame = dto.sourceFrame;
+    bo.targetFrame = dto.targetFrame;
+    fromAron(dto.objectType, bo.objectType);
+    if (dto.executionHintsRightValid)
+    {
+        bo.executionHintsRight = new GraspCandidateExecutionHints();
+        fromAron(dto.executionHintsRight, *bo.executionHintsRight);
+    }
+    else
+    {
+        bo.executionHintsRight = nullptr;
+    }
+    if (dto.executionHintsLeftValid)
+    {
+        bo.executionHintsLeft = new GraspCandidateExecutionHints();
+        fromAron(dto.executionHintsLeft, *bo.executionHintsLeft);
+    }
+    else
+    {
+        bo.executionHintsLeft = nullptr;
+    }
+    bo.groupNr = dto.groupNr;
+    bo.providerName = dto.providerName;
+    if (dto.reachabilityInfoRightValid)
+    {
+        bo.reachabilityInfoRight = new GraspCandidateReachabilityInfo();
+        fromAron(dto.reachabilityInfoRight, *bo.reachabilityInfoRight);
+    }
+    else
+    {
+        bo.reachabilityInfoRight = nullptr;
+    }
+    if (dto.reachabilityInfoLeftValid)
+    {
+        bo.reachabilityInfoLeft = new GraspCandidateReachabilityInfo();
+        fromAron(dto.reachabilityInfoLeft, *bo.reachabilityInfoLeft);
+    }
+    else
+    {
+        bo.reachabilityInfoLeft = nullptr;
+    }
+    if (dto.sourceInfoValid)
+    {
+        bo.sourceInfo = new GraspCandidateSourceInfo();
+        fromAron(dto.sourceInfo, *bo.sourceInfo);
+    }
+    else
+    {
+        bo.sourceInfo = nullptr;
+    }
+    bo.graspName = dto.graspName;
+}
+
+void armarx::grasping::toAron(armarx::grasping::arondto::BimanualGraspCandidate& dto,
+                              const armarx::grasping::BimanualGraspCandidate& bo)
+{
+    dto.approachVectorRight = fromIce(bo.approachVectorRight);
+    dto.approachVectorLeft = fromIce(bo.approachVectorLeft);
+    if (bo.executionHintsRight)
+    {
+        dto.executionHintsRightValid = true;
+        toAron(dto.executionHintsRight, *bo.executionHintsRight);
+    }
+    else
+    {
+        dto.executionHintsRightValid = false;
+        dto.executionHintsRight.toAron();
+    }
+    if (bo.executionHintsLeft)
+    {
+        dto.executionHintsLeftValid = true;
+        toAron(dto.executionHintsLeft, *bo.executionHintsLeft);
+    }
+    else
+    {
+        dto.executionHintsLeftValid = false;
+        dto.executionHintsLeft.toAron();
+
+    }
+    dto.graspPoseRight = fromIce(bo.graspPoseRight);
+    dto.graspPoseLeft = fromIce(bo.graspPoseLeft);
+    dto.groupNr = bo.groupNr;
+    toAron(dto.objectType, bo.objectType);
+    dto.providerName = bo.providerName;
+    if (bo.reachabilityInfoRight)
+    {
+        dto.reachabilityInfoRightValid = true;
+        toAron(dto.reachabilityInfoRight, *bo.reachabilityInfoRight);
+    }
+    else
+    {
+        dto.reachabilityInfoRightValid = false;
+        dto.reachabilityInfoRight.toAron();
+    }
+    if (bo.reachabilityInfoLeft)
+    {
+        dto.reachabilityInfoLeftValid = true;
+        toAron(dto.reachabilityInfoLeft, *bo.reachabilityInfoLeft);
+    }
+    else
+    {
+        dto.reachabilityInfoLeftValid = false;
+        dto.reachabilityInfoLeft.toAron();
+    }
+    dto.robotPose = fromIce(bo.robotPose);
+    dto.sourceFrame = bo.sourceFrame;
+    if (bo.sourceInfo)
+    {
+        dto.sourceInfoValid = true;
+        toAron(dto.sourceInfo, *bo.sourceInfo);
+    }
+    else
+    {
+        dto.sourceInfoValid = false;
+        dto.sourceInfo.toAron();
+    }
+    dto.targetFrame = bo.targetFrame;
+    dto.inwardsVectorRight = fromIce(bo.inwardsVectorRight);
+    dto.inwardsVectorLeft = fromIce(bo.inwardsVectorLeft);
+    dto.graspName = bo.graspName;
+}
+
+void armarx::grasping::fromAron(const armarx::grasping::arondto::GraspCandidateExecutionHints& dto,
+                                armarx::grasping::GraspCandidateExecutionHints& bo)
+{
+    bo = GraspCandidateExecutionHints();
+    fromAron(dto.approach, bo.approach);
+    fromAron(dto.preshape, bo.preshape);
+    bo.graspTrajectoryName = dto.graspTrajectoryName;
+}
+
+void armarx::grasping::toAron(armarx::grasping::arondto::GraspCandidateExecutionHints& dto,
+                              const armarx::grasping::GraspCandidateExecutionHints& bo)
+{
+    toAron(dto.approach, bo.approach);
+    toAron(dto.preshape, bo.preshape);
+    dto.graspTrajectoryName = bo.graspTrajectoryName;
+}
+
+void armarx::grasping::fromAron(const armarx::grasping::arondto::ApproachType& dto,
+                                armarx::grasping::ApproachType& bo)
+{
+    switch (dto.value)
+    {
+        case arondto::ApproachType::AnyApproach:
+            bo = ApproachType::AnyApproach;
+            return;
+        case arondto::ApproachType::TopApproach:
+            bo = ApproachType::TopApproach;
+            return;
+        case arondto::ApproachType::SideApproach:
+            bo = ApproachType::SideApproach;
+            return;
+    }
+    ARMARX_UNEXPECTED_ENUM_VALUE(arondto::ObjectType, dto.value);
+
+}
+
+void armarx::grasping::toAron(armarx::grasping::arondto::ApproachType& dto,
+                              const armarx::grasping::ApproachType& bo)
+{
+    switch (bo)
+    {
+        case ApproachType::AnyApproach:
+            dto.value = arondto::ApproachType::AnyApproach;
+            return;
+        case ApproachType::TopApproach:
+            dto.value = arondto::ApproachType::TopApproach;
+            return;
+        case ApproachType::SideApproach:
+            dto.value = arondto::ApproachType::SideApproach;
+            return;
+    }
+    ARMARX_UNEXPECTED_ENUM_VALUE(ObjectTypeEnum, bo);
+
+}
+
+void armarx::grasping::fromAron(const armarx::grasping::arondto::ApertureType& dto,
+                                armarx::grasping::ApertureType& bo)
+{
+    switch (dto.value)
+    {
+        case arondto::ApertureType::AnyAperture:
+            bo = ApertureType::AnyAperture;
+            return;
+        case arondto::ApertureType::OpenAperture:
+            bo = ApertureType::OpenAperture;
+            return;
+        case arondto::ApertureType::PreshapedAperture:
+            bo = ApertureType::PreshapedAperture;
+            return;
+    }
+    ARMARX_UNEXPECTED_ENUM_VALUE(arondto::ObjectType, dto.value);
+}
+
+void armarx::grasping::toAron(armarx::grasping::arondto::ApertureType& dto,
+                              const armarx::grasping::ApertureType& bo)
+{
+    switch (bo)
+    {
+        case ApertureType::AnyAperture:
+            dto.value = arondto::ApertureType::AnyAperture;
+            return;
+        case ApertureType::OpenAperture:
+            dto.value = arondto::ApertureType::OpenAperture;
+            return;
+        case ApertureType::PreshapedAperture:
+            dto.value = arondto::ApertureType::PreshapedAperture;
+            return;
+    }
+    ARMARX_UNEXPECTED_ENUM_VALUE(ObjectTypeEnum, bo);
+}
diff --git a/source/RobotAPI/libraries/GraspingUtility/aron_conversions.h b/source/RobotAPI/libraries/GraspingUtility/aron_conversions.h
new file mode 100644
index 0000000000000000000000000000000000000000..9e1ac4ca2f78637660c12250a0dfd4dd4b8250b5
--- /dev/null
+++ b/source/RobotAPI/libraries/GraspingUtility/aron_conversions.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <RobotAPI/interface/units/GraspCandidateProviderInterface.h>
+#include <RobotAPI/libraries/GraspingUtility/aron/GraspCandidate.aron.generated.h>
+#include <RobotAPI/libraries/ArmarXObjects/aron/ObjectType.aron.generated.h>
+
+namespace armarx
+{
+    namespace grasping
+    {
+        void fromAron(const arondto::ApproachType& dto, ApproachType& bo);
+        void toAron(arondto::ApproachType& dto, const ApproachType& bo);
+
+        void fromAron(const arondto::ApertureType& dto, ApertureType& bo);
+        void toAron(arondto::ApertureType& dto, const ApertureType& bo);
+
+        void fromAron(const arondto::BoundingBox& dto, BoundingBox& bo);
+        void toAron(arondto::BoundingBox& dto, const BoundingBox& bo);
+
+        void fromAron(const arondto::GraspCandidateSourceInfo& dto, GraspCandidateSourceInfo& bo);
+        void toAron(arondto::GraspCandidateSourceInfo& dto, const GraspCandidateSourceInfo& bo);
+
+        void fromAron(const arondto::GraspCandidateExecutionHints& dto, GraspCandidateExecutionHints& bo);
+        void toAron(arondto::GraspCandidateExecutionHints& dto, const GraspCandidateExecutionHints& bo);
+
+        void fromAron(const arondto::GraspCandidateReachabilityInfo& dto, GraspCandidateReachabilityInfo& bo);
+        void toAron(arondto::GraspCandidateReachabilityInfo& dto, const GraspCandidateReachabilityInfo& bo);
+
+        void fromAron(const arondto::GraspCandidate& dto, GraspCandidate& bo);
+        void toAron(arondto::GraspCandidate& dto, const GraspCandidate& bo);
+
+        void fromAron(const arondto::BimanualGraspCandidate& dto, BimanualGraspCandidate& bo);
+        void toAron(arondto::BimanualGraspCandidate& dto, const BimanualGraspCandidate& bo);
+    }
+}
diff --git a/source/RobotAPI/libraries/GraspingUtility/box_to_grasp_candidates.cpp b/source/RobotAPI/libraries/GraspingUtility/box_to_grasp_candidates.cpp
index 3082a9367101850c603aa710581e9bbc7e5c6032..628824cb3bfdbd750939721c1cba92f21967dc68 100644
--- a/source/RobotAPI/libraries/GraspingUtility/box_to_grasp_candidates.cpp
+++ b/source/RobotAPI/libraries/GraspingUtility/box_to_grasp_candidates.cpp
@@ -292,7 +292,7 @@ namespace armarx
         gc->providerName = provider_name;
         gc->side = side_name;
         gc->approachVector = new armarx::Vector3(approach);
-        gc->objectType = armarx::grasping::UnknownObject;
+        gc->objectType = armarx::objpose::UnknownObject;
         gc->sourceFrame = "root";
         gc->targetFrame = "root";
         return gc;
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/HeartbeatComponentPlugin.cpp b/source/RobotAPI/libraries/RobotAPIComponentPlugins/HeartbeatComponentPlugin.cpp
index 510ff8933b6e045ec96e1020e6914f2b064636f2..743d8a9bc2904a707f42633567f9b59ef184c3af 100644
--- a/source/RobotAPI/libraries/RobotAPIComponentPlugins/HeartbeatComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/HeartbeatComponentPlugin.cpp
@@ -67,6 +67,7 @@ namespace armarx::plugins
     HeartbeatComponentPlugin::preOnConnectComponent()
     {
         robotHealthTopic = parent<Component>().getTopic<RobotHealthInterfacePrx>(topicName);
+        componentName = parent<Component>().getName();
     }
 
     void
diff --git a/source/RobotAPI/libraries/armem/CMakeLists.txt b/source/RobotAPI/libraries/armem/CMakeLists.txt
index c524ecd93da7721ee95cc111beb518cafd848de5..cf8ce72dfd79c7148548940fc954b4ea10ad1fda 100644
--- a/source/RobotAPI/libraries/armem/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem/CMakeLists.txt
@@ -84,6 +84,7 @@ set(LIB_FILES
     server/RemoteGuiAronDataVisitor.cpp
 
     server/ltm/LongtermMemoryBase.cpp
+    server/ltm/disk/operations.cpp
     server/ltm/disk/MemoryManager.cpp
     server/ltm/mongodb/MemoryManager.cpp
     server/ltm/mongodb/ConnectionManager.cpp
@@ -196,6 +197,7 @@ set(LIB_HEADERS
     server/RemoteGuiAronDataVisitor.h
 
     server/ltm/LongtermMemoryBase.h
+    server/ltm/disk/operations.h
     server/ltm/disk/MemoryManager.h
     server/ltm/mongodb/MemoryManager.h
     server/ltm/mongodb/ConnectionManager.h
diff --git a/source/RobotAPI/libraries/armem/client/query/detail/NameSelectorOps.h b/source/RobotAPI/libraries/armem/client/query/detail/NameSelectorOps.h
index 219a08e47a6c0cf6fd2cb8463c8e1923997c77af..ee004f1b819769df41615b2bfa0706e68772d5ca 100644
--- a/source/RobotAPI/libraries/armem/client/query/detail/NameSelectorOps.h
+++ b/source/RobotAPI/libraries/armem/client/query/detail/NameSelectorOps.h
@@ -12,6 +12,9 @@ namespace armarx::armem::client::query::detail
     {
     public:
 
+        virtual ~NameSelectorOps() = default;
+
+
         virtual DerivedT& withName(const std::string& name) = 0;
         virtual DerivedT& withNamesMatching(const std::string& regex) = 0;
 
diff --git a/source/RobotAPI/libraries/armem/client/query/detail/SelectorOps.h b/source/RobotAPI/libraries/armem/client/query/detail/SelectorOps.h
index c6e153f0d7358b318c6966f2c9d5c9c2c35579a4..aa354b42ff993f2e669b9fada2441a788b938081 100644
--- a/source/RobotAPI/libraries/armem/client/query/detail/SelectorOps.h
+++ b/source/RobotAPI/libraries/armem/client/query/detail/SelectorOps.h
@@ -19,6 +19,7 @@ namespace armarx::armem::client::query::detail
         using QueryT = _QueryT;
 
         ChildSelectorOps() = delete;
+        virtual ~ChildSelectorOps() = default;
 
         ChildSelectorOps(const armem::query::data::QueryTargets& p) :
             _parentTargets(p)
diff --git a/source/RobotAPI/libraries/armem/client/util/SimpleReaderBase.h b/source/RobotAPI/libraries/armem/client/util/SimpleReaderBase.h
index a78db401d3f578d7be9f9c86542a37f72326aabc..e567b76b8d36d8cf41c00118a49d3e041d0607bc 100644
--- a/source/RobotAPI/libraries/armem/client/util/SimpleReaderBase.h
+++ b/source/RobotAPI/libraries/armem/client/util/SimpleReaderBase.h
@@ -44,7 +44,7 @@ namespace armarx::armem::client::util
         virtual ~SimpleReaderBase() = default;
 
         void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def);
-        void connect();
+        virtual void connect();
 
 
     protected:
@@ -65,6 +65,8 @@ namespace armarx::armem::client::util
         const armem::client::Reader& memoryReader() const;
 
 
+        MemoryNameSystem& memoryNameSystem;
+
     private:
 
         Properties props;
@@ -72,7 +74,6 @@ namespace armarx::armem::client::util
         armem::client::Reader memoryReaderClient;
         std::mutex memoryMutex;
 
-        MemoryNameSystem& memoryNameSystem;
     };
 
 } // namespace armarx::armem::client::util
diff --git a/source/RobotAPI/libraries/armem/core/base/CoreSegmentBase.h b/source/RobotAPI/libraries/armem/core/base/CoreSegmentBase.h
index f4d0b530f43afcfa7f7aeba95389bdb8a5371918..4f63c6f3a5cb14ad61f4d4664ead485c78345938 100644
--- a/source/RobotAPI/libraries/armem/core/base/CoreSegmentBase.h
+++ b/source/RobotAPI/libraries/armem/core/base/CoreSegmentBase.h
@@ -247,11 +247,10 @@ namespace armarx::armem::base
         }
 
 
-        void append(const _Derived& m)
+        template <class OtherDerivedT>
+        void append(const OtherDerivedT& other)
         {
-            // ARMARX_INFO << "CoreSegment: Merge name '" << m.name() << "' into '" << name() << "'";
-
-            m.forEachProviderSegment([this](const ProviderSegmentT & provSeg)
+            other.forEachProviderSegment([this](const auto& provSeg)
             {
                 auto it = this->_container.find(provSeg.name());
                 if (it == this->_container.end())
diff --git a/source/RobotAPI/libraries/armem/core/base/EntityBase.h b/source/RobotAPI/libraries/armem/core/base/EntityBase.h
index 6fa26a5e40ae0ba23ea7e281ec336590dea483cb..9b34e11bd3d53e896f38cd2c3301c2c35dcdffd9 100644
--- a/source/RobotAPI/libraries/armem/core/base/EntityBase.h
+++ b/source/RobotAPI/libraries/armem/core/base/EntityBase.h
@@ -538,20 +538,19 @@ namespace armarx::armem::base
         }
 
 
-        void append(const DerivedT& m)
+        template <class OtherDerivedT>
+        void append(const OtherDerivedT& other)
         {
-            // ARMARX_INFO << "Entity: Merge name '" << m.name() << "' into '" << name() << "'";
-
-            m.forEachSnapshot([this](const EntitySnapshotT & snapshot)
+            other.forEachSnapshot([this](const auto& snapshot)
             {
                 auto it = this->_container.find(snapshot.time());
                 if (it == this->_container.end())
                 {
                     EntitySnapshotT copy { snapshot };
-                    copy.id() = this->id().withTimestamp(snapshot.time()); // update id (e.g. memory name) if necessary
+                    copy.id() = this->id().withTimestamp(snapshot.time());  // update id (e.g. memory name) if necessary
                     this->_container.emplace(snapshot.time(), copy);
                 }
-                // else: segment already exists
+                // else: snapshot already exists
                 // We assume that a snapshot does not change, so ignore
                 return true;
             });
diff --git a/source/RobotAPI/libraries/armem/core/base/MemoryBase.h b/source/RobotAPI/libraries/armem/core/base/MemoryBase.h
index e1729bbcd90cc6062e93b8e62ed8db29e3bb4387..2d28474e232281c085cad9a88cd0dcd85fec70d0 100644
--- a/source/RobotAPI/libraries/armem/core/base/MemoryBase.h
+++ b/source/RobotAPI/libraries/armem/core/base/MemoryBase.h
@@ -281,11 +281,10 @@ namespace armarx::armem::base
          * @brief Merge another memory into this one. Append all data
          * @param m The other memory
          */
-        void append(const _Derived& m)
+        template <class OtherDerivedT>
+        void append(const OtherDerivedT& other)
         {
-            // ARMARX_INFO << "Memory: Merge name '" << m.name() << "' into '" << name() << "'";
-
-            m.forEachCoreSegment([this](const CoreSegmentT & coreSeg)
+            other.forEachCoreSegment([this](const auto& coreSeg)
             {
                 auto it = this->_container.find(coreSeg.name());
                 if (it == this->_container.end())
diff --git a/source/RobotAPI/libraries/armem/core/base/ProviderSegmentBase.h b/source/RobotAPI/libraries/armem/core/base/ProviderSegmentBase.h
index 6a5497444c9e5959ac7d59300e1bc99e0fac2018..a2a9f2a8c8ae6b57ff33ce1ecf8d1d1b5710ff55 100644
--- a/source/RobotAPI/libraries/armem/core/base/ProviderSegmentBase.h
+++ b/source/RobotAPI/libraries/armem/core/base/ProviderSegmentBase.h
@@ -229,9 +229,11 @@ namespace armarx::armem::base
             return ret;
         }
 
-        void append(const DerivedT& m)
+
+        template <class OtherDerivedT>
+        void append(const OtherDerivedT& other)
         {
-            m.forEachEntity([this](const EntityT & entity)
+            other.forEachEntity([this](const auto& entity)
             {
                 auto it = this->_container.find(entity.name());
                 if (it == this->_container.end())
diff --git a/source/RobotAPI/libraries/armem/core/error/ArMemError.cpp b/source/RobotAPI/libraries/armem/core/error/ArMemError.cpp
index 003ef9fb5496b92814ad68cd9904987498460c46..ac8be17b51fd8f67d90de93c77513d15b6ff8320 100644
--- a/source/RobotAPI/libraries/armem/core/error/ArMemError.cpp
+++ b/source/RobotAPI/libraries/armem/core/error/ArMemError.cpp
@@ -16,12 +16,17 @@ namespace armarx::armem::error
     }
 
 
-    InvalidArgument::InvalidArgument(const std::string& argument, const std::string& function, const std::string& message) :
+    InvalidArgument::InvalidArgument(const std::string& argument,
+                                     const std::string& function,
+                                     const std::string& message) :
         ArMemError(makeMsg(argument, function, message))
     {
     }
 
-    std::string InvalidArgument::makeMsg(const std::string& argument, const std::string& function, const std::string& message)
+    std::string
+    InvalidArgument::makeMsg(const std::string& argument,
+                             const std::string& function,
+                             const std::string& message)
     {
         std::stringstream ss;
         ss << "Invalid value for argument '" << argument << "' in function " << function << "()";
@@ -38,24 +43,37 @@ namespace armarx::armem::error
 
 
     ContainerNameMismatch::ContainerNameMismatch(const std::string& gottenName,
-            const std::string& ownTerm, const std::string& containerName) :
+                                                 const std::string& ownTerm,
+                                                 const std::string& containerName) :
         ArMemError(makeMsg(gottenName, ownTerm, containerName))
-    {}
+    {
+    }
 
-    std::string ContainerNameMismatch::makeMsg(const std::string& gottenName, const std::string& containerTerm, const std::string& containerName)
+    std::string
+    ContainerNameMismatch::makeMsg(const std::string& gottenName,
+                                   const std::string& containerTerm,
+                                   const std::string& containerName)
     {
         std::stringstream ss;
-        ss << "Name '" << gottenName << "' does not match name of " << containerTerm << " '" << containerName << "'.";
+        ss << "Name '" << gottenName << "' does not match name of " << containerTerm << " '"
+           << containerName << "'.";
         return ss.str();
     }
 
 
-    ContainerEntryAlreadyExists::ContainerEntryAlreadyExists(const std::string& existingTerm, const std::string& existingName, const std::string& ownTerm, const std::string& ownName) :
+    ContainerEntryAlreadyExists::ContainerEntryAlreadyExists(const std::string& existingTerm,
+                                                             const std::string& existingName,
+                                                             const std::string& ownTerm,
+                                                             const std::string& ownName) :
         ArMemError(makeMsg(existingTerm, existingName, ownTerm, ownName))
     {
     }
 
-    std::string ContainerEntryAlreadyExists::makeMsg(const std::string& existingTerm, const std::string& existingName, const std::string& ownTerm, const std::string& ownName)
+    std::string
+    ContainerEntryAlreadyExists::makeMsg(const std::string& existingTerm,
+                                         const std::string& existingName,
+                                         const std::string& ownTerm,
+                                         const std::string& ownName)
     {
         std::stringstream ss;
         ss << simox::alg::capitalize_words(existingTerm) << " with name '" << existingName << "' "
@@ -64,16 +82,21 @@ namespace armarx::armem::error
     }
 
 
-    MissingEntry::MissingEntry(const std::string& missingTerm, const std::string& missingName,
-                               const std::string& containerTerm, const std::string& containerName,
+    MissingEntry::MissingEntry(const std::string& missingTerm,
+                               const std::string& missingName,
+                               const std::string& containerTerm,
+                               const std::string& containerName,
                                size_t size) :
         ArMemError(makeMsg(missingTerm, missingName, containerTerm, containerName, size))
     {
     }
 
-    std::string MissingEntry::makeMsg(const std::string& missingTerm, const std::string& missingName,
-                                      const std::string& containerTerm, const std::string& containerName,
-                                      size_t size)
+    std::string
+    MissingEntry::makeMsg(const std::string& missingTerm,
+                          const std::string& missingName,
+                          const std::string& containerTerm,
+                          const std::string& containerName,
+                          size_t size)
     {
         std::stringstream ss;
         ss << "No " << missingTerm << " with name '" << missingName << "' "
@@ -82,15 +105,19 @@ namespace armarx::armem::error
     }
 
 
-
-    MissingData::MissingData(const std::string& missingTerm, const std::string& missingName,
-                             const std::string& ownTerm, const std::string& ownName) :
+    MissingData::MissingData(const std::string& missingTerm,
+                             const std::string& missingName,
+                             const std::string& ownTerm,
+                             const std::string& ownName) :
         ArMemError(makeMsg(missingTerm, missingName, ownTerm, ownName))
     {
     }
 
-    std::string MissingData::makeMsg(const std::string& missingTerm, const std::string& missingName,
-                                     const std::string& ownTerm, const std::string& ownName)
+    std::string
+    MissingData::makeMsg(const std::string& missingTerm,
+                         const std::string& missingName,
+                         const std::string& ownTerm,
+                         const std::string& ownName)
     {
         std::stringstream ss;
         ss << "No " << missingTerm << " data at '" << missingName << "' "
@@ -104,7 +131,8 @@ namespace armarx::armem::error
     {
     }
 
-    std::string ParseIntegerError::makeMsg(std::string string, std::string semanticName)
+    std::string
+    ParseIntegerError::makeMsg(std::string string, std::string semanticName)
     {
         std::stringstream ss;
         ss << "Failed to parse " << semanticName << " '" << string << "' as integer.";
@@ -112,13 +140,13 @@ namespace armarx::armem::error
     }
 
 
-
     InvalidMemoryID::InvalidMemoryID(const MemoryID& id, const std::string& message) :
         ArMemError(makeMsg(id, message))
     {
     }
 
-    std::string InvalidMemoryID::makeMsg(const MemoryID& id, const std::string& message)
+    std::string
+    InvalidMemoryID::makeMsg(const MemoryID& id, const std::string& message)
     {
         std::stringstream ss;
         ss << "Invalid memory ID " << id << ": " << message;
@@ -126,13 +154,14 @@ namespace armarx::armem::error
     }
 
 
-
-    EntityHistoryEmpty::EntityHistoryEmpty(const std::string& entityName, const std::string& message) :
+    EntityHistoryEmpty::EntityHistoryEmpty(const std::string& entityName,
+                                           const std::string& message) :
         ArMemError(makeMsg(entityName, message))
     {
     }
 
-    std::string EntityHistoryEmpty::makeMsg(const std::string& entityName, const std::string& message)
+    std::string
+    EntityHistoryEmpty::makeMsg(const std::string& entityName, const std::string& message)
     {
         std::stringstream ss;
         ss << "History of entity '" << entityName << "' is empty";
@@ -148,78 +177,47 @@ namespace armarx::armem::error
     }
 
 
-
     UnknownQueryType::UnknownQueryType(const std::string& term, const std::string& typeName) :
         ArMemError(makeMsg(term, typeName))
     {
     }
 
-    std::string UnknownQueryType::makeMsg(const std::string& term, const std::string& typeName)
+    std::string
+    UnknownQueryType::makeMsg(const std::string& term, const std::string& typeName)
     {
         std::stringstream ss;
         ss << "Unknown " << term << " query type '" << typeName << "'.";
         return ss.str();
     }
 
-
-    PathNotARegularFile::PathNotARegularFile(const std::string& path, const std::string& message) :
-        ArMemError(makeMsg(path, message))
+    QueryFailed::QueryFailed(const std::string& memory, const std::string& message) :
+        ArMemError(makeMsg(memory, message))
     {
     }
 
-    std::string PathNotARegularFile::makeMsg(const std::string& path, const std::string& message)
+    std::string QueryFailed::makeMsg(const std::string& memory, const std::string& message)
     {
         std::stringstream ss;
-        ss << "The path '" << path << "' is not a regular file. Expecting a regular file there.";
-        if (message.size() > 0)
-        {
-            ss << " " << message;
-        }
-        else
-        {
-            ss << ".";
-        }
+        ss << "Query from memory " << memory << " failed with message: " << message;
         return ss.str();
     }
 
-    PathNotADirectory::PathNotADirectory(const std::string& path, const std::string& message) :
-        ArMemError(makeMsg(path, message))
+    IOError::IOError(const std::string& path, const std::string& message) :
+        ArMemError(makeMsg(path, message)), path(path)
     {
     }
 
-    std::string PathNotADirectory::makeMsg(const std::string& path, const std::string& message)
-    {
-        std::stringstream ss;
-        ss << "The path '" << path << "' is not a directory. Expecting a directory there.";
-        if (message.size() > 0)
-        {
-            ss << " " << message;
-        }
-        else
-        {
-            ss << ".";
-        }
-        return ss.str();
-    }
 
-    PathDoesNotExist::PathDoesNotExist(const std::string& path, const std::string& message) :
-        ArMemError(makeMsg(path, message))
-    {
-    }
-
-    std::string PathDoesNotExist::makeMsg(const std::string& path, const std::string& message)
+    std::string
+    IOError::makeMsg(const std::string& path, const std::string& message)
     {
         std::stringstream ss;
-        ss << "The path '" << path << "' does not exist. Expecting a valid path.";
+        ss << "IOError on path \"" << path << "\".";
         if (message.size() > 0)
         {
-            ss << " " << message;
-        }
-        else
-        {
-            ss << ".";
+            ss << "\n" << message;
         }
         return ss.str();
     }
 
-}
+} // namespace armarx::armem::error
diff --git a/source/RobotAPI/libraries/armem/core/error/ArMemError.h b/source/RobotAPI/libraries/armem/core/error/ArMemError.h
index 219d489fad038da1098d724bddd9e2bc74b0a5d7..5678ee1a9a8e452309f2127fa41f519858ee233c 100644
--- a/source/RobotAPI/libraries/armem/core/error/ArMemError.h
+++ b/source/RobotAPI/libraries/armem/core/error/ArMemError.h
@@ -174,42 +174,34 @@ namespace armarx::armem::error
     };
 
     /**
-     * @brief Indicates that a path does not point to a directory.
+     * @brief Indicates that a query resulted in an Error.
      */
-    class PathNotADirectory : public ArMemError
+    class QueryFailed : public ArMemError
     {
     public:
 
-        PathNotADirectory(const std::string& path, const std::string& message = "");
+        QueryFailed(const std::string& memory, const std::string& message = "");
 
-        static std::string makeMsg(const std::string& path, const std::string& message = "");
+        static std::string makeMsg(const std::string& memory, const std::string& message = "");
 
     };
 
+
     /**
-     * @brief Indicates that a path does not point to a regular file.
+     * @brief Indicates that something went wrong when accessing the filesystem.
      */
-    class PathNotARegularFile : public ArMemError
+    class IOError : public ArMemError
     {
     public:
 
-        PathNotARegularFile(const std::string& path, const std::string& message = "");
+        IOError(const std::string& path, const std::string& message = "");
 
         static std::string makeMsg(const std::string& path, const std::string& message = "");
 
-    };
 
-    /**
-     * @brief Indicates that a path does not exist.
-     */
-    class PathDoesNotExist : public ArMemError
-    {
-    public:
-
-        PathDoesNotExist(const std::string& path, const std::string& message = "");
-
-        static std::string makeMsg(const std::string& path, const std::string& message = "");
+        std::string path;
 
     };
+
 }
 
diff --git a/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.cpp b/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.cpp
index a80a189ff585c7610bebe0978468aec82ebe48b9..a0c606a990fd4635a5fa2cded1c0e5be8f7566a8 100644
--- a/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.cpp
+++ b/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.cpp
@@ -40,6 +40,14 @@ namespace armarx::armem::mns
             }
         }
     }
+    
+    dto::RegisterServerResult MemoryNameSystem::registerServer(const dto::RegisterServerInput& input) 
+    {
+        const auto result = Registry::registerServer(input);
+        waitForServer_processOnce();
+
+        return result;
+    }
 
 
     armarx::RemoteGui::Client::GridLayout MemoryNameSystem::RemoteGui_buildInfoGrid()
@@ -92,4 +100,3 @@ namespace armarx::armem::mns
     }
 
 }
-
diff --git a/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.h b/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.h
index 51e4719f127ee576073e0c9b45cb0635241a185d..e0cf5b88753cb4a96caad2c004a853dcd4d11a34 100644
--- a/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.h
+++ b/source/RobotAPI/libraries/armem/mns/MemoryNameSystem.h
@@ -31,6 +31,8 @@ namespace armarx::armem::mns
 
         void waitForServer_processOnce();
 
+        dto::RegisterServerResult registerServer(const dto::RegisterServerInput& input) override;
+
 
         /// Builds a RemoteGui grid containing information about registered memories.
         armarx::RemoteGui::Client::GridLayout RemoteGui_buildInfoGrid();
diff --git a/source/RobotAPI/libraries/armem/mns/Registry.h b/source/RobotAPI/libraries/armem/mns/Registry.h
index bf9348d157ee990f6032c4cf115b9fd56c70f716..c1965bdac24fcdf943ad2b7bc945698358dd3f0c 100644
--- a/source/RobotAPI/libraries/armem/mns/Registry.h
+++ b/source/RobotAPI/libraries/armem/mns/Registry.h
@@ -35,7 +35,7 @@ namespace armarx::armem::mns
          * Causes threads waiting in `waitForMemory()` to resume if the respective
          * memory server was added.
          */
-        dto::RegisterServerResult registerServer(const dto::RegisterServerInput& input);
+        virtual dto::RegisterServerResult registerServer(const dto::RegisterServerInput& input);
         /**
          * @brief Remove a server entry.
          */
diff --git a/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.cpp b/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.cpp
index 2e8c64d64121eccc007cad7ba2d55c2e361b94e2..53e6f0169ab5ccb459ff730d67651836e78d5ec1 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.cpp
+++ b/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.cpp
@@ -1,20 +1,23 @@
-// Header
 #include "LongtermMemoryBase.h"
 
-// ArmarX
-#include <ArmarXCore/core/time/TimeUtil.h>
 #include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/time/TimeUtil.h>
+
+#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
 
 
 namespace armarx::armem::server::ltm
 {
-    void LongtermMemoryBase::setName(const std::string& name)
+    void
+    LongtermMemoryBase::setName(const std::string& name)
     {
         cache.name() = name;
         lut.name() = name;
     }
 
-    armem::wm::Memory LongtermMemoryBase::getCacheAndLutNotConverted() const
+
+    armem::wm::Memory
+    LongtermMemoryBase::getCacheAndLutNotConverted() const
     {
         std::lock_guard l(cache_mutex);
         std::lock_guard l2(lut_mutex);
@@ -32,23 +35,43 @@ namespace armarx::armem::server::ltm
         return m;
     }
 
-    void LongtermMemoryBase::append(const armem::wm::Memory& m)
+
+    template <class ...Args>
+    void LongtermMemoryBase::_append(const armem::base::MemoryBase<Args...>& memory)
     {
         TIMING_START(LTM_Append);
-        ARMARX_INFO << "Append memory with name '" << m.name() << "' into the LTM with name '" << cache.name() << "'";
+        ARMARX_INFO << "Append memory with name '" << memory.name() << "' into the LTM with name '"
+                    << cache.name() << "'";
 
         std::lock_guard l(cache_mutex);
-        cache.append(m);
+        cache.append(memory);
 
         encodeAndStore();
 
         TIMING_END(LTM_Append);
     }
 
-    void LongtermMemoryBase::checkUpdateLatestSnapshot(const armem::wm::EntitySnapshot& newSnapshot)
+
+    void
+    LongtermMemoryBase::append(const armem::wm::Memory& memory)
+    {
+        this->_append(memory);
+    }
+
+
+    void
+    LongtermMemoryBase::append(const armem::server::wm::Memory& memory)
+    {
+        this->_append(memory);
+    }
+
+
+    void
+    LongtermMemoryBase::checkUpdateLatestSnapshot(const armem::wm::EntitySnapshot& newSnapshot)
     {
         // update map of latestSnapshots
-        if (auto it = latestSnapshots.find(newSnapshot.id().getEntityID().str()); it != latestSnapshots.end())
+        if (auto it = latestSnapshots.find(newSnapshot.id().getEntityID().str());
+            it != latestSnapshots.end())
         {
             auto ptr = it->second;
             if (ptr->id().timestamp > newSnapshot.id().timestamp)
@@ -64,7 +87,9 @@ namespace armarx::armem::server::ltm
         }
     }
 
-    bool LongtermMemoryBase::containsCoreSegment(const MemoryID& coreSegmentID) const
+
+    bool
+    LongtermMemoryBase::containsCoreSegment(const MemoryID& coreSegmentID) const
     {
         //ARMARX_INFO << "Check if lut has core seg";
         if (lut.hasCoreSegment(coreSegmentID.coreSegmentName))
@@ -75,7 +100,9 @@ namespace armarx::armem::server::ltm
         return false;
     }
 
-    bool LongtermMemoryBase::containsProviderSegment(const MemoryID& providerSegmentID) const
+
+    bool
+    LongtermMemoryBase::containsProviderSegment(const MemoryID& providerSegmentID) const
     {
         //ARMARX_INFO << "Check if lut has prov seg";
         if (lut.hasCoreSegment(providerSegmentID.coreSegmentName))
@@ -90,7 +117,9 @@ namespace armarx::armem::server::ltm
         return false;
     }
 
-    bool LongtermMemoryBase::containsEntity(const MemoryID& entityID) const
+
+    bool
+    LongtermMemoryBase::containsEntity(const MemoryID& entityID) const
     {
         //ARMARX_INFO << "Check if lut has entity";
         if (lut.hasCoreSegment(entityID.coreSegmentName))
@@ -109,7 +138,9 @@ namespace armarx::armem::server::ltm
         return false;
     }
 
-    bool LongtermMemoryBase::containsSnapshot(const MemoryID& snapshotID) const
+
+    bool
+    LongtermMemoryBase::containsSnapshot(const MemoryID& snapshotID) const
     {
         //ARMARX_INFO << "Check if lut has snapshot";
         if (lut.hasCoreSegment(snapshotID.coreSegmentName))
@@ -131,4 +162,5 @@ namespace armarx::armem::server::ltm
         }
         return false;
     }
-}
+
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.h b/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.h
index 097f951548cc777fa03cedbc5f425e867439cd48..463c4c37998bd95ce4ec81f2e92eb0c937e2dc7c 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.h
@@ -1,11 +1,14 @@
 #pragma once
 
-// STD / STL
-#include <optional>
+#include <map>
 #include <mutex>
+#include <optional>
+#include <string>
+
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+#include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
+#include <RobotAPI/libraries/armem/server/forward_declarations.h>
 
-// Memory
-#include "../../core/wm/memory_definitions.h"
 
 namespace armarx::armem::server::ltm
 {
@@ -26,10 +29,10 @@ namespace armarx::armem::server::ltm
 
         struct ReloadResult
         {
-
         };
 
-        void append(const armem::wm::Memory&);
+        void append(const armem::wm::Memory& memory);
+        void append(const armem::server::wm::Memory& memory);
 
         virtual void reload() = 0;
         virtual void convert(armem::wm::Memory&) = 0;
@@ -61,5 +64,11 @@ namespace armarx::armem::server::ltm
         /// A map from entityID to its latest snapshot stored. When adding a new snapshot we compare it to the last one stored.
         std::map<std::string, const armem::wm::EntitySnapshot*> latestSnapshots;
 
+
+    private:
+
+        template <class ...Args>
+        void _append(const armem::base::MemoryBase<Args...>& memory);
+
     };
-}
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.h b/source/RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.h
index 227d419119e3889006a3f0f30a4789e3b9e76dfe..e9eeffb05667a7e4feeb9c638abea41be02201cd 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.h
@@ -1,18 +1,16 @@
 #pragma once
 
-// STD / STL
+#include <filesystem>
 #include <mutex>
 #include <optional>
-#include <filesystem>
 
-// Base Class
-#include "../LongtermMemoryBase.h"
+#include <RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.h>
+
 
 namespace armarx::armem::server::ltm::disk
 {
     /// @brief A memory storing data in mongodb (needs 'armarx memory start' to start the mongod instance)
-    class MemoryManager :
-        public LongtermMemoryBase
+    class MemoryManager : public LongtermMemoryBase
     {
         using Base = LongtermMemoryBase;
 
@@ -23,14 +21,13 @@ namespace armarx::armem::server::ltm::disk
         void convert(armem::wm::Memory&) override;
         void encodeAndStore() override;
 
-        void setBasePath(const std::filesystem::path& p)
+        void
+        setBasePath(const std::filesystem::path& p)
         {
             basePathToMemory = p;
         }
 
     protected:
-
-
     private:
         bool checkPath() const;
 
@@ -41,4 +38,5 @@ namespace armarx::armem::server::ltm::disk
         static const constexpr char* TYPE_FILENAME = "type.aron.ltm.json";
         static const constexpr char* DATA_FILENAME = "data.aron.ltm.json";
     };
-}
+
+} // namespace armarx::armem::server::ltm::disk
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/operations.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/operations.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..83d2b379d85225e6e369e8711c04ef068e5016e0
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/operations.cpp
@@ -0,0 +1,76 @@
+#include "operations.h"
+
+#include <RobotAPI/libraries/armem/client/query/Builder.h>
+#include <RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.h>
+#include <RobotAPI/libraries/armem/server/query_proc/ltm.h>
+#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
+
+
+namespace armarx::armem::server::ltm
+{
+
+    armem::wm::Memory
+    disk::load(const std::filesystem::path& directory)
+    {
+        const std::string key = directory.filename();
+        armem::server::ltm::disk::MemoryManager manager;
+        manager.setName(key);
+        manager.setBasePath(directory);
+        manager.reload();
+
+        armem::client::QueryBuilder builder;
+        builder.all();
+        armem::client::QueryInput queryInput = builder.buildQueryInput();
+        queryInput.addQueryTargetToAll(armem::query::data::QueryTarget::LTM);
+
+        armem::server::query_proc::ltm::MemoryQueryProcessor processor;
+        armem::wm::Memory memory =
+            processor.process(queryInput.toIce(), manager.getCacheAndLutNotConverted());
+        manager.convert(memory);
+
+        return memory;
+    }
+
+
+    namespace detail
+    {
+        template <class MemoryT>
+        void
+        store(const std::filesystem::path& directory, const MemoryT& memory)
+        {
+            const std::string& name = memory.name();
+            if (std::filesystem::is_regular_file(directory / name))
+            {
+                std::stringstream ss;
+                ss << "Could not export memory '" << name << "' to " << directory << ": "
+                   << "Cannot overwrite existing file.\n";
+                throw error::IOError(directory, ss.str());
+            }
+            else
+            {
+                std::filesystem::create_directories(directory / name);
+
+                armem::server::ltm::disk::MemoryManager manager;
+                manager.setName(name);
+                manager.setBasePath(directory / name);
+                manager.reload();
+                manager.append(memory);
+            }
+        }
+    } // namespace detail
+
+
+    void
+    disk::store(const std::filesystem::path& directory, const armem::wm::Memory& memory)
+    {
+        detail::store(directory, memory);
+    }
+
+
+    void
+    disk::store(const std::filesystem::path& directory, const armem::server::wm::Memory& memory)
+    {
+        detail::store(directory, memory);
+    }
+
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/operations.h b/source/RobotAPI/libraries/armem/server/ltm/disk/operations.h
new file mode 100644
index 0000000000000000000000000000000000000000..b18575996f0ba38b0251844b5b9f18a2c98d0752
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/operations.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <filesystem>
+
+#include <RobotAPI/libraries/armem/core/forward_declarations.h>
+#include <RobotAPI/libraries/armem/server/forward_declarations.h>
+
+
+namespace armarx::armem::server::ltm::disk
+{
+
+    armem::wm::Memory load(const std::filesystem::path& directory);
+
+    void store(const std::filesystem::path& directory, const armem::wm::Memory& memory);
+    void store(const std::filesystem::path& directory, const armem::server::wm::Memory& memory);
+
+
+} // namespace armarx::armem::server::ltm::disk
diff --git a/source/RobotAPI/libraries/armem_gui/disk/ControlWidget.cpp b/source/RobotAPI/libraries/armem_gui/disk/ControlWidget.cpp
index e361438099e5e2a34b80d5f64f810a23fb3270d2..166256ba2e20bc72b560f481069b4fb9a927a825 100644
--- a/source/RobotAPI/libraries/armem_gui/disk/ControlWidget.cpp
+++ b/source/RobotAPI/libraries/armem_gui/disk/ControlWidget.cpp
@@ -1,6 +1,7 @@
 #include "ControlWidget.h"
 
 #include <RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.h>
+#include <RobotAPI/libraries/armem/server/ltm/disk/operations.h>
 #include <RobotAPI/libraries/armem/server/query_proc/ltm.h>
 
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
@@ -148,18 +149,9 @@ namespace armarx::armem::gui::disk
             {
                 if (dir.is_directory())
                 {
-                    const std::string key = dir.path().filename();
-                    armem::server::ltm::disk::MemoryManager manager;
-                    manager.setName(key);
-                    manager.setBasePath(path / key);
-
-                    manager.reload();
-
-                    armem::server::query_proc::ltm::MemoryQueryProcessor ltm_processor;
-                    armem::wm::Memory query_res = ltm_processor.process(queryIce, manager.getCacheAndLutNotConverted());
-
-                    manager.convert(query_res);
-                    memoryData[key] = std::move(query_res);
+                    std::string memoryName = dir.path().filename();
+                    armem::wm::Memory memory = armem::server::ltm::disk::load(dir.path());
+                    memoryData[memoryName] = std::move(memory);
 
                     numLoaded++;
                 }
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 202c4d6c4cc5b94e9a912ee9a24a3387b8542906..c554afd52d27cd534b4015eb2c5114ddd8955181 100644
--- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp
+++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp
@@ -2,15 +2,16 @@
 
 #include <mutex>
 #include <optional>
-#include <Eigen/src/Geometry/Transform.h>
 
-#include "RobotAPI/libraries/ArmarXObjects/aron_conversions/objpose.h"
-#include <ArmarXCore/core/PackagePath.h>
-#include <ArmarXCore/core/logging/Logging.h>
+#include <Eigen/Geometry>
 
+#include "ArmarXCore/core/exceptions/local/ExpressionException.h"
 #include "RobotAPI/libraries/ArmarXObjects/ObjectInfo.h"
 #include "RobotAPI/libraries/ArmarXObjects/ObjectPose.h"
+#include "RobotAPI/libraries/ArmarXObjects/aron_conversions/objpose.h"
 #include "RobotAPI/libraries/armem_objects/aron_conversions.h"
+#include <ArmarXCore/core/PackagePath.h>
+#include <ArmarXCore/core/logging/Logging.h>
 #include <RobotAPI/libraries/ArmarXObjects/aron/ObjectPose.aron.generated.h>
 #include <RobotAPI/libraries/armem/client/query/Builder.h>
 #include <RobotAPI/libraries/armem/core/Time.h>
@@ -32,7 +33,8 @@ namespace armarx::armem::articulated_object
     {
     }
 
-    void Reader::registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def)
+    void
+    Reader::registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def)
     {
         ARMARX_DEBUG << "Reader: registerPropertyDefinitions";
 
@@ -49,7 +51,8 @@ namespace armarx::armem::articulated_object
         def->optional(properties.providerName, prefix + "read.ProviderName");
     }
 
-    void Reader::connect()
+    void
+    Reader::connect()
     {
         // Wait for the memory to become available and add it as dependency.
         ARMARX_IMPORTANT << "Reader: Waiting for memory '" << properties.memoryName << "' ...";
@@ -65,14 +68,15 @@ namespace armarx::armem::articulated_object
         }
 
         armem::MemoryID id = armem::MemoryID();
-        id.memoryName      = properties.memoryName;
+        id.memoryName = properties.memoryName;
         id.coreSegmentName = properties.coreClassSegmentName;
         // listen to all provider segments!
 
         memoryNameSystem.subscribe(id, this, &Reader::updateKnownObjects);
     }
 
-    void Reader::updateKnownObject(const armem::MemoryID& snapshotId)
+    void
+    Reader::updateKnownObject(const armem::MemoryID& snapshotId)
     {
         // const std::string& nameWithDataset = snapshotId.providerSegmentName;
 
@@ -82,8 +86,9 @@ 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!";
 
@@ -106,9 +111,15 @@ namespace armarx::armem::articulated_object
         // });
     }
 
-    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 splits = simox::alg::split(name, "/");
+        ARMARX_CHECK_EQUAL(splits.size(), 3) << "`name` must be of form `DATASET/NAME/INSTANCE`";
+
+        const std::string className = splits.at(0) + "/" + splits.at(1); // `DATASET/NAME`
+        const std::string instanceName = splits.at(2);
+
         const auto description = queryDescription(name, timestamp);
 
         if (not description)
@@ -117,36 +128,42 @@ namespace armarx::armem::articulated_object
             return std::nullopt;
         }
 
-        return get(*description, timestamp);
+        return get(*description, timestamp, instanceName);
     }
 
-    ArticulatedObject Reader::get(const ArticulatedObjectDescription& description,
-                                  const armem::Time& timestamp)
+    ArticulatedObject
+    Reader::get(const ArticulatedObjectDescription& description,
+                const armem::Time& timestamp,
+                const std::string& instanceName)
     {
         ArticulatedObject obj{.description = description,
-                              .instance    = "", // TODO(fabian.reister):
-                              .config      = {}, // will be populated by synchronize
-                              .timestamp   = timestamp};
+                              .instance = instanceName,
+                              .config = {}, // will be populated by `synchronize()`
+                              .timestamp = timestamp};
 
         synchronize(obj, timestamp);
 
         return obj;
     }
 
-    void Reader::synchronize(ArticulatedObject& obj, const armem::Time& timestamp)
+    void
+    Reader::synchronize(ArticulatedObject& obj, const armem::Time& timestamp)
     {
-        auto state = queryState(obj.description, timestamp);
+        ARMARX_CHECK_NOT_EMPTY(obj.instance) << "An instance name must be provided!";
+
+        auto state = queryState(obj.name(), timestamp);
 
         if (not state) /* c++20 [[unlikely]] */
         {
-            ARMARX_WARNING << "Could not synchronize object " << obj.description.name;
+            ARMARX_WARNING << "Could not synchronize object " << obj.instance;
             return;
         }
 
         obj.config = std::move(*state);
     }
 
-    std::vector<robot::RobotDescription> Reader::queryDescriptions(const armem::Time& timestamp)
+    std::vector<robot::RobotDescription>
+    Reader::queryDescriptions(const armem::Time& timestamp)
     {
         // Query all entities from provider.
         armem::client::query::Builder qb;
@@ -171,19 +188,23 @@ namespace armarx::armem::articulated_object
         return getRobotDescriptions(qResult.memory);
     }
 
-    std::string Reader::getProviderName() const
+    std::string
+    Reader::getProviderName() const
     {
         return properties.providerName;
     }
 
-    void Reader::setProviderName(const std::string& providerName)
+    void
+    Reader::setProviderName(const std::string& providerName)
     {
         this->properties.providerName = providerName;
     }
 
-    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)
     {
+        // FIXME: why is `name` unused?
+
         // Query all entities from provider.
         armem::client::query::Builder qb;
 
@@ -208,8 +229,8 @@ namespace armarx::armem::articulated_object
         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 std::string& instanceName, const armem::Time& timestamp)
     {
         // TODO(fabian.reister): how to deal with multiple providers?
 
@@ -220,7 +241,7 @@ namespace armarx::armem::articulated_object
         qb
         .coreSegments().withName(properties.coreInstanceSegmentName)
         .providerSegments().all() // withName(properties.providerName) // agent
-        .entities().withName(description.name)
+        .entities().withName(instanceName)
         .snapshots().latest();
         // clang-format on
 
@@ -237,7 +258,8 @@ namespace armarx::armem::articulated_object
     }
 
 
-    std::optional<robot::RobotState> convertToRobotState(const armem::wm::EntityInstance& instance)
+    std::optional<robot::RobotState>
+    convertToRobotState(const armem::wm::EntityInstance& instance)
     {
         armarx::armem::arondto::ObjectInstance aronObjectInstance;
         try
@@ -253,12 +275,9 @@ namespace armarx::armem::articulated_object
         objpose::ObjectPose objectPose;
         objpose::fromAron(aronObjectInstance.pose, objectPose);
 
-        robot::RobotState robotState
-        {
-            .timestamp = objectPose.timestamp,
-            .globalPose = Eigen::Affine3f(objectPose.objectPoseGlobal),
-            .jointMap = objectPose.objectJointValues
-        };
+        robot::RobotState robotState{.timestamp = objectPose.timestamp,
+                                     .globalPose = Eigen::Affine3f(objectPose.objectPoseGlobal),
+                                     .jointMap = objectPose.objectJointValues};
 
         return robotState;
     }
@@ -272,20 +291,16 @@ namespace armarx::armem::articulated_object
         // clang-format on
 
         std::optional<wm::EntityInstance> instance;
-        coreSegment.forEachInstance([&instance](const wm::EntityInstance & i)
-        {
-            instance = i;
-        });
-        
+        coreSegment.forEachInstance([&instance](const wm::EntityInstance& i) { instance = i; });
+
         if (instance.has_value())
         {
             return convertToRobotState(instance.value());
             // return robot::convertRobotState(instance.value());
         }
-        
+
         ARMARX_FATAL << "Failed to obtain robot state";
         return std::nullopt;
-       
     }
 
 
@@ -297,10 +312,7 @@ namespace armarx::armem::articulated_object
         // clang-format on
 
         std::optional<wm::EntityInstance> instance;
-        coreSegment.forEachInstance([&instance](const wm::EntityInstance & i)
-        {
-            instance = i;
-        });
+        coreSegment.forEachInstance([&instance](const wm::EntityInstance& i) { instance = i; });
 
         if (instance.has_value())
         {
@@ -309,7 +321,6 @@ namespace armarx::armem::articulated_object
 
         ARMARX_DEBUG << "No robot description";
         return std::nullopt;
-       
     }
 
 
@@ -320,17 +331,19 @@ namespace armarx::armem::articulated_object
             memory.getCoreSegment(properties.coreClassSegmentName);
 
         std::vector<robot::RobotDescription> descriptions;
-        coreSegment.forEachEntity([&descriptions](const wm::Entity & entity)
-        {
-            if (not entity.empty())
+        coreSegment.forEachEntity(
+            [&descriptions](const wm::Entity& entity)
             {
-                const auto robotDescription = convertRobotDescription(entity.getFirstSnapshot().getInstance(0));
-                if (robotDescription)
+                if (not entity.empty())
                 {
-                    descriptions.push_back(*robotDescription);
+                    const auto robotDescription =
+                        convertRobotDescription(entity.getFirstSnapshot().getInstance(0));
+                    if (robotDescription)
+                    {
+                        descriptions.push_back(*robotDescription);
+                    }
                 }
-            }
-        });
+            });
 
         return descriptions;
     }
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 e0dca8f3ebd68e682f7bff2bcc759c6bb2673759..3108b17f9b7054a61290a4647d5d3965f17d2fbd 100644
--- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h
+++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h
@@ -50,9 +50,9 @@ namespace armarx::armem::articulated_object
         std::optional<ArticulatedObject> get(const std::string& name,
                                              const armem::Time& timestamp) override;
         ArticulatedObject get(const ArticulatedObjectDescription& description,
-                              const armem::Time& timestamp) override;
+                              const armem::Time& timestamp, const std::string& instanceName) override;
 
-        std::optional<robot::RobotState> queryState(const robot::RobotDescription& description,
+        std::optional<robot::RobotState> queryState(const std::string &instanceName,
                 const armem::Time& timestamp);
         std::optional<robot::RobotDescription> queryDescription(const std::string& name,
                 const armem::Time& timestamp);
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 dcd44d6739bfaa3e211a79721a330cc10b4751fc..05506152012d6527110801adb5bfe5b015a42d1b 100644
--- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp
+++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp
@@ -104,6 +104,8 @@ namespace armarx::armem::articulated_object
 
     std::optional<armem::MemoryID> Writer::storeOrGetClass(const ArticulatedObject& obj)
     {
+        ARMARX_TRACE;
+
         const auto objectId = knownObjects.find(obj.description.name);
 
         // check if exists
@@ -187,7 +189,10 @@ namespace armarx::armem::articulated_object
 
         const auto& timestamp = obj.timestamp;
 
-        ARMARX_DEBUG << "Storing articulated object instance '" << obj.description.name << "' (provider '" << properties.providerName << "')";
+        ARMARX_CHECK(not obj.instance.empty()) << "An object instance name must be provided!";
+        const std::string entityName = obj.description.name + "/" + obj.instance;
+
+        ARMARX_DEBUG << "Storing articulated object instance '" << entityName << "' (provider '" << properties.providerName << "')";
 
         const auto providerId = armem::MemoryID()
                                 .withMemoryName(properties.memoryName)
@@ -195,7 +200,7 @@ namespace armarx::armem::articulated_object
                                 .withProviderSegmentName(properties.providerName);
 
         armem::EntityUpdate update;
-        update.entityID = providerId.withEntityName(obj.description.name);
+        update.entityID = providerId.withEntityName(entityName);
         // .withTimestamp(timestamp); // You only need to specify the entity ID, not the snapshot ID
 
         // arondto::Robot aronArticulatedObject;
diff --git a/source/RobotAPI/libraries/armem_objects/client/articulated_object/interfaces.h b/source/RobotAPI/libraries/armem_objects/client/articulated_object/interfaces.h
index ced0a76fd07fe4575ea4762ea062a804431fff2a..a3061a553cb545605ce37febf9632d6c73d50cda 100644
--- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/interfaces.h
+++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/interfaces.h
@@ -13,7 +13,7 @@ namespace armarx::armem::articulated_object
 
         virtual void synchronize(ArticulatedObject& obj, const armem::Time& timestamp) = 0;
 
-        virtual ArticulatedObject get(const ArticulatedObjectDescription& description, const armem::Time& timestamp) = 0;
+        virtual ArticulatedObject get(const ArticulatedObjectDescription& description, const armem::Time& timestamp, const std::string& instanceName) = 0;
         virtual std::optional<ArticulatedObject> get(const std::string& name, const armem::Time& timestamp) = 0;
     };
 
@@ -26,4 +26,4 @@ namespace armarx::armem::articulated_object
         virtual bool store(const ArticulatedObject& obj) = 0;
     };
 
-}  // namespace armarx::armem::articulated_object
\ No newline at end of file
+}  // namespace armarx::armem::articulated_object
diff --git a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp
index 9668e307ba7c7ff3ed1143087bf4aee1adf2608c..1383ae80470a5e8831326b62c2f34fc39f5a1396 100644
--- a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp
+++ b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp
@@ -937,7 +937,7 @@ namespace armarx::armem::server::obj::instance
             objpose::ObjectPose& pose = objectPoses.emplace_back();
 
             pose.providerName = sceneName;
-            pose.objectType = objpose::ObjectTypeEnum::KnownObject;
+            pose.objectType = objpose::ObjectType::KnownObject;
             pose.isStatic = true;  // Objects loaded from prior knowledge are considerd static to exclude them from decay.
             pose.objectID = classID.withInstanceName(
                                 object.instanceName.empty()
diff --git a/source/RobotAPI/libraries/armem_robot/aron_conversions.cpp b/source/RobotAPI/libraries/armem_robot/aron_conversions.cpp
index da72cc16f995f239c207dfb38dcaa6cf533fb74b..426511a9a8a59dd5cba9545f08f8479c0104d96c 100644
--- a/source/RobotAPI/libraries/armem_robot/aron_conversions.cpp
+++ b/source/RobotAPI/libraries/armem_robot/aron_conversions.cpp
@@ -1,5 +1,6 @@
 #include "aron_conversions.h"
 
+#include "ArmarXCore/core/logging/Logging.h"
 #include <RobotAPI/libraries/aron/common/aron_conversions.h>
 
 #include <RobotAPI/libraries/ArmarXObjects/ObjectID.h>
@@ -107,5 +108,19 @@ namespace armarx::armem
         dto.objectPoseGlobal = bo.globalPose.matrix();
         dto.objectJointValues = bo.jointMap;
     }
+    
+    void robot::fromAron(const armarx::armem::prop::arondto::Platform& dto, robot::PlatformState& bo) 
+    {
+        bo.twist.linear.setZero();
+        bo.twist.linear.head<2>() = dto.velocity.head<2>(); // x and y
+
+        bo.twist.angular.setZero();
+        bo.twist.angular.z() = dto.velocity.z(); // yaw
+    }
+    
+    void robot::toAron(armarx::armem::prop::arondto::Platform& dto, const robot::PlatformState& bo) 
+    {
+        ARMARX_ERROR << "Not implemented yet.";
+    }
 
 }  // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem_robot/aron_conversions.h b/source/RobotAPI/libraries/armem_robot/aron_conversions.h
index 9c124d758a9189b1ec709cca9808b430bbc63a94..e6b462fa866d0c011cb0d899f08ad4e804e3f210 100644
--- a/source/RobotAPI/libraries/armem_robot/aron_conversions.h
+++ b/source/RobotAPI/libraries/armem_robot/aron_conversions.h
@@ -8,6 +8,7 @@
 #include <RobotAPI/libraries/armem_robot/aron/RobotDescription.aron.generated.h>
 #include <RobotAPI/libraries/armem_robot/aron/RobotState.aron.generated.h>
 #include <RobotAPI/libraries/armem_robot/aron/Robot.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot_state/aron/Proprioception.aron.generated.h>
 
 
 namespace armarx::armem::robot
@@ -26,6 +27,8 @@ namespace armarx::armem::robot
     void fromAron(const arondto::RobotState& dto, RobotState& bo);
     void toAron(arondto::RobotState& dto, const RobotState& bo);
 
+    void fromAron(const armarx::armem::prop::arondto::Platform& dto, PlatformState& bo);
+    void toAron(armarx::armem::prop::arondto::Platform& dto, const PlatformState& bo);
 
     void fromAron(const arondto::ObjectClass& dto, RobotDescription& bo);
     void toAron(arondto::ObjectClass& dto, const RobotDescription& bo);
diff --git a/source/RobotAPI/libraries/armem_robot/types.h b/source/RobotAPI/libraries/armem_robot/types.h
index df39df99e945e4a1ef38c38db6f9428404a35bed..ad7454d6fb4f74b49b6909a3a6d362c302203fc9 100644
--- a/source/RobotAPI/libraries/armem_robot/types.h
+++ b/source/RobotAPI/libraries/armem_robot/types.h
@@ -8,6 +8,7 @@
 
 #include <IceUtil/Time.h>
 
+#include "ArmarXCore/core/exceptions/local/ExpressionException.h"
 #include "RobotAPI/libraries/ArmarXObjects/ObjectID.h"
 #include <ArmarXCore/core/PackagePath.h>
 
@@ -22,6 +23,18 @@ namespace armarx::armem::robot
         PackagePath xml{"", std::filesystem::path("")};
     };
 
+
+    struct Twist
+    {
+        Eigen::Vector3f linear;
+        Eigen::Vector3f angular;
+    };
+
+    struct PlatformState
+    {
+        Twist twist;
+    };
+
     struct RobotState
     {
         using JointMap = std::map<std::string, float>;
@@ -41,6 +54,14 @@ namespace armarx::armem::robot
         RobotState config;
 
         IceUtil::Time timestamp;
+
+        std::string name() const 
+        {
+            ARMARX_CHECK_NOT_EMPTY(description.name) << "The robot name must be set!";
+            ARMARX_CHECK_NOT_EMPTY(instance) << "The robot instance name must be provided!";
+
+            return description.name + "/" + instance;
+        }
     };
 
     using Robots = std::vector<Robot>;
diff --git a/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.cpp b/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.cpp
index 57ecaf8de87598880229489908edb300431b96fa..4da91df52e77ecd83fe4c061d0a969bce8bae32f 100644
--- a/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.cpp
@@ -4,6 +4,7 @@
 #include <optional>
 
 #include "ArmarXCore/core/exceptions/local/ExpressionException.h"
+#include "RobotAPI/libraries/armem_robot/types.h"
 #include <ArmarXCore/core/exceptions/LocalException.h>
 #include <ArmarXCore/core/logging/Logging.h>
 #include <ArmarXCore/core/PackagePath.h>
@@ -23,6 +24,7 @@ namespace fs = ::std::filesystem;
 
 namespace armarx::armem::robot_state
 {
+   
 
     RobotReader::RobotReader(armem::client::MemoryNameSystem& memoryNameSystem) :
         memoryNameSystem(memoryNameSystem), transformReader(memoryNameSystem)
@@ -113,11 +115,11 @@ namespace armarx::armem::robot_state
         .snapshots().latest(); // TODO(fabian.reister): atTime(timestamp);
         // clang-format on
 
-        ARMARX_INFO << "Lookup query in reader";
+        ARMARX_DEBUG << "Lookup query in reader";
 
         if (not memoryReader)
         {
-            ARMARX_WARNING << "Memory reader is null";
+            ARMARX_WARNING << "Memory reader is null. Did you forget to call RobotReader::connect() in onConnectComponent()?";
             return std::nullopt;
         }
 
@@ -125,7 +127,7 @@ namespace armarx::armem::robot_state
         {
             const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
 
-            ARMARX_INFO << "Lookup result in reader: " << qResult;
+            ARMARX_DEBUG << "Lookup result in reader: " << qResult;
 
             if (not qResult.success) /* c++20 [[unlikely]] */
             {
@@ -149,14 +151,14 @@ namespace armarx::armem::robot_state
         const auto jointMap = queryJointState(description, timestamp);
         if (not jointMap)
         {
-            ARMARX_WARNING << "Failed to query joint state";
+            ARMARX_WARNING << "Failed to query joint state for robot " << description.name;
             return std::nullopt;
         }
 
         const auto globalPose = queryGlobalPose(description, timestamp);
         if (not globalPose)
         {
-            ARMARX_WARNING << "Failed to query global pose";
+            ARMARX_WARNING << "Failed to query global pose for robot " << description.name;
             return std::nullopt;
         }
 
@@ -197,6 +199,40 @@ namespace armarx::armem::robot_state
         return getRobotJointState(qResult.memory, description.name);
     }
 
+
+
+    std::optional<robot::PlatformState>
+    RobotReader::queryPlatformState(const robot::RobotDescription& description,
+                                 const armem::Time& timestamp) const
+    {
+        // TODO(fabian.reister): how to deal with multiple providers?
+
+        // Query all entities from provider.
+        armem::client::query::Builder qb;
+
+        ARMARX_DEBUG << "Querying robot description for robot: " << description;
+
+        // clang-format off
+        qb
+        .coreSegments().withName(properties.proprioceptionCoreSegment)
+        .providerSegments().withName(description.name) // agent
+        .entities().all() // TODO
+        .snapshots().latest();
+        // clang-format on
+
+        const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
+
+        ARMARX_DEBUG << "Lookup result in reader: " << qResult;
+
+        if (not qResult.success) /* c++20 [[unlikely]] */
+        {
+            ARMARX_WARNING << qResult.errorMessage;
+            return std::nullopt;
+        }
+
+        return getRobotPlatformState(qResult.memory, description.name);
+    }
+
     std::optional<robot::RobotState::Pose>
     RobotReader::queryGlobalPose(const robot::RobotDescription& description,
                                  const armem::Time& timestamp) const
@@ -307,6 +343,34 @@ namespace armarx::armem::robot_state
         return jointMap;
     }
 
+     std::optional<robot::PlatformState>
+    RobotReader::getRobotPlatformState (const armarx::armem::wm::Memory& memory,
+                                    const std::string& name) const
+    {
+        std::optional<robot::PlatformState> platformState;
+
+        // clang-format off
+        const armem::wm::CoreSegment& coreSegment = memory
+                .getCoreSegment(properties.proprioceptionCoreSegment);
+        // clang-format on
+
+        coreSegment.forEachEntity([&platformState](const wm::Entity & entity)
+        {
+            const auto& entityInstance = entity.getLatestSnapshot().getInstance(0);
+
+            const auto proprioception = tryCast<::armarx::armem::arondto::Proprioception>(entityInstance);
+            ARMARX_CHECK(proprioception.has_value());
+
+            platformState = robot::PlatformState(); // initialize optional
+            robot::fromAron(proprioception->platform, platformState.value());
+
+        });
+
+        return platformState;
+    }
+
+
+
     std::optional<robot::RobotDescription>
     RobotReader::getRobotDescription(const armarx::armem::wm::Memory& memory,
                                      const std::string& name) const
diff --git a/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.h b/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.h
index b3f71e59ac2b33c19ff97fd0c238f5540503b6ee..e24bc65fa8a9ca14213bfe79007fc8519f02d176 100644
--- a/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.h
+++ b/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.h
@@ -72,14 +72,24 @@ namespace armarx::armem::robot_state
         queryGlobalPose(const robot::RobotDescription& description,
                         const armem::Time& timestamp) const;
 
+        std::optional<robot::PlatformState>
+        queryPlatformState(const robot::RobotDescription& description,
+                           const armem::Time& timestamp) const;
+
     private:
         std::optional<robot::RobotState> getRobotState(const armarx::armem::wm::Memory& memory,
                 const std::string& name) const;
+
         std::optional<robot::RobotDescription>
         getRobotDescription(const armarx::armem::wm::Memory& memory, const std::string& name) const;
+        
         std::optional<robot::RobotState::JointMap>
         getRobotJointState(const armarx::armem::wm::Memory& memory, const std::string& name) const;
 
+        std::optional<robot::PlatformState>
+        getRobotPlatformState(const armarx::armem::wm::Memory& memory, const std::string& name) const;
+
+
         struct Properties
         {
             std::string memoryName                = "RobotState";
diff --git a/source/RobotAPI/libraries/armem_robot_state/client/common/VirtualRobotReader.cpp b/source/RobotAPI/libraries/armem_robot_state/client/common/VirtualRobotReader.cpp
index 10e13611f3fd8608a5d0b5027fd92b960c3a7754..1c0152a463d5c38abb3b1c81f1014e1f74ef4d77 100644
--- a/source/RobotAPI/libraries/armem_robot_state/client/common/VirtualRobotReader.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/client/common/VirtualRobotReader.cpp
@@ -42,7 +42,7 @@ namespace armarx::armem::robot_state
         const auto robotState = queryState(robotDescription, timestamp);
         if (not robotState)
         {
-            ARMARX_WARNING << "Querying robot state failed!";
+            ARMARX_WARNING << "Querying robot state failed for robot `" << robot.getName() << " / " << robot.getType() << "`!";
             return false;
         }
 
@@ -67,7 +67,9 @@ namespace armarx::armem::robot_state
         const std::string xmlFilename = ArmarXDataPath::resolvePath(description->xml.serialize().path);
         ARMARX_INFO << "Loading (virtual) robot '" << description->name << "' from XML file '" << xmlFilename << "'";
 
-        return VirtualRobot::RobotIO::loadRobot(xmlFilename, loadMode);
+        auto robot = VirtualRobot::RobotIO::loadRobot(xmlFilename, loadMode);
+        robot->setName(name);
+        return robot;
     }
 
 
diff --git a/source/RobotAPI/libraries/armem_vision/CMakeLists.txt b/source/RobotAPI/libraries/armem_vision/CMakeLists.txt
index 1767c9cebd878b1d15cad6f8043a2bd7cf932814..cc81788baa40cf3089de08f3699ac8e9cf026c36 100644
--- a/source/RobotAPI/libraries/armem_vision/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem_vision/CMakeLists.txt
@@ -19,6 +19,7 @@ armarx_add_library(
         ./client/laser_scans/Writer.h
         ./client/occupancy_grid/Reader.h
         ./client/occupancy_grid/Writer.h
+        ./OccupancyGridHelper.h
     SOURCES
         ./aron_conversions.cpp
         ./client/laser_scans/Reader.cpp
diff --git a/source/RobotAPI/libraries/armem_vision/OccupancyGridHelper.h b/source/RobotAPI/libraries/armem_vision/OccupancyGridHelper.h
index 17628ef34fc4ef30fc2b46dd8f031f2fc46dbda3..4b936b6e5bbc7de8141ea380efdac63f3e8d14ad 100644
--- a/source/RobotAPI/libraries/armem_vision/OccupancyGridHelper.h
+++ b/source/RobotAPI/libraries/armem_vision/OccupancyGridHelper.h
@@ -25,7 +25,7 @@ namespace armarx
     public:
         using Params = detail::OccupancyGridHelperParams;
 
-        OccupancyGridHelper(const OccupancyGrid& occupancyGrid, const Params& params);
+        OccupancyGridHelper(const OccupancyGrid& occupancyGrid, const Params& params = Params());
 
         using BinaryArray = Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic>;
 
diff --git a/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Reader.cpp b/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Reader.cpp
index 717a2ec98e5283515a5454bfa31eb7c00636b01c..fe59e94773e8f1a82396705e43be5e51c57c08b0 100644
--- a/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Reader.cpp
+++ b/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Reader.cpp
@@ -48,6 +48,7 @@
 
 namespace armarx::armem::vision::occupancy_grid::client
 {
+    Reader::~Reader() = default;
 
     armarx::armem::client::query::Builder Reader::buildQuery(const Query& query) const
     {
@@ -55,7 +56,7 @@ namespace armarx::armem::vision::occupancy_grid::client
 
         // clang-format off
         qb
-        .coreSegments().withName(properties().memoryName)
+        .coreSegments().withName(properties().coreSegmentName)
         .providerSegments().withName(query.providerName)
         .entities().all()
         .snapshots().beforeOrAtTime(query.timestamp);
@@ -63,6 +64,20 @@ namespace armarx::armem::vision::occupancy_grid::client
 
         return qb;
     }
+    
+    std::string Reader::propertyPrefix() const 
+    {
+        return "mem.vision.occupancy_grid.";
+    }
+    
+    armarx::armem::client::util::SimpleReaderBase::Properties Reader::defaultProperties() const 
+    {
+        return 
+        {
+            .memoryName = "Vision",
+            .coreSegmentName = "OccupancyGrid"
+        };
+    }
 
     OccupancyGrid asOccupancyGrid(const wm::ProviderSegment& providerSegment)
     {
@@ -116,9 +131,19 @@ namespace armarx::armem::vision::occupancy_grid::client
                     .errorMessage  = qResult.errorMessage};
         }
 
-        // now create result from memory
-        const wm::ProviderSegment& providerSegment = qResult.memory.getCoreSegment(properties().memoryName)
-                .getProviderSegment(query.providerName);
+        const auto coreSegment = qResult.memory.getCoreSegment(properties().coreSegmentName);
+
+        if(not coreSegment.hasProviderSegment(query.providerName))
+        {
+            ARMARX_WARNING << "Provider segment `" << query.providerName << "` does not exist (yet).";
+            return
+            {
+                .occupancyGrid = std::nullopt,
+                .status = Result::Status::NoData
+            };
+        }
+
+        const wm::ProviderSegment& providerSegment = coreSegment.getProviderSegment(query.providerName);
 
         if (providerSegment.empty())
         {
diff --git a/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Writer.cpp b/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Writer.cpp
index ce5883afb6eeb72c7ebb9337d0b4980eee7e462e..3275d888db9c8841e1dd7a8baf45582d27ab03ed 100644
--- a/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Writer.cpp
+++ b/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Writer.cpp
@@ -10,12 +10,12 @@ namespace armarx::armem::vision::occupancy_grid::client
 
     bool Writer::store(const OccupancyGrid& grid,
                        const std::string& frame,
-                       const std::string& agentName,
+                       const std::string& providerName,
                        const std::int64_t& timestamp)
     {
         std::lock_guard g{memoryWriterMutex()};
 
-        const auto result = memoryWriter().addSegment(properties().coreSegmentName, agentName);
+        const auto result = memoryWriter().addSegment(properties().coreSegmentName, providerName);
 
         if (not result.success)
         {
diff --git a/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Writer.h b/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Writer.h
index b2a900321224d2c4617cab541c7b1cf77f41d1f1..df5e02ceaa5b2034e0028e7625c616924af8a2bf 100644
--- a/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Writer.h
+++ b/source/RobotAPI/libraries/armem_vision/client/occupancy_grid/Writer.h
@@ -49,7 +49,7 @@ namespace armarx::armem::vision::occupancy_grid::client
 
         bool store(const OccupancyGrid& grid,
                    const std::string& frame,
-                   const std::string& agentName,
+                   const std::string& providerName,
                    const std::int64_t& timestamp);
 
     protected:
diff --git a/source/RobotAPI/libraries/armem_vision/types.h b/source/RobotAPI/libraries/armem_vision/types.h
index dd975e9b1e6e76484c3077bebf9dc99c9f3a8d85..00fb545a104afb19c38c9d7b01fd864ed6ba1fe6 100644
--- a/source/RobotAPI/libraries/armem_vision/types.h
+++ b/source/RobotAPI/libraries/armem_vision/types.h
@@ -45,7 +45,7 @@ namespace armarx::armem
     // template<typename _ValueT = float>
     struct OccupancyGrid
     {
-        float resolution;
+        float resolution; // [mm]
 
         std::string frame;
         Eigen::Affine3f pose;
diff --git a/source/RobotAPI/libraries/aron/converter/eigen/EigenConverter.h b/source/RobotAPI/libraries/aron/converter/eigen/EigenConverter.h
index 4a5a02e56edc8fae399b2a216b4ee77a6f4536d8..810693b3af482ad0863e6dffd59adc0cf7ce68fe 100644
--- a/source/RobotAPI/libraries/aron/converter/eigen/EigenConverter.h
+++ b/source/RobotAPI/libraries/aron/converter/eigen/EigenConverter.h
@@ -150,11 +150,11 @@ namespace armarx::aron::converter
         static Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic> ConvertToDynamicArray(const datanavigator::NDArrayNavigator& nav)
         {
             const auto dims = nav.getDimensions();
+            ARMARX_CHECK_EQUAL(dims.size(), 2);
 
             using ArrayT = Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>;
 
-            ArrayT ret;
-            memcpy(reinterpret_cast<unsigned char*>(ret.data()), nav.getData(), std::accumulate(std::begin(dims), std::end(dims), 1, std::multiplies<>()));
+            ArrayT ret = Eigen::Map<ArrayT>(reinterpret_cast<T*>(nav.getData()), dims.at(0), dims.at(1));
             return ret;
         }
 
diff --git a/source/RobotAPI/libraries/aron/converter/json/CMakeLists.txt b/source/RobotAPI/libraries/aron/converter/json/CMakeLists.txt
index 8f5c8006f3b16d7343a2f74b1c6b6562de426165..d044d9dfedd3933df0293e5e0b04cf3dea09e162 100644
--- a/source/RobotAPI/libraries/aron/converter/json/CMakeLists.txt
+++ b/source/RobotAPI/libraries/aron/converter/json/CMakeLists.txt
@@ -3,8 +3,6 @@ set(LIB_NAME aronjsonconverter)
 armarx_component_set_name("${LIB_NAME}")
 armarx_set_target("Library: ${LIB_NAME}")
 
-find_package(IVT COMPONENTS ivt ivtopencv QUIET)
-armarx_build_if(IVT_FOUND "IVT not available")
 
 set(LIBS
     aron
diff --git a/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/AronCppClass.h b/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/AronCppClass.h
index 790bb1e62538da3cdd0c25908118514f9be3cddd..30f5e54450020945bf1caec30e8be1c153fb17d9 100644
--- a/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/AronCppClass.h
+++ b/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/AronCppClass.h
@@ -47,6 +47,7 @@ namespace armarx::aron::cppserializer
 
     public:
         AronCppClass() = default;
+        virtual ~AronCppClass() = default;
 
         /// Reset all member values of this class to default (as stated in the XML). This may mean that maybe types are null or false and images may be created as headers_only
         virtual void resetHard() = 0;
diff --git a/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/serializer/toplevel/IntEnumClass.cpp b/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/serializer/toplevel/IntEnumClass.cpp
index 0db5f2d68e1de29da18c9327a5b25ee5bd834bc5..5f3c8043a69376538f41f8a55313b53f0c331f80 100644
--- a/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/serializer/toplevel/IntEnumClass.cpp
+++ b/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/serializer/toplevel/IntEnumClass.cpp
@@ -59,7 +59,7 @@ namespace armarx::aron::cppserializer::serializer
         for (const auto& [key, value] : typenavigator->getAcceptedValueMap())
         {
             std::string enumKeyWithNamespace = std::string(IMPL_ENUM) + "::" + key;
-            fields.push_back(std::make_shared<CppField>("const static " + std::string(IMPL_ENUM), key + " = " + enumKeyWithNamespace));
+            fields.push_back(std::make_shared<CppField>("static constexpr " + std::string(IMPL_ENUM), key + " = " + enumKeyWithNamespace));
 
             enum_to_name << "\t\t{" << enumKeyWithNamespace << ", \"" << key << "\"}," << std::endl;
             name_to_enum << "\t\t{\"" << key << "\", " << enumKeyWithNamespace << "}," << std::endl;
diff --git a/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/serializer/toplevel/IntEnumClass.h b/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/serializer/toplevel/IntEnumClass.h
index bd4a0f8128b19bbe28b388e3fa97faddf8f743b1..4a73767f0f800f03be6c1d77759ba17993cac1a3 100644
--- a/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/serializer/toplevel/IntEnumClass.h
+++ b/source/RobotAPI/libraries/aron/core/codegenerator/codeWriter/cpp/serializer/toplevel/IntEnumClass.h
@@ -66,6 +66,6 @@ namespace armarx::aron::cppserializer::serializer
     private:
         // Members
         static const std::map<std::string, std::pair<std::string, int>> ACCEPTED_TYPES;
-        static constexpr const char* IMPL_ENUM = "__ImplEnum";
+        static constexpr const char* IMPL_ENUM = "ImplEnum";
     };
 }
diff --git a/source/RobotAPI/libraries/aron/core/navigator/Navigator.h b/source/RobotAPI/libraries/aron/core/navigator/Navigator.h
index 754d1566b0281cec57568cadee27d2177f75affb..0cd870ab77edc1a72f6cb5c90d8b820bde30b05e 100644
--- a/source/RobotAPI/libraries/aron/core/navigator/Navigator.h
+++ b/source/RobotAPI/libraries/aron/core/navigator/Navigator.h
@@ -47,6 +47,7 @@ namespace armarx::aron
     class Navigator
     {
     public:
+
         // constructors
         Navigator() = default;
         Navigator(const Descriptor& descriptor, const Path& path) :
@@ -54,6 +55,7 @@ namespace armarx::aron
             path(path)
         {
         }
+        virtual ~Navigator() = default;
 
         // public member functions
         Descriptor getDescriptor() const
@@ -76,7 +78,6 @@ namespace armarx::aron
         virtual std::string getName() const = 0;
 
     protected:
-        virtual ~Navigator() = default;
 
         // members
         const Descriptor descriptor;
diff --git a/source/RobotAPI/libraries/aron/core/test/aronRandomizedTest.cpp b/source/RobotAPI/libraries/aron/core/test/aronRandomizedTest.cpp
index 4ff0724c95ca3c0cbc31dd051b6ba3afdff37fe9..b9c54acda1e8d0e1b70477427a2d8c848bbedb15 100644
--- a/source/RobotAPI/libraries/aron/core/test/aronRandomizedTest.cpp
+++ b/source/RobotAPI/libraries/aron/core/test/aronRandomizedTest.cpp
@@ -384,3 +384,11 @@ BOOST_AUTO_TEST_CASE(test_Optional)
     OptionalTest pc2;
     runTestWithInstances<OptionalTest>(pc, pc2);
 }
+
+
+BOOST_AUTO_TEST_CASE(test_Enum)
+{
+    BOOST_TEST_MESSAGE("Running Optional test");
+    TheIntEnum value = TheIntEnum::INT_ENUM_VALUE_2;
+    BOOST_CHECK_EQUAL(value.toString(), "INT_ENUM_VALUE_2");
+}