首页 > 编程语言 >CyberRT_不同的启动方式的源码解读

CyberRT_不同的启动方式的源码解读

时间:2024-05-20 19:56:37浏览次数:29  
标签:launch CyberRT DataVisitor cyber 解读 源码 Reader apollo 加载

源码解读

 component
 node
 reader/writer  service/client parameter
 schedule
 transport
 
 apollo/cyber/cyber.cc
    CreateNode(){return  std::unique_ptr<Node>(new Node(node_name,name_space))}
 apollo/cyber/init.cc
    Init()
	OnShutdown()
 apollo/cyber/state.h
      WaitForShutdown() IsShutdown() OK  AsyncShutdown()

CyberRT启动node的方式

main()函数中写通信逻辑并编译为单独的可执行文件的方法
主要流程
    apollo::cyber::Init(argv[0]);//   启动cyber模块 初始化cyber框架
    apollo::cyber::CreateNode ;// 创建一个节点  每个Node负责创建Reader, Writer, Service, Client来帮该组件获取信息或者传达信息。
	
  Writer:	
      auto talker_node = apollo::cyber::CreateNode("talker");
     talker_node->CreateWriter<Image>( //创建 Writer 或者 reader
	 while (apollo::cyber::OK()) {
	   auto msg = std::make_shared<Car>();
	   talker->Write(msg);
	 }
    
 Reader :
      auto listener_node = apollo::cyber::CreateNode("listener");
	  auto listener = listener_node->CreateReader<Car>( "car_speed", message_callback);
	  apollo::cyber::WaitForShutdown();
	 
2.createNode() apollo/cyber/cyber.cc
  01.NodeChannelImpl 和 NodeServiceImpl	
        Node是Server/Client/Writer/Reader的容器:
        Server/Client/Writer/Reader是有向图的顶点。
         Channel 是Writer到Reader的边缘
         Service 是Server到Client的边缘 
   02.apollo/cyber/node/node.h  
     CreateWriter writer是cyber中发送消息的基本工具。每个writer都可以通过channel发送一些特定类型的消息  MessageT  channel_name
	     std::shared_ptr<Write<Message_T>>
     CreateReader
	        std::shared_ptr<Reader<Message_T>>
     CreateService  CreateClient
	 
	03. apollo/cyber/node/write.h  apollo/cyber/node/writer_base.h
        class Write:public WriteBase{}{
		   using TransmitterPtr = std::shared_ptr<transport::Transmitter<MessageT>>;
		   service_discovery::ChannelManagePtr
		   service_discovery::Managet::ChannelConnection
		   virtual bool Write(consst std::shared_ptr<Message_T>& msg_ptr)}	
		   virtual bool Write(consst proto::RoleAttributes& role_attr)}: WriteBase(role_attr(), transmitter_(nullptr),channel_manage_(nulptr))

       apollo/cyber/node/reader.h  apollo/cyber/node/reader_base.h
	       class Reader:public ReaserBase{}	 
		   // blocker主要用于缓存消息,Blocker继承自BlockerBase  Block 类是共享内存(Shared Memory, SHM)中的一个块,用于存储消息数据
		   using BlockerPtr = std::unique_ptr<blocker::Blocker<MessageT>>
		   using ReceiverPtr = std::shared_ptr<transport::Receiver<MessageT>>;
		      
	04: 其中Transport是工厂类,负责创建 Transmitter  Receiver 以及Dispatcher(上层不直接使用)
	  通讯的差异通过Receiver Transmitter Dispatcher 三个类的多态形式来实现
	   Transmitter 和 Receiver 是 Writer 和 Reader 的通信实现,service_discovery 是二者的服务发现实现
	    Dispathcer也具有四种具体实现,具有单例属性,作为 Receiver 底层 Listener 运行的实体(调用回调和触发Listen)
		  Transmitter: 发送逻辑、
		  Receiver   : 被动接收触发逻辑、数据缓存、数据同步
	 transport
	  apollo/cyber/transport/transmitter/transmitter.h
          transport::Transmitter	
             intra_transmitter.h shm_transmitter.h  rtps_transmitter.h  hybrid_transmitter.h
             			
	  apollo/cyber/transport/receiver/receiver.h
           transport::Receiver
               intra_receiver.h shm_receiver.h  rtps_receiver.h  hybrid_receiver.h	

       apollo/cyber/transport/dispatcher/dispatcher.h				   
 
    每个Writer有Transmitter,每个Reader有Receiver。它们是负责消息发送与收取的类。Transmitter与Receiver的基类为Endpoint,
	 
	  RTPS:RTPS部分基于eProsimar的Fast RTPS
	                 RtpsReceiver 中的 dispatcher_成员指向单例 RtpsDispatcher
	  SHM:Segment类表示一块对应一个channel的共享内存,由SegmentFactory::CreateSegment函数创建
	            ShmDispatcher::OnMessage()函数进行消息派发
	  INTRA :用于进程内通信。由于读者和写者是在同一进程内,因此可以直接调用。在IntraTransmitter::Transmit()
               intraDispatcher::OnMessage()	   
			   
    ● 进程内传输使用的是函数直接调用(回调)的方式。调用链条是:
        上层Writer---> IntraTransmitter--->IntraDispatcher--->(回调)IntraReceiver---> (回调)上层Reader。
    ● 进程间(本机)传输是通过共享内存辅助实现。链用链条是:
         1、上层Writer---> Segment(共享内存)和Notifier(发送通知) 
         2、ShmDispatcher(有独立线程)---> (主动读取)Segment---> (回调)上层Reader。
    
    ● 进程间(路网络)传输是通过RTPS(DDS)实现。链用链条是:
         1、上层Writer---> RtpsTransmitter打包成protobuf---> fastrtps发送到网络。
         2、fastrtps接收到网络报文---> (回调)RtpsDispatcher---> (回调)RtpsReceiver---> (回调)上层Reader。				   				   
3.数据通信基础Protobuf
   block时用来存储channel中的数据的,它也是其他类用来读写数据的对象 
    Receiver  apollo-master/cyber/transport/receiver/receiver.h	   
  
4.编译后执行
  talker 会一直给 listener 发送实时速度信息	

加载启动Component的方式

mainboard
  Cyber RT中,所有的 Comopnent 都会被编译成独立的.so文件,
   Cyber RT 会根据开发者提供的配置文件,按需加载对应的 Component。
   所以,开发者需要为.so文件编写好配置文.dag文件和.launch文件,以供 Cyber RT正确的加载执行Component。
Cyber RT提供两种
  加载启动Component的方式,
   使用 mainboard  启动component对应的dag文件。mainboard执行启动dag文件。
   使用 cyber_launch工具启动component对应的launch文件,cyber_launch工具可以启动dag文件和二进制文件      

mainboard

  cyber/mainboard/mainboard.cc
 cyber main函数中先解析dag参数,然后根据解析的参数,通过类加载器动态的加载对应的模块,然后调用Initialize方法初始化模块
    apollo::cyber::mainboard::ModuleArgument
	apollo::cyber::mainboard::ModuleController

  1.解析参数是在"ModuleArgument"类中实现的,主要是解析加载DAG文件时候带的参数。arseArgument(argc,argv);// 2. 初始化cyber
  2.apollo::cyber::Init(argv[0]);  启动cyber模块
  3.ModuleController "实现cyber模块的加载,在"ModuleController::Init()"中调用"LoadAll()"来加载所有模块
        cyber主函数在"ModuleController::Init()"进行模块的加载
		   模块首先通过classloader加载到内存,然后创建对象,并且调用模块的初始化方法。
		   component中每个模块都设计为可以动态加载和卸载,可以实时在线的开启和关闭模块,
		   实现的方式是通过classloader来进行动态的加载动态库
		ModuleController::LoadModule
          // 1. 加载动态库
           class_loader_manager_.LoadLibrary(load_path);
		   // 3. 创建对象
         std::shared_ptr<ComponentBase> base =class_loader_manager_.CreateClassObj<ComponentBase>(class_name);
	   // 4. 调用对象的Initialize方法
	    base->Initialize(component.config())
	   
	        其中 component  Apollo一共有2种类型的组件:消息触发型和定时触发型
	         bool Component<M0, M1, NullType, NullType>::Initialize
		       // 1. 创建Node  
			   // 2. 调用用户自定义初始化 Init()                             ####调用用户自定义的初始化函数Init()(子类的Init方法)
			   // 3. 创建reader1 CreateReader
			   // 5. 创建回调,回调执行Proc()  ptr-> Process(msg0, msg1); ### 实际上是执行用户定义算法Proc()函数
			   //   scheduler::Instance() 创建数据访问 器DataVisitor ; RoutineFactory 创建协程,协程绑定回调func(执行proc)
			   //  scheduler CreateTask
			   
         5. 消息写端 和消息读端
		 Reader初始化时创建的另一个关键对象为 Receiver
		   DataVisitor类,协程和Receiver类等。其中DataVisitor主要用于消息数据的访问
		 DataFusion由 DataDispather、CacheBuffer、DataVisitor三部分组成
		    DataVisitor本质功能就是数据存储器 DataDispatcher主要是将buffer放进对应channel的buffers中
		 cyber/data/data_vistor.h  cyber/data/data_dispatcher.h  cyber/data/cache_buffer.h 
		 Component 的DataVisitor和DataDispatcher
		  一个数据处理过程对应一个DataVisitor,
		  通过在DataVisitor中注册Notify(唤醒对应的协程,协程执行绑定的回调函数),
		  并且注册对应的Buffer到DataDispather
		DataFusion类是一个虚类,定义了数据融合的接口"Fusion()",Apollo里只提供了一种数据融合的方式  
		  DataVisitor只访问一个消息,则不会对消息进行融合,
		            如果DataVisitor访问2个以上的数据,那么需要进行融合,并且注册融合回调。
		                之后CacheBuffer中会调用融合回调进行数据处理,而不会把数据放入CacheBuffer中
		  
		在component中自动帮我们创建了一个DataVisitor,订阅component中的消息,融合获取最新的消息之后,执行Proc回调。  
		 数据的访问是通过"DataVisitor"来实现,数据的分发通过"DataDispatcher"来实现
		  
		  DataVisitor构造完事后,
		    调用了croutine::CreateRoutineFactory创建了一个croutine::RoutineFactory,主要是创建协程工厂,并构建出要封装为协程的函数
			
        主要两种方式:一种是通过Component的Proc()接口,它被调用时参数就是最新的消息。另一种是通过Reader的Observe()函数直接拿

cyber_launch

 1.示例: cyber_launch start /apollo/modules/drivers/camera/launch/camera.launch
    cyber_launch就是 cyber\tools\cyber_launch\cyber_launch py脚本文件
		    如果是可执行文件,就用py的多进程直接调起来, ProcessWrapper
			如果是lib文件,要通过g_binary_name="mainboard"这个程序来动态加载lib库文件

  01.cyber_launch 文件结构	
       module用于区分模块 name 
	   dag_conf
	   process_name
          dag文件有一个或者多个module_config,而每个module_config中对应一个或者多个components	
  02.cyber_launch.py分析			  

说明

  RoutineFactory  协程通过工厂模式方法创建,里面包含一个回调函数和一个dv(数据访问器)DataVisitor。
  Cyber RT工厂模式的对应 ComponentBse AbstractClassFactoryBase class_factory

Apollo 启动不同模块

2种启动方式。都是通过mainboard来启动程序
   1. cyber_launch
   2. dreamview
       Apollo Dreamview 为启动一切模块的中心	
       前端通过websocket发送消息到后端,后端通过调用命令行启动模	
        start_command"和"stop_command"来启动和关闭		   

参考

  深入探索:CyberRT架构的创新学习之旅 https://zhuanlan.zhihu.com/p/661888327
  apollo介绍之Cyber框架(十)  https://zhuanlan.zhihu.com/p/91322837
  苯苯的嗷呜-CyberRt 源码解读(十二)  https://zhuanlan.zhihu.com/p/653159026
  Apollo的启动过程1——启动命令解析 https://gutsgwh1997.github.io/2020/02/04/Apollo%E7%9A%84%E5%90%AF%E5%8A%A8/
  Apollo的启动过程2——功能模块加载
  https://gutsgwh1997.github.io/2020/02/05/Apollo%E7%9A%84%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B2%E2%80%94%E2%80%94%E5%8A%9F%E8%83%BD%E6%A8%A1%E5%9D%97%E5%8A%A0%E8%BD%BD/
  Apollo的启动过程3——Cyber RT如何加载组件 https://gutsgwh1997.github.io/2020/02/05/
  Cyber通信机制实践之Listener-Talker通信(C++)
  【apollo】cyber底层通信--订阅方如何获取数据 https://blog.csdn.net/SWX230162/article/details/125343967
  自动驾驶开发入门(三)---浅谈Apollo Cyber RT中的Transport

标签:launch,CyberRT,DataVisitor,cyber,解读,源码,Reader,apollo,加载
From: https://www.cnblogs.com/ytwang/p/18202700

相关文章

  • Kubernetes:kubelet 源码分析之探针
    0.前言kubernetes提供三种探针,配置探针(Liveness),就绪探针(Readiness)和启动(Startup)探针判断容器健康状态。其中,存活探针确定什么时候重启容器,就绪探针确定容器何时准备好接受流量请求,启动探针判断应用容器何时启动。本文通过分析kubelet源码了解kubernetes的探针是怎么工作......
  • Kubernetes:kubelet 源码分析之 pod 创建流程
    0.前言kubelet是运行在Kubernetes节点上的“节点代理”,用来管理节点。kubelet主要负责所在节点上的资源对象的管理,例如Pod资源对象的创建,删除,监控,驱逐及生命周期管理等。1.kubelet源码分析1.1kubelet模块kubelet包括的模块如下图:从图中可以看出,kubelet的模......
  • 排队叫号系统项目源码开发搭建
    一款基于PHP开发的多项目多场景排队叫号系统,支持大屏幕投屏,语音播报叫号,可用于餐厅排队取餐、美甲店排队取号、排队领取、排队就诊、排队办理业务等诸多场景,助你轻松应对各种排队取号叫号场景。采用GatewayWorker开发完成的 程序开发:PHP+MySQL程序演示:http://jh1.yetukeji.t......
  • cmake以源码的方式引入第三方项目
    最前#本文将介绍一种以源码的方式引入第三方库的方法准备#主项目,需要引用第三方库的某些函数第三方库,以源码的形式提供给主项目使用注意:本文的背景:已经将第三方源码下载好。一个例子#我这里准备一个简单的项目,调用第三方库 fmt;其中fmt是以源码的形式引入项目cmake......
  • MySQL全文索引源码剖析之Insert语句执行过程
    本文分享自华为云社区《MySQL全文索引源码剖析之Insert语句执行过程》,作者:GaussDB数据库。1.背景介绍全文索引是信息检索领域的一种常用的技术手段,用于全文搜索问题,即根据单词,搜索包含该单词的文档,比如在浏览器中输入一个关键词,搜索引擎需要找到所有相关的文档,并且按相关性......
  • lodash已死?radash库方法介绍及源码解析 —— 函数柯里化 + Number篇
    写在前面tips:点赞+收藏=学会!主页有更多其他篇章的方法,欢迎访问查看。本篇我们继续介绍radash中函数柯里化和Number相关的方法使用和源码解析。函数柯里化chain:创建一个函数链并依次执行使用说明功能描述:用于创建一个函数链,该链依次执行一系列函数,每个函数的输出......
  • xView2 比赛冠军代码解读
    CSDN搬家失败,手动导出markdown后再导入博客园代码地址:https://github.com/vdurnov/xview2_1st_place_solution模型训练中用到了混合精度训练工具Nvidiaapex和图像增强工具imgaug目录1、readme权重文件数据清洗数据处理模型细节2、代码结构3、定位模型3.1数据集......
  • 关于学习VUE源码的感受! 学习VUE源码最好的方式 !!!
    仓库地址仓库whoelse666mini-vue崔学社mini-vue文章导航Vue3源码实战课|构建你自己的Vue3|掌握源码最有效的学习方法就是手写一遍!Vue3源码实战课阮一峰推荐最佳学习vue3源码的利器-mini-vue学习源码经历过程vue从出来到现在也有好些年了,相信几乎所所有从事......
  • 全网首一份!你最需要的PPTP MS-CHAP V2 挑战响应编程模拟计算教程!代码基于RFC2759,附全
    本文基于网络密码课上的实验本来想水一水就过去,代码就网上找找,不行就GPT写,但是!一份都找不到,找到的代码都是跑不了的,总会是就是乱七八糟。所以准备认真的写一份。代码编译成功的前提是要预先装好openssl库!本随笔主要有三个内容:编写程序,模拟计算NTResponse、AuthenticatorRespo......
  • 64-SpringBoot源码分析
    Starter是什么?我们如何使用这些Starter?为什么包扫描只会扫描核心启动类所在的包及其子包?在SpringBoot启动过程中,是如何完成自动配置的?内嵌Tomcat是如何创建并启动的?引入了web场景对应的Starter,SpringMVC是如何完成自动装配的?1.源码环境构建https://gith......