緒論
SLAM(同步定位和地圖繪制)在自動駕駛、AGV 和無人機等各種應用中引起了人們的廣泛關注。盡管目前有很多優秀的 SLAM 項目可以參考,但是他們的復雜性(高性能)及依賴性(依賴于許多外部庫),使得它們無法移植到簡單的平臺(例如嵌入式系統)。
該項目更加重視簡潔的算法和更少的依賴性。很多不開源的庫也將被刪除。另一方面,利用FPGA加速來達到實時的處理速度。
功能
10 FPS實時運行
閉環檢測
3D占用網格地圖生成
通過 USB 3.0 連接進行實時監控
軟件和硬件的所有設計文件均開源
GitHub
項目很復雜,感興趣的不會太多,提前放出代碼
bin --- 預構建的二進制文件
doc---相關文件
src --- 源文件
vivado --- Vivado 工程目錄
系統概覽
系統級框圖如下所示。
傳感器板
傳感器板連接到FPGA開發板( Ultra96-V2 )以捕獲立體圖像。該板硬件是開源的,開源鏈接如下:
該板包含雙 CMOS 圖像傳感器和兩個 mikroBUS 。
在兩個mikroBUS站點中的一個站點上安裝了一個帶有內置LED(按鈕G點擊)的單按鈕開關的模塊,用于在獨立模式下控制系統。IMU模塊也已安裝,但未在本項目中使用。
圖像格式為 640x480 ,30 FPS。然后將幀速率降低到 FPGA 內的所需速率。
遷移到其他傳感器板
該傳感器板的設計符合 Ultra96-V2 規范。如果其他傳感器板也符合這些規范,則應該可以遷移到其他傳感器板。圖像傳感器配置為 640x480 分辨率和 30 FPS。一個按鈕開關和一個 LED 連接到 FPGA。
FPGA
圖像傳感器連接到 FPGA(或可編程邏輯,PL端)。用于立體視覺的圖像處理,如立體校正和塊匹配(stereo rectification 和 block matching)。FPGA也被用作一些功能的硬件加速。
遠程申請
裸機應用程序在兩個 R5 處理器之一上運行,用來控制 FPGA。此應用程序在本文中也稱為“遠程應用程序”。此應用程序與 Linux 應用程序協同工作。此應用程序還控制 USB 3.0 連接,因此如果板卡連接到 Windows PC,此系統就像是具有某些立體視覺功能的 USB 網絡攝像頭一樣工作。
Linux應用
Petalinux 系統建立在四個 A53 處理器上。在該系統上運行處理 SLAM 相關操作的應用程序。該應用程序在本文中稱為“Linux 應用程序”。
Petalinux 系統以 SMP(Symmetric Multiprocessing)模式運行。這意味著工作負載由 Linux 系統分配給每個處理器。
處理器間通信 (IPC)
這兩個應用程序通過在 FPGA 中實現的內存映射寄存器相互通信。這些寄存器由“消息”寄存器和“參數”寄存器組成。處理器在“消息”寄存器中寫入特定的消息 ID 以通知對方。另一個 CPU 輪詢“消息”寄存器并做出適當的響應。如有必要,可以發送四個 32 位參數。
調試電腦
調試電腦用于監控板子的狀態。除了通過 UART 進行的調試功能外,還可以通過 USB 3.0 連接實時查看視頻處理中的立體圖像。當連接到 Windows PC 時,此系統被視為 UVC(USB Video Class)設備,因此不需要特殊的設備驅動程序。
內存映射
FPGA開發板上有 2GB 的物理內存。該區域的前 3 / 4 被 Linux 系統使用。另一個保留給遠程應用程序。
開發環境
主要開發在 Windows 上執行,但 Petalinux 開發需要 Linux 環境。所以使用VirtualBox在Windows 10上虛擬搭建一個Linux環境。
此項目需要安裝兩個 Vitis 。Windows 上的一個用于遠程應用程序開發,另一個用于 Linux 應用程序。
開發階段
嵌入式系統的開發比較麻煩,所以需要劃分為三個階段。
第 1 階段是在 Windows上進行純軟件解決方案開發。這個階段對于軟件開發是最有效的。算法的性能也在這個階段得到了驗證。
在第 2 階段,軟件被移植到運行在開發板板上的 Petalinux 系統。在這個過渡階段,注意軟件源代碼是相同的。板載 SD 卡用于存儲數據。
在最后階段,一些功能被FPGA電路和控制FPGA的裸機應用所取代。一些功能還應用了硬件加速,以進一步減少處理時間。
算法(傳感器數據采集)
立體校正
立體校正過程將左右圖像在同一平面上進行變換,并使它們水平對齊。立體校正在 FPGA 內部實時執行,然后在存儲到 DDR 內存之前進行雙線性插值。
為了使 FPGA 電路更簡單,支持信息由軟件預先生成。此信息包括要處理的數據的位置和長度,并按到達時間的順序排序。
立體校正參數通過 OpenCV 函數獲得,該函數使用 7x5 棋盤圖案實現 Bouguet 算法。這些參數保存在 XML 文件中并存儲在 SD 卡上。
當前的實現忽略了鏡頭畸變,因為使用的圖像傳感器幾乎沒有畸變,而試圖消除它們的畸變會導致圖像產生更多畸變。
X-Sobel 濾波器
X-Sobel 濾波器用作塊匹配的預處理,結果存儲在 DDR 內存中。
塊匹配
塊匹配搜索立體圖像對之間的視覺對應關系。立體校正后,左圖中的一個位置出現在右圖中同一行的左側。源圖像中每個像素的這些差異形成了密集的深度圖。
塊匹配是通過移植OpenCV的StereoBM功能在FPGA中實現的。塊匹配所需的計算量非常大,但可以通過 OpenCV 中實現的“滑動窗口”技術來減少。為了進一步減少處理時間,FPGA 并行計算 32 個視差。
GFTT探測器
GFTT(Good Features To Track)用于檢測關鍵點。關鍵點是圖像中通常包含角的獨特部分。
該算法與OpenCV的goodFeaturesToTrack函數相同,但部分函數移植到FPGA中實現,以減少軟件處理時間。
該功能由以下步驟組成。
應用XY-Sobel濾波器提取邊緣
計算特征值量化角點的尖銳度
對特征值應用閾值并選擇好的關鍵點
步驟1和步驟2需要對圖像中的每個像素都進行計算,計算量較大,因此采用FPGA實現。
ORB 描述符生成器
ORB(Oriented FAST and Rotated BRIEF)特征描述符用于量化檢測到的關鍵點的視覺唯一性。同一物體的關鍵點具有相似的描述符,因此即使比例和角度略有不同,我們也可以從不同的圖像幀中搜索同一物體的關鍵點。
實際計算由 OpenCV 函數執行。每個 ORB 描述符都是一個 256 位的二進制字符串。
算法(SLAM)
SLAM 算法是根據RTAB-Map中實現的 F2F 算法構建的。
坐標
該項目涉及兩個坐標系。它們是圖像坐標和world (或者 robot)坐標。
這兩個都是右手坐標系,所以一個簡單的旋轉矩陣R就可以在它們之間進行轉換。源圖像在圖像坐標中捕獲。然后將計算出的相機位姿轉換為world 坐標。
視覺里程計Visual Odometry
視覺里程計計算連續圖像幀期間相機姿勢的轉換。
該算法由以下階段組成。
1.關鍵幀選擇
實際視覺里程計是在關鍵幀和新圖像幀之間計算的。使用關鍵幀的原因是為了減少累積每一幀的測距誤差,尤其是當相機靠近固定位置時。當匹配的關鍵點數量低于閾值時,關鍵幀將被更新。
2. 關鍵點匹配
關鍵點在兩個圖像幀之間匹配。通過比較關鍵點的 ORB 描述符來計算相似度。以前的相機姿勢(如果可用)用于縮小搜索范圍。此階段的輸出是匹配關鍵點的 ID 及其 2D/3D 位置。
3.運動估計
解決 PnP 問題以計算相機的旋轉和平移,從而最大限度地減少兩者之間的誤差
投影到當前圖像平面上的參考幀中關鍵點的 3D 位置,以及當前幀中關鍵點的二維位置。
輸出是相機的相對運動。它在圖像坐標中計算,然后轉換為world坐標。
在這個項目中,相機姿勢是使用圖表來描述的。估計的相機姿勢和運動分別作為節點和鏈接添加到圖中。
視覺關鍵詞Visual Word Dictionary
視覺關鍵詞包含視覺詞,它們實際上是分配有唯一 ID 的 ORB 描述符。每次新的圖像幀到達時,該幀中包含的 ORB 描述符都會與現有的視覺詞相匹配。如果它與現有單詞匹配,則增加該單詞的引用計數器。如果不是,則描述符被分配一個新的 ID 并成為一個新的視覺詞。
視覺詞的數量隨時間增加。與所有現有的視覺詞匹配實際上是這個應用程序中最耗時的過程。為了讓軟件實時運行,這個計算在一個單獨的線程中處理。因為閉環檢測不一定在每一幀中運行,所以這一操作很有效,。
閉環檢測
閉環檢測是識別先前訪問過的場景并向該節點添加另一個鏈接。
向圖形添加閉環鏈接可以通過兩種方式減少圖形錯誤。
添加閉環鏈接時會重建圖。在這個過程中,連接了從起始節點到結束節點的最短路徑。這將消除循環期間累積的里程計誤差。
閉環鏈接將為圖形添加額外的約束。通過最小化由此類約束引起的誤差,將提高估計姿勢的準確性。
默認情況下,閉環檢測每 5 幀運行一次。最新的 30 幀也將被忽略。這些抽取是為了消除相鄰節點被接受為閉環,因為它們對圖優化幾乎沒有貢獻。
每當一個新的圖像幀到達時,TF-IDF(詞頻-逆文檔頻率)分數就會通過查閱視覺詞典來計算其他圖像幀的分數。當更多的單詞包含在共同點時,這個分數會更高,并且單詞越稀有。
選擇具有最高 TF-IDF 分數的圖像幀作為閉環的候選者。然后,在兩個圖像幀之間執行類似于視覺里程計中的運動估計。當重投影誤差低于閾值時,該鏈接被接受為閉環鏈接并添加到圖中。
圖形優化
當閉環鏈接向圖形添加額外約束時,會出現差異,從而導致圖形中出現錯誤。通過最小化此類錯誤,可以提高圖表的準確性。
在這個項目中,只估計相機位姿。這稱為“姿態調整”,與“束調整”相對,后者估計相機姿態和觀察點的 3D 坐標。
這類問題可以通過最小化這種形式的成本函數 F(x) 來解決。
這里 eij 被定義為位姿 xi 和 xj 之間的誤差向量,而 zij 是它們之間的約束。Ω為信息矩陣,由重投影誤差的協方差的倒數得到。
F(x) 的一階近似值通過圍繞 x 初始值的泰勒級數展開如下給出。
Jij 是關于 xi 和 xj 的雅可比矩陣。
F(x) 由 x 最小化,x 是通過求解以下等式獲得的,其中 λ 是傾銷因子。
將 Δx 添加到初始值以更接近最優解。
雅可比計算遵循g2o的實現(https://github.com/RainerKuemmerle/g2o)。原始相機姿態包括旋轉矩陣,它們不能直接放入方程中,因為它們是一種過度參數化的表示。在這個項目中,歸一化四元數的軸用作最小表示。這也遵循 g2o 的實現,因此我們可以對雅可比矩陣使用相同的計算。因此相機姿勢將是 6 個元素的向量。
假設我們有 N 個節點,那么 H 的大小是 6N x 6N,向量 b 是 6N。矩陣 H 可以非常大,但其元素大部分為零,因為 H 僅在對應節點之間存在約束的情況下才為非零。因此,將 H 視為稀疏矩陣是有利的。構建稀疏矩陣和求解方程由Eigen執行,SimplicialLDLT 作為稀疏線性求解器。
占用網格圖
3D 占用網格圖是從優化的位姿圖和密集的深度圖生成的。地圖的實際生成由Octomap執行。結果以“二叉樹(.bt)”格式存儲在 SD 卡上。
表現
KITTI 數據集在驗證算法時用作參考。
準確性
下圖是用KITTI數據集序列00模擬時的軌跡鳥瞰圖。
在此仿真中,主要在 5 個區域檢測到閉環,平移和旋轉誤差分別為 0.91% 和 0.0038 度/米。
請注意,此結果僅顯示算法的性能,因為此仿真中使用的圖像是由不同的圖像傳感器捕獲的。
3D 占用網格地圖
下圖是在上述模擬中生成并由octovis顯示的 3D 占用網格圖。密集深度圖的分辨率在兩個方向上都降低了 1 / 4,然后在通過 Octomap 構建體素圖之前通過估計的相機姿勢進行投影。
處理時間
下圖顯示了處理圖像傳感器輸入時應用程序和 FPGA 主線程的處理時間。
視覺關鍵詞更新和閉環檢測在應用程序的子線程中運行。處理時間隨著視覺詞的數量增加,如下所示。
時隙為 500 毫秒,因為它們每 5 幀運行一次。當處理時間超過這個時隙時,下一次執行將推遲到上一個線程完成,這樣就不會干擾視覺里程計的實時運行。
內存消耗
下圖顯示了在 Windows 上處理 KITTI 數據集序列 00 時的內存消耗(僅顯示前 1700 幀)。內存消耗隨著時間的推移而增加,其中大部分是密集的深度圖和視覺詞。當應用程序運行在FPGA上時,這塊內存占用了Linux控制的內存空間,限制了連續運行的時間。
FPGA利用率
下表顯示了 FPGA 資源利用率。FPGA設備是 XCZU3EG-SBVA484-1-I。
如何復現
先決條件
Xilinx Tools 2020.2 必須安裝在兩個平臺(Ubuntu和Windows)上。
Petalinux 2020.2 必須安裝在 Ubuntu 上。
假定 Xilinx Tools 安裝到 Ubuntu 上的 [XILINX_DIR]。
假定 git 中的必要文件已復制到兩個平臺。
下載 Eigen 3.4.0 并將其放置在“slam/include”目錄下,目錄結構如下:
?
slam ?└─include ???????└─Eigen
?
硬件
傳感器板的擴展接口是開漏電路,不能直接控制開關和LED。因此,在 Button G click board 上需要進行以下修改。
構建 FPGA 項目(在 Windows 上)
git文件中已經構建好項目。
“dvp”項目
啟動 Vivado,并在“Tcl Console”中鍵入以下命令。
?
cd?[WORK_DIR]/U96-SLAM/vivado source?create_dvp.tcl
?
? 將創建名為“dvp”的項目。
點擊“工具→創建并打包新IP...”,打開“創建并打包新IP”對話框。繼續進行以下設置。
?
[Create?Peripheral,?Package?IP?or?Package?a?Block?Design] ??Packaging?Options:?Package?your?current?project [Package?Your?Current?Project] ??IP?location:?[WORK_DIR]/U96-SLAM/src/ip_repo/dvp
?
出現提示時選擇“是”,然后單擊“完成”。
將出現“Package IP - dvp”。
選擇“Review and Package”,點擊“Package IP”。
? “dvp”的 IP 源將導出到“ip_repo/dvp”目錄。
關閉“dvp”項目。
“fpga_top”項目
啟動 Vivado,并在“Tcl Console”中鍵入以下命令。
?
cd?[WORK_DIR]/U96-SLAM/vivado source?create_fpga_top.tcl
?
? 將創建名為“fpga_top”的項目。
雙擊“Sources”面板中的“Design Sources→design_1_wrapper→design_1_i”,打開“design_1.bd”框圖。
如果“/dvp_0 block in this design should be upgraded.” 顯示在窗口頂部,單擊“Report IP Status”,然后單擊“Upgrade Selected”。只有當修改了“dvp”模塊時才會發生這種情況。
單擊 Flow Navigator 中的“Generate Bitstream”。
? “design_1.bit”將在“fpga_top.runs/impl_1/”目錄中創建。
單擊“File→Export→Export Hardware”打開“Export Hardware Platform”對話框。繼續進行以下設置。
?
[Output] ??Include?bitstream:?Selected [Files] ??XSA?file?name:?design_1_wrapper ??Export?to:?[WORK_DIR]/U96-SLAM/vivado/fpga_top
?
? “design_1_wrapper.xsa”將在指定目錄中創建。
構建裸機應用程序(在 Windows 上)
只有在修改裸機應用程序時才需要此項目。“StereoBM.elf”已經包含在 git 存儲庫中。
在“[WORK_DIR]/U96-SLAM”下創建名為“vitis”的目錄。啟動 Vitis,將此目錄設置為 Vitis Workspace,然后單擊“Launch”。
?
[WORK_DIR]/U96-SLAM/vitis
?
單擊“Create Application Project”以打開“新建應用程序項目”對話框。繼續進行以下設置。注意選擇R5處理器。
?
[Platform] ??Create?a?new?platform?from?hardware?(XSA) ??XSA?File:?[WORK_DIR]U96-SLAMvivadofpga_topdesign_1_wrapper.xsa ??Target?processor?to?create?FSBL:?psu_cortexr5_0 [Application?Project?Details] ??Application?project?name:?StereoBM ??Target?processor:?psu_cortexr5_0 [Domain] ??Remain?as?default [Templates] ??SW?development?templates:?Empty?Application
?
單擊“完成”。
? 將創建“StereoBM_system”項目。
在“Application Project Settings”中,單擊“Navigate to BSP Settings”。
點擊“Board Support Package”中的“Modify BSP Settings...”?!鞍寮壷С职O置”對話框將打開。
點擊“Overview→standalone”,進行如下修改。
?
stdin:?psu_uart_1 stdout:?psu_uart_1
?
這是必要的,因為 uart_1 在 開發板中用作標準輸入/輸出。
在“Explorer”中右鍵單擊“StereoBM_system→StereoBM→src”,然后從菜單中單擊“Import Sources...”以打開“Import Sources”對話框。繼續進行以下設置。
?
From?directory:?[WORK_DIR]/U96-SLAM/src/StereoBM/src Select?All:?click
?
單擊“完成”。
在資源管理器窗格中選擇“StereoBM”,然后通過單擊 Hammer 圖標旁邊的箭頭圖標選擇“Release”構建。
? “StereoBM.elf”將在“Release”目錄中生成。
構建“StereoBM_system”而不是“StereoBM”也會生成 ROM 引導文件。
構建 Petalinux 系統(在 Ubuntu 上)
配置系統
獲取 Petalinux 環境。
?
source?[XILINX_DIR]/petaLinux-2020.2/bin/settings.sh
?
通過鍵入以下命令創建“petalinux”項目。
?
cd?[WORK_DIR]/U96-SLAM petalinux-create?--type?project?--template?zynqMP?--name?petalinux cd?petalinux/
?
? “petalinux”目錄將在 [WORK_DIR]/U96-SLAM/” 下創建。
將“design_1_wrapper.xsa”復制到“U96-SLAM/vivado”目錄。如果沒有更改 FPGA 設計,則在 git 存儲庫的“U96-SLAM/bin”目錄中提供預構建文件。
如下配置 Petalinux 系統。
以下“petalinux-xxxx”命令必須在“petalinux”目錄中發出。
?
petalinux-config?--get-hw-description?../vivado
?
“misc/config 系統配置”對話框將打開。進行以下設置,然后“退出”。
?
Subsystem?AUTO?Hardware?Settings?→?Serial?Settings?→ ??PMUFW?Serial?stdin/stdout?:?psu_uart_1 ??FSBL?Serial?stdin/stdout:?psu_uart_1 ??ATF?Serial?stdin/stdout:?psu_uart_1 ??DTG?Serial?stdin/stdout:?psu_uart_1 DTG?Settings?→?MACHINE_NAME:?avnet-ultra96-rev1 Image?Packaging?Configuration?→?Root?filesystem?type:?EXT4?(SD/eMMC/SATA/USB)
?
以下命令第一次運行可能需要很長時間。
?
petalinux-config?-c?kernel “Linux/arm64?5.4.0?內核配置”對話框將打開。進行以下設置,然后“退出”。 Enable?loadable?module?support?[*]?(default) Networking?support?→?Bluetooth?subsystem?support?> Device?Drivers?→?Remoteproc?drivers?→ ??Support?for?Remote?Processor?subsystem?[*]?(default) ??ZynqMP_r5?remoteproc?support??(default) ??
?
最后,鍵入以下配置命令。
?
petalinux-config?-c?rootfs
?
“Configuration”對話框將打開。進行以下設置,然后“退出”。
?
Filesystem?Packages?→ ??libs?→?libmetal?→?libmetal?[*] ??misc?→?gdb?[*]?(for?debug?purpose) ???????→?sysfsutils?→?libsysfs?[*] Petalinux?Package?Groups?→ ??packagegroup-petalinux-openamp?→?packagegroup-petalinux-openamp?[*] ??packagegroup-petalinux-opencv?→?packagegroup-petalinux-opencv?[*] Image?Features?→?auto-login?[*]
?
在“[WORK_DIR]/U96-SLAM/petalinux/project-spec/meta-user/recipes-bsp/device-tree/files/”中打開“system-user.dtsi”并復制并粘貼以下文本。
?
/include/?"system-conf.dtsi" /?{ reserved-memory?{ ????????#address-cells?=?<2>; ????????#size-cells?=?<2>; ????????ranges; ????????rproc_0_dma:?rproc@0x6ed00000?{ ????????????no-map; ????????????compatible?=?"shared-dma-pool"; ????????????reg?=?<0x0?0x6ed00000?0x0?0x00100000>; ????????}; ????????rproc_0_reserved:?rproc@0x5ed00000?{ ????????????no-map; ????????????reg?=?<0x0?0x5ed00000?0x0?0x10000000>; ????????}; ????}; ????zynqmp-rpu?{ ????????compatible?=?"xlnx,zynqmp-r5-remoteproc-1.0"; ????????#address-cells?=?<2>; ????????#size-cells?=?<2>; ????????ranges; ????????core_conf?=?"split"; ????????r5_0:?r5@0?{ ????????????#address-cells?=?<2>; ????????????#size-cells?=?<2>; ????????????ranges; ????????????memory-region?=?<&rproc_0_reserved>,?<&rproc_0_dma>; ????????????pnode-id?=?<0x7>; ????????????mboxes?=?<&ipi_mailbox_rpu0?0>,?<&ipi_mailbox_rpu0?1>; ????????????mbox-names?=?"tx",?"rx"; ????????????tcm_0_a:?tcm_0@0?{ ????????????????reg?=?<0x0?0xFFE00000?0x0?0x10000>; ????????????????pnode-id?=?<0xf>; ????????????}; ????????????tcm_0_b:?tcm_0@1?{ ????????????????reg?=?<0x0?0xFFE20000?0x0?0x10000>; ????????????????pnode-id?=?<0x10>; ????????????}; ????????}; ????}; ????zynqmp_ipi1?{ ????????compatible?=?"xlnx,zynqmp-ipi-mailbox"; ????????interrupt-parent?=?<&gic>; ????????interrupts?=?<0?29?4>; ????????xlnx,ipi-id?=?<7>; ????????#address-cells?=?<1>; ????????#size-cells?=?<1>; ????????ranges; ????????/*?APU<->RPU0?IPI?mailbox?controller?*/ ????????ipi_mailbox_rpu0:?mailbox@ff90000?{ ????????????reg?=?<0xff990600?0x20>, ??????????????????<0xff990620?0x20>, ??????????????????<0xff9900c0?0x20>, ??????????????????<0xff9900e0?0x20>; ????????????reg-names?=?"local_request_region", ????????????????????????"local_response_region", ????????????????????????"remote_request_region", ????????????????????????"remote_response_region"; ????????????#mbox-cells?=?<1>; ????????????xlnx,ipi-id?=?<1>; ????????}; ????}; ????chosen?{ ????????bootargs?=?"console=ttyPS0,115200?root=/dev/mmcblk0p2?rw?earlyprintk?rootfstype=ext4?rootwait?uio_pdrv_genirq.of_id=generic-uio?devtmpfs.mount=1?earlycon"; ????}; }; &dvp_0?{ ??compatible?=?"generic-uio"; };
?
該文件聲明使用遠程處理器并保留其內存空間。該文件還將FPGA內部的“dvp”模塊設置為“generic-uio”設備,以便我們可以使用內置的“generic-uio”設備驅動程序訪問它。
自動運行應用程序
以下過程將使我們的應用程序在系統啟動時自動運行。
?
petalinux-create?-t?apps?--template?install?-n?myinit?--enable
?
? “myinit”目錄將在“project-spec/meta-user/recipes-apps”下創建。
將以下文本復制并粘貼到“myinit.bb”和“files/myinit”。
【myinit.bb】
?
# #?This?file?is?the?myapp-init?recipe. # SUMMARY?=?"Simple?myinit?application" SECTION?=?"PETALINUX/apps" LICENSE?=?"MIT" LIC_FILES_CHKSUM?=?"file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" SRC_URI?=?"file://myinit? ?" S?=?"${WORKDIR}" FILESEXTRAPATHS_prepend?:=?"${THISDIR}/files:" inherit?update-rc.d INITSCRIPT_NAME?=?"myinit" INITSCRIPT_PARAMS?=?"start?99?S?." do_install()?{ ?install?-d?${D}${sysconfdir}/init.d ?install?-m?0755?${S}/myinit?${D}${sysconfdir}/init.d/myinit } FILES_${PN}?+=?"${sysconfdir}/*"
?
【文件/myinit】
?
#!/bin/sh cd?~/home/root ./run
?
這些文件使“myinit”成為一個啟動應用程序,它將在“home/root”目錄中執行“run”腳本。
構建 Petalinux
現在我們可以通過以下命令構建 Petalinux 系統。
“petalinux-build”命令可能需要很長時間。
?
petalinux-build
?
第一次會出現錯誤消息,說明設備樹中存在錯誤。然后,打開以下目錄中的“pl.dtsi”,刪除mipi_csi_rx_subsyst_0和mipi_csi_rx_subsyst_1條目。
?
“[WORK_DIR]/U96-SLAM/petalinux/components/plnx_workspace/device-tree/device-tree/pl.dtsi”
?
生成的文件應如下所示。
【pl.dtsi】
?
/?{ ?amba_pl:?amba_pl@0?{ ??#address-cells?=?<2>; ??#size-cells?=?<2>; ??compatible?=?"simple-bus"; ??ranges?; ??dvp_0:?dvp@a0000000?{ ???clock-names?=?"s00_axi_aclk",?"m00_axi_aclk"; ???clocks?=?<&zynqmp_clk?71>,?<&zynqmp_clk?71>; ???compatible?=?"xlnx,dvp-1.0"; ???interrupt-names?=?"intr"; ???interrupt-parent?=?<&gic>; ???interrupts?=?<0?89?4>; ???reg?=?<0x0?0xa0000000?0x0?0x10000>; ???xlnx,m00-axi-addr-width?=?<0x20>; ???xlnx,m00-axi-aruser-width?=?<0x0>; ???xlnx,m00-axi-awuser-width?=?<0x0>; ???xlnx,m00-axi-burst-len?=?<0x10>; ???xlnx,m00-axi-buser-width?=?<0x0>; ???xlnx,m00-axi-data-width?=?<0x20>; ???xlnx,m00-axi-id-width?=?<0x1>; ???xlnx,m00-axi-ruser-width?=?<0x0>; ???xlnx,m00-axi-target-slave-base-addr?=?<0x40000000>; ???xlnx,m00-axi-wuser-width?=?<0x0>; ??}; ??misc_clk_0:?misc_clk_0?{ ???#clock-cells?=?<0>; ???clock-frequency?=?<200000000>; ???compatible?=?"fixed-clock"; ??}; ??misc_clk_1:?misc_clk_1?{ ???#clock-cells?=?<0>; ???clock-frequency?=?<1500000000>; ???compatible?=?"fixed-clock"; ??}; ?}; };
?
CSI 接口似乎會自動添加到設備樹中,但我們在這里不需要它們,因為它們由裸機應用程序控制。
此文件是自動生成的,不應手動編輯,但我找不到其他方式解決上面的問題。每次編輯“system-user.dtsi”時,此問題仍然存在。
然后再次構建 Petalinux 系統。
?
petalinux-build
?
這次項目應該構建成功了。
創建SDK
鍵入以下命令為平臺項目創建 SDK。
?
petalinux-build?--sdk
?
這將在“/images/linux/”目錄中生成“sdk.sh”。
然后鍵入以下命令以在當前位置解壓“sdk.sh”。
?
cd?images/linux petalinux-package?--sysroot
?
構建平臺項目(在 Ubuntu 上)
在“petalinux/images/linux/”目錄下創建“linux.bif”文件。然后復制并粘貼以下文本。
【linux.bif】
?
/*?linux?*/ the_ROM_image: { ????[fsbl_config]?a53_x64 ????[bootloader]?????[pmufw_image]? ????[destination_device=pl]? ????[destination_cpu=a53-0,?exception_level=el-3,?trustzone]? ????[destination_cpu=a53-0,?exception_level=el-2]? }
?
啟動 Vitis,并選擇“[WORK_DIR]/U96-SLAM/vitis”作為其工作區。
點擊“File→New→Platform Project...”打開“New platform project”對話框。繼續進行以下設置。
?
[Create?new?platform?project] ??Platform?project?name:?platform [Platform] ??Choose?"Create?a?new?platform?from?hardware?(XSA)". ??XSA?File:?[WORK_DIR]/U96-SLAM/vivado/fpga_top/design_1_wrapper.xsa ??Operating?system:?linux ??Processor:?psu_cortexa53 ??Architecture:?64-bit ??Generate?boot?components:?checked ??Target?processor?to?create?FSBL:?psu_cortexa53_0
?
單擊“完成”。
在左窗格中選擇“platform→psu_cortexa53→linux on psu_cortexa53”。
在“域:linux_domain”對話框中填寫以下信息。
?
Bif?File?????????????????:?[WORK_DIR]/U96-SLAM/petalinux/images/linux/linux.bif Boot?Components?Directory:?[WORK_DIR]/U96-SLAM/petalinux/images/linux/ Linux?Image?Directory????:?[WORK_DIR]/U96-SLAM/petalinux/images/linux/ Linux?Rootfs?????????????:?[WORK_DIR]/U96-SLAM/petalinux/images/linux/rootfs.tar.gz Sysroot?Directory????????:?[WORK_DIR]/U96-SLAM/petalinux/images/linux/sdk/sysroots/aarch64-xilinx-linux
?
選擇“平臺→psu_cortexa53_0→zynqmp_fsbl→板級支持包”
單擊“修改 BSP 設置...”。
選擇“Overview → standalone”,修改如下。
?
stdin?:?psu_uart_1 stdout?:?psu_uart_1
?
單擊“確定”。
通過單擊錘子圖標構建項目。
? 將在 Vitis 工作區中創建一個名為“platform”的項目。
現在我們準備構建一個運行在該平臺上的 Linux 應用程序。
構建 SLAM 應用程序 (Ubuntu)
啟動 Vitis,并選擇“[WORK_DIR]/U96-SLAM/vitis”作為其工作區。
點擊“File→New→Application Project...”打開“New Application Projec”對話框。
繼續進行以下設置。
?
[Platform] ??Select?a?platform?from?repository:?platform?[custom] [Application?Project?Details] ??Application?project?name:?slam [Domain] ??Remain?as?default. [Templates] ??SW?development?templates:?Empty?Application?(C++)
?
如果在 git 控制的目錄中創建 Vitis 工作區,則可能無法識別平臺項目。如果發生這種情況,請嘗試在 git 控制的目錄之外的某個位置創建 Vitis 工作區。
單擊“完成”。
? 將創建名為“slam”的項目。
將 git 存儲庫中“vitis/slam”中的“src”和“include”目錄復制到 [WORK_DIR]/U96-SLAM/vitis/slam/”目錄。
單擊錘子圖標旁邊的箭頭圖標并選擇“Release”。
在“Explorer”中右擊“slam”,選擇“C/C++ Build Settings”。設置如下。
?
[ARM?v8?Linux?g++?compiler] ?├─Directories ?│??└─Include?Paths ?│?????[WORK_DIR]/U96-SLAM/petalinux/images/linux/sdk/sysroots/aarch64-xilinx-linux/usr/include ?│?????[WORK_DIR]/U96-SLAM/vitis/slam/include ?└─Miscellaneous ????-c?-fmessage-length=0?-MT"$@"?-ftemplate-backtrace-limit=0 [ARM?v8?Linux?g++?linker] ?└─Libraries ???└─Libraries ??????opencv_core ??????opencv_photo ??????opencv_video ??????opencv_videoio ??????opencv_optflow ??????opencv_tracking ??????opencv_features2d ??????opencv_imgcodecs ??????opencv_highgui ??????opencv_imgproc ??????opencv_calib3d ??????pthread
?
右鍵單擊“Explorer”中的“slam”,然后單擊“Clean Project”。
再次右鍵單擊“slam”并單擊“Build Project”。
? 將生成“Release/slam.elf”。
準備 SD 卡(在Ubuntu 上)
SD 卡使用 GParted 格式化,如下圖所示。
■ 引導文件
如果更改了 FPGA 設計,請將“design_1_wrapper.bit”從 Windows 復制到 Ubuntu。以下命令假定“.bit”文件位于“/vivado”目錄中。
鍵入以下命令以創建“BOOT.BIN”。
?
cd?[WORK_DIR]/U96-SLAM/petalinux petalinux-package?--boot?--force?--fsbl?images/linux/zynqmp_fsbl.elf?--fpga?../vivado/design_1_wrapper.bit?--u-boot
?
? “BOOT.BIN”將在“/petalinux/images/linux/”目錄中生成。
將以下3個文件復制到SD卡的BOOT目錄下。
?
[WORK_DIR]/U96-SLAM/petalinux/images/linux/boot.scr ???????????????????????????????????????????BOOT.BIN ???????????????????????????????????????????image.ub
?
■ 系統文件
通過以下命令將“rootfs.tar.gz”解壓到SD卡的“root”目錄下。
?
sudo?tar?xzvf?[WORK_DIR]/U96-SLAM/petalinux/imeges/linux/rootfs.tar.gz?-C?[SD_CARD_DIR]/root
?
在“[SD_CARD_DIR]/root/lib/”目錄下創建“firmware”目錄。
將“StereoBM.elf”和“slam.elf”復制到上述目錄。
運行應用程序
根據自動運行設置,會自動執行SD卡上“root/home/root/”目錄下的“run”腳本。
創建一個名為“run”的文件并賦予其執行權限。
?
chmod?774?run
?
然后,復制粘貼以下內容,將文件移動到SD卡的“root/home/root/”目錄下。
【home/root/run】
?
rm?*.csv rm?*.bmp rm?*.png rm?*.jpg rm?*.txt rm?-rf?work echo?StereoBM.elf?>?/sys/class/remoteproc/remoteproc0/firmware echo?start?>?/sys/class/remoteproc/remoteproc0/state #/lib/firmware/slam.elf?-app?"STEREO_CAPTURE"?-lc?"calib_left.yml"?-rc?"calib_right.yml" #/lib/firmware/slam.elf?-app?"FRAME_GRABBER" #/lib/firmware/slam.elf?-app?"SLAM_BATCH"?-dir?"kitti/sequences/00"?-l?"image_0"?-r?"image_1"?-t?"times.txt"?-gt?"../../poses/00.txt"?-lc?"calib.txt"?-n?100 /lib/firmware/slam.elf?-app?"SLAM_REALTIME"?-lc?"calib_left.yml"?-rc?"calib_right.yml" shutdown?-h?now
?
“echo”命令與將在遠程處理器上啟動“StereoBM”應用程序的 OpenAMP 相關。“StereoBM.elf”必須位于“lib/firmware”中。
接下來的幾行啟動帶有一些參數的 SLAM 應用程序。此文件包含每種應用程序類型的示例。取消注釋其中之一并適當修改它。
最后一行將關閉操作系統。如果操作系統未正確關閉,則可能不會生成輸出文件。
根據應用類型,可能還需要此目錄中的校準文件和測試數據。
實用程序
git 上包含一些實用程序。
它們是為 Windows 上的 Visual C++ Express 2015 編寫的。除“slam”項目外,源文件位于各自的目錄中?!皊lam”項目的源文件與我們已經構建的 Petalinux 上的“slam”項目相同。創建 Visual C++ 項目并將源文件添加到項目中。
這里列出了成功構建所需的其他設置。它們適用于“Release/x64”構建。
所有這些程序都是基于OpenCV 3.x 。在本文中,假設 OpenCV 3.2.0 安裝在以下目錄結構中。
?
opencv-3.2.0 ??└─build ????├─include ????│?└─opencv2 ????└─x64 ??????└─vc14 ????????├─bin ????????│?├─opencv_world320.dll ????????│?└─opencv_world320d.dll ????????└─lib ??????????├─opencv_world320.lib ??????????└─opencv_world320d.lib
?
■ 捕獲視頻
該程序從 USB 視頻類設備捕獲圖像。
當按下“Enter”鍵時,接收到的圖像將在寫入文件之前水平分成兩半。如果與在“Frame Grabber”模式下運行的 U96-SLAM 一起使用,該程序將適當地左右分割圖像。按“ESC”退出程序。
“main.cpp”中的“DEVICE_ID”決定了打開哪個設備。這些索引由系統以增量順序自動分配??赡苄枰鶕堰B接到的 PC 的 UVC 設備的數量更改該值。
?
[Configuration?Properties] ??C/C++?→?General?→?Additional?Include?Directory:? ????[OPENCV_DIR]opencv-3.2.0uildinclude ??Linker?→?General?→?Additional?Library?Directories:? ????[OPENCV_DIR]opencv-3.2.0uildx64vc14lib ???????????Input?→?Additional?Dependencies:?opencv_world320.lib [Argument?parameters] ??None
?
■ stereo_calib
該程序讀取棋盤圖案的立體圖像對,使用 OpenCV 函數計算立體校準參數,然后將它們存儲到文件中。
?
[Configuration?Properties] ??C/C++?→?General?→?Additional?Include?Directory:? ????[OPENCV_DIR]opencv-3.2.0uildinclude ??Linker?→?General?→?Additional?Library?Directories:? ???[OPENCV_DIR]opencv-3.2.0uildx64vc14lib ???????????Input?→?Additional?Dependencies:?opencv_world320.lib [Argument?parameters] ??-w,?-h?:?The?number?of?the?'inner'?intersections?of?the?chessboard?pattern. ??-s?:?The?size?of?the?grid?in?meters.?The?unit?of?this?parameter?is?important?as?it?determines?all?the?subsequent?units?including?the?pose?graph?output?of?SLAM?application. [Example] ??-w=7?-h=5?-s=0.03?[FILE_PATH]/dataset.xml
?
■ SLAM
這是 SLAM 應用程序的 Windows 版本。源文件與 Petalinux 上的 SLAM 應用程序相同。將“src”目錄下的所有文件添加到項目中。在 Windows 上只有沒有 FPGA 加速的批處理模式可用。
?
[Configuration?Properties] ??C/C++?→?General?→?Additional?Include?Directory:? ????[OPENCV_DIR]opencv-3.2.0uildinclude ????[WORK_DIR]U96-SLAMvcslaminclude ??????????Advanced?→?Disable?Specific?Warnings:?4996;4819 ??Linker?→?General?→?Additional?Library?Directories:? ????[OPENCV_DIR]opencv-3.2.0uildx64vc14lib ???????????Input?→?Additional?Dependencies:?opencv_world320.lib [Argument?parameters] -app????:?Application?type,?only?"SLAM_BATCH"?is?available. -dir????:?Base?directory?path.?All?the?below?paths?are?relative?to?this?directory. -l/-r???:?Image?file?paths. -lc/-rc?:?Calibration?file?paths. -t??????:?Path?to?timestamp?file. -gt?????:?Path?to?ground?truth?file. -n??????:?Number?of?files?to?be?preocessed,?negative?value?means?all?files. [Example] -app?"SLAM_BATCH"?-dir?"KITTI/odometry/dataset/sequences/00"?-l?"image_0"?-r?"image_1"?-t?"times.txt"?-gt?"../../poses/00.txt"?-lc?"calib.txt"?-n?-1
?
審核編輯:劉清
評論
查看更多