diff --git a/tesseract_task_composer/core/include/tesseract_task_composer/core/task_composer_plugin_factory.h b/tesseract_task_composer/core/include/tesseract_task_composer/core/task_composer_plugin_factory.h index 2d3f44e9aaa..9cd16896b17 100644 --- a/tesseract_task_composer/core/include/tesseract_task_composer/core/task_composer_plugin_factory.h +++ b/tesseract_task_composer/core/include/tesseract_task_composer/core/task_composer_plugin_factory.h @@ -32,6 +32,7 @@ TESSERACT_COMMON_IGNORE_WARNINGS_PUSH #include #include #include +#include TESSERACT_COMMON_IGNORE_WARNINGS_POP #include @@ -72,6 +73,8 @@ class TaskComposerNodeFactory const YAML::Node& config, const TaskComposerPluginFactory& plugin_factory) const = 0; + virtual std::unique_ptr create() const = 0; + protected: static std::string getSection(); friend class boost_plugin_loader::PluginLoader; @@ -89,6 +92,8 @@ class TaskComposerExecutorFactory virtual std::unique_ptr create(const std::string& name, const YAML::Node& config) const = 0; + virtual std::unique_ptr create() const = 0; + protected: static std::string getSection(); friend class boost_plugin_loader::PluginLoader; @@ -307,6 +312,16 @@ class TaskComposerPluginFactory */ YAML::Node getConfig() const; + /** + * @brief Returns a list of available task composer node plugins + */ + std::vector getAvailableTaskComposerNodePlugins() const; + + /** + * @brief Returns a list of available task composer executor plugins + */ + std::vector getAvailableTaskComposerExecutorPlugins() const; + private: struct Implementation; std::unique_ptr impl_; diff --git a/tesseract_task_composer/core/include/tesseract_task_composer/core/task_composer_plugin_factory_utils.h b/tesseract_task_composer/core/include/tesseract_task_composer/core/task_composer_plugin_factory_utils.h index 0132346aa1a..9c9b05d22f5 100644 --- a/tesseract_task_composer/core/include/tesseract_task_composer/core/task_composer_plugin_factory_utils.h +++ b/tesseract_task_composer/core/include/tesseract_task_composer/core/task_composer_plugin_factory_utils.h @@ -40,6 +40,8 @@ class TaskComposerTaskFactory : public TaskComposerNodeFactory { return std::make_unique(name, config, plugin_factory); } + + std::unique_ptr create() const override { return std::make_unique(); } }; template @@ -50,6 +52,8 @@ class TaskComposerExecutorFactoryImpl : public TaskComposerExecutorFactory { return std::make_unique(name, config); } + + std::unique_ptr create() const override { return std::make_unique(); } }; } // namespace tesseract_planning diff --git a/tesseract_task_composer/core/src/task_composer_plugin_factory.cpp b/tesseract_task_composer/core/src/task_composer_plugin_factory.cpp index 4655b4b44dc..67cb2f4cc9b 100644 --- a/tesseract_task_composer/core/src/task_composer_plugin_factory.cpp +++ b/tesseract_task_composer/core/src/task_composer_plugin_factory.cpp @@ -282,17 +282,42 @@ std::string TaskComposerPluginFactory::getDefaultTaskComposerNodePlugin() const std::unique_ptr TaskComposerPluginFactory::createTaskComposerExecutor(const std::string& name) const { - const auto& executor_plugin_info = impl_->executor_plugin_info; - auto cm_it = executor_plugin_info.plugins.find(name); - if (cm_it == executor_plugin_info.plugins.end()) + try + { + // Check if the input name has associated plugin information + const auto& executor_plugin_info = impl_->executor_plugin_info; + auto cm_it = executor_plugin_info.plugins.find(name); + if (cm_it != executor_plugin_info.plugins.end()) + return createTaskComposerExecutor(name, cm_it->second); + + // Check if a plugin factory has already been loaded for the input plugin name + auto& executor_factories = impl_->executor_factories; + auto it = executor_factories.find(name); + if (it != executor_factories.end()) + { + // Default create a task composer node from the plugin since no configuration information exists + return it->second->create(); + } + + // Load the plugin since one has not already been loaded + auto plugin = impl_->plugin_loader.instantiate(name); + if (plugin == nullptr) + { + CONSOLE_BRIDGE_logWarn("Failed to load symbol '%s'", name.c_str()); + return nullptr; + } + + // Store the plugin internally to keep the plugin in scope for the lifetime of this factory object + executor_factories[name] = plugin; + + // Default create a task composer node from the plugin since no configuration information exists + return plugin->create(); + } + catch (const std::exception& e) { - CONSOLE_BRIDGE_logWarn("TaskComposerPluginFactory, tried to get task composer executor '%s' that does not " - "exist!", - name.c_str()); + CONSOLE_BRIDGE_logWarn("Failed to load symbol '%s', Details: %s", name.c_str(), e.what()); return nullptr; } - - return createTaskComposerExecutor(name, cm_it->second); } std::unique_ptr @@ -324,17 +349,42 @@ TaskComposerPluginFactory::createTaskComposerExecutor(const std::string& name, std::unique_ptr TaskComposerPluginFactory::createTaskComposerNode(const std::string& name) const { - const auto& task_plugin_info = impl_->task_plugin_info; - auto cm_it = task_plugin_info.plugins.find(name); - if (cm_it == task_plugin_info.plugins.end()) + try { - CONSOLE_BRIDGE_logWarn("TaskComposerPluginFactory, tried to get task composer node '%s' that does not " - "exist!", - name.c_str()); + // Check if the input name has associated plugin information + const auto& task_plugin_info = impl_->task_plugin_info; + auto cm_it = task_plugin_info.plugins.find(name); + if (cm_it != task_plugin_info.plugins.end()) + return createTaskComposerNode(name, cm_it->second); + + // Check if a plugin factory has already been loaded for the input plugin name + auto& node_factories = impl_->node_factories; + auto it = node_factories.find(name); + if (it != node_factories.end()) + { + // Default create a task composer node from the plugin since no configuration information exists + return it->second->create(); + } + + // Load the plugin since one has not already been loaded + auto plugin = impl_->plugin_loader.instantiate(name); + if (plugin == nullptr) + { + CONSOLE_BRIDGE_logWarn("Failed to load symbol '%s'", name.c_str()); + return nullptr; + } + + // Store the plugin internally to keep the plugin in scope for the lifetime of this factory object + node_factories[name] = plugin; + + // Default create a task composer node from the plugin since no configuration information exists + return plugin->create(); + } + catch (const std::exception& e) + { + CONSOLE_BRIDGE_logWarn("Failed to load symbol '%s', Details: %s", name.c_str(), e.what()); return nullptr; } - - return createTaskComposerNode(name, cm_it->second); } std::unique_ptr @@ -384,4 +434,15 @@ YAML::Node TaskComposerPluginFactory::getConfig() const return config; } + +std::vector TaskComposerPluginFactory::getAvailableTaskComposerNodePlugins() const +{ + return impl_->plugin_loader.getAvailablePlugins("TaskNode"); +} + +std::vector TaskComposerPluginFactory::getAvailableTaskComposerExecutorPlugins() const +{ + return impl_->plugin_loader.getAvailablePlugins("TaskExec"); +} + } // namespace tesseract_planning