数据通信三个层次
1.Component 是封装好的数据处理流程
2.Node Reader/Writer 或 Service/Client
3.Transport 创建 Transmitter 或 Receiver
Component
Component 是封装好的数据处理流程
Dag 文件是模块拓扑关系的配置文件
Launch 文件提供了一种启动模块的简单方法
Node
通过Node创建Reader或Writer进行通信
Node 是整个数据拓扑网络中的基本单元。通过在节点中定义 Reader/Writer 或 Service/Client,
cyber/node/node.h
#include "cyber/node/node_channel_impl.h"
#include "cyber/node/node_service_impl.h"
01.class Node {
public:
template <typename M0, typename M1, typename M2, typename M3>
friend class Component;
friend class TimerComponent;
auto CreateService(const std::string& service_name,
const typename Service<Request, Response>::ServiceCallback&
service_callback)
-> std::shared_ptr<Service<Request, Response>>;
auto CreateClient(const std::string& service_name)
-> std::shared_ptr<Client<Request, Response>>;
CreateService DeleteReader Node::CreateReader
02.cyber/node/node_channel_impl.h
auto CreateWriter(const std::string& channel_name)
-> std::shared_ptr<Writer<MessageT>>;
auto CreateReader(const ReaderConfig& config, const CallbackFunc<MessageT>& reader_func)
-> std::shared_ptr<Reader<MessageT>>;
cyber/node/node_service_impl.h
03.cyber/node/writer.h
class Writer : public WriterBase
cyber/node/reader.h
class Reader : public ReaderBase
04.cyber/node/reader_base.h
class ReaderBase {
class ReceiverManager
cyber/node/writer_base.h
class WriterBase {
cyber/service/client.h
class Client : public ClientBase {
cyber/service/client_base.h
class ClientBase {
cyber/service/service.h
class Service : public ServiceBase {
cyber/service/service_base.h
class ServiceBase {
数据通信-数据传输层
transport 工厂模式 -通过 Transport 创建 Transmitter 或 Receiver 进行通信
cyber/transport/transport.h
auto Transport::CreateTransmitter
transmitter = std::make_shared<IntraTransmitter<M>>(modified_attr);
transmitter = std::make_shared<ShmTransmitter<M>>(modified_attr);
std::make_shared<RtpsTransmitter<M>>(modified_attr, participant());
std::make_shared<HybridTransmitter<M>>(modified_attr, participant());
auto Transport::CreateReceiver
std::make_shared<IntraReceiver<M>>(modified_attr, msg_listener);
std::make_shared<ShmReceiver<M>>(modified_attr, msg_listener);
std::make_shared<RtpsReceiver<M>>(modified_attr, msg_listener);
std::make_shared<HybridReceiver<M>>( modified_attr, msg_listener, participant());
IntraDispatcher::Instance(); ShmDispatcher::Instance(); RtpsDispatcher::Instance();
Transmitter和Receiver各有三个派生类,对应Cyber的三种数据传输方式 ,分别是进程内(Intra) 进程间(Shm))以及网络(RTPS)
cyber/transport/transmitter/transmitter.h
class IntraTransmitter : public Transmitter<M>
class ShmTransmitter : public Transmitter<M>
class RtpsTransmitter : public Transmitter<M>
class HybridTransmitter : public Transmitter<M>
cyber/transport/receiver/receiver.h class Receiver : public Endpoint
class IntraReceiver : public Receiver<M>
class ShmReceiver : public Receiver<M>
class RtpsReceiver : public Receiver<M>
class HybridReceiver : public Receiver<M>
cyber/transport/dispatcher/dispatcher.h
class IntraDispatcher : public Dispatcher
class ShmDispatcher : public Dispatcher
class RtpsDispatcher : public Dispatcher
class SubscriberListener : public eprosima::fastdds::dds::SubscriberListener
01.进程内 Intra 传输使用的是函数直接调用(回调)的方式
1.上层 Writer --->
IntraTransmitter ---> IntraDispatcher--->(回调)IntraReceiver ---> (回调)上层Reader。
02.进程间 Shm (本机)传输是通过共享内存辅助实现。链用链条是:
1、上层Writer---> Segment(共享内存)和Notifier(发送通知)
2、ShmDispatcher(有独立线程)---> (主动读取)Segment---> (回调)上层Reader。
03.主机间-Rtps(路网络)传输是通过RTPS(DDS)实现。链用链条是:
1、上层Writer--->
RtpsTransmitter 打包成protobuf---> fastrtps发送到网络。
2、fastrtps接收到网络报文---> (回调)RtpsDispatcher ---> (回调)RtpsReceiver---> (回调)上层Reader。
通知--工程模式--NotifierFactory
notifier_ = NotifierFactory::CreateNotifier();
notifier_type = g_conf.transport_conf().shm_conf().notifier_type();
NotifierFactory::CreateConditionNotifier()
NotifierFactory::CreateMulticastNotifier()
数据分发器 DataDispather 和数据访问器 DataVistor DataNotifier 用于唤醒协程任务
DataDispatcher 进行消息分发, DataVisitor 允许用户自定义通道和缓冲区大小
ChannelBuffer 实现缓冲区管理,
数据通信-service_discovery
cyber/service_discovery/topology_manager.h
Participant 类封装fastrtps接口成员 participant_ 是 Participant实例
Manager 基于 Participant 管理 topology消息的收发
NodeManager ChannelManager ServiceManager 并有共同的基类Manager
TopologyManager 初始化三个子管理器
- NodeManager 用于管理网络拓扑中的节点。
- ChannelManager用于管理channel,即网络拓扑中的边。
- ServiceManager用于管理Service和Client。
cyber/service_discovery/topology_manager.cc
node_manager_ = std::make_shared<NodeManager>();
channel_manager_ = std::make_shared<ChannelManager>();
service_manager_ = std::make_shared<ServiceManager>();
class NodeManager : public Manager {
class ChannelManager : public Manager { friend class TopologyManager;
class ServiceManager : public Manager {
参数-parameter
cyber/parameter/parameter.h
Parameter::Name()
Parameter::Type() TypeName() FromProtoParam ToProtoParam
Parameter::value()
通道 发送或接收消息。
服务 是节点之间通信的另一种方式。 服务实现双向通信,例如节点通过发送请求获得响应。
参数 都是apollo::cyber::Parameter 对象 它负责管理系统配置和参数。
cyber/parameter/parameter_client.h
#include "cyber/node/node.h"
class ParameterClient{ GetParameter SetParameter ListParameters
cyber/parameter/parameter_server.h
#include "cyber/service/service.h"
class ParameterServer { GetParameter SetParameter ListParameters
cyber/parameter/parameter_service_names.h
"get_parameter"; "set_parameter"; list_parameters";
Cyber RT
目前对整理的框架有了粗浅的了解,更进一步处理对源码进行处理
基本概念--数据通信-任务调度-变化通知
Cyber RT模块加载流程
Cyber如何注册和启动一个个模块。
在Cyber RT中,一个module可以由多个component组成
cyber/mainboard/mainboard.cc
cyber/mainboard/module_controller.h
Cyber RT的模块加载机制主要分为两部分:
编译期进行模块注册
运行期加载模块并初始化
可执行程序mainboard通过dag文件加载对应的component,
入口:cyber/mainboard/mainboard.cc中的main函数。类ModuleController负责加载动态库并初始化各component的实例。
common.dag序列化为DagConfig对象,然后调用ModuleController::LoadModule(const DagConfig& dag_config)
cyber/proto/dag_conf.proto
动态库的加载入口为 ClassLoaderManager::LoadLibrary(const std::string& library_path)
继承关系
CommonComponentSample --> 模板类Component --> ComponentBase
cyber/class_loader/class_loader.h
class ClassLoader {
ClassLoader 这个类,它是类加载器用来加载动态库和实例化Product,
它虽然没有继承 ClassFactory,但它里面大部分函数都最终调用了ClassFactory的方法
cyber/class_loader/class_loader_manager.h
class ClassLoaderManager {
cyber/class_loader/utility/class_factory.h
Factory :AbstractClassFactoryBase,它的子类AbstractClassFactory可以视为Factory cyber/class_loader/utility/class_factory.h)
FactoryA/B:ClassFactory 代码位于(cyber/class_loader/utility/class_factory.h)
cyber/component/component.h cyber/component/component_base.h cyber/component/timer_component.h
Product :ComponentBase ,Cyber基于这个基类又分了两个子类Component, TimerComponent,这两个子类可以视为Product
ProductA/B:modules里不同功能下的各种组件比如CameraComponent,它们都继承自Component或TimerComponent。
cyber/class_loader/utility/class_loader_utility.h
工厂类注册
cyber/class_loader/utility/class_loader_utility.cc BaseToClassFactoryMapMap
注册工厂类实际上要做的就是向我们刚刚介绍的那个全局static双层嵌套map里插入工厂类ClassFactory,而且工厂类对应的产品是Component/TimerComponent
参考
https://apollo.baidu.com/docs/apollo/latest/rtps__transmitter_8h.html
https://blog.csdn.net/deyili/article/details/120327777
自动驾驶开发入门(三)---浅谈Apollo Cyber RT中的Transport
Apollo 应用与源码分析:CyberRT-服务通信与参数服务器
百度Apollo系统学习-Cyber RT 注册启动模块 https://blog.csdn.net/qq_25762163/article/details/103669467