#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/ndt.h>int main(int argc, char** argv)
{// 检查输入参数if (argc != 3){PCL_ERROR("请提供两个PCD文件作为输入: source.pcd target.pcd\n");return (-1);}// 读取源点云和目标点云pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_source(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_target(new pcl::PointCloud<pcl::PointXYZ>);if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[1], *cloud_source) == -1){PCL_ERROR("无法读取文件 %s\n", argv[1]);return (-1);}if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[2], *cloud_target) == -1){PCL_ERROR("无法读取文件 %s\n", argv[2]);return (-1);}// 创建NDT配准对象pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ> ndt;// 设置NDT参数ndt.setTransformationEpsilon(0.1);ndt.setStepSize(0.9);ndt.setResolution(0.9);ndt.setMaximumIterations(10);// 设置源点云和目标点云ndt.setInputSource(cloud_source);ndt.setInputTarget(cloud_target);// 进行配准pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_registered(new pcl::PointCloud<pcl::PointXYZ>);ndt.align(*cloud_registered);if (ndt.hasConverged()){std::cout << "配准成功!" << std::endl;std::cout << "迭代次数: " << ndt.getFinalNumIteration() << std::endl;std::cout << "最终变换矩阵: \n" << ndt.getFinalTransformation() << std::endl;}else{std::cout << "配准失败!" << std::endl;}pcl::io::savePCDFile("cloud_registered.pcd",*cloud_registered);return 0;
}
简单调了一下参数,效果比icp好一些,当然了可能是icp没有调参的原因。。
-
setTransformationEpsilon(1.0):
setTransformationEpsilon
设置了变换矩阵更新的epsilon值,这是一个收敛条件,用于确定何时停止迭代。- 当连续两次迭代的变换矩阵变化的Frobenius范数小于这个epsilon值时,算法认为已经收敛,迭代过程会停止。
- 值越小,要求的精度越高,可能需要更多的迭代次数。
-
setStepSize(1.0):
setStepSize
定义了在每一步迭代中,变换矩阵可以更新的最大尺度。- 这个参数控制了搜索空间的步长,值越大,每次迭代的搜索范围越大,可能会跳过最优解,值越小,搜索越精细,但迭代次数可能会增加。
-
setResolution(1.0):
setResolution
设置了NDT算法中使用的网格的分辨率。- 分辨率越高,网格单元越小,搜索空间被划分得越精细,配准结果通常更准确,但计算量也越大。
- 值越小,网格单元越小,搜索越精细,但计算量也越大。
-
setMaximumIterations(1000):
setMaximumIterations
设置了算法的最大迭代次数。- 即使算法没有收敛,达到这个迭代次数后,算法也会停止迭代。
- 这个参数确保了算法不会无限运行下去。