#include <hdl_graph_slam/registrations.hpp> #include <iostream> #include <pcl/registration/ndt.h> #include <pcl/registration/icp.h> #include <pcl/registration/gicp.h> #include <pclomp/ndt_omp.h> #include <pclomp/gicp_omp.h> namespace hdl_graph_slam { boost::shared_ptr<pcl::Registration<pcl::PointXYZI, pcl::PointXYZI>> select_registration_method(ros::NodeHandle& pnh) { using PointT = pcl::PointXYZI; // select a registration method (ICP, GICP, NDT) std::string registration_method = pnh.param<std::string>("registration_method", "NDT_OMP"); if(registration_method == "ICP") { std::cout << "registration: ICP" << std::endl; boost::shared_ptr<pcl::IterativeClosestPoint<PointT, PointT>> icp(new pcl::IterativeClosestPoint<PointT, PointT>()); icp->setTransformationEpsilon(pnh.param<double>("transformation_epsilon", 0.01)); //前一个变换矩阵和当前变换矩阵的差异小于阈值时,就认为已经收敛了,是一条收敛条件 icp->setMaximumIterations(pnh.param<int>("maximum_iterations", 64)); icp->setUseReciprocalCorrespondences(pnh.param<bool>("use_reciprocal_correspondences", false)); //Set whether to use reciprocal correspondence or not. return icp; } else if(registration_method.find("GICP") != std::string::npos) { if(registration_method.find("OMP") == std::string::npos) { std::cout << "registration: GICP" << std::endl; boost::shared_ptr<pcl::GeneralizedIterativeClosestPoint<PointT, PointT>> gicp(new pcl::GeneralizedIterativeClosestPoint<PointT, PointT>()); gicp->setTransformationEpsilon(pnh.param<double>("transformation_epsilon", 0.01)); gicp->setMaximumIterations(pnh.param<int>("maximum_iterations", 64)); gicp->setUseReciprocalCorrespondences(pnh.param<bool>("use_reciprocal_correspondences", false)); gicp->setCorrespondenceRandomness(pnh.param<int>("gicp_correspondence_randomness", 20)); gicp->setMaximumOptimizerIterations(pnh.param<int>("gicp_max_optimizer_iterations", 20)); return gicp; } else { std::cout << "registration: GICP_OMP" << std::endl; boost::shared_ptr<pclomp::GeneralizedIterativeClosestPoint<PointT, PointT>> gicp(new pclomp::GeneralizedIterativeClosestPoint<PointT, PointT>()); gicp->setTransformationEpsilon(pnh.param<double>("transformation_epsilon", 0.01)); gicp->setMaximumIterations(pnh.param<int>("maximum_iterations", 64)); gicp->setUseReciprocalCorrespondences(pnh.param<bool>("use_reciprocal_correspondences", false)); gicp->setCorrespondenceRandomness(pnh.param<int>("gicp_correspondence_randomness", 20)); gicp->setMaximumOptimizerIterations(pnh.param<int>("gicp_max_optimizer_iterations", 20)); return gicp; } } else { if(registration_method.find("NDT") == std::string::npos ) { std::cerr << "warning: unknown registration type(" << registration_method << ")" << std::endl; std::cerr << " : use NDT" << std::endl; } double ndt_resolution = pnh.param<double>("ndt_resolution", 0.5); if(registration_method.find("OMP") == std::string::npos) { std::cout << "registration: NDT " << ndt_resolution << std::endl; boost::shared_ptr<pcl::NormalDistributionsTransform<PointT, PointT>> ndt(new pcl::NormalDistributionsTransform<PointT, PointT>()); ndt->setTransformationEpsilon(pnh.param<double>("transformation_epsilon", 0.01)); ndt->setMaximumIterations(pnh.param<int>("maximum_iterations", 64)); ndt->setResolution(ndt_resolution); return ndt; } else { int num_threads = pnh.param<int>("ndt_num_threads", 0); std::string nn_search_method = pnh.param<std::string>("ndt_nn_search_method", "DIRECT7"); std::cout << "registration: NDT_OMP " << nn_search_method << " " << ndt_resolution << " (" << num_threads << " threads)" << std::endl; boost::shared_ptr<pclomp::NormalDistributionsTransform<PointT, PointT>> ndt(new pclomp::NormalDistributionsTransform<PointT, PointT>()); if(num_threads > 0) { ndt->setNumThreads(num_threads); } ndt->setTransformationEpsilon(pnh.param<double>("transformation_epsilon", 0.01)); ndt->setMaximumIterations(pnh.param<int>("maximum_iterations", 64)); ndt->setResolution(ndt_resolution); if(nn_search_method == "KDTREE") { ndt->setNeighborhoodSearchMethod(pclomp::KDTREE); } else if (nn_search_method == "DIRECT1") { ndt->setNeighborhoodSearchMethod(pclomp::DIRECT1); } else { ndt->setNeighborhoodSearchMethod(pclomp::DIRECT7); } return ndt; } } return nullptr; } } /* 后记: SVD是奇异值分解, Singular Value Decomposition。 CL的icp里的transformation estimation是基于SVD的; 使用之前要至少set三个参数: setMaximumIterations, 最大迭代次数,icp是一个迭代的方法, 最多迭代这些次; setTransformationEpsilon, 前一个变换矩阵和当前变换矩阵的差异小于阈值时,就认为已经收敛了, 是一条收敛条件; setEuclideanFitnessEpsilon, 还有一条收敛条件是均方误差和小于阈值, 停止迭代。 */
来源:https://www.cnblogs.com/chenlinchong/p/11837317.html