当前位置: 首页 > news >正文

ros2 单线程与多线程

rclcpp::executors::SingleThreadedExecutor executor_;

在 ROS 2(Robot Operating System 2)中,rclcpp::executors::SingleThreadedExecutor 是一个常用的执行器类,用于处理节点的回调函数和事件。

你提到的 executor_ 看起来是一个 SingleThreadedExecutor 类型的成员变量。这种执行器使用单个线程来处理所有注册到它的节点的回调函数,按照它们被触发的顺序依次执行。

在实际使用中,通常的模式是:

  1. 创建一个或多个节点
  2. 将这些节点添加到执行器中
  3. 调用执行器的 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);// 创建多线程执行器,指定线程数为4rclcpp::executors::MultiThreadedExecutor executor(rclcpp::executor::ExecutorArgs(), 4);// 创建节点auto node = std::make_shared<MyNode>();// 将节点添加到执行器executor.add_node(node);// 开始执行回调executor.spin();rclcpp::shutdown();return 0;
}

主要区别和注意事项:

  1. MultiThreadedExecutor 可以通过构造函数参数指定线程数量

  2. // 方式1:直接指定线程数
    rclcpp::executors::MultiThreadedExecutor executor(4);// 方式2:使用ExecutorArgs结构体
    rclcpp::executor::ExecutorArgs args;
    args.number_of_threads = 4;
    rclcpp::executors::MultiThreadedExecutor executor(args);
    
  3. 多线程执行器会在不同线程上并行执行回调函数,因此需要注意:

    • 共享数据的线程安全问题
    • 可能需要使用互斥锁 (std::mutex) 保护共享资源
    • 回调函数的执行顺序不再有严格保证
  4. 线程数量的选择应根据实际需求:

    • 过多的线程可能导致系统开销增加
    • 通常根据 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的线程池大小,以达到最佳性能。

http://www.dtcms.com/a/323680.html

相关文章:

  • MySQL相关概念和易错知识点(4)(分组查询、连接查询、合并查询、子查询)
  • M8-11 RFID模块通过RS485转Profinet网关与PLC通信的配置指南
  • springboot 2.4跨域变化和swagger结合的问题
  • 智能的本质
  • 递归---记忆化搜索
  • 前端Web在Vue中的知识详解
  • 【MySQL】事务的基本概念
  • 智慧物流仓储分拣:陌讯多模态识别方案让准确率↑29.3% 实战解析
  • js零基础入门
  • 零基础-动手学深度学习-10.1. 注意力提示
  • vs2022编译Activemq
  • AnyDesk远程工具免费版,v9.5.110绿色便携版,秒连远程桌面,剪贴板同步超实用
  • 网络管理实战
  • B.10.01.6-DDD领域驱动设计:从理论到落地的完整指南
  • 【LLM实战|langgraph】langgrpah基础
  • WD5030A 芯片,24V降12V,输出电流15A,高度集成实现高效能与低成本的完美平衡
  • 如何免费配置各类AI API_Key?(附接入后测试)
  • 创建一个django项目
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段(15):文法+单词第5回
  • 生产环境某业务服务JVM调优总结
  • DAY35打卡
  • [IOMMU]面向芯片/SoC验证工程的IOMMU全景速览
  • FMS 2025存储峰会获奖技术全景解读
  • 【linux基础】Linux命令提示符解析与操作指南
  • c++ 容器vector基础
  • 北斗变形监测技术应用与案例解析
  • RK3568 U盘/TF卡镜像更新
  • Mysql笔记-系统变量\用户变量管理
  • 学习嵌入式第二十四天
  • 【Python 语法糖小火锅 · 第 1 涮】