Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
openni_device.h
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2009-2011, Willow Garage, Inc.
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Willow Garage, Inc. nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  */
00037 
00038 #include <pcl/pcl_config.h>
00039 #ifdef HAVE_OPENNI
00040 
00041 #ifndef __OPENNI_IDEVICE_H__
00042 #define __OPENNI_IDEVICE_H__
00043 #include <map>
00044 #include <vector>
00045 #include <utility>
00046 #include "openni_exception.h"
00047 #include <XnCppWrapper.h>
00048 #include <boost/noncopyable.hpp>
00049 #include <boost/function.hpp>
00050 #include <boost/thread.hpp>
00051 #include <boost/thread/condition.hpp>
00052 
00053 #include <pcl/pcl_macros.h>
00054 
00056 
00057 #ifndef _WIN32
00058 #define __stdcall
00059 #endif
00060 
00061 namespace openni_wrapper
00062 {
00063   class Image;
00064   class DepthImage;
00065   class IRImage;
00066 
00071   class PCL_EXPORTS OpenNIDevice : public boost::noncopyable
00072   {
00073   public:
00074     typedef boost::function<void(boost::shared_ptr<Image>, void* cookie) > ImageCallbackFunction;
00075     typedef boost::function<void(boost::shared_ptr<DepthImage>, void* cookie) > DepthImageCallbackFunction;
00076     typedef boost::function<void(boost::shared_ptr<IRImage>, void* cookie) > IRImageCallbackFunction;
00077     typedef unsigned CallbackHandle;
00078 
00079   public:
00080 
00082     virtual ~OpenNIDevice () throw ();
00083 
00091     bool 
00092     findCompatibleImageMode (const XnMapOutputMode& output_mode, XnMapOutputMode& mode ) const throw ();
00093 
00101     bool 
00102     findCompatibleDepthMode (const XnMapOutputMode& output_mode, XnMapOutputMode& mode ) const throw ();
00103 
00108     bool 
00109     isImageModeSupported (const XnMapOutputMode& output_mode) const throw ();
00110 
00115     bool 
00116     isDepthModeSupported (const XnMapOutputMode& output_mode) const throw ();
00117 
00122     const XnMapOutputMode& 
00123     getDefaultImageMode () const throw ();
00124 
00128     const XnMapOutputMode& 
00129     getDefaultDepthMode () const throw ();
00130 
00134     const XnMapOutputMode& 
00135     getDefaultIRMode () const throw ();
00136 
00140     void 
00141     setImageOutputMode (const XnMapOutputMode& output_mode);
00142 
00146     void 
00147     setDepthOutputMode (const XnMapOutputMode& output_mode);
00148 
00152     void 
00153     setIROutputMode (const XnMapOutputMode& output_mode);
00154 
00156     XnMapOutputMode 
00157     getImageOutputMode () const;
00158 
00160     XnMapOutputMode 
00161     getDepthOutputMode () const;
00162 
00164     XnMapOutputMode 
00165     getIROutputMode () const;
00166 
00170     void 
00171     setDepthRegistration (bool on_off);
00172 
00174     bool 
00175     isDepthRegistered () const throw ();
00176 
00178     bool 
00179     isDepthRegistrationSupported () const throw ();
00180 
00184     void 
00185     setSynchronization (bool on_off);
00186 
00188     bool 
00189     isSynchronized () const throw ();
00190 
00192     bool 
00193     isSynchronizationSupported () const throw ();
00194 
00196     bool 
00197     isDepthCropped () const;
00198 
00205     void 
00206     setDepthCropping (unsigned x, unsigned y, unsigned width, unsigned height);
00207 
00209     bool 
00210     isDepthCroppingSupported () const throw ();
00211 
00215     inline float 
00216     getImageFocalLength (int output_x_resolution = 0) const throw ();
00217 
00221     inline float 
00222     getDepthFocalLength (int output_x_resolution = 0) const throw ();
00223 
00225     inline float 
00226     getBaseline () const throw ();
00227 
00229     virtual void 
00230     startImageStream ();
00231 
00233     virtual void 
00234     stopImageStream ();
00235 
00237     virtual void 
00238     startDepthStream ();
00239 
00241     virtual void 
00242     stopDepthStream ();
00243 
00245     virtual void 
00246     startIRStream ();
00247 
00249     virtual void 
00250     stopIRStream ();
00251 
00253     bool 
00254     hasImageStream () const throw ();
00255 
00257     bool 
00258     hasDepthStream () const throw ();
00259 
00261     bool 
00262     hasIRStream () const throw ();
00263 
00265     virtual bool 
00266     isImageStreamRunning () const throw ();
00267 
00269     virtual bool 
00270     isDepthStreamRunning () const throw ();
00271 
00273     virtual bool 
00274     isIRStreamRunning () const throw ();
00275 
00282     CallbackHandle 
00283     registerImageCallback (const ImageCallbackFunction& callback, void* cookie = NULL) throw ();
00284 
00292     template<typename T> CallbackHandle 
00293     registerImageCallback (void (T::*callback)(boost::shared_ptr<Image>, void* cookie), T& instance, void* cookie = NULL) throw ();
00294 
00299     bool 
00300     unregisterImageCallback (const CallbackHandle& callbackHandle) throw ();
00301 
00302 
00309     CallbackHandle 
00310     registerDepthCallback (const DepthImageCallbackFunction& callback, void* cookie = NULL) throw ();
00311 
00319     template<typename T> CallbackHandle 
00320     registerDepthCallback (void (T::*callback)(boost::shared_ptr<DepthImage>, void* cookie), T& instance, void* cookie = NULL) throw ();
00321 
00326     bool 
00327     unregisterDepthCallback (const CallbackHandle& callbackHandle) throw ();
00328 
00335     CallbackHandle 
00336     registerIRCallback (const IRImageCallbackFunction& callback, void* cookie = NULL) throw ();
00337 
00345     template<typename T> CallbackHandle 
00346     registerIRCallback (void (T::*callback)(boost::shared_ptr<IRImage>, void* cookie), T& instance, void* cookie = NULL) throw ();
00347 
00352     bool 
00353     unregisterIRCallback (const CallbackHandle& callbackHandle) throw ();
00354 
00358     const char* 
00359     getSerialNumber () const throw ();
00360 
00362     const char* 
00363     getConnectionString () const throw ();
00364 
00366     const char* 
00367     getVendorName () const throw ();
00368 
00370     const char* 
00371     getProductName () const throw ();
00372 
00374     unsigned short 
00375     getVendorID () const throw ();
00376 
00378     unsigned short 
00379     getProductID () const throw ();
00380 
00382     unsigned char  
00383     getBus () const throw ();
00384 
00386     unsigned char  
00387     getAddress () const throw ();
00388 
00392     inline void
00393     setRGBFocalLength (float focal_length)
00394     {
00395       rgb_focal_length_SXGA_ = focal_length;
00396     }
00397 
00401     inline void
00402     setDepthFocalLength (float focal_length)
00403     {
00404       depth_focal_length_SXGA_ = focal_length;
00405     }
00406 
00407   protected:
00408     typedef boost::function<void(boost::shared_ptr<Image>) > ActualImageCallbackFunction;
00409     typedef boost::function<void(boost::shared_ptr<DepthImage>) > ActualDepthImageCallbackFunction;
00410     typedef boost::function<void(boost::shared_ptr<IRImage>) > ActualIRImageCallbackFunction;
00411 
00412     OpenNIDevice (xn::Context& context, const xn::NodeInfo& device_node, const xn::NodeInfo& image_node, const xn::NodeInfo& depth_node, const xn::NodeInfo& ir_node);
00413     OpenNIDevice (xn::Context& context, const xn::NodeInfo& device_node, const xn::NodeInfo& depth_node, const xn::NodeInfo& ir_node);
00414     OpenNIDevice (xn::Context& context);
00415     static void __stdcall NewDepthDataAvailable (xn::ProductionNode& node, void* cookie) throw ();
00416     static void __stdcall NewImageDataAvailable (xn::ProductionNode& node, void* cookie) throw ();
00417     static void __stdcall NewIRDataAvailable (xn::ProductionNode& node, void* cookie) throw ();
00418 
00419     // This is a workaround, since in the NewDepthDataAvailable function WaitAndUpdateData leads to a dead-lock behaviour
00420     // and retrieving image data without WaitAndUpdateData leads to incomplete images!!!
00421     void 
00422     ImageDataThreadFunction ();
00423 
00424     void 
00425     DepthDataThreadFunction ();
00426 
00427     void 
00428     IRDataThreadFunction ();
00429 
00430     virtual bool 
00431     isImageResizeSupported (unsigned input_width, unsigned input_height, unsigned output_width, unsigned output_height) const  throw () = 0;
00432 
00433     void 
00434     setRegistration (bool on_off);
00435 
00436     virtual boost::shared_ptr<Image> 
00437     getCurrentImage (boost::shared_ptr<xn::ImageMetaData> image_data) const throw () = 0;
00438 
00439     void 
00440     Init ();
00441     // holds the callback functions together with custom data
00442     // since same callback function can be registered multiple times with e.g. different custom data
00443     // we use a map structure with a handle as the key
00444     std::map<CallbackHandle, ActualImageCallbackFunction> image_callback_;
00445     std::map<CallbackHandle, ActualDepthImageCallbackFunction> depth_callback_;
00446     std::map<CallbackHandle, ActualIRImageCallbackFunction> ir_callback_;
00447 
00448     std::vector<XnMapOutputMode> available_image_modes_;
00449     std::vector<XnMapOutputMode> available_depth_modes_;
00450 
00452     xn::Context& context_;
00454     xn::NodeInfo device_node_info_;
00455 
00457     xn::DepthGenerator depth_generator_;
00459     xn::ImageGenerator image_generator_;
00461     xn::IRGenerator ir_generator_;
00462 
00463     XnCallbackHandle depth_callback_handle_;
00464     XnCallbackHandle image_callback_handle_;
00465     XnCallbackHandle ir_callback_handle_;
00466 
00468     float depth_focal_length_SXGA_;
00470     float baseline_;
00472     float rgb_focal_length_SXGA_;
00473 
00475     XnUInt64 shadow_value_;
00477     XnUInt64 no_sample_value_;
00478 
00479     OpenNIDevice::CallbackHandle image_callback_handle_counter_;
00480     OpenNIDevice::CallbackHandle depth_callback_handle_counter_;
00481     OpenNIDevice::CallbackHandle ir_callback_handle_counter_;
00482 
00483     bool quit_;
00484     mutable boost::mutex image_mutex_;
00485     mutable boost::mutex depth_mutex_;
00486     mutable boost::mutex ir_mutex_;
00487     boost::condition_variable image_condition_;
00488     boost::condition_variable depth_condition_;
00489     boost::condition_variable ir_condition_;
00490     boost::thread image_thread_;
00491     boost::thread depth_thread_;
00492     boost::thread ir_thread_;
00493   } ;
00494 
00496   float
00497   OpenNIDevice::getImageFocalLength (int output_x_resolution) const throw ()
00498   {
00499     if (output_x_resolution == 0)
00500       output_x_resolution = getImageOutputMode ().nXRes;
00501 
00502     float scale = output_x_resolution / (float) XN_SXGA_X_RES;
00503     return (rgb_focal_length_SXGA_ * scale);
00504   }
00505 
00507   float
00508   OpenNIDevice::getDepthFocalLength (int output_x_resolution) const throw ()
00509   {
00510     if (output_x_resolution == 0)
00511       output_x_resolution = getDepthOutputMode ().nXRes;
00512 
00513     float scale = output_x_resolution / (float) XN_SXGA_X_RES;
00514     if (isDepthRegistered ())
00515       return (rgb_focal_length_SXGA_ * scale);
00516     else
00517       return (depth_focal_length_SXGA_ * scale);
00518   }
00519 
00521   float
00522   OpenNIDevice::getBaseline () const throw ()
00523   {
00524     return (baseline_);
00525   }
00526 
00528   template<typename T> OpenNIDevice::CallbackHandle
00529   OpenNIDevice::registerImageCallback (void (T::*callback)(boost::shared_ptr<Image>, void* cookie), T& instance, void* custom_data) throw ()
00530   {
00531     image_callback_[image_callback_handle_counter_] = boost::bind (callback, boost::ref (instance), _1, custom_data);
00532     return (image_callback_handle_counter_++);
00533   }
00534 
00536   template<typename T> OpenNIDevice::CallbackHandle
00537   OpenNIDevice::registerDepthCallback (void (T::*callback)(boost::shared_ptr<DepthImage>, void* cookie), T& instance, void* custom_data) throw ()
00538   {
00539     depth_callback_[depth_callback_handle_counter_] = boost::bind ( callback,  boost::ref (instance), _1, custom_data);
00540     return (depth_callback_handle_counter_++);
00541   }
00542 
00544   template<typename T> OpenNIDevice::CallbackHandle
00545   OpenNIDevice::registerIRCallback (void (T::*callback)(boost::shared_ptr<IRImage>, void* cookie), T& instance, void* custom_data) throw ()
00546   {
00547     ir_callback_[ir_callback_handle_counter_] = boost::bind ( callback,  boost::ref (instance), _1, custom_data);
00548     return (ir_callback_handle_counter_++);
00549   }
00550 
00551 }
00552 #endif // __OPENNI_IDEVICE_H__
00553 #endif // HAVE_OPENNI