使用PCL进行ICP点云配准

  下面代码的功能是:把一个文件夹中所有的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;  // Black
    float 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 size
    for (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,队列长度10
    ros::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;
}


猜你喜欢

转载自blog.csdn.net/gls_nuaa/article/details/133207994
今日推荐