main_window.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement  (BSD License)
00003  *
00004  *  Point Cloud Library  (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2012-, Open Perception, Inc.
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of the copyright holder(s) nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES  (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  */
00037 
00038 #include <pcl/apps/optronic_viewer/main_window.h>
00039 #include <pcl/apps/optronic_viewer/openni_grabber.h>
00040 #include <pcl/apps/optronic_viewer/filter_window.h>
00041 
00042 #include <pcl/io/openni_grabber.h>
00043 #include <pcl/io/fotonic_grabber.h>
00044 
00045 #include <fz_api.h>
00046 #include <fz_internal.h>
00047 
00048 #include <QFileInfo>
00049 #include <vtkActor.h>
00050 #include <vtkRenderer.h>
00051 
00052 
00054 pcl::apps::optronic_viewer::
00055 MainWindow::
00056 MainWindow ()
00057   : grabber_ (NULL)
00058   , grabber_thread_ (NULL)
00059 {
00060   // initialize API
00061   pcl::FotonicGrabber::initAPI ();
00062 
00063 
00064   // setup filters
00065   filter_factories_.push_back (new VoxelGridCFF2 ());
00066   filter_factories_.push_back (new PassThroughCFF2 ());
00067   filter_factories_.push_back (new RadiusOutlierCFF2 ());
00068   filter_factories_.push_back (new FastBilateralCFF2 ());
00069   filter_factories_.push_back (new MedianCFF2 ());
00070   filter_factories_.push_back (new RandomSampleCFF2 ());
00071   filter_factories_.push_back (new PlaneCFF2 ());
00072 
00073 
00074   // reset point cloud
00075   cloud_.reset (new pcl::PointCloud<pcl::PointXYZRGBA> ());
00076   
00077 
00078   // set window title
00079   this->setWindowTitle ("PCL Optronic Viewer");
00080 
00081 
00082   // setup menu
00083   this->createFileMenu ();
00084 
00085 
00086   // setup widgets
00087   QWidget * central_widget = new QWidget (this);
00088   
00089   QLabel * sensor_label = new QLabel (tr ("Sensor"));
00090   QComboBox * sensor_selection_combo_box = new QComboBox ();
00091   sensor_selection_combo_box->addItem (tr ("none"));
00092   this->findConnectedDevices ();
00093   for (size_t device_idx = 0; device_idx < connected_devices_.size (); ++device_idx)
00094   {
00095     if (connected_devices_[device_idx]->device_type == OPENNI_DEVICE)
00096       sensor_selection_combo_box->addItem (tr (reinterpret_cast<OpenNIDevice*> (connected_devices_[device_idx])->name.c_str ()));
00097     if (connected_devices_[device_idx]->device_type == FOTONIC_DEVICE)
00098       sensor_selection_combo_box->addItem (tr (reinterpret_cast<FotonicDevice*> (connected_devices_[device_idx])->device_info.szPath));
00099   }
00100   connect (sensor_selection_combo_box, SIGNAL(activated (int)), this, SLOT(selectedSensorChanged (int)));
00101   
00102   processing_list_ = new QListWidget (central_widget);
00103   connect (processing_list_, SIGNAL (itemDoubleClicked (QListWidgetItem*)), this, SLOT (updateFilter (QListWidgetItem*)));
00104   connect (processing_list_, SIGNAL (itemSelectionChanged ()), this, SLOT (filterSelectionChanged ()));
00105 
00106 
00107   up_ = new QPushButton ("up");
00108   down_ = new QPushButton ("down");
00109   remove_ = new QPushButton ("remove");
00110 
00111   connect (up_, SIGNAL (clicked ()), this, SLOT (moveFilterUp ()));
00112   connect (down_, SIGNAL (clicked ()), this, SLOT (moveFilterDown ()));
00113   connect (remove_, SIGNAL (clicked ()), this, SLOT (removeFilter ()));
00114 
00115   up_->setEnabled (false);
00116   down_->setEnabled (false);
00117   remove_->setEnabled (false);
00118 
00119   pcl_visualizer_ = new pcl::visualization::PCLVisualizer ("", false);
00120   qvtk_widget_ = new QVTKWidget (central_widget);
00121   qvtk_widget_->SetRenderWindow (pcl_visualizer_->getRenderWindow ());
00122   pcl_visualizer_->setupInteractor (qvtk_widget_->GetInteractor (), qvtk_widget_->GetRenderWindow ());
00123   qvtk_widget_->update ();
00124 
00125 
00126   // setup layouts
00127   QHBoxLayout * sensor_layout = new QHBoxLayout ();
00128   sensor_layout->addWidget (sensor_label, 0, Qt::AlignLeft);
00129   sensor_layout->addWidget (sensor_selection_combo_box, 1);
00130 
00131   QHBoxLayout * button_layout = new QHBoxLayout ();
00132   button_layout->addWidget (up_);
00133   button_layout->addWidget (down_);
00134   button_layout->addWidget (remove_);
00135 
00136   QVBoxLayout * sensor_processing_list_layout = new QVBoxLayout ();
00137   sensor_processing_list_layout->addLayout (sensor_layout, 0);
00138   sensor_processing_list_layout->addWidget (processing_list_);
00139   sensor_processing_list_layout->addLayout (button_layout, 0);
00140 
00141   QHBoxLayout * main_layout = new QHBoxLayout (central_widget);
00142   main_layout->addLayout (sensor_processing_list_layout, 0);
00143   main_layout->addWidget (qvtk_widget_, 1);
00144 
00145   this->resize (1024, 600);
00146   this->setCentralWidget (central_widget);
00147 }
00148 
00150 pcl::apps::optronic_viewer::
00151 MainWindow::
00152 ~MainWindow ()
00153 {
00154   // exit Fotonic API
00155   pcl::FotonicGrabber::exitAPI ();
00156 }
00157 
00159 void
00160 pcl::apps::optronic_viewer::
00161 MainWindow::
00162 createFileMenu ()
00163 {
00164   // File menu
00165   QAction * exit_act = new QAction (tr ("E&xit"), this);
00166   exit_act->setStatusTip (tr ("Closes the viewer"));
00167   connect(exit_act, SIGNAL(triggered()), this, SLOT(close ()));
00168 
00169   QMenu * file_menu = this->menuBar ()->addMenu (tr ("&File"));
00170   file_menu->addAction (exit_act);
00171 
00172 
00173   // Process menu
00174   QAction * add_filter_act = new QAction (tr ("Add &Filter"), this);
00175   add_filter_act->setStatusTip (tr ("Adds a filter"));
00176   connect(add_filter_act, SIGNAL (triggered ()), this, SLOT (addFilter ()));
00177 
00178   QMenu * process_menu = this->menuBar ()->addMenu (tr ("&Process"));
00179   process_menu->addAction (add_filter_act);
00180 }
00181 
00183 void
00184 pcl::apps::optronic_viewer::
00185 MainWindow::
00186 findConnectedDevices ()
00187 {
00188   connected_devices_.clear ();
00189 
00190   std::cerr << "Check for OpenNI devices..." << std::endl;
00191   openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance();
00192   if (driver.getNumberDevices() > 0)
00193   {
00194     std::cerr << "Connected devices:" << std::endl;
00195     for (unsigned device_idx = 0; device_idx < driver.getNumberDevices(); ++device_idx)
00196     {
00197       std::cout << "  Device: " << device_idx + 1 << ", vendor: " << driver.getVendorName(device_idx) << ", product: " << driver.getProductName(device_idx)
00198         << ", connected: " << driver.getBus(device_idx) << " @ " << driver.getAddress(device_idx) << ", serial number: \'" << driver.getSerialNumber(device_idx) << "\'" << endl;
00199 
00200       OpenNIDevice * device = new OpenNIDevice ();
00201       device->device_id = device_idx + 1;
00202       device->name = driver.getProductName (device_idx);
00203       device->vendor = driver.getVendorName(device_idx);
00204       device->serial_number = driver.getSerialNumber(device_idx);
00205 
00206       connected_devices_.push_back (device);
00207     }
00208 
00209   }
00210   else
00211     std::cout << "No devices connected." << endl;
00212 
00213 
00214   std::cerr << "Check for Fotonic devices..." << std::endl;
00215   std::vector<FZ_DEVICE_INFO> fotonic_devices = pcl::FotonicGrabber::enumDevices ();
00216   for (int device_index = 0; device_index < fotonic_devices.size (); ++device_index)
00217   {
00218     FotonicDevice * device = new FotonicDevice ();
00219 
00220     device->device_info.iDeviceType = fotonic_devices[device_index].iDeviceType;
00221     memcpy (device->device_info.szPath, fotonic_devices[device_index].szPath, sizeof (fotonic_devices[device_index].szPath[0])*512);
00222     memcpy (device->device_info.szSerial, fotonic_devices[device_index].szSerial, sizeof (fotonic_devices[device_index].szSerial[0])*16);
00223     memcpy (device->device_info.szShortName, fotonic_devices[device_index].szShortName, sizeof (fotonic_devices[device_index].szShortName[0])*32);
00224 
00225     std::cerr << "device id " << device_index << std::endl;
00226     std::cerr << "  device type: " << fotonic_devices[device_index].iDeviceType << std::endl;
00227     std::cerr << "  device path: " << fotonic_devices[device_index].szPath << std::endl;
00228     std::cerr << "  device serial: " << fotonic_devices[device_index].szSerial << std::endl;
00229     std::cerr << "  device short name: " << fotonic_devices[device_index].szShortName << std::endl;
00230 
00231     connected_devices_.push_back (device);
00232   }
00233 }
00234 
00236 void 
00237 pcl::apps::optronic_viewer::
00238 MainWindow::
00239 selectedSensorChanged (int index)
00240 {
00241   std::cerr << "selected sensor changed to " << index << std::endl;
00242 
00243   // stop old grabber
00244   if (grabber_ != NULL)
00245   {
00246     if (grabber_->isRunning ())
00247       grabber_->stop ();
00248   }
00249 
00250   // stop old grabber thread
00251   if (grabber_thread_ != NULL)
00252   {
00253     disconnect (grabber_thread_, SIGNAL(cloudReceived (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr)), this, SLOT(cloud_callback (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr)));
00254     grabber_thread_->terminate ();
00255 
00256     delete grabber_thread_;
00257     grabber_thread_ = NULL;
00258   }
00259 
00260   // delete old grabber
00261   if (grabber_ != NULL)
00262   {
00263     delete grabber_;
00264     grabber_ = NULL;
00265   }
00266 
00267   if (index != 0)
00268   {
00269     if (connected_devices_[index-1]->device_type == OPENNI_DEVICE)
00270     {
00271       std::stringstream ss;
00272       ss << "#" << reinterpret_cast<OpenNIDevice*> (connected_devices_[index-1])->device_id;
00273 
00274       grabber_ = new pcl::OpenNIGrabber (ss.str ());
00275 
00276     }
00277 
00278     if (connected_devices_[index-1]->device_type == FOTONIC_DEVICE)
00279     {
00280       grabber_ = new pcl::FotonicGrabber (reinterpret_cast<FotonicDevice*> (connected_devices_[index-1])->device_info);
00281     }
00282 
00283     grabber_thread_ = new pcl::apps::optronic_viewer::OpenNIGrabber (grabber_);
00284     grabber_thread_->start ();
00285     connect (grabber_thread_, SIGNAL(cloudReceived (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr)), this, SLOT(cloud_callback (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr)));
00286 
00287     QTimer::singleShot (30, this, SLOT(refresh ()));
00288   }
00289 }
00290 
00292 void 
00293 pcl::apps::optronic_viewer::
00294 MainWindow::
00295 refresh ()
00296 {
00297         QTime now;
00298         now.start();
00299 
00300   if (cloud_mutex_.try_lock ())
00301   {
00302     // apply filters
00303     pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr cloud_in = cloud_;
00304     pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud_out (new pcl::PointCloud<pcl::PointXYZRGBA> ());
00305     for (int i = 0; i < active_cloud_filters_.size (); ++i)
00306     {
00307       active_cloud_filters_[i]->filter (cloud_in, cloud_out);
00308       cloud_in = cloud_out;
00309       cloud_out.reset (new pcl::PointCloud<pcl::PointXYZRGBA> ());
00310     }
00311 
00312     // only update if cloud is not empty, otherwise the reset of the camera 
00313     // viewpoint won't work when initially selecting a sensor
00314     if (!cloud_in->empty ()) 
00315     {
00316       // visualize
00317       if (!pcl_visualizer_->updatePointCloud (cloud_in, "OpenNICloud"))
00318       {
00319         pcl_visualizer_->addPointCloud (cloud_in, "OpenNICloud");
00320         pcl_visualizer_->resetCameraViewpoint ("OpenNICloud");
00321       }  
00322     }
00323     cloud_mutex_.unlock ();
00324   }
00325   qvtk_widget_->GetRenderWindow ()->Render ();
00326 
00327   int elapsed_time = now.elapsed ();
00328   int time = 30 - elapsed_time;
00329 
00330   std::cerr << "elapsed time: " << elapsed_time << std::endl;
00331 
00332   if (time < 0)
00333     time = 0;
00334 
00335   QTimer::singleShot (time, this, SLOT(refresh ()));
00336 }
00337 
00339 void 
00340 pcl::apps::optronic_viewer::
00341 MainWindow::
00342 cloud_callback (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr cloud)
00343 {
00344   //std::cerr << "cloud received" << std::endl;
00345 
00346   if (cloud_mutex_.try_lock ())
00347   {
00348     cloud_ = cloud;
00349     cloud_mutex_.unlock ();
00350   }
00351 }
00352 
00354 void 
00355 pcl::apps::optronic_viewer::
00356 MainWindow::
00357 addFilter ()
00358 {
00359   std::cerr << "add filter..." << std::endl;
00360 
00361   // open window to select new filter
00362   pcl::apps::optronic_viewer::FilterWindow * filter_dialog = new pcl::apps::optronic_viewer::FilterWindow (filter_factories_, active_cloud_filters_);
00363   filter_dialog->setWindowTitle (tr ("Add Filter..."));
00364 
00365   connect (filter_dialog, SIGNAL (filterCreated ()), this, SLOT (refreshFilterList ()));
00366 
00367   filter_dialog->show ();
00368 }
00369 
00371 void 
00372 pcl::apps::optronic_viewer::
00373 MainWindow::
00374 updateFilter (QListWidgetItem * item)
00375 {
00376   int id = processing_list_->row (item);
00377 
00378   QWizard * wizard = new QWizard ();
00379   wizard->addPage (active_cloud_filters_[id]->getParameterPage ());
00380   wizard->show ();
00381 }
00382 
00384 void 
00385 pcl::apps::optronic_viewer::
00386 MainWindow::
00387 filterSelectionChanged ()
00388 {
00389   std::cerr << "filter selection changed..." << std::endl;
00390 
00391   QList<QListWidgetItem*> selected_items = processing_list_->selectedItems ();
00392 
00393   std::cerr << "number of selected items: " << selected_items.size () << std::endl;
00394 
00395   if (selected_items.size () != 0)
00396   {
00397     int row = processing_list_->row (selected_items[0]);
00398     std::cerr << "selected filter: " << row << std::endl;
00399 
00400     if (row != 0)
00401       up_->setEnabled (true);
00402     else
00403       up_->setEnabled (false);
00404     
00405     const int list_size = active_cloud_filters_.size ();
00406     if (row != list_size-1)
00407       down_->setEnabled (true);
00408     else
00409       down_->setEnabled (false);
00410 
00411     remove_->setEnabled (true);
00412   }
00413   else
00414   {
00415     up_->setEnabled (false);
00416     down_->setEnabled (false);
00417     remove_->setEnabled (false);
00418   }
00419 }
00420 
00422 void 
00423 pcl::apps::optronic_viewer::
00424 MainWindow::
00425 moveFilterUp ()
00426 {
00427   std::cerr << "move filter up" << std::endl;
00428 
00429   QList<QListWidgetItem*> selected_items = processing_list_->selectedItems ();
00430   int change_id = processing_list_->row (selected_items[0]);
00431 
00432   pcl::apps::optronic_viewer::CloudFilter* tmp = active_cloud_filters_[change_id];
00433   active_cloud_filters_[change_id] = active_cloud_filters_[change_id-1];
00434   active_cloud_filters_[change_id-1] = tmp;
00435 
00436   refreshFilterList ();
00437 
00438   processing_list_->setCurrentRow (change_id-1);
00439 }
00440 
00442 void 
00443 pcl::apps::optronic_viewer::
00444 MainWindow::
00445 moveFilterDown ()
00446 {
00447   std::cerr << "move filter down" << std::endl;
00448 
00449   QList<QListWidgetItem*> selected_items = processing_list_->selectedItems ();
00450   int change_id = processing_list_->row (selected_items[0]);
00451 
00452   pcl::apps::optronic_viewer::CloudFilter* tmp = active_cloud_filters_[change_id];
00453   active_cloud_filters_[change_id] = active_cloud_filters_[change_id+1];
00454   active_cloud_filters_[change_id+1] = tmp;
00455 
00456   refreshFilterList ();
00457 
00458   processing_list_->setCurrentRow (change_id+1);
00459 }
00460 
00462 void 
00463 pcl::apps::optronic_viewer::
00464 MainWindow::
00465 removeFilter ()
00466 {
00467   std::cerr << "remove filter" << std::endl;
00468 
00469   QList<QListWidgetItem*> selected_items = processing_list_->selectedItems ();
00470   int remove_id = processing_list_->row (selected_items[0]);
00471 
00472   pcl::apps::optronic_viewer::CloudFilter* tmp = active_cloud_filters_[remove_id];
00473   active_cloud_filters_.erase (active_cloud_filters_.begin()+remove_id);
00474   refreshFilterList ();
00475 
00476   cloud_mutex_.lock ();
00477   delete tmp;
00478   cloud_mutex_.unlock ();
00479 
00480   if (active_cloud_filters_.size () > remove_id)
00481     processing_list_->setCurrentRow (remove_id);
00482   else
00483     processing_list_->setCurrentRow (remove_id-1);
00484 }
00485 
00487 void 
00488 pcl::apps::optronic_viewer::
00489 MainWindow::
00490 refreshFilterList ()
00491 {
00492   processing_list_->clear ();
00493   std::cerr << "filters: " << std::endl;
00494   for (int i = 0; i < active_cloud_filters_.size (); ++i)
00495   {
00496     std::cerr << "  " << active_cloud_filters_[i]->getName () << std::endl;
00497     processing_list_->addItem (QString (active_cloud_filters_[i]->getName ().c_str ()));
00498   }
00499 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:25:22