Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpKinect.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * API for using a Microsoft Kinect device
32  * Requires libfreenect as a third party library
33  *
34  * Authors:
35  * Celine Teuliere
36  *
37  *****************************************************************************/
38 
39 #include <visp3/core/vpConfig.h>
40 
41 // Note that libfreenect needs libusb-1.0 and libpthread
42 #if defined(VISP_HAVE_LIBFREENECT_AND_DEPENDENCIES)
43 
44 #include <limits> // numeric_limits
45 
46 #include <visp3/sensor/vpKinect.h>
47 #include <visp3/core/vpXmlParserCamera.h>
48 
52 vpKinect::vpKinect(freenect_context *ctx, int index)
53  : Freenect::FreenectDevice(ctx, index),
54  m_rgb_mutex(), m_depth_mutex(), RGBcam(), IRcam(),
55  rgbMir(), irMrgb(), DMres(DMAP_LOW_RES),
56  hd(240), wd(320),
57  dmap(), IRGB(),
58  m_new_rgb_frame(false),
59  m_new_depth_map(false),
60  m_new_depth_image(false),
61  height(480), width(640)
62 {
63  dmap.resize(height, width);
64  IRGB.resize(height, width);
65  vpPoseVector r(-0.0266,-0.0047,-0.0055,0.0320578,0.0169041,-0.0076519 );
66  rgbMir.buildFrom(r);
67  irMrgb = rgbMir.inverse();
68 }
69 
74 {
75 
76 }
77 
79 {
80  DMres = res;
81  height = 480;
82  width = 640;
84  if (DMres == DMAP_LOW_RES){
85  std::cout << "vpKinect::start LOW depth map resolution 240x320" << std::endl;
86  // IRcam.setparameters(IRcam.get_px()/2, IRcam.get_py()/2, IRcam.get_u0()/2, IRcam.get_v0()/2);
87  //IRcam.initPersProjWithoutDistortion(303.06,297.89,160.75,117.9);
88  IRcam.initPersProjWithDistortion(303.06, 297.89, 160.75, 117.9, -0.27, 0);
89  hd = 240;
90  wd = 320;
91  }
92  else
93  {
94  std::cout << "vpKinect::start MEDIUM depth map resolution 480x640" << std::endl;
95 
96  //IRcam.initPersProjWithoutDistortion(606.12,595.78,321.5,235.8);
97  IRcam.initPersProjWithDistortion(606.12, 595.78, 321.5, 235.8, -0.27, 0);
98  // Idmap.resize(height, width);
99  hd = 480;
100  wd = 640;
101  }
102 
103 #if defined(VISP_HAVE_VIPER850_DATA) && defined(VISP_HAVE_XML2)
104  vpXmlParserCamera cameraParser;
105  std::string cameraXmlFile = std::string(VISP_VIPER850_DATA_PATH) + std::string("/include/const_camera_Viper850.xml");
106  cameraParser.parse(RGBcam, cameraXmlFile, "Generic-camera", vpCameraParameters::perspectiveProjWithDistortion, width, height);
107 #else
108 // RGBcam.initPersProjWithoutDistortion(525.53, 524.94, 309.9, 282.8);//old
109 // RGBcam.initPersProjWithDistortion(536.76, 537.25, 313.45, 273.27,0.04,-0.04);//old
110 // RGBcam.initPersProjWithoutDistortion(512.0559503505,511.9352058050,310.6693938678,267.0673901049);//new
111  RGBcam.initPersProjWithDistortion(522.5431816996,522.7191431808,311.4001982614,267.4283562142,0.0477365207,-0.0462326418);//new
112 #endif
113 
114  this->startVideo();
115  this->startDepth();
116 }
117 
119 {
120  this->stopVideo();
121  this->stopDepth();
122 }
123 
124 
128 void vpKinect::VideoCallback(void* rgb, uint32_t /* timestamp */)
129 {
130 // std::cout << "vpKinect Video callback" << std::endl;
131  vpMutex::vpScopedLock lock(m_rgb_mutex);
132  uint8_t* rgb_ = static_cast<uint8_t*>(rgb);
133  for (unsigned i = 0; i< height;i++){
134  for (unsigned j = 0 ; j < width ; j++)
135  {
136  IRGB[i][j].R = rgb_[3*(width*i +j)+0];
137  IRGB[i][j].G = rgb_[3*(width*i +j)+1];
138  IRGB[i][j].B = rgb_[3*(width*i +j)+2];
139  }
140  }
141 
142  m_new_rgb_frame = true;
143 }
144 
155 void vpKinect::DepthCallback(void* depth, uint32_t /* timestamp */)
156 {
157 // std::cout << "vpKinect Depth callback" << std::endl;
158  vpMutex::vpScopedLock lock(m_depth_mutex);
159  uint16_t* depth_ = static_cast<uint16_t*>(depth);
160  for (unsigned i = 0; i< height;i++){
161  for (unsigned j = 0 ; j < width ; j++)
162  {
163  dmap[i][j] = 0.1236f * tan(depth_[width*i +j] / 2842.5f + 1.1863f);//formula from http://openkinect.org/wiki/Imaging_Information
164  if(depth_[width*i +j]>1023){//Depth cannot be computed
165  dmap[i][j] = -1;
166  }
167  }
168  }
169  m_new_depth_map = true;
170  m_new_depth_image = true;
171 }
172 
173 
178 {
179  vpMutex::vpScopedLock lock(m_depth_mutex);
180  if (!m_new_depth_map)
181  return false;
182  map = this->dmap;
183  m_new_depth_map = false;
184  return true;
185 }
186 
187 
192 {
193  // vpMutex::vpScopedLock lock(m_depth_mutex);
194  vpImage<float> tempMap;
195  m_depth_mutex.lock();
196  if (!m_new_depth_map && !m_new_depth_image)
197  {
198  m_depth_mutex.unlock();
199  return false;
200  }
201  tempMap = dmap;
202 
203  m_new_depth_map = false;
204  m_new_depth_image = false;
205  m_depth_mutex.unlock();
206 
207  if ((Imap.getHeight()!=hd )||(map.getHeight()!=hd))
208  vpERROR_TRACE(1, "Image size does not match vpKinect DM resolution");
209  if (DMres == DMAP_LOW_RES){
210  for(unsigned int i = 0; i < hd; i++)
211  for(unsigned int j = 0; j < wd; j++){
212  map[i][j] = tempMap[i<<1][j<<1];
213  //if (map[i][j] != -1)
214  if (fabs(map[i][j] + 1.f) > std::numeric_limits<float>::epsilon())
215  Imap[i][j] = (unsigned char)(255*map[i][j]/5);
216  else
217  Imap[i][j] = 255;
218  }
219  }
220  else
221  {
222  for (unsigned i = 0; i< height;i++)
223  for (unsigned j = 0 ; j < width ; j++){
224  map[i][j] = tempMap[i][j];
225  //if (map[i][j] != -1)
226  if (fabs(map[i][j] + 1.f) > std::numeric_limits<float>::epsilon())
227  Imap[i][j] = (unsigned char)(255*map[i][j]/5);
228  else
229  Imap[i][j] = 255;
230  }
231  }
232 
233  return true;
234 }
235 
236 
241 {
242  vpMutex::vpScopedLock lock(m_rgb_mutex);
243  if (!m_new_rgb_frame)
244  return false;
245  I_RGB = this->IRGB;
246  m_new_rgb_frame = false;
247  return true;
248 }
249 
253 void vpKinect::warpRGBFrame(const vpImage<vpRGBa> & Irgb, const vpImage<float> & Idepth, vpImage<vpRGBa> & IrgbWarped)
254 {
255  if ((Idepth.getHeight()!=hd )||(Idepth.getWidth()!=wd)){
256  vpERROR_TRACE(1, "Idepth image size does not match vpKinect DM resolution");
257  }
258  else{
259  if((IrgbWarped.getHeight()!=hd )||(IrgbWarped.getWidth()!=wd))
260  IrgbWarped.resize(hd, wd);
261  IrgbWarped=0;
262  double x1=0., y1=0., x2=0., y2=0., Z1, Z2;
263  vpImagePoint imgPoint(0,0);
264  double u=0., v=0.;
265  vpColVector P1(4),P2(4);
266 
267 // std::cout <<"rgbMir : "<<rgbMir<<std::endl;
268 
269  for (unsigned int i = 0; i< hd;i++)
270  for (unsigned int j = 0 ; j < wd ; j++){
272  vpPixelMeterConversion::convertPoint(IRcam, j, i, x1, y1);
273  Z1 = Idepth[i][j];
274  //if (Z1!=-1){
275  if (std::fabs(Z1+1) <= std::numeric_limits<double>::epsilon()){
276  P1[0]=x1*Z1;
277  P1[1]=y1*Z1;
278  P1[2]=Z1;
279  P1[3]=1;
280 
282  P2 = rgbMir*P1;
283  Z2 = P2[2];
284  //if (Z2!= 0){
285  if (std::fabs(Z2) > std::numeric_limits<double>::epsilon()){
286  x2 = P2[0]/P2[2];
287  y2 = P2[1]/P2[2];
288  }
289  else
290  std::cout<<"Z2 = 0 !!"<<std::endl;
291 
293  vpMeterPixelConversion::convertPoint(RGBcam, x2, y2, u, v);
294 
295  unsigned int u_ = (unsigned int)u;
296  unsigned int v_ = (unsigned int)v;
298  if ((u_<width)&&(v_<height)){
299  IrgbWarped[i][j] = Irgb[v_][u_];
300  }
301  else
302  IrgbWarped[i][j] = 0;
303  }
304  }
305  }
306 }
307 
308 #elif !defined(VISP_BUILD_SHARED_LIBS)
309 // Work arround to avoid warning: libvisp_sensor.a(vpKinect.cpp.o) has no symbols
310 void dummy_vpKinect() {};
311 #endif // VISP_HAVE_LIBFREENECT
Class that allows protection by mutex.
Definition: vpMutex.h:163
void start(vpKinect::vpDMResolution res=DMAP_LOW_RES)
Definition: vpKinect.cpp:78
vpDMResolution
Definition: vpKinect.h:125
void lock()
Definition: vpMutex.h:90
unsigned int getWidth() const
Definition: vpImage.h:226
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
Point coordinates conversion from normalized coordinates in meter to pixel coordinates ...
#define vpERROR_TRACE
Definition: vpDebug.h:391
void unlock()
Definition: vpMutex.h:106
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Point coordinates conversion from pixel coordinates to normalized coordinates in meter...
XML parser to load and save intrinsic camera parameters.
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:903
bool getRGB(vpImage< vpRGBa > &IRGB)
Definition: vpKinect.cpp:240
void warpRGBFrame(const vpImage< vpRGBa > &Irgb, const vpImage< float > &Idepth, vpImage< vpRGBa > &IrgbWarped)
Definition: vpKinect.cpp:253
Perspective projection with distortion model.
void buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:93
vpHomogeneousMatrix inverse() const
void stop()
Definition: vpKinect.cpp:118
unsigned int getHeight() const
Definition: vpImage.h:175
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
int parse(vpCameraParameters &cam, const std::string &filename, const std::string &camera_name, const vpCameraParameters::vpCameraParametersProjType &projModel, const unsigned int image_width=0, const unsigned int image_height=0)
bool getDepthMap(vpImage< float > &map)
Definition: vpKinect.cpp:177
void initPersProjWithDistortion(const double px, const double py, const double u0, const double v0, const double kud, const double kdu)
virtual ~vpKinect()
Definition: vpKinect.cpp:73
vpKinect(freenect_context *ctx, int index)
Definition: vpKinect.cpp:52