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 <openni_camera/openni_driver.h>
00038 #include <openni_camera/openni_device.h>
00039 #include <openni_camera/openni_depth_image.h>
00040 #include <openni_camera/openni_ir_image.h>
00041 #include <iostream>
00042 #include <limits>
00043 #include <sstream>
00044 #include <map>
00045 #include <vector>
00046
00047
00048 using namespace std;
00049 using namespace boost;
00050
00051 namespace openni_wrapper
00052 {
00053
00054 OpenNIDevice::OpenNIDevice (xn::Context& context, const xn::NodeInfo& device_node, const xn::NodeInfo& image_node,
00055 const xn::NodeInfo& depth_node, const xn::NodeInfo& ir_node) throw (OpenNIException)
00056 : device_node_info_ (device_node)
00057 , context_ (context)
00058 {
00059
00060 XnStatus status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(depth_node));
00061 if (status != XN_STATUS_OK)
00062 THROW_OPENNI_EXCEPTION ("creating depth generator failed. Reason: %s", xnGetStatusString (status));
00063
00064 status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(image_node));
00065 if (status != XN_STATUS_OK)
00066 THROW_OPENNI_EXCEPTION ("creating image generator failed. Reason: %s", xnGetStatusString (status));
00067
00068 status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(ir_node));
00069 if (status != XN_STATUS_OK)
00070 THROW_OPENNI_EXCEPTION ("creating IR generator failed. Reason: %s", xnGetStatusString (status));
00071
00072
00073 status = depth_node.GetInstance (depth_generator_);
00074 if (status != XN_STATUS_OK)
00075 THROW_OPENNI_EXCEPTION ("creating depth generator instance failed. Reason: %s", xnGetStatusString (status));
00076
00077 status = image_node.GetInstance (image_generator_);
00078 if (status != XN_STATUS_OK)
00079 THROW_OPENNI_EXCEPTION ("creating image generator instance failed. Reason: %s", xnGetStatusString (status));
00080
00081 status = ir_node.GetInstance (ir_generator_);
00082 if (status != XN_STATUS_OK)
00083 THROW_OPENNI_EXCEPTION ("creating IR generator instance failed. Reason: %s", xnGetStatusString (status));
00084
00085
00086 running_ = true;
00087 image_thread_ = boost::thread (&OpenNIDevice::ImageDataThreadFunction, this);
00088 depth_thread_ = boost::thread (&OpenNIDevice::DepthDataThreadFunction, this);
00089 ir_thread_ = boost::thread (&OpenNIDevice::IRDataThreadFunction, this);
00090 }
00091
00092 OpenNIDevice::OpenNIDevice (xn::Context& context, const xn::NodeInfo& device_node, const xn::NodeInfo& depth_node, const xn::NodeInfo& ir_node) throw (OpenNIException)
00093 : device_node_info_ (device_node)
00094 , context_ (context)
00095 {
00096
00097 XnStatus status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(depth_node));
00098 if (status != XN_STATUS_OK)
00099 THROW_OPENNI_EXCEPTION ("creating depth generator failed. Reason: %s", xnGetStatusString (status));
00100
00101 status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(ir_node));
00102 if (status != XN_STATUS_OK)
00103 THROW_OPENNI_EXCEPTION ("creating IR generator failed. Reason: %s", xnGetStatusString (status));
00104
00105
00106 status = depth_node.GetInstance (depth_generator_);
00107 if (status != XN_STATUS_OK)
00108 THROW_OPENNI_EXCEPTION ("creating depth generator instance failed. Reason: %s", xnGetStatusString (status));
00109
00110 status = ir_node.GetInstance (ir_generator_);
00111 if (status != XN_STATUS_OK)
00112 THROW_OPENNI_EXCEPTION ("creating IR generator instance failed. Reason: %s", xnGetStatusString (status));
00113
00114
00115 running_ = true;
00116 depth_thread_ = boost::thread (&OpenNIDevice::DepthDataThreadFunction, this);
00117 ir_thread_ = boost::thread (&OpenNIDevice::IRDataThreadFunction, this);
00118 }
00119
00120 OpenNIDevice::~OpenNIDevice () throw ()
00121 {
00122
00123 if (hasImageStream() && image_generator_.IsGenerating ())
00124 image_generator_.StopGenerating ();
00125
00126 if (hasDepthStream () && depth_generator_.IsGenerating ())
00127 depth_generator_.StopGenerating ();
00128
00129 if (hasIRStream () && ir_generator_.IsGenerating ())
00130 ir_generator_.StopGenerating ();
00131
00132
00133 image_mutex_.lock ();
00134 depth_mutex_.lock ();
00135 ir_mutex_.lock ();
00136 running_ = false;
00137
00138 depth_condition_.notify_all ();
00139 image_condition_.notify_all ();
00140 ir_condition_.notify_all ();
00141 depth_mutex_.unlock ();
00142 image_mutex_.unlock ();
00143 ir_mutex_.unlock ();
00144
00145 if (hasImageStream ())
00146 image_thread_.join ();
00147
00148 if (hasDepthStream ())
00149 depth_thread_.join ();
00150
00151 if (hasIRStream ())
00152 ir_thread_.join ();
00153 }
00154
00155 void OpenNIDevice::Init () throw (OpenNIException)
00156 {
00157
00158 this->getAvailableModes ();
00159
00160 XnDouble pixel_size;
00161
00162
00163 if (hasDepthStream ())
00164 {
00165 setDepthOutputMode (getDefaultDepthMode ());
00166
00167 unique_lock<mutex> depth_lock (depth_mutex_);
00168 XnStatus status = depth_generator_.GetRealProperty ("ZPPS", pixel_size);
00169 if (status != XN_STATUS_OK)
00170 THROW_OPENNI_EXCEPTION ("reading the pixel size of IR camera failed. Reason: %s", xnGetStatusString (status));
00171
00172 XnUInt64 depth_focal_length_SXGA;
00173 status = depth_generator_.GetIntProperty ("ZPD", depth_focal_length_SXGA);
00174 if (status != XN_STATUS_OK)
00175 THROW_OPENNI_EXCEPTION ("reading the focal length of IR camera failed. Reason: %s", xnGetStatusString (status));
00176
00177 XnDouble baseline;
00178 status = depth_generator_.GetRealProperty ("LDDIS", baseline);
00179 if (status != XN_STATUS_OK)
00180 THROW_OPENNI_EXCEPTION ("reading the baseline failed. Reason: %s", xnGetStatusString (status));
00181
00182 status = depth_generator_.GetIntProperty ("ShadowValue", shadow_value_);
00183 if (status != XN_STATUS_OK)
00184 THROW_OPENNI_EXCEPTION ("reading the value for pixels in shadow regions failed. Reason: %s", xnGetStatusString (status));
00185
00186 status = depth_generator_.GetIntProperty ("NoSampleValue", no_sample_value_);
00187 if (status != XN_STATUS_OK)
00188 THROW_OPENNI_EXCEPTION ("reading the value for pixels with no depth estimation failed. Reason: %s", xnGetStatusString (status));
00189
00190
00191 baseline_ = (float)(baseline * 0.01);
00192
00193
00194 depth_focal_length_SXGA_ = (float)depth_focal_length_SXGA / pixel_size;
00195
00196
00197
00198 depth_generator_.RegisterToNewDataAvailable ((xn::StateChangedHandler)NewDepthDataAvailable, this, depth_callback_handle_);
00199 depth_lock.unlock ();
00200 }
00201
00202 if (hasImageStream ())
00203 {
00204 setImageOutputMode (getDefaultImageMode ());
00205 lock_guard<mutex> image_lock (image_mutex_);
00206 image_generator_.RegisterToNewDataAvailable ((xn::StateChangedHandler)NewImageDataAvailable, this, image_callback_handle_);
00207 }
00208
00209 if (hasIRStream ())
00210 {
00211 setIROutputMode (getDefaultIRMode ());
00212 lock_guard<mutex> ir_lock (ir_mutex_);
00213 ir_generator_.RegisterToNewDataAvailable ((xn::StateChangedHandler)NewIRDataAvailable, this, ir_callback_handle_);
00214 }
00215 }
00216
00217 void OpenNIDevice::startImageStream () throw (OpenNIException)
00218 {
00219 if (hasImageStream ())
00220 {
00221 lock_guard<mutex> image_lock (image_mutex_);
00222 if (!image_generator_.IsGenerating ())
00223 {
00224 XnStatus status = image_generator_.StartGenerating ();
00225 if (status != XN_STATUS_OK)
00226 THROW_OPENNI_EXCEPTION ("starting image stream failed. Reason: %s", xnGetStatusString (status));
00227 }
00228 }
00229 else
00230 THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
00231 }
00232
00233 void OpenNIDevice::stopImageStream () throw (OpenNIException)
00234 {
00235 if (hasImageStream ())
00236 {
00237 lock_guard<mutex> image_lock (image_mutex_);
00238 if (image_generator_.IsGenerating ())
00239 {
00240 XnStatus status = image_generator_.StopGenerating ();
00241 if (status != XN_STATUS_OK)
00242 THROW_OPENNI_EXCEPTION ("stopping image stream failed. Reason: %s", xnGetStatusString (status));
00243 }
00244 }
00245 else
00246 THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
00247 }
00248
00249 void OpenNIDevice::startDepthStream () throw (OpenNIException)
00250 {
00251 if (hasDepthStream ())
00252 {
00253 lock_guard<mutex> depth_lock (depth_mutex_);
00254 if (!depth_generator_.IsGenerating ())
00255 {
00256 XnStatus status = depth_generator_.StartGenerating ();
00257
00258 if (status != XN_STATUS_OK)
00259 THROW_OPENNI_EXCEPTION ("starting depth stream failed. Reason: %s", xnGetStatusString (status));
00260 }
00261 }
00262 else
00263 THROW_OPENNI_EXCEPTION ("Device does not provide a depth stream");
00264 }
00265
00266 void OpenNIDevice::stopDepthStream () throw (OpenNIException)
00267 {
00268 if (hasDepthStream ())
00269 {
00270 lock_guard<mutex> depth_lock (depth_mutex_);
00271 if (depth_generator_.IsGenerating ())
00272 {
00273 XnStatus status = depth_generator_.StopGenerating ();
00274
00275 if (status != XN_STATUS_OK)
00276 THROW_OPENNI_EXCEPTION ("stopping depth stream failed. Reason: %s", xnGetStatusString (status));
00277 }
00278 }
00279 else
00280 THROW_OPENNI_EXCEPTION ("Device does not provide a depth stream");
00281 }
00282
00283 void OpenNIDevice::startIRStream () throw (OpenNIException)
00284 {
00285 if (hasIRStream ())
00286 {
00287 lock_guard<mutex> ir_lock (ir_mutex_);
00288 if (!ir_generator_.IsGenerating ())
00289 {
00290 XnStatus status = ir_generator_.StartGenerating ();
00291
00292 if (status != XN_STATUS_OK)
00293 THROW_OPENNI_EXCEPTION ("starting IR stream failed. Reason: %s", xnGetStatusString (status));
00294 }
00295 }
00296 else
00297 THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
00298 }
00299
00300 void OpenNIDevice::stopIRStream () throw (OpenNIException)
00301 {
00302 if (hasIRStream ())
00303 {
00304 lock_guard<mutex> ir_lock (ir_mutex_);
00305 if (ir_generator_.IsGenerating ())
00306 {
00307 XnStatus status = ir_generator_.StopGenerating ();
00308
00309 if (status != XN_STATUS_OK)
00310 THROW_OPENNI_EXCEPTION ("stopping IR stream failed. Reason: %s", xnGetStatusString (status));
00311 }
00312 }
00313 else
00314 THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
00315 }
00316
00317 bool OpenNIDevice::isImageStreamRunning () const throw (OpenNIException)
00318 {
00319 lock_guard<mutex> image_lock (image_mutex_);
00320 return ( hasImageStream () && image_generator_.IsGenerating ());
00321 }
00322
00323 bool OpenNIDevice::isDepthStreamRunning () const throw (OpenNIException)
00324 {
00325 lock_guard<mutex> depth_lock (depth_mutex_);
00326 return ( hasDepthStream () && depth_generator_.IsGenerating ());
00327 }
00328
00329 bool OpenNIDevice::isIRStreamRunning () const throw (OpenNIException)
00330 {
00331 lock_guard<mutex> ir_lock (ir_mutex_);
00332 return ( hasIRStream () && ir_generator_.IsGenerating ());
00333 }
00334
00335 bool OpenNIDevice::hasImageStream () const throw ()
00336 {
00337 return (available_image_modes_.size() != 0);
00338 }
00339
00340 bool OpenNIDevice::hasDepthStream () const throw ()
00341 {
00342 return (available_depth_modes_.size() != 0);
00343 }
00344
00345 bool OpenNIDevice::hasIRStream () const throw ()
00346 {
00348 return true;
00349 }
00350
00351 void OpenNIDevice::setDepthRegistration (bool on_off) throw (OpenNIException)
00352 {
00353 if (hasDepthStream () && hasImageStream())
00354 {
00355 lock_guard<mutex> image_lock (image_mutex_);
00356 lock_guard<mutex> depth_lock (depth_mutex_);
00357 if (on_off && !depth_generator_.GetAlternativeViewPointCap ().IsViewPointAs (image_generator_))
00358 {
00359 if (depth_generator_.GetAlternativeViewPointCap ().IsViewPointSupported (image_generator_))
00360 {
00361 XnStatus status = depth_generator_.GetAlternativeViewPointCap ().SetViewPoint (image_generator_);
00362 if (status != XN_STATUS_OK)
00363 THROW_OPENNI_EXCEPTION ("turning registration on failed. Reason: %s", xnGetStatusString (status));
00364 }
00365 else
00366 THROW_OPENNI_EXCEPTION ("turning registration on failed. Reason: unsopported viewpoint");
00367 }
00368 else if (!on_off)
00369 {
00370 XnStatus status = depth_generator_.GetAlternativeViewPointCap ().ResetViewPoint ();
00371
00372 if (status != XN_STATUS_OK)
00373 THROW_OPENNI_EXCEPTION ("turning registration off failed. Reason: %s", xnGetStatusString (status));
00374 }
00375 }
00376 else
00377 THROW_OPENNI_EXCEPTION ("Device does not provide image + depth stream");
00378 }
00379
00380 bool OpenNIDevice::isDepthRegistered () const throw (OpenNIException)
00381 {
00382 if (hasDepthStream () && hasImageStream())
00383 {
00384 xn::DepthGenerator& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
00385 xn::ImageGenerator& image_generator = const_cast<xn::ImageGenerator&>(image_generator_);
00386
00387 lock_guard<mutex> image_lock (image_mutex_);
00388 lock_guard<mutex> depth_lock (depth_mutex_);
00389 return (depth_generator.GetAlternativeViewPointCap ().IsViewPointAs (image_generator));
00390 }
00391 return false;
00392 }
00393
00394 bool OpenNIDevice::isSynchronizationSupported () const throw ()
00395 {
00396 lock_guard<mutex> depth_lock (depth_mutex_);
00397 return ( hasDepthStream () && hasImageStream() && depth_generator_.IsCapabilitySupported (XN_CAPABILITY_FRAME_SYNC));
00398 }
00399
00400 void OpenNIDevice::setSynchronization (bool on_off) throw (OpenNIException)
00401 {
00402 if (hasDepthStream () && hasImageStream())
00403 {
00404 lock_guard<mutex> image_lock (image_mutex_);
00405 lock_guard<mutex> depth_lock (depth_mutex_);
00406 XnStatus status;
00407
00408 if (on_off && depth_generator_.GetFrameSyncCap ().CanFrameSyncWith (image_generator_) && !depth_generator_.GetFrameSyncCap ().IsFrameSyncedWith (image_generator_))
00409 {
00410 status = depth_generator_.GetFrameSyncCap ().FrameSyncWith (image_generator_);
00411 if (status != XN_STATUS_OK)
00412 THROW_OPENNI_EXCEPTION ("could not turn on frame synchronization. Reason: %s", xnGetStatusString (status));
00413 }
00414 else if (!on_off && depth_generator_.GetFrameSyncCap ().CanFrameSyncWith (image_generator_) && depth_generator_.GetFrameSyncCap ().IsFrameSyncedWith (image_generator_))
00415 {
00416 status = depth_generator_.GetFrameSyncCap ().StopFrameSyncWith (image_generator_);
00417 if (status != XN_STATUS_OK)
00418 THROW_OPENNI_EXCEPTION ("could not turn off frame synchronization. Reason: %s", xnGetStatusString (status));
00419 }
00420 }
00421 else
00422 THROW_OPENNI_EXCEPTION ("Device does not provide image + depth stream");
00423 }
00424
00425 bool OpenNIDevice::isSynchronized () const throw (OpenNIException)
00426 {
00427 if (hasDepthStream () && hasImageStream())
00428 {
00429 lock_guard<mutex> image_lock (image_mutex_);
00430 lock_guard<mutex> depth_lock (depth_mutex_);
00431 xn::DepthGenerator& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
00432 xn::ImageGenerator& image_generator = const_cast<xn::ImageGenerator&>(image_generator_);
00433 return (depth_generator.GetFrameSyncCap ().CanFrameSyncWith (image_generator) && depth_generator.GetFrameSyncCap ().IsFrameSyncedWith (image_generator));
00434 }
00435 else
00436 return false;
00437 }
00438
00439 bool OpenNIDevice::isDepthCroppingSupported () const throw ()
00440 {
00441 lock_guard<mutex> depth_lock (depth_mutex_);
00442 return hasDepthStream () && depth_generator_.IsCapabilitySupported (XN_CAPABILITY_CROPPING);
00443 }
00444
00445 bool OpenNIDevice::isDepthCropped () const throw (OpenNIException)
00446 {
00447 if (hasDepthStream ())
00448 {
00449 lock_guard<mutex> depth_lock (depth_mutex_);
00450 XnCropping cropping;
00451 xn::DepthGenerator& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
00452 XnStatus status = depth_generator.GetCroppingCap ().GetCropping (cropping);
00453 if (status != XN_STATUS_OK)
00454 THROW_OPENNI_EXCEPTION ("could not read cropping information for depth stream. Reason: %s", xnGetStatusString (status));
00455
00456 return cropping.bEnabled;
00457 }
00458 return false;
00459 }
00460
00461 void OpenNIDevice::setDepthCropping (unsigned x, unsigned y, unsigned width, unsigned height) throw (OpenNIException)
00462 {
00463 if (hasDepthStream ())
00464 {
00465 lock_guard<mutex> depth_lock (depth_mutex_);
00466 XnCropping cropping;
00467 cropping.nXOffset = x;
00468 cropping.nYOffset = y;
00469 cropping.nXSize = width;
00470 cropping.nYSize = height;
00471
00472 cropping.bEnabled = (width != 0 && height != 0);
00473 XnStatus status = depth_generator_.GetCroppingCap ().SetCropping (cropping);
00474 if (status != XN_STATUS_OK)
00475 THROW_OPENNI_EXCEPTION ("could not set cropping information for depth stream. Reason: %s", xnGetStatusString (status));
00476 }
00477 else
00478 THROW_OPENNI_EXCEPTION ("Device does not provide depth stream");
00479 }
00480
00481 void OpenNIDevice::ImageDataThreadFunction () throw (OpenNIException)
00482 {
00483 while (running_)
00484 {
00485
00486 unique_lock<mutex> image_lock (image_mutex_);
00487 if (!running_)
00488 return;
00489 image_condition_.wait (image_lock);
00490 if (!running_)
00491 return;
00492
00493 image_generator_.WaitAndUpdateData ();
00494
00495 boost::shared_ptr<xn::ImageMetaData> image_data (new xn::ImageMetaData);
00496 image_generator_.GetMetaData (*image_data);
00497
00498 image_lock.unlock ();
00499
00500 boost::shared_ptr<Image> image = getCurrentImage (image_data);
00501 for (map< OpenNIDevice::CallbackHandle, ActualImageCallbackFunction >::iterator callbackIt = image_callback_.begin (); callbackIt != image_callback_.end (); ++callbackIt)
00502 {
00503 callbackIt->second.operator()(image);
00504 }
00505 }
00506 }
00507
00508 void OpenNIDevice::DepthDataThreadFunction () throw (OpenNIException)
00509 {
00510 while (running_)
00511 {
00512
00513 unique_lock<mutex> depth_lock (depth_mutex_);
00514 if (!running_)
00515 return;
00516 depth_condition_.wait (depth_lock);
00517 if (!running_)
00518 return;
00519
00520 depth_generator_.WaitAndUpdateData ();
00521 boost::shared_ptr<xn::DepthMetaData> depth_data (new xn::DepthMetaData);
00522 depth_generator_.GetMetaData (*depth_data);
00523 depth_lock.unlock ();
00524
00525 boost::shared_ptr<DepthImage> depth_image ( new DepthImage (depth_data, baseline_, getDepthFocalLength (), shadow_value_, no_sample_value_) );
00526
00527 for (map< OpenNIDevice::CallbackHandle, ActualDepthImageCallbackFunction >::iterator callbackIt = depth_callback_.begin ();
00528 callbackIt != depth_callback_.end (); ++callbackIt)
00529 {
00530 callbackIt->second.operator()(depth_image);
00531 }
00532 }
00533 }
00534
00535 void OpenNIDevice::IRDataThreadFunction () throw (OpenNIException)
00536 {
00537 while (running_)
00538 {
00539
00540 unique_lock<mutex> ir_lock (ir_mutex_);
00541 if (!running_)
00542 return;
00543 ir_condition_.wait (ir_lock);
00544 if (!running_)
00545 return;
00546
00547 ir_generator_.WaitAndUpdateData ();
00548 boost::shared_ptr<xn::IRMetaData> ir_data (new xn::IRMetaData);
00549 ir_generator_.GetMetaData (*ir_data);
00550 ir_lock.unlock ();
00551
00552 boost::shared_ptr<IRImage> ir_image ( new IRImage (ir_data) );
00553
00554 for (map< OpenNIDevice::CallbackHandle, ActualIRImageCallbackFunction >::iterator callbackIt = ir_callback_.begin ();
00555 callbackIt != ir_callback_.end (); ++callbackIt)
00556 {
00557 callbackIt->second.operator()(ir_image);
00558 }
00559 }
00560 }
00561
00562 void __stdcall OpenNIDevice::NewDepthDataAvailable (xn::ProductionNode& node, void* cookie) throw ()
00563 {
00564 OpenNIDevice* device = reinterpret_cast<OpenNIDevice*>(cookie);
00565 device->depth_condition_.notify_all ();
00566 }
00567
00568 void __stdcall OpenNIDevice::NewImageDataAvailable (xn::ProductionNode& node, void* cookie) throw ()
00569 {
00570 OpenNIDevice* device = reinterpret_cast<OpenNIDevice*>(cookie);
00571 device->image_condition_.notify_all ();
00572 }
00573
00574 void __stdcall OpenNIDevice::NewIRDataAvailable (xn::ProductionNode& node, void* cookie) throw ()
00575 {
00576 OpenNIDevice* device = reinterpret_cast<OpenNIDevice*>(cookie);
00577 device->ir_condition_.notify_all ();
00578 }
00579
00580 OpenNIDevice::CallbackHandle OpenNIDevice::registerImageCallback (const ImageCallbackFunction& callback, void* custom_data) throw ()
00581 {
00582 if (!hasImageStream ())
00583 THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
00584
00585 image_callback_[image_callback_handle_counter_] = boost::bind (callback, _1, custom_data);
00586 return image_callback_handle_counter_++;
00587 }
00588
00589 bool OpenNIDevice::unregisterImageCallback (const OpenNIDevice::CallbackHandle& callbackHandle) throw ()
00590 {
00591 if (!hasImageStream ())
00592 THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
00593
00594 return (image_callback_.erase (callbackHandle) != 0);
00595 }
00596
00597 OpenNIDevice::CallbackHandle OpenNIDevice::registerDepthCallback (const DepthImageCallbackFunction& callback, void* custom_data) throw ()
00598 {
00599 if (!hasDepthStream ())
00600 THROW_OPENNI_EXCEPTION ("Device does not provide a depth image");
00601
00602 depth_callback_[depth_callback_handle_counter_] = boost::bind (callback, _1, custom_data);
00603 return depth_callback_handle_counter_++;
00604 }
00605
00606 bool OpenNIDevice::unregisterDepthCallback (const OpenNIDevice::CallbackHandle& callbackHandle) throw ()
00607 {
00608 if (hasDepthStream ())
00609 return (depth_callback_.erase (callbackHandle) != 0);
00610 else
00611 THROW_OPENNI_EXCEPTION ("Device does not provide a depth image");
00612 return false;
00613 }
00614
00615 const char* OpenNIDevice::getSerialNumber () const throw ()
00616 {
00617 return device_node_info_.GetInstanceName ();
00618 }
00619
00620 const char* OpenNIDevice::getConnectionString () const throw ()
00621 {
00622 return device_node_info_.GetCreationInfo ();
00623 }
00624
00625 unsigned short OpenNIDevice::getVendorID () const throw ()
00626 {
00627 unsigned short vendor_id;
00628 unsigned short product_id;
00629 #ifndef _WIN32
00630 unsigned char bus;
00631 unsigned char address;
00632 sscanf (device_node_info_.GetCreationInfo (), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00633
00634 #else
00635 OpenNIDriver::getDeviceType (device_node_info_.GetCreationInfo (), vendor_id, product_id);
00636 #endif
00637 return vendor_id;
00638 }
00639
00640 unsigned short OpenNIDevice::getProductID () const throw ()
00641 {
00642 unsigned short vendor_id;
00643 unsigned short product_id;
00644 #ifndef _WIN32
00645 unsigned char bus;
00646 unsigned char address;
00647 sscanf (device_node_info_.GetCreationInfo (), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00648
00649 #else
00650 OpenNIDriver::getDeviceType (device_node_info_.GetCreationInfo (), vendor_id, product_id);
00651 #endif
00652 return product_id;
00653 }
00654
00655 unsigned char OpenNIDevice::getBus () const throw ()
00656 {
00657 unsigned char bus = 0;
00658 #ifndef _WIN32
00659 unsigned short vendor_id;
00660 unsigned short product_id;
00661 unsigned char address;
00662 sscanf (device_node_info_.GetCreationInfo (), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00663 #endif
00664 return bus;
00665 }
00666
00667 unsigned char OpenNIDevice::getAddress () const throw ()
00668 {
00669 unsigned char address = 0;
00670 #ifndef _WIN32
00671 unsigned short vendor_id;
00672 unsigned short product_id;
00673 unsigned char bus;
00674 sscanf (device_node_info_.GetCreationInfo (), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00675 #endif
00676 return address;
00677 }
00678
00679 const char* OpenNIDevice::getVendorName () const throw ()
00680 {
00681 XnProductionNodeDescription& description = const_cast<XnProductionNodeDescription&>(device_node_info_.GetDescription ());
00682 return description.strVendor;
00683 }
00684
00685 const char* OpenNIDevice::getProductName () const throw ()
00686 {
00687 XnProductionNodeDescription& description = const_cast<XnProductionNodeDescription&>(device_node_info_.GetDescription ());
00688 return description.strName;
00689 }
00690
00691 bool OpenNIDevice::findCompatibleImageMode (const XnMapOutputMode& output_mode, XnMapOutputMode& mode) const throw (OpenNIException)
00692 {
00693 if (isImageModeSupported (output_mode))
00694 {
00695 mode = output_mode;
00696 return true;
00697 }
00698 else
00699 {
00700 bool found = false;
00701 for (vector<XnMapOutputMode>::const_iterator modeIt = available_image_modes_.begin (); modeIt != available_image_modes_.end (); ++modeIt)
00702 {
00703 if (modeIt->nFPS == output_mode.nFPS && isImageResizeSupported (modeIt->nXRes, modeIt->nYRes, output_mode.nXRes, output_mode.nYRes))
00704 {
00705 if (found)
00706 {
00707 if (mode.nXRes * mode.nYRes > modeIt->nXRes * modeIt->nYRes )
00708 mode = *modeIt;
00709 }
00710 else
00711 {
00712 mode = *modeIt;
00713 found = true;
00714 }
00715 }
00716 }
00717 return found;
00718 }
00719 }
00720
00721 bool OpenNIDevice::findCompatibleDepthMode (const XnMapOutputMode& output_mode, XnMapOutputMode& mode) const throw (OpenNIException)
00722 {
00723 if (isDepthModeSupported (output_mode))
00724 {
00725 mode = output_mode;
00726 return true;
00727 }
00728 else
00729 {
00730 bool found = false;
00731 for (vector<XnMapOutputMode>::const_iterator modeIt = available_depth_modes_.begin (); modeIt != available_depth_modes_.end (); ++modeIt)
00732 {
00733 if (modeIt->nFPS == output_mode.nFPS && isImageResizeSupported (modeIt->nXRes, modeIt->nYRes, output_mode.nXRes, output_mode.nYRes))
00734 {
00735 if (found)
00736 {
00737 if (mode.nXRes * mode.nYRes > modeIt->nXRes * modeIt->nYRes )
00738 mode = *modeIt;
00739 }
00740 else
00741 {
00742 mode = *modeIt;
00743 found = true;
00744 }
00745 }
00746 }
00747 return found;
00748 }
00749 }
00750
00751 void OpenNIDevice::getAvailableModes () throw (OpenNIException)
00752 {
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 }
00788
00789 bool OpenNIDevice::isImageModeSupported (const XnMapOutputMode& output_mode) const throw (OpenNIException)
00790 {
00791 for (vector<XnMapOutputMode>::const_iterator modeIt = available_image_modes_.begin (); modeIt != available_image_modes_.end (); ++modeIt)
00792 {
00793 if (modeIt->nFPS == output_mode.nFPS && modeIt->nXRes == output_mode.nXRes && modeIt->nYRes == output_mode.nYRes)
00794 return true;
00795 }
00796 return false;
00797 }
00798
00799 bool OpenNIDevice::isDepthModeSupported (const XnMapOutputMode& output_mode) const throw (OpenNIException)
00800 {
00801 for (vector<XnMapOutputMode>::const_iterator modeIt = available_depth_modes_.begin (); modeIt != available_depth_modes_.end (); ++modeIt)
00802 {
00803 if (modeIt->nFPS == output_mode.nFPS && modeIt->nXRes == output_mode.nXRes && modeIt->nYRes == output_mode.nYRes)
00804 return true;
00805 }
00806 return false;
00807 }
00808
00809 const XnMapOutputMode& OpenNIDevice::getDefaultImageMode () const throw ()
00810 {
00811 return available_image_modes_[0];
00812 }
00813
00814 const XnMapOutputMode& OpenNIDevice::getDefaultDepthMode () const throw ()
00815 {
00816 return available_depth_modes_[0];
00817 }
00818
00819 const XnMapOutputMode& OpenNIDevice::getDefaultIRMode () const throw ()
00820 {
00822 return available_image_modes_[0];
00823 }
00824
00825 void OpenNIDevice::setImageOutputMode (const XnMapOutputMode& output_mode) throw (OpenNIException)
00826 {
00827 if (hasImageStream ())
00828 {
00829 lock_guard<mutex> image_lock (image_mutex_);
00830 XnStatus status = image_generator_.SetMapOutputMode (output_mode);
00831 if (status != XN_STATUS_OK)
00832 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));
00833 }
00834 else
00835 THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
00836 }
00837
00838 void OpenNIDevice::setDepthOutputMode (const XnMapOutputMode& output_mode) throw (OpenNIException)
00839 {
00840 if (hasDepthStream ())
00841 {
00842 lock_guard<mutex> depth_lock (depth_mutex_);
00843 XnStatus status = depth_generator_.SetMapOutputMode (output_mode);
00844 if (status != XN_STATUS_OK)
00845 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));
00846 }
00847 else
00848 THROW_OPENNI_EXCEPTION ("Device does not provide a depth stream");
00849 }
00850
00851 void OpenNIDevice::setIROutputMode (const XnMapOutputMode& output_mode) throw (OpenNIException)
00852 {
00853 if (hasIRStream ())
00854 {
00855 lock_guard<mutex> ir_lock (ir_mutex_);
00856 XnStatus status = ir_generator_.SetMapOutputMode (output_mode);
00857 if (status != XN_STATUS_OK)
00858 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));
00859 }
00860 else
00861 THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
00862 }
00863
00864 XnMapOutputMode OpenNIDevice::getImageOutputMode () const throw (OpenNIException)
00865 {
00866 if (!hasImageStream ())
00867 THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
00868
00869 XnMapOutputMode output_mode;
00870 lock_guard<mutex> image_lock (image_mutex_);
00871 XnStatus status = image_generator_.GetMapOutputMode (output_mode);
00872 if (status != XN_STATUS_OK)
00873 THROW_OPENNI_EXCEPTION ("Could not get image stream output mode. Reason: %s", xnGetStatusString (status));
00874 return output_mode;
00875 }
00876
00877 XnMapOutputMode OpenNIDevice::getDepthOutputMode () const throw (OpenNIException)
00878 {
00879 if (!hasDepthStream () )
00880 THROW_OPENNI_EXCEPTION ("Device does not provide a depth stream");
00881
00882 XnMapOutputMode output_mode;
00883 lock_guard<mutex> depth_lock (depth_mutex_);
00884 XnStatus status = depth_generator_.GetMapOutputMode (output_mode);
00885 if (status != XN_STATUS_OK)
00886 THROW_OPENNI_EXCEPTION ("Could not get depth stream output mode. Reason: %s", xnGetStatusString (status));
00887 return output_mode;
00888 }
00889
00890 XnMapOutputMode OpenNIDevice::getIROutputMode () const throw (OpenNIException)
00891 {
00892 if (!hasIRStream ())
00893 THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
00894
00895 XnMapOutputMode output_mode;
00896 lock_guard<mutex> ir_lock (ir_mutex_);
00897 XnStatus status = ir_generator_.GetMapOutputMode (output_mode);
00898 if (status != XN_STATUS_OK)
00899 THROW_OPENNI_EXCEPTION ("Could not get IR stream output mode. Reason: %s", xnGetStatusString (status));
00900 return output_mode;
00901 }
00902
00903
00904 const float OpenNIDevice::rgb_focal_length_SXGA_ = 1050;
00905 }