From 85c9c7d829522ac34b9f102622ccdbdfa0d03dc9 Mon Sep 17 00:00:00 2001 From: mini-1235 Date: Tue, 14 Apr 2026 18:54:17 +0000 Subject: [PATCH 1/2] Refactor component containers Signed-off-by: mini-1235 --- rclcpp_components/src/component_container.cpp | 144 +++++++++++++++++- .../src/component_container_event.cpp | 4 + .../src/component_container_isolated.cpp | 5 + .../src/component_container_mt.cpp | 3 + 4 files changed, 153 insertions(+), 3 deletions(-) diff --git a/rclcpp_components/src/component_container.cpp b/rclcpp_components/src/component_container.cpp index cc5018ef3a..5cd1ca58f4 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\n"); +} 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..967dc550a3 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.\n"); + /// 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..49a18892d5 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'.\n"); + /// 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 9675f9a7a7..fbc3353529 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. " + "Use 'component_container --executor-type multi-threaded' instead."); /// Component container with a multi-threaded executor. rclcpp::init(argc, argv); From 4bbb417e0f5f128d54a39fe5bbdbc84d3800d990 Mon Sep 17 00:00:00 2001 From: mini-1235 Date: Tue, 14 Apr 2026 19:08:04 +0000 Subject: [PATCH 2/2] Format Signed-off-by: mini-1235 --- rclcpp_components/src/component_container.cpp | 2 +- rclcpp_components/src/component_container_event.cpp | 2 +- rclcpp_components/src/component_container_isolated.cpp | 2 +- rclcpp_components/src/component_container_mt.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rclcpp_components/src/component_container.cpp b/rclcpp_components/src/component_container.cpp index 5cd1ca58f4..7e49ae3fec 100644 --- a/rclcpp_components/src/component_container.cpp +++ b/rclcpp_components/src/component_container.cpp @@ -109,7 +109,7 @@ print_usage() " 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\n"); + " component_container --executor-type single-threaded --isolated"); } int main(int argc, char * argv[]) diff --git a/rclcpp_components/src/component_container_event.cpp b/rclcpp_components/src/component_container_event.cpp index 967dc550a3..c47c9681f3 100644 --- a/rclcpp_components/src/component_container_event.cpp +++ b/rclcpp_components/src/component_container_event.cpp @@ -23,7 +23,7 @@ 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.\n"); + "Use 'component_container --executor-type events' instead."); /// Component container with an events executor. rclcpp::init(argc, argv); diff --git a/rclcpp_components/src/component_container_isolated.cpp b/rclcpp_components/src/component_container_isolated.cpp index 49a18892d5..5768e5e29a 100644 --- a/rclcpp_components/src/component_container_isolated.cpp +++ b/rclcpp_components/src/component_container_isolated.cpp @@ -27,7 +27,7 @@ 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'.\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); diff --git a/rclcpp_components/src/component_container_mt.cpp b/rclcpp_components/src/component_container_mt.cpp index fbc3353529..759289d5f1 100644 --- a/rclcpp_components/src/component_container_mt.cpp +++ b/rclcpp_components/src/component_container_mt.cpp @@ -22,7 +22,7 @@ int main(int argc, char * argv[]) { RCUTILS_LOG_WARN_NAMED("component_container_mt", - "This executable is deprecated and will be removed in M-turtle. " + "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);