Apollo 3.5 Cyber - 基本架構入門

2019-04-13 20:30发布

Apollo 3.5 Cyber - 基本架構入門


簡介

終於把cyber中的主要模塊都review了,把其整體邏輯搞通了。
現在就根據個人了解,做個簡單的全局的解釋
Apollo自己也有做講解,想避免被我誤導的,建議看官方的 先上個全局圖,整個講解會圍繞這圖來說。因為圖比較大,可先下載再配合內文使用。當中只包括一些比較重要的模塊。
structure

modules下的模塊啟動的底層流程

之前有寫過一個簡單的
https://blog.csdn.net/weixin_44450715/article/details/86075928 現把底層模塊是怎被用到的,都顯示出來 先假設沒有額外定義的Node::ReaderNode::Writer,而且是在reality mode
模塊的介紹在下面主要模塊的用途那邊
  1. 用cyber_launch起動Mainboard
  2. MainboardClassLoader加載shared object,並初始化
  3. Component的instance在上一步被生成,初始化時生成其內部Node及其Node::ReaderNode::Writer
  4. Component然後利用DataVisitorRoutineFactory的組合,把自己的Proc function變為一個任務,放到Scheduler
  5. Transport中的singleton發現有新數據來了,把數據給DataVisitor。(Transport中會根據Service Discovery的資料開關回調及在特定模式下選擇實現)
  6. DataVisitor在做了fusion等工作後,會叫預先定好的回調(即跟Scheduler那邊說這個任務狀態更新了,可執行了)
  7. Scheduler中的singleton會不停的等任務來,當發現有任務可以執行時,就拿出來執行
  8. 當執行一次之後,任務重新變回等數據的狀態
  9. 當新數據再來時,返回 (5)

主要模塊的用途

如果我之前已經講過的,就直接發連結。

Mainboard 跟 ClassLoader

在apollo 3.5中,是先把modules中的模塊編成一個shared object,再用cyber_launch把模塊啟動。cyber_launch只是個腳本,只負責預配置(讀配置交件,設定參數等),真正用到的程式是 Mainboard。而Mainboard又用到ClassLoader去把那個shared object加載,把全局設定好,然後生成instance,執行任務。
https://blog.csdn.net/weixin_44450715/article/details/86075928

Component

modules中的模塊都是要寫成Component或TimerComponent的sub class,再用macro註冊。而Component或TimerComponent都是ComponentBase的subclass.

Component 中的 Component

跟以前的Apollo 3.5之前的ApolloApp很像。在用時,都是通過繼承super class,然後再實現當中的一些virtual function去達到目的。而Component要你自己實現的function有InitProc。而且他背後幫你幹的事,比ApolloApp可是多很多。比方可以直接把數據當成Proc的參數傳進去等。

Component 中的 TimerComponent

Timer base 的Component,即每N個時間單位,就處理一次事情。 TimerComponent 跟 Component不管是內部實現還是設計,都是差很遠的。而兩者提供的功能更是完全不同。
  1. TimerComponent 的Process是沒有參數的。即是說你要甚麼數據,都一定要自己去拿,或另外在數據相關模塊設定回調。
  2. Component 中的Process的調用是由Scheduler模塊去安排在甚麼時侯執行的。而 TimerComponent 的Process的調用是由Timer 按設定時間執行的。
  3. TimerComponent 的實現比 Component 簡單很多。

Timer

TimerComponent 有點像以前ROS中寫一個loop,在loop中間做事,然後在結尾睡一下再開始下一圈的設計。 ros::Rate r(1); while (ros::ok()) { // core function .... ros::spinOnce(); r.sleep(); } 不過cyber把這一套搞得更進一步。
  1. 容許多任務
  2. 用的時候只要把任務定義好,加到Timer Manager中就可以了。不用自己寫Loop。
  3. 支持把任務異步執行
而Timer就是做這些事的地方了。
當然,把全部任務放一起就肯定要考慮一下性能了。當然不會說在每一個loop中都把全部任務檢查一次這麼粗糙的做法了。
它內部用了一個time wheel,基本就把任務按應該被執行的時間(因為空間有限,時間無限,當中還有一個取模運算),分在這個輪子中的slot。加速每次去查找當前要執行的任務的時間。
這個輪子會隨著時間而轉動,當前指向的slot也隨輪子轉動而改變,那只要判斷在當前slot中的一堆任務。那些是要執行的就好了。

Transport

低層的數據傳輸系統 https://blog.csdn.net/weixin_44450715/article/details/86314193
https://blog.csdn.net/weixin_44450715/article/details/86479466

Data Visitor

把Transport再包一層,提供專為數據訪問的接口。也是一個計設用來跟RoutineFactory配合一起用的接口。
https://blog.csdn.net/weixin_44450715/article/details/86149041

Node

Node 跟rosnode在定位上有點像,都是負責上層的讀寫功能。
可以用Node::Reader在某channel (topic)中註冊回調,可以用Node::Writer把新的數據寫到channel中。 開發者基本只要用到ComponentNode,就能滿足一切需求。

Service 跟 Service Discovery

利用Node跟Transport提供的功能,實現一個Service的抽象功能。(Service就像一個伺服器,接收數據,處理,然後返回結果)
Service Discovery則負責節點的監察 https://blog.csdn.net/weixin_44450715/article/details/86514423

Scheduler 跟 CRoutine

Cyber中的dag文件可定義多個Component,那如何調度多個Component的運行就靠Scheduler https://blog.csdn.net/weixin_44450715/article/details/86538575

那ros 中的/tf, /tf_static是由誰負責呢?

是由 modules/transform下面做的,而不是由cyber提供的,不過內部實現也是Node::ReaderNode::Writer