rclcpp::executors::SingleThreadedExecutor executor_;
在 ROS 2(Robot Operating System 2)中,rclcpp::executors::SingleThreadedExecutor 是一个常用的执行器类,用于处理节点的回调函数和事件。
你提到的 executor_ 看起来是一个 SingleThreadedExecutor 类型的成员变量。这种执行器使用单个线程来处理所有注册到它的节点的回调函数,按照它们被触发的顺序依次执行。
在实际使用中,通常的模式是:
- 创建一个或多个节点
- 将这些节点添加到执行器中
- 调用执行器的
spin()方法开始处理回调
示例代码片段:
#include "rclcpp/rclcpp.hpp"
#include "rclcpp/executors/single_threaded_executor.hpp"
class MyNode : public rclcpp::Node {
// 节点实现...
};
int main(int argc, char * argv[]) {
rclcpp::init(argc, argv);
// 创建执行器
rclcpp::executors::SingleThreadedExecutor executor_;
// 创建节点
auto node = std::make_shared<MyNode>();
// 将节点添加到执行器
executor_.add_node(node);
// 开始执行回调
executor_.spin();
rclcpp::shutdown();
return 0;
}
SingleThreadedExecutor 适用于不需要并行处理回调的简单场景,它可以避免多线程带来的同步问题,但在处理大量计算密集型回调时可能会导致延迟。
rclcpp::executors::SingleThreadedExecutor executor_; 添加多线程
如果你想在 ROS 2 中使用多线程处理回调,可以将SingleThreadedExecutor替换为MultiThreadedExecutor,它支持配置线程池大小来实现多线程处理回调。
以下是使用多线程执行器的示例代码:
#include "rclcpp/rclcpp.hpp"
#include "rclcpp/executors/multi_threaded_executor.hpp"
class MyNode : public rclcpp::Node {
public:
MyNode() : Node("my_node") {
// 创建一个定时器回调作为示例
timer_ = this->create_wall_timer(
std::chrono::milliseconds(100),
std::bind(&MyNode::timer_callback, this)
);
// 创建一个订阅者作为示例
subscriber_ = this->create_subscription<std_msgs::msg::String>(
"test_topic",
10,
std::bind(&MyNode::sub_callback, this, std::placeholders::_1)
);
}
private:
void timer_callback() {
RCLCPP_INFO(this->get_logger(), "Timer callback executed on thread: %d",
std::this_thread::get_id());
}
void sub_callback(const std_msgs::msg::String::SharedPtr msg) {
RCLCPP_INFO(this->get_logger(), "Subscriber callback executed on thread: %d",
std::this_thread::get_id());
}
rclcpp::TimerBase::SharedPtr timer_;
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscriber_;
};
int main(int argc, char * argv[]) {
rclcpp::init(argc, argv);
// 创建多线程执行器,指定线程数为4
rclcpp::executors::MultiThreadedExecutor executor(rclcpp::executor::ExecutorArgs(), 4);
// 创建节点
auto node = std::make_shared<MyNode>();
// 将节点添加到执行器
executor.add_node(node);
// 开始执行回调
executor.spin();
rclcpp::shutdown();
return 0;
}
主要区别和注意事项:
-
MultiThreadedExecutor可以通过构造函数参数指定线程数量 -
// 方式1:直接指定线程数 rclcpp::executors::MultiThreadedExecutor executor(4); // 方式2:使用ExecutorArgs结构体 rclcpp::executor::ExecutorArgs args; args.number_of_threads = 4; rclcpp::executors::MultiThreadedExecutor executor(args); -
多线程执行器会在不同线程上并行执行回调函数,因此需要注意:
- 共享数据的线程安全问题
- 可能需要使用互斥锁 (
std::mutex) 保护共享资源 - 回调函数的执行顺序不再有严格保证
-
线程数量的选择应根据实际需求:
- 过多的线程可能导致系统开销增加
- 通常根据 CPU 核心数量来设置合理的线程数
使用多线程执行器可以提高系统的响应性,特别是当某些回调函数执行时间较长时,可以避免阻塞其他回调的执行。
如何配置MultiThreadedExecutor的线程池大小?
在 ROS 2 中,配置MultiThreadedExecutor的线程池大小有几种常用方法,可根据具体需求选择:
1. 直接通过构造函数指定线程数
最简单的方式是在创建MultiThreadedExecutor对象时直接指定线程数量:
2. 使用ExecutorArgs结构体配置
更灵活的方式是通过rclcpp::executor::ExecutorArgs结构体进行配置,除了线程数外还能设置其他参数:
. 动态设置(基于 CPU 核心数)
通常建议根据系统 CPU 核心数量来设置线程数,可通过std::thread::hardware_concurrency()获取:
. 从参数服务器读取配置
更灵活的方式是从 ROS 参数服务器读取线程数配置,便于运行时调整:
// 先创建一个临时节点用于读取参数
auto temp_node = rclcpp::Node::make_shared("executor_config_node");
// 声明参数(默认值为4)
temp_node->declare_parameter("executor_threads", 4);
// 读取参数
int thread_count;
temp_node->get_parameter("executor_threads", thread_count);
// 创建执行器
rclcpp::executors::MultiThreadedExecutor executor(thread_count);
注意事项:
- 线程数并非越多越好,过多的线程会导致线程切换开销增大
- 对于 CPU 密集型任务,线程数通常设置为 CPU 核心数的 1-2 倍
- 对于 IO 密集型任务(如网络通信、传感器读取),可适当增加线程数
- 多线程执行器会并行执行回调,需确保回调函数中的共享资源线程安全(可使用
std::mutex等同步机制)
通过上述方法,你可以根据应用场景灵活配置MultiThreadedExecutor的线程池大小,以达到最佳性能。
521

被折叠的 条评论
为什么被折叠?



