openni_device.cpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011 Willow Garage, Inc.
5  * Suat Gedikli <gedikli@willowgarage.com>
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
41 #include <iostream>
42 #include <limits>
43 #include <sstream>
44 #include <map>
45 #include <vector>
46 
47 using std::vector;
48 using std::map;
49 using namespace boost;
50 
51 namespace openni_wrapper
52 {
53 
54 OpenNIDevice::OpenNIDevice (xn::Context& context, const xn::NodeInfo& device_node, const xn::NodeInfo& image_node, const xn::NodeInfo& depth_node, const xn::NodeInfo& ir_node) throw (OpenNIException)
55  : context_ (context)
56  , device_node_info_ (device_node)
57 {
58  // create the production nodes
59  XnStatus status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(depth_node));
60  if (status != XN_STATUS_OK)
61  THROW_OPENNI_EXCEPTION ("creating depth generator failed. Reason: %s", xnGetStatusString (status));
62 
63  status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(image_node));
64  if (status != XN_STATUS_OK)
65  THROW_OPENNI_EXCEPTION ("creating image generator failed. Reason: %s", xnGetStatusString (status));
66 
67  status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(ir_node));
68  if (status != XN_STATUS_OK)
69  THROW_OPENNI_EXCEPTION ("creating IR generator failed. Reason: %s", xnGetStatusString (status));
70 
71  // get production node instances
72  status = depth_node.GetInstance (depth_generator_);
73  if (status != XN_STATUS_OK)
74  THROW_OPENNI_EXCEPTION ("creating depth generator instance failed. Reason: %s", xnGetStatusString (status));
75 
76  status = image_node.GetInstance (image_generator_);
77  if (status != XN_STATUS_OK)
78  THROW_OPENNI_EXCEPTION ("creating image generator instance failed. Reason: %s", xnGetStatusString (status));
79 
80  status = ir_node.GetInstance (ir_generator_);
81  if (status != XN_STATUS_OK)
82  THROW_OPENNI_EXCEPTION ("creating IR generator instance failed. Reason: %s", xnGetStatusString (status));
83 
84  ir_generator_.RegisterToNewDataAvailable ((xn::StateChangedHandler)NewIRDataAvailable, this, ir_callback_handle_);
85 
86  depth_generator_.RegisterToNewDataAvailable ((xn::StateChangedHandler)NewDepthDataAvailable, this, depth_callback_handle_);
87  image_generator_.RegisterToNewDataAvailable ((xn::StateChangedHandler)NewImageDataAvailable, this, image_callback_handle_);
88 
89  Init ();
90 }
91 
92 OpenNIDevice::OpenNIDevice (xn::Context& context, const xn::NodeInfo& device_node, const xn::NodeInfo& depth_node, const xn::NodeInfo& ir_node) throw (OpenNIException)
93  : context_ (context)
94  , device_node_info_ (device_node)
95 {
96  // create the production nodes
97  XnStatus status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(depth_node));
98  if (status != XN_STATUS_OK)
99  THROW_OPENNI_EXCEPTION ("creating depth generator failed. Reason: %s", xnGetStatusString (status));
100 
101  status = context_.CreateProductionTree (const_cast<xn::NodeInfo&>(ir_node));
102  if (status != XN_STATUS_OK)
103  THROW_OPENNI_EXCEPTION ("creating IR generator failed. Reason: %s", xnGetStatusString (status));
104 
105  // get production node instances
106  status = depth_node.GetInstance (depth_generator_);
107  if (status != XN_STATUS_OK)
108  THROW_OPENNI_EXCEPTION ("creating depth generator instance failed. Reason: %s", xnGetStatusString (status));
109 
110  status = ir_node.GetInstance (ir_generator_);
111  if (status != XN_STATUS_OK)
112  THROW_OPENNI_EXCEPTION ("creating IR generator instance failed. Reason: %s", xnGetStatusString (status));
113 
114  ir_generator_.RegisterToNewDataAvailable ((xn::StateChangedHandler)NewIRDataAvailable, this, ir_callback_handle_);
115 
116  depth_generator_.RegisterToNewDataAvailable ((xn::StateChangedHandler)NewDepthDataAvailable, this, depth_callback_handle_);
117  // set up rest
118  Init ();
119 }
120 
121 // For ONI Player devices
122 OpenNIDevice::OpenNIDevice (xn::Context& context) throw (OpenNIException)
123  : context_ (context)
124  , device_node_info_ (0)
125 {
126 }
127 
128 OpenNIDevice::~OpenNIDevice () throw ()
129 {
130  shutdown ();
131 }
132 
133 void OpenNIDevice::shutdown ()
134 {
135  {
136  // Lock out all the XxxDataThreadFunction threads
137  boost::lock_guard<boost::mutex> image_guard(image_mutex_);
138  boost::lock_guard<boost::mutex> depth_guard(depth_mutex_);
139  boost::lock_guard<boost::mutex> ir_guard(ir_mutex_);
140 
141  // Stop streams
142  if (image_generator_.IsValid() && image_generator_.IsGenerating ())
143  image_generator_.StopGenerating ();
144 
145  if (depth_generator_.IsValid () && depth_generator_.IsGenerating ())
146  depth_generator_.StopGenerating ();
147 
148  if (ir_generator_.IsValid () && ir_generator_.IsGenerating ())
149  ir_generator_.StopGenerating ();
150 
151  // On wakeup, each data thread will check quit_ and exit
152  quit_ = true;
153  }
154 
155  // Wake up, time to die
156  depth_condition_.notify_all ();
157  image_condition_.notify_all ();
158  ir_condition_.notify_all ();
159  data_threads_.join_all ();
160 }
161 
162 void OpenNIDevice::Init () throw (OpenNIException)
163 {
164  quit_ = false;
165  XnDouble pixel_size;
166 
167  // set Depth resolution here only once... since no other mode for kinect is available -> deactivating setDepthResolution method!
168  if (hasDepthStream ())
169  {
170  unique_lock<mutex> depth_lock (depth_mutex_);
171  XnStatus status = depth_generator_.GetRealProperty ("ZPPS", pixel_size);
172  if (status != XN_STATUS_OK)
173  THROW_OPENNI_EXCEPTION ("reading the pixel size of IR camera failed. Reason: %s", xnGetStatusString (status));
174 
175  XnUInt64 depth_focal_length_SXGA;
176  status = depth_generator_.GetIntProperty ("ZPD", depth_focal_length_SXGA);
177  if (status != XN_STATUS_OK)
178  THROW_OPENNI_EXCEPTION ("reading the focal length of IR camera failed. Reason: %s", xnGetStatusString (status));
179 
180  XnDouble baseline;
181  status = depth_generator_.GetRealProperty ("LDDIS", baseline);
182  if (status != XN_STATUS_OK)
183  THROW_OPENNI_EXCEPTION ("reading the baseline failed. Reason: %s", xnGetStatusString (status));
184 
185  status = depth_generator_.GetIntProperty ("ShadowValue", shadow_value_);
186  if (status != XN_STATUS_OK)
187  THROW_OPENNI_EXCEPTION ("reading the value for pixels in shadow regions failed. Reason: %s", xnGetStatusString (status));
188 
189  status = depth_generator_.GetIntProperty ("NoSampleValue", no_sample_value_);
190  if (status != XN_STATUS_OK)
191  THROW_OPENNI_EXCEPTION ("reading the value for pixels with no depth estimation failed. Reason: %s", xnGetStatusString (status));
192 
193  // baseline from cm -> meters
194  baseline_ = (float)(baseline * 0.01);
195 
196  //focal length from mm -> pixels (valid for 1280x1024)
197  depth_focal_length_SXGA_ = (float)depth_focal_length_SXGA / pixel_size;
198 
199  data_threads_.create_thread (boost::bind (&OpenNIDevice::DepthDataThreadFunction, this));
200  }
201 
202  if (hasImageStream ())
203  {
204  lock_guard<mutex> image_lock (image_mutex_);
205  data_threads_.create_thread (boost::bind (&OpenNIDevice::ImageDataThreadFunction, this));
206  }
207 
208  if (hasIRStream ())
209  {
210  lock_guard<mutex> ir_lock (ir_mutex_);
211  data_threads_.create_thread (boost::bind (&OpenNIDevice::IRDataThreadFunction, this));
212  }
213 }
214 
215 void OpenNIDevice::startImageStream () throw (OpenNIException)
216 {
217  if (hasImageStream ())
218  {
219  lock_guard<mutex> image_lock (image_mutex_);
220  if (!image_generator_.IsGenerating ())
221  {
222  XnStatus status = image_generator_.StartGenerating ();
223  if (status != XN_STATUS_OK)
224  THROW_OPENNI_EXCEPTION ("starting image stream failed. Reason: %s", xnGetStatusString (status));
225  }
226  }
227  else
228  THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
229 }
230 
231 void OpenNIDevice::stopImageStream () throw (OpenNIException)
232 {
233  if (hasImageStream ())
234  {
235  lock_guard<mutex> image_lock (image_mutex_);
236  if (image_generator_.IsGenerating ())
237  {
238  XnStatus status = image_generator_.StopGenerating ();
239  if (status != XN_STATUS_OK)
240  THROW_OPENNI_EXCEPTION ("stopping image stream failed. Reason: %s", xnGetStatusString (status));
241  }
242  }
243  else
244  THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
245 }
246 
247 void OpenNIDevice::startDepthStream () throw (OpenNIException)
248 {
249  if (hasDepthStream ())
250  {
251  lock_guard<mutex> depth_lock (depth_mutex_);
252  if (!depth_generator_.IsGenerating ())
253  {
254  XnStatus status = depth_generator_.StartGenerating ();
255 
256  if (status != XN_STATUS_OK)
257  THROW_OPENNI_EXCEPTION ("starting depth stream failed. Reason: %s", xnGetStatusString (status));
258  }
259  }
260  else
261  THROW_OPENNI_EXCEPTION ("Device does not provide a depth stream");
262 }
263 
264 void OpenNIDevice::stopDepthStream () throw (OpenNIException)
265 {
266  if (hasDepthStream ())
267  {
268  lock_guard<mutex> depth_lock (depth_mutex_);
269  if (depth_generator_.IsGenerating ())
270  {
271  XnStatus status = depth_generator_.StopGenerating ();
272 
273  if (status != XN_STATUS_OK)
274  THROW_OPENNI_EXCEPTION ("stopping depth stream failed. Reason: %s", xnGetStatusString (status));
275  }
276  }
277  else
278  THROW_OPENNI_EXCEPTION ("Device does not provide a depth stream");
279 }
280 
281 void OpenNIDevice::startIRStream () throw (OpenNIException)
282 {
283  if (hasIRStream ())
284  {
285  lock_guard<mutex> ir_lock (ir_mutex_);
286  if (!ir_generator_.IsGenerating ())
287  {
288  XnStatus status = ir_generator_.StartGenerating ();
289 
290  if (status != XN_STATUS_OK)
291  THROW_OPENNI_EXCEPTION ("starting IR stream failed. Reason: %s", xnGetStatusString (status));
292  }
293  }
294  else
295  THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
296 }
297 
298 void OpenNIDevice::stopIRStream () throw (OpenNIException)
299 {
300  if (hasIRStream ())
301  {
302  lock_guard<mutex> ir_lock (ir_mutex_);
303  if (ir_generator_.IsGenerating ())
304  {
305  XnStatus status = ir_generator_.StopGenerating ();
306 
307  if (status != XN_STATUS_OK)
308  THROW_OPENNI_EXCEPTION ("stopping IR stream failed. Reason: %s", xnGetStatusString (status));
309  }
310  }
311  else
312  THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
313 }
314 
315 bool OpenNIDevice::isImageStreamRunning () const throw (OpenNIException)
316 {
317  lock_guard<mutex> image_lock (image_mutex_);
318  return ( image_generator_.IsValid () && image_generator_.IsGenerating ());
319 }
320 
321 bool OpenNIDevice::isDepthStreamRunning () const throw (OpenNIException)
322 {
323  lock_guard<mutex> depth_lock (depth_mutex_);
324  return ( depth_generator_.IsValid () && depth_generator_.IsGenerating ());
325 }
326 
327 bool OpenNIDevice::isIRStreamRunning () const throw (OpenNIException)
328 {
329  lock_guard<mutex> ir_lock (ir_mutex_);
330  return ( ir_generator_.IsValid () && ir_generator_.IsGenerating ());
331 }
332 
333 bool OpenNIDevice::hasImageStream () const throw ()
334 {
335  lock_guard<mutex> lock (image_mutex_);
336  return image_generator_.IsValid ();
337  //return (available_image_modes_.size() != 0);
338 }
339 
340 bool OpenNIDevice::hasDepthStream () const throw ()
341 {
342  lock_guard<mutex> lock (depth_mutex_);
343  return depth_generator_.IsValid ();
344  //return (available_depth_modes_.size() != 0);
345 }
346 
347 bool OpenNIDevice::hasIRStream () const throw ()
348 {
349  lock_guard<mutex> ir_lock (ir_mutex_);
350  return ir_generator_.IsValid ();
351 }
352 
353 void OpenNIDevice::setDepthRegistration (bool on_off) throw (OpenNIException)
354 {
355  if (hasDepthStream () && hasImageStream())
356  {
357  lock_guard<mutex> image_lock (image_mutex_);
358  lock_guard<mutex> depth_lock (depth_mutex_);
359  if (on_off && !depth_generator_.GetAlternativeViewPointCap ().IsViewPointAs (image_generator_))
360  {
361  if (depth_generator_.GetAlternativeViewPointCap ().IsViewPointSupported (image_generator_))
362  {
363  XnStatus status = depth_generator_.GetAlternativeViewPointCap ().SetViewPoint (image_generator_);
364  if (status != XN_STATUS_OK)
365  THROW_OPENNI_EXCEPTION ("turning registration on failed. Reason: %s", xnGetStatusString (status));
366  }
367  else
368  THROW_OPENNI_EXCEPTION ("turning registration on failed. Reason: unsopported viewpoint");
369  }
370  else if (!on_off)
371  {
372  XnStatus status = depth_generator_.GetAlternativeViewPointCap ().ResetViewPoint ();
373 
374  if (status != XN_STATUS_OK)
375  THROW_OPENNI_EXCEPTION ("turning registration off failed. Reason: %s", xnGetStatusString (status));
376  }
377  }
378  else
379  THROW_OPENNI_EXCEPTION ("Device does not provide image + depth stream");
380 }
381 
382 bool OpenNIDevice::isDepthRegistered () const throw (OpenNIException)
383 {
384  if (hasDepthStream () && hasImageStream() )
385  {
386  xn::DepthGenerator& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
387  xn::ImageGenerator& image_generator = const_cast<xn::ImageGenerator&>(image_generator_);
388 
389  lock_guard<mutex> image_lock (image_mutex_);
390  lock_guard<mutex> depth_lock (depth_mutex_);
391  return (depth_generator.GetAlternativeViewPointCap ().IsViewPointAs (image_generator));
392  }
393  return false;
394 }
395 
396 bool OpenNIDevice::isDepthRegistrationSupported () const throw (OpenNIException)
397 {
398  lock_guard<mutex> image_lock (image_mutex_);
399  lock_guard<mutex> depth_lock (depth_mutex_);
400  xn::ImageGenerator& image_generator = const_cast<xn::ImageGenerator&> (image_generator_);
401  return ( depth_generator_.IsValid() && image_generator_.IsValid() && depth_generator_.GetAlternativeViewPointCap().IsViewPointSupported(image_generator));
402 }
403 
404 bool OpenNIDevice::isSynchronizationSupported () const throw ()
405 {
406  lock_guard<mutex> image_lock (image_mutex_);
407  lock_guard<mutex> depth_lock (depth_mutex_);
408  return ( depth_generator_.IsValid() && image_generator_.IsValid() && depth_generator_.IsCapabilitySupported (XN_CAPABILITY_FRAME_SYNC));
409 }
410 
411 void OpenNIDevice::setSynchronization (bool on_off) throw (OpenNIException)
412 {
413  if (hasDepthStream () && hasImageStream())
414  {
415  lock_guard<mutex> image_lock (image_mutex_);
416  lock_guard<mutex> depth_lock (depth_mutex_);
417  XnStatus status;
418 
419  if (on_off && !depth_generator_.GetFrameSyncCap ().IsFrameSyncedWith (image_generator_))
420  {
421  status = depth_generator_.GetFrameSyncCap ().FrameSyncWith (image_generator_);
422  if (status != XN_STATUS_OK)
423  THROW_OPENNI_EXCEPTION ("could not turn on frame synchronization. Reason: %s", xnGetStatusString (status));
424  }
425  else if (!on_off && depth_generator_.GetFrameSyncCap ().IsFrameSyncedWith (image_generator_))
426  {
427  status = depth_generator_.GetFrameSyncCap ().StopFrameSyncWith (image_generator_);
428  if (status != XN_STATUS_OK)
429  THROW_OPENNI_EXCEPTION ("could not turn off frame synchronization. Reason: %s", xnGetStatusString (status));
430  }
431  }
432  else
433  THROW_OPENNI_EXCEPTION ("Device does not provide image + depth stream");
434 }
435 
436 bool OpenNIDevice::isSynchronized () const throw (OpenNIException)
437 {
438  if (hasDepthStream () && hasImageStream())
439  {
440  lock_guard<mutex> image_lock (image_mutex_);
441  lock_guard<mutex> depth_lock (depth_mutex_);
442  xn::DepthGenerator& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
443  xn::ImageGenerator& image_generator = const_cast<xn::ImageGenerator&>(image_generator_);
444  return (depth_generator.GetFrameSyncCap ().CanFrameSyncWith (image_generator) && depth_generator.GetFrameSyncCap ().IsFrameSyncedWith (image_generator));
445  }
446  else
447  return false;
448 }
449 
450 bool OpenNIDevice::isDepthCroppingSupported () const throw ()
451 {
452  lock_guard<mutex> depth_lock (depth_mutex_);
453  return ( image_generator_.IsValid() && depth_generator_.IsCapabilitySupported (XN_CAPABILITY_CROPPING) );
454 }
455 
456 bool OpenNIDevice::isDepthCropped () const throw (OpenNIException)
457 {
458  if (hasDepthStream ())
459  {
460  lock_guard<mutex> depth_lock (depth_mutex_);
461  XnCropping cropping;
462  xn::DepthGenerator& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
463  XnStatus status = depth_generator.GetCroppingCap ().GetCropping (cropping);
464  if (status != XN_STATUS_OK)
465  THROW_OPENNI_EXCEPTION ("could not read cropping information for depth stream. Reason: %s", xnGetStatusString (status));
466 
467  return cropping.bEnabled;
468  }
469  return false;
470 }
471 
472 void OpenNIDevice::setDepthCropping (unsigned x, unsigned y, unsigned width, unsigned height) throw (OpenNIException)
473 {
474  if (hasDepthStream ())
475  {
476  lock_guard<mutex> depth_lock (depth_mutex_);
477  XnCropping cropping;
478  cropping.nXOffset = x;
479  cropping.nYOffset = y;
480  cropping.nXSize = width;
481  cropping.nYSize = height;
482 
483  cropping.bEnabled = (width != 0 && height != 0);
484  XnStatus status = depth_generator_.GetCroppingCap ().SetCropping (cropping);
485  if (status != XN_STATUS_OK)
486  THROW_OPENNI_EXCEPTION ("could not set cropping information for depth stream. Reason: %s", xnGetStatusString (status));
487  }
488  else
489  THROW_OPENNI_EXCEPTION ("Device does not provide depth stream");
490 }
491 
492 void OpenNIDevice::ImageDataThreadFunction () throw (OpenNIException)
493 {
494  while (true)
495  {
496  // lock before checking running flag
497  unique_lock<mutex> image_lock (image_mutex_);
498  if (quit_)
499  return;
500  image_condition_.wait (image_lock);
501  if (quit_)
502  return;
503 
504  image_generator_.WaitAndUpdateData ();
505  xn::ImageMetaData image_md;
506  image_generator_.GetMetaData (image_md);
507  boost::shared_ptr<xn::ImageMetaData> image_data (new xn::ImageMetaData);
508  XnStatus xs = image_data->CopyFrom (image_md);
509  image_lock.unlock ();
510 
511  if (xs != XN_STATUS_OK)
512  continue;
513 
514  boost::shared_ptr<Image> image = getCurrentImage (image_data);
515  for (map< OpenNIDevice::CallbackHandle, ActualImageCallbackFunction >::iterator callbackIt = image_callback_.begin (); callbackIt != image_callback_.end (); ++callbackIt)
516  {
517  callbackIt->second.operator()(image);
518  }
519  }
520 }
521 
522 void OpenNIDevice::DepthDataThreadFunction () throw (OpenNIException)
523 {
524  while (true)
525  {
526  // lock before checking running flag
527  unique_lock<mutex> depth_lock (depth_mutex_);
528  if (quit_)
529  return;
530  depth_condition_.wait (depth_lock);
531  if (quit_)
532  return;
533 
534  depth_generator_.WaitAndUpdateData ();
535  xn::DepthMetaData image_md;
536  depth_generator_.GetMetaData (image_md);
537  boost::shared_ptr<xn::DepthMetaData> depth_data (new xn::DepthMetaData);
538  XnStatus xs = depth_data->CopyFrom (image_md);
539  depth_lock.unlock ();
540 
541  if (xs != XN_STATUS_OK)
542  continue;
543 
544  boost::shared_ptr<DepthImage> depth_image ( new DepthImage (depth_data, baseline_, getDepthFocalLength (), shadow_value_, no_sample_value_) );
545 
546  for (map< OpenNIDevice::CallbackHandle, ActualDepthImageCallbackFunction >::iterator callbackIt = depth_callback_.begin ();
547  callbackIt != depth_callback_.end (); ++callbackIt)
548  {
549  callbackIt->second.operator()(depth_image);
550  }
551  }
552 }
553 
554 void OpenNIDevice::IRDataThreadFunction () throw (OpenNIException)
555 {
556  while (true)
557  {
558  // lock before checking running flag
559  unique_lock<mutex> ir_lock (ir_mutex_);
560  if (quit_)
561  return;
562  ir_condition_.wait (ir_lock);
563  if (quit_)
564  return;
565 
566  ir_generator_.WaitAndUpdateData ();
567  xn::IRMetaData image_md;
568  ir_generator_.GetMetaData (image_md);
569  boost::shared_ptr<xn::IRMetaData> ir_data (new xn::IRMetaData);
570  XnStatus xs = ir_data->CopyFrom (image_md);
571  ir_lock.unlock ();
572 
573  if (xs != XN_STATUS_OK)
574  continue;
575 
576  boost::shared_ptr<IRImage> ir_image ( new IRImage (ir_data) );
577 
578  for (map< OpenNIDevice::CallbackHandle, ActualIRImageCallbackFunction >::iterator callbackIt = ir_callback_.begin ();
579  callbackIt != ir_callback_.end (); ++callbackIt)
580  {
581  callbackIt->second.operator()(ir_image);
582  }
583  }
584 }
585 
586 void __stdcall OpenNIDevice::NewDepthDataAvailable (xn::ProductionNode& node, void* cookie) throw ()
587 {
588  OpenNIDevice* device = reinterpret_cast<OpenNIDevice*>(cookie);
589  device->depth_condition_.notify_all ();
590 }
591 
592 void __stdcall OpenNIDevice::NewImageDataAvailable (xn::ProductionNode& node, void* cookie) throw ()
593 {
594  OpenNIDevice* device = reinterpret_cast<OpenNIDevice*>(cookie);
595  device->image_condition_.notify_all ();
596 }
597 
598 void __stdcall OpenNIDevice::NewIRDataAvailable (xn::ProductionNode& node, void* cookie) throw ()
599 {
600  OpenNIDevice* device = reinterpret_cast<OpenNIDevice*>(cookie);
601  device->ir_condition_.notify_all ();
602 }
603 
604 OpenNIDevice::CallbackHandle OpenNIDevice::registerImageCallback (const ImageCallbackFunction& callback, void* custom_data) throw ()
605 {
606  if (!hasImageStream ())
607  THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
608 
609  image_callback_[image_callback_handle_counter_] = boost::bind (callback, _1, custom_data);
610  return image_callback_handle_counter_++;
611 }
612 
613 bool OpenNIDevice::unregisterImageCallback (const OpenNIDevice::CallbackHandle& callbackHandle) throw ()
614 {
615  if (!hasImageStream ())
616  THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
617 
618  return (image_callback_.erase (callbackHandle) != 0);
619 }
620 
621 OpenNIDevice::CallbackHandle OpenNIDevice::registerDepthCallback (const DepthImageCallbackFunction& callback, void* custom_data) throw ()
622 {
623  if (!hasDepthStream ())
624  THROW_OPENNI_EXCEPTION ("Device does not provide a depth image");
625 
626  depth_callback_[depth_callback_handle_counter_] = boost::bind (callback, _1, custom_data);
627  return depth_callback_handle_counter_++;
628 }
629 
630 bool OpenNIDevice::unregisterDepthCallback (const OpenNIDevice::CallbackHandle& callbackHandle) throw ()
631 {
632  if (hasDepthStream ())
633  return (depth_callback_.erase (callbackHandle) != 0);
634  else
635  THROW_OPENNI_EXCEPTION ("Device does not provide a depth image");
636  return false;
637 }
638 
639 OpenNIDevice::CallbackHandle OpenNIDevice::registerIRCallback (const IRImageCallbackFunction& callback, void* custom_data) throw ()
640 {
641  if (!hasDepthStream ())
642  THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
643 
644  ir_callback_[ir_callback_handle_counter_] = boost::bind (callback, _1, custom_data);
645  return ir_callback_handle_counter_++;
646 }
647 
648 bool OpenNIDevice::unregisterIRCallback (const OpenNIDevice::CallbackHandle& callbackHandle) throw ()
649 {
650  if (!hasDepthStream ())
651  THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
652 
653  return (ir_callback_.erase (callbackHandle) != 0);
654 }
655 
656 const char* OpenNIDevice::getSerialNumber () throw ()
657 {
658  const char* openni_serial = device_node_info_.GetInstanceName ();
659  if (strlen(openni_serial)>0 && strcmp(openni_serial, "Device1")) {
660  return openni_serial;
661  } else {
662  char *primesense_serial = (char*)malloc(XN_MAX_NAME_LENGTH); // memleak
663  context_.CreateProductionTree(device_node_info_);
664  xn::Device device;
665 
666  if(device_node_info_.GetInstance(device) != XN_STATUS_OK) {
667  THROW_OPENNI_EXCEPTION ("couldn't get device instance for reading serial no.");
668  }
669 
670  xn::DeviceIdentificationCapability d = device.GetIdentificationCap();
671 
672  d.GetSerialNumber(primesense_serial,XN_MAX_NAME_LENGTH);
673 
674  device.Release();
675  return primesense_serial;
676  }
677 }
678 
679 const char* OpenNIDevice::getConnectionString () const throw ()
680 {
681  return device_node_info_.GetCreationInfo ();
682 }
683 
684 unsigned short OpenNIDevice::getVendorID () const throw ()
685 {
686  unsigned short vendor_id;
687  unsigned short product_id;
688 
689 #ifndef _WIN32
690  unsigned char bus;
691  unsigned char address;
692 
693  sscanf (device_node_info_.GetCreationInfo(), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
694 
695 #else
696  OpenNIDriver::getDeviceType (device_node_info_.GetCreationInfo(), vendor_id, product_id);
697 #endif
698  return vendor_id;
699 }
700 
701 unsigned short OpenNIDevice::getProductID () const throw ()
702 {
703  unsigned short vendor_id;
704  unsigned short product_id;
705 #ifndef _WIN32
706  unsigned char bus;
707  unsigned char address;
708  sscanf (device_node_info_.GetCreationInfo(), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
709 
710 #else
711  OpenNIDriver::getDeviceType (device_node_info_.GetCreationInfo(), vendor_id, product_id);
712 #endif
713  return product_id;
714 }
715 
716 unsigned char OpenNIDevice::getBus () const throw ()
717 {
718  unsigned char bus = 0;
719 #ifndef _WIN32
720  unsigned short vendor_id;
721  unsigned short product_id;
722  unsigned char address;
723  sscanf (device_node_info_.GetCreationInfo(), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
724 #endif
725  return bus;
726 }
727 
728 unsigned char OpenNIDevice::getAddress () const throw ()
729 {
730  unsigned char address = 0;
731 #ifndef _WIN32
732  unsigned short vendor_id;
733  unsigned short product_id;
734  unsigned char bus;
735  sscanf (device_node_info_.GetCreationInfo(), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
736 #endif
737  return address;
738 }
739 
740 const char* OpenNIDevice::getVendorName () const throw ()
741 {
742  XnProductionNodeDescription& description = const_cast<XnProductionNodeDescription&>(device_node_info_.GetDescription ());
743  return description.strVendor;
744 }
745 
746 const char* OpenNIDevice::getProductName () const throw ()
747 {
748  XnProductionNodeDescription& description = const_cast<XnProductionNodeDescription&>(device_node_info_.GetDescription ());
749  return description.strName;
750 }
751 
752 bool OpenNIDevice::findCompatibleImageMode (const XnMapOutputMode& output_mode, XnMapOutputMode& mode) const throw (OpenNIException)
753 {
754  if (isImageModeSupported (output_mode))
755  {
756  mode = output_mode;
757  return true;
758  }
759  else
760  {
761  bool found = false;
762  for (vector<XnMapOutputMode>::const_iterator modeIt = available_image_modes_.begin (); modeIt != available_image_modes_.end (); ++modeIt)
763  {
764  if (modeIt->nFPS == output_mode.nFPS && isImageResizeSupported (modeIt->nXRes, modeIt->nYRes, output_mode.nXRes, output_mode.nYRes))
765  {
766  if (found)
767  { // check wheter the new mode is better -> smaller than the current one.
768  if (mode.nXRes * mode.nYRes > modeIt->nXRes * modeIt->nYRes )
769  mode = *modeIt;
770  }
771  else
772  {
773  mode = *modeIt;
774  found = true;
775  }
776  }
777  }
778  return found;
779  }
780 }
781 
782 bool OpenNIDevice::findCompatibleDepthMode (const XnMapOutputMode& output_mode, XnMapOutputMode& mode) const throw (OpenNIException)
783 {
784  if (isDepthModeSupported (output_mode))
785  {
786  mode = output_mode;
787  return true;
788  }
789  else
790  {
791  bool found = false;
792  for (vector<XnMapOutputMode>::const_iterator modeIt = available_depth_modes_.begin (); modeIt != available_depth_modes_.end (); ++modeIt)
793  {
794  if (modeIt->nFPS == output_mode.nFPS && isImageResizeSupported (modeIt->nXRes, modeIt->nYRes, output_mode.nXRes, output_mode.nYRes))
795  {
796  if (found)
797  { // check wheter the new mode is better -> smaller than the current one.
798  if (mode.nXRes * mode.nYRes > modeIt->nXRes * modeIt->nYRes )
799  mode = *modeIt;
800  }
801  else
802  {
803  mode = *modeIt;
804  found = true;
805  }
806  }
807  }
808  return found;
809  }
810 }
811 
812 void OpenNIDevice::enumAvailableModes () throw (OpenNIException)
813 {
814  // we use the overloaded methods from subclasses!
815  /*
816  available_image_modes_.clear ();
817  unique_lock<mutex> image_lock (image_mutex_);
818  unsigned mode_count = image_generator_.GetSupportedMapOutputModesCount ();
819  XnMapOutputMode* modes = new XnMapOutputMode[mode_count];
820  XnStatus status = image_generator_.GetSupportedMapOutputModes (modes, mode_count);
821  if (status != XN_STATUS_OK)
822  {
823  delete[] modes;
824  THROW_OPENNI_EXCEPTION ("Could not enumerate image stream output modes. Reason: %s", xnGetStatusString (status));
825  }
826  image_lock.unlock ();
827 
828  for (unsigned modeIdx = 0; modeIdx < mode_count; ++modeIdx)
829  available_image_modes_.push_back (modes[modeIdx]);
830  delete[] modes;
831 
832  available_depth_modes_.clear ();
833  unique_lock<mutex> depth_lock (depth_mutex_);
834  mode_count = depth_generator_.GetSupportedMapOutputModesCount ();
835  modes = new XnMapOutputMode[mode_count];
836  status = depth_generator_.GetSupportedMapOutputModes (modes, mode_count);
837  if (status != XN_STATUS_OK)
838  {
839  delete[] modes;
840  THROW_OPENNI_EXCEPTION ("Could not enumerate depth stream output modes. Reason: %s", xnGetStatusString (status));
841  }
842  depth_lock.unlock ();
843 
844  for (unsigned modeIdx = 0; modeIdx < mode_count; ++modeIdx)
845  available_depth_modes_.push_back (modes[modeIdx]);
846  delete[] modes;
847  */
848 }
849 
850 bool OpenNIDevice::isImageModeSupported (const XnMapOutputMode& output_mode) const throw (OpenNIException)
851 {
852  for (vector<XnMapOutputMode>::const_iterator modeIt = available_image_modes_.begin (); modeIt != available_image_modes_.end (); ++modeIt)
853  {
854  if (modeIt->nFPS == output_mode.nFPS && modeIt->nXRes == output_mode.nXRes && modeIt->nYRes == output_mode.nYRes)
855  return true;
856  }
857  return false;
858 }
859 
860 bool OpenNIDevice::isDepthModeSupported (const XnMapOutputMode& output_mode) const throw (OpenNIException)
861 {
862  for (vector<XnMapOutputMode>::const_iterator modeIt = available_depth_modes_.begin (); modeIt != available_depth_modes_.end (); ++modeIt)
863  {
864  if (modeIt->nFPS == output_mode.nFPS && modeIt->nXRes == output_mode.nXRes && modeIt->nYRes == output_mode.nYRes)
865  return true;
866  }
867  return false;
868 }
869 
870 const XnMapOutputMode& OpenNIDevice::getDefaultImageMode () const throw ()
871 {
872  return available_image_modes_[0];
873 }
874 
875 const XnMapOutputMode& OpenNIDevice::getDefaultDepthMode () const throw ()
876 {
877  return available_depth_modes_[0];
878 }
879 
880 const XnMapOutputMode& OpenNIDevice::getDefaultIRMode () const throw ()
881 {
883  return available_depth_modes_[0];
884 }
885 
886 void OpenNIDevice::setImageOutputMode (const XnMapOutputMode& output_mode) throw (OpenNIException)
887 {
888  if (hasImageStream ())
889  {
890  lock_guard<mutex> image_lock (image_mutex_);
891  XnStatus status = image_generator_.SetMapOutputMode (output_mode);
892  if (status != XN_STATUS_OK)
893  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));
894  }
895  else
896  THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
897 }
898 
899 void OpenNIDevice::setDepthOutputMode (const XnMapOutputMode& output_mode) throw (OpenNIException)
900 {
901  if (hasDepthStream ())
902  {
903  lock_guard<mutex> depth_lock (depth_mutex_);
904  XnStatus status = depth_generator_.SetMapOutputMode (output_mode);
905  if (status != XN_STATUS_OK)
906  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));
907  }
908  else
909  THROW_OPENNI_EXCEPTION ("Device does not provide a depth stream");
910 }
911 
912 void OpenNIDevice::setIROutputMode (const XnMapOutputMode& output_mode) throw (OpenNIException)
913 {
914  if (hasIRStream ())
915  {
916  lock_guard<mutex> ir_lock (ir_mutex_);
917  XnStatus status = ir_generator_.SetMapOutputMode (output_mode);
918  if (status != XN_STATUS_OK)
919  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));
920  }
921  else
922  THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
923 }
924 
925 XnMapOutputMode OpenNIDevice::getImageOutputMode () const throw (OpenNIException)
926 {
927  if (!hasImageStream ())
928  THROW_OPENNI_EXCEPTION ("Device does not provide an image stream");
929 
930  XnMapOutputMode output_mode;
931  lock_guard<mutex> image_lock (image_mutex_);
932  XnStatus status = image_generator_.GetMapOutputMode (output_mode);
933  if (status != XN_STATUS_OK)
934  THROW_OPENNI_EXCEPTION ("Could not get image stream output mode. Reason: %s", xnGetStatusString (status));
935  return output_mode;
936 }
937 
938 XnMapOutputMode OpenNIDevice::getDepthOutputMode () const throw (OpenNIException)
939 {
940  if (!hasDepthStream () )
941  THROW_OPENNI_EXCEPTION ("Device does not provide a depth stream");
942 
943  XnMapOutputMode output_mode;
944  lock_guard<mutex> depth_lock (depth_mutex_);
945  XnStatus status = depth_generator_.GetMapOutputMode (output_mode);
946  if (status != XN_STATUS_OK)
947  THROW_OPENNI_EXCEPTION ("Could not get depth stream output mode. Reason: %s", xnGetStatusString (status));
948  return output_mode;
949 }
950 
951 XnMapOutputMode OpenNIDevice::getIROutputMode () const throw (OpenNIException)
952 {
953  if (!hasIRStream ())
954  THROW_OPENNI_EXCEPTION ("Device does not provide an IR stream");
955 
956  XnMapOutputMode output_mode;
957  lock_guard<mutex> ir_lock (ir_mutex_);
958  XnStatus status = ir_generator_.GetMapOutputMode (output_mode);
959  if (status != XN_STATUS_OK)
960  THROW_OPENNI_EXCEPTION ("Could not get IR stream output mode. Reason: %s", xnGetStatusString (status));
961  return output_mode;
962 }
963 
964 // This magic value is taken from a calibration routine, unless calibrated params are not supported we rely on thsi value!
965 const float OpenNIDevice::rgb_focal_length_SXGA_ = 1050;
966 } // namespace
void notify_all() BOOST_NOEXCEPT
#define THROW_OPENNI_EXCEPTION(format,...)
boost::condition_variable depth_condition_
boost::function< void(boost::shared_ptr< IRImage >, void *cookie) > IRImageCallbackFunction
Definition: openni_device.h:71
General exception class.
boost::condition_variable ir_condition_
string status
Definition: test_launch.py:51
#define __stdcall
Definition: openni_device.h:53
boost::condition_variable image_condition_
boost::function< void(boost::shared_ptr< DepthImage >, void *cookie) > DepthImageCallbackFunction
Definition: openni_device.h:70
boost::function< void(boost::shared_ptr< Image >, void *cookie) > ImageCallbackFunction
Definition: openni_device.h:69
Class representing an astract device for Primesense or MS Kinect devices.
Definition: openni_device.h:66
This class provides methods to fill a depth or disparity image.
Class containing just a reference to IR meta data.
def callback(data, args)
Definition: test_launch.py:14


openni_camera
Author(s): Patrick Mihelich, Suat Gedikli, Radu Bogdan Rusu
autogenerated on Wed Jun 5 2019 20:15:22