Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpKinect.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
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 https://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
35#include <visp3/core/vpConfig.h>
36
37// Note that libfreenect needs libusb-1.0 and libpthread
38#if defined(VISP_HAVE_LIBFREENECT_AND_DEPENDENCIES)
39
40#include <limits> // numeric_limits
41
42#include <visp3/core/vpDebug.h>
43#include <visp3/core/vpXmlParserCamera.h>
44#include <visp3/sensor/vpKinect.h>
45
50vpKinect::vpKinect(freenect_context *ctx, int index)
51 : Freenect::FreenectDevice(ctx, index), m_rgb_mutex(), m_depth_mutex(), RGBcam(), IRcam(), rgbMir(), irMrgb(),
52 DMres(DMAP_LOW_RES), hd(240), wd(320), dmap(), IRGB(), m_new_rgb_frame(false), m_new_depth_map(false),
53 m_new_depth_image(false), height(480), width(640)
54{
55 dmap.resize(height, width);
56 IRGB.resize(height, width);
57 vpPoseVector r(-0.0266, -0.0047, -0.0055, 0.0320578, 0.0169041,
58 -0.0076519);
61 rgbMir.buildFrom(r);
62 irMrgb = rgbMir.inverse();
63}
64
69
71{
72 DMres = res;
73 height = 480;
74 width = 640;
77 if (DMres == DMAP_LOW_RES) {
78 std::cout << "vpKinect::start LOW depth map resolution 240x320" << std::endl;
79 IRcam.initPersProjWithDistortion(303.06, 297.89, 160.75, 117.9, -0.27, 0);
80 hd = 240;
81 wd = 320;
82 }
83 else {
84 std::cout << "vpKinect::start MEDIUM depth map resolution 480x640" << std::endl;
85
86 IRcam.initPersProjWithDistortion(606.12, 595.78, 321.5, 235.8, -0.27, 0);
87
88 hd = 480;
89 wd = 640;
90 }
91
92#if defined(VISP_HAVE_VIPER850_DATA) && defined(VISP_HAVE_PUGIXML)
93 vpXmlParserCamera cameraParser;
94 std::string cameraXmlFile = std::string(VISP_VIPER850_DATA_PATH) + std::string("/include/const_camera_Viper850.xml");
95 cameraParser.parse(RGBcam, cameraXmlFile, "Generic-camera", vpCameraParameters::perspectiveProjWithDistortion, width,
96 height);
97#else
98 // RGBcam.initPersProjWithoutDistortion(525.53, 524.94, 309.9, 282.8);//old
99 // RGBcam.initPersProjWithDistortion(536.76, 537.25, 313.45,
100 // 273.27,0.04,-0.04);//old
101 // RGBcam.initPersProjWithoutDistortion(512.0559503505,511.9352058050,310.6693938678,267.0673901049);//new
102 RGBcam.initPersProjWithDistortion(522.5431816996, 522.7191431808, 311.4001982614, 267.4283562142, 0.0477365207,
103 -0.0462326418); // new
104#endif
105
106 this->startVideo();
107 this->startDepth();
108}
109
111{
112 this->stopVideo();
113 this->stopDepth();
114}
115
119void vpKinect::VideoCallback(void *rgb, uint32_t /* timestamp */)
120{
121 std::lock_guard<std::mutex> lock(m_rgb_mutex);
122 uint8_t *rgb_ = static_cast<uint8_t *>(rgb);
123 for (unsigned i = 0; i < height; i++) {
124 for (unsigned j = 0; j < width; j++) {
125 IRGB[i][j].R = rgb_[3 * (width * i + j) + 0];
126 IRGB[i][j].G = rgb_[3 * (width * i + j) + 1];
127 IRGB[i][j].B = rgb_[3 * (width * i + j) + 2];
128 }
129 }
130
131 m_new_rgb_frame = true;
132}
133
144void vpKinect::DepthCallback(void *depth, uint32_t /* timestamp */)
145{
146 std::lock_guard<std::mutex> lock(m_depth_mutex);
147 uint16_t *depth_ = static_cast<uint16_t *>(depth);
148 for (unsigned i = 0; i < height; i++) {
149 for (unsigned j = 0; j < width; j++) {
150 dmap[i][j] =
151 0.1236f * tan(depth_[width * i + j] / 2842.5f + 1.1863f); // formula from
152 // http://openkinect.org/wiki/Imaging_Information
153 if (depth_[width * i + j] > 1023) { // Depth cannot be computed
154 dmap[i][j] = -1;
155 }
156 }
157 }
158 m_new_depth_map = true;
159 m_new_depth_image = true;
160}
161
166{
167 std::lock_guard<std::mutex> lock(m_depth_mutex);
168 if (!m_new_depth_map)
169 return false;
170 map = this->dmap;
171 m_new_depth_map = false;
172 return true;
173}
174
179{
180 vpImage<float> tempMap;
181 m_depth_mutex.lock();
182 if (!m_new_depth_map && !m_new_depth_image) {
183 m_depth_mutex.unlock();
184 return false;
185 }
186 tempMap = dmap;
187
188 m_new_depth_map = false;
189 m_new_depth_image = false;
190 m_depth_mutex.unlock();
191
192 if ((Imap.getHeight() != hd) || (map.getHeight() != hd))
193 vpERROR_TRACE(1, "Image size does not match vpKinect DM resolution");
194 if (DMres == DMAP_LOW_RES) {
195 for (unsigned int i = 0; i < hd; i++)
196 for (unsigned int j = 0; j < wd; j++) {
197 map[i][j] = tempMap[i << 1][j << 1];
198 // if (map[i][j] != -1)
199 if (fabs(map[i][j] + 1.f) > std::numeric_limits<float>::epsilon())
200 Imap[i][j] = static_cast<unsigned char>(255 * map[i][j] / 5);
201 else
202 Imap[i][j] = 255;
203 }
204 }
205 else {
206 for (unsigned i = 0; i < height; i++)
207 for (unsigned j = 0; j < width; j++) {
208 map[i][j] = tempMap[i][j];
209 // if (map[i][j] != -1)
210 if (fabs(map[i][j] + 1.f) > std::numeric_limits<float>::epsilon())
211 Imap[i][j] = static_cast<unsigned char>(255 * map[i][j] / 5);
212 else
213 Imap[i][j] = 255;
214 }
215 }
216
217 return true;
218}
219
224{
225 std::lock_guard<std::mutex> lock(m_rgb_mutex);
226 if (!m_new_rgb_frame)
227 return false;
228 I_RGB = this->IRGB;
229 m_new_rgb_frame = false;
230 return true;
231}
232
237void vpKinect::warpRGBFrame(const vpImage<vpRGBa> &Irgb, const vpImage<float> &Idepth, vpImage<vpRGBa> &IrgbWarped)
238{
239 if ((Idepth.getHeight() != hd) || (Idepth.getWidth() != wd)) {
240 vpERROR_TRACE(1, "Idepth image size does not match vpKinect DM resolution");
241 }
242 else {
243 if ((IrgbWarped.getHeight() != hd) || (IrgbWarped.getWidth() != wd))
244 IrgbWarped.resize(hd, wd);
245 IrgbWarped = vpRGBa(0);
246 double x1 = 0., y1 = 0., x2 = 0., y2 = 0., Z1, Z2;
247 vpImagePoint imgPoint(0, 0);
248 double u = 0., v = 0.;
249 vpColVector P1(4), P2(4);
250
251 for (unsigned int i = 0; i < hd; i++)
252 for (unsigned int j = 0; j < wd; j++) {
254 vpPixelMeterConversion::convertPoint(IRcam, j, i, x1, y1);
255 Z1 = Idepth[i][j];
256 // if (Z1!=-1){
257 if (std::fabs(Z1 + 1) <= std::numeric_limits<double>::epsilon()) {
258 P1[0] = x1 * Z1;
259 P1[1] = y1 * Z1;
260 P1[2] = Z1;
261 P1[3] = 1;
262
264 P2 = rgbMir * P1;
265 Z2 = P2[2];
266 // if (Z2!= 0){
267 if (std::fabs(Z2) > std::numeric_limits<double>::epsilon()) {
268 x2 = P2[0] / P2[2];
269 y2 = P2[1] / P2[2];
270 }
271 else
272 std::cout << "Z2 = 0 !!" << std::endl;
273
276 vpMeterPixelConversion::convertPoint(RGBcam, x2, y2, u, v);
277
278 unsigned int u_ = static_cast<unsigned int>(u);
279 unsigned int v_ = static_cast<unsigned int>(v);
281 if ((u_ < width) && (v_ < height)) {
282 IrgbWarped[i][j] = Irgb[v_][u_];
283 }
284 else
285 IrgbWarped[i][j] = 0;
286 }
287 }
288 }
289}
290END_VISP_NAMESPACE
291#elif !defined(VISP_BUILD_SHARED_LIBS)
292// Work around to avoid warning: libvisp_sensor.a(vpKinect.cpp.o) has no symbols
293void dummy_vpKinect() { }
294#endif // VISP_HAVE_LIBFREENECT
@ perspectiveProjWithDistortion
Perspective projection with distortion model.
Implementation of column vector and the associated operations.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition of the vpImage class member functions.
Definition vpImage.h:131
unsigned int getWidth() const
Definition vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition vpImage.h:544
unsigned int getHeight() const
Definition vpImage.h:181
void stop()
Definition vpKinect.cpp:110
void warpRGBFrame(const vpImage< vpRGBa > &Irgb, const vpImage< float > &Idepth, vpImage< vpRGBa > &IrgbWarped)
Definition vpKinect.cpp:237
bool getDepthMap(vpImage< float > &map)
Definition vpKinect.cpp:165
void start(vpKinect::vpDMResolution res=DMAP_LOW_RES)
Definition vpKinect.cpp:70
vpKinect(freenect_context *ctx, int index)
Definition vpKinect.cpp:50
@ DMAP_LOW_RES
Definition vpKinect.h:126
bool getRGB(vpImage< vpRGBa > &IRGB)
Definition vpKinect.cpp:223
virtual ~vpKinect()
Definition vpKinect.cpp:68
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Implementation of a pose vector and operations on poses.
XML parser to load and save intrinsic camera parameters.
int parse(vpCameraParameters &cam, const std::string &filename, const std::string &camera_name, const vpCameraParameters::vpCameraParametersProjType &projModel, unsigned int image_width=0, unsigned int image_height=0, bool verbose=true)
#define vpERROR_TRACE
Definition vpDebug.h:423