资讯详情

Plotjuggler之ulog格式分析

Plotjuggler它是一种强大的绘图工具,绘图非常方便,用于分析log绝对是神器。 在这里插入图片描述

在它的主页上,看到它支持它ulog模式,而ulog格式是飞机开源库PX4里定义的官方文件写得不是很好,主要是因为只讲定义,没有实际例子,看了几遍也不懂。PX4的源码里对Ulog封装也不好,根本看不出怎么写,也抽不出来。

网上搜了一遍,没看到怎么写。ulog只能啃官方代码和文档。

记得有一天晚上,我看了两个小时PX4源代码和格式,一行代码都没写出来,那天晚上心情特别沉重,这东西真的那么难吗?

第二天发现了Pyulog,是一个Python解析ulog令人惊讶的是,里面有写作ulog的函数。

看源码单步调试,看了一天半左右,终于明白了原理,恍然大悟。

然后自己重建C 项目,自己做一些数据写成ulog,并且下载PlotJuggler调试自己写的源码ulog格式,一步一步用Plotjuggler画出来。等框架写的差不多了,再移植到我们的代码框架里。

以下是Ulog格式分析,类别定义可取Plotjuggler和PX4源码里找到。如下,分为三个部分,其中Header和Definitions预定义为初始化。

---------------------- |       Header       | ---------------------- |    Definitions     | ---------------------- |        Data        | ---------------------- 

1 Header

固定16个字节,没什么好说的。

---------------------------------------------------------------------- | 0x55 0x4c 0x6f 0x67 0x01 0x12 0x35 | 0x01         | uint64_t       | | File magic (7B)                    | Version (1B) | Timestamp (8B) | ---------------------------------------------------------------------- 

2 Definitions

Format

struct message_format_s {  struct message_header_s header;  char format[header.msg_size]; }; 

format[header.msg_size]格式如下:‘前面是格式(可以理解为结构体)名称,‘后面是类型,以’;PlotJugger按此格式进行分析format。如

"pose:uint64_t timestamp;double x;double y;double z;" 

struct message_add_logged_s {  struct message_header_s header;  uint8_t multi_id;  uint16_t msg_id;  char message_name[header.msg_size-3]; }; 

message_name:也就是注册Format “pose”

msg_id:每个message_name必须有一个独特的msg_id,作为后续记录key

multi_id: 每个message_name可能有多种类型,如同一数据类型sensor,此时msg_id相同,而multi_id不同

3 Data

struct message_data_s {  struct message_header_s header;  uint16_t msg_id;  uint8_t data[header.msg_size-2]; }; 

msg_id: 是注册变量id,对应格式为msg_id:{data},

整体log文本格式如下(实际是二进制存储)

--------------------------//header "ULog" --------------------------// format "pose:uint64_t timestamp;double x;double y;double z;" "radar:uint64_t timestamp;double x;double y;" //------------------------variable  format:msg_id "pose":0 "radar":1 //------------------------data   msg_id:timestamp,data   0:100000000,{Pose} 1:100000050,{Radar} 0:100001000,{Pose} 1:100001050,{Radar} 0:100002000,{Pose} 1:100002050,{Radar} ... 

Pose和Radar对应的结构体如下:

struct Pose {     uint64_t timestamp = 0;     double x = 0;     double y = 0;     double z = 0; } struct Radar {     uint64_t timestamp = 0;     double x = 0;     double y = 0; } 

后记

回头看,卡脖子的几个点,Ulog格式是什么,sprintf怎么用,怎么写二进制,怎么调用ulog,记录如下:

1 定义结构体时,pack push 1,没有pop,导致程序挂了,而且挂的还是别的地方,耗时2小时

#pragma pack(push, 1) #pragma pack(pop) 

2 ULogL的类名写成小写Ulog没注意,编译提示找不到定义,一直以为是CMAKELIST我没有加对,花了2个小时 3 debug调试问题,clion debug没有,bin下面没有lib,vscode怎么调试C ,怎么设置debug模式?

4 CMakeList.txt 重复定义全局变量多变量。 5

int format_len = snprintf(msg.format, sizeof(msg.format), "%s:", format_name.c_str()); format_len  = snprintf(msg.format   format_len, sizeof(msg.format) - format_len,                                    "%s", format[i].c_str()); 

6

std::ofstream file(”test.ulg“, std::ios::out|std::ios::binary); file.write((char *) &msg, msg_size); 

std::vector<std::string> format_names({"format1","format2"}); 

8 怎么调用ulog?

单例模式的使用可以全局使用ulog,一个对象只需要初始化,不需要在每个类别中定义一个对象ulog对象,可以写log在一份文件中。

标签: 固态电容ulg

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台