手把手教你執行apollo
一、Apollo的技術架構
Apollo是一套完整的自動駕駛技術方案,官方架構原圖的截圖較為模糊,這裡自己畫了一個簡單的四層結構,每層內的模組暫未畫出,因為不是本次入門的重點:
按照上圖,apollo自動駕駛分成四層技術棧,從下到上分別為:
1、Reference Vehicle Platform(參考車輛平臺)
自動駕駛最終都要落地到車上,因此apollo抽象了一個”參考車輛平臺”層,通過電子化的方式控制車輛的行駛行為。
Note: 在開發者大會上,百度展示了由美國創業公司AutonomouStuff基於Apollo 1.0開放平臺改裝而成的循跡自動駕駛車,這輛車是一輛美系的林肯MKZ。也就是說當前釋出的Apollo適配林肯MKZ是沒有問題的。 但這款中型車對於普通開發者來說門檻算是稍高了。如果百度能拿出一款大眾系、豐田系或至少也應該是一個本田系這樣的車型,那對自動駕駛領域的開發者或者說愛好者來說,才是福利。相比而言,著名黑客George Hotz創立的自動駕駛技術公司comma.ai為其openpilot初始選用的車型則是Honda系的思域和CR-V,濫大街的車型,容易搞到,且低成本搞到,也容易改裝。
2、Reference Hardware Platform(參考硬體平臺)
這一層為自動駕駛汽車提供計算、感知、互動的硬體能力,包括計算單元(車載處理器裝置)、GPS/IMU(慣性測量裝置)、攝像頭、鐳射雷達、聲波雷達、HMI(人機介面)等。在釋出的Apollo 1.0版本中,開放的硬體能力包括:計算單元、GPS/IMU(慣性測量裝置)以及HMI。
3、Apollo open software Platform (開放軟體平臺)
這一層是百度Apollo 1.0開放的核心部分,見下圖(藍色的代表在apollo 1.0.0中已經開放的能力):
從圖中看到,這一層還可以分為三個子層,從下至上分別是:
- apollo kernel層
這一層是運行於硬體上面的OS,對於自動駕駛這種實時性要求特別強的領域,這裡顯然只能是RTOS(實時作業系統)。Apollo 1.0開放的原始碼中包含一個”Apollo Kernel“的專案,在這個專案下彙集著可以滿足實時性需求的OS kernel。當然目前還僅有一個選擇:realtime linux kernel。這是apollo基於Linux Kernel 4.4.32+realtime patch定製的一款專用linux核心。
- apollo platform 層
在Kernel層的上面就是 apollo 的 runtime framework了,提供 platform 級的支撐。Apollo 1.0同樣也建立了一個專用專案:apollo-platform,用於彙集滿足apollo平臺級支撐需求的platform。當前該專案下也僅提供了一種選擇:Apollo ROS,是基於ROS1的Indigo版二次開發後的定製版ROS。Apollo ROS基於自動駕駛需求出發,對ROS1主要做了三方面改進:
- 為優化自動駕駛大量使用感測器引發很大的傳輸頻寬需求, Apollo ROS改變基於socket的網路傳輸模式,大量採用共享記憶體的node間通訊機制,減少傳輸中的資料拷貝,顯著提升傳輸效率, 尤其是在滿足一對多的傳輸場景下效果明顯;
- 從魯棒性出發,使用RTPS(Real-Time Publish Subscribe)服務發現協議實現完全的P2P網路拓撲,避免原ROS的以Master作為拓撲網路的中心的單點故障問題;
- 使用protobuf替代原ROSmessage,提供很好的向後相容,避免介面升級後,不同版本的模組難以相容的問題。
其實第二點改進也是ROS2正在做的事情。
- apollo modules層
在這一層是apollo的功能modules,當前似乎依舊是基於ROS的package開發的,在github.com/ApolloAuto/apollo/modules/common/apollo_app.cc你大致能看出來一個ROS Package的開發模板。這一層提供諸如:規劃(planning)、洞察(perception)、控制(control)、預測(prediction)、決策(decision)、定位等諸多功能。但Apollo 1.0僅僅開放了Control、Localization和HMI三個module,因為這三塊足以構成Apollo 1.0提供的封閉場地循跡駕駛體系了。
4、Cloud Services(雲端服務)
Apollo 1.0還開放了雲端資料平臺,以及喚醒萬物的DuerOS能力。DuerOS也是Baidu人工智慧戰略的重要棋子,似乎也是目前Baidu在AI方面最為成熟的、應用最廣的產品。當然這一層還包括模擬、高精度地圖等服務,不過目前尚未開放。
二、上手Apollo
買不起林肯MKZ的童鞋也不要擔心,Apollo 1.0提供了一個本地模擬工具,給你一個與Apollo親密接觸的途徑,讓你可以在PC上肆無忌憚地玩耍,畢竟Apollo 1.0僅提供封閉場地的尋跡能力,相對簡單。
我們的重點是Apollo open software Platform這一層,而這一層中,我們不關心apollo kernel,只關心Apollo ROS和三個已經開放的apollo modules。
1、下載release版本
截至目前為止,Apollo僅釋出了一個版本:apollo-v1.0.0,我們可以從github上將其下載到本地:
2、本地原始碼構建
對於基於Apollo這個framework的開發者,Apollo官方強烈建議直接採用官方預定義好的專用docker環境(for dev)。對於愛折騰的我而言,必須要在本地做一次原始碼構建,即使這個體驗是糟糕的,甚至最終是失敗的^0^。原始碼構建的命令很簡單,一行即可:
在這個過程中,我遇到了兩個錯誤:
- bazel不存在
Apollo的構建依賴google出品的bazel構建工具,我個人對bazel並沒有什麼研究,這裡先裝上再說:
- third_party/ros/setup.bash: No such file or directory
apollo的編譯要依賴ros,但apollo並沒有自帶ros。我們需要到apollo platform那個專案中去下載Apollo ROS:
# wget -c https://github.com/ApolloAuto/apollo-platform/releases/download/1.0.0/ros-indigo-apollo-1.0.0.x86_64.tar.gz
# tar zxvf ros-indigo-apollo-1.0.0.x86_64.tar.gz
# cd ros
# ls -F
bin/ BUILD env.sh* etc/ include/ lib/ setup.bash setup.sh _setup_util.py* setup.zsh share/
將下載的ros目錄copy到apollo-1.0.0/third_party下,並chmod +x third_party/ros/setup.bash。
我們再次執行bash apollo.sh build,這次執行前面的error和warning基本都消失了,apollo.sh指令碼開始下載依賴包並編譯:
# bash apollo.sh build
ROS_DISTRO was set to 'kinetic' before. Please make sure that the environment does not mix paths from different distributions.
[WARNING] ESD CAN library supplied by ESD Electronics does not exit.
[WARNING] If you need ESD CAN, please refer to third_party/can_card_library/esd_can/README.md
.
____Loading package: modules/common/util/testing
____Loading package: @com_github_grpc_grpc//
____Loading package: @google_styleguide//
____Loading package: @glog//
____Loading package: @eigen//
____Loading package: @gtest//
____Loading package: @civetweb//
____Loading package: @com_github_google_protobuf//
____Loading package: @websocketpp//
____Loading package: @curlpp//
Building on x86_64, with targets:
//tools/platforms:x86_64
//tools/platforms:aarch64
//modules/prediction:prediction
//modules/prediction:prediction_lib
... ...
//modules/common:log
//modules/canbus/proto:canbus_proto.pb
//:x86_64
//:arm64
WARNING: Running Bazel server needs to be killed, because the startup options are different.
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 2,750,374 bytes
INFO: Cloning https://github.com/madler/zlib: Receiving objects (3309 / 5016)
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 2,773,664 bytes
INFO: Cloning https://github.com/madler/zlib: Receiving objects (3314 / 5016)
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 2,795,584 bytes
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 13,504,198 bytes
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 13,522,008 bytes
INFO: Found 190 targets...
[34 / 41] Compiling external/com_github_google_protobuf/src/google/protobuf/compiler/java/java_message_lite.cc [for host]
[41 / 48] Compiling external/com_github_google_protobuf/src/google/protobuf/compiler/command_line_interface.cc [for host]
[157 / 163] Compiling external/com_github_google_protobuf/src/google/protobuf/compiler/javanano/javanano_enum.cc [for host]
[752 / 756] Compiling external/com_github_grpc_grpc/src/core/ext/client_config/resolver_result.c
ERROR: /root/test/apolloauto/apollo-1.0.0/modules/canbus/BUILD:32:1: Linking of rule '//modules/canbus:canbus' failed: gcc failed: error executing command /usr/bin/gcc -o bazel-out/local-dbg/bin/modules/canbus/canbus '-Wl,-rpath,$ORIGIN/../../_solib_k8/_U_S_Sthird_Uparty_Sros_Cros_Ucommon___Uthird_Uparty_Sros_Slib' ... (remaining 8 argument(s) skipped): com.google.devtools.build.lib.shell.BadExitStatusException: Process exited with status 1.
modules/canbus/main.cc:21: error: undefined reference to 'ros::init(int&, char**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)'
third_party/ros/include/ros/publisher.h:107: error: undefined reference to 'ros::console::initializeLogLocation(ros::console::LogLocation*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ros::console::levels::Level)'
... ...
collect2: error: ld returned 1 exit status
INFO: Elapsed time: 578.172s, Critical Path: 26.62s
============================
[ERROR] Build failed!
[INFO] Took 597.189 seconds
============================
經過漫長的等待後,還是以失敗告終。並且C++的錯誤輸出分析起來真是好痛苦,於是暫時放棄本地原始碼編譯。
3、pre-specified Docker dev環境
既然apollo已經為我們準備好了pre-specified Docker dev環境,我們不妨用一下,下載和啟動該環境可以用下面命令:
apolloauto/apollo:dev-latest這個image超級龐大,大約有7個G左右,所以你需要耐心等待一會兒了。docker執行起來後,我們在另外一個terminal windows下可以執行下面命令切入到該docker容器內部:
在dev container中,我們可以來編譯一下apollo原始碼:
由於dev環境中相關的依賴已經就緒,因此無需過多幹預,在漫長的一段等待後,我們看到編譯ok了。
4、執行apollo demo
在dev enviroment中或apollo:release-latest中,我們都可以執行apollo的一個尋跡小車的demo。以apollo:release-latest image環境為例:
在容器中啟動HMI(human-machine interface):
可以看到,hmi.sh指令碼啟動了roscore(ros master節點和相關服務)以及hmi的service,我們開啟瀏覽器,輸入:http://host_ip:8887即可看到如下場景:
在容器內繼續執行如下命令,回放小車的軌跡資料:
我們開啟hmi頁面上的Debug開關,點選右上角的”Dreamview”按鈕,稍後片刻,你就會在新開啟的頁面上看到小車模擬尋跡行駛的場景了:
三、小結
Baidu為apollo專案做了一個4年的規劃(見下面的roadmap),並計劃在2020年實現全路網自動駕駛,這個說法似乎有意避開了自動駕駛的級別,這個2020目標到底是L4呢還是L5呢?不過無論是L4還是L5,這個目標都十分有挑戰啊。
個人覺得:未來的L4、L5級別的自動駕駛一定不光光是依靠車輛自身的裝置與演算法,還要與道路基礎設施相配合去實現。甚至是依賴車與車之間的通訊才能做到全天候、全路況的自動駕駛。apollo雖然邁出了第一步,但任重道遠,讓我們拭目以待吧!