Apollo:源码分析之cyber/node/node

引入

在cyber/examples/common_component_example/channel_test_writer.c实例中,除初始化cyber框架外外,第一步就是需要创建一个节点

在这里插入图片描述

 auto talker_node = apollo::cyber::CreateNode("channel_test_writer");

接下来,我们分析一下这个接口到底干了些啥

官方文档

在cyber/doxy-docs/source/CyberRT_API_for_Developers.md目录下:
在这里插入图片描述

可以知道:

  • 在cyber中,Node是最基本的单元,类似于"句柄"
  • 比如writer, reader等都是基于Node创建的

接口:

std::unique_ptr<Node> apollo::cyber::CreateNode(const std::string& node_name, const std::string& name_space = "");
  • 参数:

    • node_name: 节点的名称,全局唯一标识符
    • name_space:
      • 节点所在空间的名称
      • name_space默认为空。它是与node_name连接的空间的名称。格式为/namespace/node_name
      • 暂时无需关注这个变量
  • 返回值:

    • 成功的话返回一个指向节点的独占智能指针
    • 错误条件:未调用"cyber::Init()" 时,系统处于未初始化状态,无法创建节点,返回nullptr

CreateNode

接下来我们看下apollo::cyber::CreateNode这个接口到底是怎么实现的

这个接口是在cyber/cyber.cc中实现的,里面返回了Node的引用。可以看到最终调用了new Node(node_name, name_space)

在这里插入图片描述

  • 如果是实车环境而且未调用"cyber::Init()",那么返回nullptr
  • 否则,调用new Node(node_name, name_space)

Node

接下来我们仔细分析下Node是怎么实现的。

它定义在cyber/node/node.h目录下

成员变量

在Node中有一些关键的成员变量:

  • 有一系列相关的Reader
  • 以及相应的NodeChannelImpl 和 NodeServiceImpl。

在这里插入图片描述

每个Node保存了它的名字和名字空间

  • 一个存有channel_name对应的Reader的map
    • 一个node可以读取多个topic,可以有多个reader
  • 一个NodeChannelImpl和一个NodeServiceImpl
    • NodeChannelImpl用来创建reader和writer
    • NodeServiceImpl用来参加service和client

上面还可以看到Node的构造函数是private的,这说明不可以直接构造Node节点,必须通过apollo::cyber::CreateNode这个接口来定义Node。

在这里插入图片描述
通过注释我们可以看到:

  • Node是通信的最顶层的类,是cyber RT最基本的单元
  • 每个Component都有一个Node
  • 每个Node负责创建Reader, Writer, Service, Client来帮该组件获取信息或者传达信息。
  • 拓扑中不允许重复的节点名。

然后我们看看Node的构造函数怎么实现的:
在这里插入图片描述
关键在于初始化了两个成员变量:NodeChannelImpl,NodeServiceImpl

在这里插入图片描述

成员函数

单向通信

CreateWriter

writer是cyber中发送消息的基本工具。每个writer都可以通过channel发送一些特定类型的消息。

一共有两种方法来创建writer:
在这里插入图片描述
参数:

  • role_attr。里面包括了要往哪个通道写
  • channel_name:要写入的通道的名称
  • MessageT:要写入的消息类型

返回值:

  • 指向Writer对象的共享指针

具体实现:

在这里插入图片描述
可以看到,node使用了node_channel_impl_以便创建writer。

CreateReader

reader是cyber中用来接收信息的基本设施。

  • 创建reader时,必须将其绑定到回调函数。
  • 当新消息到达通道时,将调用回调。

读取器由Node类的“CreateReader”接口创建。接口如下:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

参数:

  • MessageT:要读取的消息类型
  • channel_name:要从中接收的频道的名称
  • reader_func:处理消息的回调函数

返回值:

  • 指向Reader对象的共享指针

使用示例

  • cyber/examples/talker.cc
  • cyber/examples/listener.cc

双向通信

CreateService

在这里插入图片描述

CreateClient

在这里插入图片描述

使用示例

  • cyber/examples/proto/examples.pb.h
  • cyber/examples/service.cc

小结

Node是通信的最顶层的类,每个Component都有一个Node

  • 每个Node负责创建Reader, Writer, Service, Client来帮该组件获取信息或者传达信息。
  • 每个Node保存了它的名字和名字空间,一个存有channel_name对应的Reader的map以及一个NodeChannelImpl和一个NodeServiceImpl(创建以上4种东西的创建器)。

Node是Server/Client/Writer/Reader的容器:

  • Server/Client/Writer/Reader是有向图的顶点。
  • Channel是Writer到Reader的边缘
  • Service是Server到Client的边缘

在这里插入图片描述

cyber/message

MessageHeader

  • apollo-master/cyber/message/message_header.h中定义了一个消息头
  • apollo-master/cyber/message/message_header_test.cc告知你消息头应该怎么用
数据类型 变量名 作用
char magic_num_[8];
char seq_[8];
char timestamp_ns_[8];
char src_id_[8];
char dst_id_[8];
char msg_type_[129];
char res_[19];
char content_size_[4];

message_traits.h

看不懂

参数服务(Parameter Service)

  • 参数服务用于节点间共享数据,并提供基本操作,如“set”、“get”和“list”。
  • 参数服务基于“Service”实现,包含 service 和 client.

参数对象

支持的数据类型

这些参数都是基于 apollo::cyber::Parameter 的,下面列出了所有支持的数据类型

Parameter type C++ data type protobuf data type
apollo::cyber::proto::ParamType::INT int64_t int64
apollo::cyber::proto::ParamType::DOUBLE double double
apollo::cyber::proto::ParamType::BOOL bool bool
apollo::cyber::proto::ParamType::STRING std::string string
apollo::cyber::proto::ParamType::PROTOBUF std::string string
apollo::cyber::proto::ParamType::NOT_SET - -

除了上述5种类型,Parameter还支持以protobuf对象作为传入参数的接口。执行后序列化处理对象并将其转换为STRING类型以进行传输。

如何构造

构造函数:
在这里插入图片描述

使用示例:

在这里插入图片描述

如何读取

接口:
在这里插入图片描述
示例:

文件名 作用
parameter_test.cc 告知你Parameter应该怎么使用
parameter.cc 从这里可以学到如何构建一个数据类型,以及std::enable_if怎么用

parameter_test.cc

parameter.cc

数据类型 变量名 作用
Param param_; Param是proto定义的

parameter_service_names.h

std::string FixParameterServiceName(const std::string& node_name,
                                                  const char* service_name)
  • 作用:返回 node_name/service_name

其他

主要文件

文件名 作用
node_test.cc
reader_test.cc
writer_test.cc
writer_reader_test.cc
node_channel_impl_test.cc
node.cc 节点是CyberRT中的基本单元,每个模块都包含一个节点,并且相互之间使用节点通信。一个模块可以定义不同的通信方式在一个节点中,如read/write or/and service/client。
reader_base.h Reader的基类
writer_base.h Writer的基类
reader.h Reader类
writer.h Writer类
node_channel_impl.h reader writer的具体实现
node_service_impl.h service client的具体实现

在这里插入图片描述

接下来,我们从下到上分析。

Block

apollo-master/cyber/transport/shm/block.h

  • 一段segment中会有多个block
  • block时用来存储channel中的数据的,它也是其他类用来读写数据的对象

Receiver

Receiver

apollo-master/cyber/transport/receiver/receiver.h

一个基类

在这里插入图片描述

成员变量

数据类型 变量名字 说明
MessageListener msg_listener_
  • using MessageListener = std::function<void( const MessagePtr&, const MessageInfo&, const RoleAttributes&)>;
  • 这是一个函数指针,当接受到消息时会回调这个函数
  • 其参数分别是消息,存放消息的容器,当前接收者的关联信息

重要成员

猜你喜欢

转载自blog.csdn.net/zhizhengguan/article/details/129385411
今日推荐