diff --git a/rclcpp_components/src/component_container.cpp b/rclcpp_components/src/component_container.cpp index cc5018ef3a..7e49ae3fec 100644 --- a/rclcpp_components/src/component_container.cpp +++ b/rclcpp_components/src/component_container.cpp @@ -13,18 +13,156 @@ // limitations under the License. #include +#include +#include +#include +#include +#include "rcutils/logging_macros.h" +#include "rclcpp/executors/multi_threaded_executor.hpp" #include "rclcpp/executors/single_threaded_executor.hpp" +#include "rclcpp/experimental/executors/events_executor/events_executor.hpp" #include "rclcpp/utilities.hpp" #include "rclcpp_components/component_manager.hpp" +#include "rclcpp_components/component_manager_isolated.hpp" + +enum class ExecutorType +{ + SingleThreaded, + MultiThreaded, + Events +}; + +std::optional +parse_executor_type(const std::string & arg) +{ + if (arg == "single-threaded") { + return ExecutorType::SingleThreaded; + } + if (arg == "multi-threaded") { + return ExecutorType::MultiThreaded; + } + if (arg == "events") { + return ExecutorType::Events; + } + return std::nullopt; +} + +struct ParsedArgs +{ + ExecutorType executor_type = ExecutorType::SingleThreaded; + bool isolated = false; + bool help = false; + bool invalid = false; + std::string error_message; +}; + +ParsedArgs +parse_args(const std::vector & args) +{ + ParsedArgs parsed; + + for (size_t i = 1; i < args.size(); ++i) { + const std::string & arg = args[i]; + + if (arg == "--isolated") { + parsed.isolated = true; + continue; + } + + if (arg == "--help" || arg == "-h") { + parsed.help = true; + return parsed; + } + + if (arg == "--executor-type") { + if (i + 1 >= args.size()) { + parsed.invalid = true; + parsed.error_message = "Missing value for --executor-type"; + return parsed; + } + auto option = parse_executor_type(args[++i]); + if (!option) { + parsed.invalid = true; + parsed.error_message = "Invalid executor type: " + args[i]; + return parsed; + } + parsed.executor_type = option.value(); + continue; + } + + parsed.invalid = true; + parsed.error_message = "Unknown argument: " + arg; + return parsed; + } + + return parsed; +} + +void +print_usage() +{ + RCUTILS_LOG_INFO_NAMED( + "component_container", + "Usage: component_container [--executor-type ] [--isolated]\n" + " component_container --help|-h\n" + "Defaults: single-threaded, non-isolated\n" + "Examples: component_container --executor-type multi-threaded\n" + " component_container --executor-type single-threaded --isolated"); +} int main(int argc, char * argv[]) { - /// Component container with a single-threaded executor. rclcpp::init(argc, argv); - auto exec = std::make_shared(); - auto node = std::make_shared(exec); + + std::vector args = rclcpp::remove_ros_arguments(argc, argv); + ParsedArgs parsed = parse_args(args); + + if (parsed.help) { + print_usage(); + return 0; + } + + if (parsed.invalid) { + RCUTILS_LOG_ERROR_NAMED("component_container", "%s", parsed.error_message.c_str()); + print_usage(); + return 1; + } + + ExecutorType executor_type = parsed.executor_type; + bool isolated = parsed.isolated; + + std::shared_ptr exec = nullptr; + std::shared_ptr node = nullptr; + + if (executor_type == ExecutorType::MultiThreaded) { + if (isolated) { + exec = std::make_shared(); + node = std::make_shared>(); + } else { + node = std::make_shared(); + if (node->has_parameter("thread_num")) { + const auto thread_num = node->get_parameter("thread_num").as_int(); + exec = std::make_shared( + rclcpp::ExecutorOptions(), thread_num); + } else { + exec = std::make_shared(); + } + } + } else if (executor_type == ExecutorType::Events) { + exec = std::make_shared(); + node = std::make_shared(); + } else { + exec = std::make_shared(); + if (isolated) { + node = std::make_shared>(); + } else { + node = std::make_shared(); + } + } + + node->set_executor(exec); exec->add_node(node); exec->spin(); diff --git a/rclcpp_components/src/component_container_event.cpp b/rclcpp_components/src/component_container_event.cpp index f693281023..c47c9681f3 100644 --- a/rclcpp_components/src/component_container_event.cpp +++ b/rclcpp_components/src/component_container_event.cpp @@ -21,6 +21,10 @@ int main(int argc, char * argv[]) { + RCUTILS_LOG_WARN_NAMED("component_container_event", + "This executable is deprecated and will be removed in M-turtle.\n" + "Use 'component_container --executor-type events' instead."); + /// Component container with an events executor. rclcpp::init(argc, argv); auto exec = std::make_shared(); diff --git a/rclcpp_components/src/component_container_isolated.cpp b/rclcpp_components/src/component_container_isolated.cpp index dbb4c134eb..5768e5e29a 100644 --- a/rclcpp_components/src/component_container_isolated.cpp +++ b/rclcpp_components/src/component_container_isolated.cpp @@ -24,6 +24,11 @@ int main(int argc, char * argv[]) { + RCUTILS_LOG_WARN_NAMED("component_container_isolated", + "This executable is deprecated and will be removed in M-turtle.\n" + "Use 'component_container --executor-type single-threaded --isolated' instead.\n" + "For a multi-threaded isolated setup, use 'component_container --executor-type multi-threaded --isolated'."); + /// Component container with dedicated single-threaded executors for each components. rclcpp::init(argc, argv); // parse arguments diff --git a/rclcpp_components/src/component_container_mt.cpp b/rclcpp_components/src/component_container_mt.cpp index f752c4d06b..5a3faf40de 100644 --- a/rclcpp_components/src/component_container_mt.cpp +++ b/rclcpp_components/src/component_container_mt.cpp @@ -21,6 +21,9 @@ int main(int argc, char * argv[]) { + RCUTILS_LOG_WARN_NAMED("component_container_mt", + "This executable is deprecated and will be removed in M-turtle.\n" + "Use 'component_container --executor-type multi-threaded' instead."); /// Component container with a multi-threaded executor. rclcpp::init(argc, argv);