Search code examples
c++shared-ptrpoint-cloud-library

pcl use of shared pointers, does it make copies?


So i have been using the pcl SampleConsensus module to do some line fitting and i found something awfully strange with the pcl point cloud usage. I am currently ransacing to find the most prominent line, then i retrieve only the outliers from the cloud and ransac on it again.

So to perform ransac on a cloud say i have some setup:

pcl::PointCloud<pcl::PointXYZ>::Ptr dataCloud(shared_ptr_cloud_from_elsewhere);
pcl::PointCloud<pcl::PointXYZ>::Ptr outlierCloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::SampleConsensusModelLine<pcl::PointXYZ>::Ptr modelLine(
    new pcl::SampleConsensusModelLine<pcl::PointXYZ>(dataCloud));

//Pay careful attention to line below because its position determines 
//if the code is going to work or not
pcl::SampleConsensusModelLine<pcl::PointXYZ>::Ptr modelLine2(
    new pcl::SampleConsensusModelLine<pcl::PointXYZ>(outlierCloud));

pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(modelLine);
ransac.compute();
ransac.inliers(inliers);

Using ExtractIndices I retrieve the outliers from the negative of the list of inliers and i put them in the outlierCloud. outlierCloud is checked and definitely has points in it. Then all i should have to do is change the model ransac is using and go again:

ransac.setSampleConsensusModel(modelLine2)
ransac.compute(); //This will fail, due to having no points.

So ransac.compute() fails, but why? modelLine2 is defined and has a pointer to the cloud outlierCloud which definitely has points?

So that line i said to pay attention to, if you move it so that modelLine2 is defined after outlierCloud is filled out then it works just fine. Same example same everything.

This suggests to me that pcl is taking a deep copy of this cloud even though it requests a shared pointer to it? Isn't this insanely bad? There are no scope changes or anything funny happening on my end, so why do i have to create modelLine2 after the data has been filled in the cloud?


Solution

  • No deep copy is made but the constructor of SampleConsusModel internally calls its setInputCloud method which stores (as expected) the pointer to the cloud and resizes the set of indices of the points to use to the current size of the cloud (to 0 in your case). So the pointer is correct but the model uses 0 indices for the cloud it is pointing to.

    As a workaround you could call setInputCloud yourself after outlierCloud is filled.