镭神32线激光雷达pcap数据离线解析 支持A C型 矫正激光阵列有序化点云

本文介绍了如何对镭神32线激光雷达的 pcap 数据进行离线解析,支持A和C型矫正,实现激光阵列有序化点云处理。
摘要由CSDN通过智能技术生成
#include "liadr32Decoder.h"
#define LIDAR_VERSION 2				//



static LidarDatas LidarDataFrist;	//fisrt echo
static LidarDatas LidarDataSecond;	//second echo

static std::ofstream outputFile;	//output the parsed data
static uint64_t GPStimestamp = 0;	//GPS timestamp
static pcap_t *pfile;

double Angle1 = 0.0, Angle2 = 0.0;	//水平补偿角度
double device_type = 0.0;
int frame_num = 1;


double theta_3[32] = { -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1,
	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

//double theta_2[32] = { -16, 0, -15, 1, -14, 2, -13, 3, -12, 4, -11, 5, -10, 6, -9, 7, -8,
//						8, -7, 9, -6, 10, -5, 11, -4, 12, -3, 13, -2, 14, -1, 15 };
 
 
double theta_2[32] = { -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1,
	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };  // for a 

double theta_C[32] = { -18, -15, -12, -10, -8, -7, -6, -5, -4, -3.33, -2.66,-3, -2.33, -2, -1.33, -1.66, -1, -0.66,
 	0,-0.33, 0.33, 0.66, 1.33, 1, 1.66, 2, 3, 4, 6, 8, 11, 14}; // for c  angval 重写theta_2

static int exchange[32] = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 };
double vertialAngles[32] = {};
double const PI = 3.1415926;
double cosTheta[32] = { 0 };
double sinTheta[32] = { 0 };

static const float DistanePrecision = 2.5;  //mm
 
std::vector<Cld_point> temp_p_all;
int col_num = 0;
std::vector<Cld_point> channel; // 32
std::vector<std::vector<Cld_point>> thread;
std::vector<std::vector<Cld_point>> thread_rebuild;
double angle_bias;
double angle_resolution = 0.18;
int thread_bias = 0;
void HowToUse()
{
	createSaveFile();
	resetDataBuff();
	openPcapFile("E:/code/LSC32解析/test.pcap");
	//C:/Users/leishen/Desktop/iScan-Pcd-1 - 副本.pcap
	readPcapFile();   // lidarDataDecoder
	resetDataBuff();
}

void createSaveFile()
{
	time_t nowtime;
	struct tm *p;
	time(&nowtime);
	p = localtime(&nowtime);
	char filename[50] = "";
	sprintf(filename, "./output/%06d-%02d%02d%02d-%02d%02d.txt", frame_num-1 ,p->tm_year + 1900 , p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min);
	const char *file = filename;
	outputFile.close();
	outputFile.open(file, std::ios::app);
}

void createSaveFile_frame(int frame)
{
	time_t nowtime;
	struct tm* p;
	time(&nowtime);
	p = localtime(&nowtime);
	char filename[60] = "";
	sprintf(filename, "./output/%06d-%02d%02d%02d-%02d%02d.txt", frame, p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min);
	const char* file = filename;
	outputFile.close();
	outputFile.open(file, std::ios::app);
}

void openPcapFile(const char *fileName)
{
	char errbuf[100];
	pfile = pcap_open_offline(fileName, errbuf);
	if (NULL == pfile) {
		std::cout << errbuf;
	}
}

void readPcapFile()  // lidarDataDecoder
{
	pcap_pkthdr *pkthdr = 0;
	const u_char *pktdata = 0;
	bool isFindDevPacket = false;
	unsigned char databuf[1206];
	while (pcap_next_ex(pfile, &pkthdr, &pktdata) > 0) 
	{
		if (pkthdr->caplen == 1248 && (pktdata[42] == 0xa5 && pktdata[43] == 0xff && pktdata[44] == 0x00 && pktdata[45] == 0x5a)) 
		{
			pktdata = pktdata + 42;
			
			int	timeStampsFlag = 0;
			if (LIDAR_VERSION == 2)
				timeStampsFlag = 36;
			else
				timeStampsFlag = 52;
			struct tm cur_time;
			cur_time.tm_year = pktdata[timeStampsFlag++] + 2000 - 1900;
			cur_time.tm_mon = pktdata[timeStampsFlag++] - 1;
			cur_time.tm_mday = pktdata[timeStampsFlag++];
			cur_time.tm_hour = pktdata[timeStampsFlag++]/* + 8*/;
			cur_time.tm_min = pktdata[timeStampsFlag++];
			cur_time.tm_sec = pktdata[timeStampsFlag++];
			GPStimestamp = static_cast<uint64_t>(mktime(&cur_time));

			static bool flag = true;
			if (flag) {
				flag = false;

				if (LIDAR_VERSION == 2)
				{
					Angle1 = (pktdata[34] * 256 + pktdata[35]) / 100.f;
					Angle2 = (pktdata[42] * 256 + pktdata[43]) / 100.f;
					 
					std::cout << "A1:" <<Angle1 << std::endl;
					std::cout << "A2:" <<Angle2 << std::endl;
					 
					//device_type = pktdata[0:8];
					//垂直角度
					if (Angle2 != 0)
					{
						for (int i = 0; i < 32; i++)
						{
							uint8_t data1 = pktdata[882 + 2 * i];
							uint8_t data2 = pktdata[882 + 2 * i + 1];
							int angleVal = data1 * 256 + data2;
							if (angleVal > 32767) {
								angleVal = angleVal - 65535;
							}
							theta_2[i] = (double)angleVal / 100.0;
						}
					}
					
					for (int i = 0; i < 32; i++)
					{
						cosTheta[i] = cos(theta_2[i] * PI / 180);
						//std::cout << theta_2[i] << std::endl;
						sinTheta[i] = sin(theta_2[i] * PI / 180);
						//std::cout << sinTheta[i] << std::endl;
					}
				}
				else
				{
					Angle1 = (pktdata[186] * 256 + pktdata[187]) / 100.f;
					Angle2 = (pktdata[190] * 256 + pktdata[191]) / 100.f;
					

					//垂直角度
					for (int i = 0; i < 32; i++) {
						uint8_t data1 = pktdata[245 + 2 * i];
						uint8_t data2 = pktdata[245 + 2 * i + 1];
						int angleVal = data1 * 256 + data2;
						if (angleVal > 32767) {
							angleVal = angleVal - 65535;
						}
						//将角度的旧排序转换为新排序
						vertialAngles[exchange[i]] = (double)angleVal / 100.0;
					}
					//float theta1[32] = { -16, 0, -15, 1, -14, 2, -13, 3, -12, 4, -11, 5, -10, 6, -9, 7, -8, 8, -7, 9, -6, 10, -5, 11, -4, 12, -3, 13, -2, 14, -1, 15 };
					for (int i = 0; i < 32; i++)
					{
						theta_3[i] = vertialAngles[i];
						cosTheta[i] = cos(theta_3[i] * PI / 180);
						sinTheta[i] = sin(theta_3[i] * PI / 180);
					}
				}

			}
			isFindDevPacket = true;
		}
		//data
		if (isFindDevPacket && pkthdr->caplen == 1248 && (pktdata[42] == 0xff && pktdata[43] == 0xee)) {
			pktdata = pktdata + 42;
			memcpy(databuf, pktdata, 1206);
			lidarDataDecoder(databuf);
		}
	}
	pcap_close(pfile);
}

void lidarDataDecoder(const unsigned char *data)
{
	uint64_t mtimestamps = 16777216 * data[1203] + 65536 * data[1202] + 256 * data[1201] + data[1200] + (GPStimestamp) * 10e5;
	for (int i = 0; i < 12; i++) {
		if ((data[3 + 100 * i] * 256 + data[2 + 100 * i]) / 100.f >= 360.0) {
			LidarDataFrist.angle.push_back(0);
		}
		else {
			LidarDataFrist.angle.push_back((data[3 + 100 * i] * 256 + data[2 + 100 * i]) / 100.f);   //提取出一圈中的方位角度值
		}
		for (int j = 0; j < 32; j++) {
			LidarDataFrist.distance[j].push_back((data[5 + 3 * j + 100 * i] * 256 + data[4 + 3 * j + 100 * i]) / DistanePrecision);
			LidarDataFrist.intensity[j].push_back(data[6 + 3 * j + 100 * i]);
			LidarDataFrist.mtimestamp[j].push_back(mtimestamps + (32 * i + j) * 1.536 - 588.288);
		}
		if (LidarDataFrist.angle.size() >= 2) 
		{
			for (int j = 0; j < 32; j++) {
				float mdiff = (LidarDataFrist.angle.back() - LidarDataFrist.angle[LidarDataFrist.angle.size() - 2]);
				mdiff = mdiff >= 0 ? mdiff : mdiff + 360;
				if ((LidarDataFrist.angle[LidarDataFrist.angle.size() - 2] + (mdiff / 32) * j) < 360.0)
					LidarDataFrist.azimuth[j].push_back(LidarDataFrist.angle[LidarDataFrist.angle.size() - 2] + (mdiff / 32) * j);
				else
					LidarDataFrist.azimuth[j].push_back(LidarDataFrist.angle[LidarDataFrist.angle.size() - 2] + (mdiff / 32) * j - 360.0);
			}
		}
		//a circle
		if (LidarDataFrist.angle.size() >= 2 && abs(LidarDataFrist.angle.back() - LidarDataFrist.angle[LidarDataFrist.angle.size() - 2]) > 180) {
			float mdiff = (LidarDataFrist.angle.back() - LidarDataFrist.angle[LidarDataFrist.angle.size() - 2]);
			mdiff = mdiff >= 0 ? mdiff : mdiff + 360;
			for (size_t j = 0; j < 32; j++)
			{
				if ((LidarDataFrist.angle.back() + (mdiff / 32) * j) < 360)
					LidarDataFrist.azimuth[j].push_back(LidarDataFrist.angle[LidarDataFrist.angle.size() - 2] + (mdiff / 32) * j);
				else
					LidarDataFrist.azimuth[j].push_back(LidarDataFrist.angle[LidarDataFrist.angle.size() - 2] + (mdiff / 32) * j - 360);
			}


			//print first echo coordinate
			coordinateParsing(LidarDataFrist);

			//clear buffer
			resetDataBuff();
		}
	}
}
void coordinateParsing(LidarDatas LidarData)
{
	for (int i = 0; i < 32; i++)
	{
		for (int j = 0; j < (int)LidarData.azimuth[i].size(); j++)
		{
			double x, y, z;
			if (LIDAR_VERSION == 2)
			{
				if (i % 2 == 0) {
					x = (LidarData.distance[i][j] * cos((LidarData.azimuth[i][j] + Angle1) * PI / 180) * cosTheta[i] +
						4.94 * cos((LidarData.azimuth[i][j] + Angle2 - 12.98) * PI / 180)) / 100.f;
					y = -(LidarData.distance[i][j] * sin((LidarData.azimuth[i][j] + Angle1) * PI / 180) * cosTheta[i] +
						4.94 * sin((LidarData.azimuth[i][j] + Angle2 - 12.98) * PI / 180)) / 100.f;
					z = LidarData.distance[i][j] * sinTheta[i] / 100.f;

				}
				else {
					x = (LidarData.distance[i][j] * cos((LidarData.azimuth[i][j] - Angle1) * PI / 180) * cosTheta[i] +
						4.94 * cos((LidarData.azimuth[i][j] + Angle1 - 12.98) * PI / 180)) / 100.f;
					y = -(LidarData.distance[i][j] * sin((LidarData.azimuth[i][j] - Angle1) * PI / 180) * cosTheta[i] +
						4.94 * sin((LidarData.azimuth[i][j] + Angle1 - 12.98) * PI / 180)) / 100.f;
					z = LidarData.distance[i][j] * sinTheta[i] / 100.f;
					//std::cout << sinTheta[i] << std::endl;

				}
			}

			else
			{
				if (i % 4 <= 1) {
					x = (LidarData.distance[i][j] * cos((LidarData.azimuth[i][j] + Angle2) * PI / 180) * cosTheta[i] +
						4.94 * cos((LidarData.azimuth[i][j] + Angle2 - 12.98) * PI / 180)) / 100.f;
					y = -(LidarData.distance[i][j] * sin((LidarData.azimuth[i][j] + Angle2) * PI / 180) * cosTheta[i] +
						4.94 * sin((LidarData.azimuth[i][j] + Angle2 - 12.98) * PI / 180)) / 100.f;
					z = LidarData.distance[i][j] * sinTheta[i] / 100.f;
				}
				else {
					x = (LidarData.distance[i][j] * cos((LidarData.azimuth[i][j] + Angle1) * PI / 180) * cosTheta[i] +
						4.94 * cos((LidarData.azimuth[i][j] + Angle1 - 12.98) * PI / 180)) / 100.f;
					y = -(LidarData.distance[i][j] * sin((LidarData.azimuth[i][j] + Angle1) * PI / 180) * cosTheta[i] +
						4.94 * sin((LidarData.azimuth[i][j] + Angle1 - 12.98) * PI / 180)) / 100.f;
					z = LidarData.distance[i][j] * sinTheta[i] / 100.f;
				}
			}
			Cld_point temp;
			temp.x = x; temp.y = y; temp.z = z;
			temp.azimuth = LidarData.azimuth[i][j];
			temp.intensity = LidarData.intensity[i][j];
			temp.mtimestamp = LidarData.mtimestamp[i][j];
			temp_p_all.push_back(temp);

			//outputFile << x << " " << y << " " << z << " "
			//	<< LidarData.intensity[i][j] << " "
			//	<< LidarData.azimuth[i][j] << " "
			//	//<< LidarData.mtimestamp[i][j] <<" "
			//	<< std::endl;
		}
	}
	std::cout << "1" << std::endl;

	col_num = temp_p_all.size() / 32;

	for (int i = 0; i < col_num; i++)
	{
		channel.clear();
		for (int j = 0; j < 32; j++)
			channel.push_back(temp_p_all[j * col_num + i]);

		thread.push_back(channel);
	}
	if (Angle2 != 0) //c
	{
		angle_bias = Angle1 + Angle2;
		angle_bias = angle_bias / 2.0;
		 
	}
	else
	{
		angle_bias = 2.0 * Angle1;
		
	}
	thread_bias = ceil(angle_bias / angle_resolution);

	//thread_bias = ceil(angle_bias / angle_resolution);  
	//std::cout << "thread_bias" << std::endl;
	//std::cout << thread_bias << std::endl;
	 
	for (int i = 0; i < thread.size(); i++)
	{
		channel.clear();
		
		for (int j = 0; j < 32; j++)
		{
			if (j % 2 == 1) // 0 2 4为 右侧  1 3 5 为左laser
			{
				int temp_t = rtn_amend_thread_num(i, thread.size(), thread_bias);
				//std::cout << "i:" << i << std::endl;
				//std::cout << "temp_t:" << temp_t << std::endl;
				//std::cout << temp_t << std::endl;
				//std::cout << j << std::endl;
				int b = j - 1;
				channel.push_back(thread[temp_t][b]);
				channel.push_back(thread[i][j]);
				if (Angle2 != 0 && (j == 11 || j == 15 || j == 19 || j == 23)) // type c A1order
				{
					Cld_point temp1, temp2;
					temp1 = channel[channel.size() - 1];
					temp2 = channel[channel.size() - 2];
					channel.pop_back();
					channel.pop_back();
					channel.push_back(temp1);
					channel.push_back(temp2);

				}
				

			}
		}
		//std::cout << channel.size() << std::endl;
		quickSort(channel, 0, channel.size()-1);
		thread_rebuild.push_back(channel);
	}
	 
	for (int i = 0; i < thread_rebuild.size(); i++)
	{
		channel = thread_rebuild[i];
		for (int j = 0; j < 32; j++)
		{
			outputFile << channel[j].x << " " << channel[j].y << " " << channel[j].z << " "
				<< channel[j].intensity << " "
				//<< channel[j].azimuth << " "
				//<< channel[j].mtimestamp << " "
				<< channel.distance[i][j]
				<< std::endl;
		}

	}

	createSaveFile_frame(frame_num++);
	temp_p_all.clear();
	temp_p_all.shrink_to_fit();
	thread.clear();
	thread.shrink_to_fit();
	thread_rebuild.clear();
	thread_rebuild.shrink_to_fit();
}

int rtn_amend_thread_num(int t_in, int t_all, int t_bias) // for left laserseneor
{
	int t_amend = 0;
	t_amend = t_in - t_bias;
	if (t_amend < 0)
		t_amend = t_all-1 + t_amend;
	return t_amend;
}

 
void quickSort(std::vector<Cld_point> &array, int start, int end)
{
	if (start >= end) return;
	Cld_point temp = array[start];
	int L = start;          //L,R左右哨兵
	int R = end;

	while (L < R) {
		while (L < R && array[R].z >= temp.z)             
			R--;
		if (L < R)                                  
			array[L++] = array[R];
		while (L < R && array[L].z <= temp.z)
			L++;
		if (L < R)
			array[R--] = array[L];
	}
	array[L] = temp;                             
	quickSort(array, start, L - 1);
	quickSort(array, L + 1, end);
	
}

void resetDataBuff()
{
	LidarDataFrist.angle.clear();
	LidarDataFrist.azimuth.clear();
	LidarDataFrist.azimuth.resize(32);
	LidarDataFrist.distance.clear();
	LidarDataFrist.distance.resize(32);
	LidarDataFrist.intensity.clear();
	LidarDataFrist.intensity.resize(32);
	LidarDataFrist.mtimestamp.clear();
	LidarDataFrist.mtimestamp.resize(32);

	LidarDataSecond.angle.clear();
	LidarDataSecond.azimuth.clear();
	LidarDataSecond.azimuth.resize(32);
	LidarDataSecond.distance.clear();
	LidarDataSecond.distance.resize(32);
	LidarDataSecond.intensity.clear();
	LidarDataSecond.intensity.resize(32);
	LidarDataSecond.mtimestamp.clear();
	LidarDataSecond.mtimestamp.resize(32);


}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_32949333

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值