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/pcl_config.h>
00039 #ifdef HAVE_OPENNI
00040
00041 #include <pcl/io/openni_grabber.h>
00042 #include <pcl/point_cloud.h>
00043 #include <pcl/point_types.h>
00044 #include <pcl/common/time.h>
00045 #include <pcl/console/print.h>
00046 #include <pcl/io/pcl_io_exception.h>
00047 #include <boost/shared_array.hpp>
00048 #include <boost/filesystem.hpp>
00049 #include <iostream>
00050
00051 namespace pcl
00052 {
00053 typedef union
00054 {
00055 struct
00056 {
00057 unsigned char Blue;
00058 unsigned char Green;
00059 unsigned char Red;
00060 unsigned char Alpha;
00061 };
00062 float float_value;
00063 uint32_t long_value;
00064 } RGBValue;
00065 }
00066
00068 pcl::OpenNIGrabber::OpenNIGrabber (const std::string& device_id, const Mode& depth_mode, const Mode& image_mode)
00069 : rgb_sync_ ()
00070 , ir_sync_ ()
00071 , device_ ()
00072 , rgb_frame_id_ ()
00073 , depth_frame_id_ ()
00074 , image_width_ ()
00075 , image_height_ ()
00076 , depth_width_ ()
00077 , depth_height_ ()
00078 , image_required_ (false)
00079 , depth_required_ (false)
00080 , ir_required_ (false)
00081 , sync_required_ (false)
00082 , image_signal_ (), depth_image_signal_ (), ir_image_signal_ (), image_depth_image_signal_ ()
00083 , ir_depth_image_signal_ (), point_cloud_signal_ (), point_cloud_i_signal_ ()
00084 , point_cloud_rgb_signal_ (), point_cloud_rgba_signal_ (), point_cloud_eigen_signal_ ()
00085 , config2xn_map_ (), depth_callback_handle (), image_callback_handle (), ir_callback_handle ()
00086 , running_ (false)
00087 {
00088
00089 onInit (device_id, depth_mode, image_mode);
00090
00091 if (!device_->hasDepthStream ())
00092 THROW_PCL_IO_EXCEPTION ("Device does not provide 3D information.");
00093
00094 depth_image_signal_ = createSignal<sig_cb_openni_depth_image> ();
00095 ir_image_signal_ = createSignal<sig_cb_openni_ir_image> ();
00096 point_cloud_signal_ = createSignal<sig_cb_openni_point_cloud> ();
00097 point_cloud_i_signal_ = createSignal<sig_cb_openni_point_cloud_i> ();
00098 ir_depth_image_signal_ = createSignal<sig_cb_openni_ir_depth_image> ();
00099
00100 ir_sync_.addCallback (boost::bind (&OpenNIGrabber::irDepthImageCallback, this, _1, _2));
00101 if (device_->hasImageStream ())
00102 {
00103
00104 image_signal_ = createSignal<sig_cb_openni_image> ();
00105 image_depth_image_signal_ = createSignal<sig_cb_openni_image_depth_image> ();
00106 point_cloud_rgb_signal_ = createSignal<sig_cb_openni_point_cloud_rgb> ();
00107 point_cloud_rgba_signal_ = createSignal<sig_cb_openni_point_cloud_rgba> ();
00108 point_cloud_eigen_signal_ = createSignal<sig_cb_openni_point_cloud_eigen> ();
00109 rgb_sync_.addCallback (boost::bind (&OpenNIGrabber::imageDepthImageCallback, this, _1, _2));
00110 openni_wrapper::DeviceKinect* kinect = dynamic_cast<openni_wrapper::DeviceKinect*> (device_.get ());
00111 if (kinect)
00112 kinect->setDebayeringMethod (openni_wrapper::ImageBayerGRBG::EdgeAware);
00113 }
00114
00115 image_callback_handle = device_->registerImageCallback (&OpenNIGrabber::imageCallback, *this);
00116 depth_callback_handle = device_->registerDepthCallback (&OpenNIGrabber::depthCallback, *this);
00117 ir_callback_handle = device_->registerIRCallback (&OpenNIGrabber::irCallback, *this);
00118 }
00119
00121 pcl::OpenNIGrabber::~OpenNIGrabber () throw ()
00122 {
00123 try
00124 {
00125 stop ();
00126
00127
00128 device_->unregisterDepthCallback (depth_callback_handle);
00129
00130 if (device_->hasImageStream ())
00131 device_->unregisterImageCallback (image_callback_handle);
00132
00133 if (device_->hasIRStream ())
00134 device_->unregisterIRCallback (image_callback_handle);
00135
00136
00137 device_.reset ();
00138
00139
00140 disconnect_all_slots<sig_cb_openni_image> ();
00141 disconnect_all_slots<sig_cb_openni_depth_image> ();
00142 disconnect_all_slots<sig_cb_openni_ir_image> ();
00143 disconnect_all_slots<sig_cb_openni_image_depth_image> ();
00144 disconnect_all_slots<sig_cb_openni_point_cloud> ();
00145 disconnect_all_slots<sig_cb_openni_point_cloud_rgb> ();
00146 disconnect_all_slots<sig_cb_openni_point_cloud_rgba> ();
00147 disconnect_all_slots<sig_cb_openni_point_cloud_i> ();
00148 disconnect_all_slots<sig_cb_openni_point_cloud_eigen> ();
00149
00150 openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance ();
00151 driver.stopAll ();
00152 }
00153 catch (...)
00154 {
00155
00156 }
00157 }
00158
00160 void
00161 pcl::OpenNIGrabber::checkImageAndDepthSynchronizationRequired ()
00162 {
00163
00164 if (num_slots<sig_cb_openni_point_cloud_rgb> () > 0 ||
00165 num_slots<sig_cb_openni_point_cloud_rgba> () > 0 ||
00166 num_slots<sig_cb_openni_point_cloud_eigen> () > 0 ||
00167 num_slots<sig_cb_openni_image_depth_image> () > 0)
00168 sync_required_ = true;
00169 else
00170 sync_required_ = false;
00171 }
00172
00174 void
00175 pcl::OpenNIGrabber::checkImageStreamRequired ()
00176 {
00177
00178 if (num_slots<sig_cb_openni_image> () > 0 ||
00179 num_slots<sig_cb_openni_image_depth_image> () > 0 ||
00180 num_slots<sig_cb_openni_point_cloud_eigen> () > 0 ||
00181 num_slots<sig_cb_openni_point_cloud_rgba> () > 0 ||
00182 num_slots<sig_cb_openni_point_cloud_rgb> () > 0)
00183 image_required_ = true;
00184 else
00185 image_required_ = false;
00186 }
00187
00189 void
00190 pcl::OpenNIGrabber::checkDepthStreamRequired ()
00191 {
00192
00193 if (num_slots<sig_cb_openni_depth_image> () > 0 ||
00194 num_slots<sig_cb_openni_image_depth_image> () > 0 ||
00195 num_slots<sig_cb_openni_ir_depth_image> () > 0 ||
00196 num_slots<sig_cb_openni_point_cloud_eigen> () > 0 ||
00197 num_slots<sig_cb_openni_point_cloud_rgb> () > 0 ||
00198 num_slots<sig_cb_openni_point_cloud_rgba> () > 0 ||
00199 num_slots<sig_cb_openni_point_cloud> () > 0 ||
00200 num_slots<sig_cb_openni_point_cloud_i> () > 0 )
00201 depth_required_ = true;
00202 else
00203 depth_required_ = false;
00204 }
00205
00207 void
00208 pcl::OpenNIGrabber::checkIRStreamRequired ()
00209 {
00210 if (num_slots<sig_cb_openni_ir_image> () > 0 ||
00211 num_slots<sig_cb_openni_point_cloud_i> () > 0 ||
00212 num_slots<sig_cb_openni_ir_depth_image> () > 0)
00213 ir_required_ = true;
00214 else
00215 ir_required_ = false;
00216 }
00217
00219 void
00220 pcl::OpenNIGrabber::start ()
00221 {
00222 try
00223 {
00224
00225 if (image_required_ && !device_->isImageStreamRunning ())
00226 {
00227 block_signals ();
00228 device_->startImageStream ();
00229
00230 }
00231
00232 if (depth_required_ && !device_->isDepthStreamRunning ())
00233 {
00234 block_signals ();
00235 if (device_->hasImageStream () && !device_->isDepthRegistered () && device_->isDepthRegistrationSupported ())
00236 {
00237 device_->setDepthRegistration (true);
00238 }
00239 device_->startDepthStream ();
00240
00241 }
00242
00243 if (ir_required_ && !device_->isIRStreamRunning ())
00244 {
00245 block_signals ();
00246 device_->startIRStream ();
00247 }
00248 running_ = true;
00249 }
00250 catch (openni_wrapper::OpenNIException& ex)
00251 {
00252 THROW_PCL_IO_EXCEPTION ("Could not start streams. Reason: %s", ex.what ());
00253 }
00254
00255 boost::this_thread::sleep (boost::posix_time::seconds (1));
00256 unblock_signals ();
00257 }
00258
00260 void
00261 pcl::OpenNIGrabber::stop ()
00262 {
00263 try
00264 {
00265 if (device_->hasDepthStream () && device_->isDepthStreamRunning ())
00266 device_->stopDepthStream ();
00267
00268 if (device_->hasImageStream () && device_->isImageStreamRunning ())
00269 device_->stopImageStream ();
00270
00271 if (device_->hasIRStream () && device_->isIRStreamRunning ())
00272 device_->stopIRStream ();
00273
00274 running_ = false;
00275 }
00276 catch (openni_wrapper::OpenNIException& ex)
00277 {
00278 THROW_PCL_IO_EXCEPTION ("Could not stop streams. Reason: %s", ex.what ());
00279 }
00280 }
00281
00283 bool
00284 pcl::OpenNIGrabber::isRunning () const
00285 {
00286 return (running_);
00287 }
00288
00290 void
00291 pcl::OpenNIGrabber::onInit (const std::string& device_id, const Mode& depth_mode, const Mode& image_mode)
00292 {
00293 updateModeMaps ();
00294 setupDevice (device_id, depth_mode, image_mode);
00295
00296 rgb_frame_id_ = "/openni_rgb_optical_frame";
00297
00298 depth_frame_id_ = "/openni_depth_optical_frame";
00299 }
00300
00302 void
00303 pcl::OpenNIGrabber::signalsChanged ()
00304 {
00305
00306 checkImageStreamRequired ();
00307 checkDepthStreamRequired ();
00308 checkIRStreamRequired ();
00309 if (ir_required_ && image_required_)
00310 THROW_PCL_IO_EXCEPTION ("Can not provide IR stream and RGB stream at the same time.");
00311
00312 checkImageAndDepthSynchronizationRequired ();
00313 if (running_)
00314 start ();
00315 }
00316
00318 std::string
00319 pcl::OpenNIGrabber::getName () const
00320 {
00321 return std::string ("OpenNIGrabber");
00322 }
00323
00325 void
00326 pcl::OpenNIGrabber::setupDevice (const std::string& device_id, const Mode& depth_mode, const Mode& image_mode)
00327 {
00328
00329 openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance ();
00330
00331 try
00332 {
00333 if (boost::filesystem::exists (device_id))
00334 {
00335 device_ = driver.createVirtualDevice (device_id, true, true);
00336 }
00337 else if (driver.getNumberDevices () == 0)
00338 {
00339 THROW_PCL_IO_EXCEPTION ("No devices connected.");
00340 }
00341 else if (device_id[0] == '#')
00342 {
00343 unsigned index = atoi (device_id.c_str () + 1);
00344
00345 device_ = driver.getDeviceByIndex (index - 1);
00346 }
00347 #ifndef _WIN32
00348 else if (device_id.find ('@') != std::string::npos)
00349 {
00350 size_t pos = device_id.find ('@');
00351 unsigned bus = atoi (device_id.substr (0, pos).c_str ());
00352 unsigned address = atoi (device_id.substr (pos + 1, device_id.length () - pos - 1).c_str ());
00353
00354 device_ = driver.getDeviceByAddress (static_cast<unsigned char>(bus), static_cast<unsigned char>(address) );
00355 }
00356 #endif
00357 else if (!device_id.empty ())
00358 {
00359
00360 device_ = driver.getDeviceBySerialNumber (device_id);
00361 }
00362 else
00363 {
00364 device_ = driver.getDeviceByIndex (0);
00365 }
00366 }
00367 catch (const openni_wrapper::OpenNIException& exception)
00368 {
00369 if (!device_)
00370 THROW_PCL_IO_EXCEPTION ("No matching device found. %s", exception.what ());
00371 else
00372 THROW_PCL_IO_EXCEPTION ("could not retrieve device. Reason %s", exception.what ());
00373 }
00374 catch (const pcl::PCLIOException&)
00375 {
00376 throw;
00377 }
00378 catch (...)
00379 {
00380 THROW_PCL_IO_EXCEPTION ("unknown error occured");
00381 }
00382
00383 XnMapOutputMode depth_md;
00384
00385 if (depth_mode != OpenNI_Default_Mode)
00386 {
00387 XnMapOutputMode actual_depth_md;
00388 if (!mapConfigMode2XnMode (depth_mode, depth_md) || !device_->findCompatibleDepthMode (depth_md, actual_depth_md))
00389 THROW_PCL_IO_EXCEPTION ("could not find compatible depth stream mode %d", static_cast<int> (depth_mode) );
00390
00391 XnMapOutputMode current_depth_md = device_->getDepthOutputMode ();
00392 if (current_depth_md.nXRes != actual_depth_md.nXRes || current_depth_md.nYRes != actual_depth_md.nYRes)
00393 device_->setDepthOutputMode (actual_depth_md);
00394 }
00395 else
00396 {
00397 depth_md = device_->getDefaultDepthMode ();
00398 }
00399
00400 depth_width_ = depth_md.nXRes;
00401 depth_height_ = depth_md.nYRes;
00402
00403 if (device_->hasImageStream ())
00404 {
00405 XnMapOutputMode image_md;
00406 if (image_mode != OpenNI_Default_Mode)
00407 {
00408 XnMapOutputMode actual_image_md;
00409 if (!mapConfigMode2XnMode (image_mode, image_md) || !device_->findCompatibleImageMode (image_md, actual_image_md))
00410 THROW_PCL_IO_EXCEPTION ("could not find compatible image stream mode %d", static_cast<int> (image_mode) );
00411
00412 XnMapOutputMode current_image_md = device_->getImageOutputMode ();
00413 if (current_image_md.nXRes != actual_image_md.nXRes || current_image_md.nYRes != actual_image_md.nYRes)
00414 device_->setImageOutputMode (actual_image_md);
00415 }
00416 else
00417 {
00418 image_md = device_->getDefaultImageMode ();
00419 }
00420
00421 image_width_ = image_md.nXRes;
00422 image_height_ = image_md.nYRes;
00423 }
00424 }
00425
00427 void
00428 pcl::OpenNIGrabber::startSynchronization ()
00429 {
00430 try
00431 {
00432 if (device_->isSynchronizationSupported () && !device_->isSynchronized () &&
00433 device_->getImageOutputMode ().nFPS == device_->getDepthOutputMode ().nFPS &&
00434 device_->isImageStreamRunning () && device_->isDepthStreamRunning ())
00435 device_->setSynchronization (true);
00436 }
00437 catch (const openni_wrapper::OpenNIException& exception)
00438 {
00439 THROW_PCL_IO_EXCEPTION ("Could not start synchronization %s", exception.what ());
00440 }
00441 }
00442
00444 void
00445 pcl::OpenNIGrabber::stopSynchronization ()
00446 {
00447 try
00448 {
00449 if (device_->isSynchronizationSupported () && device_->isSynchronized ())
00450 device_->setSynchronization (false);
00451 }
00452 catch (const openni_wrapper::OpenNIException& exception)
00453 {
00454 THROW_PCL_IO_EXCEPTION ("Could not start synchronization %s", exception.what ());
00455 }
00456 }
00457
00459 void
00460 pcl::OpenNIGrabber::imageCallback (boost::shared_ptr<openni_wrapper::Image> image, void*)
00461 {
00462 if (num_slots<sig_cb_openni_point_cloud_rgb> () > 0 ||
00463 num_slots<sig_cb_openni_point_cloud_rgba> () > 0 ||
00464 num_slots<sig_cb_openni_point_cloud_eigen> () > 0 ||
00465 num_slots<sig_cb_openni_image_depth_image> () > 0)
00466 rgb_sync_.add0 (image, image->getTimeStamp ());
00467
00468 if (image_signal_->num_slots () > 0)
00469 image_signal_->operator()(image);
00470 }
00471
00473 void
00474 pcl::OpenNIGrabber::depthCallback (boost::shared_ptr<openni_wrapper::DepthImage> depth_image, void*)
00475 {
00476 if (num_slots<sig_cb_openni_point_cloud_rgb> () > 0 ||
00477 num_slots<sig_cb_openni_point_cloud_rgba> () > 0 ||
00478 num_slots<sig_cb_openni_point_cloud_eigen> () > 0 ||
00479 num_slots<sig_cb_openni_image_depth_image> () > 0)
00480 rgb_sync_.add1 (depth_image, depth_image->getTimeStamp ());
00481
00482 if (num_slots<sig_cb_openni_point_cloud_i> () > 0 ||
00483 num_slots<sig_cb_openni_ir_depth_image> () > 0)
00484 ir_sync_.add1 (depth_image, depth_image->getTimeStamp ());
00485
00486 if (depth_image_signal_->num_slots () > 0)
00487 depth_image_signal_->operator()(depth_image);
00488
00489 if (point_cloud_signal_->num_slots () > 0)
00490 point_cloud_signal_->operator()(convertToXYZPointCloud(depth_image));
00491 }
00492
00494 void
00495 pcl::OpenNIGrabber::irCallback (boost::shared_ptr<openni_wrapper::IRImage> ir_image, void*)
00496 {
00497 if (num_slots<sig_cb_openni_point_cloud_i> () > 0 ||
00498 num_slots<sig_cb_openni_ir_depth_image> () > 0)
00499 ir_sync_.add0(ir_image, ir_image->getTimeStamp ());
00500
00501 if (ir_image_signal_->num_slots () > 0)
00502 ir_image_signal_->operator()(ir_image);
00503 }
00504
00506 void
00507 pcl::OpenNIGrabber::imageDepthImageCallback (const boost::shared_ptr<openni_wrapper::Image> &image,
00508 const boost::shared_ptr<openni_wrapper::DepthImage> &depth_image)
00509 {
00510
00511 if (point_cloud_rgb_signal_->num_slots () > 0)
00512 {
00513 PCL_WARN ("PointXYZRGB callbacks deprecated. Use PointXYZRGBA instead.\n");
00514 point_cloud_rgb_signal_->operator()(convertToXYZRGBPointCloud<pcl::PointXYZRGB> (image, depth_image));
00515 }
00516
00517 if (point_cloud_rgba_signal_->num_slots () > 0)
00518 point_cloud_rgba_signal_->operator()(convertToXYZRGBPointCloud<pcl::PointXYZRGBA> (image, depth_image));
00519
00520
00521 if (point_cloud_eigen_signal_->num_slots () > 0)
00522 point_cloud_eigen_signal_->operator()(convertToEigenPointCloud (image, depth_image));
00523
00524 if (image_depth_image_signal_->num_slots () > 0)
00525 {
00526 float constant = 1.0f / device_->getDepthFocalLength (depth_width_);
00527 image_depth_image_signal_->operator()(image, depth_image, constant);
00528 }
00529 }
00530
00532 void
00533 pcl::OpenNIGrabber::irDepthImageCallback (const boost::shared_ptr<openni_wrapper::IRImage> &ir_image,
00534 const boost::shared_ptr<openni_wrapper::DepthImage> &depth_image)
00535 {
00536
00537 if (point_cloud_i_signal_->num_slots () > 0)
00538 point_cloud_i_signal_->operator()(convertToXYZIPointCloud (ir_image, depth_image));
00539
00540 if (ir_depth_image_signal_->num_slots () > 0)
00541 {
00542 float constant = 1.0f / device_->getDepthFocalLength (depth_width_);
00543 ir_depth_image_signal_->operator()(ir_image, depth_image, constant);
00544 }
00545 }
00546
00548 pcl::PointCloud<pcl::PointXYZ>::Ptr
00549 pcl::OpenNIGrabber::convertToXYZPointCloud (const boost::shared_ptr<openni_wrapper::DepthImage>& depth_image) const
00550 {
00551 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud <pcl::PointXYZ>);
00552
00553 cloud->height = depth_height_;
00554 cloud->width = depth_width_;
00555 cloud->is_dense = false;
00556
00557 cloud->points.resize (cloud->height * cloud->width);
00558
00559 register float constant = 1.0f / device_->getDepthFocalLength (depth_width_);
00560
00561 if (device_->isDepthRegistered ())
00562 cloud->header.frame_id = rgb_frame_id_;
00563 else
00564 cloud->header.frame_id = depth_frame_id_;
00565
00566 register int centerX = (cloud->width >> 1);
00567 int centerY = (cloud->height >> 1);
00568
00569 float bad_point = std::numeric_limits<float>::quiet_NaN ();
00570
00571
00572 register const unsigned short* depth_map = depth_image->getDepthMetaData ().Data ();
00573 if (depth_image->getWidth() != depth_width_ || depth_image->getHeight () != depth_height_)
00574 {
00575 static unsigned buffer_size = 0;
00576 static boost::shared_array<unsigned short> depth_buffer (0);
00577
00578 if (buffer_size < depth_width_ * depth_height_)
00579 {
00580 buffer_size = depth_width_ * depth_height_;
00581 depth_buffer.reset (new unsigned short [buffer_size]);
00582 }
00583 depth_image->fillDepthImageRaw (depth_width_, depth_height_, depth_buffer.get ());
00584 depth_map = depth_buffer.get ();
00585 }
00586
00587 register int depth_idx = 0;
00588 for (int v = -centerY; v < centerY; ++v)
00589 {
00590 for (register int u = -centerX; u < centerX; ++u, ++depth_idx)
00591 {
00592 pcl::PointXYZ& pt = cloud->points[depth_idx];
00593
00594 if (depth_map[depth_idx] == 0 ||
00595 depth_map[depth_idx] == depth_image->getNoSampleValue () ||
00596 depth_map[depth_idx] == depth_image->getShadowValue ())
00597 {
00598
00599 pt.x = pt.y = pt.z = bad_point;
00600 continue;
00601 }
00602 pt.z = depth_map[depth_idx] * 0.001f;
00603 pt.x = static_cast<float> (u) * pt.z * constant;
00604 pt.y = static_cast<float> (v) * pt.z * constant;
00605 }
00606 }
00607 cloud->sensor_origin_.setZero ();
00608 cloud->sensor_orientation_.w () = 0.0f;
00609 cloud->sensor_orientation_.x () = 1.0f;
00610 cloud->sensor_orientation_.y () = 0.0f;
00611 cloud->sensor_orientation_.z () = 0.0f;
00612 return (cloud);
00613 }
00614
00616 template <typename PointT> typename pcl::PointCloud<PointT>::Ptr
00617 pcl::OpenNIGrabber::convertToXYZRGBPointCloud (const boost::shared_ptr<openni_wrapper::Image> &image,
00618 const boost::shared_ptr<openni_wrapper::DepthImage> &depth_image) const
00619 {
00620 static unsigned rgb_array_size = 0;
00621 static boost::shared_array<unsigned char> rgb_array (0);
00622 static unsigned char* rgb_buffer = 0;
00623
00624 boost::shared_ptr<pcl::PointCloud<PointT> > cloud (new pcl::PointCloud<PointT>);
00625
00626 cloud->header.frame_id = rgb_frame_id_;
00627 cloud->height = std::max (image_height_, depth_height_);
00628 cloud->width = std::max (image_width_, depth_width_);
00629 cloud->is_dense = false;
00630
00631 cloud->points.resize (cloud->height * cloud->width);
00632
00633 float constant = 1.0f / device_->getImageFocalLength (depth_width_);
00634 register int centerX = (depth_width_ >> 1);
00635 int centerY = (depth_height_ >> 1);
00636
00637 register const XnDepthPixel* depth_map = depth_image->getDepthMetaData ().Data ();
00638 if (depth_image->getWidth () != depth_width_ || depth_image->getHeight() != depth_height_)
00639 {
00640 static unsigned buffer_size = 0;
00641 static boost::shared_array<unsigned short> depth_buffer (0);
00642
00643 if (buffer_size < depth_width_ * depth_height_)
00644 {
00645 buffer_size = depth_width_ * depth_height_;
00646 depth_buffer.reset (new unsigned short [buffer_size]);
00647 }
00648
00649 depth_image->fillDepthImageRaw (depth_width_, depth_height_, depth_buffer.get ());
00650 depth_map = depth_buffer.get ();
00651 }
00652
00653
00654 if (rgb_array_size < image_width_ * image_height_ * 3)
00655 {
00656 rgb_array_size = image_width_ * image_height_ * 3;
00657 rgb_array.reset (new unsigned char [rgb_array_size]);
00658 rgb_buffer = rgb_array.get ();
00659 }
00660 image->fillRGB (image_width_, image_height_, rgb_buffer, image_width_ * 3);
00661 float bad_point = std::numeric_limits<float>::quiet_NaN ();
00662
00663
00664 if (image_width_ != depth_width_)
00665 {
00666 PointT pt;
00667 pt.x = pt.y = pt.z = bad_point;
00668 pt.b = pt.g = pt.r = 0;
00669 pt.a = 255;
00670 cloud->points.assign (cloud->points.size (), pt);
00671 }
00672
00673
00674 unsigned step = cloud->width / depth_width_;
00675 unsigned skip = cloud->width * step - cloud->width;
00676
00677 int value_idx = 0;
00678 int point_idx = 0;
00679 for (int v = -centerY; v < centerY; ++v, point_idx += skip)
00680 {
00681 for (register int u = -centerX; u < centerX; ++u, ++value_idx, point_idx += step)
00682 {
00683 PointT& pt = cloud->points[point_idx];
00685
00686
00687 if (depth_map[value_idx] != 0 &&
00688 depth_map[value_idx] != depth_image->getNoSampleValue () &&
00689 depth_map[value_idx] != depth_image->getShadowValue ())
00690 {
00691 pt.z = depth_map[value_idx] * 0.001f;
00692 pt.x = static_cast<float> (u) * pt.z * constant;
00693 pt.y = static_cast<float> (v) * pt.z * constant;
00694 }
00695 else
00696 {
00697 pt.x = pt.y = pt.z = bad_point;
00698 }
00699 }
00700 }
00701
00702
00703 step = cloud->width / image_width_;
00704 skip = cloud->width * step - cloud->width;
00705
00706 value_idx = 0;
00707 point_idx = 0;
00708 RGBValue color;
00709 color.Alpha = 0;
00710
00711 for (unsigned yIdx = 0; yIdx < image_height_; ++yIdx, point_idx += skip)
00712 {
00713 for (unsigned xIdx = 0; xIdx < image_width_; ++xIdx, point_idx += step, value_idx += 3)
00714 {
00715 PointT& pt = cloud->points[point_idx];
00716
00717 color.Red = rgb_buffer[value_idx];
00718 color.Green = rgb_buffer[value_idx + 1];
00719 color.Blue = rgb_buffer[value_idx + 2];
00720
00721 pt.rgba = color.long_value;
00722 }
00723 }
00724 cloud->sensor_origin_.setZero ();
00725 cloud->sensor_orientation_.w () = 0.0;
00726 cloud->sensor_orientation_.x () = 1.0;
00727 cloud->sensor_orientation_.y () = 0.0;
00728 cloud->sensor_orientation_.z () = 0.0;
00729 return (cloud);
00730 }
00731
00733 pcl::PointCloud<Eigen::MatrixXf>::Ptr
00734 pcl::OpenNIGrabber::convertToEigenPointCloud (const boost::shared_ptr<openni_wrapper::Image> &image,
00735 const boost::shared_ptr<openni_wrapper::DepthImage> &depth_image) const
00736 {
00737 static unsigned rgb_array_size = 0;
00738 static boost::shared_array<unsigned char> rgb_array (0);
00739 static unsigned char* rgb_buffer = 0;
00740
00741 boost::shared_ptr<pcl::PointCloud<Eigen::MatrixXf> > cloud (new pcl::PointCloud<Eigen::MatrixXf>);
00742
00743 cloud->properties.acquisition_time = depth_image->getTimeStamp ();
00744 cloud->height = depth_height_;
00745 cloud->width = depth_width_;
00746 cloud->is_dense = false;
00747
00748 cloud->channels["rgb"].name = "rgb";
00749 cloud->channels["x"].name = "x"; cloud->channels["y"].name = "y"; cloud->channels["z"].name = "z";
00750 cloud->channels["rgb"].offset = 0;
00751 cloud->channels["x"].offset = 4; cloud->channels["y"].offset = 8; cloud->channels["z"].offset = 12;
00752 cloud->channels["x"].size = cloud->channels["y"].size = cloud->channels["z"].size = cloud->channels["rgb"].size = 4;
00753 cloud->channels["rgb"].datatype = 6;
00754 cloud->channels["x"].datatype = cloud->channels["y"].datatype = cloud->channels["z"].datatype = 7;
00755 cloud->channels["x"].count = cloud->channels["y"].count = cloud->channels["z"].count = cloud->channels["rgb"].count = 1;
00756
00757
00758 cloud->points.resize (cloud->height * cloud->width, 4);
00759
00760 float constant = 1.0f / device_->getImageFocalLength (cloud->width);
00761 register int centerX = (cloud->width >> 1);
00762 int centerY = (cloud->height >> 1);
00763
00764 register const XnDepthPixel* depth_map = depth_image->getDepthMetaData ().Data ();
00765 if (depth_image->getWidth () != depth_width_ || depth_image->getHeight() != depth_height_)
00766 {
00767 static unsigned buffer_size = 0;
00768 static boost::shared_array<unsigned short> depth_buffer (0);
00769
00770 if (buffer_size < depth_width_ * depth_height_)
00771 {
00772 buffer_size = depth_width_ * depth_height_;
00773 depth_buffer.reset (new unsigned short [buffer_size]);
00774 }
00775
00776 depth_image->fillDepthImageRaw (depth_width_, depth_height_, depth_buffer.get ());
00777 depth_map = depth_buffer.get ();
00778 }
00779
00780
00781 if (rgb_array_size < image_width_ * image_height_ * 3)
00782 {
00783 rgb_array_size = image_width_ * image_height_ * 3;
00784 rgb_array.reset (new unsigned char [rgb_array_size]);
00785 rgb_buffer = rgb_array.get ();
00786 }
00787 image->fillRGB (image_width_, image_height_, rgb_buffer, image_width_ * 3);
00788
00789
00790 register int color_idx = 0, depth_idx = 0;
00791 RGBValue color;
00792 color.Alpha = 0;
00793
00794 float bad_point = std::numeric_limits<float>::quiet_NaN ();
00795
00796 for (int v = -centerY; v < centerY; ++v)
00797 {
00798 for (register int u = -centerX; u < centerX; ++u, color_idx += 3, ++depth_idx)
00799 {
00801
00802 if (depth_map[depth_idx] == 0 ||
00803 depth_map[depth_idx] == depth_image->getNoSampleValue () ||
00804 depth_map[depth_idx] == depth_image->getShadowValue ())
00805 {
00806 cloud->points.row (depth_idx).setConstant (bad_point);
00807 }
00808 else
00809 {
00810 cloud->points (depth_idx, 3) = depth_map[depth_idx] * 0.001f;
00811 cloud->points (depth_idx, 1) = static_cast<float> (u) * cloud->points (depth_idx, 3) * constant;
00812 cloud->points (depth_idx, 2) = static_cast<float> (v) * cloud->points (depth_idx, 3) * constant;
00813 }
00814
00815
00816 color.Red = rgb_buffer[color_idx];
00817 color.Green = rgb_buffer[color_idx + 1];
00818 color.Blue = rgb_buffer[color_idx + 2];
00819 cloud->points (depth_idx, 0) = color.float_value;
00820 }
00821 }
00822 return (cloud);
00823 }
00824
00826 pcl::PointCloud<pcl::PointXYZI>::Ptr
00827 pcl::OpenNIGrabber::convertToXYZIPointCloud (const boost::shared_ptr<openni_wrapper::IRImage> &ir_image,
00828 const boost::shared_ptr<openni_wrapper::DepthImage> &depth_image) const
00829 {
00830 boost::shared_ptr<pcl::PointCloud<pcl::PointXYZI> > cloud (new pcl::PointCloud<pcl::PointXYZI > ());
00831
00832 cloud->header.frame_id = rgb_frame_id_;
00833 cloud->height = depth_height_;
00834 cloud->width = depth_width_;
00835 cloud->is_dense = false;
00836
00837 cloud->points.resize (cloud->height * cloud->width);
00838
00839 float constant = 1.0f / device_->getImageFocalLength (cloud->width);
00840 register int centerX = (cloud->width >> 1);
00841 int centerY = (cloud->height >> 1);
00842
00843 register const XnDepthPixel* depth_map = depth_image->getDepthMetaData ().Data ();
00844 register const XnIRPixel* ir_map = ir_image->getMetaData ().Data ();
00845
00846 if (depth_image->getWidth () != depth_width_ || depth_image->getHeight () != depth_height_)
00847 {
00848 static unsigned buffer_size = 0;
00849 static boost::shared_array<unsigned short> depth_buffer (0);
00850 static boost::shared_array<unsigned short> ir_buffer (0);
00851
00852 if (buffer_size < depth_width_ * depth_height_)
00853 {
00854 buffer_size = depth_width_ * depth_height_;
00855 depth_buffer.reset (new unsigned short [buffer_size]);
00856 ir_buffer.reset (new unsigned short [buffer_size]);
00857 }
00858
00859 depth_image->fillDepthImageRaw (depth_width_, depth_height_, depth_buffer.get ());
00860 depth_map = depth_buffer.get ();
00861
00862 ir_image->fillRaw (depth_width_, depth_height_, ir_buffer.get ());
00863 ir_map = ir_buffer.get ();
00864 }
00865
00866 register int depth_idx = 0;
00867 float bad_point = std::numeric_limits<float>::quiet_NaN ();
00868
00869 for (int v = -centerY; v < centerY; ++v)
00870 {
00871 for (register int u = -centerX; u < centerX; ++u, ++depth_idx)
00872 {
00873 pcl::PointXYZI& pt = cloud->points[depth_idx];
00875
00876 if (depth_map[depth_idx] == 0 ||
00877 depth_map[depth_idx] == depth_image->getNoSampleValue () ||
00878 depth_map[depth_idx] == depth_image->getShadowValue ())
00879 {
00880 pt.x = pt.y = pt.z = bad_point;
00881 }
00882 else
00883 {
00884 pt.z = depth_map[depth_idx] * 0.001f;
00885 pt.x = static_cast<float> (u) * pt.z * constant;
00886 pt.y = static_cast<float> (v) * pt.z * constant;
00887 }
00888
00889 pt.data_c[0] = pt.data_c[1] = pt.data_c[2] = pt.data_c[3] = 0;
00890 pt.intensity = static_cast<float> (ir_map[depth_idx]);
00891 }
00892 }
00893 return (cloud);
00894 }
00895
00897
00898 void
00899 pcl::OpenNIGrabber::updateModeMaps ()
00900 {
00901 XnMapOutputMode output_mode;
00902
00903 output_mode.nXRes = XN_SXGA_X_RES;
00904 output_mode.nYRes = XN_SXGA_Y_RES;
00905 output_mode.nFPS = 15;
00906 config2xn_map_[OpenNI_SXGA_15Hz] = output_mode;
00907
00908 output_mode.nXRes = XN_VGA_X_RES;
00909 output_mode.nYRes = XN_VGA_Y_RES;
00910 output_mode.nFPS = 25;
00911 config2xn_map_[OpenNI_VGA_25Hz] = output_mode;
00912 output_mode.nFPS = 30;
00913 config2xn_map_[OpenNI_VGA_30Hz] = output_mode;
00914
00915 output_mode.nXRes = XN_QVGA_X_RES;
00916 output_mode.nYRes = XN_QVGA_Y_RES;
00917 output_mode.nFPS = 25;
00918 config2xn_map_[OpenNI_QVGA_25Hz] = output_mode;
00919 output_mode.nFPS = 30;
00920 config2xn_map_[OpenNI_QVGA_30Hz] = output_mode;
00921 output_mode.nFPS = 60;
00922 config2xn_map_[OpenNI_QVGA_60Hz] = output_mode;
00923
00924 output_mode.nXRes = XN_QQVGA_X_RES;
00925 output_mode.nYRes = XN_QQVGA_Y_RES;
00926 output_mode.nFPS = 25;
00927 config2xn_map_[OpenNI_QQVGA_25Hz] = output_mode;
00928 output_mode.nFPS = 30;
00929 config2xn_map_[OpenNI_QQVGA_30Hz] = output_mode;
00930 output_mode.nFPS = 60;
00931 config2xn_map_[OpenNI_QQVGA_60Hz] = output_mode;
00932 }
00933
00935 bool
00936 pcl::OpenNIGrabber::mapConfigMode2XnMode (int mode, XnMapOutputMode &xnmode) const
00937 {
00938 std::map<int, XnMapOutputMode>::const_iterator it = config2xn_map_.find (mode);
00939 if (it != config2xn_map_.end ())
00940 {
00941 xnmode = it->second;
00942 return (true);
00943 }
00944 else
00945 {
00946 return (false);
00947 }
00948 }
00949
00951 std::vector<std::pair<int, XnMapOutputMode> >
00952 pcl::OpenNIGrabber::getAvailableDepthModes () const
00953 {
00954 XnMapOutputMode dummy;
00955 std::vector<std::pair<int, XnMapOutputMode> > result;
00956 for (std::map<int, XnMapOutputMode>::const_iterator it = config2xn_map_.begin (); it != config2xn_map_.end (); ++it)
00957 {
00958 if (device_->findCompatibleDepthMode (it->second, dummy))
00959 result.push_back (*it);
00960 }
00961
00962 return (result);
00963 }
00964
00966 std::vector<std::pair<int, XnMapOutputMode> >
00967 pcl::OpenNIGrabber::getAvailableImageModes () const
00968 {
00969 XnMapOutputMode dummy;
00970 std::vector<std::pair<int, XnMapOutputMode> > result;
00971 for (std::map<int, XnMapOutputMode>::const_iterator it = config2xn_map_.begin (); it != config2xn_map_.end (); ++it)
00972 {
00973 if (device_->findCompatibleImageMode (it->second, dummy))
00974 result.push_back (*it);
00975 }
00976
00977 return (result);
00978 }
00979
00981 float
00982 pcl::OpenNIGrabber::getFramesPerSecond () const
00983 {
00984 return (static_cast<float> (device_->getDepthOutputMode ().nFPS));
00985 }
00986
00987 #endif