outofcore_cloud.cpp
Go to the documentation of this file.
00001 // PCL
00002 //#include <pcl/common/time.h>
00003 //#include <pcl/point_cloud.h>
00004 #include <pcl/point_types.h>
00005 
00006 #include <pcl/io/pcd_io.h>
00007 #include <pcl/io/vtk_lib_io.h>
00008 #include <pcl/pcl_macros.h>
00009 
00010 // PCL - outofcore
00011 #include <pcl/outofcore/outofcore.h>
00012 #include <pcl/outofcore/outofcore_impl.h>
00013 #include <pcl/outofcore/impl/monitor_queue.hpp>
00014 #include <pcl/outofcore/impl/lru_cache.hpp>
00015 
00016 #include <pcl/outofcore/visualization/camera.h>
00017 #include <pcl/outofcore/visualization/common.h>
00018 #include <pcl/outofcore/visualization/object.h>
00019 #include <pcl/outofcore/visualization/scene.h>
00020 #include <pcl/outofcore/visualization/outofcore_cloud.h>
00021 
00022 // PCL - visualziation
00023 #include <pcl/visualization/common/common.h>
00024 #include <pcl/visualization/vtk/vtkVertexBufferObjectMapper.h>
00025 
00026 // VTK
00027 #include <vtkActor.h>
00028 #include <vtkPolyData.h>
00029 #include <vtkProperty.h>
00030 #include <vtkSmartPointer.h>
00031 
00032 // Boost
00033 //#include <boost/date_time.hpp>
00034 //#include <boost/filesystem.hpp>
00035 #include <boost/thread.hpp>
00036 
00037 // Forward Declarations
00038 
00039 boost::condition OutofcoreCloud::pcd_queue_ready;
00040 boost::mutex OutofcoreCloud::pcd_queue_mutex;
00041 
00042 boost::shared_ptr<boost::thread> OutofcoreCloud::pcd_reader_thread;
00043 //MonitorQueue<std::string> OutofcoreCloud::pcd_queue;
00044 
00045 //std::map<std::string, vtkSmartPointer<vtkPolyData> > OutofcoreCloud::cloud_data_cache;
00046 OutofcoreCloud::CloudDataCache OutofcoreCloud::cloud_data_cache(524288);
00047 boost::mutex OutofcoreCloud::cloud_data_cache_mutex;
00048 
00049 OutofcoreCloud::PcdQueue OutofcoreCloud::pcd_queue;
00050 
00051 void
00052 OutofcoreCloud::pcdReaderThread ()
00053 {
00054 
00055   std::string pcd_file;
00056   size_t timestamp = 0;
00057 
00058   while (true)
00059   {
00060     //{
00061       //boost::mutex::scoped_lock lock (pcd_queue_mutex);
00062       //pcd_queue_mutex.wait (lock);
00063       pcd_queue_ready.wait(pcd_queue_mutex);
00064     //}
00065     //pcd_queue_ready
00066 
00067     int queue_size = pcd_queue.size ();
00068     for (int i=0; i < queue_size; i++)
00069     {
00070       const PcdQueueItem *pcd_queue_item = &pcd_queue.top();
00071 
00072       if (cloud_data_cache.hasKey(pcd_queue_item->pcd_file))
00073       {
00074         CloudDataCacheItem *cloud_data_cache_item = &cloud_data_cache.get(pcd_queue_item->pcd_file);
00075         cloud_data_cache_item->timestamp = timestamp;
00076       }
00077       else
00078       {
00079         vtkSmartPointer<vtkPolyData> cloud_data = vtkSmartPointer<vtkPolyData>::New ();
00080 
00081         pcl::PCLPointCloud2Ptr cloud (new pcl::PCLPointCloud2);
00082 
00083         pcl::io::loadPCDFile (pcd_queue_item->pcd_file, *cloud);
00084         pcl::io::pointCloudTovtkPolyData (cloud, cloud_data);
00085 
00086         CloudDataCacheItem cloud_data_cache_item(pcd_queue_item->pcd_file, pcd_queue_item->coverage, cloud_data, timestamp);
00087 
00088         cloud_data_cache_mutex.lock();
00089         bool inserted = cloud_data_cache.insert(pcd_queue_item->pcd_file, cloud_data_cache_item);
00090         cloud_data_cache_mutex.unlock();
00091 
00092         if (!inserted)
00093         {
00094           //std::cout << "CACHE FILLED" << std::endl;
00095           while (!pcd_queue.empty())
00096           {
00097             //const PcdQueueItem *pcd_queue_item = &pcd_queue.top();
00098             //std::cout << "Skipping: " << pcd_queue_item->pcd_file <<std::endl;
00099             pcd_queue.pop();
00100           }
00101           break;
00102         }
00103         //std::cout << "Loaded: " << pcd_queue_item->pcd_file << std::endl;
00104       }
00105 
00106       pcd_queue.pop();
00107     }
00108 
00109     timestamp++;
00110   }
00111 }
00112 
00113 
00114 // Operators
00115 // -----------------------------------------------------------------------------
00116 OutofcoreCloud::OutofcoreCloud (std::string name, boost::filesystem::path& tree_root) :
00117     Object (name), display_depth_ (1), points_loaded_ (0), data_loaded_(0), render_camera_(NULL), lod_pixel_threshold_(10000)
00118 {
00119 
00120   // Create the pcd reader thread once for all outofcore nodes
00121   if (OutofcoreCloud::pcd_reader_thread.get() == NULL)
00122   {
00123 //    OutofcoreCloud::pcd_reader_thread = boost::shared_ptr<boost::thread>(new boost::thread(&OutofcoreCloud::pcdReaderThread, this));
00124     OutofcoreCloud::pcd_reader_thread = boost::shared_ptr<boost::thread>(new boost::thread(&OutofcoreCloud::pcdReaderThread));
00125   }
00126 
00127 
00128   octree_.reset (new OctreeDisk (tree_root, true));
00129   octree_->getBoundingBox (bbox_min_, bbox_max_);
00130 
00131   voxel_actor_ = vtkSmartPointer<vtkActor>::New ();
00132 
00133   updateVoxelData ();
00134 
00135   cloud_actors_ = vtkSmartPointer<vtkActorCollection>::New ();
00136 
00137   addActor (voxel_actor_);
00138 }
00139 
00140 // Methods
00141 // -----------------------------------------------------------------------------
00142 void
00143 OutofcoreCloud::updateVoxelData ()
00144 {
00145   std::vector<PointT, AlignedPointT> voxel_centers;
00146   vtkSmartPointer<vtkAppendPolyData> voxel_data = vtkSmartPointer<vtkAppendPolyData>::New ();
00147   vtkSmartPointer<vtkDataSetMapper> voxel_mapper = vtkSmartPointer<vtkDataSetMapper>::New ();
00148 
00149   voxel_centers.clear ();
00150   voxel_data->RemoveAllInputs ();
00151 
00152   octree_->getOccupiedVoxelCenters (voxel_centers, display_depth_);
00153   double voxel_side_length = octree_->getVoxelSideLength (display_depth_);
00154 
00155   double s = voxel_side_length / 2;
00156   for (size_t i = 0; i < voxel_centers.size (); i++)
00157   {
00158     double x = voxel_centers[i].x;
00159     double y = voxel_centers[i].y;
00160     double z = voxel_centers[i].z;
00161 
00162     voxel_data->AddInput (getVtkCube (x - s, x + s, y - s, y + s, z - s, z + s));
00163   }
00164 
00165   voxel_mapper->SetInput (voxel_data->GetOutput ());
00166 
00167   voxel_actor_->SetMapper (voxel_mapper);
00168   voxel_actor_->GetProperty ()->SetRepresentationToWireframe ();
00169   voxel_actor_->GetProperty ()->SetColor (0.0, 1.0, 0.0);
00170   voxel_actor_->GetProperty ()->SetLighting (false);
00171 }
00172 
00173 void
00174 OutofcoreCloud::render (vtkRenderer* renderer)
00175 {
00176   vtkSmartPointer<vtkCamera> active_camera = renderer->GetActiveCamera ();
00177 
00178   Scene *scene = Scene::instance ();
00179   Camera *camera = scene->getCamera (active_camera);
00180 
00181   if (render_camera_ != NULL && render_camera_->getName() == camera->getName ())
00182   {
00183     renderer->ComputeAspect ();
00184     //double *aspect = renderer->GetAspect ();
00185     int *size = renderer->GetSize ();
00186 
00187     OctreeDisk::BreadthFirstIterator breadth_first_it (*octree_);
00188     breadth_first_it.setMaxDepth(display_depth_);
00189 
00190     double frustum[24];
00191     camera->getFrustum(frustum);
00192 
00193     Eigen::Vector3d eye = camera->getPosition();
00194     Eigen::Matrix4d view_projection_matrix = camera->getViewProjectionMatrix();
00195     //Eigen::Matrix4d view_projection_matrix = projection_matrix * model_view_matrix;//camera->getViewProjectionMatrix();
00196 
00197     cloud_actors_->RemoveAllItems ();
00198 
00199     while ( *breadth_first_it !=0 )
00200     {
00201       OctreeDiskNode *node = *breadth_first_it;
00202 
00203       Eigen::Vector3d min_bb, max_bb;
00204       node->getBoundingBox(min_bb, max_bb);
00205 
00206       // Frustum culling
00207       if (pcl::visualization::cullFrustum(frustum, min_bb, max_bb) == pcl::visualization::PCL_OUTSIDE_FRUSTUM)
00208       {
00209         breadth_first_it.skipChildVoxels();
00210         breadth_first_it++;
00211         continue;
00212       }
00213 
00214       // Bounding box lod projection
00215       float coverage = pcl::visualization::viewScreenArea(eye, min_bb, max_bb, view_projection_matrix, size[0], size[1]);
00216       if (coverage <= lod_pixel_threshold_)
00217       {
00218         breadth_first_it.skipChildVoxels();
00219       }
00220 
00221 //      for (int i=0; i < node->getDepth(); i++)
00222 //        std::cout << " ";
00223 //      std::cout << coverage << "-" << pcd_file << endl;//" : " << (coverage > (size[0] * size[1])) << endl;
00224 
00225       std::string pcd_file = node->getPCDFilename ().string ();
00226 
00227       cloud_data_cache_mutex.lock();
00228 
00229       PcdQueueItem pcd_queue_item(pcd_file, coverage);
00230 
00231       // If we can lock the queue add another item
00232       if (pcd_queue_mutex.try_lock())
00233       {
00234         pcd_queue.push(pcd_queue_item);
00235         pcd_queue_mutex.unlock();
00236       }
00237 
00238       if (cloud_data_cache.hasKey(pcd_file))
00239       {
00240         //std::cout << "Has Key for: " << pcd_file << std::endl;
00241         if (cloud_actors_map_.find (pcd_file) == cloud_actors_map_.end ())
00242         {
00243 
00244           vtkSmartPointer<vtkActor> cloud_actor = vtkSmartPointer<vtkActor>::New ();
00245           vtkSmartPointer<vtkVertexBufferObjectMapper> mapper = vtkSmartPointer<vtkVertexBufferObjectMapper>::New ();
00246 
00247           CloudDataCacheItem *cloud_data_cache_item = &cloud_data_cache.get(pcd_file);
00248 
00249           mapper->SetInput (cloud_data_cache_item->item);
00250           cloud_actor->SetMapper (mapper);
00251           cloud_actor->GetProperty ()->SetColor (0.0, 0.0, 1.0);
00252           cloud_actor->GetProperty ()->SetPointSize (1);
00253           cloud_actor->GetProperty ()->SetLighting (0);
00254 
00255           cloud_actors_map_[pcd_file] = cloud_actor;
00256         }
00257 
00258         if (!hasActor (cloud_actors_map_[pcd_file]))
00259         {
00260           points_loaded_ += cloud_actors_map_[pcd_file]->GetMapper ()->GetInput ()->GetNumberOfPoints ();
00261           data_loaded_ += cloud_actors_map_[pcd_file]->GetMapper ()->GetInput ()->GetActualMemorySize();
00262         }
00263 
00264         //std::cout << "Adding Actor: " << pcd_file << std::endl;
00265 
00266         cloud_actors_->AddItem (cloud_actors_map_[pcd_file]);
00267         addActor (cloud_actors_map_[pcd_file]);
00268       }
00269 
00270       cloud_data_cache_mutex.unlock();
00271 
00272       breadth_first_it++;
00273     }
00274 
00275     // We're done culling, notify the pcd_reader thread the queue is read
00276     pcd_queue_ready.notify_one();
00277 
00278     std::vector<vtkActor*> actors_to_remove;
00279     {
00280       actors_to_remove.clear ();
00281       actors_->InitTraversal ();
00282       for (vtkIdType i = 0; i < actors_->GetNumberOfItems (); i++)
00283       {
00284         vtkActor* actor = actors_->GetNextActor ();
00285         if (actor != voxel_actor_.GetPointer ())
00286         {
00287           bool actor_found = false;
00288           cloud_actors_->InitTraversal ();
00289           for (vtkIdType j = 0; j < cloud_actors_->GetNumberOfItems (); j++)
00290           {
00291             vtkActor* cloud_actor = cloud_actors_->GetNextActor ();
00292             if (actor == cloud_actor)
00293             {
00294               actor_found = true;
00295               break;
00296             }
00297           }
00298 
00299           if (!actor_found)
00300           {
00301             actors_to_remove.push_back (actor);
00302           }
00303         }
00304       }
00305     }
00306 
00307     for (int i = 0; i < actors_to_remove.size (); i++)
00308     {
00309       points_loaded_ -= actors_to_remove.back ()->GetMapper ()->GetInput ()->GetNumberOfPoints ();
00310       data_loaded_ -= actors_to_remove.back ()->GetMapper ()->GetInput ()->GetActualMemorySize();
00311       removeActor (actors_to_remove.back ());
00312       actors_to_remove.pop_back ();
00313     }
00314   }
00315 
00316   Object::render(renderer);
00317 }
00318 


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:30