教你從無到有開始自己 build ArduPilot 飛控程式碼!(MacOS)

Jay/ Fienna Liang
20 min readDec 10, 2020

--

上一篇我們在筆電上安裝了 Git 等工具,這期我們來實際設定 build ArduPilot 所需要的環境啦~本篇的教學其實在 ArduPilot 官方網站都有,但有鑒於不是每一個想要研究無人機的人都是軟體背景出身,所以才有這系列文章,希望可以讓不同背景的人更容易入門囉!

首先呢,根據上一期的教學,讓我們 cd 到 ArduPilot 的 repository,如果你聽不懂我在說什麼,可以回顧一下 [Part I]

好的,那麼打開你的 Terminal (MacOS) 或 Powershell (Windows),然後輸入以下指令

cd ~/Studio/repos/ardupilot

當然如果你把 ardupilot repositoy 放在其他地方的話,就 cd 到該位置就對啦~

  1. 環境設置

根據你所使用的作業系統不同,會有不一樣的東西需要設置。 Mac 的電腦上預設都會安裝好 Xcode,這是一個讓工程師可以開發 Apple 相關系列產品 app 的 IDE (編輯器)。除此之外,Xcode 也讓使用者可以在電腦上安裝一些套件。所以,第一步你需要做的呢,是在 Terminal 輸入以下指令

xcode-select --install

接著呢,上一期我們教大家在自己筆電上裝好了 Homebrew 這個套件管理工具,現在我們就需要使用它安裝各種 ArduPilot 會需要的各種套件,方法如下

brew tap ardupilot/homebrew-px4
brew update
brew install genromfs
brew install gcc-arm-none-eabi
brew install gawk

接著我們還需要一些 Python 相關的套件。Mac 預設是有內建 Python3 的,所以我們可以透過以下指令安裝需要的套件

sudo easy_install pip
sudo pip install pyserial future empy

這樣你就設定好基本需要的環境啦!~

2. 開始建置

ArduPilot 使用 waf 這個工具進行編譯,而 repository 裡面就附帶有 waf script,因此可以直接拿來用。第一步呢,你需要根據你所使用的飛控硬體選擇相對應的 board 配置。如果你使用的是 Pixhawk 1,那可以用下列指令進行配置

./waf configure --board Pixhawk1

啊如果你用的是 Pixhawk 2,Pixhack 或其他 ChibiOS 的板子,那用以下指令

./waf configure --board fmuv3

run 下去後會跑出一大堆訊息,基本上是在確認你的電腦上是不是具備編譯時所需的工具。通常大家看到一大串的 console output 都會有點慌張,不怕不怕,我把我的執行結果放在這裡,大家可以參考一下是不是長得差不多

Setting top to                           : /path/to/ardupilot
Setting out to : /path/to/ardupilot/build
Autoconfiguration : enabled
Setting board to : fmuv3
Using toolchain : arm-none-eabi
Checking for 'g++' (C++ compiler) : /usr/local/bin/arm-none-eabi-g++
Checking for 'gcc' (C compiler) : /usr/local/bin/arm-none-eabi-gcc
Checking for c flags '-MMD' : yes
Checking for cxx flags '-MMD' : yes
CXX Compiler : g++ 9.3.1
Checking for program 'make' : /usr/bin/make
Checking for program 'arm-none-eabi-objcopy' : /usr/local/bin/arm-none-eabi-objcopy
Setup for MCU STM32F427xx
Writing hwdef setup in /path/to/ardupilot/build/fmuv3/hwdef.h
Writing DMA map
Generating ldscript.ld
No default parameter file found
Checking for env.py
env set HAL_NUM_CAN_IFACES=2
env set BOARD_FLASH_SIZE=2048
env set APJ_BOARD_TYPE=STM32F427xx
env set PERIPH_FW=0
env set USBID=0x1209/0x5741
env set MAIN_STACK=0x400
env set APJ_BOARD_ID=9
env set CORTEX=cortex-m4
env set FLASH_TOTAL=2080768
env set FLASH_RESERVE_START_KB=16
env set CHIBIOS_BUILD_FLAGS=USE_FATFS=yes MCU=cortex-m4 ENV_UDEFS=-DCHPRINTF_USE_FLOAT=1 CHIBIOS_PLATFORM_MK=os/hal/ports/STM32/STM32F4xx/platform.mk CHIBIOS_STARTUP_MK=os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
env set CPU_FLAGS=['-mcpu=cortex-m4', '-mfpu=fpv4-sp-d16', '-mfloat-abi=hard', '-DARM_MATH_CM4', '-u_printf_float']
env set IOMCU_FW=0
env set PROCESS_STACK=0x2000
Enabling ChibiOS asserts : no
Enabling -Werror : yes
Checking for intelhex module: : disabled
Checking for HAVE_CMATH_ISFINITE : yes
Checking for HAVE_CMATH_ISINF : yes
Checking for HAVE_CMATH_ISNAN : yes
Checking for NEED_CMATH_ISFINITE_STD_NAMESPACE : yes
Checking for NEED_CMATH_ISINF_STD_NAMESPACE : yes
Checking for NEED_CMATH_ISNAN_STD_NAMESPACE : yes
Checking for header endian.h : not found
Checking for header byteswap.h : not found
Checking for HAVE_MEMRCHR : no
Checking for program 'python' : /usr/local/opt/python@2/bin/python2.7
Checking for python version >= 2.7.0 : 2.7.17
Checking for program 'python' : /usr/local/opt/python@2/bin/python2.7
Checking for python version >= 2.7.0 : 2.7.17
Source is git repository : yes
Update submodules : yes
Checking for program 'git' : /usr/local/bin/git
Gtest : STM32 boards currently don't support compiling gtest
Checking for program 'arm-none-eabi-size' : /usr/local/bin/arm-none-eabi-size
Benchmarks : disabled
Unit tests : disabled
Scripting : enabled
Scripting runtime checks : enabled
Checking for program 'rsync' : /usr/bin/rsync
'configure' finished successfully (1.861s)

基本上只要看到最後寫 ‘configure’ finished successfully 就代表沒問題惹。

接著呢,使用以下指令,就會開始進行飛控程式碼的編譯。這裡說明一下,ArduPilot 支援的載具種類很多,有多旋翼、直升機、地面車、潛艇等等。這個範例會以多旋翼為主。

./waf copter

這個可能會跑一點時間,我用的是 16 吋 Macbook Pro,處理器 2.3 GHz 8 核 Intel core i9,記憶體 16 G,大概會花 3~5 分鐘 build,如果電腦效能不高可能就會比較久一點。跑起來的結果大概長下面這樣,中間很長的部分我刪掉了一些。

❯ ./waf copter
Waf: Entering directory `/path/to/ardupilot/build/fmuv3'
Checking for env.py
env added HAL_NUM_CAN_IFACES=2
env added BOARD_FLASH_SIZE=2048
env added APJ_BOARD_TYPE=STM32F427xx
env added PERIPH_FW=0
env added USBID=0x1209/0x5741
env added MAIN_STACK=0x400
env added APJ_BOARD_ID=9
env added CORTEX=cortex-m4
env added FLASH_TOTAL=2080768
env added FLASH_RESERVE_START_KB=16
env added CHIBIOS_BUILD_FLAGS=USE_FATFS=yes MCU=cortex-m4 ENV_UDEFS=-DCHPRINTF_USE_FLOAT=1 CHIBIOS_PLATFORM_MK=os/hal/ports/STM32/STM32F4xx/platform.mk CHIBIOS_STARTUP_MK=os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
env appended CPU_FLAGS=['-mcpu=cortex-m4', '-mfpu=fpv4-sp-d16', '-mfloat-abi=hard', '-DARM_MATH_CM4', '-u_printf_float']
env added IOMCU_FW=0
env added PROCESS_STACK=0x2000
Embedding file bootloader.bin:/path/to/ardupilot/Tools/bootloaders/fmuv3_bl.bin
Embedding file hwdef.dat:/path/to/ardupilot/build/fmuv3/hw.dat
Embedding file io_firmware.bin:Tools/IO_Firmware/iofirmware_lowpolh.bin
[ 3/10] Creating build/fmuv3/hwdef.h
[ 4/10] Creating build/fmuv3/modules/ChibiOS/include_dirs
[ 5/10] Compiling libraries/AP_Scripting/generator/src/main.c
[ 6/10] Processing modules/mavlink/message_definitions/v1.0/ardupilotmega.xml
Setup for MCU STM32F427xx
Writing hwdef setup in /path/to/ardupilot/build/fmuv3/hwdef.h
Writing DMA map
Generating ldscript.ld
No default parameter file found
[ 7/10] Processing uavcangen: libraries/AP_UAVCAN/dsdl/ardupilot libraries/AP_UAVCAN/dsdl/com modules/uavcan/dsdl/uavcan
[ 8/10] Creating build/fmuv3/ap_version.h
Validation skipped for /path/to/ardupilot/modules/mavlink/message_definitions/v1.0/ardupilotmega.xml.
Parsing /path/to/ardupilot/modules/mavlink/message_definitions/v1.0/ardupilotmega.xml
Validation skipped for /path/to/ardupilot/modules/mavlink/message_definitions/v1.0/common.xml.
Parsing /path/to/ardupilot/modules/mavlink/message_definitions/v1.0/common.xml
Validation skipped for /path/to/ardupilot/modules/mavlink/message_definitions/v1.0/uAvionix.xml.
Parsing /path/to/ardupilot/modules/mavlink/message_definitions/v1.0/uAvionix.xml
Validation skipped for /path/to/ardupilot/modules/mavlink/message_definitions/v1.0/icarous.xml.
Parsing /path/to/ardupilot/modules/mavlink/message_definitions/v1.0/icarous.xml
Merged enum MAV_CMD
Found 231 MAVLink message types in 4 XML files
Generating C implementation in directory /path/to/ardupilot/build/fmuv3/libraries/GCS_MAVLink/include/mavlink/v2.0/ardupilotmega
Generating C implementation in directory /path/to/ardupilot/build/fmuv3/libraries/GCS_MAVLink/include/mavlink/v2.0/common
Generating C implementation in directory /path/to/ardupilot/build/fmuv3/libraries/GCS_MAVLink/include/mavlink/v2.0/uAvionix
Generating C implementation in directory /path/to/ardupilot/build/fmuv3/libraries/GCS_MAVLink/include/mavlink/v2.0/icarous
Copying fixed headers for protocol 2.0 to /path/to/ardupilot/build/fmuv3/libraries/GCS_MAVLink/include/mavlink/v2.0
[ 9/10] Linking build/fmuv3/modules/ChibiOS/libch.a
[10/10] Processing /path/to/ardupilot/build/fmuv3/libraries/AP_Scripting/lua_generated_bindings.cpp,/path/to/ardupilot/build/fmuv3/libraries/AP_Scripting/lua_generated_bindings.h: libraries/AP_Scripting/generator/description/bindings.desc build/fmuv3/gen-bindings -> build/fmuv3/libraries/AP_Scripting/lua_generated_bindings.cpp build/fmuv3/libraries/AP_Scripting/lua_generated_bindings.h
[1/103] ChibiOS: Compiling crt0_v7m.S
[2/103] ChibiOS: Compiling vectors.S
...... 中間省略約七百行......[713/714] Generating bin/arducopter.bin
[714/714] apj_gen build/fmuv3/bin/arducopter.bin
Waf: Leaving directory `/path/to/ardupilot/build/fmuv3'
BUILD SUMMARY
Build directory: /path/to/ardupilot/build/fmuv3
Target Text Data BSS Total
----------------------------------------------
bin/arducopter 1344892 1468 195348 1541708
Build commands will be stored in build/fmuv3/compile_commands.json
'copter' finished successfully (1m41.012s)

很長對吧~這裡做的事情除了檢查參數以外,主要的事情就是把所有的程式碼編譯一次,並進行連結,最後產出能夠上傳到飛控的 bin 檔,位置是在

build/fmuv3/bin/arducopter.bin

中間的 fmuv3 會根據前面你所用的 board 不同而有所不同。

3. 上傳飛控韌體

好啦!到此我們已經從原始碼自己建置了一版飛控韌體!那要怎麼上傳到硬體上呢?已經有在玩無人機的朋友應該會知道地面站這個東西,Windows 上常見的是 Mission Planner,而 Mac 則是使用 QGroundControl。所謂地面站就是可以讓使用者進行任務規劃、參數調整,並即時監看無人機飛行狀態資訊的軟體。QGroundControl 可以到這裡下載

打開後呢,大概會長這樣:

不過我的版本是 daily build (就是你在那個網站載不到的最新版本,我就潮✌🏼✌🏼),可能會跟你看到的長得不太一樣。在 QGC 的官網其實有教大家怎麼上傳韌體,但是如果你要上傳自己 build 的韌體的話,步驟不太一樣。首先,你需要進入到 upload firmware 的頁面,長這樣

然後把你的飛控板用 micro USB 線接到你的筆電上。注意噢!一定要讓 QGC 先進入這個頁面,再連接飛控。

好的,然後 QGC 的頁面就會變這樣

有幾個要注意的地方,首先一定要選 ArduPilot,作業系統要選 ChibiOS,載具型態要選 Multi-Rotor,然後你要打開 Advanced Settings 的勾勾,他才會讓你選擇自己的韌體版本。最下面的那個下拉選單選到 Choose Firmware File,然後按下左上角的 Ok。

接著他會要你選擇檔案路徑,那當然就是要選我們剛剛親手 build 過的 bin 檔啦~位置會在 ardupilot/build/fmuv3/bin/arducopter.bin 。按下打開後,給他一點點時間,看到以下畫面就代表上傳成功囉!

恭喜你!~現在你的飛控上跑的就是自己親手從原始碼編譯過後的飛控韌體囉!至於為何要這麼大費周章自己 build 呢?我的經驗是很多時候其實很難理解飛控的行為,例如說明明叫他 Return to Launch,他怎麼他媽給我往上飛了咧?!原來是飛控預設 RTL 會先往上飛到一個“安全”高度再返航。這對室外飛行來說通常是個好的設定,但我在室內做群飛,他往上飛就直接撞天花板了啊@@搞得我看得一臉矇。當然這些設置努力找的話還是會看到文件說明,但是身為一個攻城獅,我就是很鐵齒的想要改改 code 親眼看看飛控到底在衝三小XD 下一期我會教一些最簡單的方法,讓不太懂程式的大家也可以額外得知更多飛控的狀態,敬請期待囉!

Fienna loves you ❤

--

--

Jay/ Fienna Liang
Jay/ Fienna Liang

No responses yet