Go to the documentation of this file.00001
00002
00003
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
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
00023 #include <pcl/visualization/common/common.h>
00024 #include <pcl/visualization/vtk/vtkVertexBufferObjectMapper.h>
00025
00026
00027 #include <vtkActor.h>
00028 #include <vtkPolyData.h>
00029 #include <vtkProperty.h>
00030 #include <vtkSmartPointer.h>
00031
00032
00033
00034
00035 #include <boost/thread.hpp>
00036
00037
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
00044
00045
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
00062
00063 pcd_queue_ready.wait(pcd_queue_mutex);
00064
00065
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
00095 while (!pcd_queue.empty())
00096 {
00097
00098
00099 pcd_queue.pop();
00100 }
00101 break;
00102 }
00103
00104 }
00105
00106 pcd_queue.pop();
00107 }
00108
00109 timestamp++;
00110 }
00111 }
00112
00113
00114
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
00121 if (OutofcoreCloud::pcd_reader_thread.get() == NULL)
00122 {
00123
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
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
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
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
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
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
00222
00223
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
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
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
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
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