Ardupilot -- APM源码笔记二(重制)~ Ardupilot 链接库引导

ardupilot/libraries 作为APM多旋翼、固定翼及无人车的共享资源库,这里集成了多方面的算法控制,也包括了硬件驱动,功能扩展(航拍)库等。

链接库简介


核心库:

  • AP_AHRS - 利用DCM或是EKF做姿态估算
  • AP_Common - ArduPilot库中常见的定义及实用例程
  • AP_Math - 各种对空间向量处理的数学函数
  • AC_PID - PID控制库
  • AP_InertialNav - 结合加速度计、gps和气压计数据来保持(飞行)高度跟位置的稳定
  • AC_AttitudeControl - 基于PID算法的多旋翼各种姿态及高度控制函数库
  • AP_WPNav - 导航路线规划
  • AP_Motors - 旋翼机与传统直升机机型(4、6、8轴、X8、Y6等)电机混合处理
  • RC_Channel - 利用APM_RC把pwm的输入输出转换成内部处理单位,类似角度
  • AP_HAL, AP_HAL_AVR, AP_HAL_PX4 - 提供了一个通用的顶层接口代码,实现硬件抽象层,方便源码可以移植到不同的控制板上

驱动(传感器)库:

  • AP_InertialSensor -读取陀螺仪跟加速度数据,完成校准跟给核心源码及其他库提供转换标准单位数据(deg/s,m/s)
  • AP_RangeFinder - 声呐及红外距离传感器链接库
  • AP_Baro - 气压计链接库
  • AP_GPS - GPS链接库
  • AP_Compass - 3轴罗盘链接库
  • AP_OpticalFlow - 光流传感器链接库

其他库

  • AP_Mount, AP_Camera, AP_Relay - 云台控制链接库,相机快门链接库
  • AP_Mission - 从 eeprom 存/取任务指令
  • AP_Buffer - 惯性导航相关缓冲区


    库示例草图

阅读源码的第一步是能大概看懂库的示例草图(至于为什么说是草图,你可以理解为像人物素描前都会先画个人体框架那样,各链接库也是以这个草图为框架进行补充跟改写出来的),继arduino的惯例在每个功能库下都留有一个示例草图,以cpp的文件形式写成一个主函数( libraries/AC_PID/examples)
阅读Ardupilot的代码了解库的接口调用方式是很有必要的,一个不错的方法就是去查看链接库的示例草图,可以尝试去编译运行下面这些示例草图~

  • 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板(终端操作,PX4 Console 或 linux下)

cd $ARDUPILOT_HOME # the top-level of an AruPilot repository
./waf configure –board=px4-v2
./waf build –target examples/GPS_AUTO_test –upload

利用waf列出可编译的示例草图

cd $ARDUPILOT_HOME
./waf list | grep ‘examples’

编译过的示例都可以输出在终端显示器上,输出方式取决于飞控平台,像PX4板则是通过USB接口输出的,接上USB通过串口打印输出(波特率可暂时忽略)

有安装mavproxy 的话,可以连接pixhawk在Linux作输出

mavproxy.py –setup –master /dev/serial/by-id/usb-3D_Robotics_PX4_FMU_v2.x_0-if00

利用–setup指令把mavproxy放置到底层串口输出,而不是通过MAVlink协议,这就是原始草图,用最直接的方式来编写


草图代码解析

第一次看草图代码应该会觉得有些奇怪,比如~

  • 声明了一个’hal’的变量作为引用
  • 代码写的比较粗糙且没有注释
  • setup( ) 和 loop( ) 函数

变量hal

每个文件调用AP_HAL都需要声明一个hal引用,以此来访问AP_HAL的对象,AP_HAL提供了所有的硬件特性功能(前文所提及的硬件抽象层~PX4、Linux、AVR等),包括终端打印及I2C、SPI总线通讯。
实际上的hal变量定义在运行平台的AP_HAL_XXX库中,每个文件的hal引用都是为了方便我们去创建链接。
比较常用的hal函数~

  • 字符打印 ~ hal.console->printf( )
  • 获得系统时间 ~ AP_HAL::millis( ) 和 AP_HAL::micros( )
  • 延时 ~ hal.scheduler->delay( ) 和 hal.scheduler->delay_microseconds( )
  • I/O引脚访问 ~ hal.gpio->pinMode(), hal.gpio->read() 和 hal.gpio->write()
  • I2C接口 ~ hal.i2c
  • SPI接口 ~ hal.spi

在libraries/AP_HAL目录下可以找到当前可用的hal完整函数列表

setup()和 loop()函数

用过arduino的读者对这两个函数一定很熟悉,你会发现在每个示例草图的代码中都存在这两个函数,板子启动时setup()函数会被执行,实际上是在HAL里面去调用的,可见主函数还是编写在HAL里面,之后再对板级硬件完成初始配置。
setup()函数只会被执行一次,同时初始化对应链接库,可以在setup()加入字符打印来验证代码开始运行,setup()执行后紧接着是循环执行loop()函数(在主函数AP_HAL中调用),功能库的主要工作都是在loop()中执行的。

注意
setup( )/loop( )的布局在更复杂的平台上只是凤毛菱角,也许示例草图的代码会让你以为Ardupilot是单线程执行的,事实上还有更多在其后面执行的,在平台检测时(PX4和Linux都基于平台),其实是有大量线程在实时进行的,读下面部分加深一下理解~

AP_HAL_MAIN() 宏

你会在每个草图的底端发现有这么一行~

AP_HAL_MAIN();

这是一个HAL宏定义通过创建一些必备的代码来声明C++的主函数,连同着板级初始化代码,可以不必关心它的运作流程,有兴趣的也可以在各自的AP_HAL_XXX目录中去查看 那些hal的宏定义,通常都在AP_HAL_XXX_Main.h文件中。

官方的想法

虽然这些示例草图都写的比较简单粗糙,没注释,但这可能也是一个机会,如果你也试过去编译这些示例草图,去调用那些库函数接口,探索它们之间的调用流程,可以写些对代码的注释,分享出来让其他人的学习受益。


草图编译实例

Hello World

按照上文提到的示例草图的修改编译跟输出,这里展示在Windows环境编译草图代码,在USB接口输出字符到终端控制台。
笔者的编译环境为windows下的eclipse,以GPS的草图为例,打开Ardupilot工程文件下的GPS_AUTO_test.cpp文件(libraries/AP_GPS/examples/GPS_AUTO_test/GPS_AUTO_test.cpp),对原代码做简化改动如下~

#include <stdlib.h>
#include <AP_HAL/AP_HAL.h>

const AP_HAL::HAL& hal = AP_HAL::get_HAL();

void setup()
{
    hal.console->println("AUTO library test");
}

void loop()
{
    hal.console->println("Hello World");
    hal.scheduler->delay(1000);
}

AP_HAL_MAIN();

头文件留下AP_HAL.h就行,其他的led控制,gps的数据获取打印都不需要,只要留下setup()和loop()函数中的打印跟延时就行了,但是这样编译后烧到板子上没有我们要的串口信息输出,需要再做一些修改,将setup()和loop()封装在同个类里面,这个类必须继承AP_HAL::HAL::Callbacks并重载setup和loop函数~

#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("AUTO library test");

    }

    void loop()
    {
        hal.console->println("Hello World");
        hal.scheduler->delay(1000);
    }
};

GPS_AUTO_test gat;
AP_HAL_MAIN_CALLBACKS(&gat);

这样改动过可以编译运行,添加测试编译,在eclipse右侧工程Ardupilot,点击Ardupilot/libraries/AP_GPS/examples/GPS_AUTO_test文件夹,再点击工程上方的绿色圈圈带黄色+号的图标,添加新的make目标,输入 px4-v2-upload 确定,此时在GPS_AUTO_test文件夹下会多了个px4-v2-upload选项,双击进行代码编译烧写

这里写图片描述

编译完成后会在编译窗口打印以下语句,同时开始搜索电脑上的飞控板连接端口,进行烧写

If the board does not respond within 1-2 seconds, unplug and re-plug the USB connector.

另外电脑连接USB线到飞控板上(pixhawk),方便烧录及查看串口打印,开始菜单栏打开px4-toolchain中的teraTerm软件。依次选择Setup | serial port。在打开的选项板中设置Baud rate为115200,其与保持默认,单击OK即可连接上。
此时可以看到屏幕上一直循环打印Hello World
这里写图片描述

想检测setup()跑一次后一直循环loop()可以加长延时验证

草图实例参考自
http://blog.csdn.net/u013859301/article/details/51227178

了解了链接库的作用及大概功能后,对于主控代码中的接口数据调用也会清晰很多

猜你喜欢

转载自blog.csdn.net/qq_36955622/article/details/73497813
今日推荐