ROS2学习(四)进程,线程与节点的关系
节点与节点执行器
节点,英文是node,在ROS2中,节点是一个抽象的实体,它可以代表某种或某类特定功能的抽象集合体,它可以存在于进程中,也可以存在于线程中。所有ROS2的基础功能最基础的载体是节点,所有的通信也都需要通过节点来实现和运作。
在ROS中,节点是作为最小的进程单元存在的,它作为一个独立的可执行程序,承载着与其他节点通信的重要使命。在ROS2中,节点和进程的概念完全分开的,节点是独立于操作系统进程或者线程的概念的抽象定义,它虽然依旧承载着通信的功能,但是并不作为独立的进程运行,而是嵌入进程中,作为一个抽象的实体进行运作。
在一个项目中,可能存在若干个进程,每个进程中有一个或者若干个节点执行器,而每个节点执行器中又有一个或者若干个节点。节点运行在节点执行器中,借助节点执行器协调到资源和调度方式运作,如在哪一时刻处理订阅的消息,在哪个时刻处理服务消息等。所有在服务中和订阅中有关线程的设定,也需要节点执行器满足条件才能成功运作。

节点执行器作为进程中维护节点的载体, 在rclpy和rclcpp中均有单线程节点执行器(SingleThread Executor)和多线程节点执行器(Multi Threaded Executor)。单线程节点执行器表示其负责管理的回调函数只会占用一个线程资源,并且会根据其指定的规则对回调顺序和优先级进行设置。多线程节点执行器表示其负责管理的回调函数可以占用多个线程,线程数量可以在节点执行器初始化时设置。
进程,线程与节点
一个进程可以维护多个节点执行器,一个节点执行器可以维护多个节点。按照线程数量区分,可以分为单线程节点执行器和多线程节点执行器。单线程节点执行器会将所有已添加到维护队列的节点限制在一个线程内处理所有回调,而多线程节点执行器会按照设备的性能,动态分配线程为队列内的节点处理回调。从最表象上看,在单线程节点执行器中,所有节点的进程ID相同,线程ID也相同;而在多线程节点执行器中,所有节点的进程ID相同,线程ID会不同。
下面代码在节点定时器的回调函数中打印进程ID和线程ID可以验证这一点。
//thread_sample.h
#pragma once
#include <string>#include "rclcpp/rclcpp.hpp"class ThreadSample: public rclcpp::Node
{public:explicit ThreadSample(const std::string& node_name);~ThreadSample(){};private:rclcpp::TimerBase::SharedPtr print_timer_;
};
//thread_sample.cpp
#include "sample3/thread_sample.h"#include <chrono>
#include <string>
#include <thread>
#include <unistd.h>
#include "sys/types.h"
#include "rclcpp/rclcpp.hpp"ThreadSample::ThreadSample(const std::string& node_name): rclcpp::Node(node_name)
{auto printtimer_callback =[&]()->void {pid_t pid = getpid();std::cout<< this->get_name() << ": pid is " << pid << ", thread id is " << std::this_thread::get_id() << std::endl;};print_timer_ = this->create_wall_timer(std::chrono::milliseconds(500), printtimer_callback);
}
#include "sample3/thread_sample.h"
#include <memory>
#include <vector>#include <string>
#include "rclcpp/rclcpp.hpp"int main(int argc, char ** argv)
{rclcpp::init(argc, argv);uint32_t node_count(0);bool is_multi(false);std::vector<std::shared_ptr<ThreadSample>> node_vector;rclcpp::executors::SingleThreadedExecutor executor_s;rclcpp::executors::MultiThreadedExecutor executor_m;if(argc >= 3){int input_count = atoi(argv[1]);node_count = input_count > 0 ? input_count : 0;node_vector.reserve(node_count);std::string multi_flag = static_cast<std::string>(argv[2]);if(multi_flag == std::string("m")){is_multi = true;}else if (multi_flag == std::string("s")){is_multi = false;}else{std::cout<<"Example ros2 run sample3 sample3 <node_count> s/m" << std::endl;return 0;}}else{std::cout<<"Example ros2 run sample3 sample3 <node_count> s/m" << std::endl;return 0;}for (int i = node_count; i> 0; i--){node_vector.push_back(std::make_shared<ThreadSample>("cpp_node_a_" + std::to_string(i)));if(is_multi){executor_m.add_node(node_vector.back()->get_node_base_interface());}else{executor_s.add_node(node_vector.back()->get_node_base_interface());}}if(is_multi){executor_m.spin();}else{executor_s.spin();}rclcpp::shutdown();return 0;
}
单线程节点执行器同时运行5个节点
crabe@crabe-virtual-machine:~/Desktop/ROS2_Sample/sample3$ ros2 run sample3 sample3 5 s
cpp_node_a_5: pid is 7044, thread id is 140166163743616
cpp_node_a_4: pid is 7044, thread id is 140166163743616
cpp_node_a_3: pid is 7044, thread id is 140166163743616
cpp_node_a_2: pid is 7044, thread id is 140166163743616
cpp_node_a_1: pid is 7044, thread id is 140166163743616
cpp_node_a_5: pid is 7044, thread id is 140166163743616
cpp_node_a_4: pid is 7044, thread id is 140166163743616
cpp_node_a_3: pid is 7044, thread id is 140166163743616
cpp_node_a_2: pid is 7044, thread id is 140166163743616
cpp_node_a_1: pid is 7044, thread id is 140166163743616
多线程节点执行器同时运行3个节点
cpp_node_a_2: pid is 7198, thread id is 140274060408576
cpp_node_a_1: pid is 7198, thread id is 140274060408576
cpp_node_a_2: pid is 7198, thread id is 140274060408576
cpp_node_a_1: pid is 7198, thread id is 140274159653760
cpp_node_a_2: pid is 7198, thread id is 140274159653760
相关文章:
ROS2学习(四)进程,线程与节点的关系
节点与节点执行器 节点,英文是node,在ROS2中,节点是一个抽象的实体,它可以代表某种或某类特定功能的抽象集合体,它可以存在于进程中,也可以存在于线程中。所有ROS2的基础功能最基础的载体是节点,所有的通信…...
【物联网】DMA传输原理与实现详解(超详细)
DMA(Direct Memory Access,直接内存访问)是一种计算机数据传输方式,允许外围设备直接访问系统内存,而无需CPU的干预。 文章目录 Part 1: DMA的工作原理配置阶段:数据传输阶段: Part 2: DMA数据…...
Java类集框架(二)
目录 1.Map(常用子类 HashMap,LinkedHashMap,HashTable,TreeMap) 2.Map的输出(Map.Entry,iterator,foreach) 3.数据结构 - 栈(Stack) 4.数据结构 - 队列(Q…...
爬虫008_流程控制语句_if_if else_elif_for---python工作笔记026
然后我们再来看一下这里的,判断,可以看到 再看一个判断,这里的布尔类型 第二行有4个空格,python的格式 注意这里,输入的age是字符串,需要转一下才行 int可以写到int(intput("阿斯顿法师打发地方")) 这样也可以...
【随笔】五周年创作纪念日
今天收到了 CSDN 的创作五周年提示,正好前几天(7.31)我也成功申请了 CSDN 博客专家,趁这个机会分享一下这几年写博客的感受吧 机缘 关注我比较久的读者应该知道我是从学传统工科半路出家搞计算机的,这里的经历还是比…...
7_分类算法—逻辑回归
文章目录 逻辑回归:1 Logistic回归(二分类问题)1.1 sigmoid函数1.2 Logistic回归及似然函数(求解)1.3 θ参数求解1.4 Logistic回归损失函数1.5 LogisticRegression总结 2 Softmax回归(多分类问题࿰…...
【计算机网络】应用层协议 -- DNS协议
文章目录 1. DNS背景2. 域名简介3. 域名解析过程4. 使用dig查看DNS过程 1. DNS背景 DNS(Domain Name System,域名系统)协议,是一个用来将域名转化为IP地址的应用层协议。 TCP/IP当中通过IP地址和端口号的方式,来确定…...
ES6 - 数组新增的一些常用方法
文章目录 1,Array.from()2,Array.of()3,find(),findIndex(),findLast()和findLastIndex()4,Array.fill()5,keys(),values() 和 entries()6,Array.includes()7,…...
【BEV感知】3-BEV开源数据集
3-BEV开源数据集 1 KITTI1.1 KITTI数据怎么采集?1.2 KITTI数据规模有多大?1.3 KITTI标注了哪些目标?1.4 转换矩阵1.5 标签文件 2 nuScenes2.1 nuScenes Vs KITTI2.2 标注文件 1 KITTI KITTI 1.1 KITTI数据怎么采集? 通过车载相机、激光雷达等传感器采集。 只提供了相机正…...
Kafka-Broker工作流程
kafka集群在启动时,会将每个broker节点注册到zookeeper中,每个broker节点都有一个controller,哪个controller先在zookeeper中注册,哪个controller就负责监听brokers节点变化,当有分区的leader挂掉时,contro…...
第八篇-Tesla P40+ChatGLM2+LoRA
部署环境 系统:CentOS-7CPU: 14C28T显卡:Tesla P40 24G驱动: 515CUDA: 11.7cuDNN: 8.9.2.26目的 验证P40部署可行性,只做验证学习lora方式微调创建环境 conda create --name glm-tuning python3.10 conda activate glm-tuning克隆项目 git clone http…...
调用feign返回错误的数据
bug描述: 在一个请求方法中会调用到feign去获取其他的数据。 List<Demo> list aaaFeignApi.getData(personSelectGetParam);在调用的时候,打断点到feign的地方,数据是存在的,并且有15条。但是返回到上面代码的时候数据就…...
【Spring】(二)从零开始的 Spring 项目搭建与使用
文章目录 前言一、Spring 项目的创建1.1 创建 Maven 项目1.2 添加 Spring 框架支持1.3 添加启动类 二、储存 Bean 对象2.1 创建 Bean2.1 将 Bean 注册到 Spring 容器 三、获取并使用 Bean 对象3.1 获取Spring 上下文3.2 ApplicationContext 和 BeanFactory 的区别3.3 获取指定的…...
redis五种数据类型介绍
、string(字符串) 它师最基本的类型,可以理解为Memcached一模一样的类型,一个key对应一个value。 注意:一个键最大能存储 512MB。 特性:可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512…...
【JavaEE】Spring Boot - 项目的创建和使用
【JavaEE】Spring Boot 开发要点总结(1) 文章目录 【JavaEE】Spring Boot 开发要点总结(1)1. Spring Boot 的优点2. Spring Boot 项目创建2.1 下载安装插件2.2 创建项目过程2.3 加载项目2.4 启动项目2.5 删除一些没用的文件 3. Sp…...
Git reset、revert用法
reset reset是删除之前的提交记录,所有的提交点都会被清除,我们看下执行前后的git log区别 D:\workspace\android>git log commit 87c1277a57544c53c603b04110e3dde100da8f57 (HEAD -> develop_main) Author: test <test.com> Date: Wed…...
Redis-1
Redis 理论部分 redis 速度快的原因 1、纯内存操作 2、单线程操作,避免了频繁的上下文切换和资源争用问题,多线程需要占用更多的 CPU 资源 3、采用了非阻塞 I/O 多路复用机制 4、提供了非常高效的数据结构,例如双向链表、压缩页表和跳跃…...
【Linux】Linux服务器连接百度网盘:实现上传下载
【Linux】Linux服务器连接百度网盘:实现上传下载 文章目录 【Linux】Linux服务器连接百度网盘:实现上传下载1. 前言2. 具体过程2.1 pip 安装所需包2.2 认证(第一次连接需要认证)2.3 下载所需文件或者目录2.4 其他指令使用2.5 注意…...
ADC模拟看门狗
如果被ADC转换的模拟电压低于低阀值或高于高阀值,AWD模拟看门狗状态位被设置。阀值位 于ADC_HTR和ADC_LTR寄存器的最低12个有效位中。通过设置ADC_CR1寄存器的AWDIE位 以允许产生相应中断。通过以下函数可以进行配置 void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx…...
google谷歌gmail邮箱账号注册手机号无法进行验证怎么办?此电话号码无法用于进行验证 或 此电话号码验证次数太多
谷歌gmail邮箱账号注册手机号无法进行验证怎么办? 使用手机号码注册谷歌gmail邮箱账号时会遇到:此电话号码无法用于进行验证 或 此电话号码验证次数太多。造成注册google谷歌gmail邮箱账号受阻,无法正常完成注册。 谷歌Gmail邮箱账号正确的注册方法与教…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...
【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统
Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...
WEB3全栈开发——面试专业技能点P7前端与链上集成
一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
【阅读笔记】MemOS: 大语言模型内存增强生成操作系统
核心速览 研究背景 研究问题:这篇文章要解决的问题是当前大型语言模型(LLMs)在处理内存方面的局限性。LLMs虽然在语言感知和生成方面表现出色,但缺乏统一的、结构化的内存架构。现有的方法如检索增强生成(RA…...
STL 2迭代器
文章目录 1.迭代器2.输入迭代器3.输出迭代器1.插入迭代器 4.前向迭代器5.双向迭代器6.随机访问迭代器7.不同容器返回的迭代器类型1.输入 / 输出迭代器2.前向迭代器3.双向迭代器4.随机访问迭代器5.特殊迭代器适配器6.为什么 unordered_set 只提供前向迭代器? 1.迭代器…...
【Go语言基础【6】】字符串格式化说明
文章目录 零、格式化常用场景一、Go 字符串格式化核心概念二、常用格式化占位符1. 整数类型2. 浮点数类型3. 字符串与布尔类型4. 指针与通用类型 三、宽度与精度控制1. 宽度控制2. 精度控制(浮点数/字符串) 零、格式化常用场景 数值转字符串:…...
