我是平凡的,但不想平庸!梦想还是要有!
本节主要学习ardupilot如何进行基础入门学习飞控代码,最好的就是看库例程代码。
参考网址:Ardupilot 库学习例程
探索代码的第一步是看库里面的例子. 沿袭arduino的传统, 我们在很多库里面都实现了例子. 这些例子就是一个主程序 .cpp文件格式的。
了解ArduPilot中使用的库API和习惯约定,是看懂代码的重要基础.所以使用库里面的例子是一个很好的上手方法。刚开始,您应该阅读、构建和运行以下库的示例草图:
比如以下指令会编译并加载AP_Notify例子程序到PixHawk_v5:
采用waf编译
切换路径:cd Desktop/2018-11-19/ardupilot
编译:./waf configure --board fmuv5
下载:./waf build --target examples/ToshibaLED_test --upload
使用waf命令能够列出可以构建的例子
终端输入:./waf list | grep 'examples'
一旦你更新上传了这个示例代码,就可以在终端控制台上查看信息。终端控制台是什么取决于板的类型。在PixHawk板上,它是USB连接器。所以只需连接到USB设备与您最喜爱的串口调试模块(波特率不是很重要)就可以看数据了。说白了就是通过USB连接飞控和电脑上的串口,在串口观察测试的数据就OK!
例如,如果你安装了mavproxy ,就可以在Linux上连接到PixHawk。
使用命令:mavproxy.py --setup --master /dev/serial/by-id/usb-3D_Robotics_PX4_FMU_v2.x_0-if00
使用–setup 选项将 mavproxy 转换为原始串行模式, 而不是经过处理的 MAVLink 模式。这就是你需要的例子草图。
个人感觉这里没必要,直接用串口就可以。
当您阅读示例草图代码 (如 GPS_AUTO_test 代码) 时, 您会注意到一些最初可能看起来很奇怪的事情:
这里不依GPS_AUTO_test来进行分析,我采用Led进行分析
1.hal引用:
const AP_HAL::HAL& hal = AP_HAL::get_HAL(); //声明
2.对象创建:
AP_Notify notify; //创建对象
static ToshibaLED_I2C toshiba_led(1); //选择IIC1
3.初始化:
void setup(void)
{
// display welcome message
hal.console->printf("Toshiba LED test ver 0.1\n");
// initialise LED
if (toshiba_led.init())
{
hal.console->printf("Failed to initialise Toshiba LED\n");
}
toshiba_led.pNotify = ¬ify;
// turn on initialising notification
AP_Notify::flags.initialising = false;
AP_Notify::flags.save_trim = true;
AP_Notify::flags.gps_status = 1;
AP_Notify::flags.armed = 1;
AP_Notify::flags.pre_arm_check = 1;
}
4.循环函数执行:
void loop(void)
{
// blink test
//hal.console->printf("Blink test\n");
//blink();
/*
// full spectrum test
hal.console->printf("Spectrum test\n");
full_spectrum();
*/
// update the toshiba led
toshiba_led.update();
// wait 1/50th of a second
hal.scheduler->delay(20);
}
5.主函数入口:
AP_HAL_MAIN();
每个例程如果想使用 AP_HAL 功能的文件都需要声明 HAL 引用。可以访问 AP_HAL: HAL 对象, 它提供对所有硬件特定功能的访问, 包括将消息打印到控制台、休眠和与 I2C 和 SPI 总线通信。
实际的 hal 变量被隐藏在主板特定的 AP_HAL_XXX 库中。每个文件中的引用只是提供了一个方便的方法来获取 hal。 (备注:hal定义接口,不同的板子来实现)
最常用的 hal 函数有:
现在, 请在libraries/AP_HAL 目录中查看 HAL 上可用的功能的完整列表。
您会注意到, 每个草图都有一个setup() 函数和loop() 函数。当主板启动时, 将调用setup() 函数。实际的调用来自于每个主板的 hal 内部, 因此 main() 函数被放在 hal 内部, 然后在主板特定的启动完成后调用setup()程序 。
setup() 函数只调用一次,用于初始化库, 并可能打印一个 “hello” 横幅来显示它正在启动。
在setup() 完成后, loop() 函数被连续调用 (通过 AP_HAL 中的主代码)。sketch 的主要工作通常在loop() 函数中。
请注意, 这个setup()/loop() 复杂的板子程序的冰山一角。它会使 ArduPilot 像是单线程, 但实际上有更多的在下面, 并在板上(如 PX4 和 Linux 基板) 实际上会有大量的实时线程启动了。请参见下面关于理解 ArduPilot 线程的部分。
在每个sketch 的底部, 你会注意到这样一行额外的代码:
AP_HAL_MAIN();
这是一个 hal 宏, 它生成必要的代码来声明 c++ 主函数, 以及 hal 的任何板级初始化代码。你很少需要担心它是如何工作的, 但是如果你很好奇, 你可以在每个 HAL 的 AP_HAL_XXX 目录中寻找 #define。它通常在 AP_HAL_XXX_Main。(最新代码都在AP_HAL_MAIN.h中)
#ifndef AP_MAIN
#define AP_MAIN main
#endif
#define AP_HAL_MAIN() \
AP_HAL::HAL::FunCallbacks callbacks(setup, loop); \
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; \
} \
}
#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; \
} \
}
您会注意到,示例草图是相当粗糙的,而且注释很少。这是你为代码做出贡献的机会!当您通过示例草图阅读并探索它们如何工作时,向代码添加一些注释来解释API,然后提交一个请求,以便其他人可以从您的学习中受益。