#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, 还有一条收敛条件是均方误差和小于阈值, 停止迭代。
*/
HDL_Graph_slam骨头记(5)——src/hdl_graph_slam/registration
原文:https://www.cnblogs.com/chenlinchong/p/11837317.html