百度Apollo開發平臺調研
1?? Apollo軟件架構
Core software modules running on the Apollo powered autonomous vehicle include:
Perception?— The perception module identifies the world surrounding the autonomous vehicle. There are two important submodules inside perception: obstacle detection and traffic light detection.
Prediction?— The prediction module anticipates the future motion trajectories of the perceived obstacles.
Routing?— The routing module tells the autonomous vehicle how to reach its destination via a series of lanes or roads.
Planning?— The planning module plans the spatio-temporal trajectory for the autonomous vehicle to take.
Control?— The control module executes the planned spatio-temporal trajectory by generating control commands such as throttle, brake, and steering.
CanBus?— The CanBus is the interface that passes control commands to the vehicle hardware. It also passes chassis information to the software system.
HD-Map?— This module is similar to a library. Instead of publishing and subscribing messages, it frequently functions as query engine support to provide ad-hoc structured information regarding the roads.
Localization?— The localization module leverages various information sources such as GPS, LiDAR and IMU to estimate where the autonomous vehicle is located.
HMI?- Human Machine Interface or DreamView in Apollo is a module for viewing the status of the vehicle, testing other modules and controlling the functioning of the vehicle in real-time.
Monitor?- The surveillance system of all the modules in the vehicle including hardware.
Guardian?- A new safety module that performs the function of an Action Center and intervenes should Monitor detect a failure.
Storytelling?- A new module that isolates and manages complex scenarios, creating stories that would trigger multiple modules' actions. All other modules can subscribe to this particular module.
Apollo Software Architecture
Every module is running as a separate CarOS-based ROS node. Each module node publishes and subscribes certain topics. The subscribed topics serve as data input while the published topics serve as data output. The detailed interactions are described in the following sections.
2?? CyberRT背景
Apollo 3.5以前使用的系統為ROS,各節點之間的通信方式為進程間的通信。在實際的應用中,ROS在自動駕駛領域遇到很多挑戰:
調度的不確定性:ROS的算法模塊以獨立進程的形式存在,獨立進程的節點的運行順序無法確定,因此業務邏輯的調度順序無法保證。
運行效率:ROS是一個分布式的系統,存在通信的開銷。
ROS系統中還存在其他很多不確定的地方,比如內存的動態申請。ROS的資源分配時不確定的,
Cyber RT如何解決ROS所遇到的問題的?
ROS的主要挑戰之一是:ROS的算法模塊以獨立進程的形式存在,獨立進程的節點的運行順序無法確定,因此業務邏輯的調度順序無法保證。為了解決這個問題,Cyber RT將調度、任務從內核空間搬到了任務空間,使得調度可以和算法業務邏輯緊密結合。?從Cyber RT角度,OS的Native thread相當于物理CPU。在OS中,是內核中的調度器負責調度任務(進程、線程……)到物理CPU上運行。而在Cyber RT中,是Cyber RT中的調度器調度協程(Coroutine)在Native Thread上有序運行。
CyberRT驅動需求
Cyber RT為什么要使用協程?
Apollo將算法模塊搭載在協程上,關于協程和線程的區別可以簡單的描述為:協程是輕量化的線程,線程是進程下面的多個并行化任務,線程與線程之間的通信必須經過信道進行,然而協程能夠直接經過訪問全局變量來進行協程之間的通訊。Cyber RT通過croutine模塊實現了一個高性能的協程庫,為整個系統提供協程的調用。
3?? Cyber RT定位
是百度Apollo推出的代替ROS的消息中間件,它是一個開源、高性能的運行時框架,專為自動駕駛場景而設計。基于中心化的計算模型,針對自動駕駛的高并發、低延遲、高吞吐進行了大幅優化。 自動駕駛的各個模塊通過Cyber進行消息的訂閱和發布,同時Cyber還提供了任務調度,錄制bag包等功能。通過Cyber實現了自動駕駛的中間層。
4?? Cyber RT主要功能
Cyber是一個分布式收發消息,和調度的框架,同時對外提供一系列的工具和井口來輔助開發和定位問題。Cyber提供的功能主要包括一下方面:
消息隊列:主要作用是接收和發送各個節點的消息,涉及到消息的發布、訂閱以及消息的buffer緩存等。
實時調度:主要作用是調度處理上述消息的算法模塊,保證算法模塊能夠實時調度處理消息。
用戶接口:Cyber提供了靈活的用戶接口(?)
開發工具:提供了一系列的工具包括消息監控(Cyber_monitor),消息可視化(Cyber_visualizer),錄制/回放工具(Cyber_recorder), ros包錄制(rosbag_to_recorder)。
總結起來就是,cyber是一個分布式收發消息,和調度框架,同時對外提供一系列的工具和接口來輔助開發和定位問題。其中cyber對比ROS來說有很多優勢,唯一的劣勢是cyber相對ROS沒有豐富的算法庫支持
5?? Cyber RT架構
基礎庫:Cyber RT為了高性能和減少依賴,實現了自己的基礎庫。(Lock-free的對象池,隊列)
通信層:Publish/Subscribe機制,Service/Client機制,服務自發現,自適應的通信機制(共享內存、Socket、進程內存),Cyber RT支持跨進程、跨機通信,上層業務邏輯無需關心,通信層會根據算法模塊的部署,自動選擇相應通信機制
數據緩存/融合層:數據緩存與融合。多路傳感器之間數據需要融合,而且算法可能需要緩存一定的數據。比如典型的仿真應用,不同算法模塊之間需要有一個數據橋梁,數據層起到了這個模塊間通信的橋梁的作用
計算層:計算模型,任務以及任務調度
接口: Cyber RT為開發者提供了component類,開發者的算法業務模塊只需要繼承該類,實現其中的proc接口即可。該接口類似于ROS的callback,消息通過參數的方式傳遞。此外Cyber RT也提供了并行計算的相關接口以及用于開發調試、錄制回放的工具。
6?? CyberRT的特點
高性能:無鎖對象,協程(coroutine),自適應通信機制;
確定性:可配置的任務以及任務調度,通過協程將調度從內核空間轉移到用戶空間;
模塊化:在框架內實現組件以及節點,即可完成系統任務;
便利性:創建和使用任務
7?? CyberRT運行流程
算法模塊:算法模塊通過有向無環圖(DAG, Directed Acyclic Graph)配置任務間的邏輯關系。每個算法都可以進行優先級、運行時間、使用資源等方面的配置。
創建任務:Cyber RT可以結合DAG創建任務,任務的實現方式不是thread,而是協程(coroutine)。
調度器:調度器根據調度、任務配置將任務放入相關Processor的隊列中。
數據輸入: Senor輸入數據驅動系統的運轉。
8?? CyberRT數據流程
CyberRT的數據流程可以分為6個過程:
Node節點中的Writer往通道里面寫數據。
通道中的Transmitter發布消息,通道中的Receiver訂閱消息。
Receiver接收到消息之后,觸發回調,觸發DataDispather進行消息分發。
DataDispather接收到消息后,把消息放入CacheBuffer,并且觸發Notifier,通知對應的DataVisitor處理消息。
DataVisitor把數據從CacheBuffer中讀出,并且進行融合,然后通過notifier_喚醒對應的協程。
協程執行對應的注冊回調函數,進行數據處理,處理完成之后接著進入睡眠狀態。
9?? CyberRT調度策略
9.1?? 調度
將調度、任務從內核空間放到了用戶空間,在原生的thread上加了一層協程(Coroutine),Cyber RT主要調度的就是協程。
9.2?? 編排
調度編排策略,很好的結合了業務邏輯、數據共享和算力的平衡。并且任務不會在不同CPU上隨機的調度來調度去,具有非常好的Cache友好性。通過多隊列減少并發瓶頸,并且集成了一些獨占的策略
9.3?? 協程
協程,即線程更上一層的載體,Cyber RT調度器調度有狀態的協程在各個線程上運行。協程不僅切換快,而且調度有著高確定性,不像線程的調度完全依賴操作系統
10??? CyberRT與ROS概念對照
Cyber
ROS
注釋
Component
無
組件之間通過 Cyber channel 通信。
component加載時自動創建一個node,通過node來訂閱和發布對應的消息,每個component有且只能對應一個node
Channel
Topic
channel 用于管理數據通信,用戶可以通過 publish/subscribe 相同的 channel 來通信。
Node
Node
每一個模塊包含 Node 并通過 Node 來通信。一個模塊通過定義 read/write 和/或 service/client 使用不同的通信模式。
Reader
Writer
Publish
Subscribe
訂閱者模式。往 channel 讀寫消息的類。 通常作為 Node 主要的消息傳輸接口。
Service
Client
Service
Client
請求/響應模式,支持節點間雙向通信。
Message
Message
CyberRT 中用于模塊間通信的數據單元。其實現基于 protobuf
Parameter
Parameter
Parameter 服務提供全局參數訪問接口。該服務基于 service/client 模式。
Record file
Bag file
用于記錄從 channel 發送或接收的消息。 回放 record file 可以重現之前的操作行為。
Launch file
Launch file
提供一種啟動模塊的便利途徑。通過在 launch file 中定義一個或多個 dag 文件,可以同時啟動多個 modules。
Task
無
異步計算任務
CRoutine
無
協程,優化線程使用與系統資源分配
Scheduler
無
任務調度器,用戶空間。
Dag file
無
定義模塊拓撲結構的配置文件。
11??? CyberRT中的共享內存
共享內存實際上就是兩個不相關的進程訪問同一塊邏輯內存,相應的肯定需要額外的同步機制來保證讀寫正確。采用共享內存通信的一個顯而易見的好處是效率高,因為進程可以直接讀寫內存,而不需要任何數據的拷貝。對于像管道和消息隊列等通信方式,則需要在內核和用戶空間進行四次的數據拷貝,而共享內存則只拷貝兩次數據:一次從輸入文件到共享內存區,另一次從共享內存區到輸出文件。實際上,進程之間在共享內存時,并不總是讀寫少量數據后就解除映射,有新的通信時,再重新建立共享內存區域。而是保持共享區域,直到通信完畢為止,這樣,數據內容一直保存在共享內存中,并沒有寫回文件。共享內存中的內容往往是在解除映射時才寫回文件的。因此,采用共享內存的通信方式效率是非常高的。
11.1???? mmap機制-對應cyber中共享內存通信模式中的PosixSegment
內存映射機制mmap是POSIX標準的系統調用,mmap()系統調用使得進程之間通過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間后,進程可以向訪問普通內存一樣對文件進行訪問,不必再調用read(),write()等操作。一般說來,進程在映射空間的對共享內容的改變并不直接寫回到磁盤文件中,往往在調用munmap(該調用在進程地址空間中解除一個映射關系)后才執行該操作。可以通過調用msync實現磁盤上文件內容與共享內存區的內容一致。
mmap用于共享內存有兩種使用方式,分別是使用普通文件提供內存映射和使用特殊文件提供匿名內存映射(適用于有親緣關系的進程之間)。下面分別介紹用法。
11.2???? 普通文件映射的步驟(cyber中方法)
創建共享內存區域。調用shm_open函數(這是cyber中做法,實際上創建普通文件即可),創建內存文件(默認路徑為Linux下sysv共享內存的默認掛載點/dev/shm),參數是文件名和讀寫權限等,返回一個int文件描述符。
分配大小。調用ftruncate函數,給剛剛創建的文件設置大小即設置內存區域的大小。
映射內存。調用mmap函數,將某塊內存映射到剛剛的文件,接下去對該文件的操作都會反映到內存上,注意該函數使用時的參數,映射區域的特性flags需要像cyber中那樣設置為MAP_SHARED,這樣對映射區域的寫入數據會復制回文件內,而且允許其他映射該文件的進程共享。如果設置為MAP_PRIVATE則對映射區域的寫入操作會產生一個映射文件的復制,即私人的“寫入時復制”(copy on write)對此區域作的任何修改都不會寫回原來的文件內容。
讀寫數據,之后就可以通過直接讀寫對應內存比如memcpy或cyber中的string*->assign/append函數等來進行操作和通信。
11.3???? 匿名映射實現共享內存
父進程中調用mmap映射一塊內存,對于具有親緣關系的進程實現共享內存最好的方式應該是采用匿名內存映射的方式。此時,不必指定具體的文件,只要設置相應的標志即可。
父進程調用fork創建子進程,子進程繼承父進程匿名映射后的地址空間,同樣也繼承mmap()返回的地址,這樣,父子進程就可以通過映射區域進行通信了。
對這塊內存進行讀寫就能實現通信。
12??? 參考
https://zhuanlan.zhihu.com/p/115046708
https://blog.csdn.net/qq_25762163/article/details/103895527
https://blog.csdn.net/qq_25762163/article/details/103803032
https://blog.csdn.net/qq_25762163/article/details/103945289
https://blog.csdn.net/weixin_44450715/article/details/86314193
https://zhuanlan.zhihu.com/p/91322837
https://blog.csdn.net/qq_25762163/article/details/103591766
https://gitee.com/ApolloAuto/apollo/blob/master/docs/specs/Apollo_5.5_Software_Architecture.md
EI企業智能 任務調度 自動駕駛
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。