c++3dpoint-cloud-librarypoint-cloudsransac

SACSegmentation detecting odd plane model


I'm trying to fit a plane model to a point cloud (with a plane-like structure).

The problem I'm encountering is that the fitted plane is just a small slice of the cloud, even if the distance threshold is set to a relatively large value.

Here are some images of the result: (white points are model inliers)

enter image description here

You can see how thin the cloud is here:

enter image description here

enter image description here

I've tweaked all sorts of parameters for the SACSegmentation object and even tried multiple RANSAC methods that PCL has with no luck.

This is the point cloud displayed: https://drive.google.com/file/d/0B0PUIShwQuU7RmFKUW1Cd2V1Zk0/view?usp=sharing

Here is the minimal code that follows the tutorial pretty closely:

#include <iostream>
#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>


int
main(int argc, char** argv)
{
    pcl::PointCloud<pcl::PointXYZI>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZI>);
    pcl::io::loadPCDFile<pcl::PointXYZI>("test.pcd", *cloud); //* load the file

    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
    pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
    // Create the segmentation object
    pcl::SACSegmentation<pcl::PointXYZI> seg;
    // Optional
    seg.setOptimizeCoefficients(true);
    // Mandatory
    seg.setModelType(pcl::SACMODEL_PLANE);
    seg.setMethodType(pcl::SAC_RANSAC);
    seg.setDistanceThreshold(0.025);

    seg.setInputCloud(cloud);
    seg.segment(*inliers, *coefficients);

    if (inliers->indices.size() == 0)
    {
        PCL_ERROR("Could not estimate a planar model for the given dataset.");
        return (-1);
    }

    std::cerr << "Model coefficients: " << coefficients->values[0] << " "
        << coefficients->values[1] << " "
        << coefficients->values[2] << " "
        << coefficients->values[3] << std::endl;

    //add points to plane that fit plane model
    pcl::PointCloud<pcl::PointXYZI>::Ptr output(new pcl::PointCloud<pcl::PointXYZI>);
    for (size_t i = 0; i < inliers->indices.size(); ++i)
    {
        output->push_back(cloud->points[inliers->indices[i]]);
    }

    displaySubcloud(cloud, output);
    displayPlane(cloud, coefficients, "plane");

    return (0);
}

Solution

  • I've figured out a solution, but I don't know why it fixes it. By translating the cloud closer to the origin, it is able to detect the correct plane model.