29 #if defined(__linux__) 30 #include <sys/prctl.h> 31 #elif defined(__APPLE__) 35 #include <opencv2/opencv.hpp> 39 #include <std_msgs/Header.h> 40 #include <sensor_msgs/CameraInfo.h> 41 #include <sensor_msgs/SetCameraInfo.h> 42 #include <sensor_msgs/Image.h> 43 #include <sensor_msgs/CompressedImage.h> 50 #include <libfreenect2/libfreenect2.hpp> 51 #include <libfreenect2/frame_listener_impl.h> 52 #include <libfreenect2/packet_pipeline.h> 53 #include <libfreenect2/config.h> 54 #include <libfreenect2/registration.h> 81 libfreenect2::Freenect2Device *
device;
86 libfreenect2::Freenect2Device::IrCameraParams
irParams;
138 : sizeColor(1920, 1080), sizeIr(512, 424), sizeLowRes(sizeColor.width / 2, sizeColor.height / 2), color(sizeColor.width, sizeColor.height, 4), nh(nh), priv_nh(priv_nh),
139 frameColor(0), frameIrDepth(0), pubFrameColor(0), pubFrameIrDepth(0), lastColor(0, 0), lastDepth(0, 0), nextColor(false),
140 nextIrDepth(false), depthShift(0), running(false), deviceActive(false), clientConnected(false)
149 OUT_ERROR(
"kinect2_bridge is already running!");
164 for(
size_t i = 0; i < threads.size(); ++i)
177 OUT_ERROR(
"kinect2_bridge is not running!");
184 for(
size_t i = 0; i < threads.size(); ++i)
194 if(deviceActive && !device->stop())
211 for(
size_t i = 0; i <
COUNT; ++i)
213 imagePubs[i].shutdown();
214 compressedPubs[i].shutdown();
226 double fps_limit, maxDepth, minDepth;
227 bool use_png, bilateral_filter, edge_aware_filter;
228 int32_t jpeg_quality, png_level, queueSize, reg_dev, depth_dev, worker_threads;
229 std::string depth_method, reg_method, calib_path, sensor, base_name;
231 std::string depthDefault =
"cpu";
232 std::string regDefault =
"default";
234 #ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT 235 depthDefault =
"opengl";
237 #ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT 238 depthDefault =
"opencl";
240 #ifdef LIBFREENECT2_WITH_CUDA_SUPPORT 241 depthDefault =
"cuda";
243 #ifdef DEPTH_REG_OPENCL 244 regDefault =
"opencl";
248 priv_nh.
param(
"sensor", sensor, std::string(
""));
249 priv_nh.
param(
"fps_limit", fps_limit, -1.0);
250 priv_nh.
param(
"calib_path", calib_path, std::string(K2_CALIB_PATH));
251 priv_nh.
param(
"use_png", use_png,
false);
252 priv_nh.
param(
"jpeg_quality", jpeg_quality, 90);
253 priv_nh.
param(
"png_level", png_level, 1);
254 priv_nh.
param(
"depth_method", depth_method, depthDefault);
255 priv_nh.
param(
"depth_device", depth_dev, -1);
256 priv_nh.
param(
"reg_method", reg_method, regDefault);
257 priv_nh.
param(
"reg_device", reg_dev, -1);
258 priv_nh.
param(
"max_depth", maxDepth, 12.0);
259 priv_nh.
param(
"min_depth", minDepth, 0.1);
260 priv_nh.
param(
"queue_size", queueSize, 2);
261 priv_nh.
param(
"bilateral_filter", bilateral_filter,
true);
262 priv_nh.
param(
"edge_aware_filter", edge_aware_filter,
true);
263 priv_nh.
param(
"publish_tf", publishTF,
false);
264 priv_nh.
param(
"base_name_tf", baseNameTF, base_name);
265 priv_nh.
param(
"worker_threads", worker_threads, 4);
267 worker_threads = std::max(1, worker_threads);
268 threads.resize(worker_threads);
272 <<
" sensor: " FG_CYAN << (sensor.empty() ?
"default" : sensor) <<
NO_COLOR << std::endl
275 <<
" use_png: " FG_CYAN << (use_png ?
"true" :
"false") <<
NO_COLOR << std::endl
285 <<
" bilateral_filter: " FG_CYAN << (bilateral_filter ?
"true" :
"false") <<
NO_COLOR << std::endl
286 <<
"edge_aware_filter: " FG_CYAN << (edge_aware_filter ?
"true" :
"false") <<
NO_COLOR << std::endl
287 <<
" publish_tf: " FG_CYAN << (publishTF ?
"true" :
"false") <<
NO_COLOR << std::endl
291 deltaT = fps_limit > 0 ? 1.0 / fps_limit : 0.0;
293 if(calib_path.empty() || calib_path.back() !=
'/')
310 initConfig(bilateral_filter, edge_aware_filter, minDepth, maxDepth);
331 bool initRegistration(
const std::string &method,
const int32_t device,
const double maxDepth)
335 if(method ==
"default")
339 else if(method ==
"cpu")
344 OUT_ERROR(
"CPU registration is not available!");
348 else if(method ==
"opencl")
350 #ifdef DEPTH_REG_OPENCL 353 OUT_ERROR(
"OpenCL registration is not available!");
359 OUT_ERROR(
"Unknown registration method: " << method);
366 if(!depthRegLowRes->
init(cameraMatrixLowRes, sizeLowRes, cameraMatrixDepth, sizeIr, distortionDepth, rotation, translation, 0.5f, maxDepth, device) ||
367 !depthRegHighRes->
init(cameraMatrixColor, sizeColor, cameraMatrixDepth, sizeIr, distortionDepth, rotation, translation, 0.5
f, maxDepth, device))
374 registration =
new libfreenect2::Registration(irParams, colorParams);
381 if(method ==
"default")
383 #ifdef LIBFREENECT2_WITH_CUDA_SUPPORT 384 packetPipeline =
new libfreenect2::CudaPacketPipeline(device);
385 #elif defined(LIBFREENECT2_WITH_OPENCL_SUPPORT) 386 packetPipeline =
new libfreenect2::OpenCLPacketPipeline(device);
387 #elif defined(LIBFREENECT2_WITH_OPENGL_SUPPORT) 388 packetPipeline =
new libfreenect2::OpenGLPacketPipeline();
390 packetPipeline =
new libfreenect2::CpuPacketPipeline();
393 else if(method ==
"cpu")
395 packetPipeline =
new libfreenect2::CpuPacketPipeline();
397 else if(method ==
"cuda")
399 #ifdef LIBFREENECT2_WITH_CUDA_SUPPORT 400 packetPipeline =
new libfreenect2::CudaPacketPipeline(device);
402 OUT_ERROR(
"Cuda depth processing is not available!");
406 else if(method ==
"opencl")
408 #ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT 409 packetPipeline =
new libfreenect2::OpenCLPacketPipeline(device);
411 OUT_ERROR(
"OpenCL depth processing is not available!");
415 else if(method ==
"opengl")
417 #ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT 418 packetPipeline =
new libfreenect2::OpenGLPacketPipeline();
420 OUT_ERROR(
"OpenGL depth processing is not available!");
424 else if(method ==
"clkde")
426 #ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT 427 packetPipeline =
new libfreenect2::OpenCLKdePacketPipeline(device);
429 OUT_ERROR(
"OpenCL depth processing is not available!");
433 else if(method ==
"cudakde")
435 #ifdef LIBFREENECT2_WITH_CUDA_SUPPORT 436 packetPipeline =
new libfreenect2::CudaKdePacketPipeline(device);
438 OUT_ERROR(
"Cuda depth processing is not available!");
444 OUT_ERROR(
"Unknown depth processing method: " << method);
451 void initConfig(
const bool bilateral_filter,
const bool edge_aware_filter,
const double minDepth,
const double maxDepth)
453 libfreenect2::Freenect2Device::Config config;
454 config.EnableBilateralFilter = bilateral_filter;
455 config.EnableEdgeAwareFilter = edge_aware_filter;
456 config.MinDepth = minDepth;
457 config.MaxDepth = maxDepth;
458 device->setConfiguration(config);
461 void initCompression(
const int32_t jpegQuality,
const int32_t pngLevel,
const bool use_png)
463 compressionParams.resize(7, 0);
464 compressionParams[0] = CV_IMWRITE_JPEG_QUALITY;
465 compressionParams[1] = jpegQuality;
466 compressionParams[2] = CV_IMWRITE_PNG_COMPRESSION;
467 compressionParams[3] = pngLevel;
468 compressionParams[4] = CV_IMWRITE_PNG_STRATEGY;
469 compressionParams[5] = CV_IMWRITE_PNG_STRATEGY_RLE;
470 compressionParams[6] = 0;
474 compression16BitExt =
".png";
479 compression16BitExt =
".tif";
484 void initTopics(
const int32_t queueSize,
const std::string &base_name)
486 std::vector<std::string> topics(
COUNT);
507 imagePubs.resize(
COUNT);
508 compressedPubs.resize(
COUNT);
511 for(
size_t i = 0; i <
COUNT; ++i)
513 imagePubs[i] = nh.
advertise<sensor_msgs::Image>(base_name + topics[i], queueSize, cb, cb);
523 bool deviceFound =
false;
524 const int numOfDevs = freenect2.enumerateDevices();
535 sensor = freenect2.getDefaultDeviceSerialNumber();
538 OUT_INFO(
"Kinect2 devices found: ");
539 for(
int i = 0; i < numOfDevs; ++i)
541 const std::string &
s = freenect2.getDeviceSerialNumber(i);
542 deviceFound = deviceFound || s == sensor;
548 OUT_ERROR(
"Device with serial '" << sensor <<
"' not found!");
553 device = freenect2.openDevice(sensor, packetPipeline);
557 OUT_INFO(
"no device connected or failure opening the default one!");
561 listenerColor =
new libfreenect2::SyncMultiFrameListener(libfreenect2::Frame::Color);
562 listenerIrDepth =
new libfreenect2::SyncMultiFrameListener(libfreenect2::Frame::Ir | libfreenect2::Frame::Depth);
564 device->setColorFrameListener(listenerColor);
565 device->setIrAndDepthFrameListener(listenerIrDepth);
579 colorParams = device->getColorCameraParams();
580 irParams = device->getIrCameraParams();
590 OUT_DEBUG(
"default ir camera parameters: ");
594 OUT_DEBUG(
"default color camera parameters: ");
597 cameraMatrixColor = cv::Mat::eye(3, 3, CV_64F);
598 distortionColor = cv::Mat::zeros(1, 5, CV_64F);
600 cameraMatrixColor.at<
double>(0, 0) = colorParams.fx;
601 cameraMatrixColor.at<
double>(1, 1) = colorParams.fy;
602 cameraMatrixColor.at<
double>(0, 2) = colorParams.cx;
603 cameraMatrixColor.at<
double>(1, 2) = colorParams.cy;
604 cameraMatrixColor.at<
double>(2, 2) = 1;
606 cameraMatrixIr = cv::Mat::eye(3, 3, CV_64F);
607 distortionIr = cv::Mat::zeros(1, 5, CV_64F);
609 cameraMatrixIr.at<
double>(0, 0) = irParams.fx;
610 cameraMatrixIr.at<
double>(1, 1) = irParams.fy;
611 cameraMatrixIr.at<
double>(0, 2) = irParams.cx;
612 cameraMatrixIr.at<
double>(1, 2) = irParams.cy;
613 cameraMatrixIr.at<
double>(2, 2) = 1;
615 distortionIr.at<
double>(0, 0) = irParams.k1;
616 distortionIr.at<
double>(0, 1) = irParams.k2;
617 distortionIr.at<
double>(0, 2) = irParams.p1;
618 distortionIr.at<
double>(0, 3) = irParams.p2;
619 distortionIr.at<
double>(0, 4) = irParams.k3;
621 cameraMatrixDepth = cameraMatrixIr.clone();
622 distortionDepth = distortionIr.clone();
624 rotation = cv::Mat::eye(3, 3, CV_64F);
625 translation = cv::Mat::zeros(3, 1, CV_64F);
631 std::string calibPath = calib_path + sensor +
'/';
633 struct stat fileStat;
634 bool calibDirNotFound = stat(calibPath.c_str(), &fileStat) != 0 || !S_ISDIR(fileStat.st_mode);
637 OUT_WARN(
"using sensor defaults for color intrinsic parameters.");
642 OUT_WARN(
"using sensor defaults for ir intrinsic parameters.");
647 OUT_WARN(
"using defaults for rotation and translation.");
652 OUT_WARN(
"using defaults for depth shift.");
656 cameraMatrixLowRes = cameraMatrixColor.clone();
657 cameraMatrixLowRes.at<
double>(0, 0) /= 2;
658 cameraMatrixLowRes.at<
double>(1, 1) /= 2;
659 cameraMatrixLowRes.at<
double>(0, 2) /= 2;
660 cameraMatrixLowRes.at<
double>(1, 2) /= 2;
662 const int mapType = CV_16SC2;
663 cv::initUndistortRectifyMap(cameraMatrixColor, distortionColor, cv::Mat(), cameraMatrixColor, sizeColor, mapType, map1Color, map2Color);
664 cv::initUndistortRectifyMap(cameraMatrixIr, distortionIr, cv::Mat(), cameraMatrixIr, sizeIr, mapType, map1Ir, map2Ir);
665 cv::initUndistortRectifyMap(cameraMatrixColor, distortionColor, cv::Mat(), cameraMatrixLowRes, sizeLowRes, mapType, map1LowRes, map2LowRes);
682 if(fs.open(filename, cv::FileStorage::READ))
690 OUT_ERROR(
"can't open calibration file: " << filename);
699 if(fs.open(filename, cv::FileStorage::READ))
707 OUT_ERROR(
"can't open calibration pose file: " << filename);
716 if(fs.open(filename, cv::FileStorage::READ))
723 OUT_ERROR(
"can't open calibration depth file: " << filename);
731 cv::Mat projColor = cv::Mat::zeros(3, 4, CV_64F);
732 cv::Mat projIr = cv::Mat::zeros(3, 4, CV_64F);
733 cv::Mat projLowRes = cv::Mat::zeros(3, 4, CV_64F);
735 cameraMatrixColor.copyTo(projColor(cv::Rect(0, 0, 3, 3)));
736 cameraMatrixIr.copyTo(projIr(cv::Rect(0, 0, 3, 3)));
737 cameraMatrixLowRes.copyTo(projLowRes(cv::Rect(0, 0, 3, 3)));
739 createCameraInfo(sizeColor, cameraMatrixColor, distortionColor, cv::Mat::eye(3, 3, CV_64F), projColor, infoHD);
740 createCameraInfo(sizeIr, cameraMatrixIr, distortionIr, cv::Mat::eye(3, 3, CV_64F), projIr, infoIR);
741 createCameraInfo(sizeLowRes, cameraMatrixLowRes, distortionColor, cv::Mat::eye(3, 3, CV_64F), projLowRes, infoQHD);
744 void createCameraInfo(
const cv::Size &size,
const cv::Mat &cameraMatrix,
const cv::Mat &distortion,
const cv::Mat &rotation,
const cv::Mat &projection, sensor_msgs::CameraInfo &cameraInfo)
const 746 cameraInfo.height = size.height;
747 cameraInfo.width = size.width;
749 const double *itC = cameraMatrix.ptr<
double>(0, 0);
750 for(
size_t i = 0; i < 9; ++i, ++itC)
752 cameraInfo.K[i] = *itC;
755 const double *itR = rotation.ptr<
double>(0, 0);
756 for(
size_t i = 0; i < 9; ++i, ++itR)
758 cameraInfo.R[i] = *itR;
761 const double *itP = projection.ptr<
double>(0, 0);
762 for(
size_t i = 0; i < 12; ++i, ++itP)
764 cameraInfo.P[i] = *itP;
767 cameraInfo.distortion_model =
"plumb_bob";
768 cameraInfo.D.resize(distortion.cols);
769 const double *itD = distortion.ptr<
double>(0, 0);
770 for(
size_t i = 0; i < (size_t)distortion.cols; ++i, ++itD)
772 cameraInfo.D[i] = *itD;
778 bool isSubscribedDepth =
false;
779 bool isSubscribedColor =
false;
782 clientConnected =
updateStatus(isSubscribedColor, isSubscribedDepth);
785 if(clientConnected && !deviceActive)
787 OUT_INFO(
"client connected. starting device...");
788 if(!device->startStreams(isSubscribedColor, isSubscribedDepth))
798 else if(!clientConnected && deviceActive)
800 OUT_INFO(
"no clients connected. stopping device...");
808 deviceActive =
false;
811 else if(deviceActive && (isSubscribedColor != this->isSubscribedColor || isSubscribedDepth != this->isSubscribedDepth))
818 else if(!device->startStreams(isSubscribedColor, isSubscribedDepth))
822 deviceActive =
false;
837 isSubscribedDepth =
false;
838 isSubscribedColor =
false;
840 for(
size_t i = 0; i <
COUNT; ++i)
843 if(imagePubs[i].getNumSubscribers() > 0)
847 if(compressedPubs[i].getNumSubscribers() > 0)
854 isSubscribedDepth =
true;
858 isSubscribedColor =
true;
865 isSubscribedColor =
true;
869 isSubscribedDepth =
true;
878 OUT_INFO(
"waiting for clients to connect");
881 size_t oldFrameIrDepth = 0, oldFrameColor = 0;
889 std::this_thread::sleep_for(std::chrono::milliseconds(10));
891 nextFrame = fpsTime +
deltaT;
897 if(now - fpsTime >= 3.0)
899 fpsTime = now - fpsTime;
900 size_t framesIrDepth = frameIrDepth - oldFrameIrDepth;
901 size_t framesColor = frameColor - oldFrameColor;
908 elapsedTimeColor = 0;
909 elapsedTimeIrDepth = 0;
912 if(isSubscribedDepth)
914 OUT_INFO(
"depth processing: " FG_YELLOW "~" << (tDepth / framesIrDepth) * 1000 <<
"ms" NO_COLOR " (~" << framesIrDepth / tDepth <<
"Hz) publishing rate: " FG_YELLOW "~" << framesIrDepth / fpsTime <<
"Hz" NO_COLOR);
916 if(isSubscribedColor)
918 OUT_INFO(
"color processing: " FG_YELLOW "~" << (tColor / framesColor) * 1000 <<
"ms" NO_COLOR " (~" << framesColor / tColor <<
"Hz) publishing rate: " FG_YELLOW "~" << framesColor / fpsTime <<
"Hz" NO_COLOR);
930 std::this_thread::sleep_for(std::chrono::milliseconds(10));
937 elapsedTimeColor = 0;
938 elapsedTimeIrDepth = 0;
948 const size_t checkFirst =
id % 2;
949 bool processedFrame =
false;
950 int oldNice = nice(0);
951 oldNice = nice(19 - oldNice);
955 processedFrame =
false;
957 for(
size_t i = 0; i < 2; ++i)
961 if(nextIrDepth && lockIrDepth.try_lock())
965 processedFrame =
true;
970 if(nextColor && lockColor.try_lock())
974 processedFrame =
true;
981 std::this_thread::sleep_for(std::chrono::milliseconds(1));
988 libfreenect2::FrameMap frames;
990 std_msgs::Header header;
991 std::vector<cv::Mat> images(
COUNT);
992 std::vector<Status> status = this->
status;
997 lockIrDepth.unlock();
1004 libfreenect2::Frame *irFrame = frames[libfreenect2::Frame::Ir];
1005 libfreenect2::Frame *depthFrame = frames[libfreenect2::Frame::Depth];
1007 if(irFrame->status != 0 || depthFrame->status != 0)
1009 listenerIrDepth->release(frames);
1010 lockIrDepth.unlock();
1012 OUT_ERROR(
"failure in depth packet processor from libfreenect2");
1015 if(irFrame->format != libfreenect2::Frame::Float || depthFrame->format != libfreenect2::Frame::Float)
1017 listenerIrDepth->release(frames);
1018 lockIrDepth.unlock();
1020 OUT_ERROR(
"received invalid frame format");
1024 frame = frameIrDepth++;
1028 cv::Mat(depthFrame->height, depthFrame->width, CV_32FC1, depthFrame->data).copyTo(depth);
1033 ir = cv::Mat(irFrame->height, irFrame->width, CV_32FC1, irFrame->data);
1034 ir.convertTo(images[
IR_SD], CV_16U);
1037 listenerIrDepth->release(frames);
1038 lockIrDepth.unlock();
1046 elapsedTimeIrDepth += elapsed;
1052 libfreenect2::FrameMap frames;
1053 std_msgs::Header header;
1054 std::vector<cv::Mat> images(
COUNT);
1055 std::vector<Status> status = this->
status;
1067 libfreenect2::Frame *colorFrame = frames[libfreenect2::Frame::Color];
1069 if(colorFrame->status != 0)
1071 listenerColor->release(frames);
1072 lockIrDepth.unlock();
1074 OUT_ERROR(
"failure in rgb packet processor from libfreenect2");
1077 if(colorFrame->format != libfreenect2::Frame::BGRX && colorFrame->format != libfreenect2::Frame::RGBX)
1079 listenerColor->release(frames);
1080 lockIrDepth.unlock();
1082 OUT_ERROR(
"received invalid frame format");
1086 frame = frameColor++;
1088 cv::Mat color = cv::Mat(colorFrame->height, colorFrame->width, CV_8UC4, colorFrame->data);
1092 memcpy(this->color.data, colorFrame->data, sizeColor.width * sizeColor.height * 4);
1093 this->color.format = colorFrame->format;
1100 cv::flip(color, tmp, 1);
1101 if(colorFrame->format == libfreenect2::Frame::BGRX)
1103 cv::cvtColor(tmp, images[
COLOR_HD], CV_BGRA2BGR);
1107 cv::cvtColor(tmp, images[
COLOR_HD], CV_RGBA2BGR);
1111 listenerColor->release(frames);
1120 elapsedTimeColor += elapsed;
1124 bool receiveFrames(libfreenect2::SyncMultiFrameListener *listener, libfreenect2::FrameMap &frames)
1126 bool newFrames =
false;
1129 #ifdef LIBFREENECT2_THREADING_STDLIB 1130 newFrames = listener->waitForNewFrame(frames, 1000);
1133 listener->waitForNewFrame(frames);
1135 if(!deviceActive || !running || !
ros::ok())
1139 listener->release(frames);
1162 std_msgs::Header header;
1164 header.stamp = timestamp;
1168 void processIrDepth(
const cv::Mat &depth, std::vector<cv::Mat> &images,
const std::vector<Status> &status)
1174 libfreenect2::Frame depthFrame(sizeIr.width, sizeIr.height, 4, depth.data);
1175 libfreenect2::Frame undistorted(sizeIr.width, sizeIr.height, 4);
1176 libfreenect2::Frame registered(sizeIr.width, sizeIr.height, 4);
1178 registration->apply(&color, &depthFrame, &undistorted, ®istered);
1180 cv::flip(cv::Mat(sizeIr, CV_8UC4, registered.data), tmp, 1);
1181 if(color.format == libfreenect2::Frame::BGRX)
1183 cv::cvtColor(tmp, images[COLOR_SD_RECT], CV_BGRA2BGR);
1187 cv::cvtColor(tmp, images[COLOR_SD_RECT], CV_RGBA2BGR);
1194 cv::flip(images[
IR_SD], images[IR_SD], 1);
1196 if(status[IR_SD_RECT])
1198 cv::remap(images[
IR_SD], images[IR_SD_RECT], map1Ir, map2Ir, cv::INTER_AREA);
1202 cv::Mat depthShifted;
1205 depth.convertTo(images[DEPTH_SD], CV_16U, 1);
1206 cv::flip(images[DEPTH_SD], images[DEPTH_SD], 1);
1210 depth.convertTo(depthShifted, CV_16U, 1, depthShift);
1211 cv::flip(depthShifted, depthShifted, 1);
1215 cv::remap(depthShifted, images[DEPTH_SD_RECT], map1Ir, map2Ir, cv::INTER_NEAREST);
1219 lockRegLowRes.lock();
1220 depthRegLowRes->
registerDepth(depthShifted, images[DEPTH_QHD]);
1221 lockRegLowRes.unlock();
1223 if(status[DEPTH_HD])
1225 lockRegHighRes.lock();
1226 depthRegHighRes->
registerDepth(depthShifted, images[DEPTH_HD]);
1227 lockRegHighRes.unlock();
1231 void processColor(std::vector<cv::Mat> &images,
const std::vector<Status> &status)
1240 cv::resize(images[
COLOR_HD], images[
COLOR_QHD], sizeLowRes, 0, 0, cv::INTER_AREA);
1250 cv::cvtColor(images[
COLOR_HD], images[MONO_HD], CV_BGR2GRAY);
1252 if(status[MONO_HD_RECT])
1254 cv::cvtColor(images[
COLOR_HD_RECT], images[MONO_HD_RECT], CV_BGR2GRAY);
1256 if(status[MONO_QHD])
1258 cv::cvtColor(images[
COLOR_QHD], images[MONO_QHD], CV_BGR2GRAY);
1260 if(status[MONO_QHD_RECT])
1262 cv::cvtColor(images[
COLOR_QHD_RECT], images[MONO_QHD_RECT], CV_BGR2GRAY);
1266 void publishImages(
const std::vector<cv::Mat> &images,
const std_msgs::Header &header,
const std::vector<Status> &status,
const size_t frame,
size_t &pubFrame,
const size_t begin,
const size_t end)
1268 std::vector<sensor_msgs::ImagePtr> imageMsgs(
COUNT);
1269 std::vector<sensor_msgs::CompressedImagePtr> compressedMsgs(
COUNT);
1270 sensor_msgs::CameraInfoPtr infoHDMsg, infoQHDMsg, infoIRMsg;
1271 std_msgs::Header _header = header;
1277 infoIRMsg = sensor_msgs::CameraInfoPtr(
new sensor_msgs::CameraInfo);
1279 infoIRMsg->header = _header;
1285 infoHDMsg = sensor_msgs::CameraInfoPtr(
new sensor_msgs::CameraInfo);
1287 infoHDMsg->header = _header;
1289 infoQHDMsg = sensor_msgs::CameraInfoPtr(
new sensor_msgs::CameraInfo);
1291 infoQHDMsg->header = _header;
1295 for(
size_t i = begin; i < end; ++i)
1311 imageMsgs[i] = sensor_msgs::ImagePtr(
new sensor_msgs::Image);
1315 compressedMsgs[i] = sensor_msgs::CompressedImagePtr(
new sensor_msgs::CompressedImage);
1319 imageMsgs[i] = sensor_msgs::ImagePtr(
new sensor_msgs::Image);
1320 compressedMsgs[i] = sensor_msgs::CompressedImagePtr(
new sensor_msgs::CompressedImage);
1327 while(frame != pubFrame)
1329 std::this_thread::sleep_for(std::chrono::microseconds(100));
1332 for(
size_t i = begin; i < end; ++i)
1339 imagePubs[i].publish(imageMsgs[i]);
1342 compressedPubs[i].publish(compressedMsgs[i]);
1345 imagePubs[i].publish(imageMsgs[i]);
1346 compressedPubs[i].publish(compressedMsgs[i]);
1366 infoQHDPub.
publish(infoQHDMsg);
1374 void createImage(
const cv::Mat &image,
const std_msgs::Header &header,
const Image type, sensor_msgs::Image &msgImage)
const 1377 step = image.cols * image.elemSize();
1378 size = image.rows * step;
1407 msgImage.header = header;
1408 msgImage.height = image.rows;
1409 msgImage.width = image.cols;
1410 msgImage.is_bigendian =
false;
1411 msgImage.step = step;
1412 msgImage.data.resize(size);
1413 memcpy(msgImage.data.data(), image.data, size);
1416 void createCompressed(
const cv::Mat &image,
const std_msgs::Header &header,
const Image type, sensor_msgs::CompressedImage &msgImage)
const 1418 msgImage.header = header;
1429 cv::imencode(compression16BitExt, image, msgImage.data, compressionParams);
1437 cv::imencode(
".jpg", image, msgImage.data, compressionParams);
1444 cv::imencode(
".jpg", image, msgImage.data, compressionParams);
1458 tf::Matrix3x3 rot(rotation.at<
double>(0, 0), rotation.at<
double>(0, 1), rotation.at<
double>(0, 2),
1459 rotation.at<
double>(1, 0), rotation.at<
double>(1, 1), rotation.at<
double>(1, 2),
1460 rotation.at<
double>(2, 0), rotation.at<
double>(2, 1), rotation.at<
double>(2, 2));
1464 tf::Vector3 trans(translation.at<
double>(0), translation.at<
double>(1), translation.at<
double>(2));
1480 std::this_thread::sleep_for(std::chrono::milliseconds(10));
1486 #if defined(__linux__) 1487 prctl(PR_SET_NAME, name.c_str());
1488 #elif defined(__APPLE__) 1489 pthread_setname_np(name.c_str());
1508 pKinect2Bridge->
stop();
1509 delete pKinect2Bridge;
1515 pKinect2Bridge =
new Kinect2Bridge(getNodeHandle(), getPrivateNodeHandle());
1516 if(!pKinect2Bridge->
start())
1518 delete pKinect2Bridge;
1519 pKinect2Bridge = NULL;
1532 <<
" info: " << desc << std::endl;
1537 std::string depthMethods =
"cpu";
1538 std::string depthDefault =
"cpu";
1539 std::string regMethods =
"default";
1540 std::string regDefault =
"default";
1542 #ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT 1543 depthMethods +=
", opengl";
1544 depthDefault =
"opengl";
1546 #ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT 1547 depthMethods +=
", opencl";
1548 depthDefault =
"opencl";
1550 #ifdef LIBFREENECT2_WITH_CUDA_SUPPORT 1551 depthMethods +=
", cuda";
1552 depthMethods +=
", cudakde";
1553 depthDefault =
"cuda";
1555 #ifdef DEPTH_REG_CPU 1556 regMethods +=
", cpu";
1558 #ifdef DEPTH_REG_OPENCL 1559 regMethods +=
", opencl";
1560 regMethods +=
", clkde";
1561 regDefault =
"opencl";
1564 std::cout << path <<
FG_BLUE " [_options:=value]" << std::endl;
1566 helpOption(
"sensor",
"double",
"-1.0",
"serial of the sensor to use");
1567 helpOption(
"fps_limit",
"double",
"-1.0",
"limit the frames per second");
1568 helpOption(
"calib_path",
"string", K2_CALIB_PATH,
"path to the calibration files");
1569 helpOption(
"use_png",
"bool",
"false",
"Use PNG compression instead of TIFF");
1570 helpOption(
"jpeg_quality",
"int",
"90",
"JPEG quality level from 0 to 100");
1571 helpOption(
"png_level",
"int",
"1",
"PNG compression level from 0 to 9");
1572 helpOption(
"depth_method",
"string", depthDefault,
"Use specific depth processing: " + depthMethods);
1573 helpOption(
"depth_device",
"int",
"-1",
"openCL device to use for depth processing");
1574 helpOption(
"reg_method",
"string", regDefault,
"Use specific depth registration: " + regMethods);
1575 helpOption(
"reg_device",
"int",
"-1",
"openCL device to use for depth registration");
1576 helpOption(
"max_depth",
"double",
"12.0",
"max depth value");
1577 helpOption(
"min_depth",
"double",
"0.1",
"min depth value");
1578 helpOption(
"queue_size",
"int",
"2",
"queue size of publisher");
1579 helpOption(
"bilateral_filter",
"bool",
"true",
"enable bilateral filtering of depth images");
1580 helpOption(
"edge_aware_filter",
"bool",
"true",
"enable edge aware filtering of depth images");
1581 helpOption(
"publish_tf",
"bool",
"false",
"publish static tf transforms for camera");
1582 helpOption(
"base_name_tf",
"string",
"as base_name",
"base name for the tf frames");
1583 helpOption(
"worker_threads",
"int",
"4",
"number of threads used for processing the images");
1590 if(!getenv(
"ROSCONSOLE_FORMAT"))
1599 for(
int argI = 1; argI < argc; ++argI)
1601 std::string arg(argv[argI]);
1603 if(arg ==
"--help" || arg ==
"--h" || arg ==
"-h" || arg ==
"-?" || arg ==
"--?")
void initConfig(const bool bilateral_filter, const bool edge_aware_filter, const double minDepth, const double maxDepth)
double elapsedTimeIrDepth
sensor_msgs::CameraInfo infoHD
boost::function< void(const SingleSubscriberPublisher &)> SubscriberStatusCallback
#define K2_TOPIC_IMAGE_COLOR
std::string compression16BitString
void processIrDepth(const cv::Mat &depth, std::vector< cv::Mat > &images, const std::vector< Status > &status)
void publish(const boost::shared_ptr< M > &message) const
#define K2_TOPIC_IMAGE_IR
void createCompressed(const cv::Mat &image, const std_msgs::Header &header, const Image type, sensor_msgs::CompressedImage &msgImage) const
DepthRegistration * depthRegLowRes
std::vector< ros::Publisher > compressedPubs
#define K2_CALIB_CAMERA_MATRIX
std::string compression16BitExt
#define K2_CALIB_DEPTH_SHIFT
void threadDispatcher(const size_t id)
std_msgs::Header createHeader(ros::Time &last, ros::Time &other)
void initCompression(const int32_t jpegQuality, const int32_t pngLevel, const bool use_png)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
PLUGINLIB_EXPORT_CLASS(depth_image_proc::ConvertMetricNodelet, nodelet::Nodelet)
cv::Mat cameraMatrixLowRes
const std::string TYPE_8UC1
void processColor(std::vector< cv::Mat > &images, const std::vector< Status > &status)
#define ROSCONSOLE_AUTOINIT
#define K2_TF_IR_OPT_FRAME
std::vector< Status > status
#define K2_TOPIC_COMPRESSED
cv::Mat cameraMatrixColor
ROSCPP_DECL void spin(Spinner &spinner)
bool receiveFrames(libfreenect2::SyncMultiFrameListener *listener, libfreenect2::FrameMap &frames)
std::mutex lockRegHighRes
std::vector< std::thread > threads
libfreenect2::Registration * registration
void initCalibration(const std::string &calib_path, const std::string &sensor)
libfreenect2::SyncMultiFrameListener * listenerIrDepth
#define K2_CALIB_TRANSLATION
static DepthRegistration * New(Method method=DEFAULT)
bool updateStatus(bool &isSubscribedColor, bool &isSubscribedDepth)
void setRPY(const tfScalar &roll, const tfScalar &pitch, const tfScalar &yaw)
virtual bool registerDepth(const cv::Mat &depth, cv::Mat ®istered)=0
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
#define K2_TOPIC_IMAGE_MONO
const std::string TYPE_16UC1
void createCameraInfo(const cv::Size &size, const cv::Mat &cameraMatrix, const cv::Mat &distortion, const cv::Mat &rotation, const cv::Mat &projection, sensor_msgs::CameraInfo &cameraInfo) const
libfreenect2::Freenect2Device::ColorCameraParams colorParams
Kinect2Bridge(const ros::NodeHandle &nh=ros::NodeHandle(), const ros::NodeHandle &priv_nh=ros::NodeHandle("~"))
#define K2_CALIB_DISTORTION
libfreenect2::Freenect2 freenect2
libfreenect2::Frame color
std::vector< ros::Publisher > imagePubs
Kinect2Bridge * pKinect2Bridge
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define K2_TOPIC_IMAGE_DEPTH
bool loadCalibrationDepthFile(const std::string &filename, double &depthShift) const
ros::Publisher infoQHDPub
libfreenect2::Freenect2Device * device
bool initDevice(std::string &sensor)
libfreenect2::PacketPipeline * packetPipeline
static void setThreadName(const std::string &name)
sensor_msgs::CameraInfo infoQHD
void helpOption(const std::string &name, const std::string &stype, const std::string &value, const std::string &desc)
bool initPipeline(const std::string &method, const int32_t device)
#define K2_CALIB_ROTATION
bool loadCalibrationFile(const std::string &filename, cv::Mat &cameraMatrix, cv::Mat &distortion) const
uint32_t getNumSubscribers() const
bool init(const cv::Mat &cameraMatrixRegistered, const cv::Size &sizeRegistered, const cv::Mat &cameraMatrixDepth, const cv::Size &sizeDepth, const cv::Mat &distortionDepth, const cv::Mat &rotation, const cv::Mat &translation, const float zNear=0.5f, const float zFar=12.0f, const int deviceId=-1)
void publishImages(const std::vector< cv::Mat > &images, const std_msgs::Header &header, const std::vector< Status > &status, const size_t frame, size_t &pubFrame, const size_t begin, const size_t end)
std::vector< int > compressionParams
void initTopics(const int32_t queueSize, const std::string &base_name)
ROSCPP_DECL void shutdown()
DepthRegistration * depthRegHighRes
cv::Mat cameraMatrixDepth
void createImage(const cv::Mat &image, const std_msgs::Header &header, const Image type, sensor_msgs::Image &msgImage) const
bool initRegistration(const std::string &method, const int32_t device, const double maxDepth)
ROSCONSOLE_DECL Formatter g_formatter
sensor_msgs::CameraInfo infoIR
libfreenect2::SyncMultiFrameListener * listenerColor
libfreenect2::Freenect2Device::IrCameraParams irParams
void help(const std::string &path)
#define K2_TOPIC_IMAGE_RECT
#define K2_TF_RGB_OPT_FRAME
bool loadCalibrationPoseFile(const std::string &filename, cv::Mat &rotation, cv::Mat &translation) const