第一個應用程序
此部分對應教程原文
http://ardupilot.org/dev/docs/learning-ardupilot-the-example-sketches.html
HelloWorld
代碼編寫及編譯
學習任何一種平臺都從Hello World開始。由於官方教程中的方法有一些問題,因此在這裏詳細寫一下如何在Pixhawk中運行helloworld程序。
在eclipse左側的 project explorer中,打開ardupilot | libraries | AP_GPS | examples | GPS_AUTO_test文件夾,雙擊裏面的GPS_AUTO_test.cpp文件。
這個文件的主要功能是打印出GPS信息到控制檯上。
當然,作爲初學者,我們更關心怎麼打印hello world到屏幕上(畢竟GPS模塊不是誰都有的)。所以我們先對代碼做如下改動:
#include <AP_HAL/AP_HAL.h>
const AP_HAL::HAL& hal = AP_HAL::get_HAL();
void setup() {
hal.console->println("GPS AUTO library test");
}
void loop()
{
hal.console->println("hello world!");
hal.scheduler->delay(1000);
}
AP_HAL_MAIN();
如果你熟悉arduino開發的話,你一定對上面的代碼很眼熟。
沒錯,apm組織代碼的形式和arduino是一樣的。一個setup()函數,一個loop()函數,當pixhawk通電後,系統會先執行一次setup(),再循環執行loop()直到斷電。
然而經過我的測試上面的代碼是不能直接運行的(Linux和Windows下編譯後燒錄到板子上均無反應)。需要將上面的代碼改爲下面的代碼才能正常打印
#include <AP_HAL/AP_HAL.h>
const AP_HAL::HAL& hal = AP_HAL::get_HAL();
class GPS_AUTO_test: public AP_HAL::HAL::Callbacks{
public:
void setup()
{
hal.console->println("GPS AUTO library test");
}
void loop()
{
hal.console->println("hello world!");
hal.scheduler->delay(1000);
}
};
GPS_AUTO_test gat;
// Register above functions in HAL board level
AP_HAL_MAIN_CALLBACKS(&gat);
區別在於在第二段代碼中我們把setup()函數和loop()函數封裝在了一個類裏。這個類必須繼承AP_HAL::HAL::Callbacks並重載setup和loop函數。燒錄後可正常運行。
編者注:此處編者閱讀了AP_HAL_MAIN和AP_HAL_MAIN_CALLBACKS兩個宏,發現兩個宏都是沒有錯誤的,尚不清楚爲何第一種宏編譯後無法運行。
改完後就是編譯了。在Eclipse右側的Make Target選項卡上找到我們的當前目錄ardupilot | libraries | AP_GPS | examples | GPS_AUTO_test,單擊上面的綠色加號,輸入px4-v2-upload
,之後雙擊生成的綠色圖標,編譯開始。
注:apm採用增量編譯的形式,初次編譯時間很長,而第二次編譯時僅重新編譯修改過的部分。因此請耐心等待。
編譯完成時,會提示
If the board does not respond within 1-2 seconds, unplug and re-plug the USB connector.
此時請將pixhawk板通過USB線連接到電腦上。系統會自動擦除原先的代碼,並燒錄進新的代碼。
運行代碼
打開px4-toolchain中的teraTerm軟件。依次選擇Setup | serial port。在打開的選項板中設置Baud rate爲115200,其與保持默認,單擊OK即可連接上。
編者注:TeraTerm爲一個串口監視器,你可以選用任何你喜歡的串口監視器來執行程序。
此時可以看到屏幕上打出一堆hello world!
其他細節
到了這裏,我們已經完成了環境的搭建,以及簡單地編譯和運行程序。使用eclipse強大的代碼閱讀能力可以幫助我們迅速的定位每一個函數的定義位置,將鼠標光標定位到函數處,即可出現該函數定義。在此處按下F3即可打開相應的定義文件。
這裏我們簡單介紹一下宏AP_HAL_MAIN_CALLBACKS
。
該宏展開後代碼如下:
#define AP_HAL_MAIN_CALLBACKS(CALLBACKS) extern "C" { \
int AP_MAIN(int argc, char* const argv[]); \
int AP_MAIN(int argc, char* const argv[]) { \
hal.run(argc, argv, CALLBACKS); \
return 0; \
} \
}
這段宏相當於定義了我們熟悉的main函數。進入main函數後,迅速將控制權轉移給hal.run這個函數,並將我們實現的類的實例傳給hal.run。這也是所有基於APM開發的程序的共同入口。
如果你想繼續閱讀關於hal.run的函數,可以繼續往裏跳轉,直到解決了你所有疑惑爲止。但是作爲初學,我們還是更關心一些頂層的實現(如姿態、位置、EKF等)。硬件底層的實現細節可以在對代碼有整體把握後再往下深挖。
在讀到這裏以後我們就可以讀官方文檔了。(注意把每一個教程裏的setup和loop函數封裝到類裏)。在這裏我們引用一個別人已經翻譯好的文檔,此部分內容不再贅述。
http://blog.csdn.net/linuxarmsummary/article/details/45402891
依次閱讀該文檔中的pixhawk源碼筆記一二三四五六七八九十。該文檔較老,如遇到和本博不一樣的地方以本博客爲準。