開始入坑pixhawk。講講遇到的坑。(見解可能有誤,歡迎拍磚)
1.一開始並不清楚pixhawk飛控是什麼,後來發現是一個開源硬件平臺,而且有兩大開源飛控代碼可以在其上運行。一個出自APM開源社區點擊打開鏈接,一個出自蘇黎世理工點擊打開鏈接。
APM的代碼已有多年的積累,其穩定性較好,但由於歷史原因,導致其原有的硬件平臺性能已經被榨乾,於是APM社區人員將其移植到pixhawk的硬件平臺上繼續發展。也正是因爲代碼多年的累積,導致其結構邏輯較爲晦澀,要想再做改動,非專業人士很難入門和下手。
PIXHAWK的軟件是重構了APM的架構,將模塊間的關係重新整理,但在算法上並非完全複製。同時又有蘇黎世理工的大神加盟,代碼性能和APM的相比,據說有所提高。不過最重要的是代碼架構的清晰讓新鮮血液更快的融入,大大降低了開發者的工作量,果斷選擇這個了。(dota和lol的區別吧,嘿嘿)
2.關開發環境配置。最要吐槽的是官方要求使用git clone 。而下載的速度慘目忍睹。而且無論是win還是ubuntu,clone工程以後,第一次編譯你會發現非常非常慢。仔細觀察會發現,他還在clone其他的依賴文件,而這個過程也是非常非常慢。。運氣不好,clone失敗。總之要有耐心,跟着官網的教程來。我試過從別人那兒拷貝整個工程過來,發現編譯會失敗,原因莫名其妙,總之還是乖乖地clone吧。
3.遇到的第一個問題,nsh啓動亂碼。按照官網的要求,一步步配置,到了插上usb下載固件後連接串口,發現無論如何,一打開串口就是亂碼。後來發現sd卡不插時就能正常啓動nsh服務。一開始沒搞懂,後來查閱了\Firmware\ROMFS\px4fmu_common\init.d\rcS文件。這個是啓動腳本,在最後找到了問題所在。
# Start USB shell if no microSD present, MAVLink else
if [ $LOG_FILE == /dev/null ]
then
# Try to get an USB console
nshterm /dev/ttyACM0 &
else
mavlink start -r 800000 -d /dev/ttyACM0 -m config -x
fi
官網上的說明沒有更新(好像頁面上有說教程過時了,會有所不同)。在這裏啓動程序檢測了sd卡的存在,如果存在就開啓mavlink傳輸協議,否則開啓nsh。
4.未解決的問題1。將錯就錯,我把代碼修改了一下,去除mavlink,保留nsh,但是在插着sd卡的時候,還是無法打開nsh。實在不明白,求高人指點。
if [ $LOG_FILE == /dev/null ]
then
# Try to get an USB console
nshterm /dev/ttyACM0 &
else
nshterm /dev/ttyACM0 &
#mavlink start -r 800000 -d /dev/ttyACM0 -m config -x
fi
5.未解決的問題2。在跑了官網的教程代碼後想試試程序自動啓動。px4_daemon_app 在正常模式下運行 px4_daemon_app start 會隔10秒輸出信息,px4_daemon_app stop會終止程序,px4_daemon_app status會輸出當前程序是否運行。我稍稍修改了啓動文件。在不插sd卡的情況下進行測試。
if [ $LOG_FILE == /dev/null ]
then
# Try to get an USB console
px4_daemon_app start
nshterm /dev/ttyACM0 &
else
mavlink start -r 800000 -d /dev/ttyACM0 -m config -x
fi
理論上,px4_daemon_app 隨着系統啓動而啓動,會定時輸出信息,但實際上沒有任何信息輸出到串口上。但是奇怪的是,我直接輸入px4_daemon_app status命令(注意之前沒有輸入px4_daemon_app start ),串口輸出px4_daemon_app: running。換言之,px4_daemon_app 程序是在運行的!只是warnx("Hello daemon!\n");沒有將數據輸出到串口。之後輸入px4_daemon_app stop 再px4_daemon_app start ,數據正常輸出。
之後我在想是否是由於在啓動文件中先調用了px4_daemon_app start 再調用nshterm /dev/ttyACM0 &導致的問題。於是將其位置互換,得到的結果還是一樣的。沒有解決。
貼一下px4_daemon_app 的代碼。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <px4_config.h>
#include <nuttx/sched.h>
#include <systemlib/systemlib.h>
#include <systemlib/err.h>
static bool thread_should_exit = false; /**< daemon exit flag */
static bool thread_running = false; /**< daemon status flag */
static int daemon_task; /**< Handle of daemon task / thread */
/**
* daemon management function.
*/
__EXPORT int px4_daemon_app_main(int argc, char *argv[]);
/**
* Mainloop of daemon.
*/
int px4_daemon_thread_main(int argc, char *argv[]);
/**
* Print the correct usage.
*/
static void usage(const char *reason);
static void
usage(const char *reason)
{
if (reason) {
warnx("%s\n", reason);
}
warnx("usage: daemon {start|stop|status} [-p <additional params>]\n\n");
}
/**
* The daemon app only briefly exists to start
* the background job. The stack size assigned in the
* Makefile does only apply to this management task.
*
* The actual stack size should be set in the call
* to task_create().
*/
int px4_daemon_app_main(int argc, char *argv[])
{
if (argc < 2) {
usage("missing command");
return 1;
}
if (!strcmp(argv[1], "start")) {
if (thread_running) {
warnx("daemon already running\n");
/* this is not an error */
return 0;
}
thread_should_exit = false;
daemon_task = px4_task_spawn_cmd("daemon",
SCHED_DEFAULT,
SCHED_PRIORITY_DEFAULT,
2000,
px4_daemon_thread_main,
(argv) ? (char *const *)&argv[2] : (char *const *)NULL);
return 0;
}
if (!strcmp(argv[1], "stop")) {
thread_should_exit = true;
return 0;
}
if (!strcmp(argv[1], "status")) {
if (thread_running) {
warnx("\trunning\n");
} else {
warnx("\tnot started\n");
}
return 0;
}
usage("unrecognized command");
return 1;
}
int px4_daemon_thread_main(int argc, char *argv[])
{
warnx("[daemon] starting\n");
thread_running = true;
while (!thread_should_exit) {
warnx("Hello daemon!\n");
sleep(10);
}
warnx("[daemon] exiting.\n");
thread_running = false;
return 0;
}