Point Cloud Library (PCL)  1.7.0
/tmp/buildd/pcl-1.7-1.7.0/io/include/pcl/io/openni_camera/openni_device.h
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 the copyright holder(s) 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 "openni.h"
00048 
00049 #include <pcl/io/boost.h>
00050 #include <pcl/pcl_macros.h>
00051 
00052 
00053 /// @todo Get rid of all exception-specifications, these are useless and soon to be deprecated
00054 
00055 #ifndef _WIN32
00056 #define __stdcall
00057 #endif
00058 
00059 namespace openni_wrapper
00060 {
00061   class Image;
00062   class DepthImage;
00063   class IRImage;
00064 
00065   /** \brief Class representing an astract device for OpenNI devices: Primesense PSDK, Microsoft Kinect, Asus Xtion Pro/Live.
00066     * \author Suat Gedikli
00067     * \ingroup io
00068     */
00069   class PCL_EXPORTS OpenNIDevice
00070   {
00071     public:
00072       typedef enum
00073       {
00074         OpenNI_shift_values = 0, // Shift values (disparity)
00075         OpenNI_12_bit_depth = 1, // Default mode: regular 12-bit depth
00076       } DepthMode;
00077 
00078       typedef boost::function<void(boost::shared_ptr<Image>, void* cookie) > ImageCallbackFunction;
00079       typedef boost::function<void(boost::shared_ptr<DepthImage>, void* cookie) > DepthImageCallbackFunction;
00080       typedef boost::function<void(boost::shared_ptr<IRImage>, void* cookie) > IRImageCallbackFunction;
00081       typedef unsigned CallbackHandle;
00082 
00083     public:
00084 
00085       /** \brief virtual destructor. Never throws an exception. */
00086       virtual ~OpenNIDevice () throw ();
00087 
00088       /** \brief finds an image output mode that can be used to retrieve images in desired output mode.
00089         *        e.g If device just supports VGA at 30Hz, then the desired mode QVGA at 30Hz would be possible by down sampling,
00090         *        but the modes VGA at 25Hz and SXGA at 30Hz would not be compatible.
00091         * \param[in] output_mode the desired output mode
00092         * \param[out] mode the compatible mode that the device natively supports.
00093         * \return true, if a compatible mode could be found, false otherwise.
00094         */
00095       bool 
00096       findCompatibleImageMode (const XnMapOutputMode& output_mode, XnMapOutputMode& mode ) const throw ();
00097 
00098       /** \brief finds a depth output mode that can be used to retrieve depth images in desired output mode.
00099         *        e.g If device just supports VGA at 30Hz, then a desired mode of QVGA at 30Hz would be possbile by downsampling,
00100         *        but the modes VGA at 25Hz and SXGA at 30Hz would not be compatible.
00101         * \param[in] output_mode the desired output mode
00102         * \param[out] mode the compatible mode that the device natively supports.
00103         * \return true, if a compatible mode could be found, false otherwise.
00104         */
00105       bool 
00106       findCompatibleDepthMode (const XnMapOutputMode& output_mode, XnMapOutputMode& mode ) const throw ();
00107 
00108       /** \brief returns whether a given mode is natively supported by the device or not
00109         * \param[in] output_mode mode to be checked
00110         * \return true if mode natively available, false otherwise
00111         */
00112       bool 
00113       isImageModeSupported (const XnMapOutputMode& output_mode) const throw ();
00114 
00115       /** \brief returns whether a given mode is natively supported by the device or not
00116         * \param[in] output_mode mode to be checked
00117         * \return true if mode natively available, false otherwise
00118         */
00119       bool 
00120       isDepthModeSupported (const XnMapOutputMode& output_mode) const throw ();
00121 
00122       /** \brief returns the default image mode, which is simply the first entry in the list of modes
00123         * \return the default image mode
00124         */
00125       const XnMapOutputMode& 
00126       getDefaultImageMode () const throw ();
00127 
00128       /** \brief  returns the default depth mode, which is simply the first entry in the list of modes
00129         * \return the default depth mode
00130         */
00131       const XnMapOutputMode& 
00132       getDefaultDepthMode () const throw ();
00133 
00134       /** \brief  returns the default IR mode, which is simply the first entry in the list of modes
00135         * \return the default IR mode
00136         */
00137       const XnMapOutputMode& 
00138       getDefaultIRMode () const throw ();
00139 
00140       /** \brief sets the output mode of the image stream
00141         * \param[in] output_mode the desired output mode
00142         */
00143       void 
00144       setImageOutputMode (const XnMapOutputMode& output_mode);
00145 
00146       /** \brief sets the output mode of the depth stream
00147         * \param[in] output_mode the desired output mode
00148         */
00149       void 
00150       setDepthOutputMode (const XnMapOutputMode& output_mode);
00151 
00152       /** \brief sets the output mode of the IR stream
00153         * \param[in] output_mode the desired output mode
00154         */
00155       void 
00156       setIROutputMode (const XnMapOutputMode& output_mode);
00157 
00158       /** \return the current output mode of the image stream */
00159       XnMapOutputMode 
00160       getImageOutputMode () const;
00161 
00162       /** \return the current output mode of the depth stream */
00163       XnMapOutputMode 
00164       getDepthOutputMode () const;
00165 
00166       /** \return the current output mode of the IR stream */
00167       XnMapOutputMode 
00168       getIROutputMode () const;
00169 
00170       /** \brief set the depth stream registration on or off
00171         * \param[in] on_off
00172         */
00173       void 
00174       setDepthRegistration (bool on_off);
00175 
00176       /** \return whether the depth stream is registered to the RGB camera fram or not. */
00177       bool 
00178       isDepthRegistered () const throw ();
00179 
00180       /** \return whether a registration of the depth stream to the RGB camera frame is supported or not. */
00181       bool 
00182       isDepthRegistrationSupported () const throw ();
00183 
00184       /** \brief set the hardware synchronization between Depth and RGB stream on or off.
00185         * \param[in] on_off
00186         */
00187       void 
00188       setSynchronization (bool on_off);
00189 
00190       /** \return true if Depth stream is synchronized to RGB stream, false otherwise. */
00191       bool 
00192       isSynchronized () const throw ();
00193 
00194       /** \return true if the Device supports hardware synchronization between Depth and RGB streams or not. */ 
00195       virtual bool 
00196       isSynchronizationSupported () const throw ();
00197 
00198       /** \return true if depth stream is a cropped version of the native depth stream, false otherwise. */
00199       bool 
00200       isDepthCropped () const;
00201 
00202       /** \brief turn on cropping for the depth stream.
00203         * \param[in] x x-position of the rectangular subregion.
00204         * \param[in] y y-position of the rectangular subregion.
00205         * \param[in] width width of the rectangular subregion.
00206         * \param[in] height height of the rectangular subregion.
00207         */
00208       void 
00209       setDepthCropping (unsigned x, unsigned y, unsigned width, unsigned height);
00210 
00211       /** \return true if cropping of the depth stream is supported, false otherwise. */
00212       bool 
00213       isDepthCroppingSupported () const throw ();
00214 
00215       /** \brief returns the focal length for the color camera in pixels. The pixels are assumed to be square.
00216         *        Result depends on the output resolution of the image.
00217         */
00218       inline float 
00219       getImageFocalLength (int output_x_resolution = 0) const throw ();
00220 
00221       /** \brief returns the focal length for the IR camera in pixels. The pixels are assumed to be square.
00222         *        Result depends on the output resolution of the depth image.
00223         */
00224       inline float 
00225       getDepthFocalLength (int output_x_resolution = 0) const throw ();
00226 
00227       /** \return Baseline of the "stereo" frame. i.e. for PSDK compatible devices its the distance between the Projector and the IR camera. */
00228       inline float 
00229       getBaseline () const throw ();
00230 
00231       /** \brief starts the image stream. */
00232       virtual void 
00233       startImageStream ();
00234 
00235       /** \brief stops the image stream. */
00236       virtual void 
00237       stopImageStream ();
00238 
00239       /** \brief starts the depth stream. */
00240       virtual void 
00241       startDepthStream ();
00242 
00243       /** \brief stops the depth stream. */
00244       virtual void 
00245       stopDepthStream ();
00246 
00247       /** \brief starts the IR stream. */
00248       virtual void 
00249       startIRStream ();
00250 
00251       /** \brief stops the IR stream. */
00252       virtual void 
00253       stopIRStream ();
00254 
00255       /** \return true if the device supports an image stream, false otherwise. */
00256       bool 
00257       hasImageStream () const throw ();
00258 
00259       /** \return true if the device supports a depth stream, false otherwise. */
00260       bool 
00261       hasDepthStream () const throw ();
00262 
00263       /** \return true if the device supports an IR stream, false otherwise. */
00264       bool 
00265       hasIRStream () const throw ();
00266 
00267       /** \return true if the image stream is running / started, false otherwise. */
00268       virtual bool 
00269       isImageStreamRunning () const throw ();
00270 
00271       /** \return true if the depth stream is running / started, false otherwise. */
00272       virtual bool 
00273       isDepthStreamRunning () const throw ();
00274 
00275       /** \return true if the IR stream is running / started, false otherwise. */
00276       virtual bool 
00277       isIRStreamRunning () const throw ();
00278 
00279       /** \brief registers a callback function of boost::function type for the image stream with an optional user defined parameter.
00280         *        The callback will always be called with a new image and the user data "cookie".
00281         * \param[in] callback the user callback to be called if a new image is available
00282         * \param[in] cookie the cookie that needs to be passed to the callback together with the new image.
00283         * \return a callback handler that can be used to remove the user callback from list of image-stream callbacks.
00284         */
00285       CallbackHandle 
00286       registerImageCallback (const ImageCallbackFunction& callback, void* cookie = NULL) throw ();
00287 
00288       /** \brief registers a callback function for the image stream with an optional user defined parameter.
00289         *        This version is used to register a member function of any class.
00290         *        The callback will always be called with a new image and the user data "cookie".
00291         * \param[in] callback the user callback to be called if a new image is available
00292         * \param[in] cookie the cookie that needs to be passed to the callback together with the new image.
00293         * \return a callback handler that can be used to remove the user callback from list of image-stream callbacks.
00294         */
00295       template<typename T> CallbackHandle 
00296       registerImageCallback (void (T::*callback)(boost::shared_ptr<Image>, void* cookie), T& instance, void* cookie = NULL) throw ();
00297 
00298       /** \brief unregisters a callback function. i.e. removes that function from the list of image stream callbacks.
00299         * \param[in] callbackHandle the handle of the callback to unregister.
00300         * \return true, if callback was in list and could be unregistered, false otherwise.
00301         */
00302       bool 
00303       unregisterImageCallback (const CallbackHandle& callbackHandle) throw ();
00304 
00305 
00306       /** \brief registers a callback function of boost::function type for the depth stream with an optional user defined parameter.
00307         *        The callback will always be called with a new depth image and the user data "cookie".
00308         * \param[in] callback the user callback to be called if a new depth image is available
00309         * \param[in] cookie the cookie that needs to be passed to the callback together with the new depth image.
00310         * \return a callback handler that can be used to remove the user callback from list of depth-stream callbacks.
00311         */
00312       CallbackHandle 
00313       registerDepthCallback (const DepthImageCallbackFunction& callback, void* cookie = NULL) throw ();
00314 
00315       /** \brief registers a callback function for the depth stream with an optional user defined parameter.
00316         *        This version is used to register a member function of any class.
00317         *        The callback will always be called with a new depth image and the user data "cookie".
00318         * \param[in] callback the user callback to be called if a new depth image is available
00319         * \param[in] cookie the cookie that needs to be passed to the callback together with the new depth image.
00320         * \return a callback handler that can be used to remove the user callback from list of depth-stream callbacks.
00321         */
00322       template<typename T> CallbackHandle 
00323       registerDepthCallback (void (T::*callback)(boost::shared_ptr<DepthImage>, void* cookie), T& instance, void* cookie = NULL) throw ();
00324 
00325       /** \brief unregisters a callback function. i.e. removes that function from the list of depth stream callbacks.
00326         * \param[in] callbackHandle the handle of the callback to unregister.
00327         * \return true, if callback was in list and could be unregistered, false otherwise.
00328         */
00329       bool 
00330       unregisterDepthCallback (const CallbackHandle& callbackHandle) throw ();
00331 
00332       /** \brief registers a callback function of boost::function type for the IR stream with an optional user defined parameter.
00333         *        The callback will always be called with a new IR image and the user data "cookie".
00334         * \param[in] callback the user callback to be called if a new IR image is available
00335         * \param[in] cookie the cookie that needs to be passed to the callback together with the new IR image.
00336         * \return a callback handler that can be used to remove the user callback from list of IR-stream callbacks.
00337         */
00338       CallbackHandle 
00339       registerIRCallback (const IRImageCallbackFunction& callback, void* cookie = NULL) throw ();
00340 
00341       /** \brief registers a callback function for the IR stream with an optional user defined parameter.
00342         *        This version is used to register a member function of any class.
00343         *        The callback will always be called with a new IR image and the user data "cookie".
00344         * \param[in] callback the user callback to be called if a new IR image is available
00345         * \param[in] cookie the cookie that needs to be passed to the callback together with the new IR image.
00346         * \return a callback handler that can be used to remove the user callback from list of IR-stream callbacks.
00347         */
00348       template<typename T> CallbackHandle 
00349       registerIRCallback (void (T::*callback)(boost::shared_ptr<IRImage>, void* cookie), T& instance, void* cookie = NULL) throw ();
00350 
00351       /** \brief unregisters a callback function. i.e. removes that function from the list of IR stream callbacks.
00352         * \param[in] callbackHandle the handle of the callback to unregister.
00353         * \return true, if callback was in list and could be unregistered, false otherwise.
00354         */
00355       bool 
00356       unregisterIRCallback (const CallbackHandle& callbackHandle) throw ();
00357 
00358       /** \brief returns the serial number for device.
00359         * \attention This might be an empty string!!!
00360         */
00361       const char* 
00362       getSerialNumber () const throw ();
00363 
00364       /** \brief returns the connection string for current device, which has following format vendorID/productID\@BusID/DeviceID. */
00365       const char* 
00366       getConnectionString () const throw ();
00367 
00368       /** \return the Vendor name of the USB device. */
00369       const char* 
00370       getVendorName () const throw ();
00371 
00372       /** \return the product name of the USB device. */
00373       const char* 
00374       getProductName () const throw ();
00375 
00376       /** \return the vendor ID of the USB device. */
00377       unsigned short 
00378       getVendorID () const throw ();
00379 
00380       /** \return the product ID of the USB device. */
00381       unsigned short 
00382       getProductID () const throw ();
00383 
00384       /** \return the USB bus on which the device is connected. */
00385       unsigned char  
00386       getBus () const throw ();
00387 
00388       /** \return the USB Address of the device. */
00389       unsigned char  
00390       getAddress () const throw ();
00391 
00392       /** \brief Set the RGB image focal length.
00393         * \param[in] focal_length the RGB image focal length
00394         */
00395       inline void
00396       setRGBFocalLength (float focal_length)
00397       {
00398         rgb_focal_length_SXGA_ = focal_length;
00399       }
00400 
00401       /** \brief Set the depth image focal length.
00402         * \param[in] focal_length the depth image focal length
00403         */
00404       inline void
00405       setDepthFocalLength (float focal_length)
00406       {
00407         depth_focal_length_SXGA_ = focal_length;
00408       }
00409 
00410       /** \brief Set the depth output format. Use 12bit depth values or shift values.
00411         * \param[in] depth_mode the depth output format
00412         */
00413       void
00414       setDepthOutputFormat (const DepthMode& depth_mode = OpenNI_12_bit_depth);
00415 
00416       /** \brief Get the depth output format as set by the user. */
00417       XnUInt64 
00418       getDepthOutputFormat () const;
00419 
00420 
00421       /** \brief Convert shift to depth value. */
00422       pcl::uint16_t
00423       shiftToDepth (pcl::uint16_t shift_value) const
00424       {
00425         assert (shift_conversion_parameters_.init_);
00426 
00427         pcl::uint16_t ret = 0;
00428 
00429         // lookup depth value in shift lookup table
00430         if (shift_value<shift_to_depth_table_.size())
00431           ret = shift_to_depth_table_[shift_value];
00432 
00433         return ret;
00434       }
00435 
00436     private:
00437       // make OpenNIDevice non copyable
00438       OpenNIDevice (OpenNIDevice const &);
00439       OpenNIDevice& operator=(OpenNIDevice const &);
00440     protected:
00441       typedef boost::function<void(boost::shared_ptr<Image>) > ActualImageCallbackFunction;
00442       typedef boost::function<void(boost::shared_ptr<DepthImage>) > ActualDepthImageCallbackFunction;
00443       typedef boost::function<void(boost::shared_ptr<IRImage>) > ActualIRImageCallbackFunction;
00444 
00445       OpenNIDevice (xn::Context& context, const xn::NodeInfo& device_node, const xn::NodeInfo& image_node, const xn::NodeInfo& depth_node, const xn::NodeInfo& ir_node);
00446       OpenNIDevice (xn::Context& context, const xn::NodeInfo& device_node, const xn::NodeInfo& depth_node, const xn::NodeInfo& ir_node);
00447       OpenNIDevice (xn::Context& context);
00448       static void __stdcall NewDepthDataAvailable (xn::ProductionNode& node, void* cookie) throw ();
00449       static void __stdcall NewImageDataAvailable (xn::ProductionNode& node, void* cookie) throw ();
00450       static void __stdcall NewIRDataAvailable (xn::ProductionNode& node, void* cookie) throw ();
00451 
00452       // This is a workaround, since in the NewDepthDataAvailable function WaitAndUpdateData leads to a dead-lock behaviour
00453       // and retrieving image data without WaitAndUpdateData leads to incomplete images!!!
00454       void 
00455       ImageDataThreadFunction ();
00456 
00457       void 
00458       DepthDataThreadFunction ();
00459 
00460       void 
00461       IRDataThreadFunction ();
00462 
00463       virtual bool 
00464       isImageResizeSupported (unsigned input_width, unsigned input_height, unsigned output_width, unsigned output_height) const  throw () = 0;
00465 
00466       void 
00467       setRegistration (bool on_off);
00468 
00469       virtual boost::shared_ptr<Image> 
00470       getCurrentImage (boost::shared_ptr<xn::ImageMetaData> image_data) const throw () = 0;
00471 
00472       void 
00473       Init ();
00474 
00475       void InitShiftToDepthConversion();
00476       void ReadDeviceParametersFromSensorNode();
00477 
00478       struct ShiftConversion
00479       {
00480         ShiftConversion() : init_(false) {}
00481 
00482         XnUInt16 zero_plane_distance_;
00483         XnFloat zero_plane_pixel_size_;
00484         XnFloat emitter_dcmos_distace_;
00485         XnUInt32 max_shift_;
00486         XnUInt32 device_max_shift_;
00487         XnUInt32 const_shift_;
00488         XnUInt32 pixel_size_factor_;
00489         XnUInt32 param_coeff_;
00490         XnUInt32 shift_scale_;
00491         XnUInt32 min_depth_;
00492         XnUInt32 max_depth_;
00493         bool init_;
00494 
00495       } shift_conversion_parameters_;
00496 
00497       std::vector<pcl::uint16_t> shift_to_depth_table_;
00498 
00499       // holds the callback functions together with custom data
00500       // since same callback function can be registered multiple times with e.g. different custom data
00501       // we use a map structure with a handle as the key
00502       std::map<CallbackHandle, ActualImageCallbackFunction> image_callback_;
00503       std::map<CallbackHandle, ActualDepthImageCallbackFunction> depth_callback_;
00504       std::map<CallbackHandle, ActualIRImageCallbackFunction> ir_callback_;
00505 
00506       std::vector<XnMapOutputMode> available_image_modes_;
00507       std::vector<XnMapOutputMode> available_depth_modes_;
00508 
00509       /** \brief context to OpenNI driver*/
00510       xn::Context& context_;
00511       /** \brief node object for current device */
00512       xn::NodeInfo device_node_info_;
00513 
00514       /** \brief Depth generator object. */
00515       xn::DepthGenerator depth_generator_;
00516       /** \brief Image generator object. */
00517       xn::ImageGenerator image_generator_;
00518       /** \brief IR generator object. */
00519       xn::IRGenerator ir_generator_;
00520 
00521       XnCallbackHandle depth_callback_handle_;
00522       XnCallbackHandle image_callback_handle_;
00523       XnCallbackHandle ir_callback_handle_;
00524 
00525       /** \brief focal length for IR camera producing depth information in native SXGA mode */
00526       float depth_focal_length_SXGA_;
00527       /** \brief distance between the projector and the IR camera*/
00528       float baseline_;
00529       /** \brief focal length for regular camera producing color images in native SXGA mode */
00530       float rgb_focal_length_SXGA_;
00531 
00532       /** the value for shadow (occluded pixels) */
00533       XnUInt64 shadow_value_;
00534       /** the value for pixels without a valid disparity measurement */
00535       XnUInt64 no_sample_value_;
00536 
00537       OpenNIDevice::CallbackHandle image_callback_handle_counter_;
00538       OpenNIDevice::CallbackHandle depth_callback_handle_counter_;
00539       OpenNIDevice::CallbackHandle ir_callback_handle_counter_;
00540 
00541       bool quit_;
00542       mutable boost::mutex image_mutex_;
00543       mutable boost::mutex depth_mutex_;
00544       mutable boost::mutex ir_mutex_;
00545       boost::condition_variable image_condition_;
00546       boost::condition_variable depth_condition_;
00547       boost::condition_variable ir_condition_;
00548       boost::thread image_thread_;
00549       boost::thread depth_thread_;
00550       boost::thread ir_thread_;
00551   };
00552 
00553   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00554   float
00555   OpenNIDevice::getImageFocalLength (int output_x_resolution) const throw ()
00556   {
00557     if (output_x_resolution == 0)
00558       output_x_resolution = getImageOutputMode ().nXRes;
00559 
00560     float scale = static_cast<float> (output_x_resolution) / static_cast<float> (XN_SXGA_X_RES);
00561     return (rgb_focal_length_SXGA_ * scale);
00562   }
00563 
00564   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00565   float
00566   OpenNIDevice::getDepthFocalLength (int output_x_resolution) const throw ()
00567   {
00568     if (output_x_resolution == 0)
00569       output_x_resolution = getDepthOutputMode ().nXRes;
00570 
00571     float scale = static_cast<float> (output_x_resolution) / static_cast<float> (XN_SXGA_X_RES);
00572     if (isDepthRegistered ())
00573       return (rgb_focal_length_SXGA_ * scale);
00574     else
00575       return (depth_focal_length_SXGA_ * scale);
00576   }
00577 
00578   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00579   float
00580   OpenNIDevice::getBaseline () const throw ()
00581   {
00582     return (baseline_);
00583   }
00584 
00585   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00586   template<typename T> OpenNIDevice::CallbackHandle
00587   OpenNIDevice::registerImageCallback (void (T::*callback)(boost::shared_ptr<Image>, void* cookie), T& instance, void* custom_data) throw ()
00588   {
00589     image_callback_[image_callback_handle_counter_] = boost::bind (callback, boost::ref (instance), _1, custom_data);
00590     return (image_callback_handle_counter_++);
00591   }
00592 
00593   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00594   template<typename T> OpenNIDevice::CallbackHandle
00595   OpenNIDevice::registerDepthCallback (void (T::*callback)(boost::shared_ptr<DepthImage>, void* cookie), T& instance, void* custom_data) throw ()
00596   {
00597     depth_callback_[depth_callback_handle_counter_] = boost::bind ( callback,  boost::ref (instance), _1, custom_data);
00598     return (depth_callback_handle_counter_++);
00599   }
00600 
00601   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00602   template<typename T> OpenNIDevice::CallbackHandle
00603   OpenNIDevice::registerIRCallback (void (T::*callback)(boost::shared_ptr<IRImage>, void* cookie), T& instance, void* custom_data) throw ()
00604   {
00605     ir_callback_[ir_callback_handle_counter_] = boost::bind ( callback,  boost::ref (instance), _1, custom_data);
00606     return (ir_callback_handle_counter_++);
00607   }
00608 
00609 }
00610 #endif // __OPENNI_IDEVICE_H__
00611 #endif // HAVE_OPENNI