1
votes

My question concerns about PointClouds library (PCL) and QVTK widget.

I have an QVTK widget in a MainWindow widget. The method that draws my pointclouds is called each time I load a new pointcloud from disk (or a ToF camera):

void CamWindow::on_PointCloudChanged()
{
      //pclPointCloud is declared as "pcl::PointCloud<pcl::PointXYZ>::Ptr pclPointCloud;". When that variable is updated, this method is called.
      //pclVisorName is global std::string, with "visor" as content
      //pclPointCloudName is global std::string, with "MyPointCloud" as content
      pcl::visualization::PCLVisualizer localPclVisor = pcl::visualization::PCLVisualizer(pclVisorName,false);
      localPclVisor.addPointCloud<pcl::PointXYZ>(pclPointCloud,pclPointCloudName);
      //localPclVisor.setBackgroundColor(1,1,0);
      vtkSmartPointer<vtkRenderWindow> localRenderWindow = localPclVisor.getRenderWindow();
      ui->QvtkPointCloud->SetRenderWindow(localRenderWindow);
      ui->QvtkPointCloud->update();

    existPclPointCloud = true;
}

This works, but each time this method is called, the camera position, pointview and other things are reset. I want to change only pointcloud to view, without resetting positions, colors, etc. How can I achieve this?

I've tried things like:

std::string                         pclPointCloudName;
pcl::PointCloud<pcl::PointXYZ>::Ptr pclPointCloud;
pcl::visualization::PCLVisualizer   pclVisor;
std::string                         pclVisorName;
vtkSmartPointer<vtkRenderWindow>    renderWindow;

(declaring pointcloud representation components as global vars)

void CamWindow::on_PointCloudChanged()
{
      //pclPointCloud is declared as "pcl::PointCloud<pcl::PointXYZ>::Ptr pclPointCloud;". When that variable is updated, this method is called.
      //pclVisorName is global std::string, with "visor" as content
      //pclPointCloudName is global std::string, with "MyPointCloud" as content
    if (existPclPointCloud)
    {
        localPclVisor.updatePointCloud<pcl::PointXYZ>(pclPointCloud,pclPointCloudName);
    }
    else
    {
      pcl::visualization::PCLVisualizer pclVisor = pcl::visualization::PCLVisualizer(pclVisorName,false);
      pclVisor.addPointCloud<pcl::PointXYZ>(pclPointCloud,pclPointCloudName);
      vtkSmartPointer<vtkRenderWindow> renderWindow = pclVisor.getRenderWindow();
      ui->QvtkPointCloud->SetRenderWindow(renderWindow);        
    }
     ui->QvtkPointCloud->update();

    existPclPointCloud = true;
}

But this does not work... Declaring QVTK and PCL components as global variables (in MainWindow Widget) make this program to show nothing in QVTK widget!! Why?

[I've also tried several variations of this, but it appears as every PCL+VTK+QT variable must be local in method in order to work. Spent hours and hours looking and googling for docs about VTK Visualizer, QVTK methods, objects, etc with no luck]

I understand that vars and objects relatives to PCL+VTK+QT are never empty or null (as they're global in MainWindow!!)...

My environment is Ubuntu 12.04 LTS, with Qt Creator 2.5.2, 64 bits. PCL 1.6, VTK 5.8

1

1 Answers

1
votes

If I understood your implementation right, every time you want to update your point cloud (pc), you call CamWindow::on_PointCloudChanged() and a new pcl::visualization::PCLVisualizer gets initialized, that's why you lose all your camera settings.

Maybe this can help. Declare the visualizer as global var, outside of any method

pcl::visualization::PCLVisualizer pclVisor ("visor", false);

Then write an init method similar to this, which you have to call once at the beginning:

void CamWindow::init() {
   vtkSmartPointer<vtkRenderWindow> renderWindow = pclVisor.getRenderWindow();
   this->SetRenderWindow(renderWindow);

   this->show();
   this->update();
}

Now you can update the pc named cloud0, every time a new_pc was created:

void CamWindow::on_PointCloudChanged(pcl::PointCloud<pcl::PointXYZ>::Ptr new_pc) {
   if (!pc->empty()) {

      // in case there is no pc called `cloud0` - create one,
      // otherwise just update it
      if (!pclVisor.updatePointCloud<pcl::PointXYZ>(new_pc, "cloud0")) {
         pclVisor.addPointCloud<pcl::PointXYZ>(new_pc, "cloud0");
      } else {
         pclVisor.updatePointCloud<pcl::PointXYZ>(new_pc, "cloud0");
      } 

      this->update();
   } else {
      std::cerr << "There is nothing to add to the visualizer!" << std::endl;
   }
}

I haven't compiled the code, so feel free to edit my answer, in case you used it and found any mistake. But this should be the basic idea.