Velodyne线性激光雷达pcap文件格式及写入、数据解析 Lebal:激光雷达
转载自https://blog.csdn.net/qq_25241325/article/details/80766305
roslaunch loam_velodyne loam_velodyne.launch
rosbag record -o out /velodyne_points
rosbag play nsh_indoor_outdoor.bag
最后会记录一个名为out_(记录时间)的.bag包
然后将.bag包转化为 .pcd文件
rosrun pcl_ros bag_to_pcd out_.bag(上面记录的那个包) /cloud pcd
此时转化为一个名为cloud的pcd集,进入pcd那个文件夹
用pcl_viewer last.pcd(最后一帧pcd)然后就看到了最终的结果
一 基本格式:
文件头 数据包头 数据报数据包头数据报......
二、文件头:

文件头结构体
sturct pcap_file_header
{
DWORD magic;
DWORD version_major;
DWORD version_minor;
DWORD thiszone;
DWORD sigfigs;
DWORD snaplen;
DWORD linktype;
}
说明:
1、标识位:32位的,这个标识位的值是16进制的 0xa1b2c3d4。
a 32-bit magic number ,The magic number has the value hex a1b2c3d4.
2、主版本号:16位, 默认值为0x2。
a 16-bit major version number,The major version number should have the value 2.
3、副版本号:16位,默认值为0x04。
a 16-bit minor version number,The minor version number should have the value 4.
4、区域时间:32位,实际上该值并未使用,因此可以将该位设置为0。
a 32-bit time zone offset field that actually not used, so you can (and probably should) just make it 0;
5、精确时间戳:32位,实际上该值并未使用,因此可以将该值设置为0。
a 32-bit time stamp accuracy field tha not actually used,so you can (and probably should) just make it 0;
6、数据包最大长度:32位,该值设置所抓获的数据包的最大长度,如果所有数据包都要抓获,将该值设置为65535;例如:想获取数据包的前64字节,可将该值设置为64。
a 32-bit snapshot length" field;The snapshot length field should be the maximum number of bytes perpacket that will be captured. If the entire packet is captured, make it 65535; if you only capture, for example, the first 64 bytes of the packet, make it 64.
7、链路层类型:32位, 数据包的链路层包头决定了链路层的类型。
a 32-bit link layer type field.The link-layer type depends on the type of link-layer header that the
packets in the capture file have:以下是数据值与链路层类型的对应表
0 BSD loopback devices, except for later OpenBSD
1 Ethernet, and Linux loopback devices 以太网类型,大多数的数据包为这种类型。
6 802.5 Token Ring
7 ARCnet
8 SLIP
9 PPP
10
在使用velodyne的时候,PCAP数据解析比较麻烦,为此写了一点代码来专门解析PCAP文件,将PCAP格式数据转为XYZ格式的点云数据,写完之后发现其实代码也不多,更轻量级了,代码如下:
// readpcap.cpp : 定义控制台应用程序的入口点。
//
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS
#include "pcap.h"
#include "stdio.h"
#include "math.h"
#include<stdlib.h>
#include<conio.h>
#include "velodyneptk.h"
#define LINE_LEN 16 int Azimuth_[12]; //原始值
float Azimuth_Value_[12];
int Distance_[12][32]; //原始值
float Distance_Value_[12][32];
int Atten_[12][32]; //原始值
Usefulmessage UsefulData;
int framecount;
int frameint;
//计算时间戳函数
float Timeoffsetvec[384];
float lasersinvec[384];
float lasercosvec[384];
void Timeoffsetfun()
{
for (int i = 0; i < 24; i++)
{
for (int j = 0; j < 16; j++)
{
Timeoffsetvec[i * 16 + j] = i*55.296 + j*2.304;
lasersinvec[i * 16 + j] = LASER_SIN[j];
lasercosvec[i * 16 + j] = LASER_COS[j];
}
}
} void dispatcher_handler(u_char *, const struct pcap_pkthdr *, const u_char *); //byte转int Azimuth
int bytes2ToInt(byte* bytes)
{
int addr = bytes[0] & 0xFF;
addr |= (bytes[1]<<8 & 0xFF00);
return addr;
} int bytes1ToInt(byte* bytes)
{
int addr = bytes[0] & 0xFF;
return addr;
} //byte转int Azimuth
long int bytes4ToInt(byte* bytes)
{
long int addr = bytes[0] & 0xFF;
addr |= (bytes[1] << 8 & 0xFF00);
addr |= ((bytes[2] << 16) & 0xFF0000);
addr |= ((bytes[3] << 24) & 0xFF000000);
return addr;
} float stamptimecount = 0;
void UDPtoXYZfun(Usefulmessage data);
void UDPtoXYZfunALL(Usefulmessage data);
errno_t err; int _tmain(int argc, _TCHAR* argv[])
{
pcap_t *fp;
char errbuf[PCAP_ERRBUF_SIZE];
Usefulmessage UsefulData;
Timeoffsetfun();
framecount = 0; fp = pcap_open_offline("1.pcap",errbuf);
pcap_loop(fp, 0, dispatcher_handler, NULL);
pcap_close(fp);
return 0;
} void dispatcher_handler(u_char *temp1,
const struct pcap_pkthdr *header,
const u_char *pkt_data)
{
u_int it = 0; (VOID*)temp1; //保存数据
char fn[20];
PointXYZ point;
FILE *fp; long int ustime = header->ts.tv_usec;
printf("%ld:%ld (%ld)\n", header->ts.tv_sec, header->ts.tv_usec, header->len);
if (header->len==1248)
{
byte timestampl[4];
byte factoryl[2]; byte lo[1248];
memcpy(&lo, pkt_data, 1248);
memcpy(×tampl, pkt_data + 42 + 12 * 100, 4);
memcpy(&factoryl, pkt_data + 42 + 12 * 100 + 4, 2);
//float fValuet = *((float*)×tampl); //系统时间
int fValue1 = *((float*)&factoryl[0]);
long int fValue = bytes4ToInt(timestampl);
if (stamptimecount == 0)
{
stamptimecount = fValue;
}
if ((fValue - stamptimecount) >= 100000)
{
stamptimecount = fValue;
frameint++;
}
/////保存数据
sprintf_s(fn, "%05d.txt", frameint);
//err = fopen_s( &stream, "crt_fopen_s.c", "r" )) !=0
if ((fp = fopen(fn, "a")) == NULL)
{
printf("Create File failure 1");
fclose(fp);
//exit(1);
} //read data
byte datal[12][100];
int packet_size = 100;
int azimuth;
float distance;
int passway;
for (int i = 0; i < 12; i++)
{
memcpy(&datal[i], pkt_data + 42 + i * 100, packet_size);
BYTE b[2];
BYTE b1[1];
memcpy(&b, pkt_data + 42 + i * 100 + 2, 2);
azimuth = bytes2ToInt(b);
UsefulData.JIAODU_[i] = azimuth;
UsefulData.JIAODU2_[i] = azimuth*0.01;
UsefulData.Timesec = header->ts.tv_sec;
//printf("%f\n", UsefulData.JIAODU2_[i]);
UsefulData.TimeStamp = fValue;
for (int j = 0; j < 32; j++)
{
memcpy(&b, pkt_data + 42 + i * 100 + 4 + j * 3, 2);
memcpy(&b1, pkt_data + 42 + i * 100 + 4 + j * 3 + 2, 1);
distance = float(bytes2ToInt(b))*0.002f; passway = bytes1ToInt(b1);
if (distance<0.05)
{
UsefulData.JULI_[i][j] = 0;
UsefulData.PointPos[i][j] = i * 32 + j;
//printf("%d ", UsefulData.PointPos[i][j]);
}
else
{
UsefulData.JULI_[i][j] = distance;
UsefulData.PointPos[i][j] = i * 32 + j;
} UsefulData.PASSEGEWAY_[i][j] = passway; UsefulData.TimeOffset[i][j] = Timeoffsetvec[i * 32 + j] + header->ts.tv_usec; //时间戳
UsefulData.SIN_[i][j] = lasersinvec[i * 32 + j];
UsefulData.COS_[i][j] = lasercosvec[i * 32 + j];
// printf("%f ", UsefulData.PASSEGEWAY_[i][j]); } }
//经度赋值
for (int i1 = 0; i1 < 12; i1++)
{
for (int k = 0; k < 32; k++)
{
if (k < 16)
{
UsefulData.Azimuth[i1][k] = UsefulData.JIAODU2_[i1];// +LASER_vert_correction[k];
}
else if (k >= 16)
{
if (i1 < 11)//前11帧
{
if (UsefulData.JIAODU2_[i1 + 1] < UsefulData.JIAODU2_[i1])
{
UsefulData.JIAODU2_[i1 + 1] += 360.0;
float azimuth2 = UsefulData.JIAODU2_[i1] + (UsefulData.JIAODU2_[i1 + 1] - UsefulData.JIAODU2_[i1]) / 2.0;
if (azimuth2 > 360)// 角度变化了
{
azimuth2 -= 360;
UsefulData.Azimuth[i1][k] = azimuth2;// +LASER_vert_correction[k - 16];
}
else
{
UsefulData.Azimuth[i1][k] = azimuth2;// +LASER_vert_correction[k - 16];
}
}
else
{
float azimuth4 = UsefulData.JIAODU2_[i1] + (UsefulData.JIAODU2_[i1 + 1] - UsefulData.JIAODU2_[i1]) / 2.0;
UsefulData.Azimuth[i1][k] = azimuth4;// +LASER_vert_correction[k - 16
}
}
else if (i1 == 11)//最后一帧
{
float azimuth3 = UsefulData.JIAODU2_[i1] + 0.2;
if (azimuth3 > 360)
{
azimuth3 -= 360;
}
else
{
}
UsefulData.Azimuth[i1][k] = azimuth3;//;+LASER_vert_correction[k - 16];
}
}
point.x = UsefulData.JULI_[i1][k] * UsefulData.COS_[i1][k] * sin(UsefulData.Azimuth[i1][k] / 180.0*3.1415926);
point.y = UsefulData.JULI_[i1][k] * UsefulData.COS_[i1][k] * cos(UsefulData.Azimuth[i1][k] / 180.0*3.1415926);
point.z = UsefulData.JULI_[i1][k] * UsefulData.SIN_[i1][k];
point.r = UsefulData.PASSEGEWAY_[i1][k];
point.tus = UsefulData.TimeOffset[i1][k];
point.tsec = UsefulData.Timesec;
if ((point.x == 0) && (point.y == 0) && (point.z == 0) || (UsefulData.JULI_[i1][k] <= 0.05))
{
}
else
{
//X Y Z Azimuth Distance Laser_ID
fprintf(fp, "%f %f %f %f %f %d ", point.x, point.y, point.z, UsefulData.Azimuth[i1][k], UsefulData.JULI_[i1][k], UsefulData.PointPos[i1][k] % 16);
fprintf(fp, "%f %f %ld %ld\n ", UsefulData.PASSEGEWAY_[i1][k], point.tus, header->ts.tv_sec,ustime);
}
} }
fclose(fp); } printf("\n\n");
} void UDPtoXYZfunALL(Usefulmessage data)
{
PointXYZ point[384];
FILE *fp;
if ((fp = fopen("all.txt", "a")) == NULL)
{
printf("Create File failure");
//getch();
exit(1);
}
for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 32; j++)
{
point[i * 32 + j].x = data.JULI_[i][j] * data.COS_[i][j] * sin(data.Azimuth[i][j] / 180.0*3.1415926);
point[i * 32 + j].y = data.JULI_[i][j] * data.COS_[i][j] * cos(data.Azimuth[i][j] / 180.0*3.1415926);
point[i * 32 + j].z = data.JULI_[i][j] * data.SIN_[i][j];
point[i * 32 + j].r = data.PASSEGEWAY_[i][j];
point[i * 32 + j].tus = data.TimeOffset[i][j];
point[i * 32 + j].tsec = data.Timesec;
if ((point[i * 32 + j].x == 0) && (point[i * 32 + j].y == 0) && (point[i * 32 + j].z == 0) || (data.JULI_[i][j] <= 0.05))
{
}
else
{
//X Y Z Azimuth Distance Laser_ID
fprintf(fp, "%f %f %f %f %f %d ", point[i * 32 + j].x, point[i * 32 + j].y, point[i * 32 + j].z, data.Azimuth[i][j], data.JULI_[i][j], data.PointPos[i][j] % 16);
fprintf(fp, "%f %f %f %f \n ", data.PASSEGEWAY_[i][j], point[i * 32 + j].tus, data.TimeStamp, data.Timesec); //fprintf(fp, "%f %f %f \n", point[i * 32 + j].x, point[i * 32 + j].y, point[i * 32 + j].z); }
}
}
fclose(fp);
} void UDPtoXYZfun(Usefulmessage data)
{
PointXYZ point[384];
FILE *fp;
if ((fp = fopen("my.txt", "a")) == NULL)
{
printf("Create File failure");
//getch();
exit(1);
}
for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 32; j++)
{
point[i * 32 + j].x = data.JULI_[i][j]*data.COS_[i][j]*sin(data.Azimuth[i][j]/180.0*3.1415926);
point[i * 32 + j].y = data.JULI_[i][j]*data.COS_[i][j]*cos(data.Azimuth[i][j]/180.0*3.1415926);
point[i * 32 + j].z = data.JULI_[i][j] * data.SIN_[i][j];
point[i * 32 + j].r = data.PASSEGEWAY_[i][j];
point[i * 32 + j].tus = data.TimeOffset[i][j];
point[i * 32 + j].tsec = data.Timesec;
if ((point[i * 32 + j].x == 0) && (point[i * 32 + j].y == 0) && (point[i * 32 + j].z == 0)||(data.JULI_[i][j]<=0.05))
{
}
else
{ //fprintf(fp, "%f %f %f %f %f %d\n", point[i * 32 + j].x, point[i * 32 + j].y, point[i * 32 + j].z,data.Azimuth[i][j],data.JULI_[i][j],data.PointPos[i][j]%16);
fprintf(fp, "%f %f %f \n", point[i * 32 + j].x, point[i * 32 + j].y, point[i * 32 + j].z); }
}
}
fclose(fp);
}
Velodyne线性激光雷达pcap文件格式及写入、数据解析 Lebal:激光雷达的更多相关文章
- PCAP文件格式分析(做抓包软件之必备)
转载源:http://blog.csdn.net/anzijin/article/details/2008333 http://www.ebnd.cn/2009/09/07/file-format-a ...
- pcap文件格式
pcap文件格式 pcap文件格式是bpf保存原始数据包的格式,很多软件都在使用,比如tcpdump.wireshark等等,了解pcap格式可以加深对原始数据包的了解,自己也可以手工构造任意的数 ...
- pcap文件格式解析
pcap文件格式是常用的数据报存储格式,包括wireshark在内的主流抓包软件都可以生成这种格式的数据包 下面对这种格式的文件简单分析一下: pcap文件的格式为: 文件头 24字节 ...
- 关于matlab向文件写入数据的方法——留着备用
MATLAB数据采集的时候,往往需要把得到的数据保存下来. fid = fopen(文件名,‘打开方式’): 说明:fid用于存储文件句柄值,如果fid>0,这说明文件打开成功.打开方式有如下选 ...
- IP流量重放与pcap文件格式解析
(作者:燕云 出处:http://www.cnblogs.com/SwordTao/ 欢迎转载,但也请保留这段声明,谢谢!) 君不见 黄河之水 天上来 奔流到海不复回 君不见 高堂明镜 悲 ...
- spark读取hdfs上的文件和写入数据到hdfs上面
def main(args: Array[String]): Unit = { val conf = new SparkConf() conf.set("spark.master" ...
- java向Excel文件写入数据
/*使用之前要记得导入第三的jar包这个是我之前使用的时候那别人的东西自己修改了一下 还没来得及好好地封装一下还望见谅,注释我感觉写的挺清楚的就在不进行解释代码了*/package com.zzp.E ...
- NPOI操作excel之写入数据到excel表
在上一篇<NPOI操作excel之读取excel数据>我们把excel数据写入了datatable中,本篇就讲如何把datatable数据写入excel中. using System; u ...
- Python中,添加写入数据到已经存在的Excel的xls文件,即打开excel文件,写入新数据
背景 Python中,想要打开已经存在的excel的xls文件,然后在最后新的一行的数据. 折腾过程 1.找到了参考资料: writing to existing workbook using xlw ...
随机推荐
- NumPy IO文件操作
NumPy - IO ndarray对象可以保存到磁盘文件并从磁盘文件加载. 可用的 IO 功能有: load()和save()函数处理 numPy 二进制文件(带npy扩展名) loadtxt()和 ...
- C-RAN
无线接入网(RAN)是移动运营商赖以生存的重要资产.传统的无线接入网具有以下特点: 1. 每一个基站连接若干个固定数量的扇区天线,并覆盖小片区域,每个基站只能处理本小区收发信号: 2. 系统的容量是干 ...
- 编辑器上的vim插件,常用到的快捷件
[vim]常用到的插件命令 [Esc] 退出编辑(输入,插入)模式,回到命令模式中(常用)i, I进入插入模式(Insert mode):i 为『从目前光标所在处插入』, I 为『在目前所在行的第一个 ...
- SSL和SSH的区别
SSL是一种国际标准的加密及身份认证通信协议,您用的浏览器就支持此协议.SSL(Secure Sockets Layer)最初是由美国Netscape公司研究出来的,后来成为了Internet网上安全 ...
- PhantomJS 和Selenium模拟页面js点击
由于自己不怎么会javascripts,无法找全所有的参数进行模拟提交,所以只能寻求Selenium和PhantpmJS的方式. 先说下ubuntu上怎么安装相应的环境,尤其PhantomJS安装比较 ...
- C# 为什么用接口实例化一个实现该接口的类?
这是多态的体现. 首先接口不能实例化的. 实现接口的类 实例 = new 实现接口的类()// 这样用不好吗? //这样已经不是好不好的问题了,这样的话,要接口有什么用?//用接口就是让实例和实现类的 ...
- openlayers自定义图层控制的实现
好久没写博文了,今天出来冒个泡. 最近一直在考虑一件事情,那就是openlayers中自定义wms的图层控制.用过openlayers的人都知道,在openlayers中有自带的图层控制的控件,调用方 ...
- canvas 绘制坐标轴
结果: 代码: <!DOCTYPE html> <html> <head lang="en"> <meta charset="U ...
- 【ci框架学习】环境搭建
系统 -- Ubuntu 14.0(虚拟机linux 实体机Windows) 目标环境 -- lnmp 附加内容: 1.目录共享(方便代码编写) 2.使用secure crt终端软件连接(便于操作,不 ...
- HDU - 5297:Y sequence (迭代&容斥)
Yellowstar likes integers so much that he listed all positive integers in ascending order,but he hat ...