Apollo部署与简易架构梳理

news2024/11/18 7:29:28

文章目录

    • apollo 安装
    • apollo的基本架构
    • 组件机制
      • component
        • 编译与加载
    • 节点通讯
      • 数据的传输
      • 消息读写的实现
        • 消息的写端
        • 消息读端
    • 常用术语
        • Component
        • Channel
        • Task
        • Node
        • Reader/Writer
        • Service/Client
        • Parameter
        • 服务发现
        • CRoutine
        • Scheduler
        • Message
        • Dag文件
        • Launch文件
        • Record文件
        • Mainboard
    • Monitor工具使用

原文

apollo 安装

sudo apt-get update
sudo apt-add-repository multiverse
sudo apt-get update
# sudo apt-get install nividia-driver-455 # 看版本

启用cuda


distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get -y update
sudo apt-get install -y nvidia-docker2

clone源代码

# 使用 SSH 的方式  
git clone git@github.com:ApolloAuto/apollo.git

启动容器

./docker/scripts/dev_start.sh

进入容器

./docker/scripts/dev_into.sh

构建

./apollo.sh build

启动

./scripts/bootstrap.sh start

http://localhost:8888 可以显示DreamView界面

回放demo
在docs/02_Quick Start/demo_guide

python3 record_helper.py demo_3.5.record
cyber_recorder play -f demo_3.5.record -l

cyber_recorder在apollo/中

apollo的基本架构

apollo开发文档

请添加图片描述

请添加图片描述

常用数据见本篇末尾

组件机制

Cyber RT 组件机制
Cyber RT采用了基于Component模块和有向无环图(DAG)的动态加载配置的工程框架。即将相关算法模块通过Component创建,并通过DAG拓扑定义对各Component依赖关系进行动态加载和配置,从而实现对算法进行统一调度,对资源进行统一分配。

component

Component构成去中心化的网络,系统由多个component组成,构成一张计算图,如

请添加图片描述

component分为两类:
apollo::cyber::Component最多可以支持4路消息融合。多个channel读取数据时,第一个channel为主channel。当主 Channel 有消息到达,Cyber RT会调用 Component 的 apollo::cyber::Component::Proc 进行一次数据处理。
也就是说,每次有主消息到达,其就会执行一次Proc。

apollo::cyber::TimerComponent不会被消息出发,而是由系统定时调用。

创建一个Component的方式如下:

//1、包含头文件
#include "cyber/component/component.h"
#include "test/proto/examples.pb.h"
 
// 2、定义一个类,继承以Driver和Chatter为参数的Component模版类
class ComponentSample : public Component<Driver, Chatter> {
public:
  //3、重写Init() 函数和Proc() 函数
  bool Init() override;
  bool Proc(const std::shared_ptr<Driver>& msg0,
  const std::shared_ptr<Chatter>& msg1) override;
};
//4、 在cyber中注册ComopnentSample
CYBER_REGISTER_COMPONENT(ComponentSample)

也就是说我们需要继承一个模版类,并在cyber RT中注册这个类。

编译与加载

在Cyber RT中,Component会变编译为独立的.so文件。Cyber RT可以使用cyber_launch工具启动componenet对应的launch文件(可以是二进制文件或dag)或使用mainboard启动component对应的dag文件。
![[Apollo部署与简易架构梳理/Pasted image 20240723163142.png]]

节点通讯

参考资料
Publish-Subscribe模式
Reader和Writer

![[apollo/Apollo部署与简易架构梳理/Pasted image 20240715111104.png]]
RTPS(Real-Time Publish-Subscribe) 是一种用于实时分布式系统的通信协议,主要用于实现设备间的实时数据交换。

Fast RTPS是DDS标准的一个非常流行的开源实现。

DDS(Data Distribution Service)标准提供了一个平台无关的数据模型,主要用于实时分布式系统。不同的实现可以相互通信。

  1. 数据中心化:DDS采用数据为中心的架构,数据被看作是核心,而不是进程之间的直接通信。
  2. 发布/订阅模型:DDS使用发布/订阅(Pub/Sub)模式,允许数据生产者(发布者)和数据消费者(订阅者)之间进行解耦,从而提高系统的灵活性和可扩展性。

节点间通过channel进行读写形成数据通路,这些数据通路形成一个动态的数据流图。

cyber/service_discovery/TopologyManager对网络拓扑进行监控管理。只需要一个管理因此单例即可

- NodeManager用于管理网络拓扑中的节点。
  - ChannelManager用于管理channel,即网络拓扑中的边。
  - ServiceManager用于管理ServiceClient

TopologyManager::TopologyManager()

: init_(false),

node_manager_(nullptr),

channel_manager_(nullptr),

service_manager_(nullptr),

participant_(nullptr),

participant_listener_(nullptr) {

Init();

}

TopologyManager::CreateParticipant()函数可以创建网络拓扑的参与者——transport::Participant对象,其包含host name与process id的名称。
ParticipantListener用于监听网络的变化。网络拓扑发生变化时,Fast RTPS传上来ParticipantDiscoveryInfo,在TopologyManager::Convert()函数中对该信息转换成Cyber RT中的数据结构ChangeMsg。然后调用回调函数TopologyManager::OnParticipantChange(),它会调用其它几个子管理器的OnTopoModuleLeave()函数。然后子管理器中便可以将相应维护的信息进行更新(如NodeManager中将相应的节点删除)。

初始化的时候会创建实例

数据的传输

- INTRA:如果是同进程的,因为在同一地址空间,直接传指针就完了。
  - SHM(Shared memory):如果是同一机器上,但跨进程的,为了高效可以使用共享内存。
  - RTPS:如果是跨设备的,那就老老实实通过网络传吧。
  (目前我们的车机应该不太设计跨设备咯?)
![[apollo/Apollo部署与简易架构梳理/Pasted image 20240715120551.png]]
每个Writer有Transmitter,每个Reader有Receiver。它们是负责消息发送与收取的类。Transmitter与Receiver的基类为Endpoint,代表一个通信的端点,它主要的信息是身份标识与属性。其类型为RoleAttributes(定义在role_attributes.proto)的成员attr_包含了host name,process id和一个根据uuid产生的hash值作为id。通过它们就可以判断节点之间的相对位置关系了。

Reader和Writer会调用Transport的方法CreateTransmitter()和CreateReceiver()用于创建发送端的transmitter和接收端的receiver。创建时有四种模式可选,分别是INTRA,SHM和RTPS,和HYBRID。最后一种是前三种的混合模式,也是默认的模式。

消息读写的实现

消息的写端

在Component组件中通过CreaterWriter()函数创建Writer对象,然后向指定的channel发送消息。

writer_ = node_->CreateWriter<Image>(camera_config_->channel_name());// 创建writer对象

// 在创建该对象时,会在Init()初始化中通过CreateTransmitter()创建Transmitter对象,并调用JointTheTopology()将其加入到ChannelManager维护的拓扑信息中。
//
//此外,还会对该channel的读者相应的调用Enable函数和Disable函数。
//
...
auto pb_image = std::make_shared<Image>();                                 
pb_image->mutable_header()->set_frame_id(camera_config_->frame_id());      
pb_image->set_width(raw_image_->width);                                    
pb_image->set_height(raw_image_->height);                                  
pb_image->mutable_data()->reserve(raw_image_->image_size);  
// 以上完成发送数据的准备
// 这些消息如pb_image是定义好的protobuf类消息。
...
writer_->Write(pb_image);
// 其会调用Transmitter::Transmit()将message发出
消息读端

对于一个component而言,其可以从多个channel收取消息。
上层模块要取用这些消息,主要两种方式:一种是通过ComponentProc()接口,它被调用时参数就是最新的消息。另一种是通过ReaderObserve()函数直接拿
例:

template <typename M0, typename M1>  // 声明一个模板类Component,其中M0和M1是数据类型参数
bool Component<M0, M1, NullType, NullType>::Initialize(  // 初始化函数的定义
  ...
  ReaderConfig reader_cfg;  // 创建一个ReaderConfig对象用于配置读者
  reader_cfg.channel_name = config.readers(1).channel();  // 设置通道名称为配置中的第二个读者通道
  reader_cfg.qos_profile.CopyFrom(config.readers(1).qos_profile());  // 从配置中复制第二个读者的QoS配置
  reader_cfg.pending_queue_size = config.readers(1).pending_queue_size();  // 设置待处理队列大小为配置中的第二个读者大小
  
  auto reader1 = node_->template CreateReader<M1>(reader_cfg);  // 使用配置创建一个类型为M1的读者,并命名为reader1
  
  reader_cfg.channel_name = config.readers(0).channel();  // 更新通道名称为配置中的第一个读者通道
  reader_cfg.qos_profile.CopyFrom(config.readers(0).qos_profile());  // 从配置中复制第一个读者的QoS配置
  reader_cfg.pending_queue_size = config.readers(0).pending_queue_size();  // 设置待处理队列大小为配置中的第一个读者大小
  
  auto reader0 = node_->template CreateReader<M0>(reader_cfg);  // 使用配置创建一个类型为M0的读者,并命名为reader0
  ...
  readers_.push_back(std::move(reader0));  // 将reader0移动到readers_向量中
  readers_.push_back(std::move(reader1));  // 将reader1移动到readers_向量中
  ...  
  std::vector<data::VisitorConfig> config_list;  // 创建一个data::VisitorConfig类型的向量用于存储访问者配置
  for (auto& reader : readers_) {  // 遍历所有读者
    config_list.emplace_back(reader->ChannelId(), reader->PendingQueueSize());  // 将每个读者的配置添加到配置列表中
  }  
  auto dv = std::make_shared<data::DataVisitor<M0, M1>>(config_list);  // 使用配置列表创建一个DataVisitor智能指针,并特化为M0和M1类型
  croutine::RoutineFactory factory =  // 创建一个RoutineFactory对象
      croutine::CreateRoutineFactory<M0, M1>(func, dv);  // 使用工厂函数创建RoutineFactory,并传入func函数和数据访问者
  return sched->CreateTask(factory, node_->Name());  // 创建一个任务并返回创建结果,任务使用RoutineFactory和节点名称
}

这个案例中有两个channel并分别创建了reader对象。
每个channel都有对应的协程进行数据处理,还有一个协程实现消息的组合,所以有n个channel的component至少会有n+1个协程

常用术语

Component

在自动驾驶系统中,模块(如感知、定位、控制系统…)在 Cyber RT 下以 Component 的形式存在。不同 Component 之间通过 Channel 进行通信。Component 概念不仅解耦了模块,还为将模块拆分为多个子模块提供了灵活性。

Channel

Channel 用于管理 Cyber RT 中的数据通信。用户可以发布/订阅同一个 Channel,实现 p2p 通信。

Task

Task 是 Cyber RT 中异步计算任务的抽象描述。

Node

Node 是 Cyber RT 的基本组成部分;每个模块都包含一个 Node 并通过 Node 进行通信。通过在节点中定义 Reader/Writer 或 Service/Client,模块可以具有不同类型的通信形式。

Reader/Writer

Reader/Writer 通常在 Node 内创建,作为 Cyber RT 中的主要消息传输接口。

Service/Client

除了 Reader/Writer 之外,Cyber RT 还提供了用于模块通信的 Service/Client 模式。它支持节点之间的双向通信。当对服务发出请求时,客户端节点将收到响应。

Parameter

参数服务在 Cyber RT 中提供了全局参数访问接口。它是基于 Service/Client 模式构建的。

服务发现

作为一个去中心化的框架,Cyber RT 没有用于服务注册的主/中心节点。所有节点都被平等对待,可以通过“服务发现”找到其他服务节点。使用UDP用来服务发现。

CRoutine

参考协程(Coroutine)的概念,Cyber RT 实现了 Coroutine 来优化线程使用和系统资源分配。

Scheduler

为了更好地支持自动驾驶场景,Cyber RT 提供了多种资源调度算法供开发者选择。

Message

Message 是 Cyber RT 中用于模块之间数据传输的数据单元。

Dag文件

Dag 文件是模块拓扑关系的配置文件。您可以在 dag 文件中定义使用的 Component 和上游/下游通道。

Launch文件

Launch 文件提供了一种启动模块的简单方法。通过在launch文件中定义一个或多个 dag 文件,可以同时启动多个模块。

Record文件

Record 文件用于记录从 Cyber RT 中的 Channel 发送/接收的消息。回放 Record 文件可以帮助重现Cyber RT之前操作的行为。

Mainboard

Cyber RT 的主入口,可以通过mainboard -d xxx.dag来启动一个模块进程。

Monitor工具使用

ESC | q key ---- 退出
Backspace ---- 后退
h | H ---- 显示帮助页
PageDown | Ctrl+d ---- 上一页
PageUp | Ctrl+u ---- 下一页
Up, down or w, s keys ---- 上下移动当前的高亮行
Right arrow or d key ---- 进入高亮行, 显示高亮行数据的详细信息
Left arrow or a key ---- 从当前界面返回上一层界面
Enter key ---- 与d键相同
f | F ---- 显示数据帧频率
t | T ---- 显示channel消息类型
Space ---- 关闭|开启 channel (仅在channel有数据到达时有效; channel关闭后会变成黄色)
i | I ---- 显示channel的Reader和Writer信息
b | B ---- 显示channel消息内容
n | N ---- 显示消息中RepeatedField的下一条数据
m | M ---- 显示消息中RepeatedField的上一条数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1949237.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机会性加密技术:网络安全的新趋势

在当今数字化时代&#xff0c;网络安全已成为各行各业不可忽视的重要议题。随着网络攻击手段的不断演进&#xff0c;传统的加密方式已难以满足复杂多变的安全需求。机会性加密技术&#xff08;Opportunistic Encryption&#xff0c;简称OE&#xff09;&#xff0c;作为一种新兴…

快速入门Jupyter notebook

快速入门 Jupyter notebook 一、前言&#xff08;一&#xff09;优点&#xff08;二&#xff09;特点&#xff08;三&#xff09;调用运行&#xff08;四&#xff09;新建 二、认识界面快捷键&#xff08;一&#xff09;三种模式&#xff08;1&#xff09;蓝色模式&#xff1a;…

qt做的分页控件

介绍 qt做的分页控件 如何使用 创建 Pagination必须基于一个QWidget创建&#xff0c;否则会引发错误。 Pagination* pa new Pagination(QWidget*);设置总页数 Pagination需要设置一个总的页数&#xff0c;来初始化页码。 pa->SetTotalItem(count);设置可选的每页数量…

Spring中使用到的设计模式及其源码分析

前言 众所周知&#xff0c;Spring框架是一个强大而灵活的开发框架。这不&#xff0c;上次的面试刚问到这些&#xff0c;没防住&#xff01;&#xff01;&#xff01;因此下来总结一下。这篇文章主要介绍Spring中使用到的设计模式&#xff0c;自己做个面试复盘&#xff0c;同时…

51单片机嵌入式开发:19、STC89C52R控制LCD1602码表+数码管+后台数显(串口)

STC89C52R控制LCD1602码表数码管后台数显&#xff08;串口&#xff09; 1 概述1.1 项目概述1.2 项目组成部分1.3 功能描述 2 开发环境2.1 支持设备2.2 硬件电路 3 软件代码工程4 演示4.1 Proteus仿真4.2 实物演示 5 总结 1 概述 1.1 项目概述 本项目旨在利用STC89C52R单片机实…

C语言程序设计结构(未完待续...)

文章目录 **C**语言设计的核心&#xff08;灵魂&#xff09;**C**语言程序设计的设计结构顺序结构选择结构循环结构 **C**语言的语句 C语言设计的核心&#xff08;灵魂&#xff09; 程序 数据结构 算法 算法&#xff1a;对于问题解决的方法思路或者步骤 算法的特征&#x…

mac|安装PostgreSQL

1、官网下载&#xff1a;EDB: Open-Source, Enterprise Postgres Database Management 选择需要的版本&#xff1a; 双击得到的.dmg文件 双击&#xff0c;弹窗选择打开&#xff0c;一路next&#xff0c;然后输入你要设置的密码&#xff0c;默认账号名字为&#xff1a;postgres…

vite构建vue3项目hmr生效问题踩坑记录

vite构建vue3项目hmr生效问题踩坑记录 hmr的好处 以下是以表格形式呈现的前端开发中HMR&#xff08;热模块替换&#xff09;带来的好处&#xff1a; 好处描述提升开发效率允许开发者在不刷新整个页面的情况下实时更新修改的代码&#xff0c;减少等待时间保持应用状态在模块替…

一起学Java(1)-新建一个Gradle管理的Java项目

一时兴起&#xff0c;也为了便于跟大家同步学习进展和分享样例代码&#xff0c;遂决定创建一个全新的Java项目&#xff0c;并通过Github与大家分享。本文就是记录该项目的创建过程以及其中的一些知识要点&#xff08;如Gradle等&#xff09;。为了紧跟技术潮流和提高操作效率&a…

怎么给PDF文件加密码?关于PDF文件加密的四种方法推荐

怎么给PDF文件加密码&#xff1f;给PDF文件加上密码是保护文件安全的一种重要方法&#xff0c;特别是当需要在不受授权的访问下保护敏感信息时。这个过程不仅仅是简单地设置密码&#xff0c;而是涉及到对文档内容和访问控制的深思熟虑。加密PDF文件可以有效防止未经授权的用户查…

electron TodoList网页应用打包成linux deb、AppImage应用

这里用的是windows的wsl的ubuntu环境 electron应用打包linux应用需要linux下打包&#xff0c;这里用windows的wsl的ubuntu环境进行操作 1&#xff09;linux ubuntu安装nodejs、electron 安装nodejs&#xff1a; sudo apt update sudo apt upgrade ##快捷安装 curl -fsSL http…

数据缺失补全方法综述

数据缺失补全方法综述 摘要1. 引言2. 数据缺失的类型3. 数据缺失补全方法3.1 简单插补方法3.1.1 均值插补3.1.2 中位数插补3.1.3 众数插补3.1.4 前向填充和后向填充3.1.5 线性插值3.1.6 多重插补 3.2 基于模型的插补方法3.2.1 线性回归插补3.2.2 加权回归插补3.2.3 主成分分析&…

如何改桥接模式

桥接模式主要是解决 路由功能的 因为NAT多层 主要是网络连接数太多时 然后路由器要好 不然光猫 比差路由要强的 光猫 请注意&#xff0c;对光猫的任何设置进行修改前&#xff0c;请一定要备份光猫的配置文件&#xff0c;并在每次修改前都截图保存原始设置信息&#xff01;不要…

Jacoco 单元测试配置

前言 编写单元测试是开发健壮程序的有效途径&#xff0c;单元测试写的好不好可以从多个指标考量&#xff0c;其中一个就是单元测试的覆盖率。单元测试覆盖率可以看到我们的单元测试覆盖了多少代码行、类、分支等。查看单元测试覆盖率可以使用一些工具帮助我们计算&#xff0c;…

pytest结合allure-pytest插件生成测试报告

目录 一、安装allure-pytest插件 二、下载allure 三、生成allure报告 四、效果展示 一、安装allure-pytest插件 二、下载allure 下载之后解压&#xff0c;解压之后还要配置环境变量&#xff08;把allure目录下bin目录配置到系统变量的path路径&#xff09;&#xff0c;下…

AcWing1维差分

输入数据a数组 a[i]a0a1a2 … \dots …anb[i]b0b1b2 … \dots …bn b1a1 b2a2-a1 … \dots … bnan-an-1 以上各式累加相消得到 b1b2 … \dots …bnan 也就是说任一an可以由b数组累加求和得到并且任一个bi加上元素c等于在an上面c。 对于区间[L,R], aLb1b2 … \dots …bL aL1…

【短视频矩阵系统源码如何构建?】

在数字化时代&#xff0c;短视频已成为信息传播的重要载体。针对这一趋势&#xff0c;短视频矩阵系统的构建应运而生&#xff0c;集混剪、发布、数据分析及线索跟进于一体&#xff0c;旨在为内容创作者和品牌提供全方位的服务支持。 系统通过混剪功能&#xff0c;能够将长视频或…

接口测试 ★ ✔【接口测试理论、http协议、接口测试文档解析、Postman使用、接口测试用例设计、Request库、UnitTest框架、】

接口测试 接口测试-第01天&#xff08;接口测试理论、HTTP协议、接口测试流程、接口文档解析&#xff09;学习⽬标能够分析HTTP协议的请求和响应数据完成ihrm系统指定接⼝的API⽂档解析接⼝测试理论概念作用 ★实现⽅式 ★HTTP协议 ★HTTP协议简介URL格式 ★练习 HTTP请求 ★整…

A Comprehensive Study of Knowledge Editing for Large Language Models

大型语言模型&#xff08;LLMs&#xff09;在理解和生成与人类交流密切相关的文本方面表现出了非凡的能力。然而&#xff0c;一个主要的限制在于训练期间的大量计算需求&#xff0c;这是由于它们的广泛参数化而产生的。世界的动态性质进一步加剧了这一挑战&#xff0c;需要经常…

Java面试八股之Spring-boot-starter-parent的作用是什么

Spring-boot-starter-parent的作用是什么 spring-boot-starter-parent 是Spring Boot项目中的一个特殊POM&#xff08;Project Object Model&#xff09;&#xff0c;它主要的作用是提供一系列默认的配置和依赖管理&#xff0c;以便简化项目的构建过程。以下是spring-boot-sta…