天天看點

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

作者:車東西Fast
基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

6月7日,地平線「你好,開發者」技術公開課在智東西公開課順利完結直播。公開課由地平線TROS.A系統架構師傅亞濤主講,主題為《基于TogetheROS.Auto的智能駕駛軟體開發範式》。

本文是此次技術公開課主講環節的實錄整理。如果對直播回放以及Q&A有需求,可以點選閱讀原文前去觀看。

大家好,我是來自地平線的架構師傅亞濤,主要負責TROS.A的技術規劃和系統設計,很榮幸有機會和大家來分享《基于TogetheROS.Auto的智能駕駛軟體開發範式》。

首先,我會簡單介紹智駕開發中遇到的各種問題,然後會基于這些問題來看如何從設計角度将問題做簡化;然後,我會把TROS.A基于這些設計方式和設計思路所做的相關設計及實踐進行分享;最後,我會分享智駕軟體開發的發展趨勢,以及智駕中間件的發展方向。

01智能駕駛軟體研發的易與難

智駕已經發展很多年,近幾年也越來越熱。最開始我們做的時候,做一個智駕的demo都會非常困難。當時做一些AI應用,最開始是在一些通用的CPU上,之後是在一些類似于FPGA闆上做智駕開發。當時參加各種展會的時候,如果有一套基于FPGA闆的算法demo,且整體效果OK,就已經非常亮眼了。而近兩年參加智駕相關的展會,如果拿不出一個實車的demo,然後做一些試駕評測的話,在整個展會上看起來會薄弱很多。

為什麼現在整個智駕開發較之前成熟且看起來簡單了許多,我簡單總結了一下。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

一是智駕開發生态百花齊放。大家可以看到,目前基于智駕的各種開發生态環境以及開源軟體發展地非常好。一個典型的例子,比如說ROS2。可以看到基于ROS2往上,做的感覺、規控這種智駕的服務,以及往下的廠家硬體接入,現在已經發展得比較成熟了。此外,目前各種開源軟體在智駕裡面使用很成熟,并且經過了多輪疊代,比如DDS、FAST DDS、Cyclone DDS。同時,有多家DDS商用的開發商在開發這種功能安全的DDS版本。另外一個就是AUTOSAR。最近幾年,AUTOSAR AP的标準發展非常快,可以看它最近的一些更新。實際上,它對于智能駕駛往上的AI開發,會變得越來越友好。現在很多特性,都已經很貼近上層的應用開發了。算法的話,基本上每過一兩年,算法都會有一個大的疊代。從原來的最早的檢測模型,到BEV,再到Transformer,算法的疊代非常快。而且,基本上是業界有什麼新的算法,大家很快就能跟上。硬體平台算力方面,每年都可以看到哪個廠家的算力破新高,發了新的計算平台。二是智駕開發能力快速提升。可以看到,整個智駕,從研發的投入上來說,增長非常明顯。這周我用智駕這一關鍵字查了一下相關的企業,大概有15000多家,但裡面有一些可能和智駕關系也不大,但相較幾年前來說,這個數量增長的非常快。而且,涉及到智駕的開發人員也大幅增加,大家從技術棧上,成長也非常快。然後,從平時接觸到的各種相關廠家,比方說OEM、Tier1、Tier2,現在基本上都把自己的能力棧建立起來了。原來很難搞定的一些事情,現在來說可能都是一些基礎的事情。算法原型以及工程的原型,現在也有各種開源的實作、各種樣闆間。算法的疊代方法,包括方法論,也不是一個新鮮的話題。有很多的公司實際上都建立了類似的能力,讓整個算法疊代越來越快。最後,可以看到,目前做智駕已經初步形成了一些分工。往往在做一個量産産品的時候,會遇到好幾家方案解決商,然後多家協作,這家做感覺,那家做規控,另一個做硬體加內建。整個量産好像變成了一個拼圖遊戲,相對來說,難度大幅降低。相對于幾年前,智駕開發難度低了很多。但從目前來看,是不是真的低到了大家都可以去做,并能做完整的量産,也是不一定的。我和很多OEM的小夥伴聊過,得到的一個回報是:現在和任意一家方案解決商或者其他從業者,去聊有個東西能不能做?能做;但是能不能量産?現在還沒有驗證過。是以,基本上是一問就會,但真正到量産的話,還有很多困難。這就是為什麼從做一個智駕的原型到量産會這麼難。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

首先,從開發模式上,我們常見的智駕開發模式,這裡寫了主要的兩種:

一種是典型的V模型。做過智駕開發的應該都會比較熟悉。這個V模型,一般是從研發側,基本上是從系統需求、系統架構,再到子系統的設計研發。相對于常見的V模型,從需求,到設計,到研發來說,智駕會複雜很多。

基于智駕的軟體規模,基本上經常做的是一個大的系統需求,從頂層的架構,再分解到多個不同的子產品或公司。這個公司本身會再去做頂層的系統需求的分解,然後再去做設計。這種層級可能有兩到三層,導緻的一個問題是:在需求設計上經過層層分解,而這個分解的過程和軟體研發其實是分離的。需求設計可能更多停留在文檔上,研發基本上就到了整個系統的設計,然後再到編碼。這個過程其實是分離的,流程越長,分離的越開的話,會造成在真正開發過程中,越容易造成變形。有可能做着做着就做歪了,有一些東西可能會漏掉。

反過來做這種內建的時候,又會發現有這麼多層這麼多組在并行開發,反向去層層做內建的時候,內建的成本非常高。遇到一個小問題,可能都需要拉一大撥人去長時間的定位。一個問題當涉及到跨團隊跨公司的時候,來回踢皮球的情況,其實非常常見。

另一種開發模式其實也很常見。我們一般會去做一個原型系統,其實是用來做算法驗證快速疊代的。基于這個原型系統,并對效果做了一定疊代之後,再往量産的環境上遷移這時候會面臨很多問題:

一是原型系統和量産環境的架構差異很大。在原型上,可能是怎麼快怎麼來,比如說基于ROS2,或者基于Python來寫;但在量産上,比方說,可能需要一個功能安全的軟體底座,為了性能的話,可能會基于C++,甚至寫一些性能更高的定制化實作。這就導緻遷移過程很重,軟體的效果一緻性以及算法的一緻性很難保障。此外,在原型開發的時候,大家更多關注的是算法的效果,但很少關注軟體的性能,這會導緻在原型系統向量産系統遷移的時候,性能優化成本非常高,整個軟體的品質收斂速度會較低。

另外一個問題剛才也提到過,就是我們現在的智駕開發,通常是多團隊開發,很多時候還是多公司聯合開發。那它帶來了一個問題,就是大家都有自己的一套技術棧,然後底下的軟體棧,包括中間件和基礎庫可能也不太一樣,最終內建到一個系統會非常困難。若出了一個問題,其實很難定位,比如某個線程執行發現總是出現delay,這種時候去定位線程被哪些資訊影響,是非常難定位的。因為大家對于任務劃分的粒度,以及開發控制的界面都不同。

此外整個智駕涉及到的系統非常複雜,不同子產品間的影響會非常大。比如感覺輸出的周期可能不是那麼固定,或者我的Latency的方差會比較大,就會影響到後面,比如預測、規控、定位相關的計算效果。

另外,前面也說到,多團隊的開發,由于底層的架構不統一,再來做性能優化的時候會非常難。我們和一些團隊接觸過,在某些情況下,整個軟體的線程數可能會達到三到四千。這種情況下,想去優化某個具體任務的性能會非常難,不一定是這個任務算得慢,而是整個系統就調不過來。同時,在這種規模下,去做問題定位,會很困難。比如說運作的過程,若發現延遲不符合預期,或者整個過程block住了,要定位是哪個子產品的問題,都非常困難。

最後,整個軟體棧的話,從最上層的算法、工程、政策,再到中間的中間件,再到底層的BSP、Driver是非常複雜的,有時候面對一個簡單的問題,可能會需要聯合多個團隊來進行聯合定位。所有的這些都會造成一個問題,就是在自己子產品開發的時候,可能已經開發好了,但一旦真正做內建量産的時候,會發現整個周期依舊拉得非常長。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

第三點,前面也有講到,現在做智駕這一塊,涉及到的知識面,不管是橫向還是縱向,都非常廣。比方說在基礎能力方面,你可能需要C++,然後也需要有些python或者shell能力,至少能看懂算法工程師寫的算法政策;然後可能需要去了解一些基礎的系統知識、基礎的工具;做性能優化的時候,正常的優化手段,比方說線程池、協程池、對象池、記憶體池等會用上去;對于熱點,可能會做一些定點化的優化,然後做一些OMP、neon、彙編優化都有可能;然後問題定位的時候,用GDB還有ftrace、位址消除器各種各樣的工具來去定位,比方說熱點的性能問題,或者一些記憶體問題。

雖然做工程開發的時候,可能大部分用到的是軟體工程的能力。但做智駕的話,其實需要有一定的算法知識。最基礎的,例如資料結構算法,是通用知識;另外基礎的CV算法肯定要會,比如至少要去了解一個圖怎麼轉成一個BEV的圖,大概的原理和計算方式是什麼;關于機器學習,可能相關的算法工程師會研究的更深入,但在做軟體開發的時候,至少要了解對應模型是什麼、大緻的邏輯以及它的輸入輸出、相關的處理調用;做性能優化的時候,對于常用的排程算法,肯定要有了解;此外,還涉及到資料壓縮、資料加密、标定算法等。

另外就是業務相關能力,各種傳感器基礎知識、硬體基礎知識;然後AutoSAR、ROS、DDS這種正常的軟體,各種資料、渲染工具,以及功能安全一類的等。

是以,做智駕方面的軟體開發,對工程師的技術棧要求會非常高,也帶來幾個問題:一是很難招到合适的人;二是從整個團隊來說,新人進來要真正地能開始動手幹一些比較實際的活,可能需要幾個月的培養;而他開始能做一些跨子產品複雜的工作,可能需要一年左右。所有這些都會導緻整個軟體開發難度加大,整個開發的帶寬會非常地受限。

我這裡面隻列了一些常見的問題,當然會有更多的問題。比如整個智駕,要去做資料的管理,從采集到傳輸分析,然後再到Software2.0這種資料驅動整個軟體的疊代。

02從設計角度如何化難為易

今天我主要是從軟體的角度來看怎樣去減少這些軟體開發中各種各樣的問題帶來的複雜度。接下來,從設計的角度簡單介紹一下如何化難為易,分兩個方面:

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

首先,從橫向來說,因為會面臨多團隊多公司的并行開發,是以在整個設計上肯定會選擇,例如SOA架構,來進行橫向設計的解耦。各個團隊開發的功能子產品需要能做到自洽可驗證,但僅僅隻做到SOA,可能不太夠。除此之外,在頂層設計上協定标準需要是統一可控的,且子產品間的傳遞界面需要非常清晰。這種傳遞界面,除了SOA的基礎的服務協定以外,實際上對于子產品的限制,也需要有完整的定義。前面講到在整個V模型開發裡面,做設計開發分解其實是會有多個層級。在頂層的限制一層一層往下分解,需要在架構上能支援一層一層的傳遞下去。除了這些以外,還需要整個架構能提供非常豐富的問題定位能力,至少可以快速做分責。在做軟體開發經常會遇到一個情況,就是一個問題涉及到多團隊,然後這個問題的定位就會變得非常困難。這個時候其實就需要整個架構有能力,能很快速地确定問題具體在哪一端,然後involve相關的人員進行分析,有效地加快整個軟體開發的過程。在做頂層架構的時候,實際上會做兩部分東西:一部分去做功能界面的分離。比如,有哪些大的子產品?它的能力是什麼?它的接口是什麼?然後,另外一個,我們會做算力以及部署上的劃分。但這一部分,一般來說可能會做非常頂層的劃分。比方說,感覺和規劃放在哪一塊,定位地圖放在哪一塊。但再往下的話,一般不會在設計階段做太多限制。這個就要求架構能支援設計實作和部署的分離解耦。也就是說在設計實作的時候,我來做開發,然後多個子產品有可能是完全分離地去做開發;但實際部署的時候,我可能會把它部署在同一個程序或者同一個服務内。當有問題,或者算力有一些不足,或者有一些調整的時候,需要靈活地把這些子產品再分離成不同的服務。部署與實作分離,從架構層面支援,不需要軟體開發去做過多的适配和考慮。要實作上面這個能力,就需要底層在架構上做到統一。這其實也是現在合作分工開發的一個痛點,就是大家現在或多或少都有自己的一部分内容。現在看到的一個情況是,如果底層架構不統一,遇到一些問題可能根本就沒辦法定位。前面舉過一個例子,我們有遇到整個應用非常複雜,幾千個線程。而線程這麼多的原因是架構底層完全不統一,都有自己的線程池,有自己的排程政策。在這種情況下,出現了一個高優任務延遲上百毫秒才執行的情況,根本就沒有辦法進行問題定位。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

說完橫向的設計,再從縱向設計進行說明。前面有提到,現在智駕的軟體開發,需要了解的知識點會非常多,對人員的要求會很高。這就需要從架構上去做邏輯概念的分層和屏蔽。一般來說,大部分算法開發人員和應用開發人員,關注的點,其實是算法實作或者是應用的邏輯政策實作。其實不必再往下層關注,比如應用應該怎麼配,資源是怎麼樣,應該和誰通信。再往下層,會有同學負責應用的內建。他可能對上層的算法政策、應用政策開發并不關心。他關心的是整個應用資源的配置設定,從功能安全怎麼去做配置,整個通訊拓撲怎麼配,整個應用怎麼部署執行。然後再往下,其實會有一些基礎的能力。比方說傳感器接入,異構加速器的使用,各種比較常見的算法、基礎服務、基礎庫。從架構上來說,屬于非常固定的東西。這些在整個架構内應該是已實作的,使用者可直接調用,完全不關注它的細節。這樣,從縱向上來說,做到多層的概念和任務分離。當一個應用開發人員隻關注他需要關注的部分的時候,對開發人員的要求會低非常多。這麼做的好處,是整個軟體開發對于開發人員的要求降低,整個團隊更容易搭建,也更容易進行擴充。 03TROS.Auto開發最佳實踐從設計角度圍繞橫向和縱向簡單做了分析,接下來和大家分享一下TROS.Auto怎麼樣從橫向和縱向兩個次元簡化整個智駕開發的過程。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

首先,什麼是TROS.Auto?這個圖是我們現在的系統架構圖。看起來很複雜,因為裡面包含的東西會很多。在基礎應用架構裡面,有Communication做通信架構、DataFlow去做應用界面以及排程、會有各種的基礎服務,如EM、SM、 PHM診斷;另外,我們也會做很多SoC上的基礎能力抽象,比如用easyDNN來做模型推理的抽象、用HobotCV來做各種CV硬核的抽象,也提供了各種基礎庫,做了各種工具;在PC端,我們做了整套從設計,到開發到部署,再到調試的開發工具,也做了類似于錄制回灌、2D /3D渲染的資料相關的工具。然後基于這一架構,我們也做了很多标準子產品。比方說,sensor center用來做傳感器接入的基礎服務,vehicleIO用來做車輛底盤信号的接入。然後,再往上也有我們各個項目做的标準的服務,比方說一些trigger或者标定。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

前面看到這種架構圖确實會比較複雜,它是屬于我們内部的一個設計架構。但從大的概念上來說,簡單來看,會包含五個部分:一是應用架構,就剛才說的Dataflow用的開發和排程的界面;Communication是屬于底層的通信架構;二是開發工具;三是功能子產品,是基于我們的架構之上做的一些标準的應用子產品;四是各種基礎庫;五是基礎服務,我們參考AutoSAR AP做了自己的一套實作,裡面的一些概念會有些類似。從使用者,或者從開發者視角來看,其實并不需要了解這麼多。從最頂層的開發視角,比方說我是做算法政策開發,或者做應用邏輯的話,了解的概念主要是這三個:

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

第一個是package,實際上是最頂層的一個概念,用來做功能子產品的打包封裝,然後可以去package去做子產品的共享以及執行。相當于我在做應用開發時候,可以把package作為一個功能子產品引進來,依賴它去做開發。我也可以把多個package放在一起 然後直接去執行。這一塊,我們也提供了相關的工具,把基于TROS.Auto開發的工程打成package,提供部署安裝編譯執行的一些基礎的能力。然後,package往下,graphlet是我們軟體子產品的一個頂層概念,很多時候我們也叫它為DAG,實際上是一個有向無環圖的概念,由多個軟體子產品組成,構成了一個基礎的執行單元。整個graphlet是支援嵌套的。相當于一個graphlat裡面可以嵌套多個不同的子圖。我們可以基于graphlet這一層級,去做整個應用的排程部署相關的一些配置。這一塊更多會在整個應用的部署、排程優化的時候,會從這一層的概念上出發,做相關的配置和優化。最底層的概念module,是我們的功能子產品開發的最小單元,一般是用來封裝一個最小的任務的概念。從圖上可以看到,一個module裡面包含三個概念:

一個是port,是我們功能子產品的一個輸入輸出的端點。一個module可以有多個輸入,也可以有多個輸出。

第二個概念proc,是最小的執行單元。在很多情況下,可以認為一個proc 其實就是一個task,它會由觸發器來觸發進行運作。這個觸發器有可能是基于前面的消息觸發,也有可能是基于一些時間觸發。然後,實際觸發之後的執行會由底層的排程器來執行。使用者從開發界面其實不太會關注具體怎麼調。怎麼調其實是排程器部分的政策,它的配置更多是在graphlet這一層,我們來看這個子圖應該是怎麼去執行。

第三個概念filter或者是condition,其實是proc的觸發條件。一般來說,一個proc可能會由多條消息或者多個條件,來進行觸發,我們其實是内置了一些常用的。比方說A消息和B消息同時到達,再執行proc A;或者A消息或者B消息随便來一個,我都去執行。同時,這部分能力,也支援使用者做擴充,比方說我們自己常用的一個擴充,會對消息進行篩選,來做消息的時間對齊。

單純從使用者的開發界面,主要了解這三層概念,就可以進行相關的功能子產品的開發。

怎麼樣從TROS.Auto上做設計,前面其實有提到。TROS.Auto從概念上可以分三層:package,graphlet和module。這其實和設計是相呼應的。前面講到V模型有多層的設計分解,展現在TROS.Auto裡面,我們從設計上也做了一個層層分解的設計。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

在頂層架構上,可能會有一個非常大的graphlet,裡面的子產品相對來說可能都是非常粗粒度的。比方說,感覺就是一個大的module,或者是一個package;定位、預測、規控都是相關的這種粒度。基于這個确定這些大子產品之間的互動是什麼樣的,限制是什麼樣的。

然後再往下,我們會做子產品的分解。比方說感覺,是由一個複雜的graphlet組成的感覺。由于前面感覺在頂層設計上,已經定義了它的輸入輸出的标準,以及對于感覺的限制,比如執行資源或者其他的限制。這時展開做設計時,這些限制和輸出,天然會在下一層設計上會被引入進來。這一層的設計和頂層的一樣,對這一層做架構的分解。

再往後可能會有更進一層的架構分解,也是一樣來做各種輸入輸出、限制的傳遞,來保證整個架構從頂層到底層,是基于同一套限制層層傳遞,不會造成架構多級分解的資訊丢失或者變形。

整個設計,到最底下一層的時候,支援基于這個設計去做對應的代碼架構生成。在生成的代碼上,天然的裡面定義的各種輸入輸出、各種限制,就會嵌在生成的代碼架構裡面。使用者在這一套架構裡面,去做自己的功能開發就可以。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

這是TROS.Auto真正從設計到實際研發的一個大緻過程。可以看到,最左側,架構已經分解到最底層,可能在我這一層是一個比較小的功能子產品。在這一層上,我們定義了一個graphlet,裡面的子產品與子產品間的資料流會被定義出來。基于它,我們會去用工具生成整個應用的代碼的架構,這個架構在這個時候實際上是屬于已經可編譯、可運作的架構,隻是沒有具體的業務邏輯。使用者在開發的時候,基于生成的這個架構去做具體的功能子產品的應用開發。因為輸入輸出已經定義好,基本上是把自己的業務邏輯加進去。

可以看到,部署、排程和開發是分離的。因為從我們的設計上來說,使用者真正做這種應用的業務開發的時候,不應太關注應用如何配置以及如何調用。它實際上是配置運作的一個過程。會有少部分的同學做應用內建的時候,會更關注應用怎麼配置,以及應用怎麼做排程優化。他和實際開發同學有可能是同一個人,也有可能不是。是以,這兩部分概念在設計裡面應該是分離的。最終在部署配置、排程優化之後去上闆運作。

整個開發過程是這樣一個過程的循環疊代。部署運作之後,來看功能以及性能,效果是否符合預期;如果不符合預期,可能會傳回到子產品開發、部署配置、排程優化,來循環做這種持續的疊代,最終達到一個比較穩定,比較好的效果。

剛才有提到,我們将整個軟體的應用邏輯的開發、部署以及排程做了隔離。這裡可以看到,我們是如何做縱向封裝來減輕使用者在排程方面的投入,和降低排程的了解成本。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

左側是基于剛才說到graphlet在工具上通過拖拉拽的方式,生成的一個graphlet的執行個體。它會生成具體的一個架構代碼。

可以看到,實際上它定義的是剛才的内容:input的一個port,output port以及裡面不同的proc;input和output之間會去定義一些具體的執行觸發條件。

整個代碼架構生成之後,使用者基于這個界面去做具體子產品的開發。而實際在輸入的時候,使用者其實不會太關注具體每一個proc怎麼配。因為整個支架其實裡面任務數會非常多,可能幾千個任務,或者上萬個任務。如果對每個任務去配它的排程政策,比方說綁核、優先級以及任務之間的這種關聯關系,其實會非常困難。都做這種配置,在某種程度上可能性其實很低。

是以,目前我們的做法,更多是在使用者界面上基于graph來配。就是整個graphlet實際上會有一個子圖的概念。前面有說過graphlet也支援嵌套。那我的配置可能更關注執行鍊路應該有一個什麼樣的執行效果。整個graphlet,我會劃分成不同的子圖,不同的子圖有不同的排程預期。而實際的排程是由底下的scheduleGroup來進行排程和配置設定。scheduleGroup裡面,我們現在有做大概4種不同的排程器:基于定時的(Timer Scheduler)、基于線程優先級的(Priority Scheduler)、基于公平排程的(Deteministic Scheduler),也提供了基于協程的排程的能力(Coroutine Scheduler)。當然,每一種排程器裡面有很多種政策。

對于排程的确定性要求比較高的,我們也提供了基于任務鍊時間做編排的一些排程的邏輯。是以,整個來說,在上層使用者的開發界面,可能更多看到的是,我希望graphlet達到一個什麼樣的排程效果;映射到底層的scheduleGroup會映射到不同的排程器裡面去;這些排程器再基于它的排程政策來進行實際的排程。

右下角這個圖,是我們在進行了排程配置之後,實際生成的一個排程配置檔案。可以看到,不同的排程器可能會有不同的配置字段,但這一部分更多的是基于我們的工具來幫你生成。當然一些工程能力比較強的同學,可以直接基于這個配置檔案去手動做修改。我們盡量簡化整個應用在排程上的複雜度,希望通過架構來屏蔽整個排程的一個過程,做到應用開發和排程的分離。

前面也有提到,我們也做了應用開發和部署的分離。分離這部分是基于我們的通信架構來實作的,主要由兩部分能力構成:

一部分是我們實作了一套IDL工具,目的主要是将消息定義和實際的序列化方式做解綁。做軟體開發的同學可能會體會到,實際在做消息定義的時候,一般會綁定某一種序列化方式,比方說綁定protobuf,或者DDS的話,有可能是Fast Buffer或者其他的序列化方式。

這會導緻一個問題,就是當我們一個消息發送給不同的序列化接收對象時,在代碼裡面可能需要定制開發。比方說我發給對端,對端是走DDS的,我可能要在發送的時候就給他綁Fast Buffer;如果對方是程序内,我可能什麼都不綁。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

我們IDL目前做的方式,實際上就是将消息和序列方式做解綁,從使用者界面看到的消息實際上就是一個一個的struct,我們當成常用的結構體來進行使用。真正和對端通信走什麼樣的序列化方式的時候,實際上是IDL生成的library來做決定。我們會在裡面做IDL 的擴充,比方說,現在預設其實已經做了protobuf、 Fast DDS 的序列化方式的擴充,也可以擴充第三方自定義的序列化方式。在這種情況下,整個消息通信走哪一種,更多是運作時看通道的配置。

另外一部分就是具體的通信和通信協定、通信鍊路的解綁。我們開發了一套通信架構,它對上提供了這種常用的Pub/Sub、CS和Action的通信接口。然後往下可以看到,會接入非常多的不同的通信協定,比方說DDS,ZMQ,PCIE或者一些其他的。我們目前的做法是一種插件化的接入,也就是說我實際使用了哪一種,我把對應的SO扔進來就可以支援。但是對上來說,使用者使用界面是完全不感覺。

具體使用哪一種通道或者協定去跑,更多決定于我運作的配置。可以在部署配置裡面配,也可以基于類似于Hybrid的方式,讓它自動去選擇,這個更多取決于我們使用的時候的一個場景。通常來說,我們可能在調試的時候用一些Hybrid的方式,但真正量産的時候可能會把通信的配置給固化下來,直接走平台定制。

通過這兩種方式,我們就做到了整個通信方式和實際的通信鍊路以及通信協定的解耦。這時候就可以做到多子產品開發的時候,開發的接口完全一緻,但把它部署在同一個程序,還是部署在不同的程序,甚至部署在不同的SoC上,這時候應用的代碼是完全一緻的,它隻是一個運作期的配置,就達到了前面說到的軟體研發和通信配置的解耦。這種能力在後期做功能調試的時候,會非常有用。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

第三個方面,我們也做了基礎服務簡化。前面有聊到過,我們有參考AP來定義一套我們自己的基礎服務,比方說EM、SM、PHM診斷時間同步。在這一部分,前面有講到在Dataflow這一層,我們有DAG或者是graphlet這層概念。很多這種基礎能力,我們可以在這一層界面上和它打通。

比方說EM去做應用生命周期管理,但應用生命周期某種程度來說,是應用的一個graphlet執行的管理。是把graphlet的運作起來,還是停掉或者暫停,都可以通過這個界面。

SM其實也類似,比方做functionGroup。functionGroup粗粒度的可能是程序級的程序組控制。它和前面的EM的邏輯有點像,就是我去做程序級的graphlet的啟停。

基于graphlet,其實也可以做更細粒度的。前面有講到過,graphlet支援嵌套,我們可以在這個概念上,去做更細粒度的程序内的一些子功能的控制。

PHM和診斷這一塊,我們在架構内會有內建。因為架構本身也會有一些PHM的檢查,比方說執行邏輯或者執行逾時,也會有診斷資訊的上報。使用者也可以調這一塊的接口去做執行檢查和上報資訊。這一塊其實對使用者來說是可見的一部分内容。

其他的,也有一些基礎的庫,比方說時間相關的timer,我們也做了封裝。基于它可以屏蔽掉底層的時間變化,比方說基于系統時間、基于虛拟時間,還是基于外部時鐘源。在應用開發界面,就不需要特别關注切換時間導緻的代碼适配變更。

另外,我們其他的一些基礎子產品也是類似的一些設計思路。比方說也做了一套log的前端,統一由這個前端按照固定的格式進行輸入。那它的後端可以接各種各樣的log後端的服務,比方說預設做這種檔案傳輸,但它也可以接比方說安卓的Alog,也可以接AutoSAR的log service,或者一些其他的自定義的log服務,來做log後端log盤的管理。

整個基礎服務,和AP很大層面上概念會比較接近。是以,在實際的項目裡面,我們也遇到廠家已經買了某種AP。但對于我們來說,這種基礎服務和AP的替換,從應用的開發界面來說,其實是無感的。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

前面簡單聊了一下,TROS.A從橫向或者縱向是怎麼樣設計,來簡化整個軟體開發的界面,并降低智駕開發的難度。舉一個簡單的例子,剛才也講過我們會做一些能力的屏蔽。實際開發的時候,我們可能的一個做法,在頂層上會有一些大的子產品:感覺、定位、預測、規控。這些子產品内部本身是一個graphlet的組成,裡面不同子產品有可能是使用者已有的一些子產品,可以從某個其他項目直接給遷移過來。因為每個module都是可以單獨進行引用的,也有可能是你自己去開發。

當然,從TROS.A來說,我們也做了很多标準的功能子產品,比方說Sensor center、VechicleIO、Odom、tf,我們其實做了一些标準實作,可以直接用。這一整套架構會在DataFlow的開發界面上,進行架構的組成以及排程的配置劃分。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

做完開發之後,接下來就是去做調試。在很多時候,調試比開發更麻煩。前面有講過,現在做軟體開發,其實并不是我一組人聚在一起把整個軟體開發就做完,很多時候涉及到跨團隊甚至跨公司去并行開發。在這種時候,需要很完善的工具來進行問題的定位。某種程度上來說,很多時候我們需要快速分鍋。

我們會提供一些基礎的能力:

首先是線上調試。在整個軟體的graph上,我們在不同層級提供了不同的能力。

在通信這一層,我們做了一些工具,用于檢視整個通信拓撲以及通信節點的狀态;同時,我們也做了通信相關的統計,比方說通信節點發送了多少資料,接收了多少資料,接收的延遲是多少;也會有工具去做模拟的資料發送,來進行問題的定位跟蹤。

從排程的層面,前面其實有講過,我們是基于上層Graph界面做排程。但在執行的時候,我們基于proc這個力度做了執行統計,包括執行時長、CPU占用情況。從右側可以看到,這個圖是studio上的一個工具,顯示的是整個應用在不同的計算核上的計算分布情況。整個應用在不同計算核上,在某個時間段是哪個task在上面執行。基于這個,可以比較清晰分辨出具體的軟體執行情況,來做各種性能問題、功能問題的定位;同時,我們也提供了一些msg trace能力來跟蹤整個消息在整個graphlet裡面是怎麼運作的,可以有效地去做功能定位,比方說我跑着跑着block住了,或者在某些節點有大量的消息積壓。

從控制的角度,基于graphlet這一層,我們提供了一些控制的能力,包括基于module/ proc的啟停控制、基于graphlet的切換,還有一些配置相關的,這個在功能開發階段會非常有用。一般不會在量産階段去做控制,但在功能開發階段,可能會為了調整功能,需要把整個圖裡面的某一部分給停掉,或者需要直接把圖的執行邏輯改一下。

最後會有一些狀态的資料。像前面說到通信的狀态、module的節點的狀态、整個系統的狀态,包括各種資源的使用率、系統執行的基礎情況。這是我們線上調試階段提供的基礎能力。

其次,我們有做各種資料分析的一些工具。首先,我們會提供基于pack的各種資料相關的工具。pack是地平線自定義的一套深度資料存儲格式。基于pack,我們做了一系列的資料存儲檢視、查詢分析的工具。比方說右側第二個圖,就是用來檢視pack裡面具體的資料内容。基于pack,我們也做了各種指令行的小工具,比方說基于topic做資料的錄制、做資料的回放。在這個過程中做各種基礎的控制以及做pack的資料轉換。這個轉換更多是和第三方做一些資料相容.比方說,我們現在做了RosBag-to-pack的轉換,可以和RosBag做一些簡單的互轉。

最後,我們也做了一些資料展示相關工具。比如文本的展示,像pack資料展示分析、log資料的展示分析和過濾;以及2D資料的展示,比方說統計資料、2D的image渲染;還有3D的資料展示。

基于這些工具,不管是在開發過程中進行功能調試,還是在出現問題之後,去确定問題是發生在哪個子產品,進而進行問題的分解,會提供非常大的幫助,能有效提高開發效率。

04智駕發展趨勢對軟體開發平台的影響和要求

前面簡單介紹了我們基于TROS.A做軟體設計、開發、調試的一些基礎内容。接下來,想和大家分享和讨論一下,智駕的發展趨勢對軟體開發工作的影響。這也是地平線目前正在讨論和預研的,希望分享出來後可以引起更大範圍的讨論。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

首先,一個很明顯的趨勢,提出來也有很多年了。智駕相關的電子電氣架構,從傳統架構,往中央計算平台架構進行疊代,這一趨勢已經非常明顯了。可以看到,有很多家都提出了艙駕一體。

各種算力平台,特别是一些大算力平台,基本上也可以開始做計算任務的融合。這對于軟體開發平台或者說中間件,影響會是什麼?

雖然大家在一個平台上,但實際執行的時候需要做多域的隔離。最簡單來說,雖然做艙駕一體,但座艙和智駕在很多地方要求會不一樣,比方說功能安全等級。這種時候我們就需要做多域隔離。在底層,比如BSP這一層,要做資源隔離引擎;在更上一層,需要去做基于資源隔離引擎的應用架構,然後基于它來做各種排程相關的任務。

基于中央計算平台,整個資料的通信模式會發生比較大的變化。現在常見的多SOC,會有很大的資料量去做SOC之間的互動,比如通過網絡、通過PCIE或者通過其他的一些通訊鍊路。中央計算平台下,資料通訊其實更多會往IPC的方式去發展。這就會要求整個軟體平台對于記憶體管理、對于IPC零拷貝,會提出更高的要求。我們現在也支援零拷貝,但更多是在SoC内。但基于做多域隔離之後,怎麼做記憶體管理,怎麼做零拷貝,可能是後面需要去優化的一個方向。

由于多個不同應用都在一個計算平台上運作,但各種計算核實際上是同一套。CPU相對會比較好處理,比方說,有8核或者16核,做多域隔離的時候,可以分别給2個核、4個核。但其他的一些計算資源,比方說DSP,GPU,BPU,可能不會按照核來劃分。這時候就需要有裝置虛拟化的能力,對不同的應用來說都是一個完整的裝置。這些裝置可能會使用不同數量的計算資源。我們可能會基于裝置虛拟化的技術,去做計算資源的管理。對于上層來說讓他能無感地進行使用,而不需要考慮太多應用的計算核的搶占。

最後,基于同一個計算平台,排程其實要求會比較高。前面有講到,我們現在看到已經有幾千個線程,再往後這個數量隻會更高。那在這種情況下就需要全局的排程能力。比方說你可能總共就8個核或16核,如果有4000或5000個線程,那花線上程切換上的代價會非常高。我們會真正的把上層的計算任務和底下的執行排程,去做分離和解耦。在全局上去做排程資源的配置設定,有效地把計算資源給利用起來。

以上是剛才提到的中央架構的演化對智能駕駛軟體開發範式的影響。

基于TogetheROS.Auto的智能駕駛軟體開發範式 | 地平線「你好,開發者」技術公開課全程實錄

另一個比較顯著的趨勢,就是整個智駕智能化的程度會越來越高。最開始我們做智駕的時候,相對來說AI占的比重會比較少。更多的是在感覺部分,做各種物體的感覺。但現在可以看到,AI模型的能力會越來越強,比方說BEV大模型或者Transformer。另外一部分,就是我們也會把越來越多的任務往AI核上放。比方說,規控有可能就直接在AI核上跑。是以,整個智駕的AI化程度顯著的提高。然後和一些同學聊的時候,也得到一個觀點,大家也在想後面整個智駕會不會就是一個AI大模型?前面資料結構,中間一個AI大模型,後面直接接對應的控制器。現在确實有這個趨勢。

我們前面有提DAG或者graphlet,可以看到它更多是一個在CPU上的純軟的graphlet的概念。但再往後,我們在SoC上不同的計算核越來越多,能力越來越強,整個應用的graphlet可能越來越多,直接在硬體上跑,那實際上整個graphlet可能會硬體化。有可能一個大graphlet,中間有很大一部分都是直接在不同的專用計算核上跑,比方說在BPU或者在DSP上。這種時候,它的排程邏輯、執行邏輯,和在純CPU上跑會非常不一樣,比方說不需要來回去做CPU的中斷,通信鍊路上也不需要在CPU上把資料來回倒騰。整個穩定性和性能其實會有非常顯著地提高。

對于開發平台來說,對于這種趨勢,我們可能需要設計合适的異構排程架構。然後和現有的排程架構融合起來,做無感地、平穩地過渡。

第三個點,剛才其實也有聊到,大家在說後面整個智駕會不會往大模型的方向去走,有可能智駕工程開發的内容會越來越少。現在,算法工程師和應用工程師其實工作分得還比較開:算法工程師去做算法的疊代、模型的效果,應用工程師來做整個應用的落地。後面這部分工作的區分,就不會那麼明顯。

對于整個開發平台來說,可能需要提供的一個能力,其實就是“原型即應用”。我們真正在做算法原型的時候,比方說我在x86上做算法原型,直接就可以在SoC上直接去跑,做到無感地切換。把裡面大量的通信排程相關東西,屏蔽在底層,上層的工程師可能就不必太關注。

整個應用的開發界面,可能就不會像現在這樣,基于C++,然後一個一個的coding,可能是基于一些DSL,甚至基于python的方式去做應用的開發。但底下執行可能是基于編譯器,或者基于一些轉換的工具,将它轉化為可高速執行的二進制檔案直接執行。

是以,整個智駕AI化程度越來越高,有可能算法和應用的分界會越來越不明顯。對于應用開發平台來說,怎麼樣去做算法開發、往應用開發過渡以及直接運作,也是我們在探索和讨論的一個點,希望和更多業界的同學有更廣泛地讨論。

關于發展趨勢,我先和大家分享這兩個點。當然,會有更多額外的内容,比方說GPT相關的内容,及Copilot相關的内容等等。這些對後面整個智駕開發的影響都會非常大,期待之後有機會和大家做更多的探讨。謝謝大家。

END

繼續閱讀