源代码分析(3)

2019-05-17 19:06

FUNCTION参数如下:

// FUNCTION 为1-27,function参数。 typedef enum {

k_none = 0, ///< disabled

k_manual = 1, ///< manual, just pass-thru the RC in signal k_flap = 2, ///< flap

k_flap_auto = 3, ///< flap automated k_aileron = 4, ///< aileron

k_unused1 = 5, ///< unused function k_mount_pan = 6, ///< mount yaw (pan) k_mount_tilt = 7, ///< mount pitch (tilt) k_mount_roll = 8, ///< mount roll

k_mount_open = 9, ///< mount open (deploy) / close (retract) k_cam_trigger = 10, ///< camera trigger k_egg_drop = 11, ///< egg drop

k_mount2_pan = 12, ///< mount2 yaw (pan) k_mount2_tilt = 13, ///< mount2 pitch (tilt) k_mount2_roll = 14, ///< mount2 roll

k_mount2_open = 15, ///< mount2 open (deploy) / close (retract) k_dspoiler1 = 16, ///< differential spoiler 1 (left wing) k_dspoiler2 = 17, ///< differential spoiler 2 (right wing) k_aileron_with_input = 18, ///< aileron, with rc input k_elevator = 19, ///< elevator

k_elevator_with_input = 20, ///< elevator, with rc input k_rudder = 21, ///< secondary rudder channel

k_sprayer_pump = 22, ///< crop sprayer pump channel k_sprayer_spinner = 23, ///< crop sprayer spinner channel k_flaperon1 = 24, ///< flaperon, left wing k_flaperon2 = 25, ///< flaperon, right wing

k_steering = 26, ///< ground steering, used to separate from rudder k_parachute_release = 27, ///< parachute release k_epm = 28, ///< epm gripper

k_nr_aux_servo_functions ///< This must be the last enum value (only add new values _before_ this one)

} Aux_servo_function_t;

AP_Int8 function; ///< see Aux_servo_function_t enum

这里,我们对 APM EEPROM存储接口进行讲解。如有问题,可以交流30175224@qq.com。新浪@WalkAnt,转载本博客文章,请注明出处,以便更大范围的交流,谢谢。 第六部分 存储与EEPROM管理 详细参考:http://dev.ardupilot.com/wiki/learning-ardupilot-storage-and-eeprom-management/

用户参数、航点、集结点、地图数据以及其他有用的信息需要存储。ArduPilot提供4个基本存储接口:

1、AP_HAL::Storage对象:hal.storage;

2、StorageManager库,是hal.storage更高级别的封装; 3、DataFlash用于日志存储;

4、Posix IO函数,是传统文件系统读写函数。

其他用于永久存储信息的函数库,都是基于以上4种实现。例如:AP_Param library(用于处理用户可配置参数)是建立在StorageManager库之上的,而StorageManager库则是基于AP_HAL::Storage之上。AP_Terrain library(用于处理地形数据)则是建立在Posix IO functions之上,用于操作地形数据库。 1、AP_HAL::Storage library

AP_HAL::Storage对象适用于所有ArduPilot硬件平台。最小支持4096字节空间的存储,一些类似PX4v1的板子有8K EEPROM,Pixhawk有16K FRAM。所有这些都封装在AP_HAL::Storage API中。

hal.storage API,非常简单,仅3个函数: 1、init(),初始化存储系统; 2、read_block(),读块数据; 3、write_block(),写块数据。

之所以这么简单,是因为APM团队鼓励开发者使用StorageManager API,而不是hal.storage。只有在代码移植或调试时,使用hal.storage会比较方便(原文:You should only be delving into hal.storage when doing bringup of a new board, or when debugging.)。 存储空间的大小,在AP_HAL/AP_HAL_Boards.h文件中的HAL_STORAGE_SIZE宏中定义,如下:

#define CONFIG_HAL_BOARD_SUBTYPE HAL_BOARD_SUBTYPE_PX4_V2 #define HAL_STORAGE_SIZE 16384 // 存储空间 16KB #endif

也就是说,我们不支持动态存储空间的定义。如果希望使用动态存储空间,可以使用Posix IO。

2、StorageManager library

在将ArduPilot代码移植到一个新的硬件板上时,hal.storage API非常简单,但是在操作存储区时就不那么好使了。我们会采用StorageManager。StorageManager library提供对存储区域“伪连续块”(一般用作不同的功能和目的)的访问。正因此我们将存储区域分配了不同的功能:

1、参数区;

2、飞行区域限制点数据区; 3、航点数据区; 4、集结点数据区。

参见: libraries/StorageManager/StorageManager.cpp,我们可以看到存储区域的划分: const StorageManager::StorageArea StorageManager::layout_copter[STORAGE_NUM_AREAS] PROGMEM = {

// ------------------------ 0-4096 分配给了 AVR版本的 APM { StorageParam, 0, 1536}, // 0x600 param bytes { StorageMission, 1536, 2422},

{ StorageRally, 3958, 90}, // 6 rally points { StorageFence, 4048, 48}, // 6 fence points #if STORAGE_NUM_AREAS >= 8

// ------------------------ 4096-8192 分配给了PX4版本 { StorageParam, 4096, 1280}, { StorageRally, 5376, 300}, { StorageFence, 5676, 256},

{ StorageMission, 5932, 2132}, // leave 128 byte gap for // expansion and PX4 sentinal #endif

#if STORAGE_NUM_AREAS >= 12 // Pixhawk // ------------------------ 8192-16384 分配给了 Pixhawk版本 { StorageParam, 8192, 1280}, // 类型 偏移量 长度 { StorageRally, 9472, 300}, { StorageFence, 9772, 256},

{ StorageMission, 10028, 6228}, // leave 128 byte gap for expansion #endif };

对于上面的存储分布,我们可以观察到AVR版本用到存储地址是0-4095,而PX4用到地址是4096-8191,Pixhawk用到的地址是8192-16383。这样的结构,是为了更好的与之前的版本兼容。这样一来,用户在更新最新的固件时,所有之前配置的参数将不会改变,将继续起作用。

StorageManager API也提供对类似整型数的读写访问,AP_Mission中就会利用这个API来存储和恢复航点数据。

相关例程(libraries/StorageManager/examples/StorageTest.pde)对StoageManager layer和AP_HAL::Storage object进行了测试。它对随机的偏移量、随机的长度进行了随机的IO操作。这也就意味可能会出现跨边界访问。这个例程非常有用,它用于对StorageManager API进行严苛测试,同样对于移植ArduPilot到新硬件平台也是极为有用的,因为它对EEPROM的访问函数进行了很严格的测试。

注意StorageTest是一个毁坏性的测试,它将会删除你之前存储的参数和航点。一定要

记得测试之前,备份你的配置。 存储对象的声明,一般如下:

StorageAccess AP_Param::_storage(StorageManager::StorageParam); 又或者

StorageAccess AP_Rally::_storage(StorageManager::StorageRally);

StorageAccess AP_Mission::_storage(StorageManager::StorageMission);

StorageAccess AP_Limit_Geofence::_storage(StorageManager::StorageFence); 3、DataFlash library

另一类存储,就是飞行日志存储,这个基于DataFlash library。这个库的名字看上去有些怪怪的,实际上这个库最开始是为APM1的DataFlash芯片设计的,它原本是一个硬件驱动库,后来慢慢演变为一个通用日志系统,这个可以在代码中找到蛛丝马迹(这些都是以前的痕迹,不是最好的代码实现方式)。

现在DataFlash API主要用于实现日志存储。它允许你自定义日志消息的数据结构。例如GPS消息,用于记录GPS传感器的日志数据。它能够非常有效存储这些数据,它同时也对其他库提供相应的APIs,用来进行日志回传、下载。

LOG数据结构是自定义的,其结构可以查看日志文件的FMT消息。FMT消息地应以的其他数据的存储格式。

相关例程 libraries/DataFlash/examples/DataFlash_test/DataFlash_test.pde。这里描述了数据的存储结构和数据格式。简单列举如下:

第一点,在.log文件中,我们可以看到如下格式的表达:

FMT, 128, 89, FMT, BBnNZ, Type,Length,Name,Format,Columns FMT, 129, 23, PARM, Nf, Name,Value FMT, 130, 45, GPS, BIHBcLLeeEefI,Status,TimeMS,Week,NSats,HDop,Lat,Lng,RelAlt,Alt,Spd,GCrs,VZ,T FMT, 131, 31, IMU, Iffffff, TimeMS,GyrX,GyrY,GyrZ,AccX,AccY,AccZ FMT, 132, 67, MSG, Z, Message

第二点,上述格式,对应的代码(参见DataFlash.h): #define LOG_BASE_STRUCTURES \\

{ LOG_FORMAT_MSG, sizeof(log_Format), \\

\ { LOG_PARAMETER_MSG, sizeof(log_Parameter), \\ \ { LOG_GPS_MSG, sizeof(log_GPS), \\ \

\ { LOG_IMU_MSG, sizeof(log_IMU), \\

\ 上述结构,以 LOG_IMU_MSG为例讲解: 信息类型ID 数据大小 信息名称 数数据1 数据2 数据3 数据4 数据5 数据6 数据7 据类型 LOG_IMU_Msizeof(log_IIMIffffTimeSG MU) U ff MS 131 31(字节) GyrX GyrY GyrZ AccX AccY AccZ IMl:整整型 0.0007-0.0001-0.0003-0.13390.0342-9.7487U 型; 46481 03 90 59 95 36 02 f:浮点 第三点,日志文件(.log)的一条数据如下:

IMU, 46481, 0.000703, -0.000190, -0.000359, -0.133995, 0.034236, -9.748702

第四点,消息类型的定义:

// message types for common messages

// 消息类型,,,对应 FMT 中的消息类型,,,见日志文件 .log 文件。 #define LOG_FORMAT_MSG 128 #define LOG_PARAMETER_MSG 129 #define LOG_GPS_MSG 130 #define LOG_IMU_MSG 131 #define LOG_MESSAGE_MSG 132 #define LOG_RCIN_MSG 133 #define LOG_RCOUT_MSG 134 #define LOG_IMU2_MSG 135 ?

第五点, log_IMU的结构,共占用 3 + 4 + 12 + 12 = 31字节。 struct PACKED log_IMU {

LOG_PACKET_HEADER; // 3 uint32_t timestamp; // 4

float gyro_x, gyro_y, gyro_z; // 4*3 = 12 float accel_x, accel_y, accel_z; // 4*3 = 12 };

第六点:如果要增加自定义的数据结构,那么可以像以下代码一样增加。 #define LOG_TEST_MSG 1

struct PACKED log_Test { LOG_PACKET_HEADER; uint16_t v1, v2, v3, v4; int32_t l1, l2; };

static const struct LogStructure log_structure[] PROGMEM = { LOG_COMMON_STRUCTURES,

{ LOG_TEST_MSG, sizeof(log_Test), // 增加自定义格式数据 \增加自定义格式数据


源代码分析(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:基于导游讲解视角的景区旅游形象感知研究-以凤凰古城为例

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: