LiDAR-Velodyne激光雷达pcap文件解析

2024-02-14 23:38

本文主要是介绍LiDAR-Velodyne激光雷达pcap文件解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

       在使用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 16int 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" )) !=0if ((fp = fopen(fn, "a")) == NULL){printf("Create File failure 1");fclose(fp);//exit(1);}//read databyte 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);
}


这篇关于LiDAR-Velodyne激光雷达pcap文件解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/709895

相关文章

全面解析Golang 中的 Gorilla CORS 中间件正确用法

《全面解析Golang中的GorillaCORS中间件正确用法》Golang中使用gorilla/mux路由器配合rs/cors中间件库可以优雅地解决这个问题,然而,很多人刚开始使用时会遇到配... 目录如何让 golang 中的 Gorilla CORS 中间件正确工作一、基础依赖二、错误用法(很多人一开

Mysql中设计数据表的过程解析

《Mysql中设计数据表的过程解析》数据库约束通过NOTNULL、UNIQUE、DEFAULT、主键和外键等规则保障数据完整性,自动校验数据,减少人工错误,提升数据一致性和业务逻辑严谨性,本文介绍My... 目录1.引言2.NOT NULL——制定某列不可以存储NULL值2.UNIQUE——保证某一列的每一

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

MySQL CTE (Common Table Expressions)示例全解析

《MySQLCTE(CommonTableExpressions)示例全解析》MySQL8.0引入CTE,支持递归查询,可创建临时命名结果集,提升复杂查询的可读性与维护性,适用于层次结构数据处... 目录基本语法CTE 主要特点非递归 CTE简单 CTE 示例多 CTE 示例递归 CTE基本递归 CTE 结

Spring Boot 3.x 中 WebClient 示例详解析

《SpringBoot3.x中WebClient示例详解析》SpringBoot3.x中WebClient是响应式HTTP客户端,替代RestTemplate,支持异步非阻塞请求,涵盖GET... 目录Spring Boot 3.x 中 WebClient 全面详解及示例1. WebClient 简介2.

在MySQL中实现冷热数据分离的方法及使用场景底层原理解析

《在MySQL中实现冷热数据分离的方法及使用场景底层原理解析》MySQL冷热数据分离通过分表/分区策略、数据归档和索引优化,将频繁访问的热数据与冷数据分开存储,提升查询效率并降低存储成本,适用于高并发... 目录实现冷热数据分离1. 分表策略2. 使用分区表3. 数据归档与迁移在mysql中实现冷热数据分

C#解析JSON数据全攻略指南

《C#解析JSON数据全攻略指南》这篇文章主要为大家详细介绍了使用C#解析JSON数据全攻略指南,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、为什么jsON是C#开发必修课?二、四步搞定网络JSON数据1. 获取数据 - HttpClient最佳实践2. 动态解析 - 快速

Spring Boot3.0新特性全面解析与应用实战

《SpringBoot3.0新特性全面解析与应用实战》SpringBoot3.0作为Spring生态系统的一个重要里程碑,带来了众多令人兴奋的新特性和改进,本文将深入解析SpringBoot3.0的... 目录核心变化概览Java版本要求提升迁移至Jakarta EE重要新特性详解1. Native Ima

spring中的@MapperScan注解属性解析

《spring中的@MapperScan注解属性解析》@MapperScan是Spring集成MyBatis时自动扫描Mapper接口的注解,简化配置并支持多数据源,通过属性控制扫描路径和过滤条件,利... 目录一、核心功能与作用二、注解属性解析三、底层实现原理四、使用场景与最佳实践五、注意事项与常见问题六

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应