freenect_device.hpp
Go to the documentation of this file.
1 #ifndef FREENECT_DEVICE_T01IELX0
2 #define FREENECT_DEVICE_T01IELX0
3 
4 #include <boost/shared_ptr.hpp>
5 #include <boost/noncopyable.hpp>
6 #include <boost/thread/mutex.hpp>
7 #include <boost/date_time/posix_time/ptime.hpp>
8 #include <stdexcept>
9 
10 #include <libfreenect/libfreenect.h>
11 #include <libfreenect/libfreenect_registration.h>
13 
15 
16  static const std::string PRODUCT_NAME = "Xbox NUI Camera";
17  static const unsigned PRODUCT_ID = 0x2ae;
18  static const std::string VENDOR_NAME = "Microsoft";
19  static const unsigned VENDOR_ID = 0x45e;
20 
22 
23  bool isImageMode(const ImageBuffer& buffer) {
25  }
26 
27  class FreenectDriver;
28  class TiltDriver;
29 
30  class FreenectDevice : public boost::noncopyable {
31 
32  public:
33 
34  FreenectDevice(freenect_context* driver, std::string serial) {
35  openDevice(driver, serial);
37  {
38  ROS_INFO("flushDevice\n");
40  }
41  else
42  {
44  }
45  //Initialize default variables
51 
57 
58  publishers_ready_ = false;
59  }
60 
61 
63  shutdown();
64  }
65 
67  device_flush_start_time_ = boost::posix_time::microsec_clock::local_time();
68  device_flush_enabled_ = true;
69  ROS_INFO("Starting a 3s RGB and Depth stream flush.");
70  }
71 
72  void openDevice(freenect_context* driver, std::string serial) {
73  if (freenect_open_device_by_camera_serial(driver, &device_, serial.c_str()) < 0) {
74  throw std::runtime_error("[ERROR] Unable to open specified kinect");
75  }
77 
78  //freenect_set_depth_callback(device_, freenectDepthCallback);
79  //freenect_set_video_callback(device_, freenectVideoCallback);
80 
83  driver_ = driver;
84  device_serial_ = serial;
86  }
87 
88  void shutdown() {
91  }
92 
93  /* DEVICE SPECIFIC FUNCTIONS */
94 
96  unsigned getBus() const {
97  return 0;
98  }
99 
101  unsigned getAddress() const {
102  return 0;
103  }
104 
105  const char* getProductName() const {
106  return PRODUCT_NAME.c_str();
107  }
108 
109  const char* getSerialNumber() const {
110  return device_serial_.c_str();
111  }
112 
113  bool hasImageStream() const {
114  return true;
115  }
116 
117  bool hasDepthStream() const {
118  return true;
119  }
120 
121  bool hasIRStream() const {
122  return true;
123  }
124 
126  return true;
127  }
128 
130  return false;
131  }
132 
133  bool isSynchronized() const {
134  return false;
135  }
136 
137  bool setSynchronization(bool on_off) const {
138  throw std::runtime_error("[ERROR] The kinect does not support hardware synchronization");
139  }
140 
144  float getBaseline() const {
146  }
147 
148  /* CALLBACK ASSIGNMENT FUNCTIONS */
149 
150  template<typename T> void registerImageCallback (
151  void (T::*callback)(const ImageBuffer& image, void* cookie),
152  T& instance, void* cookie = NULL) {
153  image_callback_ = boost::bind(callback, boost::ref(instance), _1, cookie);
154  }
155 
156  template<typename T> void registerDepthCallback (
157  void (T::*callback)(const ImageBuffer& depth_image, void* cookie),
158  T& instance, void* cookie = NULL) {
159  depth_callback_ = boost::bind(callback, boost::ref(instance), _1, cookie);
160  }
161 
162  template<typename T> void registerIRCallback (
163  void (T::*callback)(const ImageBuffer& ir_image, void* cookie),
164  T& instance, void* cookie = NULL) {
165  ir_callback_ = boost::bind(callback, boost::ref(instance), _1, cookie);
166  }
167 
169  publishers_ready_ = true;
170  }
171 
172  /* IMAGE SETTINGS FUNCTIONS */
173 
174  OutputMode getImageOutputMode() {
175  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
177  }
178 
179  void setImageOutputMode(OutputMode mode) {
180  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
181  new_video_resolution_ = mode;
182  }
183 
184  OutputMode getDefaultImageMode() const {
186  }
187 
188  bool findCompatibleImageMode(const OutputMode& mode, OutputMode& compatible_mode) const {
189  freenect_frame_mode new_mode =
191  if (!new_mode.is_valid) {
192  compatible_mode = getDefaultImageMode();
193  return false;
194  }
195  compatible_mode = mode;
196  return true;
197  }
198 
200  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
201  //std::cout << "STOP IMAGE STREAM" << std::endl;
204  }
205 
207  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
208  //std::cout << "START IMAGE STREAM" << std::endl;
210  should_stream_video_ = true;
211  }
212 
214  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
216  }
217 
218  void stopIRStream() {
219  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
221  (isIRStreamRunning()) ? false : streaming_video_;
222  }
223 
224  void startIRStream() {
225  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
227  should_stream_video_ = true;
228  }
229 
231  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
233  }
234 
235  /* DEPTH SETTINGS FUNCTIONS */
236 
237  OutputMode getDepthOutputMode() {
238  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
240  }
241 
242  void setDepthOutputMode(OutputMode mode) {
243  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
244  new_depth_resolution_ = mode;
245  }
246 
247  OutputMode getDefaultDepthMode() const {
249  }
250 
251  bool findCompatibleDepthMode(const OutputMode& mode, OutputMode& compatible_mode) const {
252  freenect_frame_mode new_mode =
254  if (!new_mode.is_valid) {
255  compatible_mode = getDefaultDepthMode();
256  return false;
257  }
258  compatible_mode = mode;
259  return true;
260  }
261 
263  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
265  }
266 
267  void setDepthRegistration(bool enable) {
268  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
271  }
272 
274  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
275  should_stream_depth_ = false;
276  }
277 
279  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
280  should_stream_depth_ = true;
281  }
282 
284  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
286  }
287 
288  /* LIBFREENECT ASYNC CALLBACKS */
289 
291  freenect_device *dev, void *depth, uint32_t timestamp) {
292 
294  static_cast<FreenectDevice*>(freenect_get_user(dev));
295  device->depthCallback(depth);
296  }
297 
299  freenect_device *dev, void *video, uint32_t timestamp) {
300 
302  static_cast<FreenectDevice*>(freenect_get_user(dev));
303  device->videoCallback(video);
304  }
305 
306  private:
307 
308  friend class FreenectDriver;
309  friend class TiltDriver;
312  std::string device_serial_;
314 
315  boost::function<void(const ImageBuffer&)> image_callback_;
316  boost::function<void(const ImageBuffer&)> depth_callback_;
317  boost::function<void(const ImageBuffer&)> ir_callback_;
318 
324 
330 
331  /* Prevents changing settings unless the freenect thread in the driver
332  * is ready */
333  boost::recursive_mutex m_settings_;
334 
335  boost::posix_time::ptime device_flush_start_time_;
338 
339  void executeChanges() {
340  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
341  //ROS_INFO_THROTTLE(1.0, "exec changes");
342 
343  bool stop_device_flush = false;
344 
345  if (device_flush_enabled_) {
346 
347  boost::posix_time::ptime current_time =
348  boost::posix_time::microsec_clock::local_time();
349  if ((current_time - device_flush_start_time_).total_milliseconds() > 3000) {
350  device_flush_enabled_ = false;
351  stop_device_flush = true;
352  ROS_INFO("Stopping device RGB and Depth stream flush.");
353  }
354  }
355 
356  bool change_video_settings =
357  video_buffer_.metadata.video_format != new_video_format_ ||
358  video_buffer_.metadata.resolution != new_video_resolution_ ||
359  ((streaming_video_ != should_stream_video_) && !device_flush_enabled_) ||
360  device_flush_enabled_ && !streaming_video_ ||
361  stop_device_flush;
362 
363  if (change_video_settings) {
365  // Stop video stream
366  if (streaming_video_) {
367  //ROS_INFO(" stopping video images...");
368  freenect_stop_video(device_);
369  streaming_video_ = false;
370  return;
371  }
372  // Allocate buffer for video if settings have changed
373  if (video_buffer_.metadata.resolution != new_video_resolution_ ||
374  video_buffer_.metadata.video_format != new_video_format_) {
375  try {
376  allocateBufferVideo(video_buffer_, new_video_format_,
377  new_video_resolution_, registration_);
378  } catch (std::runtime_error& e) {
379  printf("[ERROR] Unsupported video format/resolution provided. %s\n",
380  e.what());
381  printf("[INFO] Setting default settings (RGB/VGA)\n");
383  FREENECT_RESOLUTION_MEDIUM, registration_);
384  }
385  freenect_set_video_mode(device_, video_buffer_.metadata);
386  freenect_set_video_buffer(device_, video_buffer_.image_buffer.get());
387  new_video_resolution_ = video_buffer_.metadata.resolution;
388  new_video_format_ = video_buffer_.metadata.video_format;
389  }
390  // Restart stream if required
391  if (should_stream_video_ || device_flush_enabled_) {
392  int rgb_out = freenect_start_video(device_);
393  //ROS_INFO(" streaming rgb images... %i", rgb_out);
394  streaming_video_ = true;
395  }
396 
397  // Don't make more than 1 change at a time
398  return;
399  }
400 
401  bool change_depth_settings =
402  depth_buffer_.metadata.depth_format != new_depth_format_ ||
403  depth_buffer_.metadata.resolution != new_depth_resolution_ ||
404  ((streaming_depth_ != should_stream_depth_) && !device_flush_enabled_) ||
405  device_flush_enabled_ && !streaming_depth_ ||
406  stop_device_flush;
407 
408  if (change_depth_settings) {
409  //ROS_INFO("change depth called");
410  // Stop depth stream
411  if (streaming_depth_) {
412  //ROS_INFO(" stopping depth images...");
413  freenect_stop_depth(device_);
414  streaming_depth_ = false;
415  return;
416  }
417  // Allocate buffer for depth if settings have changed
418  if (depth_buffer_.metadata.resolution != new_depth_resolution_ ||
419  depth_buffer_.metadata.depth_format != new_depth_format_) {
420  try {
421  allocateBufferDepth(depth_buffer_, new_depth_format_,
422  new_depth_resolution_, registration_);
423  } catch (std::runtime_error& e) {
424  printf("[ERROR] Unsupported depth format/resolution provided. %s\n",
425  e.what());
426  printf("[INFO] Setting default settings (depth registered/VGA)\n");
427  allocateBufferDepth(depth_buffer_, FREENECT_DEPTH_MM,
428  FREENECT_RESOLUTION_MEDIUM, registration_);
429  }
430  freenect_set_depth_mode(device_, depth_buffer_.metadata);
431  freenect_set_depth_buffer(device_, depth_buffer_.image_buffer.get());
432  new_depth_resolution_ = depth_buffer_.metadata.resolution;
433  new_depth_format_ = depth_buffer_.metadata.depth_format;
434  }
435  // Restart stream if required
436  if (should_stream_depth_ || device_flush_enabled_) {
437  int depth_out = freenect_start_depth(device_);
438  //ROS_INFO(" streaming depth images... %i", depth_out);
439  streaming_depth_ = true;
440  return;
441  }
442  }
443  }
444 
446  boost::lock_guard<boost::recursive_mutex> lock(m_settings_);
447  return isImageMode(video_buffer_);
448  }
449 
450  void depthCallback(void* depth) {
451  boost::lock_guard<boost::mutex> buffer_lock(depth_buffer_.mutex);
452  assert(depth == depth_buffer_.image_buffer.get());
453  if (publishers_ready_) {
454  depth_callback_.operator()(depth_buffer_);
455  }
456  }
457 
458  void videoCallback(void* video) {
459  boost::lock_guard<boost::mutex> buffer_lock(video_buffer_.mutex);
460  assert(video == video_buffer_.image_buffer.get());
461  if (publishers_ready_) {
462  if (isImageMode(video_buffer_)) {
463  image_callback_.operator()(video_buffer_);
464  } else {
465  ir_callback_.operator()(video_buffer_);
466  }
467  }
468  }
469 
470  };
471 }
472 
473 #endif /* end of include guard: FREENECT_DEVICE_T01IELX0 */
void allocateBufferDepth(ImageBuffer &buffer, const freenect_depth_format &format, const freenect_resolution &resolution, const freenect_registration &registration)
FREENECTAPI int freenect_destroy_registration(freenect_registration *reg)
int freenect_set_depth_buffer(freenect_device *dev, void *buf)
void allocateBufferVideo(ImageBuffer &buffer, const freenect_video_format &format, const freenect_resolution &resolution, const freenect_registration &registration)
freenect_zero_plane_info zero_plane_info
static const unsigned PRODUCT_ID
freenect_video_format
FreenectDevice(freenect_context *driver, std::string serial)
FREENECT_RESOLUTION_DUMMY
void freenect_set_video_callback(freenect_device *dev, freenect_video_cb cb)
int freenect_start_video(freenect_device *dev)
boost::posix_time::ptime device_flush_start_time_
int freenect_stop_video(freenect_device *dev)
void openDevice(freenect_context *driver, std::string serial)
FREENECT_VIDEO_IR_10BIT
void registerImageCallback(void(T::*callback)(const ImageBuffer &image, void *cookie), T &instance, void *cookie=NULL)
Holds an image buffer with all the metadata required to transmit the image over ROS channels...
int freenect_set_depth_mode(freenect_device *dev, const freenect_frame_mode mode)
int freenect_set_video_mode(freenect_device *dev, const freenect_frame_mode mode)
freenect_depth_format
static const unsigned VENDOR_ID
freenect_frame_mode freenect_find_video_mode(freenect_resolution res, freenect_video_format fmt)
boost::function< void(const ImageBuffer &)> ir_callback_
freenect_resolution OutputMode
FREENECT_DEPTH_DUMMY
bool findCompatibleImageMode(const OutputMode &mode, OutputMode &compatible_mode) const
FREENECTAPI freenect_registration freenect_copy_registration(freenect_device *dev)
FREENECTAPI int freenect_open_device_by_camera_serial(freenect_context *ctx, freenect_device **dev, const char *camera_serial)
int freenect_set_video_buffer(freenect_device *dev, void *buf)
#define ROS_INFO(...)
FREENECTAPI freenect_device_flags freenect_enabled_subdevices(freenect_context *ctx)
FREENECT_VIDEO_DUMMY
MyFreenectDevice * device
freenect_frame_mode freenect_find_depth_mode(freenect_resolution res, freenect_depth_format fmt)
bool findCompatibleDepthMode(const OutputMode &mode, OutputMode &compatible_mode) const
boost::shared_array< unsigned char > image_buffer
static const std::string PRODUCT_NAME
void registerDepthCallback(void(T::*callback)(const ImageBuffer &depth_image, void *cookie), T &instance, void *cookie=NULL)
FREENECTAPI void * freenect_get_user(freenect_device *dev)
FREENECT_VIDEO_BAYER
bool isImageMode(const ImageBuffer &buffer)
FREENECT_DEVICE_CAMERA
void registerIRCallback(void(T::*callback)(const ImageBuffer &ir_image, void *cookie), T &instance, void *cookie=NULL)
freenect_resolution
int freenect_start_depth(freenect_device *dev)
FREENECT_RESOLUTION_MEDIUM
boost::function< void(const ImageBuffer &)> depth_callback_
unsigned int uint32_t
FREENECT_DEPTH_MM
int freenect_stop_depth(freenect_device *dev)
static void freenectVideoCallback(freenect_device *dev, void *video, uint32_t timestamp)
boost::function< void(const ImageBuffer &)> image_callback_
FREENECTAPI void freenect_set_user(freenect_device *dev, void *user)
freenect_resolution resolution
freenect_depth_format depth_format
FREENECT_DEPTH_REGISTERED
static void freenectDepthCallback(freenect_device *dev, void *depth, uint32_t timestamp)
void freenect_set_depth_callback(freenect_device *dev, freenect_depth_cb cb)
FREENECTAPI int freenect_close_device(freenect_device *dev)
freenect_video_format video_format
static const std::string VENDOR_NAME


xiaoqiang_freenect_camera
Author(s): Patrick Mihelich, Suat Gedikli, Radu Bogdan Rusu (original openni_camera driver)., Piyush Khandelwal (libfreenect port).
autogenerated on Mon Jun 10 2019 15:53:18