登录·注册
文章详情
0
PCL正态分布变换(Normal Distributions Transform)进行点云配准
直接记录代码
void NormTran::run()
{
	readfile("bunny_0.asc", "bunny_1.asc");//加载目标点云数据
	//滤波

	pcl::ApproximateVoxelGrid<pcl::PointXYZ> approximate_voxel_filter;
	approximate_voxel_filter.setLeafSize(0.01, 0.01, 0.01);
	approximate_voxel_filter.setInputCloud(cloud_Source);
	approximate_voxel_filter.filter(*filtered_cloud_Source);
	std::cout << "Filtered cloud contains " << filtered_cloud_Source->size() << std::endl;
	//
	//初始化NDT对象
	pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ> ndt;

	//根据输入数据的尺寸设置相关参数
	ndt.setTransformationEpsilon(0.0001);//为终止条件设置最小转换差异
	ndt.setStepSize(0.1); //为more-thuente线搜索设置最大步长
	ndt.setResolution(0.01); //设置NDT网格网格结构的分辨率(voxelgridcovariance)
	ndt.setMaximumIterations(100);

	ndt.setInputSource(filtered_cloud_Source);//源点云
	ndt.setInputTarget(cloud_Target);//目标点云

	// 设置使用机器人测距法得到的粗略初始变换矩阵结果
	Eigen::AngleAxisf init_rotation(0.6931, Eigen::Vector3f::UnitZ());
	Eigen::Translation3f init_translation(1.79387, 0.72047, 0);
	Eigen::Matrix4f init_guess = (init_translation * init_rotation).matrix();

	// 计算需要的刚体变换以便将输入的源点云匹配到目标点云
	pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	ndt.align(*output_cloud, init_guess);

	//这个地方的output_cloud不能作为最终的源点云变换,因为上面对点云进行了滤波处理
	std::cout << "Normal Distributions Transform has converged:" << ndt.hasConverged()
		<< " score: " << ndt.getFitnessScore() << std::endl;

	pcl::transformPointCloud(*cloud_Source,*output_cloud,ndt.getFinalTransformation());

	// 初始化点云可视化对象
	boost::shared_ptr<pcl::visualization::PCLVisualizer>
		viewer_final(new pcl::visualization::PCLVisualizer("3D Viewer"));
	viewer_final->setBackgroundColor(0, 0, 0);  //设置背景颜色为黑色


	// 对目标点云着色可视化 (red).
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
		target_color(cloud_Target, 255, 0, 0);
	viewer_final->addPointCloud<pcl::PointXYZ>(cloud_Target, target_color, "target cloud");
	viewer_final->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
		1, "target cloud");

	//对源点云着色可视化(blue)
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
		source_color(cloud_Source, 0, 0, 255);
	viewer_final->addPointCloud(cloud_Source, source_color, "source_cloud");
	viewer_final->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
		1, "source cloud");

	//创建配准后的显示
	int v2 = 1;
	viewer_final->createViewPort(0.5, 0, 1, 1, v2);
	viewer_final->createViewPortCamera(v2);
	viewer_final->setBackgroundColor(0, 0, 0, v2);
	viewer_final->setCameraPosition(
		0, 0, 0,
		0, 0, -1,
		0, 0, 0, v2);

	// 对转换后的源点云着色 (green)可视化.
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
		output_color(output_cloud, 0, 255, 0);

	viewer_final->addPointCloud(cloud_Source, source_color, "source_cloud1",v2);
	viewer_final->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
		1, "source cloud1",v2);

	viewer_final->addPointCloud<pcl::PointXYZ>(output_cloud, output_color, "output cloud",v2);
	viewer_final->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
		1, "output cloud",v2);

	// 启动可视化
	viewer_final->addCoordinateSystem(1.0);  //显示XYZ指示轴
	viewer_final->initCameraParameters();   //初始化摄像头参数

	// 等待直到可视化窗口关闭
	while (!viewer_final->wasStopped())
	{
		viewer_final->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}

}