diff --git a/source/RobotAPI/components/armem/CMakeLists.txt b/source/RobotAPI/components/armem/CMakeLists.txt index 526448e132f6e282b3d3f14fd39132fe32017ebb..f6c875f0b9f96079cad2880ca2b64f48fc68fdb9 100644 --- a/source/RobotAPI/components/armem/CMakeLists.txt +++ b/source/RobotAPI/components/armem/CMakeLists.txt @@ -2,7 +2,7 @@ add_subdirectory(server) # memory server addons - +add_subdirectory(addon) # clients add_subdirectory(client) diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp index 27aaa07ddf1c0f0dc819a9a74366036cdadfe11c..95018ad3cee17565ea0feaf07da615e3119d3674 100644 --- a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp +++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp @@ -45,11 +45,10 @@ namespace armarx::armem::server::robot_state { addPlugin(debugObserver); ARMARX_CHECK_NOT_NULL(debugObserver); + addPlugin(robotUnit.plugin); ARMARX_CHECK_NOT_NULL(robotUnit.plugin); - - robotUnit.reader.setTag(getName()); - robotUnit.writer.setTag(getName()); + robotUnit.plugin->setRobotUnitAsOptionalDependency(true); } @@ -62,7 +61,7 @@ namespace armarx::armem::server::robot_state { armarx::PropertyDefinitionsPtr defs = new ComponentPropertyDefinitions(getConfigIdentifier()); - const std::string robotUnitPrefix = sensorValuePrefix; + const std::string robotUnitPrefix = robotUnit.sensorValuePrefix; defs->optional(robotUnit.reader.properties.sensorPrefix, robotUnitPrefix + "SensorValuePrefix", "Prefix of all sensor values."); @@ -71,13 +70,13 @@ namespace armarx::armem::server::robot_state .setMin(1); defs->optional(robotUnit.pollFrequency, robotUnitPrefix + "UpdateFrequency", "The frequency to store values in Hz. All other values get discarded. " - "Minimum is 1, max is " + std::to_string(ROBOT_UNIT_MAXIMUM_FREQUENCY) + ".") - .setMin(1).setMax(ROBOT_UNIT_MAXIMUM_FREQUENCY); + "Minimum is 1, max is " + std::to_string(robotUnit.ROBOT_UNIT_MAXIMUM_FREQUENCY) + ".") + .setMin(1).setMax(robotUnit.ROBOT_UNIT_MAXIMUM_FREQUENCY); const std::string prefix = "mem."; - workingMemory().name() = "RobotState"; + setMemoryName("RobotState"); descriptionSegment.defineProperties(defs, prefix + "desc."); proprioceptionSegment.defineProperties(defs, prefix + "prop."); @@ -101,7 +100,7 @@ namespace armarx::armem::server::robot_state localizationSegment.onInit(); commonVisu.init(); - robotUnit.pollFrequency = std::clamp(robotUnit.pollFrequency, 0.f, ROBOT_UNIT_MAXIMUM_FREQUENCY); + robotUnit.pollFrequency = std::clamp(robotUnit.pollFrequency, 0.f, robotUnit.ROBOT_UNIT_MAXIMUM_FREQUENCY); robotUnit.writer.properties.memoryBatchSize = std::max(static_cast<unsigned int>(1), robotUnit.writer.properties.memoryBatchSize); std::vector<std::string> includePaths; @@ -127,38 +126,43 @@ namespace armarx::armem::server::robot_state { ARMARX_CHECK_NOT_NULL(debugObserver->getDebugObserver()); - if (robotUnit.plugin->getRobotUnit()) + // 1. General setup + localizationSegment.onConnect(); + commonVisu.connect(getArvizClient(), debugObserver->getDebugObserver()); + + // 2. Check for RobotUnit. If RobotUnit is enabled. Otherwise we do not wait for a streaming service and do not setup the segments + if (robotUnit.plugin->hasRobotUnitName()) { robotUnit.plugin->waitUntilRobotUnitIsRunning(); - } - RobotUnitInterfacePrx robotUnitPrx = robotUnit.plugin->getRobotUnit(); + RobotUnitInterfacePrx robotUnitPrx = robotUnit.plugin->getRobotUnit(); - descriptionSegment.onConnect(robotUnitPrx); - proprioceptionSegment.onConnect(robotUnitPrx); - localizationSegment.onConnect(); + robotUnit.reader.setTag(getName()); + robotUnit.writer.setTag(getName()); - commonVisu.connect(getArvizClient(), debugObserver->getDebugObserver()); + descriptionSegment.onConnect(robotUnitPrx); + proprioceptionSegment.onConnect(robotUnitPrx); - robotUnit.reader.connect(*robotUnit.plugin, *debugObserver, - proprioceptionSegment.getRobotUnitProviderID().providerSegmentName); - robotUnit.writer.connect(*debugObserver); - robotUnit.writer.properties.robotUnitProviderID = proprioceptionSegment.getRobotUnitProviderID(); + robotUnit.reader.connect(*robotUnit.plugin, *debugObserver, + proprioceptionSegment.getRobotUnitProviderID().providerSegmentName); + robotUnit.writer.connect(*debugObserver); + robotUnit.writer.properties.robotUnitProviderID = proprioceptionSegment.getRobotUnitProviderID(); - robotUnit.reader.task = new SimpleRunningTask<>([this]() - { - robotUnit.reader.run( - robotUnit.pollFrequency, robotUnit.dataQueue, robotUnit.dataMutex - ); - }, "Robot Unit Reader"); - robotUnit.writer.task = new SimpleRunningTask<>([this]() - { - robotUnit.writer.run( - robotUnit.pollFrequency, robotUnit.dataQueue, robotUnit.dataMutex, - iceAdapter(), localizationSegment - ); - }, "Robot State Writer"); + robotUnit.reader.task = new SimpleRunningTask<>([this]() + { + robotUnit.reader.run( + robotUnit.pollFrequency, robotUnit.dataQueue, robotUnit.dataMutex + ); + }, "Robot Unit Reader"); + robotUnit.writer.task = new SimpleRunningTask<>([this]() + { + robotUnit.writer.run( + robotUnit.pollFrequency, robotUnit.dataQueue, robotUnit.dataMutex, + iceAdapter(), localizationSegment + ); + }, "Robot State Writer"); - startRobotUnitStream(); + startRobotUnitStream(); + } } @@ -181,6 +185,8 @@ namespace armarx::armem::server::robot_state void RobotStateMemory::startRobotUnitStream() { + ARMARX_CHECK(robotUnit.plugin->robotUnitIsRunning()); + if (robotUnit.reader.task->isRunning() || robotUnit.writer.task->isRunning()) { if (robotUnit.reader.task->isRunning() && robotUnit.writer.task->isRunning()) diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.h b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.h index 74dd4a3fa12fea08186ec14d1b93fdf6872ac7dd..6459b2aac44dbea0a64c8b2fe35efed2e69f020c 100644 --- a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.h +++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.h @@ -111,6 +111,10 @@ namespace armarx::armem::server::robot_state struct RobotUnit { + // params + static constexpr float ROBOT_UNIT_MAXIMUM_FREQUENCY = 100; + static constexpr const char* sensorValuePrefix = "RobotUnit."; + float pollFrequency = 50; armarx::plugins::RobotUnitComponentPlugin* plugin = nullptr; @@ -122,13 +126,6 @@ namespace armarx::armem::server::robot_state std::mutex dataMutex; }; RobotUnit robotUnit; - - - // params - static constexpr float ROBOT_UNIT_MAXIMUM_FREQUENCY = 100; - static constexpr const char* sensorValuePrefix = "RobotUnit."; - - }; } // namespace armarx::armem::server::robot_state diff --git a/source/RobotAPI/interface/CMakeLists.txt b/source/RobotAPI/interface/CMakeLists.txt index a7cc9ca79c5ecc5f99f294065709cc3daa0e2790..a4810afdc94dbd8b1260a3e5c41ba714d3c25d42 100644 --- a/source/RobotAPI/interface/CMakeLists.txt +++ b/source/RobotAPI/interface/CMakeLists.txt @@ -126,6 +126,9 @@ set(SLICE_FILES # Special Servers armem/server/ObjectMemoryInterface.ice + # Special Addons + armem/addon/LegacyRobotStateMemoryAdapterInterface.ice + armem/mns.ice armem/mns/MemoryNameSystemInterface.ice diff --git a/source/RobotAPI/interface/units/LaserScannerUnit.ice b/source/RobotAPI/interface/units/LaserScannerUnit.ice index 208f51515387ee99e5dd095719c43482e772fae5..631974396e0de5c50dcd67e73c47da2ad78fa99f 100644 --- a/source/RobotAPI/interface/units/LaserScannerUnit.ice +++ b/source/RobotAPI/interface/units/LaserScannerUnit.ice @@ -48,7 +48,7 @@ module armarx { float angle; float distance; - float intensity; +// float intensity; }; struct LaserScannerInfo diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.cpp b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.cpp index 6647cf38585cb868a3df29e9c328bbfe8ac3a677..2bc74d3ea925b041652f020b47223afe872cdeb4 100644 --- a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.cpp +++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.cpp @@ -80,16 +80,29 @@ namespace armarx::plugins void RobotUnitComponentPlugin::preOnConnectComponent() { - parent<Component>().getProxy(_robotUnit, _robotUnitName); + if (not _robotUnitName.empty()) + { + parent<Component>().getProxy(_robotUnit, _robotUnitName); + } } void RobotUnitComponentPlugin::postCreatePropertyDefinitions(armarx::PropertyDefinitionsPtr& properties) { if (!properties->hasDefinition(PROPERTY_NAME)) { - properties->defineRequiredProperty<std::string>( - PROPERTY_NAME, - "Name of the RobotUnit"); + if (_isRobotUnitOptionalDependency) + { + properties->defineOptionalProperty<std::string>( + PROPERTY_NAME, + "", + "Name of the RobotUnit"); + } + else + { + properties->defineRequiredProperty<std::string>( + PROPERTY_NAME, + "Name of the RobotUnit"); + } } } @@ -100,7 +113,6 @@ namespace armarx::plugins void RobotUnitComponentPlugin::setRobotUnitName(const std::string& name) { - ARMARX_CHECK_NOT_EMPTY(name); ARMARX_CHECK_EMPTY(_robotUnitName); _robotUnitName = name; } @@ -110,17 +122,28 @@ namespace armarx::plugins return _robotUnitName; } - void RobotUnitComponentPlugin::deactivate() + bool RobotUnitComponentPlugin::hasRobotUnitName() const { - _isRobotUnitOptionalDependency = true; + return not _robotUnitName.empty(); } + void RobotUnitComponentPlugin::setRobotUnitAsOptionalDependency(bool isOptional) + { + _isRobotUnitOptionalDependency = isOptional; + } - void RobotUnitComponentPlugin::waitUntilRobotUnitIsRunning(const std::function<bool ()>& termCond) const + void RobotUnitComponentPlugin::waitUntilRobotUnitIsRunning(const std::function<bool ()>& termCond) { ARMARX_INFO << "Waiting until robot unit is running ..."; - while (not(termCond() or not isNullptr(getRobotUnit()) or getRobotUnit()->isRunning())) + if (not hasRobotUnitName()) + { + ARMARX_ERROR << "Could not wait for a robotUnit without a name!"; + return; + } + + parent<Component>().usingProxy(_robotUnitName); + while (not(termCond() or not robotUnitIsRunning())) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } @@ -128,7 +151,15 @@ namespace armarx::plugins ARMARX_INFO << "Robot unit is up and running."; } - + bool RobotUnitComponentPlugin::robotUnitIsRunning() const + { + if (not hasRobotUnitName()) + { + // An empty robotUnit can never run + return false; + } + return not(isNullptr(getRobotUnit()) or not getRobotUnit()->isRunning()); + } } // namespace armarx::plugins diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h index 4371934b97182947afbaad3d60fd5295a717615a..6edd2d83691362e3dfdebb372984ca05f497e586 100644 --- a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h +++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h @@ -26,13 +26,9 @@ namespace armarx void setRobotUnitName(const std::string& name); const std::string& getRobotUnitName() const; + bool hasRobotUnitName() const; - void deactivate(); - - void setRobotUnitAsOptionalDependency(bool isOptional = true) - { - - } + void setRobotUnitAsOptionalDependency(bool isOptional = true); /** * @brief Waits until the robot unit is running. @@ -44,7 +40,9 @@ namespace armarx * If it evaluates to true, waitUntilRobotUnitIsRunning returns without waiting * for the robot unit to become available. */ - void waitUntilRobotUnitIsRunning(const std::function<bool()>& termCond = [] {return false;}) const; + void waitUntilRobotUnitIsRunning(const std::function<bool()>& termCond = [] {return false;}); + + bool robotUnitIsRunning() const;