Three methods to iterate every point in pointcloud of PCL(三种遍历点云的方式)

2019/08/10 10:13
阅读数 9.3K

The most common way to do this is by subscript in the [] operand<sup>[1]</sup>

pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud;
for(int nIndex = 0; nIndex < pointCloud->points.size (); nIndex++)
{
	pointCloud->points[nIndex].x;
	pointCloud->points[nIndex].y;
	pointCloud->points[nIndex].z;
}

The more efficient way is to use an iterator <sup>[2]</sup> <sup>[3]</sup>

The example in Euclidean Cluster Extraction of pcl tutorials is well known <sup>[2]</sup>.

Extract the indices cluster_indices then use it to iterate each pointcloud from cluster_indices.begin () to cluster_indices.end (). Next step is to iterate every point in the pointcloud from it->indices.begin (); to it->indices.end (). The code snippet is:

    std::vector<pcl::PointIndices> cluster_indices;
    pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
    ec.setClusterTolerance (0.02); // 2cm
    ec.setMinClusterSize (100);
    ec.setMaxClusterSize (25000);
    ec.setSearchMethod (tree);
    ec.setInputCloud (cloud_filtered);
    ec.extract (cluster_indices);

    int j = 0;
    for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
    {
        pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
        for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); ++pit)
        cloud_cluster->points.push_back (cloud_filtered->points[*pit]); //*
        cloud_cluster->width = cloud_cluster->points.size ();
        cloud_cluster->height = 1;
        cloud_cluster->is_dense = true;

        std::cout << "PointCloud representing the Cluster: " << cloud_cluster->points.size () << " data points." << std::endl;
        std::stringstream ss;
        ss << "cloud_cluster_" << j << ".pcd";
        writer.write<pcl::PointXYZ> (ss.str (), *cloud_cluster, false); //*
        j++;
    }

Last way do iteration but only Eigen::Vector3f values of points can be extract instead of a PCL point. <sup>[3]</sup>

If having trouble to save memory consumption, try this! Note: Only if the second way didn't work out!

The advantage of using this iterator is that no indices should be extracted before.

for (std::vector<pcl::PointXYZ, Eigen::aligned_allocator<pcl::PointXYZ> >::iterator it = pointCloud.bigin(); it != cropedCloud.end(); it++)
{
    // Return an Eigen::Vector3f of points coordinate.
	it->getVector3fMap();  // if double wanted, just say it->getVector3fMap().cast<double>
}

Note:

  1. The snippet should be modified to YOUR version before using it
  2. pcl::PointXYZ can be replaced by any type of PointT
  3. pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud can be replaced by pcl::PointCloud<pcl::PointXYZ> pointCloud, so by the mean time replace pointCloud->points.size() instead of pointCloud.points.size() */

What matters to me but it might not be helpful to you

Let's talk about how to find a way to use data of unknown type

  1. pcl::CropBox< PointT > does gives an access to achieve indices.
  2. There is an iterator begin () on the PCL namespace website. I guess can use it to iterate all around in the pointcloud.
  3. Look for definition at line 442 of point_cloud.h, which returns points.begin () Click the function begin () in the const_iterator begin () const.
  4. In the tutorial of iterating pointcloud<sup>[2]</sup>, pointcloud->begin() is neither indices nor points. The data structure type it use is std::vector<pcl::PointXYZ, Eigen::aligned_allocator<pcl::PointXYZ> >::iterator, which I got from the error building. Note: Sometimes you don't know what the type it is, but you can got it from the error. What a amazing thing.
  5. The most important thing is: how to get the data? So I go through the pcl directory, and search for function points.begin().
  6. $ cd ~/Downloads/nozuonodie/pcl-pcl-1.7.2, grep -rn -ie "points.begin ()". Look for those lines of matched completely function "points.begin ()" in hpp or cpp files.
  7. After several attemps, I got it by common/include/pcl/range_image/impl/range_image.hpp:1225: for (typename PointCloudType::const_iterator it = far_ranges.points.begin (); it != far_ranges.points.end (); ++it). Go to line 1225, see Vector3fMapConst current_point = it->getVector3fMap ();, then look for variable current_point
  8. In line 1231, this->getImagePoint (current_point, x_real, y_real, range_of_current_point); just go to the definition of getImagePoint.
  9. In line 352, function void RangeImage::getImagePoint (const Eigen::Vector3f& point, float& image_x, float& image_y, float& range) const totally matches.
  10. In conclusion, member function getVector3fMap() can get Eigen::Vector3f from the point by iterator. And also can be proved by referece <sup>[3]</sup>.

References:

<span id="jump1">[1]</span> Filtering a PointCloud using a PassThrough filter <span id="jump2">[2]</span> Euclidean Cluster Extraction <span id="jump3">[3]</span> Creating a PCL point cloud using a container of Eigen Vector3d

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部