diff --git a/scenarios/ArViz/ArViz.scx b/scenarios/ArViz/ArViz.scx new file mode 100644 index 0000000000000000000000000000000000000000..9db4bd77abbffafe413daf98d0024aa7716241d4 --- /dev/null +++ b/scenarios/ArViz/ArViz.scx @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<scenario name="ArViz" creation="2020-10-09.12:02:02" globalConfigName="./config/global.cfg" package="RobotAPI" deploymentType="local" nodeName="NodeMain"> + <application name="ArVizStorage" instance="" package="RobotAPI" nodeName="" enabled="true" iceAutoRestart="false"/> + <application name="DebugObserver" instance="" package="ArmarXCore" nodeName="" enabled="true" iceAutoRestart="false"/> +</scenario> + diff --git a/scenarios/ArViz/config/ArVizStorage.cfg b/scenarios/ArViz/config/ArVizStorage.cfg new file mode 100644 index 0000000000000000000000000000000000000000..0dcbd8d5775b8c0f562bba62b5f2fe282e2da6d0 --- /dev/null +++ b/scenarios/ArViz/config/ArVizStorage.cfg @@ -0,0 +1,212 @@ +# ================================================================== +# ArVizStorage 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.ArVizStorage.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.ArVizStorage.EnableProfiling = false + + +# ArmarX.ArVizStorage.HistoryPath: Destination path where the history are serialized to +# Attributes: +# - Default: RobotAPI/ArVizStorage +# - Case sensitivity: yes +# - Required: no +# ArmarX.ArVizStorage.HistoryPath = RobotAPI/ArVizStorage + + +# ArmarX.ArVizStorage.MaxHistorySize: How many layer updates are saved in the history until they are compressed +# Attributes: +# - Default: 1000 +# - Case sensitivity: yes +# - Required: no +# ArmarX.ArVizStorage.MaxHistorySize = 1000 + + +# ArmarX.ArVizStorage.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.ArVizStorage.MinimumLoggingLevel = Undefined + + +# ArmarX.ArVizStorage.ObjectName: Name of IceGrid well-known object +# Attributes: +# - Default: "" +# - Case sensitivity: yes +# - Required: no +# ArmarX.ArVizStorage.ObjectName = "" + + +# ArmarX.ArVizStorage.TopicName: Layer updates are sent over this topic. +# Attributes: +# - Default: ArVizTopic +# - Case sensitivity: yes +# - Required: no +# ArmarX.ArVizStorage.TopicName = ArVizTopic + + +# 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.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/ArViz/config/DebugObserver.cfg b/scenarios/ArViz/config/DebugObserver.cfg new file mode 100644 index 0000000000000000000000000000000000000000..4a0b9dac036cd4d103efd7d1b718d508f285d85a --- /dev/null +++ b/scenarios/ArViz/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/ArViz/config/global.cfg b/scenarios/ArViz/config/global.cfg new file mode 100644 index 0000000000000000000000000000000000000000..1ffed4089a8f737783aeee687af3ce5e4dd287a7 --- /dev/null +++ b/scenarios/ArViz/config/global.cfg @@ -0,0 +1,4 @@ +# ================================================================== +# Global Config from Scenario ArViz +# ================================================================== + diff --git a/scenarios/ArVizExample/config/RobotToArVizApp.cfg b/scenarios/ArVizExample/config/RobotToArVizApp.cfg index a38badd327185c65c1cdbb4b19b5534ab438b0e4..b023833a9d18ac3f4c1d92911b29ad1f8699a22c 100644 --- a/scenarios/ArVizExample/config/RobotToArVizApp.cfg +++ b/scenarios/ArVizExample/config/RobotToArVizApp.cfg @@ -168,6 +168,15 @@ # ArmarX.RobotToArViz.ShowRobotNodeFrames = false +# ArmarX.RobotToArViz.UseCollisionModel: Use the collision model for visualization +# Attributes: +# - Default: false +# - Case sensitivity: yes +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +# ArmarX.RobotToArViz.UseCollisionModel = false + + # ArmarX.RobotToArViz.updateFrequency: Target number of updates per second. # Attributes: # - Default: 100 diff --git a/scenarios/ObjectPoseObserverExample/ObjectPoseObserverExample.scx b/scenarios/ObjectPoseObserverExample/ObjectPoseObserverExample.scx new file mode 100644 index 0000000000000000000000000000000000000000..f08898f6ac0177295ddaeb2858aeed9dcdea6eab --- /dev/null +++ b/scenarios/ObjectPoseObserverExample/ObjectPoseObserverExample.scx @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<scenario name="ObjectPoseObserverExample" creation="2020-08-03.10:09:13" globalConfigName="./config/global.cfg" package="RobotAPI" deploymentType="local" nodeName="NodeMain"> + <application name="ObjectPoseObserver" instance="" package="RobotAPI" nodeName="" enabled="true" iceAutoRestart="false"/> + <application name="ObjectPoseProviderExample" instance="" package="RobotAPI" nodeName="" enabled="true" iceAutoRestart="false"/> + <application name="RemoteGuiProviderApp" instance="" package="ArmarXGui" nodeName="" enabled="true" iceAutoRestart="false"/> + <application name="RobotStateComponent" instance="" package="RobotAPI" nodeName="" enabled="true" iceAutoRestart="false"/> +</scenario> + diff --git a/scenarios/ObjectPoseObserverExample/config/ArVizStorage.cfg b/scenarios/ObjectPoseObserverExample/config/ArVizStorage.cfg new file mode 100644 index 0000000000000000000000000000000000000000..0dcbd8d5775b8c0f562bba62b5f2fe282e2da6d0 --- /dev/null +++ b/scenarios/ObjectPoseObserverExample/config/ArVizStorage.cfg @@ -0,0 +1,212 @@ +# ================================================================== +# ArVizStorage 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.ArVizStorage.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.ArVizStorage.EnableProfiling = false + + +# ArmarX.ArVizStorage.HistoryPath: Destination path where the history are serialized to +# Attributes: +# - Default: RobotAPI/ArVizStorage +# - Case sensitivity: yes +# - Required: no +# ArmarX.ArVizStorage.HistoryPath = RobotAPI/ArVizStorage + + +# ArmarX.ArVizStorage.MaxHistorySize: How many layer updates are saved in the history until they are compressed +# Attributes: +# - Default: 1000 +# - Case sensitivity: yes +# - Required: no +# ArmarX.ArVizStorage.MaxHistorySize = 1000 + + +# ArmarX.ArVizStorage.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.ArVizStorage.MinimumLoggingLevel = Undefined + + +# ArmarX.ArVizStorage.ObjectName: Name of IceGrid well-known object +# Attributes: +# - Default: "" +# - Case sensitivity: yes +# - Required: no +# ArmarX.ArVizStorage.ObjectName = "" + + +# ArmarX.ArVizStorage.TopicName: Layer updates are sent over this topic. +# Attributes: +# - Default: ArVizTopic +# - Case sensitivity: yes +# - Required: no +# ArmarX.ArVizStorage.TopicName = ArVizTopic + + +# 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.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/ObjectPoseObserverExample/config/DebugObserver.cfg b/scenarios/ObjectPoseObserverExample/config/DebugObserver.cfg new file mode 100644 index 0000000000000000000000000000000000000000..4a0b9dac036cd4d103efd7d1b718d508f285d85a --- /dev/null +++ b/scenarios/ObjectPoseObserverExample/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/ObjectPoseObserverExample/config/ObjectPoseObserver.cfg b/scenarios/ObjectPoseObserverExample/config/ObjectPoseObserver.cfg new file mode 100644 index 0000000000000000000000000000000000000000..d14b730f3ab022ddb4bfc9bc0fea2038d5cd03ab --- /dev/null +++ b/scenarios/ObjectPoseObserverExample/config/ObjectPoseObserver.cfg @@ -0,0 +1,313 @@ +# ================================================================== +# ObjectPoseObserver 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.ObjectPoseObserver.ArVizTopicName: Name of the ArViz topic +# Attributes: +# - Default: ArVizTopic +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseObserver.ArVizTopicName = ArVizTopic + + +# ArmarX.ObjectPoseObserver.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.ObjectPoseObserver.CreateUpdateFrequenciesChannel = false + + +# ArmarX.ObjectPoseObserver.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.ObjectPoseObserver.EnableProfiling = false + + +# ArmarX.ObjectPoseObserver.MaxHistoryRecordFrequency: The Observer history is written with this maximum frequency. Everything faster is being skipped. +# Attributes: +# - Default: 50 +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseObserver.MaxHistoryRecordFrequency = 50 + + +# ArmarX.ObjectPoseObserver.MaxHistorySize: Maximum number of entries in the Observer history +# Attributes: +# - Default: 5000 +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseObserver.MaxHistorySize = 5000 + + +# ArmarX.ObjectPoseObserver.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.ObjectPoseObserver.MinimumLoggingLevel = Undefined + + +# ArmarX.ObjectPoseObserver.ObjectName: Name of IceGrid well-known object +# Attributes: +# - Default: "" +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseObserver.ObjectName = "" + + +# ArmarX.ObjectPoseObserver.ObjectPoseTopicName: Name of the Object Pose Topic. +# Attributes: +# - Default: ObjectPoseTopic +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseObserver.ObjectPoseTopicName = ObjectPoseTopic + + +# ArmarX.ObjectPoseObserver.RemoteGuiName: Name of the remote gui provider +# Attributes: +# - Default: RemoteGuiProvider +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseObserver.RemoteGuiName = RemoteGuiProvider + + +# ArmarX.ObjectPoseObserver.RemoteStateComponentName: Name of the robot state component +# Attributes: +# - Default: RobotStateComponent +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseObserver.RemoteStateComponentName = RobotStateComponent + + +# ArmarX.ObjectPoseObserver.calibration.offset: Offset for the node to be calibrated +# Attributes: +# - Default: 0 +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseObserver.calibration.offset = 0 + + +# ArmarX.ObjectPoseObserver.calibration.robotNode: Robot node which can be calibrated +# Attributes: +# - Default: Neck_2_Pitch +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseObserver.calibration.robotNode = Neck_2_Pitch + + +# ArmarX.ObjectPoseObserver.visu.alpha: Alpha of objects (1 = solid, 0 = transparent). +# Attributes: +# - Default: 1 +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseObserver.visu.alpha = 1 + + +# ArmarX.ObjectPoseObserver.visu.enabled: Enable or disable visualization of objects. +# Attributes: +# - Default: false +# - Case sensitivity: yes +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +ArmarX.ObjectPoseObserver.visu.enabled = true + + +# ArmarX.ObjectPoseObserver.visu.inGlobalFrame: If true, show global poses. If false, show poses in robot frame. +# Attributes: +# - Default: true +# - Case sensitivity: yes +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +# ArmarX.ObjectPoseObserver.visu.inGlobalFrame = true + + +# ArmarX.ObjectPoseObserver.visu.objectFrames: Enable showing object frames. +# Attributes: +# - Default: false +# - Case sensitivity: yes +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +# ArmarX.ObjectPoseObserver.visu.objectFrames = false + + +# ArmarX.ObjectPoseObserver.visu.objectFramesScale: Scaling of object frames. +# Attributes: +# - Default: 1 +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseObserver.visu.objectFramesScale = 1 + + +# ArmarX.ObjectPoseObserver.visu.oobbs: Enable showing oriented bounding boxes. +# Attributes: +# - Default: false +# - Case sensitivity: yes +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +# ArmarX.ObjectPoseObserver.visu.oobbs = false + + +# 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/ObjectPoseObserverExample/config/ObjectPoseProviderExample.cfg b/scenarios/ObjectPoseObserverExample/config/ObjectPoseProviderExample.cfg new file mode 100644 index 0000000000000000000000000000000000000000..53ccf9cb429c6f9b94ebf0aed72f3a72a9c368a9 --- /dev/null +++ b/scenarios/ObjectPoseObserverExample/config/ObjectPoseProviderExample.cfg @@ -0,0 +1,213 @@ +# ================================================================== +# ObjectPoseProviderExample 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.ObjectPoseProviderExample.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.ObjectPoseProviderExample.EnableProfiling = false + + +# ArmarX.ObjectPoseProviderExample.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.ObjectPoseProviderExample.MinimumLoggingLevel = Undefined + + +# ArmarX.ObjectPoseProviderExample.ObjectName: Name of IceGrid well-known object +# Attributes: +# - Default: "" +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseProviderExample.ObjectName = "" + + +# ArmarX.ObjectPoseProviderExample.ObjectPoseTopicName: Name of the object pose topic. +# Attributes: +# - Default: ObjectPoseTopic +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseProviderExample.ObjectPoseTopicName = ObjectPoseTopic + + +# ArmarX.ObjectPoseProviderExample.Objects: Object IDs of objects to be tracked. +# Attributes: +# - Default: KIT/Amicelli, KIT/YellowSaltCylinder +# - Case sensitivity: yes +# - Required: no +# - Possible values: {KIT/Amicelli, KIT/YellowSaltCylinder} +ArmarX.ObjectPoseProviderExample.Objects = KIT/Amicelli, YCB/002_master_chef_can + + +# ArmarX.ObjectPoseProviderExample.tpc.pub.DebugObserver: Name of the `DebugObserver` topic to publish data to. +# Attributes: +# - Default: DebugObserver +# - Case sensitivity: yes +# - Required: no +# ArmarX.ObjectPoseProviderExample.tpc.pub.DebugObserver = DebugObserver + + +# 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/ObjectPoseObserverExample/config/RemoteGuiProviderApp.cfg b/scenarios/ObjectPoseObserverExample/config/RemoteGuiProviderApp.cfg new file mode 100644 index 0000000000000000000000000000000000000000..4fd690cefd94559b207493cf40e346a3e47f3b12 --- /dev/null +++ b/scenarios/ObjectPoseObserverExample/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/ObjectPoseObserverExample/config/RobotStateComponent.cfg b/scenarios/ObjectPoseObserverExample/config/RobotStateComponent.cfg new file mode 100644 index 0000000000000000000000000000000000000000..2755127da3115e43c83b7d3e946a31020f3b71af --- /dev/null +++ b/scenarios/ObjectPoseObserverExample/config/RobotStateComponent.cfg @@ -0,0 +1,324 @@ +# ================================================================== +# RobotStateComponent 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.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.RobotStateComponent.AgentName: Name of the agent for which the sensor values are provided +# Attributes: +# - Case sensitivity: yes +# - Required: yes +# ArmarX.RobotStateComponent.AgentName = ::_NOT_SET_:: + + +# ArmarX.RobotStateComponent.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.RobotStateComponent.EnableProfiling = false + + +# ArmarX.RobotStateComponent.GlobalRobotPoseLocalizationTopicName: Topic where the global robot pose can be reported. +# Attributes: +# - Default: GlobalRobotPoseLocalization +# - Case sensitivity: yes +# - Required: no +# ArmarX.RobotStateComponent.GlobalRobotPoseLocalizationTopicName = GlobalRobotPoseLocalization + + +# ArmarX.RobotStateComponent.HistoryLength: Number of entries in the robot state history +# Attributes: +# - Default: 10000 +# - Case sensitivity: yes +# - Required: no +# ArmarX.RobotStateComponent.HistoryLength = 10000 + + +# ArmarX.RobotStateComponent.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.RobotStateComponent.MinimumLoggingLevel = Undefined + + +# ArmarX.RobotStateComponent.ObjectName: Name of IceGrid well-known object +# Attributes: +# - Default: "" +# - Case sensitivity: yes +# - Required: no +# ArmarX.RobotStateComponent.ObjectName = "" + + +# ArmarX.RobotStateComponent.PlatformTopicName: Topic where platform state is published. +# Attributes: +# - Default: PlatformState +# - Case sensitivity: yes +# - Required: no +# ArmarX.RobotStateComponent.PlatformTopicName = PlatformState + + +# ArmarX.RobotStateComponent.RobotFileName: Filename of VirtualRobot robot model (e.g. robot_model.xml) +# Attributes: +# - Case sensitivity: yes +# - Required: yes +# ArmarX.RobotStateComponent.RobotFileName = ::_NOT_SET_:: + + +# ArmarX.RobotStateComponent.RobotModelScaling: Scaling of the robot model +# Attributes: +# - Default: 1 +# - Case sensitivity: yes +# - Required: no +# ArmarX.RobotStateComponent.RobotModelScaling = 1 + + +# ArmarX.RobotStateComponent.RobotNodeSetName: Set of nodes that is controlled by the KinematicUnit +# Attributes: +# - Case sensitivity: yes +# - Required: yes +# ArmarX.RobotStateComponent.RobotNodeSetName = ::_NOT_SET_:: + + +# ArmarX.RobotStateComponent.RobotStateReportingTopic: Name of the topic on which updates of the robot state are reported. +# Attributes: +# - Default: RobotStateUpdates +# - Case sensitivity: yes +# - Required: no +# ArmarX.RobotStateComponent.RobotStateReportingTopic = RobotStateUpdates + + +# ArmarX.RobotStateComponent.TopicPrefix: Prefix for the sensor value topic name. +# Attributes: +# - Default: "" +# - Case sensitivity: yes +# - Required: no +# ArmarX.RobotStateComponent.TopicPrefix = "" + + +# ArmarX.RobotStateComponent.inheritFrom: No Description +# Attributes: +# - Default: RobotConfig +# - Case sensitivity: no +# - Required: no +ArmarX.RobotStateComponent.inheritFrom = RobotConfig + + +# ArmarX.RobotStateObserver.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.RobotStateObserver.CreateUpdateFrequenciesChannel = false + + +# ArmarX.RobotStateObserver.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.RobotStateObserver.EnableProfiling = false + + +# ArmarX.RobotStateObserver.MaxHistoryRecordFrequency: The Observer history is written with this maximum frequency. Everything faster is being skipped. +# Attributes: +# - Default: 50 +# - Case sensitivity: yes +# - Required: no +# ArmarX.RobotStateObserver.MaxHistoryRecordFrequency = 50 + + +# ArmarX.RobotStateObserver.MaxHistorySize: Maximum number of entries in the Observer history +# Attributes: +# - Default: 5000 +# - Case sensitivity: yes +# - Required: no +# ArmarX.RobotStateObserver.MaxHistorySize = 5000 + + +# ArmarX.RobotStateObserver.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.RobotStateObserver.MinimumLoggingLevel = Undefined + + +# ArmarX.RobotStateObserver.ObjectName: Name of IceGrid well-known object +# Attributes: +# - Default: "" +# - Case sensitivity: yes +# - Required: no +# ArmarX.RobotStateObserver.ObjectName = "" + + +# ArmarX.RobotStateObserver.TCPsToReport: comma seperated list of nodesets' endeffectors, which poses and velocities that should be reported. * for all, empty for none +# Attributes: +# - Default: "" +# - Case sensitivity: yes +# - Required: no +# ArmarX.RobotStateObserver.TCPsToReport = "" + + +# 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/ObjectPoseObserverExample/config/global.cfg b/scenarios/ObjectPoseObserverExample/config/global.cfg new file mode 100644 index 0000000000000000000000000000000000000000..7c603bf9905a566cbf240054770023ad225aebbc --- /dev/null +++ b/scenarios/ObjectPoseObserverExample/config/global.cfg @@ -0,0 +1,52 @@ +# ================================================================== +# Global Config from Scenario ObjectPoseObserverExample +# ================================================================== + +# RobotConfig.AgentName: Custom Property +# Attributes: +# - Default: ::NOT_DEFINED:: +# - Case sensitivity: no +# - Required: no +RobotConfig.AgentName = Armar6 + + +# RobotConfig.ForceTorqueTopicName: Custom Property +# Attributes: +# - Default: ::NOT_DEFINED:: +# - Case sensitivity: no +# - Required: no +RobotConfig.ForceTorqueTopicName = Armar6ForceTorqueUnitState + + +# RobotConfig.KinematicUnitName: Custom Property +# Attributes: +# - Default: ::NOT_DEFINED:: +# - Case sensitivity: no +# - Required: no +RobotConfig.KinematicUnitName = Armar6KinematicUnit + + +# RobotConfig.PlatformName: Custom Property +# Attributes: +# - Default: ::NOT_DEFINED:: +# - Case sensitivity: no +# - Required: no +RobotConfig.PlatformName = Platform + + +# RobotConfig.RobotFileName: Custom Property +# Attributes: +# - Default: ::NOT_DEFINED:: +# - Case sensitivity: no +# - Required: no +RobotConfig.RobotFileName = Armar6RT/robotmodel/Armar6-SH/Armar6-SH.xml + + +# RobotConfig.RobotNodeSetName: Custom Property +# Attributes: +# - Default: ::NOT_DEFINED:: +# - Case sensitivity: no +# - Required: no +RobotConfig.RobotNodeSetName = Robot + + diff --git a/source/RobotAPI/components/CMakeLists.txt b/source/RobotAPI/components/CMakeLists.txt index fb382b82c1c1cf054a24da77b2e2cf5a22540bb4..0d6b340500a1ba58576ee7c4ead23fe9e6b666df 100644 --- a/source/RobotAPI/components/CMakeLists.txt +++ b/source/RobotAPI/components/CMakeLists.txt @@ -15,6 +15,7 @@ add_subdirectory(KITProstheticHandUnit) add_subdirectory(MultiHandUnit) add_subdirectory(NaturalIKTest) add_subdirectory(ObjectPoseObserver) +add_subdirectory(ObjectPoseProviderExample) add_subdirectory(RobotHealth) add_subdirectory(RobotNameService) add_subdirectory(RobotState) diff --git a/source/RobotAPI/components/ObjectPoseObserver/CMakeLists.txt b/source/RobotAPI/components/ObjectPoseObserver/CMakeLists.txt index f369dd0247620277b719e59891bbff9c88d13e6e..2dac9b5a5138fe9664c22e03d2ee5015ba3f444d 100644 --- a/source/RobotAPI/components/ObjectPoseObserver/CMakeLists.txt +++ b/source/RobotAPI/components/ObjectPoseObserver/CMakeLists.txt @@ -15,6 +15,7 @@ set(SOURCES plugins/ObjectPoseProviderPlugin.cpp plugins/ObjectPoseClientPlugin.cpp + plugins/RequestedObjects.cpp ice_conversions.cpp json_conversions.cpp @@ -25,6 +26,7 @@ set(HEADERS plugins/ObjectPoseProviderPlugin.h plugins/ObjectPoseClientPlugin.h + plugins/RequestedObjects.h ice_conversions.h json_conversions.h @@ -45,6 +47,5 @@ armarx_add_component("${SOURCES}" "${HEADERS}") # add unit tests add_subdirectory(test) -armarx_component_set_name("ObjectPoseObserverApp") -set(COMPONENT_LIBS ObjectPoseObserver) -armarx_add_component_executable(main.cpp) +# generate the application +armarx_generate_and_add_component_executable() diff --git a/source/RobotAPI/components/ObjectPoseObserver/ObjectPose.cpp b/source/RobotAPI/components/ObjectPoseObserver/ObjectPose.cpp index af808d1de3634821a761e2ae4bb3183aa1e2bcfd..6ca0338ce6c4c8edae44bb3248d9d4e8b1ea6c03 100644 --- a/source/RobotAPI/components/ObjectPoseObserver/ObjectPose.cpp +++ b/source/RobotAPI/components/ObjectPoseObserver/ObjectPose.cpp @@ -7,6 +7,7 @@ #include <RobotAPI/libraries/core/Pose.h> #include <RobotAPI/libraries/core/FramedPose.h> +#include <RobotAPI/libraries/ArmarXObjects/ice_conversions.h> #include "ice_conversions.h" @@ -45,7 +46,7 @@ namespace armarx::objpose { providerName = ice.providerName; objectType = ice.objectType; - objectID = { ice.objectID.dataset, ice.objectID.className, ice.objectID.instanceName }; + armarx::fromIce(ice.objectID, objectID); objectPoseRobot = armarx::objpose::toEigen(ice.objectPoseRobot); objectPoseGlobal = armarx::objpose::toEigen(ice.objectPoseGlobal); @@ -72,7 +73,7 @@ namespace armarx::objpose { ice.providerName = providerName; ice.objectType = objectType; - ice.objectID = { objectID.dataset(), objectID.className(), objectID.instanceName() }; + armarx::toIce(ice.objectID, objectID); ice.objectPoseRobot = new Pose(objectPoseRobot); ice.objectPoseGlobal = new Pose(objectPoseGlobal); @@ -92,8 +93,7 @@ namespace armarx::objpose { providerName = provided.providerName; objectType = provided.objectType; - - objectID = { provided.objectID.dataset, provided.objectID.className, provided.objectID.instanceName }; + armarx::fromIce(provided.objectID, objectID); objectPoseOriginal = armarx::objpose::toEigen(provided.objectPose); objectPoseOriginalFrame = provided.objectPoseFrame; diff --git a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp index fda9571084893b61eef4cdde94a599720bc3fd34..892094431698411a2ad66189986a7fa0f2cbb6ef 100644 --- a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp +++ b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp @@ -32,6 +32,7 @@ #include <RobotAPI/libraries/core/Pose.h> #include <RobotAPI/libraries/core/FramedPose.h> +#include <RobotAPI/libraries/ArmarXObjects/ice_conversions.h> #include "ice_conversions.h" @@ -150,10 +151,9 @@ namespace armarx } - void ObjectPoseObserver::reportProviderAvailable(const std::string& providerName, const Ice::Current&) + void ObjectPoseObserver::reportProviderAvailable(const std::string& providerName, const objpose::ProviderInfo& info, const Ice::Current&) { - static const bool refresh = true; - fetchProviderInfo(providerName, refresh); + updateProviderInfo(providerName, info); } void ObjectPoseObserver::reportObjectPoses( @@ -161,9 +161,6 @@ namespace armarx { ARMARX_VERBOSE << "Received object poses from '" << providerName << "'."; - static const bool refresh = false; - fetchProviderInfo(providerName, refresh); - objpose::ObjectPoseSeq objectPoses; { std::scoped_lock lock(dataMutex); @@ -203,37 +200,23 @@ namespace armarx } - void ObjectPoseObserver::fetchProviderInfo(const std::string& providerName, bool refresh) + void ObjectPoseObserver::updateProviderInfo(const std::string& providerName, const objpose::ProviderInfo& info) { + if (!info.proxy) { - std::scoped_lock lock(dataMutex); - if (!refresh && providers.count(providerName) > 0) - { - return; // Do nothing. - } - } - - objpose::ObjectPoseProviderPrx provider = getProviderProxy(providerName); - if (!provider) - { - ARMARX_WARNING << "Received availability signal from provider '" << providerName << "', " - << "but could not get provider proxy."; + ARMARX_WARNING << "Received availability signal from provider '" << providerName << "' " + << "with invalid provider proxy.\nIgnoring provider '" << providerName << "'."; return; } - objpose::ProviderInfo info = provider->getProviderInfo(); - { std::scoped_lock lock(dataMutex); - if (providers.count(providerName) == 0) + std::stringstream ss; + for (const auto& id : info.supportedObjects) { - std::stringstream ss; - for (const auto& id : info.supportedObjects) - { - ss << "- " << id << "\n"; - } - ARMARX_VERBOSE << "New provider '" << providerName << "' available.\n" - << "Supported objects: \n" << ss.str(); + ss << "- " << id << "\n"; } + ARMARX_VERBOSE << "Provider '" << providerName << "' available.\n" + << "Supported objects: \n" << ss.str(); providers[providerName] = info; if (updateCounters.count(providerName) == 0) @@ -246,7 +229,8 @@ namespace armarx { offerChannel(providerName, "Channel of provider '" + providerName + "'."); } - offerOrUpdateDataField(providerName, "objectType", objpose::ObjectTypeEnumNames.to_name(info.objectType), ""); + offerOrUpdateDataField(providerName, "objectType", objpose::ObjectTypeEnumNames.to_name(info.objectType), "The object type (known or unknown)"); + offerOrUpdateDataField(providerName, "numSupportedObjects", int(info.supportedObjects.size()), "Number of requestable objects."); } @@ -275,38 +259,83 @@ namespace armarx } - void ObjectPoseObserver::requestObjects(const objpose::ObjectIDSeq& objectIDs, Ice::Long relativeTimeoutMS, const Ice::Current&) + objpose::observer::RequestObjectsOutput ObjectPoseObserver::requestObjects( + const objpose::observer::RequestObjectsInput& input, const Ice::Current&) { - std::map<std::string, objpose::ObjectIDSeq> requests; + std::map<std::string, objpose::provider::RequestObjectsInput> providerRequests; + std::map<std::string, objpose::ObjectPoseProviderPrx> proxies; + + objpose::observer::RequestObjectsOutput output; + + auto updateProxy = [&](const std::string & providerName) + { + if (proxies.count(providerName) == 0) + { + if (auto it = providers.find(providerName); it != providers.end()) + { + proxies[providerName] = it->second.proxy; + } + else + { + ARMARX_ERROR << "No proxy for provider ' " << providerName << "'."; + proxies[providerName] = nullptr; + } + } + }; + if (input.provider.size() > 0) + { + providerRequests[input.provider] = input.request; + updateProxy(input.provider); + } + else { std::scoped_lock lock(dataMutex); - for (const auto& objectID : objectIDs) + for (const auto& objectID : input.request.objectIDs) { - for (const auto& [name, info] : providers) + bool found = true; + for (const auto& [providerName, info] : providers) { // ToDo: optimize look up. if (std::find(info.supportedObjects.begin(), info.supportedObjects.end(), objectID) != info.supportedObjects.end()) { - requests[name].push_back(objectID); + providerRequests[providerName].objectIDs.push_back(objectID); + updateProxy(providerName); + break; } } + if (!found) + { + ARMARX_ERROR << "Did not find a provider for " << objectID << "."; + output.results[objectID].providerName = ""; + } } } - for (const auto& [providerName, objects] : requests) + for (const auto& [providerName, request] : providerRequests) { - objpose::ObjectPoseProviderPrx provider = getProviderProxy(providerName); - if (provider) + if (objpose::ObjectPoseProviderPrx proxy = proxies.at(providerName); proxy) { - ARMARX_VERBOSE << "Requesting provider '" << providerName << "' for objects " << objects; - provider->requestObjects(objects, relativeTimeoutMS); + ARMARX_INFO << "Requesting " << request.objectIDs.size() << " objects from provider '" + << providerName << "' for " << request.relativeTimeoutMS << " ms."; + objpose::provider::RequestObjectsOutput providerOutput = proxy->requestObjects(request); + + int successful = 0; + for (const auto& [objectID, result] : providerOutput.results) + { + objpose::observer::ObjectRequestResult& res = output.results[objectID]; + res.providerName = providerName; + res.result = result; + successful += int(result.success); + } + ARMARX_INFO << successful << " of " << request.objectIDs.size() << " object requests successful."; } } + return output; } - objpose::ProviderInfoMap ObjectPoseObserver::getAvailableProvidersWithInfo(const Ice::Current&) + objpose::ProviderInfoMap ObjectPoseObserver::getAvailableProvidersInfo(const Ice::Current&) { std::scoped_lock lock(dataMutex); return providers; @@ -344,18 +373,6 @@ namespace armarx } - Ice::Int ObjectPoseObserver::getUpdateCounterByProvider(const std::string& providerName, const Ice::Current&) - { - std::scoped_lock lock(dataMutex); - return updateCounters.at(providerName); - } - - StringIntDictionary ObjectPoseObserver::getAllUpdateCounters(const Ice::Current&) - { - return updateCounters; - } - - void ObjectPoseObserver::handleProviderUpdate(const std::string& providerName) { // Initialized to 0 on first access. @@ -370,7 +387,7 @@ namespace armarx offerChannel(providerName, "Channel of provider '" + providerName + "'."); } offerOrUpdateDataField(providerName, "updateCounter", Variant(updateCounters.at(providerName)), "Counter incremented for each update."); - offerOrUpdateDataField(providerName, "candidateCount", Variant(int(objectPoses.at(providerName).size())), "Number of provided object poses."); + offerOrUpdateDataField(providerName, "objectCount", Variant(int(objectPoses.at(providerName).size())), "Number of provided object poses."); if (visu.enabled) { @@ -440,7 +457,7 @@ namespace armarx { try { - oobb = objectInfo->oobb(); + oobb = objectInfo->loadOOBB(); } catch (const std::ios_base::failure& e) { diff --git a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h index 1e7197d3b068ad58fad6a01912b6f9e7d6b51a6f..687db8ec03dfc84ab83a9e57da6e443d59e23dc5 100644 --- a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h +++ b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h @@ -82,7 +82,7 @@ namespace armarx // ObjectPoseTopic interface public: - void reportProviderAvailable(const std::string& providerName, ICE_CURRENT_ARG) override; + void reportProviderAvailable(const std::string& providerName, const objpose::ProviderInfo& info, ICE_CURRENT_ARG) override; void reportObjectPoses(const std::string& providerName, const objpose::data::ProvidedObjectPoseSeq& objectPoses, ICE_CURRENT_ARG) override; // ObjectPoseObserverInterface interface @@ -91,16 +91,16 @@ namespace armarx objpose::data::ObjectPoseSeq getObjectPoses(ICE_CURRENT_ARG) override; objpose::data::ObjectPoseSeq getObjectPosesByProvider(const std::string& providerName, ICE_CURRENT_ARG) override; - void requestObjects(const objpose::ObjectIDSeq& objectIDs, Ice::Long relativeTimeoutMS, ICE_CURRENT_ARG) override; + objpose::observer::RequestObjectsOutput requestObjects(const objpose::observer::RequestObjectsInput& input, ICE_CURRENT_ARG) override; Ice::StringSeq getAvailableProviderNames(ICE_CURRENT_ARG) override; objpose::ProviderInfo getProviderInfo(const std::string& providerName, ICE_CURRENT_ARG) override; - objpose::ProviderInfoMap getAvailableProvidersWithInfo(ICE_CURRENT_ARG) override; + objpose::ProviderInfoMap getAvailableProvidersInfo(ICE_CURRENT_ARG) override; bool hasProvider(const std::string& providerName, ICE_CURRENT_ARG) override; - Ice::Int getUpdateCounterByProvider(const std::string& providerName, ICE_CURRENT_ARG) override; - StringIntDictionary getAllUpdateCounters(ICE_CURRENT_ARG) override; + //Ice::Int getUpdateCounterByProvider(const std::string& providerName, ICE_CURRENT_ARG) override; + //StringIntDictionary getAllUpdateCounters(ICE_CURRENT_ARG) override; // Remote GUI @@ -120,7 +120,7 @@ namespace armarx private: - void fetchProviderInfo(const std::string& providerName, bool refresh = false); + void updateProviderInfo(const std::string& providerName, const objpose::ProviderInfo& info); void handleProviderUpdate(const std::string& providerName); void visProviderUpdate(const std::string& providerName); @@ -175,6 +175,7 @@ namespace armarx RemoteGui::Client::FloatSpinBox visuObjectFramesScale; }; RemoteGuiTab tab; + }; } diff --git a/source/RobotAPI/components/ObjectPoseObserver/ice_conversions.cpp b/source/RobotAPI/components/ObjectPoseObserver/ice_conversions.cpp index fb5a3bebe7c005c8799398df79909922ed360e9a..0f520c8fcc12391e7b47474248043dbafac0d73b 100644 --- a/source/RobotAPI/components/ObjectPoseObserver/ice_conversions.cpp +++ b/source/RobotAPI/components/ObjectPoseObserver/ice_conversions.cpp @@ -34,17 +34,6 @@ namespace armarx return cast->toEigen(); } - - std::ostream& objpose::operator<<(std::ostream& os, const ObjectID& id) - { - os << "'" << id.dataset << "/" << id.className; - if (!id.instanceName.empty()) - { - os << "/" << id.instanceName; - } - return os << "'"; - } - const simox::meta::EnumNames<objpose::ObjectTypeEnum> objpose::ObjectTypeEnumNames = { { objpose::ObjectTypeEnum::AnyObject, "AnyObject" }, diff --git a/source/RobotAPI/components/ObjectPoseObserver/ice_conversions.h b/source/RobotAPI/components/ObjectPoseObserver/ice_conversions.h index 0957980702de8cb17bf4c59214330cc9015ab99d..80da9b7e8408e8099450340280bc4072eecb9f7f 100644 --- a/source/RobotAPI/components/ObjectPoseObserver/ice_conversions.h +++ b/source/RobotAPI/components/ObjectPoseObserver/ice_conversions.h @@ -3,6 +3,7 @@ #include <SimoxUtility/meta/enum/EnumNames.hpp> #include <RobotAPI/interface/objectpose/object_pose_types.h> +#include <RobotAPI/libraries/ArmarXObjects/ice_conversions.h> #include "ObjectPose.h" @@ -19,8 +20,6 @@ namespace simox namespace armarx::objpose { - std::ostream& operator<<(std::ostream& os, const ObjectID& id); - extern const simox::meta::EnumNames<objpose::ObjectTypeEnum> ObjectTypeEnumNames; diff --git a/source/RobotAPI/components/ObjectPoseObserver/plugins/ObjectPoseProviderPlugin.cpp b/source/RobotAPI/components/ObjectPoseObserver/plugins/ObjectPoseProviderPlugin.cpp index d614e214f0c9ad5505ece0680ed3766469859752..63ccab6e140afa4bb8fdd174d0523e7c3b0cd78d 100644 --- a/source/RobotAPI/components/ObjectPoseObserver/plugins/ObjectPoseProviderPlugin.cpp +++ b/source/RobotAPI/components/ObjectPoseObserver/plugins/ObjectPoseProviderPlugin.cpp @@ -26,14 +26,20 @@ namespace armarx::plugins void ObjectPoseProviderPlugin::postOnConnectComponent() { - objpose::ObjectPoseTopicPrx& topic = parent<ObjectPoseProviderPluginUser>().objectPoseTopic; + ObjectPoseProviderPluginUser& parent = this->parent<ObjectPoseProviderPluginUser>(); + objpose::ObjectPoseTopicPrx& topic = parent.objectPoseTopic; if (topic) { - topic->reportProviderAvailable(parent<Component>().getName()); + objpose::ProviderInfo info = parent.getProviderInfo(); + if (!info.proxy) + { + info.proxy = ::armarx::objpose::ObjectPoseProviderPrx::checkedCast(parent.getProxy()); + } + topic->reportProviderAvailable(parent.getName(), info); } else { - ARMARX_WARNING << "Object pose topic not ready."; + ARMARX_ERROR << "Object pose topic not ready."; } } @@ -53,6 +59,17 @@ namespace armarx addPlugin(plugin); } + objpose::provider::RequestObjectsOutput ObjectPoseProviderPluginUser::requestObjects(const objpose::provider::RequestObjectsInput& input, const Ice::Current&) + { + // ARMARX_INFO << "Requested " << input.objectIDs.size() << " objects for " << input.relativeTimeoutMS << " ms."; + objpose::provider::RequestObjectsOutput output; + for (const auto& id : input.objectIDs) + { + output.results[id].success = false; + } + return output; + } + objpose::ObjectPoseTopicPrx ObjectPoseProviderPluginUser::createObjectPoseTopic() { return plugin->createObjectPoseTopic(); diff --git a/source/RobotAPI/components/ObjectPoseObserver/plugins/ObjectPoseProviderPlugin.h b/source/RobotAPI/components/ObjectPoseObserver/plugins/ObjectPoseProviderPlugin.h index f15a5b813e130bec95ffaa6ce4339b52be87d6ec..332064711b688d0e81969f3d1cc2ced472d817b1 100644 --- a/source/RobotAPI/components/ObjectPoseObserver/plugins/ObjectPoseProviderPlugin.h +++ b/source/RobotAPI/components/ObjectPoseObserver/plugins/ObjectPoseProviderPlugin.h @@ -45,6 +45,9 @@ namespace armarx ObjectPoseProviderPluginUser(); + /// Implement to process object requests (empty default implementation). + objpose::provider::RequestObjectsOutput requestObjects(const objpose::provider::RequestObjectsInput& input, const Ice::Current&) override; + objpose::ObjectPoseTopicPrx createObjectPoseTopic(); objpose::ObjectPoseTopicPrx objectPoseTopic; diff --git a/source/RobotAPI/components/ObjectPoseObserver/plugins/RequestedObjects.cpp b/source/RobotAPI/components/ObjectPoseObserver/plugins/RequestedObjects.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42dba6bc80bcff3e024afcbdb9156d726202c1dc --- /dev/null +++ b/source/RobotAPI/components/ObjectPoseObserver/plugins/RequestedObjects.cpp @@ -0,0 +1,87 @@ +#include "RequestedObjects.h" + +#include <ArmarXCore/core/time/TimeUtil.h> +#include <ArmarXCore/core/exceptions/local/ExpressionException.h> + +#include <RobotAPI/libraries/ArmarXObjects/ice_conversions.h> + + +namespace armarx::objpose +{ + RequestedObjects::RequestedObjects() + { + } + + void RequestedObjects::requestObjects(const std::vector<armarx::data::ObjectID>& objectIDs, long relativeTimeOutMS) + { + requestObjects(fromIce(objectIDs), relativeTimeOutMS); + } + + void RequestedObjects::requestObjects(const std::vector<armarx::ObjectID>& objectIDs, long relativeTimeOutMS) + { + requestObjects(objectIDs, IceUtil::Time::milliSeconds(relativeTimeOutMS)); + } + + void RequestedObjects::requestObjects( + const std::vector<armarx::ObjectID>& objectIDs, IceUtil::Time relativeTimeout) + { + if (relativeTimeout.toMilliSeconds() < 0) + { + for (const auto& id : objectIDs) + { + infiniteRequests.push_back(id); + } + } + else + { + IceUtil::Time absoluteTimeout = TimeUtil::GetTime() + relativeTimeout; + Request req; + req.objectIDs = objectIDs; + currentRequests[absoluteTimeout].push_back(req); + } + } + + RequestedObjects::Update RequestedObjects::updateRequestedObjects() + { + return updateRequestedObjects(TimeUtil::GetTime()); + } + + RequestedObjects::Update RequestedObjects::updateRequestedObjects(IceUtil::Time now) + { + // Remove requests with timeout. + while (currentRequests.size() > 0 && currentRequests.begin()->first <= now) + { + currentRequests.erase(currentRequests.begin()); + } + + std::set<armarx::ObjectID> current; + current.insert(infiniteRequests.begin(), infiniteRequests.end()); + + // Process current requests. + for (const auto& [timeout, requests] : currentRequests) + { + ARMARX_CHECK_LESS(now, timeout); + for (const auto& request : requests) + { + current.insert(request.objectIDs.begin(), request.objectIDs.end()); + } + } + + Update update; + update.current = { current.begin(), current.end() }; + + // added = current - last + std::set_difference(update.current.begin(), update.current.end(), + lastCurrent.begin(), lastCurrent.end(), + std::inserter(update.added, update.added.begin())); + // removed = last - current + std::set_difference(lastCurrent.begin(), lastCurrent.end(), + update.current.begin(), update.current.end(), + std::inserter(update.removed, update.removed.begin())); + + this->lastCurrent = update.current; + return update; + } + +} + diff --git a/source/RobotAPI/components/ObjectPoseObserver/plugins/RequestedObjects.h b/source/RobotAPI/components/ObjectPoseObserver/plugins/RequestedObjects.h new file mode 100644 index 0000000000000000000000000000000000000000..eebaf7af21e54ee9995d68940390c4cae48176f8 --- /dev/null +++ b/source/RobotAPI/components/ObjectPoseObserver/plugins/RequestedObjects.h @@ -0,0 +1,59 @@ +#pragma once + +#include <set> +#include <deque> +#include <vector> + + +#include <RobotAPI/interface/objectpose/object_pose_types.h> +#include <RobotAPI/libraries/ArmarXObjects/ObjectID.h> + + + +namespace armarx::objpose +{ + /** + * @brief Handles requests for object pose estimation from the ObjectPoseProviderInterface. + */ + class RequestedObjects + { + + public: + struct Request + { + std::vector<armarx::ObjectID> objectIDs; + bool infinite = false; + }; + struct Update + { + std::vector<armarx::ObjectID> added; + std::vector<armarx::ObjectID> removed; + std::vector<armarx::ObjectID> current; + }; + + + public: + + RequestedObjects(); + + void requestObjects(const std::vector<armarx::data::ObjectID>& objectIDs, long relativeTimeOutMS); + void requestObjects(const std::vector<armarx::ObjectID>& objectIDs, long relativeTimeOutMS); + void requestObjects(const std::vector<armarx::ObjectID>& objectIDs, IceUtil::Time relativeTimeout); + + + Update updateRequestedObjects(); + Update updateRequestedObjects(IceUtil::Time now); + + + public: + + /// Map from (absolute timeout) to (request) + std::map<IceUtil::Time, std::vector<Request>> currentRequests; + std::vector<armarx::ObjectID> infiniteRequests; + + + private: + std::vector<armarx::ObjectID> lastCurrent; + + }; +} diff --git a/source/RobotAPI/components/ObjectPoseProviderExample/CMakeLists.txt b/source/RobotAPI/components/ObjectPoseProviderExample/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fae15ee0afc1b1577bf808383a75faaa2d814ec3 --- /dev/null +++ b/source/RobotAPI/components/ObjectPoseProviderExample/CMakeLists.txt @@ -0,0 +1,33 @@ +armarx_component_set_name("ObjectPoseProviderExample") + + +set(COMPONENT_LIBS + ArmarXCore ArmarXCoreInterfaces # for DebugObserverInterface + # RobotAPICore RobotAPIInterfaces + # RobotAPIComponentPlugins # for ArViz and other plugins + RobotAPIArmarXObjects ObjectPoseObserver +) + +set(SOURCES + ObjectPoseProviderExample.cpp +) +set(HEADERS + ObjectPoseProviderExample.h +) + + +armarx_add_component("${SOURCES}" "${HEADERS}") + +#find_package(MyLib QUIET) +#armarx_build_if(MyLib_FOUND "MyLib not available") +# all target_include_directories must be guarded by if(Xyz_FOUND) +# for multiple libraries write: if(X_FOUND AND Y_FOUND).... +#if(MyLib_FOUND) +# target_include_directories(ObjectPoseProviderExample PUBLIC ${MyLib_INCLUDE_DIRS}) +#endif() + +# add unit tests +add_subdirectory(test) + +#generate the application +armarx_generate_and_add_component_executable() diff --git a/source/RobotAPI/components/ObjectPoseProviderExample/ObjectPoseProviderExample.cpp b/source/RobotAPI/components/ObjectPoseProviderExample/ObjectPoseProviderExample.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95a51a1fe0c0f7c90c463364a1320ee58fa0c5dc --- /dev/null +++ b/source/RobotAPI/components/ObjectPoseProviderExample/ObjectPoseProviderExample.cpp @@ -0,0 +1,190 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::ArmarXObjects::ObjectPoseProviderExample + * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu ) + * @date 2020 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#include "ObjectPoseProviderExample.h" + +#include <SimoxUtility/algorithm/string/string_tools.h> + +#include <ArmarXCore/core/time/CycleUtil.h> + +#include <RobotAPI/libraries/core/Pose.h> +#include <RobotAPI/libraries/core/FramedPose.h> +#include <RobotAPI/libraries/ArmarXObjects/ice_conversions.h> +#include <RobotAPI/components/ObjectPoseObserver/ice_conversions.h> + + +namespace armarx +{ + ObjectPoseProviderExamplePropertyDefinitions::ObjectPoseProviderExamplePropertyDefinitions(std::string prefix) : + armarx::ComponentPropertyDefinitions(prefix) + { + } + + armarx::PropertyDefinitionsPtr ObjectPoseProviderExample::createPropertyDefinitions() + { + armarx::PropertyDefinitionsPtr defs = new ObjectPoseProviderExamplePropertyDefinitions(getConfigIdentifier()); + + defs->topic(debugObserver); + + defs->optional(initialObjectIDs, "Objects", "Object IDs of objects to be tracked.") + .map(simox::alg::join(initialObjectIDs, ", "), initialObjectIDs); + + return defs; + } + + std::string ObjectPoseProviderExample::getDefaultName() const + { + return "ObjectPoseProviderExample"; + } + + + void ObjectPoseProviderExample::onInitComponent() + { + for (const auto& initial : initialObjectIDs) + { + // -1 -> infinitely + requestedObjects.requestObjects({ObjectID(initial)}, -1); + } + + { + providerInfo.objectType = objpose::ObjectTypeEnum::KnownObject; + std::vector<ObjectInfo> objects = objectFinder.findAllObjectsOfDataset("KIT"); + for (const auto& obj : objects) + { + providerInfo.supportedObjects.push_back(armarx::toIce(obj.id())); + } + } + } + + + void ObjectPoseProviderExample::onConnectComponent() + { + poseEstimationTask = new SimpleRunningTask<>([this]() + { + this->poseEstimationTaskRun(); + }); + poseEstimationTask->start(); + } + + + void ObjectPoseProviderExample::onDisconnectComponent() + { + } + + void ObjectPoseProviderExample::onExitComponent() + { + } + + + objpose::ProviderInfo ObjectPoseProviderExample::getProviderInfo(const Ice::Current&) + { + return providerInfo; + } + + objpose::provider::RequestObjectsOutput ObjectPoseProviderExample::requestObjects( + const objpose::provider::RequestObjectsInput& input, const Ice::Current&) + { + ARMARX_INFO << "Requested object IDs for " << input.relativeTimeoutMS << " ms: " + << input.objectIDs; + { + std::scoped_lock lock(requestedObjectsMutex); + requestedObjects.requestObjects(input.objectIDs, input.relativeTimeoutMS); + } + + objpose::provider::RequestObjectsOutput output; + // All requests are successful. + for (const auto& id : input.objectIDs) + { + output.results[id].success = true; + } + return output; + } + + + void ObjectPoseProviderExample::poseEstimationTaskRun() + { + CycleUtil cycle(50); + IceUtil::Time start = TimeUtil::GetTime(); + + std::map<ObjectID, ObjectInfo> objectInfos; + + while (poseEstimationTask && !poseEstimationTask->isStopped()) + { + IceUtil::Time now = TimeUtil::GetTime(); + float t = float((now - start).toSecondsDouble()); + + objpose::RequestedObjects::Update update; + { + std::scoped_lock lock(requestedObjectsMutex); + update = requestedObjects.updateRequestedObjects(now); + } + + if (update.added.size() > 0 || update.removed.size() > 0) + { + ARMARX_INFO << "Added: " << update.added + << "Removed: " << update.removed; + } + + int i = 0; + armarx::objpose::data::ProvidedObjectPoseSeq poses; + for (const ObjectID& id : update.current) + { + if (objectInfos.count(id) == 0) + { + if (std::optional<ObjectInfo> info = objectFinder.findObject(id)) + { + objectInfos.emplace(id, *info); + } + else + { + ARMARX_WARNING << "Could not find object class '" << id << "'."; + } + } + const ObjectInfo& info = objectInfos.at(id); + + armarx::objpose::data::ProvidedObjectPose& pose = poses.emplace_back(); + pose.providerName = getName(); + pose.objectType = objpose::ObjectTypeEnum::KnownObject; + + pose.objectID.dataset = info.id().dataset(); + pose.objectID.className = info.id().className(); + pose.objectID.instanceName = info.id().instanceName(); + + Eigen::Vector3f pos = 200 * Eigen::Vector3f(std::sin(t - i), std::cos(t - i), i); + Eigen::Quaternionf ori = Eigen::Quaternionf::Identity(); + pose.objectPose = new Pose(ori.toRotationMatrix(), pos); + pose.objectPoseFrame = armarx::GlobalFrame; + + pose.confidence = 1.0; + pose.timestampMicroSeconds = TimeUtil::GetTime().toMicroSeconds(); + + i++; + } + + ARMARX_VERBOSE << "Reporting " << poses.size() << " object poses"; + objectPoseTopic->reportObjectPoses(getName(), poses); + + cycle.waitForCycleDuration(); + } + } + +} diff --git a/source/RobotAPI/components/ObjectPoseProviderExample/ObjectPoseProviderExample.h b/source/RobotAPI/components/ObjectPoseProviderExample/ObjectPoseProviderExample.h new file mode 100644 index 0000000000000000000000000000000000000000..aac11a5f1c9fd6d8a920a85166495e29346e6772 --- /dev/null +++ b/source/RobotAPI/components/ObjectPoseProviderExample/ObjectPoseProviderExample.h @@ -0,0 +1,124 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::ArmarXObjects::ObjectPoseProviderExample + * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu ) + * @date 2020 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#pragma once + +#include <mutex> + +#include <ArmarXCore/core/Component.h> + +#include <ArmarXCore/interface/observers/ObserverInterface.h> +#include <ArmarXCore/core/services/tasks/TaskUtil.h> +// #include <RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.h> + +// Include the ProviderPlugin +#include <RobotAPI/components/ObjectPoseObserver/plugins/ObjectPoseProviderPlugin.h> +#include <RobotAPI/components/ObjectPoseObserver/plugins/RequestedObjects.h> + +#include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h> + + +namespace armarx +{ + /** + * @class ObjectPoseProviderExamplePropertyDefinitions + * @brief Property definitions of `ObjectPoseProviderExample`. + */ + class ObjectPoseProviderExamplePropertyDefinitions : + public armarx::ComponentPropertyDefinitions + { + public: + ObjectPoseProviderExamplePropertyDefinitions(std::string prefix); + }; + + + + /** + * @defgroup Component-ObjectPoseProviderExample ObjectPoseProviderExample + * @ingroup RobotAPI-Components + * A description of the component ObjectPoseProviderExample. + * + * @class ObjectPoseProviderExample + * @ingroup Component-ObjectPoseProviderExample + * @brief Brief description of class ObjectPoseProviderExample. + * + * Detailed description of class ObjectPoseProviderExample. + */ + class ObjectPoseProviderExample : + virtual public armarx::Component + // Derive from the provider plugin. + , virtual public armarx::ObjectPoseProviderPluginUser + { + public: + + /// @see armarx::ManagedIceObject::getDefaultName() + std::string getDefaultName() const override; + + + // Implement the ObjectPoseProvider interface + public: + objpose::ProviderInfo getProviderInfo(const Ice::Current& = Ice::emptyCurrent) override; + objpose::provider::RequestObjectsOutput requestObjects(const objpose::provider::RequestObjectsInput& input, const Ice::Current&) override; + + + protected: + + /// @see armarx::ManagedIceObject::onInitComponent() + void onInitComponent() override; + + /// @see armarx::ManagedIceObject::onConnectComponent() + void onConnectComponent() override; + + /// @see armarx::ManagedIceObject::onDisconnectComponent() + void onDisconnectComponent() override; + + /// @see armarx::ManagedIceObject::onExitComponent() + void onExitComponent() override; + + /// @see PropertyUser::createPropertyDefinitions() + armarx::PropertyDefinitionsPtr createPropertyDefinitions() override; + + + private: + + void poseEstimationTaskRun(); + + + private: + + // To be moved to plugin + std::mutex requestedObjectsMutex; + objpose::RequestedObjects requestedObjects; + + + objpose::ProviderInfo providerInfo; + + armarx::ObjectFinder objectFinder; + std::vector<std::string> initialObjectIDs = { "KIT/Amicelli", "KIT/YellowSaltCylinder" }; + + armarx::SimpleRunningTask<>::pointer_type poseEstimationTask; + + /// Debug observer. Used to visualize e.g. time series. + armarx::DebugObserverInterfacePrx debugObserver; + + }; +} diff --git a/source/RobotAPI/components/ObjectPoseProviderExample/test/CMakeLists.txt b/source/RobotAPI/components/ObjectPoseProviderExample/test/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e65a2f31bc9150164b5e5ed6fc0e93227f5176ce --- /dev/null +++ b/source/RobotAPI/components/ObjectPoseProviderExample/test/CMakeLists.txt @@ -0,0 +1,5 @@ + +# Libs required for the tests +SET(LIBS ${LIBS} ArmarXCore ${ARMARX_COMPONENT_LIB_NAME}) + +armarx_add_test(ObjectPoseProviderExampleTest ObjectPoseProviderExampleTest.cpp "${LIBS}") diff --git a/source/RobotAPI/components/ObjectPoseObserver/main.cpp b/source/RobotAPI/components/ObjectPoseProviderExample/test/ObjectPoseProviderExampleTest.cpp similarity index 65% rename from source/RobotAPI/components/ObjectPoseObserver/main.cpp rename to source/RobotAPI/components/ObjectPoseProviderExample/test/ObjectPoseProviderExampleTest.cpp index d83c2d5e8c60bd9dfb2a104f4ae9bc9c815ea4ca..d173c24a7a110c93d94a95d3df6b7c1d1a6d5e78 100644 --- a/source/RobotAPI/components/ObjectPoseObserver/main.cpp +++ b/source/RobotAPI/components/ObjectPoseProviderExample/test/ObjectPoseProviderExampleTest.cpp @@ -13,20 +13,25 @@ * 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::application::ObjectPoseObserver + * @package RobotAPI::ArmarXObjects::ObjectPoseProviderExample * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu ) * @date 2020 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt * GNU General Public License */ -#include <RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h> +#define BOOST_TEST_MODULE RobotAPI::ArmarXObjects::ObjectPoseProviderExample -#include <ArmarXCore/core/application/Application.h> -#include <ArmarXCore/core/Component.h> -#include <ArmarXCore/core/logging/Logging.h> +#define ARMARX_BOOST_TEST -int main(int argc, char* argv[]) +#include <RobotAPI/Test.h> +#include <RobotAPI/components/ObjectPoseProviderExample/ObjectPoseProviderExample.h> + +#include <iostream> + +BOOST_AUTO_TEST_CASE(testExample) { - return armarx::runSimpleComponentApp < armarx::ObjectPoseObserver > (argc, argv, "ObjectPoseObserver"); + armarx::ObjectPoseProviderExample instance; + + BOOST_CHECK_EQUAL(true, true); } diff --git a/source/RobotAPI/gui-plugins/ObjectPoseGui/CMakeLists.txt b/source/RobotAPI/gui-plugins/ObjectPoseGui/CMakeLists.txt index d4d29bd3e4181aa055f7dee976a778f75d42a877..e588dbbb75a0512b19015e10ceace1b07b1d9215 100644 --- a/source/RobotAPI/gui-plugins/ObjectPoseGui/CMakeLists.txt +++ b/source/RobotAPI/gui-plugins/ObjectPoseGui/CMakeLists.txt @@ -8,12 +8,15 @@ armarx_set_target("ObjectPoseGuiPlugin") armarx_build_if(ArmarXGui_FOUND "ArmarXGui not available") set(SOURCES - ObjectPoseGuiPlugin.cpp ObjectPoseGuiWidgetController.cpp + ObjectPoseGuiPlugin.cpp + ObjectPoseGuiWidgetController.cpp ) # do not rename this variable, it is used in armarx_gui_library()... set(HEADERS - ObjectPoseGuiPlugin.h ObjectPoseGuiWidgetController.h + ObjectPoseGuiPlugin.h + ObjectPoseGuiWidgetController.h + TreeWidgetBuilder.h ) set(GUI_MOC_HDRS ${HEADERS}) diff --git a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidget.ui b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidget.ui index 83f77d3ae4886eaced3509fa4c1af1c62a21d80f..00677428b7b88ead1fbf7dbd1fb380ffad0a94d9 100644 --- a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidget.ui +++ b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidget.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>400</width> - <height>300</height> + <width>621</width> + <height>350</height> </rect> </property> <property name="windowTitle"> @@ -15,46 +15,276 @@ </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <widget class="QGroupBox" name="objectsGroupBox"> - <property name="title"> - <string>Objects</string> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="updateButton"> + <property name="text"> + <string>Update</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="autoUpdateCheckBox"> + <property name="text"> + <string>Auto Update</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>1</number> </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="updateObjectsButton"> + <widget class="QWidget" name="tabObjects"> + <attribute name="title"> + <string>Objects</string> + </attribute> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QTreeWidget" name="objectsTree"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <column> + <property name="text"> + <string>ID</string> + </property> + </column> + <column> + <property name="text"> + <string>Provider</string> + </property> + </column> + <column> <property name="text"> - <string>Update</string> + <string>Type</string> </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="autoUpdateCheckBox"> + </column> + <column> <property name="text"> - <string>Auto Update</string> + <string>OOBB</string> </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> + </column> + <column> + <property name="text"> + <string>Confidence</string> + </property> + </column> + <column> + <property name="text"> + <string>Timestamp</string> </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> + </column> + <item> + <property name="text"> + <string>Provider2</string> + </property> + <item> + <property name="text"> + <string>Dataset1/Object2</string> + </property> + <property name="text"> + <string>Provider2</string> + </property> + </item> + </item> + <item> + <property name="text"> + <string>Provider1</string> </property> - </spacer> - </item> - </layout> - </item> - <item> - <widget class="QTableWidget" name="objectsTable"/> - </item> - </layout> + <item> + <property name="text"> + <string>Dataset2/Object2/instance1</string> + </property> + <property name="text"> + <string>Provider1</string> + </property> + </item> + <item> + <property name="text"> + <string>Dataset1/Object1</string> + </property> + <property name="text"> + <string>Provider1</string> + </property> + </item> + </item> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tabRequest"> + <attribute name="title"> + <string>Request</string> + </attribute> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QTreeWidget" name="requestTree"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="columnCount"> + <number>3</number> + </property> + <attribute name="headerStretchLastSection"> + <bool>true</bool> + </attribute> + <column> + <property name="text"> + <string>ID</string> + </property> + </column> + <column> + <property name="text"> + <string>Provider</string> + </property> + </column> + <column> + <property name="text"> + <string>Request</string> + </property> + </column> + <item> + <property name="text"> + <string>Dataset1</string> + </property> + <property name="text"> + <string/> + </property> + <property name="text"> + <string/> + </property> + <item> + <property name="text"> + <string>ClassName1</string> + </property> + <property name="text"> + <string>Provider2</string> + </property> + <property name="text"> + <string/> + </property> + </item> + <item> + <property name="text"> + <string>ClassName2</string> + </property> + <property name="text"> + <string>Provider1</string> + </property> + <property name="text"> + <string/> + </property> + </item> + </item> + <item> + <property name="text"> + <string>Dataset2</string> + </property> + <property name="text"> + <string/> + </property> + <property name="text"> + <string/> + </property> + <item> + <property name="text"> + <string>ClassName3</string> + </property> + <property name="text"> + <string>Provider1</string> + </property> + <property name="text"> + <string/> + </property> + </item> + <item> + <property name="text"> + <string>ClassName3</string> + </property> + <property name="text"> + <string>Provider2</string> + </property> + </item> + </item> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QLabel" name="labelTimeout"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Timeout:</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="requestTimeoutSpinBox"> + <property name="suffix"> + <string> s</string> + </property> + <property name="maximum"> + <double>999.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.250000000000000</double> + </property> + <property name="value"> + <double>30.000000000000000</double> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="requestInfiniteCheckBox"> + <property name="text"> + <string>Infinite</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="requestButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Request +Selected +Objects</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> </widget> </item> </layout> diff --git a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.cpp b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.cpp index 9c97a261eec0c4aadb303ac8e2f61607202bbf75..828d0fb5b2d1ea32a288bbd6c2fd6ed00ba2bc47 100644 --- a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.cpp +++ b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.cpp @@ -26,9 +26,13 @@ #include <QTimer> +#include <ArmarXCore/core/time/TimeUtil.h> + #include <RobotAPI/components/ObjectPoseObserver/ice_conversions.h> #include <RobotAPI/components/ObjectPoseObserver/ObjectPose.h> +#include "TreeWidgetBuilder.h" + namespace armarx { @@ -37,20 +41,39 @@ namespace armarx { widget.setupUi(getWidget()); - QStringList header = {"Dataset", "ClassName", "InstanceName", "Provider", "Type"}; - widget.objectsTable->setColumnCount(header.size()); - widget.objectsTable->setHorizontalHeaderLabels(header); + widget.objectsTree->clear(); + widget.objectsTree->sortItems(0, Qt::SortOrder::AscendingOrder); + + widget.requestTree->clear(); + widget.requestTree->sortItems(0, Qt::SortOrder::AscendingOrder); + using This = ObjectPoseGuiWidgetController; - connect(widget.updateObjectsButton, &QPushButton::clicked, this, &This::updateObjects); - // QTimer* timer = new QTimer(this,); + connect(widget.updateButton, &QPushButton::pressed, this, &This::updateTab); + connect(widget.tabWidget, &QTabWidget::currentChanged, this, &This::updateTab); + + connect(widget.requestButton, &QPushButton::pressed, this, &This::requestSelectedObjects); + + QTimer* timer = new QTimer(this); + timer->setInterval(500); + connect(timer, &QTimer::timeout, this, &This::updateTab); + connect(widget.autoUpdateCheckBox, &QCheckBox::toggled, this, [timer](bool checked) + { + if (checked) + { + timer->start(); + } + else + { + timer->stop(); + } + }); } ObjectPoseGuiWidgetController::~ObjectPoseGuiWidgetController() { - } @@ -66,7 +89,7 @@ namespace armarx QString ObjectPoseGuiWidgetController::GetWidgetName() { - return "ObjectPoseGui"; + return "MemoryX.ObjectPoseGui"; } static const std::string CONFIG_KEY_OBJECT_POSE_OBSERVER = "ObjectPoseObserver"; @@ -105,37 +128,225 @@ namespace armarx } } - void ObjectPoseGuiWidgetController::updateObjects() + void ObjectPoseGuiWidgetController::onDisconnectComponent() + { + objectPoseObserver = nullptr; + } + + void ObjectPoseGuiWidgetController::updateTab() + { + if (widget.tabWidget->currentWidget() == widget.tabObjects) + { + updateObjectsTab(); + } + else if (widget.tabWidget->currentWidget() == widget.tabRequest) + { + updateRequestTab(); + } + } + + + + void ObjectPoseGuiWidgetController::updateObjectsTab() + { + if (!objectPoseObserver) + { + ARMARX_WARNING << "No object pose observer."; + return; + } + + IceUtil::Time start = IceUtil::Time::now(); + ARMARX_INFO << "Getting object poses..."; + const objpose::data::ObjectPoseSeq objectPosesIce = objectPoseObserver->getObjectPoses(); + ARMARX_INFO << "Got " << objectPosesIce.size() << " object poses. " + << "(Took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms.)"; + + const objpose::ObjectPoseSeq objectPoses = objpose::fromIce(objectPosesIce); + + std::map<std::string, objpose::ObjectPoseSeq> objectPosesByProvider; + for (const auto& pose : objectPoses) + { + objectPosesByProvider[pose.providerName].push_back(pose); + } + + start = IceUtil::Time::now(); + + QTreeWidget* tree = widget.objectsTree; + + MapTreeWidgetBuilder builder(objectPosesByProvider); + builder.setMakeItemFn([](const std::string & provider, const objpose::ObjectPoseSeq&) + { + QTreeWidgetItem* item = new QTreeWidgetItem({QString::fromStdString(provider)}); + return item; + }); + builder.setUpdateItemFn([](const std::string&, const objpose::ObjectPoseSeq & objectPoses, QTreeWidgetItem * item) + { + bool expand = item->childCount() == 0; + + TreeWidgetBuilder builder(objectPoses); + builder.setNameFn([](const objpose::ObjectPose & pose) + { + return pose.objectID.str(); + }); + builder.setMakeItemFn([](const objpose::ObjectPose&) + { + QTreeWidgetItem* item = new QTreeWidgetItem(QStringList{}); + return item; + }); + builder.setUpdateItemFn([](const objpose::ObjectPose & pose, QTreeWidgetItem * item) + { + 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))); + + std::stringstream ss; + if (pose.localOOBB) + { + static const Eigen::IOFormat iof(5, 0, "", " x ", "", "", "", ""); + ss << pose.localOOBB->dimensions().format(iof); + } + else + { + ss << "None"; + } + item->setText(col++, QString::fromStdString(ss.str())); + item->setText(col++, QString::number(double(pose.confidence), 'g', 2)); + item->setText(col++, QString::fromStdString(TimeUtil::toStringDateTime(pose.timestamp))); + + return true; + }); + builder.updateTree(item, objectPoses); + + if (expand) + { + item->setExpanded(true); + } + + return true; + }); + builder.updateTree(tree, objectPosesByProvider); + + ARMARX_INFO << "Gui update took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms."; + } + + + void ObjectPoseGuiWidgetController::updateRequestTab() { if (!objectPoseObserver) { + ARMARX_WARNING << "No object pose observer."; return; } - ARMARX_INFO << "Get object poses..."; - // const objpose::ObjectPoseSeq objectPoses = objpose::fromIce(objectPoseObserver->getObjectPoses()); + IceUtil::Time start = IceUtil::Time::now(); + objpose::ProviderInfoMap availableProvidersInfo = objectPoseObserver->getAvailableProvidersInfo(); + ARMARX_INFO << "Got infos of " << availableProvidersInfo.size() << " object pose providers. " + << "(Took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms.)"; + - const objpose::data::ObjectPoseSeq objectPoses = objectPoseObserver->getObjectPoses(); - ARMARX_INFO << "Got " << objectPoses.size() << " object poses."; + // Restructure data. + std::map<std::string, std::set<std::pair<std::string, std::string>>> data; + for (const auto& [providerName, info] : availableProvidersInfo) + { + for (const auto& id : info.supportedObjects) + { + data[id.dataset].insert(std::make_pair(id.className, providerName)); + } + } - widget.objectsTable->setRowCount(int(objectPoses.size())); + start = IceUtil::Time::now(); - for (int i = 0; i < int(objectPoses.size()); ++i) + QTreeWidget* tree = widget.requestTree; + + MapTreeWidgetBuilder builder(data); + builder.setMakeItemFn([](const std::string & dataset, const auto&) + { + QTreeWidgetItem* item = new QTreeWidgetItem({QString::fromStdString(dataset)}); + return item; + }); + builder.setUpdateItemFn([tree](const std::string & dataset, const auto & datasetData, QTreeWidgetItem * datasetItem) { - const objpose::data::ObjectPose& pose = objectPoses.at(size_t(i)); - int col = 0; + (void) dataset; + + TreeWidgetBuilder builder(datasetData); + builder.setCompareFn([](const std::pair<std::string, std::string>& lhs, QTreeWidgetItem * item) + { + auto rhs = std::make_pair(item->text(0).toStdString(), item->text(1).toStdString()); + if (lhs < rhs) + { + return -1; + } + return lhs == rhs ? 0 : 1; + }); + builder.setMakeItemFn([](const std::pair<std::string, std::string>& element) + { + QTreeWidgetItem* item = new QTreeWidgetItem({ QString::fromStdString(element.first), QString::fromStdString(element.second)}); + return item; + }); + builder.setUpdateItemFn([tree](const std::pair<std::string, std::string>& element, QTreeWidgetItem * item) + { + (void) element; + if (!tree->itemWidget(item, 2)) + { + QCheckBox* requestCheckBox = new QCheckBox(); + tree->setItemWidget(item, 2, requestCheckBox); + } + return true; + }); + builder.updateTree(datasetItem, datasetData); + + return true; + }); + builder.updateTree(tree, data); + + ARMARX_INFO << "Gui update took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms."; + } + + void ObjectPoseGuiWidgetController::requestSelectedObjects() + { + std::map<std::string, objpose::observer::RequestObjectsInput> requestsPerProvider; - widget.objectsTable->setItem( - i, col++, new QTableWidgetItem(pose.objectID.dataset.c_str())); - widget.objectsTable->setItem( - i, col++, new QTableWidgetItem(pose.objectID.className.c_str())); - widget.objectsTable->setItem( - i, col++, new QTableWidgetItem(pose.objectID.instanceName.c_str())); - widget.objectsTable->setItem( - i, col++, new QTableWidgetItem(pose.providerName.c_str())); - widget.objectsTable->setItem( - i, col++, new QTableWidgetItem(objpose::ObjectTypeEnumNames.to_name(pose.objectType).c_str())); + QTreeWidget* tree = widget.requestTree; + for (int i = 0; i < tree->topLevelItemCount(); ++i) + { + QTreeWidgetItem* datasetItem = tree->topLevelItem(i); + for (int j = 0; j < datasetItem->childCount(); ++j) + { + QTreeWidgetItem* classItem = datasetItem->child(j); + QCheckBox* selected = dynamic_cast<QCheckBox*>(tree->itemWidget(classItem, 2)); + ARMARX_CHECK_NOT_NULL(selected); + if (selected->isChecked()) + { + std::string providerName = classItem->text(1).toStdString(); + objpose::observer::RequestObjectsInput& requests = requestsPerProvider[providerName]; + data::ObjectID& id = requests.request.objectIDs.emplace_back(); + id.dataset = datasetItem->text(0).toStdString(); + id.className = classItem->text(0).toStdString(); + } + } + } + + long timeoutMS = -1; + if (!widget.requestInfiniteCheckBox->isChecked()) + { + timeoutMS = long(widget.requestTimeoutSpinBox->value() * 1000); + } + + for (auto& [providerName, request] : requestsPerProvider) + { + request.provider = providerName; + request.request.relativeTimeoutMS = timeoutMS; + ARMARX_INFO << "Requesting " << request.request.objectIDs.size() << " objects for " + << request.request.relativeTimeoutMS << " ms."; + objpose::observer::RequestObjectsOutput output = objectPoseObserver->requestObjects(request); + int successful = 0; + for (const auto& [id, result] : output.results) + { + successful += int(!result.providerName.empty() && result.result.success); + } + ARMARX_INFO << successful << " of " << request.request.objectIDs.size() << " object request successful."; } } diff --git a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.h b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.h index d9b716d7cc4186cbbff58858aaf25088726fa283..26767131953cdd7f756951fdf011597d7716426b 100644 --- a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.h +++ b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.h @@ -53,7 +53,7 @@ namespace armarx * Detailed description */ class ARMARXCOMPONENT_IMPORT_EXPORT - ObjectPoseGuiWidgetController: + ObjectPoseGuiWidgetController : public armarx::ArmarXComponentWidgetControllerTemplate < ObjectPoseGuiWidgetController > { Q_OBJECT @@ -85,11 +85,19 @@ namespace armarx /// @see armarx::Component::onConnectComponent() void onConnectComponent() override; + /// @see armarx::Component::onConnectComponent() + void onDisconnectComponent() override; + public slots: /* QT slot declarations */ - void updateObjects(); + /// Update the currently opened tab. + void updateTab(); + void updateObjectsTab(); + void updateRequestTab(); + + void requestSelectedObjects(); signals: @@ -102,7 +110,6 @@ namespace armarx QPointer<SimpleConfigDialog> configDialog; - std::string objectPoseObserverName; armarx::objpose::ObjectPoseObserverInterfacePrx objectPoseObserver; diff --git a/source/RobotAPI/gui-plugins/ObjectPoseGui/TreeWidgetBuilder.h b/source/RobotAPI/gui-plugins/ObjectPoseGui/TreeWidgetBuilder.h new file mode 100644 index 0000000000000000000000000000000000000000..2b7cdf0d88038acf03b6e5e229baa8cc446fc3fc --- /dev/null +++ b/source/RobotAPI/gui-plugins/ObjectPoseGui/TreeWidgetBuilder.h @@ -0,0 +1,287 @@ +#pragma once + +#include <functional> +#include <map> +#include <sstream> + +#include <QTreeWidget> + +#include <ArmarXCore/core/exceptions/local/ExpressionException.h> + + +namespace armarx +{ + + /** + * A class to efficiently build and maintain sorted items of `QTreeWidget` + * or `QTreeWidgetItem` based on a sorted container matching the intended structure. + */ + template <class ContainerT> + struct TreeWidgetBuilder + { + using ElementT = typename ContainerT::value_type; + + /// Return < 0 if `element < item`, 0 if `element == item`, and > 0 if `element > item`. + using CompareFn = std::function<int(const ElementT& element, QTreeWidgetItem* item)>; + using NameFn = std::function<std::string(const ElementT& element)>; + using MakeItemFn = std::function<QTreeWidgetItem*(const ElementT& element)>; + using UpdateItemFn = std::function<bool(const ElementT& element, QTreeWidgetItem* item)>; + + + TreeWidgetBuilder() = default; + TreeWidgetBuilder(const ContainerT&) + {} + + TreeWidgetBuilder(CompareFn compareFn, MakeItemFn makeItemFn, UpdateItemFn updateItemFn = NoUpdate) : + compareFn(compareFn), makeItemFn(makeItemFn), updateItemFn(updateItemFn) + {} + TreeWidgetBuilder(NameFn nameFn, MakeItemFn makeItemFn, UpdateItemFn updateItemFn = NoUpdate) : + compareFn(MakeCompareNameFn(nameFn)), makeItemFn(makeItemFn), updateItemFn(updateItemFn) + {} + + + void setCompareFn(CompareFn compareFn) + { + this->compareFn = compareFn; + } + void setNameFn(NameFn nameFn) + { + compareFn = MakeCompareNameFn(nameFn); + } + void setMakeItemFn(MakeItemFn makeItemFn) + { + this->makeItemFn = makeItemFn; + } + void setUpdateItemFn(UpdateItemFn updateItemFn) + { + this->updateItemFn = updateItemFn; + } + + + template <class ParentT> + void updateTree(ParentT* parent, const ContainerT& elements); + + + /// No update function (default). + static bool NoUpdate(const ElementT& element, QTreeWidgetItem* item) + { + (void) element, (void) item; + return true; + } + + /// Use the name for comparison. + static CompareFn MakeCompareNameFn(NameFn nameFn) + { + return [nameFn](const ElementT & element, QTreeWidgetItem * item) + { + std::string name = nameFn(element); + return name.compare(item->text(0).toStdString()); + }; + } + + + private: + + CompareFn compareFn; + MakeItemFn makeItemFn; + UpdateItemFn updateItemFn; + + }; + + + /** + * A class to efficiently build and maintain sorted items of `QTreeWidget` + * or `QTreeWidgetItem` based on a map matching the intended structure. + */ + template <class KeyT, class ValueT> + struct MapTreeWidgetBuilder + { + using MapT = std::map<KeyT, ValueT>; + using Base = TreeWidgetBuilder<MapT>; + using ElementT = typename Base::ElementT; + + using NameFn = std::function<std::string(const KeyT& key, const ValueT& value)>; + + using MakeItemFn = std::function<QTreeWidgetItem*(const KeyT& key, const ValueT& value)>; + using UpdateItemFn = std::function<bool(const KeyT& key, const ValueT& value, QTreeWidgetItem* item)>; + + + MapTreeWidgetBuilder() + { + setNameFn(KeyAsName); + } + /// Allows declaring instance from container without explicit template arguments. + MapTreeWidgetBuilder(const MapT&) : MapTreeWidgetBuilder() + {} + + MapTreeWidgetBuilder(MakeItemFn makeItemFn, UpdateItemFn updateItemFn = NoUpdate) : MapTreeWidgetBuilder() + { + setMakeItemFn(makeItemFn); + setUpdateItemFn(updateItemFn); + } + MapTreeWidgetBuilder(NameFn nameFn, MakeItemFn makeItemFn, UpdateItemFn updateItemFn = NoUpdate) + { + setNameFn(nameFn); + setMakeItemFn(makeItemFn); + setUpdateItemFn(updateItemFn); + } + + void setNameFn(NameFn nameFn) + { + builder.setNameFn([nameFn](const ElementT & element) + { + const auto& [key, value] = element; + return nameFn(key, value); + }); + } + void setMakeItemFn(MakeItemFn makeItemFn) + { + builder.setMakeItemFn([makeItemFn](const ElementT & element) + { + const auto& [key, value] = element; + return makeItemFn(key, value); + }); + } + void setUpdateItemFn(UpdateItemFn updateItemFn) + { + builder.setUpdateItemFn([updateItemFn](const ElementT & element, QTreeWidgetItem * item) + { + const auto& [key, value] = element; + return updateItemFn(key, value, item); + }); + } + + + template <class ParentT> + void updateTree(ParentT* tree, const MapT& elements) + { + builder.updateTree(tree, elements); + } + + + /// A name function using the key as name. + static std::string KeyAsName(const KeyT& key, const ValueT& value) + { + (void) value; + if constexpr(std::is_same<KeyT, std::string>()) + { + return key; + } + else + { + std::stringstream ss; + ss << key; + return ss.str(); + } + } + + /// No update function (default). + static bool NoUpdate(const KeyT& key, const ValueT& value, QTreeWidgetItem* item) + { + (void) key, (void) value, (void) item; + return true; + } + + + private: + + TreeWidgetBuilder<MapT> builder; + + }; + + + + namespace detail + { + template <class ParentT> struct ParentAPI; + + template <> struct ParentAPI<QTreeWidget> + { + static int getItemCount(QTreeWidget* tree) + { + return tree->topLevelItemCount(); + } + static QTreeWidgetItem* getItem(QTreeWidget* tree, int index) + { + return tree->topLevelItem(index); + } + static void insertItem(QTreeWidget* tree, int index, QTreeWidgetItem* item) + { + tree->insertTopLevelItem(index, item); + } + static QTreeWidgetItem* takeItem(QTreeWidget* tree, int index) + { + return tree->takeTopLevelItem(index); + } + }; + + template <> struct ParentAPI<QTreeWidgetItem> + { + static int getItemCount(QTreeWidgetItem* parent) + { + return parent->childCount(); + } + static QTreeWidgetItem* getItem(QTreeWidgetItem* parent, int index) + { + return parent->child(index); + } + static QTreeWidgetItem* takeItem(QTreeWidgetItem* parent, int index) + { + return parent->takeChild(index); + } + static void insertItem(QTreeWidgetItem* parent, int index, QTreeWidgetItem* item) + { + parent->insertChild(index, item); + } + }; + } + + + template <class ContainerT> + template <typename ParentT> + void TreeWidgetBuilder<ContainerT>::updateTree(ParentT* parent, const ContainerT& elements) + { + using api = detail::ParentAPI<ParentT>; + + int currentIndex = 0; + for (const auto& element : elements) + { + QTreeWidgetItem* item = nullptr; + if (currentIndex >= api::getItemCount(parent)) + { + // Add elements to the end of the list. + item = makeItemFn(element); + api::insertItem(parent, api::getItemCount(parent), item); + ++currentIndex; + } + else + { + QTreeWidgetItem* currentItem = api::getItem(parent, currentIndex); + while (currentItem != nullptr && compareFn(element, currentItem) > 0) + { + delete api::takeItem(parent, currentIndex); + currentItem = api::getItem(parent, currentIndex); + } + if (currentItem == nullptr || compareFn(element, currentItem) < 0) + { + // Insert new item before child. + item = makeItemFn(element); + api::insertItem(parent, currentIndex, item); + ++currentIndex; + } + else if (currentItem != nullptr && compareFn(element, currentItem) == 0) + { + // Already existing. + item = currentItem; + ++currentIndex; + } + } + ARMARX_CHECK_NOT_NULL(item); + if (!updateItemFn(element, item)) + { + break; + } + } + } + +} diff --git a/source/RobotAPI/interface/ArmarXObjects/ArmarXObjectsTypes.ice b/source/RobotAPI/interface/ArmarXObjects/ArmarXObjectsTypes.ice new file mode 100644 index 0000000000000000000000000000000000000000..779b25dd1902e49409fa9c23576192c7bc5f97ba --- /dev/null +++ b/source/RobotAPI/interface/ArmarXObjects/ArmarXObjectsTypes.ice @@ -0,0 +1,42 @@ +/** +* 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 Rainer Kartmann +* @copyright 2020 Humanoids Group, H2T, KIT +* @license http://www.gnu.org/licenses/gpl-2.0.txt +* GNU General Public License +*/ + +#pragma once + +module armarx +{ + module data + { + struct ObjectID + { + /// The dataset name in ArmarXObjects, e.g. "KIT", "YCB", "SecondHands", ... + string dataset; + /// The class name in ArmarXObjects, e.g. "Amicelli", "001_chips_can", ... + string className; + /// An optional instance name, chosen by the provider. + string instanceName; + }; + sequence<ObjectID> ObjectIDSeq; + }; +}; + diff --git a/source/RobotAPI/interface/CMakeLists.txt b/source/RobotAPI/interface/CMakeLists.txt index b4f2814c141564baadf2aabe762e9f01f98367e1..7bee558e7b619e2c71dcb1ba127309e1126326e7 100644 --- a/source/RobotAPI/interface/CMakeLists.txt +++ b/source/RobotAPI/interface/CMakeLists.txt @@ -31,6 +31,8 @@ set(SLICE_FILES observers/SpeechObserverInterface.ice observers/GraspCandidateObserverInterface.ice + ArmarXObjects/ArmarXObjectsTypes.ice + objectpose/object_pose_types.ice objectpose/ObjectPoseObserver.ice objectpose/ObjectPoseProvider.ice diff --git a/source/RobotAPI/interface/objectpose/ObjectPoseObserver.ice b/source/RobotAPI/interface/objectpose/ObjectPoseObserver.ice index 5cc889cd13d206e416ce3c1830a372d052a3224d..0333c21c51055c711e29f06a34570d341987a226 100644 --- a/source/RobotAPI/interface/objectpose/ObjectPoseObserver.ice +++ b/source/RobotAPI/interface/objectpose/ObjectPoseObserver.ice @@ -36,21 +36,44 @@ module armarx module objpose { + module observer + { + struct RequestObjectsInput + { + /// The provider to request. If empty, any suitable provider per object ID is chosen. + string provider; + provider::RequestObjectsInput request; + }; + struct ObjectRequestResult + { + /// Name of the provider who was requested. + /// If empty, no suitable provider was found. + string providerName; + provider::ObjectRequestResult result; + }; + dictionary<armarx::data::ObjectID, ObjectRequestResult> ObjectRequestResultMap; + struct RequestObjectsOutput + { + /// The results per objectID. + ObjectRequestResultMap results; + }; + }; + interface ObjectPoseObserverInterface extends ObserverInterface, ObjectPoseTopic { + // Reading data::ObjectPoseSeq getObjectPoses(); data::ObjectPoseSeq getObjectPosesByProvider(string providerName); - void requestObjects(ObjectIDSeq objectIDs, long relativeTimeoutMS); - - + bool hasProvider(string providerName); Ice::StringSeq getAvailableProviderNames(); - ProviderInfoMap getAvailableProvidersWithInfo(); + ProviderInfoMap getAvailableProvidersInfo(); ProviderInfo getProviderInfo(string providerName); - bool hasProvider(string providerName); - int getUpdateCounterByProvider(string providerName); - StringIntDictionary getAllUpdateCounters(); + + // Modifying + observer::RequestObjectsOutput requestObjects(observer::RequestObjectsInput input); + }; }; diff --git a/source/RobotAPI/interface/objectpose/ObjectPoseProvider.ice b/source/RobotAPI/interface/objectpose/ObjectPoseProvider.ice index fc4ea878b6090b76baf1e05f3b8c1eaab699ad75..18201e65d3c652bd02c6957bbaff50cb9e8f46cc 100644 --- a/source/RobotAPI/interface/objectpose/ObjectPoseProvider.ice +++ b/source/RobotAPI/interface/objectpose/ObjectPoseProvider.ice @@ -33,27 +33,56 @@ module armarx // A struct's name cannot cannot differ only in capitalization from its immediately enclosing module name. module objpose { + interface ObjectPoseProvider; struct ProviderInfo { + ObjectPoseProvider* proxy; ObjectTypeEnum objectType = AnyObject; - ObjectIDSeq supportedObjects; + armarx::data::ObjectIDSeq supportedObjects; }; dictionary<string, ProviderInfo> ProviderInfoMap; - interface ObjectPoseTopic + module provider { - /// Signal that a new provider is now available (and ready for `getProviderInfo()`. - void reportProviderAvailable(string providerName); - void reportObjectPoses(string providerName, data::ProvidedObjectPoseSeq objectPoses); - }; + struct RequestObjectsInput + { + /// Object IDs. + armarx::data::ObjectIDSeq objectIDs; + /// For how long to request localization. Negative for no timeout. + long relativeTimeoutMS; + }; + struct ObjectRequestResult + { + bool success; + }; + dictionary<armarx::data::ObjectID, ObjectRequestResult> ObjectRequestResultMap; + struct RequestObjectsOutput + { + ObjectRequestResultMap results; + }; + }; interface ObjectPoseProvider { /// Get the provider info. ProviderInfo getProviderInfo(); /// Request to track the specified objects for some time. - void requestObjects(ObjectIDSeq objectIDs, long relativeTimeoutMS); + provider::RequestObjectsOutput requestObjects(provider::RequestObjectsInput input); + }; + + interface ObjectPoseTopic + { + /// Signal that a new provider is now available. + void reportProviderAvailable(string providerName, ProviderInfo info); + + /** + * @brief Report new object poses. + * + * This will overwrite all object poses previously provided + * with the same provider name. + */ + void reportObjectPoses(string providerName, data::ProvidedObjectPoseSeq candidates); }; }; diff --git a/source/RobotAPI/interface/objectpose/object_pose_types.ice b/source/RobotAPI/interface/objectpose/object_pose_types.ice index 19aa0e2df527ac84bed7a392e0c50818696189a1..d6b4d7a6eb93a681068f5d3583c9e80e5d0fe91b 100644 --- a/source/RobotAPI/interface/objectpose/object_pose_types.ice +++ b/source/RobotAPI/interface/objectpose/object_pose_types.ice @@ -24,6 +24,7 @@ #pragma once #include <RobotAPI/interface/core/PoseBase.ice> +#include <RobotAPI/interface/ArmarXObjects/ArmarXObjectsTypes.ice> module armarx @@ -36,18 +37,6 @@ module armarx AnyObject, KnownObject, UnknownObject }; - struct ObjectID - { - /// The dataset name in ArmarXObjects, e.g. "KIT", "YCB", "SecondHands", ... - string dataset; - /// The class name in ArmarXObjects, e.g. "Amicelli", "001_chips_can", ... - string className; - /// An optional instance name, chosen by the provider. - string instanceName; - }; - sequence<ObjectID> ObjectIDSeq; - - class AABB { Vector3Base center; @@ -77,7 +66,7 @@ module armarx ObjectTypeEnum objectType = AnyObject; /// The object ID, i.e. dataset and name. - ObjectID objectID; + armarx::data::ObjectID objectID; /// Pose in `objectPoseFrame`. PoseBase objectPose; @@ -88,7 +77,7 @@ module armarx /// Source timestamp. long timestampMicroSeconds = -1; - /// Object bounding box in object's local coordinate frame. May be null. + /// [Optional] Object bounding box in object's local coordinate frame. Box localOOBB; }; sequence<ProvidedObjectPose> ProvidedObjectPoseSeq; @@ -103,7 +92,7 @@ module armarx ObjectTypeEnum objectType = AnyObject; /// The object ID, i.e. dataset and name. - ObjectID objectID; + armarx::data::ObjectID objectID; PoseBase objectPoseRobot; PoseBase objectPoseGlobal; diff --git a/source/RobotAPI/libraries/ArmarXObjects/CMakeLists.txt b/source/RobotAPI/libraries/ArmarXObjects/CMakeLists.txt index 8bda146bb3a89d2ccd32fd3ffb54ac612bbdfb84..1eb0e4d8158f766649e7b0089e7001761241e664 100644 --- a/source/RobotAPI/libraries/ArmarXObjects/CMakeLists.txt +++ b/source/RobotAPI/libraries/ArmarXObjects/CMakeLists.txt @@ -13,6 +13,7 @@ set(LIB_FILES ObjectFinder.cpp json_conversions.cpp + ice_conversions.cpp ) set(LIB_HEADERS ArmarXObjects.h @@ -22,6 +23,7 @@ set(LIB_HEADERS ObjectFinder.h json_conversions.h + ice_conversions.h ) diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.cpp b/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.cpp index ac272b10abe1bc26e47a52527df38034b2f24905..1dc1903ea050d8c2f9fba6596d04fc12d197f5ba 100644 --- a/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.cpp +++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.cpp @@ -85,11 +85,20 @@ namespace armarx return file(".json", "_bb"); } - simox::AxisAlignedBoundingBox ObjectInfo::aabb() const + std::optional<simox::AxisAlignedBoundingBox> ObjectInfo::loadAABB() const { - nlohmann::json j = nlohmann::read_json(boundingBoxJson().absolutePath); - nlohmann::json jaabb = j.at("aabb"); + nlohmann::json j; + try + { + j = nlohmann::read_json(boundingBoxJson().absolutePath); + } + catch (const std::exception& e) + { + ARMARX_ERROR << e.what(); + return std::nullopt; + } + nlohmann::json jaabb = j.at("aabb"); auto center = jaabb.at("center").get<Eigen::Vector3f>(); auto extents = jaabb.at("extents").get<Eigen::Vector3f>(); auto min = jaabb.at("min").get<Eigen::Vector3f>(); @@ -106,9 +115,19 @@ namespace armarx return aabb; } - simox::OrientedBox<float> ObjectInfo::oobb() const + std::optional<simox::OrientedBox<float>> ObjectInfo::loadOOBB() const { - nlohmann::json j = nlohmann::read_json(boundingBoxJson().absolutePath); + nlohmann::json j; + try + { + j = nlohmann::read_json(boundingBoxJson().absolutePath); + } + catch (const std::exception& e) + { + ARMARX_ERROR << e.what(); + return std::nullopt; + } + nlohmann::json joobb = j.at("oobb"); auto pos = joobb.at("pos").get<Eigen::Vector3f>(); auto ori = joobb.at("ori").get<Eigen::Quaternionf>().toRotationMatrix(); diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.h b/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.h index c141bd9d467857c8869b60c2b5c5eebdd48697d4..5f50ec95691bb881b00be5e64703f39c9e9e7b02 100644 --- a/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.h +++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectInfo.h @@ -1,6 +1,7 @@ #pragma once #include <filesystem> +#include <optional> #include <string> #include "ObjectID.h" @@ -63,8 +64,17 @@ namespace armarx PackageFileLocation boundingBoxJson() const; - simox::AxisAlignedBoundingBox aabb() const; - simox::OrientedBox<float> oobb() const; + /** + * @brief Load the AABB (axis-aligned bounding-box) from the bounding box JSON file. + * @return Return the AABB if successful, `std::nullopt` if file does not exist. + */ + std::optional<simox::AxisAlignedBoundingBox> loadAABB() const; + /** + * @brief Load the OOBB (object-oriented bounding box) from the bounding box JSON file. + * The OOBB is defined the object's local frame. + * @return Return the OOBB if successful, `std::nullopt` if file does not exist. + */ + std::optional<simox::OrientedBox<float>> loadOOBB() const; /** diff --git a/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.cpp b/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7dd31ad9379e40a716869631b72ae3a6a7fb99a4 --- /dev/null +++ b/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.cpp @@ -0,0 +1,68 @@ +#include "ice_conversions.h" + + +namespace armarx +{ + std::ostream& data::operator<<(std::ostream& os, const ObjectID& id) + { + os << "'" << id.dataset << "/" << id.className; + if (!id.instanceName.empty()) + { + os << "/" << id.instanceName; + } + return os << "'"; + } + +} + +void armarx::fromIce(const data::ObjectID& ice, ObjectID& id) +{ + id = fromIce(ice); +} + +armarx::ObjectID armarx::fromIce(const data::ObjectID& ice) +{ + return { ice.dataset, ice.className, ice.instanceName }; +} + +void armarx::toIce(data::ObjectID& ice, const ObjectID& id) +{ + ice.dataset = id.dataset(); + ice.className = id.className(); + ice.instanceName = id.instanceName(); +} + +armarx::data::ObjectID armarx::toIce(const ObjectID& id) +{ + data::ObjectID ice; + toIce(ice, id); + return ice; +} + +void armarx::fromIce(const data::ObjectIDSeq& ice, std::vector<ObjectID>& ids) +{ + ids.clear(); + std::transform(ice.begin(), ice.end(), std::back_inserter(ids), + static_cast<ObjectID(*)(const data::ObjectID&)>(&fromIce)); +} + +std::vector<armarx::ObjectID> armarx::fromIce(const data::ObjectIDSeq& ice) +{ + std::vector<ObjectID> ids; + fromIce(ice, ids); + return ids; +} + +void armarx::toIce(data::ObjectIDSeq& ice, const std::vector<ObjectID>& ids) +{ + ice.clear(); + std::transform(ids.begin(), ids.end(), std::back_inserter(ice), + static_cast<data::ObjectID(*)(const ObjectID&)>(&toIce)); +} + +armarx::data::ObjectIDSeq armarx::toIce(const std::vector<ObjectID>& ids) +{ + data::ObjectIDSeq ice; + toIce(ice, ids); + return ice; +} diff --git a/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.h b/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.h new file mode 100644 index 0000000000000000000000000000000000000000..e17f37e35e1ff217d3fe8baab719ccaefe2d88b6 --- /dev/null +++ b/source/RobotAPI/libraries/ArmarXObjects/ice_conversions.h @@ -0,0 +1,28 @@ +#pragma once + +#include <RobotAPI/interface/ArmarXObjects/ArmarXObjectsTypes.h> + +#include "ObjectID.h" + + +namespace armarx::data +{ + std::ostream& operator<<(std::ostream& os, const ObjectID& id); +} + +namespace armarx +{ + + void fromIce(const data::ObjectID& ice, ObjectID& id); + ObjectID fromIce(const data::ObjectID& id); + + void fromIce(const data::ObjectIDSeq& ice, std::vector<ObjectID>& ids); + std::vector<ObjectID> fromIce(const data::ObjectIDSeq& id); + + void toIce(data::ObjectID& ice, const ObjectID& ids); + data::ObjectID toIce(const ObjectID& ids); + + void toIce(data::ObjectIDSeq& ice, const std::vector<ObjectID>& ids); + data::ObjectIDSeq toIce(const std::vector<ObjectID>& ids); + +}