下面代码的功能是:把一个文件夹中所有的pcd文件进行ICP点云配准,并且把每帧结果使用PCL的cloud_viewer进行显示。因为是在ROS下使用,所以还有一个ROS的发布操作(可忽略)。
源码如下:
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <dirent.h>
#include <vector>
#include <cstring>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/icp.h>
#include <ros/ros.h>
#include <pcl/visualization/cloud_viewer.h>
#include "position/Position.h"using namespace std;#define NUMBER 50000
#define ITERATIONS 5
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloudT;// function:获取路径下所有文件名,存在filenames中
void getFiles(string path, vector<string>& filenames)
{DIR *pDir;struct dirent* ptr;if(!(pDir = opendir(path.c_str()))){cout<<"Folder doesn't Exist!"<<endl;return;}while((ptr = readdir(pDir))!=0) {if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0){filenames.push_back(path + "/" + ptr->d_name);}}closedir(pDir);
}// function:读取整个文件夹下pcd文件,通过PCL将其中的坐标存储在position_x和position_y中
void Get_position_data(float *position_x, float *position_y, int &position_num,int &file_count) {string filePath = "/home/lyn/pcd"; // 待读取文件夹路径string pwd = get_current_dir_name();string logPath = pwd + "/pcd.log";vector<string> files;//获取该路径下的所有文件getFiles(filePath, files);float bckgr_gray_level = 0.0; // Blackfloat txt_gray_lvl = 1.0 - bckgr_gray_level;PointCloudT::Ptr first_cloud (new PointCloudT);PointCloudT::Ptr second_cloud (new PointCloudT);PointCloudT::Ptr cloud_icp(new PointCloudT);pcl::visualization::PCLVisualizer viewer("viewer");fstream log;log.open(logPath,ios::app);if(log.fail()){cout<<"open fail"<<endl;}else{log<<"file size is "<<(int)files.size()<<endl;log<<"begin reading,file count is "<<file_count<<endl;}if(file_count==(int)files.size()){log<<"stop reading"<<endl;return;}if(pcl::io::loadPCDFile<PointT>(files[file_count],*first_cloud)==-1){PCL_ERROR("Couldn't read file test_pcd.pcd\n");return ;}else{log<<"file 0 is "<<files[file_count]<<endl;}if(pcl::io::loadPCDFile<PointT>(files[file_count+1],*second_cloud)==-1){PCL_ERROR("Couldn't read file test_pcd.pcd\n");return ;}else{log<<"file 1 is "<<files[file_count+1]<<endl;}file_count += 2;pcl::IterativeClosestPoint<PointT,PointT> icp;icp.setMaximumIterations(ITERATIONS);icp.setInputSource(first_cloud);icp.setInputTarget(second_cloud);icp.align(*cloud_icp);if(icp.hasConverged()){std::cout<<"\nICP has converged" << icp.getFitnessScore()<<std::endl;}else{PCL_ERROR ("\nICP has not converged.\n");}int v1 (0);int v2 (1);viewer.createViewPort (0.0, 0.0, 0.5, 1.0, v1);viewer.createViewPort (0.5, 0.0, 1.0, 1.0, v2);pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_color(first_cloud,(int) 255 * txt_gray_lvl, (int) 255 * txt_gray_lvl,(int) 255 * txt_gray_lvl);viewer.addPointCloud(first_cloud,cloud_color,"cloud_in_v1",v1);viewer.addPointCloud(first_cloud,cloud_color,"cloud_in_v2",v2);pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_tr_color(second_cloud, 20, 180, 20);viewer.addPointCloud(second_cloud,cloud_tr_color,"cloud_tr",v1);pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_icp_color(cloud_icp, 180, 20, 20);viewer.addPointCloud(cloud_icp,cloud_icp_color,"cloud_icp",v2);viewer.setCameraPosition (-3.68332, 2.94092, 12.71266, 0.289847, 0.921947, -0.256907, 0);viewer.setSize (1280, 1960); // Visualiser window sizefor (int i=2; i<(int)files.size(); i++) { PointCloudT::Ptr cloud_in (new PointCloudT);PointCloudT::Ptr cloud_temp (new PointCloudT);if(pcl::io::loadPCDFile<PointT>(files[i], *cloud_in)==-1) { //*打开点云文件 PCL_ERROR("Couldn't read file test_pcd.pcd\n");return ;}else{log<<"target file is "<<files[i]<<endl; }// The Iterative Closest Point algorithm*cloud_temp = *cloud_icp;pcl::IterativeClosestPoint<PointT,PointT> icp;icp.setMaximumIterations(ITERATIONS);icp.setInputSource(cloud_icp);icp.setInputTarget(cloud_in);icp.align(*cloud_icp);if(icp.hasConverged()){std::cout<<"\nICP has converged" << icp.getFitnessScore()<<std::endl; }else{PCL_ERROR ("\nICP has not converged.\n");}viewer.updatePointCloud(cloud_in,cloud_color,"cloud_in_v1");viewer.updatePointCloud(cloud_in,cloud_color,"cloud_in_v2");viewer.updatePointCloud(cloud_temp,cloud_tr_color,"cloud_tr");viewer.updatePointCloud(cloud_icp,cloud_icp_color,"cloud_icp");for(size_t t=0; t<cloud_icp->points.size(); ++t) {position_x[position_num] = cloud_icp->points[t].x;position_y[position_num] = cloud_icp->points[t].y;position_num++;}file_count++;} log<<"end reading,file count is"<<file_count<<endl;log.close();return ;
}int main(int argc, char** argv) {float *position_x = (float *)malloc(sizeof(float) * NUMBER);float *position_y = (float *)malloc(sizeof(float) * NUMBER);// ROS节点初始化ros::init(argc, argv, "position_publisher");// 创建节点句柄ros::NodeHandle n;// 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10ros::Publisher position_info_pub = n.advertise<position::Position>("/position_info", 10);//设置循环的频率ros::Rate loop_rate(1);int count = 0;int file_count = 0;while (ros::ok()) {int position_num = 0;Get_position_data(position_x, position_y, position_num,file_count);// 初始化learning_topic::Person类型的消息position::Position position_msg;for (int i=0; i<position_num; i++) {position_msg.position_x[i] = position_x[i];position_msg.position_y[i] = position_y[i];}position_msg.position_num = position_num;// 发布消息position_info_pub.publish(posirtion_msg);ROS_INFO("Publish Successfully!");cout << "point num is:" << position_num << endl;// 按照循环频率延时loop_rate.sleep();sleep(5);}return 0;
}