先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024b (备注运维)
正文
去中心化网络拓扑
前文我们提到,ROS系统中包含了一个通信的主节点,所有其他节点都要借助于这个节点来进行通信。所以,很显然的,假如这个节点发生了通信故障,就会影响整个系统的通信。并且,整个结构还缺乏异常恢复机制。
所以Apollo项目对于ROS的第二个改造就是去除这种中心化的网络结构。Apollo使用RTPS(Real-Time Publish-Subscribe)服务发现协议实现完全的P2P网络拓扑。整个通信过程包含下面四个步骤:
关于RTPS详见这里:
Real-Time Publish-Subscribe
数据兼容性扩展
Apollo项目对于ROS最后一个较大的改进就是对于数据格式的调整。
在ROS系统中,使用msg描述文件定义模块间的消息接口。但不幸的是,接口升级之后不同的版本的模块难以兼容。
因此,Apollo选择了Google的Protocol Buffers格式数据来解决这个问题。
Protocol Buffers,是Google公司开发的一种数据描述语言,类似于XML能够将结构化数据序列化,可用于数据存储、通信协议等方面。它不依赖于语言和平台并且可扩展性极强。现阶段官方支持C++、JAVA、Python三种编程语言,但可以找到大量的几乎涵盖所有语言的第三方拓展包。
注:如果你查看了Apollo项目的源码,可以看到很多名称为“proto”的文件夹,这些文件夹中包含的就是Protocol Buffers(简称protobuf)格式的数据结构。
硬件架构
Apollo 2.5上必须的硬件如下表所示:
外设包括下面这些:
硬件架构如下图所示:
软件架构
Apollo平台的软件架构如下图所示:
在Apollo上,运行的核心软件模块包括:
- Perception:感知模块识别自动车辆周围的世界。在Perception模块中有两个重要的子模块:障碍物检测和交通灯检测。
- Prediction:Prediction模块预测未来的感知障碍物的运动轨迹。
- Routing:Routing模块告诉自动车辆如何通过一系列车道或道路到达目的地。
- Planning:Planning模块计划自主车辆的时空轨迹。
- Control:Control模块通过生成诸如节流阀,制动器和转向的控制命令来执行计划的时空轨迹。
- CanBus:CanBus将控制命令传递给车辆硬件的接口。它还将机架信息传递给软件系统。
- HD-Map:提供有关道路特定结构化的信息。
- Localization:该模块利用各种信息来源,例如GPS,LiDAR和IMU来估计自动车辆所在的位置。
这些模块的交互结构如下图所示:
每个模块都作为独立的基于CarOS的ROS节点运行。每个模块节点都会发布和订阅某些主题。订阅的主题用作数据输入,而发布的主题用作数据输出。
关于Apollo平台的系统架构可以阅读这篇文档:HOW TO UNDERSTAND ARCHITECTURE AND WORKFLOW。
从这篇文档中我们看到:
- 自动驾驶车辆由规划引擎通过CAN总线(Controller Area Network bus)来进行控制。
- 为了计算效率,Location模块,Perception模块,Planning模块作为独立的输入源和输出源通过P2P一起工作。
- 通过阅读源码
${MODULE_NAME}/conf
目录下的配置文件,我们可以获得有关模块订阅和发布的主题的基本信息。 - 每个模块通过触发
Init
接口和注册回调开始。 - 所有模块都会在下面这个点上注册:AdapterManager::Init。该函数部分代码片段如下:
void AdapterManager::Init(const AdapterManagerConfig &configs) {
if (Initialized()) {
return;
}
instance()->initialized_ = true;
if (configs.is_ros()) {
instance()->node_handle_.reset(new ros::NodeHandle());
}
for (const auto &config : configs.config()) {
switch (config.type()) {
case AdapterConfig::POINT_CLOUD:
EnablePointCloud(FLAGS_pointcloud_topic, config);
break;
case AdapterConfig::GPS:
EnableGps(FLAGS_gps_topic, config);
break;
case AdapterConfig::IMU:
EnableImu(FLAGS_imu_topic, config);
break;
case AdapterConfig::RAW_IMU:
EnableRawImu(FLAGS_raw_imu_topic, config);
break;
case AdapterConfig::CHASSIS:
EnableChassis(FLAGS_chassis_topic, config);
break;
case AdapterConfig::LOCALIZATION:
EnableLocalization(FLAGS_localization_topic, config);
break;
case AdapterConfig::PERCEPTION_OBSTACLES:
EnablePerceptionObstacles(FLAGS_perception_obstacle_topic, config);
break;
case AdapterConfig::TRAFFIC_LIGHT_DETECTION:
EnableTrafficLightDetection(FLAGS_traffic_light_detection_topic,
config);
...
下面是对系统中主要的核心模块的一些解析。
核心模块
apollo/modules/中包含了系统中的各个模块的源码。
阅读这些源码会发现,这些核心模块的类都继承自一个公共基类ApolloApp,相关结构如下图所示:
ApolloApp类的结构如下图所示:
该类中的主要函数说明如下:
函数名 | 说明 |
---|
在apollo_app.h
这个头文件中,还包含了一个宏以方便每个模块声明main函数,相关代码如下:
#define APOLLO_MAIN(APP) \
int main(int argc, char **argv) { \
google::InitGoogleLogging(argv[0]); \
google::ParseCommandLineFlags(&argc, &argv, true); \
signal(SIGINT, apollo::common::apollo_app_sigint_handler); \
APP apollo_app_; \
ros::init(argc, argv, apollo_app_.Name()); \
apollo_app_.Spin(); \
return 0; \
}
每个模块的根目录都包含了一个README.md
文件,是对这个模块的说明。我们可以以此为入口来了解模块的实现。
Perception(感知)
模块介绍
自动驾驶车辆通过前置摄像头和雷达与最近的车辆(closest in-path vehicle,简称CIPV)保持距离。子模块还预测障碍物运动和位置信息(例如,航向和速度)。Apollo 2.5支持高速公路上的高速自动驾驶,无需任何地图。深度网络算法已经学会处理图像数据。随着收集更多数据,深度网络的性能将随着时间的推移而提高。
模块输入:
- 雷达数据
- 图像数据
- 雷达传感器校准的外部参数(来自YAML文件)
- 前置相机校准的外部和内部参数(来自YAML文件)
- 车辆的速度和角速度
模块输出:
- 3D障碍物跟踪航向,速度和分类信息
- 带有拟合曲线参数的车道标记信息,空间信息以及语义信息
模块解析
Perception模块需要根据输入信息快速的解析出两类信息,即:道路和物体。其中的深入网络基于YOLO算法[1][2]。
Apollo 2.5不支持高曲率,没有车道标志的道路,包括当地道路和交叉路口。感知模块基于使用具有有限数据的深度网络的视觉检测。因此,在发布更好的网络之前,驾驶员在驾驶时应小心谨慎,并始终准备好通过将车轮转向正确的方向来解除自主驾驶。
-
推荐道路
- 两侧清晰的白色车道线
-
不推荐道路
- 高曲率的道路
- 没有车道线标记的道路
- 路口
- 对接点或虚线车道线
- 公共道路
而对于物体来说,又分为静态物体和动态物体。静态物体包括道路和交通灯等。动态物体包括机动车,自行车,行人,动物等。
为了保持车辆在车道上,需要一系列模块的配合,相关流程图如下所示:
Perception模块在Init
函数中会注册一系列类以完成模块启动后的正常工作,相关代码如下:
void Perception::RegistAllOnboardClass() {
/// regist sharedata
RegisterFactoryLidarObjectData();
RegisterFactoryRadarObjectData();
RegisterFactoryCameraObjectData();
RegisterFactoryCameraSharedData();
RegisterFactoryCIPVObjectData();
RegisterFactoryLaneSharedData();
RegisterFactoryFusionSharedData();
traffic_light::RegisterFactoryTLPreprocessingData();
/// regist subnode
RegisterFactoryLidarProcessSubnode();
RegisterFactoryRadarProcessSubnode();
RegisterFactoryCameraProcessSubnode();
RegisterFactoryCIPVSubnode();
RegisterFactoryLanePostProcessingSubnode();
RegisterFactoryAsyncFusionSubnode();
RegisterFactoryFusionSubnode();
RegisterFactoryMotionService();
lowcostvisualizer::RegisterFactoryVisualizationSubnode();
traffic_light::RegisterFactoryTLPreprocessorSubnode();
traffic_light::RegisterFactoryTLProcSubnode();
}
我们可以以这里为入口了解各个子模块的逻辑。
以RegisterFactoryLidarProcessSubnode
为例。
代码中其实并不存在RegisterFactoryLidarProcessSubnode
这个函数,该函数的定义其实是由宏完成的。相关代码如下:
Lidar(也称之为LIDAR,LiDAR,或LADAR)的全称是Light Detection And Ranging,即激光探测与测量。
// /modules/perception/onboard/subnode.h
#define REGISTER_SUBNODE(name) REGISTER_CLASS(Subnode, name)
// /modules/perception/lib/base/registerer.h
#define REGISTER_CLASS(clazz, name) \
class ObjectFactory##name : public apollo::perception::ObjectFactory { \
public: \
virtual ~ObjectFactory##name() {} \
virtual perception::Any NewInstance() { \
return perception::Any(new name()); \
} \
}; \
inline void RegisterFactory##name() { \
perception::FactoryMap &map = perception::GlobalFactoryMap()[#clazz]; \
if (map.find(#name) == map.end()) map[#name] = new ObjectFactory##name(); \
}
而在lidar_process_subnode.h
中使用了上面这个宏。
REGISTER_SUBNODE(LidarProcessSubnode);
于是就会生成一个名称为ObjectFactoryLidarProcessSubnode
的类,该类继承自apollo::perception::ObjectFactory
,并且其中包含了名称为RegisterFactoryLidarProcessSubnode
的函数。
Prediction(预测)
模块介绍
Prediction模块从Perception模块接受障碍物信息。该模块需要的信息包括位置,航向,速度,加速度,并产生具有障碍概率的预测轨迹。
模块输入:
- 来自Prediction模块的障碍物信息
- 来自Localizaton模块的位置信息
模块输出:
- 障碍物的预测轨迹
模块解析
Prediction的Init
函数中添加了三个回调用来从其他模块获取信息的更新:
AdapterManager::AddLocalizationCallback(&Prediction::OnLocalization, this);
AdapterManager::AddPlanningCallback(&Prediction::OnPlanning, this);
AdapterManager::AddPerceptionObstaclesCallback(&Prediction::RunOnce, this);
这里最重要的就是Prediction::RunOnce
这个函数。这个函数中包含了Prediction模块的主要逻辑,它会在接收到一个新的障碍物消息时触发。
Prediction模块中有三类重要的子模块。
第一类是Container,用来存储从订阅频道获取的数据。包括:
- 感到到的障碍物信息
- 车辆位置信息
- 车辆计划信息
第二类是Evaluator,用来针对指定的障碍物预测路线和速度。目前有三类Evaluator,包括:
Evaluator通过EvaluatorManager
类管理,Evaluator类结构如下图所示:
Prediction模块中第三类重要的子模块就是Predictor。它用来预测障碍物的轨迹。
不同的障碍物运动的轨迹会不一样,因此实现中包含了很多个类型的Predictor,它们的结构如下图所示。
类似的,会有一个PredictorManager
来管理Predictor。
Routing(路由)
模块介绍
Routing模块根据请求生成导航信息。
模块输入:
- 地图数据
- 请求,包括:开始和结束位置
模块输出:
- 路由导航信息
模块解析
Routing模块的内部结构如下图所示:
Routing模块的输入是地图数据和导航请求,因此其Init
函数就是围绕这个逻辑的:
apollo::common::Status Routing::Init() {
const auto routing_map_file = apollo::hdmap::RoutingMapFile();
AINFO << "Use routing topology graph path: " << routing_map_file;
navigator_ptr_.reset(new Navigator(routing_map_file));
CHECK(common::util::GetProtoFromFile(FLAGS_routing_conf_file, &routing_conf_))
<< "Unable to load routing conf file: " + FLAGS_routing_conf_file;
AINFO << "Conf file: " << FLAGS_routing_conf_file << " is loaded.";
hdmap_ = apollo::hdmap::HDMapUtil::BaseMapPtr();
CHECK(hdmap_) << "Failed to load map file:" << apollo::hdmap::BaseMapFile();
AdapterManager::Init(FLAGS_routing_adapter_config_filename);
AdapterManager::AddRoutingRequestCallback(&Routing::OnRoutingRequest, this);
return apollo::common::Status::OK();
}
这段代码的重点是下面三个地方:
apollo::hdmap::RoutingMapFile()
包含了HD地图数据。Navigator
负责导航,我们很容易想到这个类应当是该模块的核心。Routing::OnRoutingRequest
是接收导航请求的回调函数。
在Routing::OnRoutingRequest
中,最主要的就是通过Navigator::SearchRoute
来搜索导航路径。
void Routing::OnRoutingRequest(const RoutingRequest& routing_request) {
AINFO << "Get new routing request:" << routing_request.DebugString();
RoutingResponse routing_response;
apollo::common::monitor::MonitorLogBuffer buffer(&monitor_logger_);
const auto& fixed_request = FillLaneInfoIfMissing(routing_request);
if (!navigator_ptr_->SearchRoute(fixed_request, &routing_response)) {
AERROR << "Failed to search route with navigator.";
buffer.WARN("Routing failed! " + routing_response.status().msg());
return;
}
buffer.INFO("Routing success!");
AdapterManager::PublishRoutingResponse(routing_response);
return;
}
目前,Apollo 2.5版本中的导航基于A*算法。这是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法。该算法综合了Best-First Search和Dijkstra算法的优点:在进行启发式搜索提高算法效率的同时,可以保证找到一条最优路径(基于评估函数)。
在A*算法计算的过程中,会尝试多条路径。一旦遇到障碍物,便将该路径上的点标记为不需要继续探索(图中的实心点)。继续以剩下的空心点为基础探索。最终求得最优路径。
下图动态描述了A*算法查找目标路径的算法过程。
Planing(计划)
模块介绍
Planing模块根据定位信息,车辆状态(位置,速度,加速度,底盘),地图,路线,感知和预测,计算出安全和舒适的形式线路让控制器执行。
目前的系统实现中包含了四种计划器:
- RTKReplayPlanner(自Apollo 1.0以来):RTK重放计划器首先在初始化时加载记录的轨迹,并根据当前系统时间和车辆位置发送适当的轨迹段。
- EMPlanner(自Apollo1.5以来。EM是Expectation Maximization的缩写):EM计划器,会根据地图,路线和障碍物计算驾驶决策和线路。基于动态规划(Dynamic programming,简称DP)的方法首先用于确定原始路径和速度曲线,然后使用基于二次规划(Quadratic programming,简称QP)的方法来进一步优化路径和速度曲线以获得平滑的轨迹。
- LatticePlanner:网格计划器
- NaviPlanner:这是一个基于实时相对地图的计划器。它使用车辆的FLU(Front-Left-Up)坐标系来完成巡航,跟随,超车,接近,变道和停车任务。
模块输入:
- RTK重放计划器:
- Localization
- Localization
最全的Linux教程,Linux从入门到精通
======================
-
linux从入门到精通(第2版)
-
Linux系统移植
-
Linux驱动开发入门与实战
-
LINUX 系统移植 第2版
-
Linux开源网络全栈详解 从DPDK到OpenFlow
第一份《Linux从入门到精通》466页
====================
内容简介
====
本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。
本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。
需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。
本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。
需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)
[外链图片转存中…(img-ZAqIZi69-1713484353684)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!