学习代码的第一部是看库里面的例子. 沿袭arduino的传统, 我们在很多库里面都实现了例子. 这些例子就是一个主程序, cpp格式的.
了解ArduPilot中使用的库API和习惯约定,是看懂代码的基础.所以使用库里面的例子是一个很好的上手方法.
- libraries/AP_GPS/examples/GPS_AUTO_test
- libraries/AP_InertialSensor/examples/INS_generic
- libraries/AP_Compass/examples/AP_Compass_test
- libraries/AP_Baro/examples/BARO_generic
- libraries/AP_AHRS/examples/AHRS_Test
比如以下指令会编译并加载AP_GPS例子程序到PixHawk:
cd libraries/AP_GPS/examples/GPS_AUTO_test
make px4-clean
make px4-v2
make px4-v2-upload
一旦你加载了例子,你就可以连上命令行终端查看输出的信息.具体是什么终端取决于你用什么板子.在PX4的板子上(比如PX4v1和Pixhawk)是用usb连接的.所以只要用你的串口软件连上USB设备既可以了(波特率无所谓的).
比如,如果你安装了mavproxy(楼主还不太懂,待补充描述信息), 你可以用以下指令在linux上连接Pixhawk:
mavproxy.py --setup --master /dev/serial/by-id/usb-3D_Robotics_PX4_FMU_v2.x_0-if00
这里使用了-setup选项把mavproxy推送到原始串行模式(raw serial mode,楼主功力不够,以后补充), 取代处理过的MAVLink模式(processed MAVLink mode).
理解例子代码的结构
打您在读例子代码时,比如 GPS_AUTO_test, 你会注意到一些奇怪的情况:
- 定了一个引用变量 hal,
const AP_HAL::HAL& hal = AP_HAL::get_HAL();
- 代码的注释比较少(其实根据楼主觉得注释太多了,楼主从来认为代码就是注释,
)
- 两个奇怪的函数setup()和loop()
说说hal引用
每个使用了AP_HAL特性的文件都要定义一个hal引用.用它来访问AP_HAL::HAL,这就提供了访问所有硬件相关功能的总入口,包括打印消息到命令行,休眠和处理I2C及SPI总线.
实际的hal变量隐藏在和板子相关的AP_HAL_XXX库中. 这个引用提供了一个方便的访问方式.
The most commonly used hal functions are:
常用的hal函数有这些:
- 输出字符串:hal.console->printf() 和 hal.console->printf_P() (带_P的在AVR上用的内存较小)
- 获取启动以来的时间:hal.scheduler->millis() 和 hal.scheduler->micros()
- 休眠一小段时间:hal.scheduler->delay() 和 hal.scheduler->delay_microseconds()
- 访问GPIO管脚: hal.gpio->pinMode(), hal.gpio->read() 和 hal.gpio->write()
- I2C访问 hal.i2c
- SPI访问 hal.spi
到libraries/AP_HAL目录看看HAL可用的完整函数列表吧.
setup() 和 loop() 函数
每个例子都有一个setup()和loop()函数. setup()会在板子启动的时候被调用.调用的位置在每个板子的HAL代码里面, 其实main()就是在HAL里面, 板子自身的启动完成之后就会调用setup().
setup()函数纸币调用一次, 一般也就是初始化各种库, 也许输出一个"hello"信息( “hello” banner)来表示正在启动.
setup()结束就反复执行loop(), 还是在AP_HAL里面的主函数里面调用. 例子的主要工作一般都是在loop()里面完成的.
相信我,setup()/loop()组合只是很多远为复杂板子的冰山一角. 也许这让ArduPilot看起来像是单线程, 但是实际上背后有不少线程在默默奉献着, 而且在有多线程的板子上(比如PX4和面向linux的板子), 实际上启动了大量的实时线程. 查看ArduPilot的多线程章节了解更多内容吧.
AP_HAL_MAIN() 宏
你可以在每个例子最下面看到这么一行代码:
AP_HAL_MAIN();
这是一个HAL宏, 她产生必须要的代码来声明C++的主函数, 以及各种板级HAL初始化函数.你通常不用管她是怎么工作的, 如果想了解的话,可以到具体的AP_HAL_XXX目录下去看看定义, 一般是在AP_HAL_XXX_Main.h文件里面.
注释不多的的示例代码
你可能发现这些例子代码都比较简单,没什么注释. 那么你可以考虑奉献一下. 当你读了例子代码的时候,弄明白他们是怎么工作的之后, 通过注释代码来解释这些API, 然后提交代码请求以便其他人能从您的研究中获益.