00001
00038 #include <pcl/visualization/cloud_viewer.h>
00039 #include <pcl/visualization/pcl_visualizer.h>
00040
00041 #include <boost/thread.hpp>
00042 #include <boost/thread/mutex.hpp>
00043 #include <boost/foreach.hpp>
00044
00045 namespace pcl
00046 {
00047 struct cloud_show_base
00048 {
00049 virtual void pop () = 0;
00050 virtual bool popped () const = 0;
00051 typedef boost::shared_ptr<cloud_show_base> Ptr;
00052 };
00053
00054 template <typename CloudT>
00055 struct cloud_show : cloud_show_base
00056 {
00057 cloud_show (const std::string &cloud_name, typename CloudT::ConstPtr cloud,
00058 boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer) :
00059 cloud_name (cloud_name), cloud (cloud), viewer (viewer),popped_ (false)
00060 {}
00061
00062 template <typename Handler> void
00063 pop (const Handler &handler)
00064 {
00065 double psize = 1.0, opacity = 1.0, linesize =1.0;
00066 viewer->getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, linesize, cloud_name);
00067 viewer->getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, cloud_name);
00068 viewer->getPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, psize, cloud_name);
00069
00070 if (!viewer->updatePointCloud (cloud, handler, cloud_name))
00071 {
00072 viewer->addPointCloud (cloud, handler, cloud_name);
00073 viewer->resetCameraViewpoint (cloud_name);
00074 }
00075
00076
00077 viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, linesize, cloud_name);
00078 viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, cloud_name);
00079 viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, psize, cloud_name);
00080 popped_ = true;
00081 }
00082
00083 virtual void pop ();
00084
00085 virtual bool
00086 popped () const
00087 {
00088 return popped_;
00089 }
00090
00091 std::string cloud_name;
00092 typename CloudT::ConstPtr cloud;
00093 boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
00094 bool popped_;
00095 };
00096
00097 typedef pcl::PointCloud<pcl::PointXYZRGBA> cca;
00098 typedef pcl::PointCloud<pcl::PointXYZRGB> cc;
00099 typedef pcl::PointCloud<pcl::PointXYZI> gc;
00100 typedef pcl::PointCloud<pcl::PointXYZ> mc;
00101
00102 template <> void
00103 cloud_show<cca>::pop ()
00104 {
00105 pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGBA> handler (cloud);
00106 pop (handler);
00107 }
00108
00109 template <> void
00110 cloud_show<cc>::pop ()
00111 {
00112 pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> handler (cloud);
00113 pop (handler);
00114 }
00115
00116 template <> void
00117 cloud_show<gc>::pop ()
00118 {
00119 pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI> handler (cloud, "intensity");
00120 pop (handler);
00121 }
00122
00123 template <> void
00124 cloud_show<mc>::pop ()
00125 {
00126 pcl::visualization::PointCloudGeometryHandlerXYZ<pcl::PointXYZ> handler (cloud);
00127 pop (handler);
00128 }
00129 }
00130
00131 struct pcl::visualization::CloudViewer::CloudViewer_impl
00132 {
00134 CloudViewer_impl (const std::string& window_name) :
00135 window_name_ (window_name), has_cloud_ (false), quit_ (false)
00136 {
00137 viewer_thread_ = boost::thread (boost::ref (*this));
00138 while (!viewer_)
00139 {
00140 boost::thread::yield ();
00141 }
00142 }
00143
00144 ~CloudViewer_impl ()
00145 {
00146 }
00147
00149 template <typename T> void
00150 block_post_cloud (const typename T::ConstPtr &cloud, const std::string &name)
00151 {
00152 cloud_show_base::Ptr cs (new cloud_show<T>(name,cloud,viewer_));
00153 {
00154 boost::mutex::scoped_lock lock (mtx_);
00155 cloud_shows_.push_back (cs);
00156 }
00157 while (!cs->popped ())
00158 {
00159 boost::thread::yield ();
00160 }
00161 }
00162
00163 template <typename T> void
00164 nonblock_post_cloud (const typename T::ConstPtr &cloud, const std::string &name)
00165 {
00166 cloud_show_base::Ptr cs (new cloud_show<T>(name,cloud,viewer_));
00167 {
00168 boost::mutex::scoped_lock lock (mtx_);
00169
00170 cloud_shows_.push_back (cs);
00171 }
00172 }
00173
00175 void
00176 operator() ()
00177 {
00178 using namespace pcl::visualization;
00179
00180 #if ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION <= 4))
00181 viewer_ = boost::shared_ptr<PCLVisualizer>(new PCLVisualizer (window_name_));
00182 #else
00183 viewer_ = boost::shared_ptr<PCLVisualizer>(new PCLVisualizer (window_name_, true));
00184 #endif
00185 viewer_->setBackgroundColor (0.1, 0.1, 0.1);
00186 viewer_->addCoordinateSystem (0.1);
00187
00188 while (!quit_)
00189 {
00190 {
00191 boost::mutex::scoped_lock lock (mtx_);
00192 while (!cloud_shows_.empty ())
00193 {
00194 cloud_shows_.back ()->pop ();
00195 cloud_shows_.pop_back ();
00196 }
00197 }
00198 {
00199 boost::mutex::scoped_lock lock (once_mtx);
00200 BOOST_FOREACH (CallableList::value_type& x, callables_once)
00201 {
00202 (x)(*viewer_);
00203 }
00204 callables_once.clear ();
00205 }
00206 {
00207 boost::mutex::scoped_lock lock (c_mtx);
00208 BOOST_FOREACH (CallableMap::value_type& x, callables)
00209 {
00210 (x.second)(*viewer_);
00211 }
00212 }
00213 if (viewer_->wasStopped ())
00214 {
00215 quit_ = true;
00216 }else
00217 {
00218 boost::mutex::scoped_lock lock (spin_mtx_);
00219
00220
00221 viewer_->spinOnce (10);
00222 }
00223
00224 }
00225 viewer_.reset ();
00226 }
00227
00229 void
00230 post (VizCallable x, const std::string &key)
00231 {
00232 boost::mutex::scoped_lock lock (c_mtx);
00233 callables[key] = x;
00234 }
00235
00236 void
00237 post (VizCallable x)
00238 {
00239 boost::mutex::scoped_lock lock (once_mtx);
00240 callables_once.push_back (x);
00241 }
00242
00244 void
00245 remove (const std::string &key)
00246 {
00247 boost::mutex::scoped_lock lock (c_mtx);
00248 if (callables.find (key) != callables.end ())
00249 callables.erase (key);
00250 }
00251
00252 std::string window_name_;
00253 boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer_;
00254 boost::mutex mtx_, spin_mtx_, c_mtx, once_mtx;
00255 boost::thread viewer_thread_;
00256 bool has_cloud_;
00257 bool quit_;
00258 std::list<boost::shared_ptr<cloud_show_base> > cloud_shows_;
00259 typedef std::map<std::string, VizCallable> CallableMap;
00260 CallableMap callables;
00261 typedef std::list<VizCallable> CallableList;
00262 CallableList callables_once;
00263 };
00264
00266 pcl::visualization::CloudViewer::CloudViewer (const std::string &window_name) :
00267 impl_ (new CloudViewer_impl (window_name))
00268 {}
00269
00270 pcl::visualization::CloudViewer::~CloudViewer ()
00271 {
00272 impl_->quit_ = true;
00273 impl_->viewer_thread_.join();
00274 }
00275
00277 void
00278 pcl::visualization::CloudViewer::showCloud (const ColorACloud::ConstPtr &cloud,
00279 const std::string &cloudname)
00280 {
00281 if (!impl_->viewer_ || impl_->viewer_->wasStopped ())
00282 return;
00283 impl_->block_post_cloud<ColorACloud>(cloud, cloudname);
00284 }
00285
00287 void
00288 pcl::visualization::CloudViewer::showCloud (const ColorCloud::ConstPtr &cloud,
00289 const std::string &cloudname)
00290 {
00291 if (!impl_->viewer_ || impl_->viewer_->wasStopped ())
00292 return;
00293 impl_->block_post_cloud<ColorCloud>(cloud, cloudname);
00294 }
00295
00297 void
00298 pcl::visualization::CloudViewer::showCloud (const GrayCloud::ConstPtr &cloud,
00299 const std::string &cloudname)
00300 {
00301 if (!impl_->viewer_ || impl_->viewer_->wasStopped ())
00302 return;
00303 impl_->block_post_cloud<GrayCloud>(cloud, cloudname);
00304 }
00305
00307 void
00308 pcl::visualization::CloudViewer::showCloud (const MonochromeCloud::ConstPtr &cloud,
00309 const std::string &cloudname)
00310 {
00311 if (!impl_->viewer_ || impl_->viewer_->wasStopped ())
00312 return;
00313 impl_->block_post_cloud<MonochromeCloud>(cloud, cloudname);
00314 }
00315
00317 void
00318 pcl::visualization::CloudViewer::runOnVisualizationThread (VizCallable x, const std::string &key)
00319 {
00320 impl_->post (x, key);
00321 }
00322
00324 void
00325 pcl::visualization::CloudViewer::runOnVisualizationThreadOnce (VizCallable x)
00326 {
00327 impl_->post (x);
00328 }
00329
00331 void
00332 pcl::visualization::CloudViewer::removeVisualizationCallable (const std::string &key)
00333 {
00334 impl_->remove (key);
00335 }
00336
00338 bool
00339 pcl::visualization::CloudViewer::wasStopped (int)
00340 {
00341 boost::thread::yield ();
00342 return !impl_->viewer_;
00343 }
00344
00346 boost::signals2::connection
00347 pcl::visualization::CloudViewer::registerKeyboardCallback (boost::function<void (const pcl::visualization::KeyboardEvent&)> callback)
00348 {
00349 return impl_->viewer_->registerKeyboardCallback (callback);
00350 }
00351
00353 boost::signals2::connection
00354 pcl::visualization::CloudViewer::registerMouseCallback (boost::function<void (const pcl::visualization::MouseEvent&)> callback)
00355 {
00356 return impl_->viewer_->registerMouseCallback (callback);
00357 }
00358
00360 boost::signals2::connection
00361 pcl::visualization::CloudViewer::registerPointPickingCallback (boost::function<void (const pcl::visualization::PointPickingEvent&)> callback)
00362 {
00363 return (impl_->viewer_->registerPointPickingCallback (callback));
00364 }
00365