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 #include <pcl/pcl_config.h>
00038 #ifdef HAVE_OPENNI
00039
00040 #include <pcl/io/openni_camera/openni_driver.h>
00041 #include <pcl/io/openni_camera/openni_device.h>
00042 #include <pcl/io/openni_camera/openni_depth_image.h>
00043 #include <pcl/io/openni_camera/openni_ir_image.h>
00044 #include <iostream>
00045 #include <limits>
00046 #include <sstream>
00047 #include <map>
00048 #include <vector>
00049 #include "XnVersion.h"
00050
00051 using namespace std;
00052 using namespace boost;
00053
00055 openni_wrapper::OpenNIDevice::OpenNIDevice (
00056 xn::Context& context,
00057 const xn::NodeInfo& device_node,
00058 const xn::NodeInfo& image_node,
00059 const xn::NodeInfo& depth_node,
00060 const xn::NodeInfo& ir_node)
00061 : image_callback_ (),
00062 depth_callback_ (),
00063 ir_callback_ (),
00064 available_image_modes_ (),
00065 available_depth_modes_ (),
00066 context_ (context),
00067 device_node_info_ (device_node),
00068 depth_generator_ (),
00069 image_generator_ (),
00070 ir_generator_ (),
00071 depth_callback_handle_ (),
00072 image_callback_handle_ (),
00073 ir_callback_handle_ (),
00074 depth_focal_length_SXGA_ (),
00075 baseline_ (),
00076
00077 rgb_focal_length_SXGA_ (1050),
00078 shadow_value_ (),
00079 no_sample_value_ (),
00080 image_callback_handle_counter_ (),
00081 depth_callback_handle_counter_ (),
00082 ir_callback_handle_counter_ (),
00083 quit_ (),
00084 image_mutex_ (), depth_mutex_ (), ir_mutex_ (),
00085 image_condition_ (), depth_condition_ (), ir_condition_ (),
00086 image_thread_ (), depth_thread_ (), ir_thread_ ()
00087 {
00088
00089 #ifdef __APPLE__
00090 XnStatus rc;
00091
00092 xn::EnumerationErrors errors;
00093 rc = context_.InitFromXmlFile ("/etc/openni/SamplesConfig.xml", &errors);
00094 if (rc == XN_STATUS_NO_NODE_PRESENT)
00095 {
00096 XnChar strError[1024];
00097 errors.ToString(strError, 1024);
00098 printf ("%s\n", strError);
00099 }
00100 else if (rc != XN_STATUS_OK)
00101 {
00102 printf ("Open failed: %s\n", xnGetStatusString(rc));
00103 }
00104
00105 XnStatus status = context_.FindExistingNode(XN_NODE_TYPE_DEPTH, depth_generator_);
00106 if (status != XN_STATUS_OK)
00107 cerr << "node depth problems" << endl;
00108 status = context_.FindExistingNode(XN_NODE_TYPE_IMAGE, image_generator_);
00109 if (status != XN_STATUS_OK)
00110 cerr << "node image problems" << endl;
00111 status = context_.FindExistingNode(XN_NODE_TYPE_IR, ir_generator_);
00112 if (status != XN_STATUS_OK)
00113 cerr << "node ir problems" << endl;
00114
00115 #else
00116
00117 #if (XN_MINOR_VERSION >= 3)
00118
00119 XnStatus status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(depth_node), depth_generator_);
00120 if (status != XN_STATUS_OK)
00121 THROW_OPENNI_EXCEPTION ("creating depth generator failed. Reason: %s", xnGetStatusString (status));
00122
00123 status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(image_node), image_generator_);
00124 if (status != XN_STATUS_OK)
00125 THROW_OPENNI_EXCEPTION ("creating image generator failed. Reason: %s", xnGetStatusString (status));
00126
00127 status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(ir_node), ir_generator_);
00128 if (status != XN_STATUS_OK)
00129 THROW_OPENNI_EXCEPTION ("creating IR generator failed. Reason: %s", xnGetStatusString (status));
00130 #else
00131 XnStatus status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(depth_node));
00132 if (status != XN_STATUS_OK)
00133 THROW_OPENNI_EXCEPTION ("creating depth generator failed. Reason: %s", xnGetStatusString (status));
00134
00135 status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(image_node));
00136 if (status != XN_STATUS_OK)
00137 THROW_OPENNI_EXCEPTION ("creating image generator failed. Reason: %s", xnGetStatusString (status));
00138
00139 status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(ir_node));
00140 if (status != XN_STATUS_OK)
00141 THROW_OPENNI_EXCEPTION ("creating IR generator failed. Reason: %s", xnGetStatusString (status));
00142
00143
00144 status = depth_node.GetInstance (depth_generator_);
00145 if (status != XN_STATUS_OK)
00146 THROW_OPENNI_EXCEPTION ("creating depth generator instance failed. Reason: %s", xnGetStatusString (status));
00147
00148 status = image_node.GetInstance (image_generator_);
00149 if (status != XN_STATUS_OK)
00150 THROW_OPENNI_EXCEPTION ("creating image generator instance failed. Reason: %s", xnGetStatusString (status));
00151
00152 status = ir_node.GetInstance (ir_generator_);
00153 if (status != XN_STATUS_OK)
00154 THROW_OPENNI_EXCEPTION ("creating IR generator instance failed. Reason: %s", xnGetStatusString (status));
00155 #endif // (XN_MINOR_VERSION >= 3)
00156 ir_generator_.RegisterToNewDataAvailable (static_cast<xn::StateChangedHandler> (NewIRDataAvailable), this, ir_callback_handle_);
00157 #endif // __APPLE__
00158
00159 depth_generator_.RegisterToNewDataAvailable (static_cast<xn::StateChangedHandler> (NewDepthDataAvailable), this, depth_callback_handle_);
00160 image_generator_.RegisterToNewDataAvailable (static_cast<xn::StateChangedHandler> (NewImageDataAvailable), this, image_callback_handle_);
00161
00162 Init ();
00163 }
00164
00166 openni_wrapper::OpenNIDevice::OpenNIDevice (xn::Context& context, const xn::NodeInfo& device_node, const xn::NodeInfo& depth_node, const xn::NodeInfo& ir_node)
00167 : image_callback_ (),
00168 depth_callback_ (),
00169 ir_callback_ (),
00170 available_image_modes_ (),
00171 available_depth_modes_ (),
00172 context_ (context),
00173 device_node_info_ (device_node),
00174 depth_generator_ (),
00175 image_generator_ (),
00176 ir_generator_ (),
00177 depth_callback_handle_ (),
00178 image_callback_handle_ (),
00179 ir_callback_handle_ (),
00180 depth_focal_length_SXGA_ (),
00181 baseline_ (),
00182
00183 rgb_focal_length_SXGA_ (1050),
00184 shadow_value_ (),
00185 no_sample_value_ (),
00186 image_callback_handle_counter_ (),
00187 depth_callback_handle_counter_ (),
00188 ir_callback_handle_counter_ (),
00189 quit_ (),
00190 image_mutex_ (), depth_mutex_ (), ir_mutex_ (),
00191 image_condition_ (), depth_condition_ (), ir_condition_ (),
00192 image_thread_ (), depth_thread_ (), ir_thread_ ()
00193 {
00194
00195 #ifdef __APPLE__
00196 cerr << "Creating OpenNIDevice" << endl;
00197 XnStatus rc;
00198
00199 xn::EnumerationErrors errors;
00200 rc = context_.InitFromXmlFile("/etc/primesense/SamplesConfig.xml", &errors);
00201 if (rc == XN_STATUS_NO_NODE_PRESENT)
00202 {
00203 XnChar strError[1024];
00204 errors.ToString(strError, 1024);
00205 printf("%s\n", strError);
00206 }
00207 else if (rc != XN_STATUS_OK)
00208 {
00209 printf("Open failed: %s\n", xnGetStatusString(rc));
00210 }
00211
00212 XnStatus status = context_.FindExistingNode(XN_NODE_TYPE_DEPTH, depth_generator_);
00213 if (status != XN_STATUS_OK)
00214 cerr << "node depth problems" << endl;
00215 status = context_.FindExistingNode(XN_NODE_TYPE_IR, ir_generator_);
00216 if (status != XN_STATUS_OK)
00217 cerr << "node ir problems" << endl;
00218
00219 #else
00220 XnStatus status;
00221 #if (XN_MINOR_VERSION >=3)
00222
00223 status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(depth_node), depth_generator_);
00224 if (status != XN_STATUS_OK)
00225 THROW_OPENNI_EXCEPTION ("creating depth generator failed. Reason: %s", xnGetStatusString (status));
00226
00227 status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(ir_node), ir_generator_);
00228 if (status != XN_STATUS_OK)
00229 THROW_OPENNI_EXCEPTION ("creating IR generator failed. Reason: %s", xnGetStatusString (status));
00230 #else
00231 status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(depth_node));
00232 if (status != XN_STATUS_OK)
00233 THROW_OPENNI_EXCEPTION ("creating depth generator failed. Reason: %s", xnGetStatusString (status));
00234
00235 status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(ir_node));
00236 if (status != XN_STATUS_OK)
00237 THROW_OPENNI_EXCEPTION ("creating IR generator failed. Reason: %s", xnGetStatusString (status));
00238
00239 status = depth_node.GetInstance (depth_generator_);
00240 if (status != XN_STATUS_OK)
00241 THROW_OPENNI_EXCEPTION ("creating depth generator instance failed. Reason: %s", xnGetStatusString (status));
00242
00243 status = ir_node.GetInstance (ir_generator_);
00244 if (status != XN_STATUS_OK)
00245 THROW_OPENNI_EXCEPTION ("creating IR generator instance failed. Reason: %s", xnGetStatusString (status));
00246 #endif // (XN_MINOR_VERSION >= 3)
00247 ir_generator_.RegisterToNewDataAvailable (static_cast<xn::StateChangedHandler> (NewIRDataAvailable), this, ir_callback_handle_);
00248 #endif // __APPLE__
00249
00250 depth_generator_.RegisterToNewDataAvailable (static_cast <xn::StateChangedHandler> (NewDepthDataAvailable), this, depth_callback_handle_);
00251
00252 Init ();
00253 }
00254
00256
00257 openni_wrapper::OpenNIDevice::OpenNIDevice (xn::Context& context)
00258 : image_callback_ (),
00259 depth_callback_ (),
00260 ir_callback_ (),
00261 available_image_modes_ (),
00262 available_depth_modes_ (),
00263 context_ (context),
00264 device_node_info_ (0),
00265 depth_generator_ (),
00266 image_generator_ (),
00267 ir_generator_ (),
00268 depth_callback_handle_ (),
00269 image_callback_handle_ (),
00270 ir_callback_handle_ (),
00271 depth_focal_length_SXGA_ (),
00272 baseline_ (),
00273
00274 rgb_focal_length_SXGA_ (1050),
00275 shadow_value_ (),
00276 no_sample_value_ (),
00277 image_callback_handle_counter_ (),
00278 depth_callback_handle_counter_ (),
00279 ir_callback_handle_counter_ (),
00280 quit_ (),
00281 image_mutex_ (), depth_mutex_ (), ir_mutex_ (),
00282 image_condition_ (), depth_condition_ (), ir_condition_ (),
00283 image_thread_ (), depth_thread_ (), ir_thread_ ()
00284 {
00285 }
00286
00288 openni_wrapper::OpenNIDevice::~OpenNIDevice () throw ()
00289 {
00290
00291 if (image_generator_.IsValid() && image_generator_.IsGenerating ())
00292 image_generator_.StopGenerating ();
00293
00294 if (depth_generator_.IsValid () && depth_generator_.IsGenerating ())
00295 depth_generator_.StopGenerating ();
00296
00297 if (ir_generator_.IsValid () && ir_generator_.IsGenerating ())
00298 ir_generator_.StopGenerating ();
00299
00300
00301 image_mutex_.lock ();
00302 depth_mutex_.lock ();
00303 ir_mutex_.lock ();
00304 quit_ = true;
00305
00306 depth_condition_.notify_all ();
00307 image_condition_.notify_all ();
00308 ir_condition_.notify_all ();
00309 ir_mutex_.unlock ();
00310 depth_mutex_.unlock ();
00311 image_mutex_.unlock ();
00312
00313 xn::Device deviceNode;
00314 device_node_info_.GetInstance(deviceNode);
00315 if (deviceNode.IsValid())
00316 deviceNode.Release ();
00317
00318 if (hasImageStream ())
00319 {
00320 image_thread_.join ();
00321 image_generator_.Release ();
00322 }
00323
00324 if (hasDepthStream ())
00325 {
00326 depth_thread_.join ();
00327 depth_generator_.Release ();
00328 }
00329
00330 if (hasIRStream ())
00331 {
00332 ir_thread_.join ();
00333 ir_generator_.Release ();
00334 }
00335 }
00336
00338 void
00339 openni_wrapper::OpenNIDevice::Init ()
00340 {
00341 quit_ = false;
00342 XnDouble pixel_size;
00343
00344
00345 if (hasDepthStream ())
00346 {
00347 unique_lock<mutex> depth_lock (depth_mutex_);
00348 XnStatus status = depth_generator_.GetRealProperty ("ZPPS", pixel_size);
00349 if (status != XN_STATUS_OK)
00350 THROW_OPENNI_EXCEPTION ("reading the pixel size of IR camera failed. Reason: %s", xnGetStatusString (status));
00351
00352 XnUInt64 depth_focal_length_SXGA;
00353 status = depth_generator_.GetIntProperty ("ZPD", depth_focal_length_SXGA);
00354 if (status != XN_STATUS_OK)
00355 THROW_OPENNI_EXCEPTION ("reading the focal length of IR camera failed. Reason: %s", xnGetStatusString (status));
00356
00357 XnDouble baseline;
00358 status = depth_generator_.GetRealProperty ("LDDIS", baseline);
00359 if (status != XN_STATUS_OK)
00360 THROW_OPENNI_EXCEPTION ("reading the baseline failed. Reason: %s", xnGetStatusString (status));
00361
00362 status = depth_generator_.GetIntProperty ("ShadowValue", shadow_value_);
00363 if (status != XN_STATUS_OK)
00364 THROW_OPENNI_EXCEPTION ("reading the value for pixels in shadow regions failed. Reason: %s", xnGetStatusString (status));
00365
00366 status = depth_generator_.GetIntProperty ("NoSampleValue", no_sample_value_);
00367 if (status != XN_STATUS_OK)
00368 THROW_OPENNI_EXCEPTION ("reading the value for pixels with no depth estimation failed. Reason: %s", xnGetStatusString (status));
00369
00370
00371 baseline_ = static_cast<float> (baseline * 0.01);
00372
00373
00374 depth_focal_length_SXGA_ = static_cast<float> (static_cast<XnDouble> (depth_focal_length_SXGA) / pixel_size);
00375
00376 depth_thread_ = boost::thread (&OpenNIDevice::DepthDataThreadFunction, this);
00377 }
00378
00379 if (hasImageStream ())
00380 {
00381 lock_guard<mutex> image_lock (image_mutex_);
00382 image_thread_ = boost::thread (&OpenNIDevice::ImageDataThreadFunction, this);
00383 }
00384
00385 if (hasIRStream ())
00386 {
00387 lock_guard<mutex> ir_lock (ir_mutex_);
00388 ir_thread_ = boost::thread (&OpenNIDevice::IRDataThreadFunction, this);
00389 }
00390 }
00391
00393 void
00394 openni_wrapper::OpenNIDevice::startImageStream ()
00395 {
00396 if (hasImageStream ())
00397 {
00398 lock_guard<mutex> image_lock (image_mutex_);
00399 if (!image_generator_.IsGenerating ())
00400 {
00401 XnStatus status = image_generator_.StartGenerating ();
00402 if (status != XN_STATUS_OK)
00403 THROW_OPENNI_EXCEPTION ("starting image stream failed. Reason: %s", xnGetStatusString (status));
00404 }
00405 }
00406 else
00407 THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
00408 }
00409
00411 void
00412 openni_wrapper::OpenNIDevice::stopImageStream ()
00413 {
00414 if (hasImageStream ())
00415 {
00416 lock_guard<mutex> image_lock (image_mutex_);
00417 if (image_generator_.IsGenerating ())
00418 {
00419 XnStatus status = image_generator_.StopGenerating ();
00420 if (status != XN_STATUS_OK)
00421 THROW_OPENNI_EXCEPTION ("stopping image stream failed. Reason: %s", xnGetStatusString (status));
00422 }
00423 }
00424 else
00425 THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
00426 }
00427
00429 void
00430 openni_wrapper::OpenNIDevice::startDepthStream ()
00431 {
00432 if (hasDepthStream ())
00433 {
00434 lock_guard<mutex> depth_lock (depth_mutex_);
00435 if (!depth_generator_.IsGenerating ())
00436 {
00437 XnStatus status = depth_generator_.StartGenerating ();
00438
00439 if (status != XN_STATUS_OK)
00440 THROW_OPENNI_EXCEPTION ("starting depth stream failed. Reason: %s", xnGetStatusString (status));
00441 }
00442 }
00443 else
00444 THROW_OPENNI_EXCEPTION ("Device does not provide a depth stream");
00445 }
00446
00448 void
00449 openni_wrapper::OpenNIDevice::stopDepthStream ()
00450 {
00451 if (hasDepthStream ())
00452 {
00453 lock_guard<mutex> depth_lock (depth_mutex_);
00454 if (depth_generator_.IsGenerating ())
00455 {
00456 XnStatus status = depth_generator_.StopGenerating ();
00457
00458 if (status != XN_STATUS_OK)
00459 THROW_OPENNI_EXCEPTION ("stopping depth stream failed. Reason: %s", xnGetStatusString (status));
00460 }
00461 }
00462 else
00463 THROW_OPENNI_EXCEPTION ("Device does not provide a depth stream");
00464 }
00465
00467 void
00468 openni_wrapper::OpenNIDevice::startIRStream ()
00469 {
00470 if (hasIRStream ())
00471 {
00472 lock_guard<mutex> ir_lock (ir_mutex_);
00473 if (!ir_generator_.IsGenerating ())
00474 {
00475 XnStatus status = ir_generator_.StartGenerating ();
00476
00477 if (status != XN_STATUS_OK)
00478 THROW_OPENNI_EXCEPTION ("starting IR stream failed. Reason: %s", xnGetStatusString (status));
00479 }
00480 }
00481 #ifndef __APPLE__
00482 else
00483 THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
00484 #endif
00485 }
00486
00488 void
00489 openni_wrapper::OpenNIDevice::stopIRStream ()
00490 {
00491 if (hasIRStream ())
00492 {
00493 lock_guard<mutex> ir_lock (ir_mutex_);
00494 if (ir_generator_.IsGenerating ())
00495 {
00496 XnStatus status = ir_generator_.StopGenerating ();
00497
00498 if (status != XN_STATUS_OK)
00499 THROW_OPENNI_EXCEPTION ("stopping IR stream failed. Reason: %s", xnGetStatusString (status));
00500 }
00501 }
00502 else
00503 THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
00504 }
00505
00507 bool
00508 openni_wrapper::OpenNIDevice::isImageStreamRunning () const throw ()
00509 {
00510 lock_guard<mutex> image_lock (image_mutex_);
00511 return (image_generator_.IsValid () && image_generator_.IsGenerating ());
00512 }
00513
00515 bool
00516 openni_wrapper::OpenNIDevice::isDepthStreamRunning () const throw ()
00517 {
00518 lock_guard<mutex> depth_lock (depth_mutex_);
00519 return (depth_generator_.IsValid () && depth_generator_.IsGenerating ());
00520 }
00521
00523 bool
00524 openni_wrapper::OpenNIDevice::isIRStreamRunning () const throw ()
00525 {
00526 lock_guard<mutex> ir_lock (ir_mutex_);
00527 return (ir_generator_.IsValid () && ir_generator_.IsGenerating ());
00528 }
00529
00531 bool
00532 openni_wrapper::OpenNIDevice::hasImageStream () const throw ()
00533 {
00534 lock_guard<mutex> lock (image_mutex_);
00535 return (image_generator_.IsValid () != 0);
00536
00537 }
00538
00540 bool
00541 openni_wrapper::OpenNIDevice::hasDepthStream () const throw ()
00542 {
00543 lock_guard<mutex> lock (depth_mutex_);
00544 return (depth_generator_.IsValid () != 0);
00545
00546 }
00547
00549 bool
00550 openni_wrapper::OpenNIDevice::hasIRStream () const throw ()
00551 {
00552 lock_guard<mutex> ir_lock (ir_mutex_);
00553 return (ir_generator_.IsValid () != 0);
00554 }
00555
00557 void
00558 openni_wrapper::OpenNIDevice::setDepthRegistration (bool on_off)
00559 {
00560 if (hasDepthStream () && hasImageStream())
00561 {
00562 lock_guard<mutex> image_lock (image_mutex_);
00563 lock_guard<mutex> depth_lock (depth_mutex_);
00564 if (on_off && !depth_generator_.GetAlternativeViewPointCap ().IsViewPointAs (image_generator_))
00565 {
00566 if (depth_generator_.GetAlternativeViewPointCap ().IsViewPointSupported (image_generator_))
00567 {
00568 XnStatus status = depth_generator_.GetAlternativeViewPointCap ().SetViewPoint (image_generator_);
00569 if (status != XN_STATUS_OK)
00570 THROW_OPENNI_EXCEPTION ("turning registration on failed. Reason: %s", xnGetStatusString (status));
00571 }
00572 else
00573 THROW_OPENNI_EXCEPTION ("turning registration on failed. Reason: unsopported viewpoint");
00574 }
00575 else if (!on_off)
00576 {
00577 XnStatus status = depth_generator_.GetAlternativeViewPointCap ().ResetViewPoint ();
00578
00579 if (status != XN_STATUS_OK)
00580 THROW_OPENNI_EXCEPTION ("turning registration off failed. Reason: %s", xnGetStatusString (status));
00581 }
00582 }
00583 else
00584 THROW_OPENNI_EXCEPTION ("Device does not provide image + depth stream");
00585 }
00586
00588 bool
00589 openni_wrapper::OpenNIDevice::isDepthRegistered () const throw ()
00590 {
00591 if (hasDepthStream () && hasImageStream() )
00592 {
00593 xn::DepthGenerator& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
00594 xn::ImageGenerator& image_generator = const_cast<xn::ImageGenerator&>(image_generator_);
00595
00596 lock_guard<mutex> image_lock (image_mutex_);
00597 lock_guard<mutex> depth_lock (depth_mutex_);
00598 return (depth_generator.GetAlternativeViewPointCap ().IsViewPointAs (image_generator) != 0);
00599 }
00600 return (false);
00601 }
00602
00604 bool
00605 openni_wrapper::OpenNIDevice::isDepthRegistrationSupported () const throw ()
00606 {
00607 lock_guard<mutex> image_lock (image_mutex_);
00608 lock_guard<mutex> depth_lock (depth_mutex_);
00609 xn::ImageGenerator& image_generator = const_cast<xn::ImageGenerator&> (image_generator_);
00610 return (depth_generator_.IsValid() && image_generator_.IsValid() && depth_generator_.GetAlternativeViewPointCap().IsViewPointSupported(image_generator));
00611 }
00612
00614 bool
00615 openni_wrapper::OpenNIDevice::isSynchronizationSupported () const throw ()
00616 {
00617 lock_guard<mutex> image_lock (image_mutex_);
00618 lock_guard<mutex> depth_lock (depth_mutex_);
00619 return (depth_generator_.IsValid() && image_generator_.IsValid() && depth_generator_.IsCapabilitySupported (XN_CAPABILITY_FRAME_SYNC));
00620 }
00621
00623 void
00624 openni_wrapper::OpenNIDevice::setSynchronization (bool on_off)
00625 {
00626 if (hasDepthStream () && hasImageStream())
00627 {
00628 lock_guard<mutex> image_lock (image_mutex_);
00629 lock_guard<mutex> depth_lock (depth_mutex_);
00630 XnStatus status;
00631
00632 if (on_off && !depth_generator_.GetFrameSyncCap ().IsFrameSyncedWith (image_generator_))
00633 {
00634 status = depth_generator_.GetFrameSyncCap ().FrameSyncWith (image_generator_);
00635 if (status != XN_STATUS_OK)
00636 THROW_OPENNI_EXCEPTION ("could not turn on frame synchronization. Reason: %s", xnGetStatusString (status));
00637 }
00638 else if (!on_off && depth_generator_.GetFrameSyncCap ().IsFrameSyncedWith (image_generator_))
00639 {
00640 status = depth_generator_.GetFrameSyncCap ().StopFrameSyncWith (image_generator_);
00641 if (status != XN_STATUS_OK)
00642 THROW_OPENNI_EXCEPTION ("could not turn off frame synchronization. Reason: %s", xnGetStatusString (status));
00643 }
00644 }
00645 else
00646 THROW_OPENNI_EXCEPTION ("Device does not provide image + depth stream");
00647 }
00648
00650 bool
00651 openni_wrapper::OpenNIDevice::isSynchronized () const throw ()
00652 {
00653 if (hasDepthStream () && hasImageStream())
00654 {
00655 lock_guard<mutex> image_lock (image_mutex_);
00656 lock_guard<mutex> depth_lock (depth_mutex_);
00657 xn::DepthGenerator& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
00658 xn::ImageGenerator& image_generator = const_cast<xn::ImageGenerator&>(image_generator_);
00659 return (depth_generator.GetFrameSyncCap ().CanFrameSyncWith (image_generator) && depth_generator.GetFrameSyncCap ().IsFrameSyncedWith (image_generator));
00660 }
00661 else
00662 return (false);
00663 }
00664
00666 bool
00667 openni_wrapper::OpenNIDevice::isDepthCroppingSupported () const throw ()
00668 {
00669 lock_guard<mutex> depth_lock (depth_mutex_);
00670 return (image_generator_.IsValid() && depth_generator_.IsCapabilitySupported (XN_CAPABILITY_CROPPING) );
00671 }
00672
00674 bool
00675 openni_wrapper::OpenNIDevice::isDepthCropped () const
00676 {
00677 if (hasDepthStream ())
00678 {
00679 lock_guard<mutex> depth_lock (depth_mutex_);
00680 XnCropping cropping;
00681 xn::DepthGenerator& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
00682 XnStatus status = depth_generator.GetCroppingCap ().GetCropping (cropping);
00683 if (status != XN_STATUS_OK)
00684 THROW_OPENNI_EXCEPTION ("could not read cropping information for depth stream. Reason: %s", xnGetStatusString (status));
00685
00686 return (cropping.bEnabled != 0);
00687 }
00688 return (false);
00689 }
00690
00692 void
00693 openni_wrapper::OpenNIDevice::setDepthCropping (unsigned x, unsigned y, unsigned width, unsigned height)
00694 {
00695 if (hasDepthStream ())
00696 {
00697 lock_guard<mutex> depth_lock (depth_mutex_);
00698 XnCropping cropping;
00699 cropping.nXOffset = static_cast<XnUInt16> (x);
00700 cropping.nYOffset = static_cast<XnUInt16> (y);
00701 cropping.nXSize = static_cast<XnUInt16> (width);
00702 cropping.nYSize = static_cast<XnUInt16> (height);
00703
00704 cropping.bEnabled = (width != 0 && height != 0);
00705 XnStatus status = depth_generator_.GetCroppingCap ().SetCropping (cropping);
00706 if (status != XN_STATUS_OK)
00707 THROW_OPENNI_EXCEPTION ("could not set cropping information for depth stream. Reason: %s", xnGetStatusString (status));
00708 }
00709 else
00710 THROW_OPENNI_EXCEPTION ("Device does not provide depth stream");
00711 }
00712
00714 void
00715 openni_wrapper::OpenNIDevice::ImageDataThreadFunction ()
00716 {
00717 while (true)
00718 {
00719
00720 unique_lock<mutex> image_lock (image_mutex_);
00721 if (quit_)
00722 return;
00723 image_condition_.wait (image_lock);
00724 if (quit_)
00725 return;
00726
00727 image_generator_.WaitAndUpdateData ();
00728
00729 boost::shared_ptr<xn::ImageMetaData> image_data (new xn::ImageMetaData);
00730 image_generator_.GetMetaData (*image_data);
00731 image_lock.unlock ();
00732
00733 boost::shared_ptr<Image> image = getCurrentImage (image_data);
00734 for (map< OpenNIDevice::CallbackHandle, ActualImageCallbackFunction >::iterator callbackIt = image_callback_.begin (); callbackIt != image_callback_.end (); ++callbackIt)
00735 {
00736 callbackIt->second.operator()(image);
00737 }
00738 }
00739 }
00740
00742 void
00743 openni_wrapper::OpenNIDevice::DepthDataThreadFunction ()
00744 {
00745 while (true)
00746 {
00747
00748 unique_lock<mutex> depth_lock (depth_mutex_);
00749 if (quit_)
00750 return;
00751 depth_condition_.wait (depth_lock);
00752 if (quit_)
00753 return;
00754
00755 depth_generator_.WaitAndUpdateData ();
00756 boost::shared_ptr<xn::DepthMetaData> depth_data (new xn::DepthMetaData);
00757 depth_generator_.GetMetaData (*depth_data);
00758 depth_lock.unlock ();
00759
00760 boost::shared_ptr<DepthImage> depth_image ( new DepthImage (depth_data, baseline_, getDepthFocalLength (), shadow_value_, no_sample_value_) );
00761
00762 for (map< OpenNIDevice::CallbackHandle, ActualDepthImageCallbackFunction >::iterator callbackIt = depth_callback_.begin ();
00763 callbackIt != depth_callback_.end (); ++callbackIt)
00764 {
00765 callbackIt->second.operator()(depth_image);
00766 }
00767 }
00768 }
00769
00771 void
00772 openni_wrapper::OpenNIDevice::IRDataThreadFunction ()
00773 {
00774 while (true)
00775 {
00776
00777 unique_lock<mutex> ir_lock (ir_mutex_);
00778 if (quit_)
00779 return;
00780 ir_condition_.wait (ir_lock);
00781 if (quit_)
00782 return;
00783
00784 ir_generator_.WaitAndUpdateData ();
00785 boost::shared_ptr<xn::IRMetaData> ir_data (new xn::IRMetaData);
00786 ir_generator_.GetMetaData (*ir_data);
00787 ir_lock.unlock ();
00788
00789 boost::shared_ptr<IRImage> ir_image ( new IRImage (ir_data) );
00790
00791 for (map< OpenNIDevice::CallbackHandle, ActualIRImageCallbackFunction >::iterator callbackIt = ir_callback_.begin ();
00792 callbackIt != ir_callback_.end (); ++callbackIt)
00793 {
00794 callbackIt->second.operator()(ir_image);
00795 }
00796 }
00797 }
00798
00800 void __stdcall
00801 openni_wrapper::OpenNIDevice::NewDepthDataAvailable (xn::ProductionNode&, void* cookie) throw ()
00802 {
00803 OpenNIDevice* device = reinterpret_cast<OpenNIDevice*>(cookie);
00804 device->depth_condition_.notify_all ();
00805 }
00806
00808 void __stdcall
00809 openni_wrapper::OpenNIDevice::NewImageDataAvailable (xn::ProductionNode&, void* cookie) throw ()
00810 {
00811 OpenNIDevice* device = reinterpret_cast<OpenNIDevice*>(cookie);
00812 device->image_condition_.notify_all ();
00813 }
00814
00816 void __stdcall
00817 openni_wrapper::OpenNIDevice::NewIRDataAvailable (xn::ProductionNode&, void* cookie) throw ()
00818 {
00819 OpenNIDevice* device = reinterpret_cast<OpenNIDevice*>(cookie);
00820 device->ir_condition_.notify_all ();
00821 }
00822
00824 openni_wrapper::OpenNIDevice::CallbackHandle
00825 openni_wrapper::OpenNIDevice::registerImageCallback (const ImageCallbackFunction& callback, void* custom_data) throw ()
00826 {
00827 image_callback_[image_callback_handle_counter_] = boost::bind (callback, _1, custom_data);
00828 return (image_callback_handle_counter_++);
00829 }
00830
00832 bool
00833 openni_wrapper::OpenNIDevice::unregisterImageCallback (const OpenNIDevice::CallbackHandle& callbackHandle) throw ()
00834 {
00835 return (image_callback_.erase (callbackHandle) != 0);
00836 }
00837
00839 openni_wrapper::OpenNIDevice::CallbackHandle
00840 openni_wrapper::OpenNIDevice::registerDepthCallback (const DepthImageCallbackFunction& callback, void* custom_data) throw ()
00841 {
00842 depth_callback_[depth_callback_handle_counter_] = boost::bind (callback, _1, custom_data);
00843 return (depth_callback_handle_counter_++);
00844 }
00845
00847 bool
00848 openni_wrapper::OpenNIDevice::unregisterDepthCallback (const OpenNIDevice::CallbackHandle& callbackHandle) throw ()
00849 {
00850 return (depth_callback_.erase (callbackHandle) != 0);
00851 }
00852
00854 openni_wrapper::OpenNIDevice::CallbackHandle
00855 openni_wrapper::OpenNIDevice::registerIRCallback (const IRImageCallbackFunction& callback, void* custom_data) throw ()
00856 {
00857 ir_callback_[ir_callback_handle_counter_] = boost::bind (callback, _1, custom_data);
00858 return (ir_callback_handle_counter_++);
00859 }
00860
00862 bool
00863 openni_wrapper::OpenNIDevice::unregisterIRCallback (const OpenNIDevice::CallbackHandle& callbackHandle) throw ()
00864 {
00865 return (ir_callback_.erase (callbackHandle) != 0);
00866 }
00867
00869 const char*
00870 openni_wrapper::OpenNIDevice::getSerialNumber () const throw ()
00871 {
00872 return (device_node_info_.GetInstanceName ());
00873 }
00874
00876 const char*
00877 openni_wrapper::OpenNIDevice::getConnectionString () const throw ()
00878 {
00879 return (device_node_info_.GetCreationInfo ());
00880 }
00881
00883 unsigned short
00884 openni_wrapper::OpenNIDevice::getVendorID () const throw ()
00885 {
00886 unsigned short vendor_id;
00887 unsigned short product_id;
00888
00889 #ifndef _WIN32
00890 unsigned char bus;
00891 unsigned char address;
00892
00893 sscanf (device_node_info_.GetCreationInfo(), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00894
00895 #else
00896 OpenNIDriver::getDeviceType (device_node_info_.GetCreationInfo(), vendor_id, product_id);
00897 #endif
00898 return (vendor_id);
00899 }
00900
00902 unsigned short
00903 openni_wrapper::OpenNIDevice::getProductID () const throw ()
00904 {
00905 unsigned short vendor_id;
00906 unsigned short product_id;
00907 #ifndef _WIN32
00908 unsigned char bus;
00909 unsigned char address;
00910 sscanf (device_node_info_.GetCreationInfo(), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00911
00912 #else
00913 OpenNIDriver::getDeviceType (device_node_info_.GetCreationInfo(), vendor_id, product_id);
00914 #endif
00915 return (product_id);
00916 }
00917
00919 unsigned char
00920 openni_wrapper::OpenNIDevice::getBus () const throw ()
00921 {
00922 unsigned char bus = 0;
00923 #ifndef _WIN32
00924 unsigned short vendor_id;
00925 unsigned short product_id;
00926 unsigned char address;
00927 sscanf (device_node_info_.GetCreationInfo(), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00928 #endif
00929 return (bus);
00930 }
00931
00933 unsigned char
00934 openni_wrapper::OpenNIDevice::getAddress () const throw ()
00935 {
00936 unsigned char address = 0;
00937 #ifndef _WIN32
00938 unsigned short vendor_id;
00939 unsigned short product_id;
00940 unsigned char bus;
00941 sscanf (device_node_info_.GetCreationInfo(), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00942 #endif
00943 return (address);
00944 }
00945
00947 const char*
00948 openni_wrapper::OpenNIDevice::getVendorName () const throw ()
00949 {
00950 XnProductionNodeDescription& description = const_cast<XnProductionNodeDescription&>(device_node_info_.GetDescription ());
00951 return (description.strVendor);
00952 }
00953
00955 const char*
00956 openni_wrapper::OpenNIDevice::getProductName () const throw ()
00957 {
00958 XnProductionNodeDescription& description = const_cast<XnProductionNodeDescription&>(device_node_info_.GetDescription ());
00959 return (description.strName);
00960 }
00961
00963 bool
00964 openni_wrapper::OpenNIDevice::findCompatibleImageMode (const XnMapOutputMode& output_mode, XnMapOutputMode& mode) const throw ()
00965 {
00966 if (isImageModeSupported (output_mode))
00967 {
00968 mode = output_mode;
00969 return (true);
00970 }
00971 else
00972 {
00973 bool found = false;
00974 for (vector<XnMapOutputMode>::const_iterator modeIt = available_image_modes_.begin (); modeIt != available_image_modes_.end (); ++modeIt)
00975 {
00976 if (modeIt->nFPS == output_mode.nFPS && isImageResizeSupported (modeIt->nXRes, modeIt->nYRes, output_mode.nXRes, output_mode.nYRes))
00977 {
00978 if (found)
00979 {
00980 if (mode.nXRes * mode.nYRes > modeIt->nXRes * modeIt->nYRes )
00981 mode = *modeIt;
00982 }
00983 else
00984 {
00985 mode = *modeIt;
00986 found = true;
00987 }
00988 }
00989 }
00990 return (found);
00991 }
00992 }
00993
00995 bool
00996 openni_wrapper::OpenNIDevice::findCompatibleDepthMode (const XnMapOutputMode& output_mode, XnMapOutputMode& mode) const throw ()
00997 {
00998 if (isDepthModeSupported (output_mode))
00999 {
01000 mode = output_mode;
01001 return (true);
01002 }
01003 else
01004 {
01005 bool found = false;
01006 for (vector<XnMapOutputMode>::const_iterator modeIt = available_depth_modes_.begin (); modeIt != available_depth_modes_.end (); ++modeIt)
01007 {
01008 if (modeIt->nFPS == output_mode.nFPS && isImageResizeSupported (modeIt->nXRes, modeIt->nYRes, output_mode.nXRes, output_mode.nYRes))
01009 {
01010 if (found)
01011 {
01012 if (mode.nXRes * mode.nYRes > modeIt->nXRes * modeIt->nYRes )
01013 mode = *modeIt;
01014 }
01015 else
01016 {
01017 mode = *modeIt;
01018 found = true;
01019 }
01020 }
01021 }
01022 return (found);
01023 }
01024 }
01025
01027 bool
01028 openni_wrapper::OpenNIDevice::isImageModeSupported (const XnMapOutputMode& output_mode) const throw ()
01029 {
01030 for (vector<XnMapOutputMode>::const_iterator modeIt = available_image_modes_.begin (); modeIt != available_image_modes_.end (); ++modeIt)
01031 {
01032 if (modeIt->nFPS == output_mode.nFPS && modeIt->nXRes == output_mode.nXRes && modeIt->nYRes == output_mode.nYRes)
01033 return (true);
01034 }
01035 return (false);
01036 }
01037
01039 bool
01040 openni_wrapper::OpenNIDevice::isDepthModeSupported (const XnMapOutputMode& output_mode) const throw ()
01041 {
01042 for (vector<XnMapOutputMode>::const_iterator modeIt = available_depth_modes_.begin (); modeIt != available_depth_modes_.end (); ++modeIt)
01043 {
01044 if (modeIt->nFPS == output_mode.nFPS && modeIt->nXRes == output_mode.nXRes && modeIt->nYRes == output_mode.nYRes)
01045 return (true);
01046 }
01047 return (false);
01048 }
01049
01051 const XnMapOutputMode&
01052 openni_wrapper::OpenNIDevice::getDefaultImageMode () const throw ()
01053 {
01054 return (available_image_modes_[0]);
01055 }
01056
01058 const XnMapOutputMode&
01059 openni_wrapper::OpenNIDevice::getDefaultDepthMode () const throw ()
01060 {
01061 return (available_depth_modes_[0]);
01062 }
01063
01065 const XnMapOutputMode&
01066 openni_wrapper::OpenNIDevice::getDefaultIRMode () const throw ()
01067 {
01069 return (available_depth_modes_[0]);
01070 }
01071
01073 void
01074 openni_wrapper::OpenNIDevice::setImageOutputMode (const XnMapOutputMode& output_mode)
01075 {
01076 if (hasImageStream ())
01077 {
01078 lock_guard<mutex> image_lock (image_mutex_);
01079 XnStatus status = image_generator_.SetMapOutputMode (output_mode);
01080 if (status != XN_STATUS_OK)
01081 THROW_OPENNI_EXCEPTION ("Could not set image stream output mode to %dx%d@%d. Reason: %s", output_mode.nXRes, output_mode.nYRes, output_mode.nFPS, xnGetStatusString (status));
01082 }
01083 else
01084 THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
01085 }
01086
01088 void
01089 openni_wrapper::OpenNIDevice::setDepthOutputMode (const XnMapOutputMode& output_mode)
01090 {
01091 if (hasDepthStream ())
01092 {
01093 lock_guard<mutex> depth_lock (depth_mutex_);
01094 XnStatus status = depth_generator_.SetMapOutputMode (output_mode);
01095 if (status != XN_STATUS_OK)
01096 THROW_OPENNI_EXCEPTION ("Could not set depth stream output mode to %dx%d@%d. Reason: %s", output_mode.nXRes, output_mode.nYRes, output_mode.nFPS, xnGetStatusString (status));
01097 }
01098 else
01099 THROW_OPENNI_EXCEPTION ("Device does not provide a depth stream");
01100 }
01101
01103 void
01104 openni_wrapper::OpenNIDevice::setIROutputMode (const XnMapOutputMode& output_mode)
01105 {
01106 if (hasIRStream ())
01107 {
01108 lock_guard<mutex> ir_lock (ir_mutex_);
01109 XnStatus status = ir_generator_.SetMapOutputMode (output_mode);
01110 if (status != XN_STATUS_OK)
01111 THROW_OPENNI_EXCEPTION ("Could not set IR stream output mode to %dx%d@%d. Reason: %s", output_mode.nXRes, output_mode.nYRes, output_mode.nFPS, xnGetStatusString (status));
01112 }
01113 #ifndef __APPLE__
01114 else
01115 THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
01116 #endif
01117 }
01118
01120 XnMapOutputMode
01121 openni_wrapper::OpenNIDevice::getImageOutputMode () const
01122 {
01123 if (!hasImageStream ())
01124 THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
01125
01126 XnMapOutputMode output_mode;
01127 lock_guard<mutex> image_lock (image_mutex_);
01128 XnStatus status = image_generator_.GetMapOutputMode (output_mode);
01129 if (status != XN_STATUS_OK)
01130 THROW_OPENNI_EXCEPTION ("Could not get image stream output mode. Reason: %s", xnGetStatusString (status));
01131 return (output_mode);
01132 }
01133
01135 XnMapOutputMode
01136 openni_wrapper::OpenNIDevice::getDepthOutputMode () const
01137 {
01138 if (!hasDepthStream () )
01139 THROW_OPENNI_EXCEPTION ("Device does not provide a depth stream");
01140
01141 XnMapOutputMode output_mode;
01142 lock_guard<mutex> depth_lock (depth_mutex_);
01143 XnStatus status = depth_generator_.GetMapOutputMode (output_mode);
01144 if (status != XN_STATUS_OK)
01145 THROW_OPENNI_EXCEPTION ("Could not get depth stream output mode. Reason: %s", xnGetStatusString (status));
01146 return (output_mode);
01147 }
01148
01150 XnMapOutputMode
01151 openni_wrapper::OpenNIDevice::getIROutputMode () const
01152 {
01153 if (!hasIRStream ())
01154 THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
01155
01156 XnMapOutputMode output_mode;
01157 lock_guard<mutex> ir_lock (ir_mutex_);
01158 XnStatus status = ir_generator_.GetMapOutputMode (output_mode);
01159 if (status != XN_STATUS_OK)
01160 THROW_OPENNI_EXCEPTION ("Could not get IR stream output mode. Reason: %s", xnGetStatusString (status));
01161 return (output_mode);
01162 }
01163
01164 #endif //OPENNI