移植Ardupilot的日志记录方法到linux上
- 说明
- 日志结构组成
- 日志写入操作
- 预定义日志项
- 运行时添加日志项的方法
- 单例测试
- 编译方法
- 查看数据
- 其他
说明
采用二进制文件记录,可在mission planer查看
- 支持所有数据类型记录
- 精巧移植方便
- 可直接在地面站绘制曲线查看
- 可导出生成mat文件在matlab上分析
提供的日志目标结构
日志结构组成
- 日志头
- 日志消息类型
- 消息长度
- 日志消息名称
- 数据类型标识
- 数据标签
- 数据单位
- 数据格式
数据结构体定义:
// 用于定义日志记录格式的结构
struct LogStructure {
uint8_t msg_type;
uint8_t msg_len;
const char *name;
const char *format;
const char *labels;
const char *units;
const char *multipliers;
};
日志写入操作
预定义日志项
该日志项为预先设定好,使用时无需在进行日志名称定义。
预先设置的日志项如下:
// 日志头声明处理
const struct LogStructure log_structure[] = {
{ LOG_FORMAT_MSG, sizeof(log_Format), \
"FMT", "BBnNZ", "Type,Length,Name,Format,Columns", "-b---", "-----" },
{ LOG_FORMAT_UNITS_MSG, sizeof(log_Format_Units), \
"FMTU", "QBNN", "TimeUS,FmtType,UnitIds,MultIds","s---", "F---" },
{
LOG_TEST_MSG, sizeof(struct log_TEST),
"TEST", "QH", "TimeUS,value","S-","F-"
},
{ LOG_MESSAGE_MSG, sizeof(log_Message), \
"MSG", "QZ", "TimeUS,Message", "s-", "F-"},
};
其中,LOG_FORMAT_MSG与LOG_FORMAT_UNITS_MSG是必须的,这个是地面站能够正常解析日志的关键,其他为用户自定义。
预先设置的日志写入函数:
// 预先定义类型的日志记录测试函数实体
void Write_Test(uint64_t time_us, uint16_t value)
{
struct log_TEST pkt = {
LOG_PACKET_HEADER_INIT(LOG_TEST_MSG),
.time_us = time_us,
.value = value,
};
WriteBlock(&pkt, sizeof(pkt));
}
uint64_t micros64()
{
uint64_t sys_time;
//在此处赋值系统时间戳
//sys_time = ;
return sys_time;
}
// 在日志中写入文本消息的函数实体
bool Write_Message(const char *message)
{
struct log_Message pkt{
LOG_PACKET_HEADER_INIT(LOG_MESSAGE_MSG),
time_us : micros64(),
msg : {}
};
strncpy(pkt.msg, message, sizeof(pkt.msg));
return WriteBlock(&pkt, sizeof(pkt));
}
运行时添加日志项的方法
很多时候想临时添加一组日志来对某些状态进行记录分析,直接进行日志结构体构造会省很多事,所以专门提供了一个进行此操作的接口。
/* Write support */
void Write_Log(const char *name, const char *labels, const char *units, const char *mults, const char *fmt, ...)
{
va_list arg_list;
va_start(arg_list, fmt);
WriteV(name, labels, units, mults, fmt, arg_list);
va_end(arg_list);
}
单例测试
主函数代码:
主要实现了日志初始化,对预先设定的日志项进行一百次的写入,之后对文本消息进行写入操作。
int main()
{
//初始化日志
Log_Init();
//循环写入100次各项日志
for(uint16_t i=0; i<100; i++){
Write_Test(i,i); //预先写好的日志实体测试
Write_Log("WTS","T1,T2,T3", //运行时添加的任意日志
"s--","F--","HHH",
i,i,i);
Write_Log_test(); //写入不同数据类型的数据
}
//以下为消息日志记录,每次写入的字符串不能大于64字节
Write_Message("This logging method is applicable to Linux systems");
Write_Message("In the case of MCU system with SD card,");
Write_Message("it is also necessary to adjust the write function");
Write_Message("Take a closer look at the WriteBlock function");
return 0;
}
编译方法
- 进入logts目标,创建build文件夹
mkdir build
- 进入build目录
cd build
- 运行cmake
cmake ..
- 编译源码
make
运行demo
./log
可看到在build目录下生成了log1.bin文件,该文件即为我们需要的日志文件,此时可使用地面站打开次文件查看相关内容
查看数据
- 查看常规数据
打开mission planner地面站,选择回顾日志,打开log1.bin,选择对应的日志项勾选对应的标签即可查看数据。
- 查看文本消息日志
勾选Data Table,再对消息进行滤波,选择MSG日志项。
文件日志也可以在该界面上右键导出csv文件。 - 导出成matlab文件可使用地面站的创建matlab文件 功能
其他
- 将本例程放入到实际系统去时还需要考虑每次开始记录时按照递进的方式对文件名曾1,否则会直接在文件尾继续写入新数据。
- 若在MCU上使用,则需要另外封装读写函数,主要是WriteBlock函数
资料下载链接:
https://download.csdn.net/download/qq_39016531/87720027