PointCloudLibrary / pcl

Point Cloud Library (PCL)
https://pointclouds.org/
Other
9.87k stars 4.61k forks source link

pcl::MeshQuadricDecimationVTK seg fault #967

Open felipepolido opened 9 years ago

felipepolido commented 9 years ago

Oi,

I am running a continuous loop that get the latest point-cloud from a laser sensor and transform it into a mesh. The Point-cloud( input data) is very similar in each loop.
I am using the pcl::MeshQuadricDecimationVTK to decimate most of the mesh. The code works for a few loops, behaving exactly like expected, but after what appears to be a random number of iterations it seg-faults with the following ( from gbd):

Program received signal SIGSEGV, Segmentation fault.

[Switching to Thread 0x7fffa6ffd700 (LWP 2502)]
0x00007fffde6006f9 in vtkQuadricDecimation::CollapseEdge(long long, long long) () from /usr/lib/libvtkGraphics.so.5.8
(gdb) bt
#0  0x00007fffde6006f9 in vtkQuadricDecimation::CollapseEdge(long long, long long) ()
   from /usr/lib/libvtkGraphics.so.5.8
#1  0x00007fffde602927 in vtkQuadricDecimation::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) () from /usr/lib/libvtkGraphics.so.5.8
#2  0x00007fffe0973204 in vtkExecutive::CallAlgorithm(vtkInformation*, int, vtkInformationVector**, vtkInformationVector*) () from /usr/lib/libvtkFiltering.so.5.8
#3  0x00007fffe096775c in vtkDemandDrivenPipeline::ExecuteData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) () from /usr/lib/libvtkFiltering.so.5.8
#4  0x00007fffe096a79d in vtkDemandDrivenPipeline::ProcessRequest(vtkInformation*, vtkInformationVector**, vtkInformationVector*) () from /usr/lib/libvtkFiltering.so.5.8
#5  0x00007fffe0aa6cac in vtkStreamingDemandDrivenPipeline::ProcessRequest(vtkInformation*, vtkInformationVector**, vtkInformationVector*) () from /usr/lib/libvtkFiltering.so.5.8
#6  0x00007fffe09692a7 in vtkDemandDrivenPipeline::UpdateData(int) () from /usr/lib/libvtkFiltering.so.5.8
#7  0x00007fffe0aa8485 in vtkStreamingDemandDrivenPipeline::Update(int) () from /usr/lib/libvtkFiltering.so.5.8
#8  0x00007fffe586af1d in pcl::MeshQuadricDecimationVTK::performProcessing(pcl::PolygonMesh&) ()
   from /usr/lib/libpcl_surface.so.1.7
#9  0x00007fffe5717986 in pcl::MeshProcessing::process(pcl::PolygonMesh&) () from /usr/lib/libpcl_surface.so.1.7
#10 0x00007fffee194a88 in TrajOpt::AtlasTraj::PrepPointCloud(boost::shared_ptr<pcl::PointCloud<pcl::PointXYZRGB> >, Eigen::Transform<double, 3, 2, 0>) () from /home/fpolido/drc_workspace/src/trajopt/build_trajopt/lib/libatlas_traj.so
#11 0x000000000040ec07 in ConvexDecompLoop() ()
#12 0x00007ffff7020ce9 in thread_proxy () from /usr/lib/libboost_thread.so.1.46.1
#13 0x00007ffff6dfee9a in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#14 0x00007fffed6f331d in clone () from /lib/x86_64-linux-gnu/libc.so.6
#15 0x0000000000000000 in ?? ()

The specific lines in my code are =

pcl::PolygonMesh::Ptr simpleMesh(new pcl::PolygonMesh()); 
pcl::MeshQuadricDecimationVTK mesh_decimator; 
mesh_decimator.setInputMesh(triangles); 
mesh_decimator.setTargetReductionFactor(1 - 0.1); 
mesh_decimator.process(*simpleMesh); 

For reference, the mesh generation from Point-Cloud is:

// Normal estimation*
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;
pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
tree->setInputCloud (temp);
n.setInputCloud (temp);
n.setSearchMethod (tree);
n.setKSearch (20);
n.compute (*normals);
//* normals should not contain the point normals + surface curvatures

// Concatenate the XYZ and normal fields*
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals (new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields (*temp, *normals, *cloud_with_normals);
//* cloud_with_normals = cloud + normals

// Create search tree*
pcl::search::KdTree<pcl::PointNormal>::Ptr tree2 (new pcl::search::KdTree<pcl::PointNormal>);
tree2->setInputCloud (cloud_with_normals);

// Initialize objects
pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;
//pcl::PolygonMesh triangles;
pcl::PolygonMesh::Ptr triangles(new pcl::PolygonMesh());

// Set the maximum distance between connected points (maximum edge length)
//Very importan in setting the size of blocks:
gp3.setSearchRadius (0.15); //0.025

// Set typical values for the parameters
gp3.setMu (250);//2.5
gp3.setMaximumNearestNeighbors (100);
gp3.setMaximumSurfaceAngle(M_PI/4); // 45 degrees
gp3.setMinimumAngle(M_PI/18); // 10 degrees
gp3.setMaximumAngle(2*M_PI/3); // 120 degrees
gp3.setNormalConsistency(false);

// Get result
gp3.setInputCloud (cloud_with_normals);
gp3.setSearchMethod (tree2);
gp3.reconstruct (*triangles);

The computer is concurrently running a simulator, which hogs a lot of the memory. I am guessing this is an internal memory-leak. I wasn't able to find any similar bugs on the Issue Tracker

Any ideas? And is there any alternative options for the same functionality as MeshQuadricDecimationVTK?

Thanks in advance!

Felipe

felipepolido commented 9 years ago

Alright, I compiled VTK from source in DEBUG mode, and the error message is the following:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fff93fff700 (LWP 13376)]
0x00007fffe8ac2d85 in vtkQuadricDecimation2::CollapseEdge (this=0x7fff9406cc20, pt0Id=635, pt1Id=635)
    at /home/fpolido/drc_workspace/src/trajopt/src/cloudproc/vtkQuadricDecimation2.cxx:1101
1101          if (pts[j] == pt1Id) 
(gdb) bt
#0  0x00007fffe8ac2d85 in vtkQuadricDecimation2::CollapseEdge (this=0x7fff9406cc20, pt0Id=635, pt1Id=635)
    at /home/fpolido/drc_workspace/src/trajopt/src/cloudproc/vtkQuadricDecimation2.cxx:1101
#1  0x00007fffe8abeee2 in vtkQuadricDecimation2::RequestData (this=0x7fff9406cc20, inputVector=0x7fff94764da0, 
    outputVector=0x7fff94795d70)
    at /home/fpolido/drc_workspace/src/trajopt/src/cloudproc/vtkQuadricDecimation2.cxx:352
#2  0x00007fffe00b1204 in vtkExecutive::CallAlgorithm(vtkInformation*, int, vtkInformationVector**, vtkInformationVector*) () from /usr/lib/libvtkFiltering.so.5.8
#3  0x00007fffe00a575c in vtkDemandDrivenPipeline::ExecuteData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) () from /usr/lib/libvtkFiltering.so.5.8
#4  0x00007fffe00a879d in vtkDemandDrivenPipeline::ProcessRequest(vtkInformation*, vtkInformationVector**, vtkInformationVector*) () from /usr/lib/libvtkFiltering.so.5.8
#5  0x00007fffe01e4cac in vtkStreamingDemandDrivenPipeline::ProcessRequest(vtkInformation*, vtkInformationVector**, vtkInformationVector*) () from /usr/lib/libvtkFiltering.so.5.8
#6  0x00007fffe00a72a7 in vtkDemandDrivenPipeline::UpdateData(int) () from /usr/lib/libvtkFiltering.so.5.8
#7  0x00007fffe01e6485 in vtkStreamingDemandDrivenPipeline::Update(int) () from /usr/lib/libvtkFiltering.so.5.8
#8  0x00007fffe8aba7fc in cloudproc::quadricSimplifyVTK (in=..., meshDecimationFrac=0.100000001)
    at /home/fpolido/drc_workspace/src/trajopt/src/cloudproc/mesh_simplification.cpp:81
#9  0x00007fffee0ed06d in TrajOpt::AtlasTraj::PrepPointCloud (this=0x330b330, cloudPtr=..., trans=...)
    at /home/fpolido/drc_workspace/src/trajopt/drc_traj/src/atlas_traj.cpp:597
#10 0x000000000043537a in ConvexDecompLoop ()
    at /home/fpolido/drc_workspace/src/trajopt/ros_interface/src/TrajOptNode.cpp:62
#11 0x000000000044a263 in boost::detail::thread_data<void (*)()>::run (this=0x904f540)
    at /usr/include/boost/thread/detail/thread.hpp:61
#12 0x00007ffff7020ce9 in thread_proxy () from /usr/lib/libboost_thread.so.1.46.1
#13 0x00007ffff6dfee9a in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#14 0x00007fffed5c131d in clone () from /lib/x86_64-linux-gnu/libc.so.6
#15 0x0000000000000000 in ?? ()

Line 1101 is the IF statement below:

int vtkQuadricDecimation2::CollapseEdge(vtkIdType pt0Id, vtkIdType pt1Id) 
{
  int j, numDeleted=0;
  vtkIdType i, npts, *pts, cellId;

  this->Mesh->GetPointCells(pt0Id, this->CollapseCellIds);
  for (i = 0; i < this->CollapseCellIds->GetNumberOfIds(); i++) 
    {
    cellId = this->CollapseCellIds->GetId(i);
    this->Mesh->GetCellPoints(cellId, npts, pts);
    for (j = 0; j < 3; j++) 
      {
      if (pts[j] == pt1Id) 
        {
        this->Mesh->RemoveCellReference(cellId);
        this->Mesh->DeleteCell(cellId);       
        numDeleted++;
        }
      }
    }

I narrowed down to the pts[j] variable returning an Invalid Pointer. So as a quick "hack solution" I wrapped the for loop with an if statement that checks for the pointer validity:

if(NULL !=pts) 
{
for (j = 0; j < 3; j++) 
  {
  if (pts[j] == pt1Id) 
    {
    this->Mesh->RemoveCellReference(cellId);
    this->Mesh->DeleteCell(cellId);       
    numDeleted++;
    }
  }
}
}

This "solved" the problem for me, but it doesn't actually tackle why this->Mesh->GetCellPoints is never initializing the pointer on some edge case.

Best,

Felipe

taketwo commented 9 years ago

So this is a bug on vtk side, not ours?

stale[bot] commented 4 years ago

Marking this as stale due to 30 days of inactivity. It will be closed in 7 days if no further activity occurs.