00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
00061 pcl::FotonicGrabber::initAPI ();
00062
00063
00064
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
00075 cloud_.reset (new pcl::PointCloud<pcl::PointXYZRGBA> ());
00076
00077
00078
00079 this->setWindowTitle ("PCL Optronic Viewer");
00080
00081
00082
00083 this->createFileMenu ();
00084
00085
00086
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
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
00155 pcl::FotonicGrabber::exitAPI ();
00156 }
00157
00159 void
00160 pcl::apps::optronic_viewer::
00161 MainWindow::
00162 createFileMenu ()
00163 {
00164
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
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
00244 if (grabber_ != NULL)
00245 {
00246 if (grabber_->isRunning ())
00247 grabber_->stop ();
00248 }
00249
00250
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
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
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
00313
00314 if (!cloud_in->empty ())
00315 {
00316
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
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
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 }