PCL库简单NDT算法配准

发布于:2024-10-11 ⋅ 阅读:(10) ⋅ 点赞:(0)
#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没有调参的原因。。

  1. setTransformationEpsilon(1.0):

    • setTransformationEpsilon 设置了变换矩阵更新的epsilon值,这是一个收敛条件,用于确定何时停止迭代。
    • 当连续两次迭代的变换矩阵变化的Frobenius范数小于这个epsilon值时,算法认为已经收敛,迭代过程会停止。
    • 值越小,要求的精度越高,可能需要更多的迭代次数。
  2. setStepSize(1.0):

    • setStepSize 定义了在每一步迭代中,变换矩阵可以更新的最大尺度。
    • 这个参数控制了搜索空间的步长,值越大,每次迭代的搜索范围越大,可能会跳过最优解,值越小,搜索越精细,但迭代次数可能会增加。
  3. setResolution(1.0):

    • setResolution 设置了NDT算法中使用的网格的分辨率。
    • 分辨率越高,网格单元越小,搜索空间被划分得越精细,配准结果通常更准确,但计算量也越大。
    • 值越小,网格单元越小,搜索越精细,但计算量也越大。
  4. setMaximumIterations(1000):

    • setMaximumIterations 设置了算法的最大迭代次数。
    • 即使算法没有收敛,达到这个迭代次数后,算法也会停止迭代。
    • 这个参数确保了算法不会无限运行下去。