31 #include "rtabmap/core/Version.h" 42 #include <opencv2/imgproc/types_c.h> 43 #if CV_MAJOR_VERSION >= 3 44 #include <opencv2/videoio/videoio_c.h> 48 #include <pcl/io/openni_grabber.h> 49 #include <pcl/io/oni_grabber.h> 50 #include <pcl/io/openni_camera/openni_depth_image.h> 51 #include <pcl/io/openni_camera/openni_image.h> 54 #ifdef RTABMAP_FREENECT 55 #include <libfreenect.h> 56 #ifdef FREENECT_DASH_INCLUDES 57 #include <libfreenect-registration.h> 59 #include <libfreenect_registration.h> 63 #ifdef RTABMAP_FREENECT2 64 #include <libfreenect2/libfreenect2.hpp> 65 #include <libfreenect2/frame_listener_impl.h> 66 #include <libfreenect2/registration.h> 67 #include <libfreenect2/packet_pipeline.h> 68 #include <libfreenect2/config.h> 75 #ifdef RTABMAP_REALSENSE 76 #include <librealsense/rs.hpp> 77 #ifdef RTABMAP_REALSENSE_SLAM 80 #include <librealsense/slam/slam.h> 84 #ifdef RTABMAP_REALSENSE2 85 #include <librealsense2/rs.hpp> 86 #include <librealsense2/rsutil.h> 87 #include <librealsense2/hpp/rs_processing.hpp> 88 #include <librealsense2/rs_advanced_mode.hpp> 91 #ifdef RTABMAP_OPENNI2 92 #include <OniVersion.h> 103 Camera(imageRate, localTransform),
112 #ifdef RTABMAP_OPENNI 121 #ifdef RTABMAP_OPENNI 137 #ifdef RTABMAP_OPENNI 138 void CameraOpenni::image_cb (
145 bool notify =
rgb_.empty();
147 cv::Mat rgbFrame(rgb->getHeight(), rgb->getWidth(), CV_8UC3);
148 rgb->fillRGB(rgb->getWidth(), rgb->getHeight(), rgbFrame.data);
149 cv::cvtColor(rgbFrame,
rgb_, CV_RGB2BGR);
151 depth_ = cv::Mat(rgb->getHeight(), rgb->getWidth(), CV_16UC1);
152 depth->fillDepthImageRaw(rgb->getWidth(), rgb->getHeight(), (
unsigned short*)
depth_.data);
165 #ifdef RTABMAP_OPENNI 185 boost::function<void (
188 float)>
f = boost::bind (&CameraOpenni::image_cb,
this, _1, _2, _3);
193 catch(
const pcl::IOException& ex)
195 UERROR(
"OpenNI exception: %s", ex.what());
205 UERROR(
"PCL not built with OpenNI! Cannot initialize CameraOpenNI");
212 #ifdef RTABMAP_OPENNI 221 #ifdef RTABMAP_OPENNI 233 #ifdef RTABMAP_OPENNI 238 UWARN(
"Not received new frames since 5 seconds, end of stream reached!");
248 float(
rgb_.cols/2) - 0.5f,
249 float(
rgb_.rows/2) - 0.5f,
250 this->getLocalTransform(),
262 UERROR(
"CameraOpenNI: RTAB-Map is not built with PCL having OpenNI support!");
274 return cv::getBuildInformation().find(
"OpenNI: YES") != std::string::npos;
278 Camera(imageRate, localTransform),
301 _capture.set( CV_CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CV_CAP_OPENNI_VGA_30HZ );
304 UINFO(
"Depth generator output mode:");
305 UINFO(
"FRAME_WIDTH %f",
_capture.get( CV_CAP_PROP_FRAME_WIDTH ));
306 UINFO(
"FRAME_HEIGHT %f",
_capture.get( CV_CAP_PROP_FRAME_HEIGHT ));
307 UINFO(
"FRAME_MAX_DEPTH %f mm",
_capture.get( CV_CAP_PROP_OPENNI_FRAME_MAX_DEPTH ));
308 UINFO(
"BASELINE %f mm",
_capture.get( CV_CAP_PROP_OPENNI_BASELINE ));
310 UINFO(
"Focal %f",
_capture.get( CV_CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH ));
311 UINFO(
"REGISTRATION %f",
_capture.get( CV_CAP_PROP_OPENNI_REGISTRATION ));
312 if(
_capture.get( CV_CAP_PROP_OPENNI_REGISTRATION ) == 0.0)
314 UERROR(
"Depth registration is not activated on this device!");
316 if(
_capture.get( CV_CAP_OPENNI_IMAGE_GENERATOR_PRESENT ) )
318 UINFO(
"Image generator output mode:");
319 UINFO(
"FRAME_WIDTH %f",
_capture.get( CV_CAP_OPENNI_IMAGE_GENERATOR+CV_CAP_PROP_FRAME_WIDTH ));
320 UINFO(
"FRAME_HEIGHT %f",
_capture.get( CV_CAP_OPENNI_IMAGE_GENERATOR+CV_CAP_PROP_FRAME_HEIGHT ));
321 UINFO(
"FPS %f",
_capture.get( CV_CAP_OPENNI_IMAGE_GENERATOR+CV_CAP_PROP_FPS ));
325 UERROR(
"Camera: Device doesn't contain image generator.");
351 _capture.retrieve(depth, CV_CAP_OPENNI_DEPTH_MAP );
352 _capture.retrieve(rgb, CV_CAP_OPENNI_BGR_IMAGE );
354 depth = depth.clone();
358 if(!rgb.empty() && !depth.empty())
363 float(rgb.cols/2) - 0.5f,
364 float(rgb.rows/2) - 0.5f,
365 this->getLocalTransform(),
373 ULOGGER_WARN(
"The camera must be initialized before requesting an image.");
384 #ifdef RTABMAP_OPENNI2 393 #if ONI_VERSION_MAJOR > 2 || (ONI_VERSION_MAJOR==2 && ONI_VERSION_MINOR >= 2) 401 const std::string & deviceId,
405 Camera(imageRate, localTransform)
406 #ifdef RTABMAP_OPENNI2
409 _device(new
openni::Device()),
410 _color(new
openni::VideoStream()),
411 _depth(new
openni::VideoStream()),
415 _openNI2StampsAndIDsUsed(
false),
424 #ifdef RTABMAP_OPENNI2 430 openni::OpenNI::shutdown();
440 #ifdef RTABMAP_OPENNI2 441 if(_color && _color->getCameraSettings())
443 return _color->getCameraSettings()->setAutoWhiteBalanceEnabled(enabled) == openni::STATUS_OK;
446 UERROR(
"CameraOpenNI2: RTAB-Map is not built with OpenNI2 support!");
453 #ifdef RTABMAP_OPENNI2 454 if(_color && _color->getCameraSettings())
456 return _color->getCameraSettings()->setAutoExposureEnabled(enabled) == openni::STATUS_OK;
459 UERROR(
"CameraOpenNI2: RTAB-Map is not built with OpenNI2 support!");
466 #ifdef RTABMAP_OPENNI2 467 #if ONI_VERSION_MAJOR > 2 || (ONI_VERSION_MAJOR==2 && ONI_VERSION_MINOR >= 2) 468 if(_color && _color->getCameraSettings())
470 return _color->getCameraSettings()->setExposure(value) == openni::STATUS_OK;
473 UERROR(
"CameraOpenNI2: OpenNI >= 2.2 required to use this method.");
476 UERROR(
"CameraOpenNI2: RTAB-Map is not built with OpenNI2 support!");
483 #ifdef RTABMAP_OPENNI2 484 #if ONI_VERSION_MAJOR > 2 || (ONI_VERSION_MAJOR==2 && ONI_VERSION_MINOR >= 2) 485 if(_color && _color->getCameraSettings())
487 return _color->getCameraSettings()->setGain(value) == openni::STATUS_OK;
490 UERROR(
"CameraOpenNI2: OpenNI >= 2.2 required to use this method.");
493 UERROR(
"CameraOpenNI2: RTAB-Map is not built with OpenNI2 support!");
500 #ifdef RTABMAP_OPENNI2 501 if(_color->isValid() && _depth->isValid())
503 return _depth->setMirroringEnabled(enabled) == openni::STATUS_OK &&
504 _color->setMirroringEnabled(enabled) == openni::STATUS_OK;
512 #ifdef RTABMAP_OPENNI2 513 _openNI2StampsAndIDsUsed = used;
519 #ifdef RTABMAP_OPENNI2 522 _depthHShift = horizontal;
523 _depthVShift = vertical;
529 #ifdef RTABMAP_OPENNI2 530 openni::OpenNI::initialize();
532 openni::Array<openni::DeviceInfo> devices;
533 openni::OpenNI::enumerateDevices(&devices);
534 for(
int i=0; i<devices.getSize(); ++i)
536 UINFO(
"Device %d: Name=%s URI=%s Vendor=%s",
540 devices[i].getVendor());
542 if(_deviceId.empty() && devices.getSize() == 0)
544 UERROR(
"CameraOpenNI2: No device detected!");
548 openni::Status error = _device->open(_deviceId.empty()?openni::ANY_DEVICE:_deviceId.c_str());
549 if(error != openni::STATUS_OK)
551 if(!_deviceId.empty())
553 UERROR(
"CameraOpenNI2: Cannot open device \"%s\" (error=%d).", _deviceId.c_str(), error);
558 UERROR(
"CameraOpenNI2: Cannot open device \"%s\" (error=%d).", devices[0].
getName(), error);
560 UERROR(
"CameraOpenNI2: Cannot open device \"%s\" (error=%d). Verify if \"%s\" is in udev rules: \"/lib/udev/rules.d/40-libopenni2-0.rules\". If not, add it and reboot.", devices[0].
getName(), error, devices[0].getUri());
565 openni::OpenNI::shutdown();
571 bool hardwareRegistration =
true;
572 if(!calibrationFolder.empty())
575 std::string calibrationName = _device->getDeviceInfo().getName();
576 if(!cameraName.empty())
578 calibrationName = cameraName;
580 _stereoModel.setName(calibrationName,
"depth",
"rgb");
581 hardwareRegistration = !_stereoModel.load(calibrationFolder, calibrationName,
false);
585 hardwareRegistration =
false;
589 if((_type !=
kTypeColorDepth && !_stereoModel.left().isValidForRectification()) ||
590 (_type ==
kTypeColorDepth && !_stereoModel.right().isValidForRectification()))
592 UWARN(
"Missing calibration files for camera \"%s\" in \"%s\" folder, default calibration used.",
593 calibrationName.c_str(), calibrationFolder.c_str());
595 else if(_type ==
kTypeColorDepth && _stereoModel.right().isValidForRectification() && hardwareRegistration)
597 UWARN(
"Missing extrinsic calibration file for camera \"%s\" in \"%s\" folder, default registration is used even if rgb is rectified!",
598 calibrationName.c_str(), calibrationFolder.c_str());
600 else if(_type ==
kTypeColorDepth && _stereoModel.right().isValidForRectification() && !hardwareRegistration)
602 UINFO(
"Custom calibration files for \"%s\" were found in \"%s\" folder. To use " 603 "factory calibration, remove the corresponding files from that directory.", calibrationName.c_str(), calibrationFolder.c_str());
609 if(_device->getPlaybackControl() &&
610 _device->getPlaybackControl()->setRepeatEnabled(
false) != openni::STATUS_OK)
612 UERROR(
"CameraOpenNI2: Cannot set repeat mode to false.");
614 openni::OpenNI::shutdown();
619 !_device->isImageRegistrationModeSupported(openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR))
621 UERROR(
"CameraOpenNI2: Device doesn't support depth/color registration.");
623 openni::OpenNI::shutdown();
627 if(_device->getSensorInfo(openni::SENSOR_DEPTH) ==
NULL ||
628 _device->getSensorInfo(_type==
kTypeColorDepth?openni::SENSOR_COLOR:openni::SENSOR_IR) ==
NULL)
630 UERROR(
"CameraOpenNI2: Cannot get sensor info for depth and %s.", _type==
kTypeColorDepth?
"color":
"ir");
632 openni::OpenNI::shutdown();
636 if(_depth->create(*_device, openni::SENSOR_DEPTH) != openni::STATUS_OK)
638 UERROR(
"CameraOpenNI2: Cannot create depth stream.");
640 openni::OpenNI::shutdown();
644 if(_color->create(*_device, _type==
kTypeColorDepth?openni::SENSOR_COLOR:openni::SENSOR_IR) != openni::STATUS_OK)
649 openni::OpenNI::shutdown();
654 _device->setImageRegistrationMode(openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR ) != openni::STATUS_OK)
656 UERROR(
"CameraOpenNI2: Failed to set depth/color registration.");
659 if (_device->setDepthColorSyncEnabled(
true) != openni::STATUS_OK)
661 UERROR(
"CameraOpenNI2: Failed to set depth color sync");
664 _depth->setMirroringEnabled(
false);
665 _color->setMirroringEnabled(
false);
667 const openni::Array<openni::VideoMode>& depthVideoModes = _depth->getSensorInfo().getSupportedVideoModes();
668 for(
int i=0; i<depthVideoModes.getSize(); ++i)
670 UINFO(
"CameraOpenNI2: Depth video mode %d: fps=%d, pixel=%d, w=%d, h=%d",
672 depthVideoModes[i].getFps(),
673 depthVideoModes[i].getPixelFormat(),
674 depthVideoModes[i].getResolutionX(),
675 depthVideoModes[i].getResolutionY());
678 const openni::Array<openni::VideoMode>& colorVideoModes = _color->getSensorInfo().getSupportedVideoModes();
679 for(
int i=0; i<colorVideoModes.getSize(); ++i)
681 UINFO(
"CameraOpenNI2: %s video mode %d: fps=%d, pixel=%d, w=%d, h=%d",
684 colorVideoModes[i].getFps(),
685 colorVideoModes[i].getPixelFormat(),
686 colorVideoModes[i].getResolutionX(),
687 colorVideoModes[i].getResolutionY());
690 openni::VideoMode mMode;
692 mMode.setResolution(640,480);
693 mMode.setPixelFormat(openni::PIXEL_FORMAT_DEPTH_1_MM);
694 _depth->setVideoMode(mMode);
696 openni::VideoMode mModeColor;
697 mModeColor.setFps(30);
698 mModeColor.setResolution(640,480);
699 mModeColor.setPixelFormat(openni::PIXEL_FORMAT_RGB888);
700 _color->setVideoMode(mModeColor);
702 UINFO(
"CameraOpenNI2: Using depth video mode: fps=%d, pixel=%d, w=%d, h=%d, H-FOV=%f rad, V-FOV=%f rad",
703 _depth->getVideoMode().getFps(),
704 _depth->getVideoMode().getPixelFormat(),
705 _depth->getVideoMode().getResolutionX(),
706 _depth->getVideoMode().getResolutionY(),
707 _depth->getHorizontalFieldOfView(),
708 _depth->getVerticalFieldOfView());
709 UINFO(
"CameraOpenNI2: Using %s video mode: fps=%d, pixel=%d, w=%d, h=%d, H-FOV=%f rad, V-FOV=%f rad",
711 _color->getVideoMode().getFps(),
712 _color->getVideoMode().getPixelFormat(),
713 _color->getVideoMode().getResolutionX(),
714 _color->getVideoMode().getResolutionY(),
715 _color->getHorizontalFieldOfView(),
716 _color->getVerticalFieldOfView());
718 if(_depth->getVideoMode().getResolutionX() != 640 ||
719 _depth->getVideoMode().getResolutionY() != 480 ||
720 _depth->getVideoMode().getPixelFormat() != openni::PIXEL_FORMAT_DEPTH_1_MM)
722 UERROR(
"Could not set depth format to 640x480 pixel=%d(mm)!",
723 openni::PIXEL_FORMAT_DEPTH_1_MM);
727 openni::OpenNI::shutdown();
730 if(_color->getVideoMode().getResolutionX() != 640 ||
731 _color->getVideoMode().getResolutionY() != 480 ||
732 _color->getVideoMode().getPixelFormat() != openni::PIXEL_FORMAT_RGB888)
734 UERROR(
"Could not set %s format to 640x480 pixel=%d!",
736 openni::PIXEL_FORMAT_RGB888);
740 openni::OpenNI::shutdown();
744 if(_color->getCameraSettings())
746 UINFO(
"CameraOpenNI2: AutoWhiteBalanceEnabled = %d", _color->getCameraSettings()->getAutoWhiteBalanceEnabled()?1:0);
747 UINFO(
"CameraOpenNI2: AutoExposureEnabled = %d", _color->getCameraSettings()->getAutoExposureEnabled()?1:0);
748 #if ONI_VERSION_MAJOR > 2 || (ONI_VERSION_MAJOR==2 && ONI_VERSION_MINOR >= 2) 749 UINFO(
"CameraOpenNI2: Exposure = %d", _color->getCameraSettings()->getExposure());
750 UINFO(
"CameraOpenNI2: GAIN = %d", _color->getCameraSettings()->getGain());
756 _depthFx = float(_color->getVideoMode().getResolutionX()/2) /
std::tan(_color->getHorizontalFieldOfView()/2.0f);
757 _depthFy = float(_color->getVideoMode().getResolutionY()/2) /
std::tan(_color->getVerticalFieldOfView()/2.0f);
761 _depthFx = float(_depth->getVideoMode().getResolutionX()/2) /
std::tan(_depth->getHorizontalFieldOfView()/2.0f);
762 _depthFy = float(_depth->getVideoMode().getResolutionY()/2) /
std::tan(_depth->getVerticalFieldOfView()/2.0f);
764 UINFO(
"depth fx=%f fy=%f", _depthFx, _depthFy);
768 UWARN(
"With type IR-only, depth stream will not be started");
771 if((_type !=
kTypeIR && _depth->start() != openni::STATUS_OK) ||
772 _color->start() != openni::STATUS_OK)
774 UERROR(
"CameraOpenNI2: Cannot start depth and/or color streams.");
780 openni::OpenNI::shutdown();
788 UERROR(
"CameraOpenNI2: RTAB-Map is not built with OpenNI2 support!");
800 #ifdef RTABMAP_OPENNI2 803 return _device->getDeviceInfo().getName();
812 #ifdef RTABMAP_OPENNI2 813 int readyStream = -1;
814 if(_device->isValid() &&
817 _device->getSensorInfo(openni::SENSOR_DEPTH) !=
NULL &&
818 _device->getSensorInfo(_type==
kTypeColorDepth?openni::SENSOR_COLOR:openni::SENSOR_IR) !=
NULL)
820 openni::VideoStream* depthStream[] = {_depth};
821 openni::VideoStream* colorStream[] = {_color};
822 if((_type !=
kTypeIR && openni::OpenNI::waitForAnyStream(depthStream, 1, &readyStream, 5000) != openni::STATUS_OK) ||
823 openni::OpenNI::waitForAnyStream(colorStream, 1, &readyStream, 5000) != openni::STATUS_OK)
825 UWARN(
"No frames received since the last 5 seconds, end of stream is reached!");
829 openni::VideoFrameRef depthFrame, colorFrame;
832 _depth->readFrame(&depthFrame);
834 _color->readFrame(&colorFrame);
836 if((_type ==
kTypeIR || depthFrame.isValid()) && colorFrame.isValid())
841 h=depthFrame.getHeight();
842 w=depthFrame.getWidth();
843 depth = cv::Mat(h, w, CV_16U, (
void*)depthFrame.getData()).clone();
845 h=colorFrame.getHeight();
846 w=colorFrame.getWidth();
847 cv::Mat tmp(h, w, CV_8UC3, (
void *)colorFrame.getData());
850 cv::cvtColor(tmp, rgb, CV_RGB2BGR);
857 UASSERT(_depthFx != 0.0
f && _depthFy != 0.0
f);
858 if(!rgb.empty() && (_type ==
kTypeIR || !depth.empty()))
864 float(rgb.cols/2) - 0.5f,
865 float(rgb.rows/2) - 0.5f,
866 this->getLocalTransform(),
872 if(_stereoModel.right().isValidForRectification())
875 model = _stereoModel.right();
877 if(_stereoModel.left().isValidForRectification() && !_stereoModel.stereoTransform().isNull())
879 if (_depthHShift > 0 || _depthVShift > 0)
881 cv::Mat out = cv::Mat::zeros(depth.size(), depth.type());
882 depth(cv::Rect(_depthHShift, _depthVShift, depth.cols - _depthHShift, depth.rows - _depthVShift)).copyTo(out(cv::Rect(0, 0, depth.cols - _depthHShift, depth.rows - _depthVShift)));
885 depth = _stereoModel.left().rectifyImage(depth, 0);
886 depth =
util2d::registerDepth(depth, _stereoModel.left().K(), rgb.size(), _stereoModel.right().K(), _stereoModel.stereoTransform());
892 if(_stereoModel.left().isValidForRectification())
894 rgb = _stereoModel.left().rectifyImage(rgb);
897 depth = _stereoModel.left().rectifyImage(depth, 0);
899 model = _stereoModel.left();
904 if(_openNI2StampsAndIDsUsed)
906 data =
SensorData(rgb, depth, model, depthFrame.getFrameIndex(), double(depthFrame.getTimestamp()) / 1000000.0);
917 ULOGGER_WARN(
"The camera must be initialized before requesting an image.");
920 UERROR(
"CameraOpenNI2: RTAB-Map is not built with OpenNI2 support!");
925 #ifdef RTABMAP_FREENECT 929 class FreenectDevice :
public UThread {
931 FreenectDevice(
freenect_context * ctx,
int index,
bool color =
true,
bool registered =
true) :
934 registered_(registered),
945 if(device_ && freenect_close_device(device_) < 0){}
948 const std::string &
getSerial()
const {
return serial_;}
955 freenect_close_device(device_);
959 std::vector<std::string> deviceSerials;
960 freenect_device_attributes* attr_list;
961 freenect_device_attributes* item;
962 freenect_list_device_attributes(ctx_, &attr_list);
963 for (item = attr_list; item !=
NULL; item = item->next) {
964 deviceSerials.push_back(std::string(item->camera_serial));
966 freenect_free_device_attributes(attr_list);
968 if(freenect_open_device(ctx_, &device_, index_) < 0)
970 UERROR(
"FreenectDevice: Cannot open Kinect");
974 if(index_ >= 0 && index_ < (
int)deviceSerials.size())
976 serial_ = deviceSerials[index_];
980 UERROR(
"Could not get serial for index %d", index_);
983 UINFO(
"color=%d registered=%d", color_?1:0, registered_?1:0);
985 freenect_set_user(device_,
this);
986 freenect_frame_mode videoMode = freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, color_?FREENECT_VIDEO_RGB:FREENECT_VIDEO_IR_8BIT);
987 freenect_frame_mode depthMode = freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, color_ && registered_?FREENECT_DEPTH_REGISTERED:FREENECT_DEPTH_MM);
988 if(!videoMode.is_valid)
990 UERROR(
"Freenect: video mode selected not valid!");
993 if(!depthMode.is_valid)
995 UERROR(
"Freenect: depth mode selected not valid!");
998 UASSERT(videoMode.data_bits_per_pixel == 8 || videoMode.data_bits_per_pixel == 24);
999 UASSERT(depthMode.data_bits_per_pixel == 16);
1000 freenect_set_video_mode(device_, videoMode);
1001 freenect_set_depth_mode(device_, depthMode);
1002 rgbIrBuffer_ = cv::Mat(cv::Size(videoMode.width,videoMode.height), color_?CV_8UC3:CV_8UC1);
1003 depthBuffer_ = cv::Mat(cv::Size(depthMode.width,depthMode.height), CV_16UC1);
1004 freenect_set_depth_buffer(device_, depthBuffer_.data);
1005 freenect_set_video_buffer(device_, rgbIrBuffer_.data);
1006 freenect_set_depth_callback(device_, freenect_depth_callback);
1007 freenect_set_video_callback(device_, freenect_video_callback);
1009 float rgb_focal_length_sxga = 1050.0f;
1010 float width_sxga = 1280.0f;
1011 float width = freenect_get_current_depth_mode(device_).width;
1012 float scale = width / width_sxga;
1013 if(color_ && registered_)
1015 depthFocal_ = rgb_focal_length_sxga *
scale;
1019 freenect_registration reg = freenect_copy_registration(device_);
1020 float depth_focal_length_sxga = reg.zero_plane_info.reference_distance / reg.zero_plane_info.reference_pixel_size;
1021 freenect_destroy_registration(®);
1023 depthFocal_ = depth_focal_length_sxga *
scale;
1026 UINFO(
"FreenectDevice: Depth focal = %f", depthFocal_);
1030 float getDepthFocal()
const {
return depthFocal_;}
1032 void getData(cv::Mat & rgb, cv::Mat & depth)
1034 if(this->isRunning())
1036 if(!dataReady_.acquire(1, 5000))
1038 UERROR(
"Not received any frames since 5 seconds, try to restart the camera again.");
1043 rgb = rgbIrLastFrame_;
1044 depth = depthLastFrame_;
1045 rgbIrLastFrame_ = cv::Mat();
1046 depthLastFrame_= cv::Mat();
1053 void VideoCallback(
void* rgb)
1055 UASSERT(rgbIrBuffer_.data == rgb);
1057 bool notify = rgbIrLastFrame_.empty();
1061 cv::cvtColor(rgbIrBuffer_, rgbIrLastFrame_, CV_RGB2BGR);
1065 rgbIrLastFrame_ = rgbIrBuffer_.clone();
1067 if(!depthLastFrame_.empty() && notify)
1069 dataReady_.release();
1074 void DepthCallback(
void* depth)
1076 UASSERT(depthBuffer_.data == depth);
1078 bool notify = depthLastFrame_.empty();
1079 depthLastFrame_ = depthBuffer_.clone();
1080 if(!rgbIrLastFrame_.empty() && notify)
1082 dataReady_.release();
1087 if(device_ && freenect_start_video(device_) < 0)
UERROR(
"Cannot start RGB callback");
1090 if(device_ && freenect_stop_video(device_) < 0)
UERROR(
"Cannot stop RGB callback");
1093 if(device_ && freenect_start_depth(device_) < 0)
UERROR(
"Cannot start depth callback");
1096 if(device_ && freenect_stop_depth(device_) < 0)
UERROR(
"Cannot stop depth callback");
1099 virtual void mainLoopBegin()
1105 virtual void mainLoop()
1110 if(freenect_process_events_timeout(ctx_, &t) < 0)
1112 UERROR(
"FreenectDevice: Cannot process freenect events");
1117 virtual void mainLoopEnd()
1121 dataReady_.release();
1125 FreenectDevice* device =
static_cast<FreenectDevice*
>(freenect_get_user(dev));
1126 device->DepthCallback(depth);
1129 FreenectDevice* device =
static_cast<FreenectDevice*
>(freenect_get_user(dev));
1130 device->VideoCallback(video);
1134 FreenectDevice(
const FreenectDevice& );
1135 const FreenectDevice& operator=(
const FreenectDevice& );
1141 std::string serial_;
1144 cv::Mat depthBuffer_;
1145 cv::Mat rgbIrBuffer_;
1147 cv::Mat depthLastFrame_;
1148 cv::Mat rgbIrLastFrame_;
1159 #ifdef RTABMAP_FREENECT 1167 Camera(imageRate, localTransform)
1168 #ifdef RTABMAP_FREENECT
1170 deviceId_(deviceId),
1176 #ifdef RTABMAP_FREENECT 1177 if(freenect_init(&ctx_,
NULL) < 0)
UERROR(
"Cannot initialize freenect library");
1179 freenect_select_subdevices(ctx_, static_cast<freenect_device_flags>(FREENECT_DEVICE_CAMERA));
1185 #ifdef RTABMAP_FREENECT 1188 freenectDevice_->join(
true);
1189 delete freenectDevice_;
1190 freenectDevice_ = 0;
1194 if(freenect_shutdown(ctx_) < 0){}
1201 #ifdef RTABMAP_FREENECT 1204 freenectDevice_->join(
true);
1205 delete freenectDevice_;
1206 freenectDevice_ = 0;
1209 if(ctx_ && freenect_num_devices(ctx_) > 0)
1212 bool hardwareRegistration =
true;
1214 if(!calibrationFolder.empty())
1217 FreenectDevice dev(ctx_, deviceId_);
1220 UERROR(
"CameraFreenect: Init failed!");
1222 std::string calibrationName = dev.getSerial();
1223 if(!cameraName.empty())
1225 calibrationName = cameraName;
1227 stereoModel_.setName(calibrationName,
"depth",
"rgb");
1228 hardwareRegistration = !stereoModel_.load(calibrationFolder, calibrationName,
false);
1232 hardwareRegistration =
false;
1236 if((type_ ==
kTypeIRDepth && !stereoModel_.left().isValidForRectification()) ||
1237 (type_ ==
kTypeColorDepth && !stereoModel_.right().isValidForRectification()))
1239 UWARN(
"Missing calibration files for camera \"%s\" in \"%s\" folder, default calibration used.",
1240 calibrationName.c_str(), calibrationFolder.c_str());
1242 else if(type_ ==
kTypeColorDepth && stereoModel_.right().isValidForRectification() && hardwareRegistration)
1244 UWARN(
"Missing extrinsic calibration file for camera \"%s\" in \"%s\" folder, default registration is used even if rgb is rectified!",
1245 calibrationName.c_str(), calibrationFolder.c_str());
1247 else if(type_ ==
kTypeColorDepth && stereoModel_.right().isValidForRectification() && !hardwareRegistration)
1249 UINFO(
"Custom calibration files for \"%s\" were found in \"%s\" folder. To use " 1250 "factory calibration, remove the corresponding files from that directory.", calibrationName.c_str(), calibrationFolder.c_str());
1254 freenectDevice_ =
new FreenectDevice(ctx_, deviceId_, type_==
kTypeColorDepth, hardwareRegistration);
1255 if(freenectDevice_->init())
1257 freenectDevice_->start();
1263 UERROR(
"CameraFreenect: Init failed!");
1265 delete freenectDevice_;
1266 freenectDevice_ = 0;
1270 UERROR(
"CameraFreenect: No devices connected!");
1273 UERROR(
"CameraFreenect: RTAB-Map is not built with Freenect support!");
1285 #ifdef RTABMAP_FREENECT 1288 return freenectDevice_->getSerial();
1297 #ifdef RTABMAP_FREENECT 1298 if(ctx_ && freenectDevice_)
1300 if(freenectDevice_->isRunning())
1303 freenectDevice_->getData(rgb, depth);
1304 if(!rgb.empty() && !depth.empty())
1306 UASSERT(freenectDevice_->getDepthFocal() != 0.0f);
1310 freenectDevice_->getDepthFocal(),
1311 freenectDevice_->getDepthFocal(),
1312 float(rgb.cols/2) - 0.5f,
1313 float(rgb.rows/2) - 0.5f,
1320 if(stereoModel_.left().isValidForRectification())
1323 depth = stereoModel_.left().rectifyImage(depth, 0);
1324 model = stereoModel_.left();
1329 if(stereoModel_.right().isValidForRectification())
1331 rgb = stereoModel_.right().rectifyImage(rgb);
1332 model = stereoModel_.right();
1334 if(stereoModel_.left().isValidForRectification() && !stereoModel_.stereoTransform().isNull())
1336 depth = stereoModel_.left().rectifyImage(depth, 0);
1337 depth =
util2d::registerDepth(depth, stereoModel_.left().K(), rgb.size(), stereoModel_.right().K(), stereoModel_.stereoTransform());
1348 UERROR(
"CameraFreenect: Re-initialization needed!");
1349 delete freenectDevice_;
1350 freenectDevice_ = 0;
1354 UERROR(
"CameraFreenect: RTAB-Map is not built with Freenect support!");
1364 #ifdef RTABMAP_FREENECT2 1378 bool bilateralFiltering,
1379 bool edgeAwareFiltering,
1380 bool noiseFiltering,
1381 const std::string & pipelineName) :
1382 Camera(imageRate, localTransform)
1383 #ifdef RTABMAP_FREENECT2
1385 deviceId_(deviceId),
1391 minKinect2Depth_(minDepth),
1392 maxKinect2Depth_(maxDepth),
1393 bilateralFiltering_(bilateralFiltering),
1394 edgeAwareFiltering_(edgeAwareFiltering),
1395 noiseFiltering_(noiseFiltering),
1396 pipelineName_(pipelineName)
1399 #ifdef RTABMAP_FREENECT2 1400 UASSERT(minKinect2Depth_ < maxKinect2Depth_ && minKinect2Depth_>0 && maxKinect2Depth_>0 && maxKinect2Depth_<=65.535
f);
1401 freenect2_ =
new libfreenect2::Freenect2();
1405 listener_ =
new libfreenect2::SyncMultiFrameListener(libfreenect2::Frame::Color | libfreenect2::Frame::Ir);
1408 listener_ =
new libfreenect2::SyncMultiFrameListener(libfreenect2::Frame::Ir | libfreenect2::Frame::Depth);
1414 listener_ =
new libfreenect2::SyncMultiFrameListener(libfreenect2::Frame::Color | libfreenect2::Frame::Depth);
1422 #ifdef RTABMAP_FREENECT2 1437 #ifdef RTABMAP_FREENECT2 1438 libfreenect2::PacketPipeline *createPacketPipelineByName(
const std::string & name)
1440 std::string availablePipelines;
1441 #if defined(LIBFREENECT2_WITH_OPENGL_SUPPORT) 1442 availablePipelines +=
"gl ";
1445 UINFO(
"Using 'gl' pipeline.");
1446 return new libfreenect2::OpenGLPacketPipeline();
1449 #if defined(LIBFREENECT2_WITH_CUDA_SUPPORT) 1450 availablePipelines +=
"cuda cudakde ";
1453 UINFO(
"Using 'cuda' pipeline.");
1454 return new libfreenect2::CudaPacketPipeline();
1456 if (name ==
"cudakde")
1458 UINFO(
"Using 'cudakde' pipeline.");
1459 return new libfreenect2::CudaKdePacketPipeline();
1462 #if defined(LIBFREENECT2_WITH_OPENCL_SUPPORT) 1463 availablePipelines +=
"cl clkde ";
1466 UINFO(
"Using 'cl' pipeline.");
1467 return new libfreenect2::OpenCLPacketPipeline();
1469 if (name ==
"clkde")
1471 UINFO(
"Using 'clkde' pipeline.");
1472 return new libfreenect2::OpenCLKdePacketPipeline();
1475 availablePipelines +=
"cpu";
1478 UINFO(
"Using 'cpu' pipeline.");
1479 return new libfreenect2::CpuPacketPipeline();
1484 UERROR(
"'%s' pipeline is not available. Available pipelines are: \"%s\". Default one is used instead (first one in the list).",
1485 name.c_str(), availablePipelines.c_str());
1489 #if defined(LIBFREENECT2_WITH_OPENGL_SUPPORT) 1490 UINFO(
"Using 'gl' pipeline.");
1491 return new libfreenect2::OpenGLPacketPipeline();
1492 #elif defined(LIBFREENECT2_WITH_CUDA_SUPPORT) 1493 UINFO(
"Using 'cuda' pipeline.");
1494 return new libfreenect2::CudaPacketPipeline();
1495 #elif defined(LIBFREENECT2_WITH_OPENCL_SUPPORT) 1496 UINFO(
"Using 'cl' pipeline.");
1497 return new libfreenect2::OpenCLPacketPipeline();
1499 UINFO(
"Using 'cpu' pipeline.");
1500 return new libfreenect2::CpuPacketPipeline();
1507 #ifdef RTABMAP_FREENECT2 1521 libfreenect2::PacketPipeline * pipeline = createPacketPipelineByName(pipelineName_);
1525 UDEBUG(
"Opening default device...");
1526 dev_ = freenect2_->openDefaultDevice(pipeline);
1531 UDEBUG(
"Opening device ID=%d...", deviceId_);
1532 dev_ = freenect2_->openDevice(deviceId_, pipeline);
1543 libfreenect2::Freenect2Device::Config
config;
1544 config.EnableBilateralFilter = bilateralFiltering_;
1545 config.EnableEdgeAwareFilter = edgeAwareFiltering_;
1546 config.MinDepth = minKinect2Depth_;
1547 config.MaxDepth = maxKinect2Depth_;
1548 dev_->setConfiguration(config);
1550 dev_->setColorFrameListener(listener_);
1551 dev_->setIrAndDepthFrameListener(listener_);
1555 UINFO(
"CameraFreenect2: device serial: %s", dev_->getSerialNumber().c_str());
1556 UINFO(
"CameraFreenect2: device firmware: %s", dev_->getFirmwareVersion().c_str());
1559 libfreenect2::Freenect2Device::IrCameraParams depthParams = dev_->getIrCameraParams();
1560 libfreenect2::Freenect2Device::ColorCameraParams colorParams = dev_->getColorCameraParams();
1561 reg_ =
new libfreenect2::Registration(depthParams, colorParams);
1565 if(!calibrationFolder.empty())
1567 std::string calibrationName = dev_->getSerialNumber();
1568 if(!cameraName.empty())
1570 calibrationName = cameraName;
1572 stereoModel_.setName(calibrationName,
"depth",
"rgb");
1573 if(!stereoModel_.load(calibrationFolder, calibrationName,
false))
1575 UWARN(
"Missing calibration files for camera \"%s\" in \"%s\" folder, default calibration " 1576 "is used. Note that from version 0.11.10, calibration suffixes for Freenect2 driver have " 1577 "changed from \"_left\"->\"_depth\" and \"_right\"->\"_rgb\". You can safely rename " 1578 "the calibration files to avoid recalibrating.",
1579 calibrationName.c_str(), calibrationFolder.c_str());
1583 UINFO(
"Custom calibration files for \"%s\" were found in \"%s\" folder. To use " 1584 "factory calibration, remove the corresponding files from that directory.", calibrationName.c_str(), calibrationFolder.c_str());
1588 UWARN(
"Freenect2: When using custom calibration file, type " 1589 "kTypeColor2DepthSD is not supported. kTypeDepth2ColorSD is used instead...");
1594 cv::Mat colorP = stereoModel_.right().P();
1595 cv::Size colorSize = stereoModel_.right().imageSize();
1598 colorP.at<
double>(0,0)/=2.0
f;
1599 colorP.at<
double>(1,1)/=2.0
f;
1600 colorP.at<
double>(0,2)/=2.0
f;
1601 colorP.at<
double>(1,2)/=2.0
f;
1603 colorSize.height/=2;
1605 cv::Mat depthP = stereoModel_.left().P();
1606 cv::Size depthSize = stereoModel_.left().imageSize();
1607 float ratioY = float(colorSize.height)/float(depthSize.height);
1608 float ratioX = float(colorSize.width)/float(depthSize.width);
1609 depthP.at<
double>(0,0)*=ratioX;
1610 depthP.at<
double>(1,1)*=ratioY;
1611 depthP.at<
double>(0,2)*=ratioX;
1612 depthP.at<
double>(1,2)*=ratioY;
1613 depthSize.width*=ratioX;
1614 depthSize.height*=ratioY;
1620 stereoModel_.R(), stereoModel_.T(), stereoModel_.E(), stereoModel_.F());
1629 UERROR(
"CameraFreenect2: no device connected or failure opening the default one! Note that rtabmap should link on libusb of libfreenect2. " 1630 "Tip, before starting rtabmap: \"$ export LD_LIBRARY_PATH=~/libfreenect2/depends/libusb/lib:$LD_LIBRARY_PATH\"");
1633 UERROR(
"CameraFreenect2: RTAB-Map is not built with Freenect2 support!");
1645 #ifdef RTABMAP_FREENECT2 1648 return dev_->getSerialNumber();
1657 #ifdef RTABMAP_FREENECT2 1658 if(dev_ && listener_)
1660 libfreenect2::FrameMap frames;
1661 #ifndef LIBFREENECT2_THREADING_STDLIB 1662 UDEBUG(
"Waiting for new frames... If it is stalled here, rtabmap should link on libusb of libfreenect2. " 1663 "Tip, before starting rtabmap: \"$ export LD_LIBRARY_PATH=~/libfreenect2/depends/libusb/lib:$LD_LIBRARY_PATH\"");
1664 listener_->waitForNewFrame(frames);
1666 if(!listener_->waitForNewFrame(frames, 1000))
1668 UWARN(
"CameraFreenect2: Failed to get frames! rtabmap should link on libusb of libfreenect2. " 1669 "Tip, before starting rtabmap: \"$ export LD_LIBRARY_PATH=~/libfreenect2/depends/libusb/lib:$LD_LIBRARY_PATH\"");
1675 libfreenect2::Frame *rgbFrame = 0;
1676 libfreenect2::Frame *irFrame = 0;
1677 libfreenect2::Frame *depthFrame = 0;
1682 rgbFrame =
uValue(frames, libfreenect2::Frame::Color, (libfreenect2::Frame*)0);
1683 irFrame =
uValue(frames, libfreenect2::Frame::Ir, (libfreenect2::Frame*)0);
1686 irFrame =
uValue(frames, libfreenect2::Frame::Ir, (libfreenect2::Frame*)0);
1687 depthFrame =
uValue(frames, libfreenect2::Frame::Depth, (libfreenect2::Frame*)0);
1694 rgbFrame =
uValue(frames, libfreenect2::Frame::Color, (libfreenect2::Frame*)0);
1695 depthFrame =
uValue(frames, libfreenect2::Frame::Depth, (libfreenect2::Frame*)0);
1700 float fx=0,fy=0,cx=0,cy=0;
1701 if(irFrame && depthFrame)
1703 cv::Mat irMat((
int)irFrame->height, (
int)irFrame->width, CV_32FC1, irFrame->data);
1705 float maxIr_ = 0x7FFF;
1707 const float factor = 255.0f / float((maxIr_ - minIr_));
1708 rgb = cv::Mat(irMat.rows, irMat.cols, CV_8UC1);
1709 for(
int i=0; i<irMat.rows; ++i)
1711 for(
int j=0; j<irMat.cols; ++j)
1713 rgb.at<
unsigned char>(i, j) = (
unsigned char)
std::min(
float(
std::max(irMat.at<
float>(i,j) - minIr_, 0.0f)) * factor, 255.0f);
1717 cv::Mat((
int)depthFrame->height, (
int)depthFrame->width, CV_32FC1, depthFrame->data).convertTo(depth, CV_16U, 1);
1719 cv::flip(rgb, rgb, 1);
1720 cv::flip(depth, depth, 1);
1722 if(stereoModel_.isValidForRectification())
1725 rgb = stereoModel_.left().rectifyImage(rgb);
1726 depth = stereoModel_.left().rectifyDepth(depth);
1727 fx = stereoModel_.left().fx();
1728 fy = stereoModel_.left().fy();
1729 cx = stereoModel_.left().cx();
1730 cy = stereoModel_.left().cy();
1734 libfreenect2::Freenect2Device::IrCameraParams params = dev_->getIrCameraParams();
1744 if(stereoModel_.isValidForRectification())
1746 cv::Mat rgbMatC4((
int)rgbFrame->height, (
int)rgbFrame->width, CV_8UC4, rgbFrame->data);
1748 #ifdef LIBFREENECT2_WITH_TEGRAJPEG_SUPPORT 1750 cv::cvtColor(rgbMatC4, rgbMat, CV_RGBA2BGR);
1754 cv::cvtColor(rgbMatC4, rgbMat, CV_BGRA2BGR);
1757 cv::flip(rgbMat, rgb, 1);
1760 rgb = stereoModel_.right().rectifyImage(rgb);
1764 cv::Mat((
int)irFrame->height, (
int)irFrame->width, CV_32FC1, irFrame->data).convertTo(depth, CV_16U, 1);
1765 cv::flip(depth, depth, 1);
1766 depth = stereoModel_.left().rectifyImage(depth);
1771 cv::Mat((
int)depthFrame->height, (
int)depthFrame->width, CV_32FC1, depthFrame->data).convertTo(depth, CV_16U, 1);
1772 cv::flip(depth, depth, 1);
1775 depth = stereoModel_.left().rectifyDepth(depth);
1777 bool registered =
true;
1782 stereoModel_.left().P().colRange(0,3).rowRange(0,3),
1784 stereoModel_.right().P().colRange(0,3).rowRange(0,3),
1785 stereoModel_.stereoTransform());
1787 fx = stereoModel_.right().fx();
1788 fy = stereoModel_.right().fy();
1789 cx = stereoModel_.right().cx();
1790 cy = stereoModel_.right().cy();
1794 fx = stereoModel_.left().fx();
1795 fy = stereoModel_.left().fy();
1796 cx = stereoModel_.left().cx();
1797 cy = stereoModel_.left().cy();
1806 cv::Mat rgbMatC4((
int)rgbFrame->height, (
int)rgbFrame->width, CV_8UC4, rgbFrame->data);
1808 #ifdef LIBFREENECT2_WITH_TEGRAJPEG_SUPPORT 1810 cv::cvtColor(rgbMatC4, rgbMat, CV_RGB2BGR);
1814 cv::cvtColor(rgbMatC4, rgbMat, CV_BGRA2BGR);
1817 cv::flip(rgbMat, rgb, 1);
1819 cv::Mat((
int)irFrame->height, (
int)irFrame->width, CV_32FC1, irFrame->data).convertTo(depth, CV_16U, 1);
1820 cv::flip(depth, depth, 1);
1827 float maxDepth = maxKinect2Depth_*1000.0f;
1828 float minDepth = minKinect2Depth_*1000.0f;
1832 libfreenect2::Frame depthUndistorted(512, 424, 4);
1833 libfreenect2::Frame rgbRegistered(512, 424, 4);
1838 cv::Mat depthMat = cv::Mat((
int)depthFrame->height, (
int)depthFrame->width, CV_32FC1, depthFrame->data);
1839 for(
int dx=0; dx<depthMat.cols; ++dx)
1841 bool onEdgeX = dx==depthMat.cols-1;
1842 for(
int dy=0; dy<depthMat.rows; ++dy)
1844 bool onEdge = onEdgeX || dy==depthMat.rows-1;
1846 float & dz = depthMat.at<
float>(dy,dx);
1847 if(dz>=minDepth && dz <= maxDepth)
1850 if(noiseFiltering_ && !onEdge)
1853 const float & dz1 = depthMat.at<
float>(dy,dx+1);
1854 const float & dz2 = depthMat.at<
float>(dy+1,dx);
1855 const float & dz3 = depthMat.at<
float>(dy+1,dx+1);
1856 if( dz1>=minDepth && dz1 <= maxDepth &&
1857 dz2>=minDepth && dz2 <= maxDepth &&
1858 dz3>=minDepth && dz3 <= maxDepth)
1860 float avg = (dz + dz1 + dz2 + dz3) / 4.0
f;
1861 float thres = 0.01f*avg;
1863 if( fabs(dz-avg) < thres &&
1864 fabs(dz1-avg) < thres &&
1865 fabs(dz2-avg) < thres &&
1866 fabs(dz3-avg) < thres)
1878 libfreenect2::Frame bidDepth(1920, 1082, 4);
1879 reg_->apply(rgbFrame, depthFrame, &depthUndistorted, &rgbRegistered,
true, &bidDepth);
1884 rgbMatBGRA = cv::Mat((
int)rgbRegistered.height, (
int)rgbRegistered.width, CV_8UC4, rgbRegistered.data);
1885 depthMat = cv::Mat((
int)depthUndistorted.height, (
int)depthUndistorted.width, CV_32FC1, depthUndistorted.data);
1888 libfreenect2::Freenect2Device::IrCameraParams params = dev_->getIrCameraParams();
1896 rgbMatBGRA = cv::Mat((
int)rgbFrame->height, (
int)rgbFrame->width, CV_8UC4, rgbFrame->data);
1897 depthMat = cv::Mat((
int)bidDepth.height, (
int)bidDepth.width, CV_32FC1, bidDepth.data);
1901 libfreenect2::Freenect2Device::ColorCameraParams params = dev_->getColorCameraParams();
1909 depth = cv::Mat(depthMat.size(), CV_16UC1);
1910 for(
int dx=0; dx<depthMat.cols; ++dx)
1912 for(
int dy=0; dy<depthMat.rows; ++dy)
1914 unsigned short z = 0;
1915 const float & dz = depthMat.at<
float>(dy,dx);
1916 if(dz>=minDepth && dz <= maxDepth)
1918 z = (
unsigned short)dz;
1920 depth.at<
unsigned short>(dy,(depthMat.cols-1)-dx) = z;
1925 #ifdef LIBFREENECT2_WITH_TEGRAJPEG_SUPPORT 1927 cv::cvtColor(rgbMatBGRA, rgb, CV_RGBA2BGR);
1931 cv::cvtColor(rgbMatBGRA, rgb, CV_BGRA2BGR);
1934 cv::flip(rgb, rgb, 1);
1939 cv::Mat rgbMatBGRA = cv::Mat((
int)rgbFrame->height, (
int)rgbFrame->width, CV_8UC4, rgbFrame->data);
1943 cv::resize(rgbMatBGRA, tmp, cv::Size(), 0.5, 0.5, cv::INTER_AREA);
1947 #ifdef LIBFREENECT2_WITH_TEGRAJPEG_SUPPORT 1949 cv::cvtColor(rgbMatBGRA, rgb, CV_RGBA2BGR);
1953 cv::cvtColor(rgbMatBGRA, rgb, CV_BGRA2BGR);
1956 cv::flip(rgb, rgb, 1);
1958 cv::Mat depthFrameMat = cv::Mat((
int)depthFrame->height, (
int)depthFrame->width, CV_32FC1, depthFrame->data);
1959 depth = cv::Mat::zeros(rgbMatBGRA.rows, rgbMatBGRA.cols, CV_16U);
1960 for(
int dx=0; dx<depthFrameMat.cols-1; ++dx)
1962 for(
int dy=0; dy<depthFrameMat.rows-1; ++dy)
1964 float dz = depthFrameMat.at<
float>(dy,dx);
1965 if(dz>=minDepth && dz<=maxDepth)
1967 bool goodDepth =
true;
1971 float dz1 = depthFrameMat.at<
float>(dy,dx+1);
1972 float dz2 = depthFrameMat.at<
float>(dy+1,dx);
1973 float dz3 = depthFrameMat.at<
float>(dy+1,dx+1);
1974 if(dz1>=minDepth && dz1 <= maxDepth &&
1975 dz2>=minDepth && dz2 <= maxDepth &&
1976 dz3>=minDepth && dz3 <= maxDepth)
1978 float avg = (dz + dz1 + dz2 + dz3) / 4.0
f;
1979 float thres = 0.01 * avg;
1980 if( fabs(dz-avg) < thres &&
1981 fabs(dz1-avg) < thres &&
1982 fabs(dz2-avg) < thres &&
1983 fabs(dz3-avg) < thres)
1992 reg_->apply(dx, dy, dz, cx, cy);
1998 int rcx = cvRound(cx);
1999 int rcy = cvRound(cy);
2002 unsigned short & zReg = depth.at<
unsigned short>(rcy, rcx);
2003 if(zReg == 0 || zReg > (
unsigned short)dz)
2005 zReg = (
unsigned short)dz;
2014 cv::flip(depth, depth, 1);
2015 libfreenect2::Freenect2Device::ColorCameraParams params = dev_->getColorCameraParams();
2039 listener_->release(frames);
2043 UERROR(
"CameraFreenect2: RTAB-Map is not built with Freenect2 support!");
2054 template<
class Interface>
2055 inline void SafeRelease(Interface *& pInterfaceToRelease)
2057 if (pInterfaceToRelease !=
NULL)
2059 pInterfaceToRelease->Release();
2060 pInterfaceToRelease =
NULL;
2079 Camera(imageRate, localTransform)
2083 pKinectSensor_(
NULL),
2084 pCoordinateMapper_(
NULL),
2087 pMultiSourceFrameReader_(
NULL),
2088 pColorRGBX_(new
RGBQUAD[cColorWidth * cColorHeight]),
2097 if (pDepthCoordinates_)
2099 delete[] pDepthCoordinates_;
2100 pDepthCoordinates_ =
NULL;
2103 if (pColorCoordinates_)
2105 delete[] pColorCoordinates_;
2106 pColorCoordinates_ =
NULL;
2111 delete[] pColorRGBX_;
2122 if (pMultiSourceFrameReader_)
2124 pMultiSourceFrameReader_->UnsubscribeMultiSourceFrameArrived(hMSEvent);
2125 CloseHandle((HANDLE)hMSEvent);
2130 SafeRelease(pMultiSourceFrameReader_);
2133 SafeRelease(pCoordinateMapper_);
2138 pKinectSensor_->Close();
2141 SafeRelease(pKinectSensor_);
2154 hr = GetDefaultKinectSensor(&pKinectSensor_);
2164 hr = pKinectSensor_->Open();
2168 hr = pKinectSensor_->get_CoordinateMapper(&pCoordinateMapper_);
2172 hr = pKinectSensor_->OpenMultiSourceFrameReader(
2173 FrameSourceTypes::FrameSourceTypes_Depth | FrameSourceTypes::FrameSourceTypes_Color,
2174 &pMultiSourceFrameReader_);
2178 hr = pMultiSourceFrameReader_->SubscribeMultiSourceFrameArrived(&hMSEvent);
2184 if (!pKinectSensor_ || FAILED(hr))
2186 UERROR(
"No ready Kinect found!");
2195 CameraIntrinsics intrinsics;
2196 hr = pCoordinateMapper_->GetDepthCameraIntrinsics(&intrinsics);
2197 if (SUCCEEDED(hr) && intrinsics.FocalLengthX > 0.0f)
2201 intrinsics.FocalLengthX,
2202 intrinsics.FocalLengthY,
2203 intrinsics.PrincipalPointX,
2204 intrinsics.PrincipalPointY);
2210 int firstIndex = -1;
2217 if (p.X != -std::numeric_limits<float>::infinity() && p.Y != -std::numeric_limits<float>::infinity())
2219 if (firstIndex == -1)
2221 firstIndex = depthIndex;
2223 lastIndex = depthIndex;
2227 UASSERT(firstIndex >= 0 && lastIndex >= 0);
2228 float fx, fy, cx, cy;
2229 float x1, y1, z1, x2, y2, z2;
2231 depthModel.
project(lastIndex - (lastIndex / cDepthWidth)*cDepthWidth, lastIndex / cDepthWidth, 1.0
f, x2, y2, z2);
2234 fx = ((uv1.X - uv2.X)*z1*z2) / (x1*z2 - x2*z1);
2235 cx = uv1.X - (x1 / z1) * fx;
2236 fy = ((uv1.Y - uv2.Y)*z1*z2) / (y1*z2 - y2*z1);
2237 cy = uv1.Y - (y1 / z1) * fy;
2250 if (!colorCameraModel_.isValidForProjection())
2252 UERROR(
"Failed to get camera parameters! Is the camera connected? Try restarting the camera again or use kTypeColor2DepthSD.");
2258 if (!serial.empty())
2260 UINFO(
"Running kinect device \"%s\"", serial.c_str());
2265 UERROR(
"CameraK4W2: RTAB-Map is not built with Kinect for Windows 2 SDK support!");
2280 wchar_t uid[255] = { 0 };
2282 HRESULT hr = pKinectSensor_->get_UniqueKinectId(255, uid);
2285 std::wstring ws(uid);
2286 return std::string(ws.begin(), ws.end());
2299 if (!pMultiSourceFrameReader_)
2307 HANDLE handles[] = {
reinterpret_cast<HANDLE
>(hMSEvent) };
2310 while((
UTimer::now()-t < 5.0) && WaitForMultipleObjects(_countof(handles), handles,
false, 5000) == WAIT_OBJECT_0)
2312 IMultiSourceFrameArrivedEventArgs* pArgs =
NULL;
2314 hr = pMultiSourceFrameReader_->GetMultiSourceFrameArrivedEventData(hMSEvent, &pArgs);
2317 IMultiSourceFrameReference * pFrameRef =
NULL;
2318 hr = pArgs->get_FrameReference(&pFrameRef);
2321 IMultiSourceFrame* pMultiSourceFrame =
NULL;
2322 IDepthFrame* pDepthFrame =
NULL;
2323 IColorFrame* pColorFrame =
NULL;
2325 hr = pFrameRef->AcquireFrame(&pMultiSourceFrame);
2328 UERROR(
"Failed getting latest frame.");
2331 IDepthFrameReference* pDepthFrameReference =
NULL;
2332 hr = pMultiSourceFrame->get_DepthFrameReference(&pDepthFrameReference);
2335 hr = pDepthFrameReference->AcquireFrame(&pDepthFrame);
2337 SafeRelease(pDepthFrameReference);
2339 IColorFrameReference* pColorFrameReference =
NULL;
2340 hr = pMultiSourceFrame->get_ColorFrameReference(&pColorFrameReference);
2343 hr = pColorFrameReference->AcquireFrame(&pColorFrame);
2345 SafeRelease(pColorFrameReference);
2347 if (pDepthFrame && pColorFrame)
2349 IFrameDescription* pDepthFrameDescription =
NULL;
2350 int nDepthWidth = 0;
2351 int nDepthHeight = 0;
2352 UINT nDepthBufferSize = 0;
2353 UINT16 *pDepthBuffer =
NULL;
2355 IFrameDescription* pColorFrameDescription =
NULL;
2356 int nColorWidth = 0;
2357 int nColorHeight = 0;
2358 ColorImageFormat imageFormat = ColorImageFormat_None;
2359 UINT nColorBufferSize = 0;
2364 hr = pDepthFrame->get_FrameDescription(&pDepthFrameDescription);
2366 hr = pDepthFrameDescription->get_Width(&nDepthWidth);
2368 hr = pDepthFrameDescription->get_Height(&nDepthHeight);
2370 hr = pDepthFrame->AccessUnderlyingBuffer(&nDepthBufferSize, &pDepthBuffer);
2374 hr = pColorFrame->get_FrameDescription(&pColorFrameDescription);
2376 hr = pColorFrameDescription->get_Width(&nColorWidth);
2378 hr = pColorFrameDescription->get_Height(&nColorHeight);
2380 hr = pColorFrame->get_RawColorImageFormat(&imageFormat);
2383 if (imageFormat == ColorImageFormat_Bgra)
2385 hr = pColorFrame->AccessRawUnderlyingBuffer(&nColorBufferSize, reinterpret_cast<BYTE**>(&pColorBuffer));
2387 else if (pColorRGBX_)
2389 pColorBuffer = pColorRGBX_;
2391 hr = pColorFrame->CopyConvertedFrameDataToArray(nColorBufferSize, reinterpret_cast<BYTE*>(pColorBuffer), ColorImageFormat_Bgra);
2406 if (pCoordinateMapper_ &&
2412 HRESULT hr = pCoordinateMapper_->MapColorFrameToDepthSpace(nDepthWidth * nDepthHeight, (UINT16*)pDepthBuffer, nColorWidth * nColorHeight, pDepthCoordinates_);
2415 cv::Mat depth = cv::Mat::zeros(nDepthHeight, nDepthWidth, CV_16UC1);
2416 cv::Mat imageColorRegistered = cv::Mat::zeros(nDepthHeight, nDepthWidth, CV_8UC3);
2418 for (
int colorIndex = 0; colorIndex < (nColorWidth*nColorHeight); ++colorIndex)
2423 if (p.X != -std::numeric_limits<float>::infinity() && p.Y != -std::numeric_limits<float>::infinity())
2427 int pixel_x_l, pixel_y_l, pixel_x_h, pixel_y_h;
2428 pixel_x_l = nDepthWidth -
static_cast<int>(p.X);
2429 pixel_y_l =
static_cast<int>(p.Y);
2430 pixel_x_h = pixel_x_l - 1;
2431 pixel_y_h = pixel_y_l + 1;
2433 const RGBQUAD* pSrc = pColorBuffer + colorIndex;
2434 if ((pixel_x_l >= 0 && pixel_x_l < nDepthWidth) && (pixel_y_l >= 0 && pixel_y_l < nDepthHeight))
2436 unsigned char * ptr = imageColorRegistered.ptr<
unsigned char>(pixel_y_l, pixel_x_l);
2437 ptr[0] = pSrc->rgbBlue;
2438 ptr[1] = pSrc->rgbGreen;
2439 ptr[2] = pSrc->rgbRed;
2440 depth.at<
unsigned short>(pixel_y_l, pixel_x_l) = *(pDepthBuffer + nDepthWidth - pixel_x_l + pixel_y_l*nDepthWidth);
2442 if ((pixel_x_l >= 0 && pixel_x_l < nDepthWidth) && (pixel_y_h >= 0 && pixel_y_h < nDepthHeight))
2444 unsigned char * ptr = imageColorRegistered.ptr<
unsigned char>(pixel_y_h, pixel_x_l);
2445 ptr[0] = pSrc->rgbBlue;
2446 ptr[1] = pSrc->rgbGreen;
2447 ptr[2] = pSrc->rgbRed;
2448 depth.at<
unsigned short>(pixel_y_h, pixel_x_l) = *(pDepthBuffer + nDepthWidth - pixel_x_l + pixel_y_h*nDepthWidth);
2450 if ((pixel_x_h >= 0 && pixel_x_h < nDepthWidth) && (pixel_y_l >= 0 && pixel_y_l < nDepthHeight))
2452 unsigned char * ptr = imageColorRegistered.ptr<
unsigned char>(pixel_y_l, pixel_x_h);
2453 ptr[0] = pSrc->rgbBlue;
2454 ptr[1] = pSrc->rgbGreen;
2455 ptr[2] = pSrc->rgbRed;
2456 depth.at<
unsigned short>(pixel_y_l, pixel_x_h) = *(pDepthBuffer + nDepthWidth - pixel_x_h + pixel_y_l*nDepthWidth);
2458 if ((pixel_x_h >= 0 && pixel_x_h < nDepthWidth) && (pixel_y_h >= 0 && pixel_y_h < nDepthHeight))
2460 unsigned char * ptr = imageColorRegistered.ptr<
unsigned char>(pixel_y_h, pixel_x_h);
2461 ptr[0] = pSrc->rgbBlue;
2462 ptr[1] = pSrc->rgbGreen;
2463 ptr[2] = pSrc->rgbRed;
2464 depth.at<
unsigned short>(pixel_y_h, pixel_x_h) = *(pDepthBuffer + nDepthWidth - pixel_x_h + pixel_y_h*nDepthWidth);
2469 CameraIntrinsics intrinsics;
2470 pCoordinateMapper_->GetDepthCameraIntrinsics(&intrinsics);
2472 intrinsics.FocalLengthX,
2473 intrinsics.FocalLengthY,
2474 intrinsics.PrincipalPointX,
2475 intrinsics.PrincipalPointY,
2476 this->getLocalTransform(),
2483 UERROR(
"Failed color to depth registration!");
2488 HRESULT hr = pCoordinateMapper_->MapDepthFrameToColorSpace(nDepthWidth * nDepthHeight, (UINT16*)pDepthBuffer, nDepthWidth * nDepthHeight, pColorCoordinates_);
2491 cv::Mat depthSource(nDepthHeight, nDepthWidth, CV_16UC1, pDepthBuffer);
2492 cv::Mat depthRegistered = cv::Mat::zeros(
2500 cv::resize(cv::Mat(nColorHeight, nColorWidth, CV_8UC4, pColorBuffer), tmp, cv::Size(), 0.5, 0.5, cv::INTER_AREA);
2501 cv::cvtColor(tmp, imageColor, CV_BGRA2BGR);
2505 cv::cvtColor(cv::Mat(nColorHeight, nColorWidth, CV_8UC4, pColorBuffer), imageColor, CV_BGRA2BGR);
2508 for (
int depthIndex = 0; depthIndex < (nDepthWidth*nDepthHeight); ++depthIndex)
2513 if (p.X != -std::numeric_limits<float>::infinity() && p.Y != -std::numeric_limits<float>::infinity())
2520 const unsigned short & depth_value = depthSource.at<
unsigned short>(0, depthIndex);
2521 int pixel_x_l, pixel_y_l, pixel_x_h, pixel_y_h;
2523 pixel_x_l = depthRegistered.cols - p.X;
2525 pixel_x_h = pixel_x_l - 1;
2526 pixel_y_h = pixel_y_l + 1;
2528 if (pixel_x_l >= 0 && pixel_x_l < depthRegistered.cols &&
2529 pixel_y_l>0 && pixel_y_l < depthRegistered.rows &&
2532 unsigned short & depthPixel = depthRegistered.at<
unsigned short>(pixel_y_l, pixel_x_l);
2533 if (depthPixel == 0 || depthPixel > depth_value)
2535 depthPixel = depth_value;
2538 if (pixel_x_h >= 0 && pixel_x_h < depthRegistered.cols &&
2539 pixel_y_h>0 && pixel_y_h < depthRegistered.rows &&
2542 unsigned short & depthPixel = depthRegistered.at<
unsigned short>(pixel_y_h, pixel_x_h);
2543 if (depthPixel == 0 || depthPixel > depth_value)
2545 depthPixel = depth_value;
2554 model = model.
scaled(0.5);
2558 cv::flip(imageColor, imageColor, 1);
2563 UERROR(
"Failed depth to color registration!");
2569 SafeRelease(pDepthFrameDescription);
2570 SafeRelease(pColorFrameDescription);
2573 pFrameRef->Release();
2575 SafeRelease(pDepthFrame);
2576 SafeRelease(pColorFrame);
2577 SafeRelease(pMultiSourceFrame);
2587 UERROR(
"CameraK4W2: RTAB-Map is not built with Kinect for Windows 2 SDK support!");
2597 #ifdef RTABMAP_REALSENSE 2608 bool computeOdometry,
2611 Camera(imageRate, localTransform)
2612 #ifdef RTABMAP_REALSENSE
2617 presetRGB_(presetRGB),
2618 presetDepth_(presetDepth),
2619 computeOdometry_(computeOdometry),
2620 depthScaledToRGBSize_(
false),
2631 #ifdef RTABMAP_REALSENSE 2639 dev_->stop(rs::source::all_sources);
2646 catch(
const rs::error & error){
UWARN(
"%s", error.what());}
2654 #ifdef RTABMAP_REALSENSE_SLAM 2659 slam_->flush_resources();
2667 #ifdef RTABMAP_REALSENSE_SLAM 2668 bool setStreamConfigIntrin(
2669 rs::core::stream_type stream,
2670 std::map< rs::core::stream_type, rs::core::intrinsics > intrinsics,
2671 rs::core::video_module_interface::supported_module_config & supported_config,
2672 rs::core::video_module_interface::actual_module_config & actual_config)
2674 auto & supported_stream_config = supported_config[stream];
2675 if (!supported_stream_config.is_enabled || supported_stream_config.size.width != intrinsics[stream].width || supported_stream_config.size.height != intrinsics[stream].height)
2677 UERROR(
"size of stream is not supported by slam");
2678 UERROR(
" supported: stream %d, width: %d height: %d", (
uint32_t) stream, supported_stream_config.size.width, supported_stream_config.size.height);
2679 UERROR(
" received: stream %d, width: %d height: %d", (
uint32_t) stream, intrinsics[stream].width, intrinsics[stream].height);
2683 rs::core::video_module_interface::actual_image_stream_config &actual_stream_config = actual_config[stream];
2684 actual_config[stream].size.width = intrinsics[stream].width;
2685 actual_config[stream].size.height = intrinsics[stream].height;
2686 actual_stream_config.frame_rate = supported_stream_config.frame_rate;
2687 actual_stream_config.intrinsics = intrinsics[stream];
2688 actual_stream_config.is_enabled =
true;
2694 #ifdef RTABMAP_REALSENSE 2695 depthScaledToRGBSize_ = enabled;
2700 #ifdef RTABMAP_REALSENSE 2705 #ifdef RTABMAP_REALSENSE 2706 template<
class GET_DEPTH,
class TRANSFER_PIXEL>
void align_images(
const rs_intrinsics & depth_intrin,
const rs_extrinsics & depth_to_other,
const rs_intrinsics & other_intrin, GET_DEPTH get_depth, TRANSFER_PIXEL transfer_pixel)
2709 #pragma omp parallel for schedule(dynamic) 2710 for(
int depth_y = 0; depth_y < depth_intrin.height; ++depth_y)
2712 int depth_pixel_index = depth_y * depth_intrin.width;
2713 for(
int depth_x = 0; depth_x < depth_intrin.width; ++depth_x, ++depth_pixel_index)
2716 if(
float depth = get_depth(depth_pixel_index))
2719 float depth_pixel[2] = {depth_x-0.5f, depth_y-0.5f}, depth_point[3], other_point[3], other_pixel[2];
2720 rs_deproject_pixel_to_point(depth_point, &depth_intrin, depth_pixel, depth);
2721 rs_transform_point_to_point(other_point, &depth_to_other, depth_point);
2722 rs_project_point_to_pixel(other_pixel, &other_intrin, other_point);
2723 const int other_x0 =
static_cast<int>(other_pixel[0] + 0.5f);
2724 const int other_y0 =
static_cast<int>(other_pixel[1] + 0.5f);
2727 depth_pixel[0] = depth_x+0.5f; depth_pixel[1] = depth_y+0.5f;
2728 rs_deproject_pixel_to_point(depth_point, &depth_intrin, depth_pixel, depth);
2729 rs_transform_point_to_point(other_point, &depth_to_other, depth_point);
2730 rs_project_point_to_pixel(other_pixel, &other_intrin, other_point);
2731 const int other_x1 =
static_cast<int>(other_pixel[0] + 0.5f);
2732 const int other_y1 =
static_cast<int>(other_pixel[1] + 0.5f);
2734 if(other_x0 < 0 || other_y0 < 0 || other_x1 >= other_intrin.width || other_y1 >= other_intrin.height)
continue;
2737 for(
int y=other_y0; y<=other_y1; ++y)
for(
int x=other_x0; x<=other_x1; ++x) transfer_pixel(depth_pixel_index, y * other_intrin.width + x);
2744 void align_z_to_other(byte * z_aligned_to_other,
const uint16_t * z_pixels,
float z_scale,
const rs_intrinsics & z_intrin,
const rs_extrinsics & z_to_other,
const rs_intrinsics & other_intrin)
2746 auto out_z = (
uint16_t *)(z_aligned_to_other);
2747 align_images(z_intrin, z_to_other, other_intrin,
2748 [z_pixels, z_scale](
int z_pixel_index) {
return z_scale * z_pixels[z_pixel_index]; },
2749 [out_z, z_pixels](
int z_pixel_index,
int other_pixel_index) { out_z[other_pixel_index] = out_z[other_pixel_index] ?
std::min(out_z[other_pixel_index],z_pixels[z_pixel_index]) : z_pixels[z_pixel_index]; });
2752 void align_disparity_to_other(byte * disparity_aligned_to_other,
const uint16_t * disparity_pixels,
float disparity_scale,
const rs_intrinsics & disparity_intrin,
const rs_extrinsics & disparity_to_other,
const rs_intrinsics & other_intrin)
2754 auto out_disparity = (
uint16_t *)(disparity_aligned_to_other);
2755 align_images(disparity_intrin, disparity_to_other, other_intrin,
2756 [disparity_pixels, disparity_scale](
int disparity_pixel_index) {
return disparity_scale / disparity_pixels[disparity_pixel_index]; },
2757 [out_disparity, disparity_pixels](
int disparity_pixel_index,
int other_pixel_index) { out_disparity[other_pixel_index] = disparity_pixels[disparity_pixel_index]; });
2760 template<
int N>
struct bytes {
char b[N]; };
2761 template<
int N,
class GET_DEPTH>
void align_other_to_depth_bytes(byte * other_aligned_to_depth, GET_DEPTH get_depth,
const rs_intrinsics & depth_intrin,
const rs_extrinsics & depth_to_other,
const rs_intrinsics & other_intrin,
const byte * other_pixels)
2763 auto in_other = (
const bytes<N> *)(other_pixels);
2764 auto out_other = (bytes<N> *)(other_aligned_to_depth);
2765 align_images(depth_intrin, depth_to_other, other_intrin, get_depth,
2766 [out_other, in_other](
int depth_pixel_index,
int other_pixel_index) { out_other[depth_pixel_index] = in_other[other_pixel_index]; });
2773 std::vector<int> compute_rectification_table(
const rs_intrinsics & rect_intrin,
const rs_extrinsics & rect_to_unrect,
const rs_intrinsics & unrect_intrin)
2775 std::vector<int> rectification_table;
2776 rectification_table.resize(rect_intrin.width * rect_intrin.height);
2777 align_images(rect_intrin, rect_to_unrect, unrect_intrin, [](
int) {
return 1.0f; },
2778 [&rectification_table](
int rect_pixel_index,
int unrect_pixel_index) { rectification_table[rect_pixel_index] = unrect_pixel_index; });
2779 return rectification_table;
2782 template<
class T>
void rectify_image_pixels(T * rect_pixels,
const std::vector<int> & rectification_table,
const T * unrect_pixels)
2784 for(
auto entry : rectification_table) *rect_pixels++ = unrect_pixels[entry];
2787 void rectify_image(
uint8_t * rect_pixels,
const std::vector<int> & rectification_table,
const uint8_t * unrect_pixels, rs_format format)
2792 return rectify_image_pixels((bytes<1> *)rect_pixels, rectification_table, (
const bytes<1> *)unrect_pixels);
2793 case RS_FORMAT_Y16:
case RS_FORMAT_Z16:
2794 return rectify_image_pixels((bytes<2> *)rect_pixels, rectification_table, (
const bytes<2> *)unrect_pixels);
2795 case RS_FORMAT_RGB8:
case RS_FORMAT_BGR8:
2796 return rectify_image_pixels((bytes<3> *)rect_pixels, rectification_table, (
const bytes<3> *)unrect_pixels);
2797 case RS_FORMAT_RGBA8:
case RS_FORMAT_BGRA8:
2798 return rectify_image_pixels((bytes<4> *)rect_pixels, rectification_table, (
const bytes<4> *)unrect_pixels);
2808 #ifdef RTABMAP_REALSENSE 2816 dev_->stop(rs::source::all_sources);
2823 catch(
const rs::error & error){
UWARN(
"%s", error.what());}
2826 bufferedFrames_.clear();
2827 rsRectificationTable_.clear();
2829 #ifdef RTABMAP_REALSENSE_SLAM 2830 motionSeq_[0] = motionSeq_[1] = 0;
2835 slam_->flush_resources();
2843 ctx_ =
new rs::context();
2847 if (ctx_->get_device_count() == 0)
2849 UERROR(
"No RealSense device detected!");
2854 dev_ = ctx_->get_device(deviceId_);
2857 UERROR(
"Cannot connect to device %d", deviceId_);
2860 std::string name = dev_->get_name();
2861 UINFO(
"Using device %d, an %s", deviceId_, name.c_str());
2862 UINFO(
" Serial number: %s", dev_->get_serial());
2863 UINFO(
" Firmware version: %s", dev_->get_firmware_version());
2864 UINFO(
" Preset RGB: %d", presetRGB_);
2865 UINFO(
" Preset Depth: %d", presetDepth_);
2867 #ifndef RTABMAP_REALSENSE_SLAM 2868 computeOdometry_ =
false;
2871 if (name.find(
"ZR300") == std::string::npos)
2875 computeOdometry_ =
false;
2879 UWARN(
"Fisheye cannot be used with %s camera, using color instead...", name.c_str());
2884 rs::intrinsics depth_intrin;
2885 rs::intrinsics fisheye_intrin;
2886 rs::intrinsics color_intrin;
2888 UINFO(
"Enabling streams...");
2896 if(rgbSource_==
kFishEye || computeOdometry_)
2898 dev_->enable_stream(rs::stream::fisheye, 640, 480, rs::format::raw8, 30);
2899 if(computeOdometry_)
2902 dev_->set_option(rs::option::fisheye_strobe, 1);
2905 dev_->set_option(rs::option::fisheye_external_trigger, 1);
2906 dev_->set_option(rs::option::fisheye_color_auto_exposure, 1);
2907 fisheye_intrin = dev_->get_stream_intrinsics(rs::stream::fisheye);
2908 UINFO(
" Fisheye: %dx%d", fisheye_intrin.width, fisheye_intrin.height);
2911 color_intrin = fisheye_intrin;
2916 dev_->enable_stream(rs::stream::color, (rs::preset)presetRGB_);
2917 color_intrin = dev_->get_stream_intrinsics(rs::stream::rectified_color);
2918 UINFO(
" RGB: %dx%d", color_intrin.width, color_intrin.height);
2922 dev_->enable_stream(rs::stream::infrared, (rs::preset)presetRGB_);
2923 color_intrin = dev_->get_stream_intrinsics(rs::stream::infrared);
2924 UINFO(
" IR left: %dx%d", color_intrin.width, color_intrin.height);
2928 dev_->enable_stream(rs::stream::depth, (rs::preset)presetDepth_);
2929 depth_intrin = dev_->get_stream_intrinsics(rs::stream::depth);
2930 UINFO(
" Depth: %dx%d", depth_intrin.width, depth_intrin.height);
2932 catch(
const rs::error & error)
2934 UERROR(
"Failed starting the streams: %s", error.what());
2940 #ifdef RTABMAP_REALSENSE_SLAM 2941 UDEBUG(
"Setup frame callback");
2943 std::function<void(rs::frame)> frameCallback = [
this](rs::frame frame)
2947 const auto timestampDomain = frame.get_frame_timestamp_domain();
2948 if (rs::timestamp_domain::microcontroller != timestampDomain)
2950 UERROR(
"error: Junk time stamp in stream: %d\twith frame counter: %d",
2951 (
int)(frame.get_stream_type()), frame.get_frame_number());
2956 int width = frame.get_width();
2957 int height = frame.get_height();
2958 rs::core::correlated_sample_set sample_set = {};
2960 rs::core::image_info info =
2964 rs::utils::convert_pixel_format(frame.get_format()),
2968 if(frame.get_format() == rs::format::raw8 || frame.get_format() == rs::format::y8)
2970 image = cv::Mat(height, width, CV_8UC1, (
unsigned char*)frame.get_data());
2971 if(frame.get_stream_type() == rs::stream::fisheye)
2974 if(bufferedFrames_.size())
2976 bufferedFrames_.rbegin()->second.first = image.clone();
2978 bool notify = lastSyncFrames_.first.empty();
2979 lastSyncFrames_ = bufferedFrames_.rbegin()->second;
2982 dataReady_.release();
2984 bufferedFrames_.clear();
2987 else if(frame.get_stream_type() == rs::stream::infrared)
2989 if(bufferedFrames_.find(frame.get_timestamp()) != bufferedFrames_.end())
2991 bufferedFrames_.find(frame.get_timestamp())->second.first = image.clone();
2993 bool notify = lastSyncFrames_.first.empty();
2994 lastSyncFrames_ = bufferedFrames_.find(frame.get_timestamp())->second;
2997 dataReady_.release();
2999 bufferedFrames_.erase(frame.get_timestamp());
3003 bufferedFrames_.insert(std::make_pair(frame.get_timestamp(), std::make_pair(image.clone(), cv::Mat())));
3005 if(bufferedFrames_.size()>5)
3007 UWARN(
"Frames cannot be synchronized!");
3008 bufferedFrames_.clear();
3013 else if(frame.get_format() == rs::format::z16)
3015 image = cv::Mat(height, width, CV_16UC1, (
unsigned char*)frame.get_data());
3016 if(bufferedFrames_.find(frame.get_timestamp()) != bufferedFrames_.end())
3018 bufferedFrames_.find(frame.get_timestamp())->second.second = image.clone();
3020 bool notify = lastSyncFrames_.first.empty();
3021 lastSyncFrames_ = bufferedFrames_.find(frame.get_timestamp())->second;
3024 dataReady_.release();
3026 bufferedFrames_.erase(frame.get_timestamp());
3030 bufferedFrames_.insert(std::make_pair(frame.get_timestamp(), std::make_pair(cv::Mat(), image.clone())));
3032 if(bufferedFrames_.size()>5)
3034 UWARN(
"Frames cannot be synchronized!");
3035 bufferedFrames_.clear();
3038 else if(frame.get_format() == rs::format::rgb8)
3040 if(rsRectificationTable_.size())
3042 image = cv::Mat(height, width, CV_8UC3);
3043 rectify_image(image.data, rsRectificationTable_, (
unsigned char*)frame.get_data(), (rs_format)frame.get_format());
3047 image = cv::Mat(height, width, CV_8UC3, (
unsigned char*)frame.get_data());
3049 if(bufferedFrames_.find(frame.get_timestamp()) != bufferedFrames_.end())
3051 bufferedFrames_.find(frame.get_timestamp())->second.first = image.clone();
3053 bool notify = lastSyncFrames_.first.empty();
3054 lastSyncFrames_ = bufferedFrames_.find(frame.get_timestamp())->second;
3057 dataReady_.release();
3059 bufferedFrames_.erase(frame.get_timestamp());
3063 bufferedFrames_.insert(std::make_pair(frame.get_timestamp(), std::make_pair(image.clone(), cv::Mat())));
3065 if(bufferedFrames_.size()>5)
3067 UWARN(
"Frames cannot be synchronized!");
3068 bufferedFrames_.clear();
3079 rs::core::stream_type stream = rs::utils::convert_stream_type(frame.get_stream_type());
3080 sample_set[stream] = rs::core::image_interface::create_instance_from_raw_data(
3085 frame.get_timestamp(),
3086 (
uint64_t)frame.get_frame_number(),
3087 rs::core::timestamp_domain::microcontroller);
3090 if (slam_->process_sample_set(sample_set) < rs::core::status_no_error)
3092 UERROR(
"error: failed to process sample");
3094 sample_set[stream]->release();
3100 if(computeOdometry_ || rgbSource_ ==
kFishEye)
3102 dev_->set_frame_callback(rs::stream::fisheye, frameCallback);
3106 dev_->set_frame_callback(rs::stream::infrared, frameCallback);
3108 else if(rgbSource_ ==
kColor)
3110 dev_->set_frame_callback(rs::stream::color, frameCallback);
3113 dev_->set_frame_callback(rs::stream::depth, frameCallback);
3117 if (computeOdometry_)
3119 UDEBUG(
"Setup motion callback");
3121 std::function<void(rs::motion_data)> motion_callback;
3122 motion_callback = [
this](rs::motion_data entry)
3124 if ((entry.timestamp_data.source_id != RS_EVENT_IMU_GYRO) &&
3125 (entry.timestamp_data.source_id != RS_EVENT_IMU_ACCEL))
3128 rs_event_source motionType = entry.timestamp_data.source_id;
3130 rs::core::correlated_sample_set sample_set = {};
3131 if (motionType == RS_EVENT_IMU_ACCEL)
3133 sample_set[rs::core::motion_type::accel].timestamp = entry.timestamp_data.timestamp;
3134 sample_set[rs::core::motion_type::accel].data[0] = (float)entry.axes[0];
3135 sample_set[rs::core::motion_type::accel].data[1] = (
float)entry.axes[1];
3136 sample_set[rs::core::motion_type::accel].data[2] = (float)entry.axes[2];
3137 sample_set[rs::core::motion_type::accel].type = rs::core::motion_type::accel;
3139 sample_set[rs::core::motion_type::accel].frame_number = motionSeq_[0];
3141 else if (motionType == RS_EVENT_IMU_GYRO)
3143 sample_set[rs::core::motion_type::gyro].timestamp = entry.timestamp_data.timestamp;
3144 sample_set[rs::core::motion_type::gyro].data[0] = (float)entry.axes[0];
3145 sample_set[rs::core::motion_type::gyro].data[1] = (
float)entry.axes[1];
3146 sample_set[rs::core::motion_type::gyro].data[2] = (float)entry.axes[2];
3147 sample_set[rs::core::motion_type::gyro].type = rs::core::motion_type::gyro;
3149 sample_set[rs::core::motion_type::gyro].frame_number = motionSeq_[1];
3153 if (slam_->process_sample_set(sample_set) < rs::core::status_no_error)
3155 UERROR(
"error: failed to process sample");
3159 std::function<void(rs::timestamp_data)> timestamp_callback;
3160 timestamp_callback = [](rs::timestamp_data entry) {};
3162 dev_->enable_motion_tracking(motion_callback, timestamp_callback);
3163 UINFO(
" enabled accel and gyro stream");
3165 rs::motion_intrinsics imuIntrinsics;
3166 rs::extrinsics fisheye2ImuExtrinsics;
3167 rs::extrinsics fisheye2DepthExtrinsics;
3170 imuIntrinsics = dev_->get_motion_intrinsics();
3171 fisheye2ImuExtrinsics = dev_->get_motion_extrinsics_from(rs::stream::fisheye);
3172 fisheye2DepthExtrinsics = dev_->get_extrinsics(rs::stream::depth, rs::stream::fisheye);
3174 catch (
const rs::error &
e) {
3175 UERROR(
"Exception: %s (try to unplug/plug the camera)", e.what());
3181 slam_ =
new rs::slam::slam();
3182 slam_->set_auto_occupancy_map_building(
false);
3183 slam_->force_relocalization_pose(
false);
3185 rs::core::video_module_interface::supported_module_config supported_config = {};
3186 if (slam_->query_supported_module_config(0, supported_config) < rs::core::status_no_error)
3188 UERROR(
"Failed to query the first supported module configuration");
3192 rs::core::video_module_interface::actual_module_config actual_config = {};
3195 std::map< rs::core::stream_type, rs::core::intrinsics > intrinsics;
3196 intrinsics[rs::core::stream_type::fisheye] = rs::utils::convert_intrinsics(fisheye_intrin);
3197 intrinsics[rs::core::stream_type::depth] = rs::utils::convert_intrinsics(depth_intrin);
3199 if(!setStreamConfigIntrin(rs::core::stream_type::fisheye, intrinsics, supported_config, actual_config))
3203 if(!setStreamConfigIntrin(rs::core::stream_type::depth, intrinsics, supported_config, actual_config))
3209 actual_config[rs::core::motion_type::accel].is_enabled =
true;
3210 actual_config[rs::core::motion_type::gyro].is_enabled =
true;
3211 actual_config[rs::core::motion_type::gyro].intrinsics = rs::utils::convert_motion_device_intrinsics(imuIntrinsics.gyro);
3212 actual_config[rs::core::motion_type::accel].intrinsics = rs::utils::convert_motion_device_intrinsics(imuIntrinsics.acc);
3215 actual_config[rs::core::stream_type::fisheye].extrinsics_motion = rs::utils::convert_extrinsics(fisheye2ImuExtrinsics);
3216 actual_config[rs::core::stream_type::fisheye].extrinsics = rs::utils::convert_extrinsics(fisheye2DepthExtrinsics);
3218 UDEBUG(
"Set SLAM config");
3220 if (slam_->set_module_config(actual_config) < rs::core::status_no_error)
3222 UERROR(
"error : failed to set the enabled module configuration");
3226 rs::extrinsics fisheye2imu = dev_->get_motion_extrinsics_from(rs::stream::fisheye);
3228 fisheye2imu.rotation[0], fisheye2imu.rotation[1], fisheye2imu.rotation[2], fisheye2imu.translation[0],
3229 fisheye2imu.rotation[3], fisheye2imu.rotation[4], fisheye2imu.rotation[5], fisheye2imu.translation[1],
3230 fisheye2imu.rotation[6], fisheye2imu.rotation[7], fisheye2imu.rotation[8], fisheye2imu.translation[2]).
inverse();
3234 rs::extrinsics color2Fisheye = dev_->get_extrinsics(rs::stream::fisheye, rs::stream::infrared);
3236 color2Fisheye.rotation[0], color2Fisheye.rotation[1], color2Fisheye.rotation[2], color2Fisheye.translation[0],
3237 color2Fisheye.rotation[3], color2Fisheye.rotation[4], color2Fisheye.rotation[5], color2Fisheye.translation[1],
3238 color2Fisheye.rotation[6], color2Fisheye.rotation[7], color2Fisheye.rotation[8], color2Fisheye.translation[2]).
inverse();
3239 imu2Camera *= fisheye2Color;
3241 else if(rgbSource_ ==
kColor)
3243 rs::extrinsics color2Fisheye = dev_->get_extrinsics(rs::stream::fisheye, rs::stream::rectified_color);
3245 color2Fisheye.rotation[0], color2Fisheye.rotation[1], color2Fisheye.rotation[2], color2Fisheye.translation[0],
3246 color2Fisheye.rotation[3], color2Fisheye.rotation[4], color2Fisheye.rotation[5], color2Fisheye.translation[1],
3247 color2Fisheye.rotation[6], color2Fisheye.rotation[7], color2Fisheye.rotation[8], color2Fisheye.translation[2]).
inverse();
3248 imu2Camera *= fisheye2Color;
3254 dev_->start(rs::source::all_sources);
3256 catch(
const rs::error & error)
3258 UERROR(
"Failed starting the device: %s (try to unplug/plug the camera)", error.what());
3269 catch(
const rs::error & error)
3271 UERROR(
"Failed starting the device: %s (try to unplug/plug the camera)", error.what());
3278 dev_->wait_for_frames();
3280 catch (
const rs::error &
e)
3282 UERROR(
"Exception: %s (try to unplug/plug the camera)", e.what());
3290 D = cv::Mat::zeros(1,6,CV_64FC1);
3291 D.at<
double>(0,0) = color_intrin.coeffs[0];
3292 D.at<
double>(0,1) = color_intrin.coeffs[1];
3293 D.at<
double>(0,4) = color_intrin.coeffs[2];
3294 D.at<
double>(0,5) = color_intrin.coeffs[3];
3299 D = cv::Mat::zeros(1,5,CV_64FC1);
3300 D.at<
double>(0,0) = color_intrin.coeffs[0];
3301 D.at<
double>(0,1) = color_intrin.coeffs[1];
3302 D.at<
double>(0,2) = color_intrin.coeffs[2];
3303 D.at<
double>(0,3) = color_intrin.coeffs[3];
3304 D.at<
double>(0,4) = color_intrin.coeffs[4];
3306 cv::Mat K = cv::Mat::eye(3, 3, CV_64FC1);
3307 K.at<
double>(0,0) = color_intrin.fx;
3308 K.at<
double>(1,1) = color_intrin.fy;
3309 K.at<
double>(0,2) = color_intrin.ppx;
3310 K.at<
double>(1,2) = color_intrin.ppy;
3311 cv::Mat R = cv::Mat::eye(3, 3, CV_64FC1);
3312 cv::Mat P = cv::Mat::eye(3, 4, CV_64FC1);
3313 K(cv::Range(0,2), cv::Range(0,3)).copyTo(P(cv::Range(0,2), cv::Range(0,3)));
3316 cv::Size(color_intrin.width, color_intrin.height),
3327 rs::extrinsics rect_to_unrect = dev_->get_extrinsics(rs::stream::rectified_color, rs::stream::color);
3328 rs::intrinsics unrect_intrin = dev_->get_stream_intrinsics(rs::stream::color);
3329 rsRectificationTable_ = compute_rectification_table(color_intrin, rect_to_unrect, unrect_intrin);
3333 UINFO(
"calibration folder=%s name=%s", calibrationFolder.c_str(), cameraName.c_str());
3334 if(!calibrationFolder.empty() && !cameraName.empty())
3337 if(!model.
load(calibrationFolder, cameraName))
3339 UWARN(
"Failed to load calibration \"%s\" in \"%s\" folder, you should calibrate the camera!",
3340 cameraName.c_str(), calibrationFolder.c_str());
3344 UINFO(
"Camera parameters: fx=%f fy=%f cx=%f cy=%f",
3349 cameraModel_ = model;
3350 cameraModel_.
setName(cameraName);
3351 cameraModel_.initRectificationMap();
3358 UINFO(
"Enabling streams...done!");
3363 UERROR(
"CameraRealSense: RTAB-Map is not built with RealSense support!");
3375 #ifdef RTABMAP_REALSENSE 3378 return dev_->get_serial();
3382 UERROR(
"Cannot get a serial before initialization. Call init() before.");
3390 #ifdef RTABMAP_REALSENSE_SLAM 3397 #ifdef RTABMAP_REALSENSE_SLAM 3398 Transform rsPoseToTransform(
const rs::slam::PoseMatrix4f & pose)
3401 pose.m_data[0], pose.m_data[1], pose.m_data[2], pose.m_data[3],
3402 pose.m_data[4], pose.m_data[5], pose.m_data[6], pose.m_data[7],
3403 pose.m_data[8], pose.m_data[9], pose.m_data[10], pose.m_data[11]);
3410 #ifdef RTABMAP_REALSENSE 3417 rs::intrinsics depth_intrin = dev_->get_stream_intrinsics(rs::stream::depth);
3418 rs::extrinsics depth_to_color;
3419 rs::intrinsics color_intrin;
3422 depth_to_color = dev_->get_extrinsics(rs::stream::depth, rs::stream::fisheye);
3423 color_intrin = dev_->get_stream_intrinsics(rs::stream::fisheye);
3427 depth_to_color = dev_->get_extrinsics(rs::stream::depth, rs::stream::infrared);
3428 color_intrin = dev_->get_stream_intrinsics(rs::stream::infrared);
3432 depth_to_color = dev_->get_extrinsics(rs::stream::depth, rs::stream::rectified_color);
3433 color_intrin = dev_->get_stream_intrinsics(rs::stream::rectified_color);
3436 #ifdef RTABMAP_REALSENSE_SLAM 3437 if(!dataReady_.acquire(1, 5000))
3439 UWARN(
"Not received new frames since 5 seconds, end of stream reached!");
3445 rgb = lastSyncFrames_.first;
3446 depthIn = lastSyncFrames_.second;
3447 lastSyncFrames_.first = cv::Mat();
3448 lastSyncFrames_.second = cv::Mat();
3451 if(rgb.empty() || depthIn.empty())
3457 dev_->wait_for_frames();
3459 catch (
const rs::error &
e)
3461 UERROR(
"Exception: %s", e.what());
3466 depthIn = cv::Mat(depth_intrin.height, depth_intrin.width, CV_16UC1, (
unsigned char*)dev_->get_frame_data(rs::stream::depth));
3469 rgb = cv::Mat(color_intrin.height, color_intrin.width, CV_8UC1, (
unsigned char*)dev_->get_frame_data(rs::stream::fisheye));
3473 rgb = cv::Mat(color_intrin.height, color_intrin.width, CV_8UC1, (
unsigned char*)dev_->get_frame_data(rs::stream::infrared));
3477 rgb = cv::Mat(color_intrin.height, color_intrin.width, CV_8UC3, (
unsigned char*)dev_->get_frame_data(rs::stream::color));
3489 cv::cvtColor(rgb, bgr, CV_RGB2BGR);
3492 bool rectified =
false;
3493 if(rgbSource_ ==
kFishEye && cameraModel_.isRectificationMapInitialized())
3495 bgr = cameraModel_.rectifyImage(bgr);
3497 color_intrin.fx = cameraModel_.fx();
3498 color_intrin.fy = cameraModel_.fy();
3499 color_intrin.ppx = cameraModel_.cx();
3500 color_intrin.ppy = cameraModel_.cy();
3501 UASSERT_MSG(color_intrin.width == cameraModel_.imageWidth() && color_intrin.height == cameraModel_.imageHeight(),
3502 uFormat(
"color_intrin=%dx%d cameraModel_=%dx%d",
3503 color_intrin.width, color_intrin.height, cameraModel_.imageWidth(), cameraModel_.imageHeight()).c_str());
3504 ((rs_intrinsics*)&color_intrin)->model = RS_DISTORTION_NONE;
3506 #ifndef RTABMAP_REALSENSE_SLAM 3507 else if(rgbSource_ !=
kColor)
3514 if(rgbSource_ !=
kFishEye || rectified)
3516 if (color_intrin.width % depth_intrin.width == 0 && color_intrin.height % depth_intrin.height == 0 &&
3517 depth_intrin.width < color_intrin.width &&
3518 depth_intrin.height < color_intrin.height &&
3519 !depthScaledToRGBSize_)
3522 depth = cv::Mat::zeros(cv::Size(depth_intrin.width, depth_intrin.height), CV_16UC1);
3523 float scaleX = float(depth_intrin.width) / float(color_intrin.width);
3524 float scaleY = float(depth_intrin.height) / float(color_intrin.height);
3525 color_intrin.fx *= scaleX;
3526 color_intrin.fy *= scaleY;
3527 color_intrin.ppx *= scaleX;
3528 color_intrin.ppy *= scaleY;
3529 color_intrin.height = depth_intrin.height;
3530 color_intrin.width = depth_intrin.width;
3535 depth = cv::Mat::zeros(bgr.size(), CV_16UC1);
3538 float scale = dev_->get_depth_scale();
3539 for (
int dy = 0; dy < depth_intrin.height; ++dy)
3541 for (
int dx = 0; dx < depth_intrin.width; ++dx)
3544 uint16_t depth_value = depthIn.at<
unsigned short>(dy,dx);
3545 float depth_in_meters = depth_value *
scale;
3548 if (depth_value == 0 || depth_in_meters>10.0
f)
continue;
3555 rs::float2 depth_pixel = { (float)dx, (
float)dy };
3556 rs::float3 depth_point = depth_intrin.deproject(depth_pixel, depth_in_meters);
3557 rs::float3 color_point = depth_to_color.transform(depth_point);
3558 rs::float2 color_pixel = color_intrin.project(color_point);
3560 pdx = color_pixel.x;
3561 pdy = color_pixel.y;
3567 depth.at<
unsigned short>(pdy, pdx) = (
unsigned short)(depth_in_meters*1000.0f);
3572 if (color_intrin.width > depth_intrin.width)
3582 if (!bgr.empty() && ((rgbSource_==
kFishEye && !rectified) || !depth.empty()))
3585 #ifdef RTABMAP_REALSENSE_SLAM 3589 rs::slam::PoseMatrix4f pose;
3590 if(slam_->get_camera_pose(pose) == rs::core::status_no_error)
3598 Transform opticalRotation(0,0,1,0, -1,0,0,0, 0,-1,0,0);
3599 info->
odomPose = opticalRotation * rsPoseToTransform(pose) * opticalRotation.
inverse();
3609 UERROR(
"Failed getting odometry pose");
3617 ULOGGER_WARN(
"The camera must be initialized before requesting an image.");
3620 UERROR(
"CameraRealSense: RTAB-Map is not built with RealSense support!");
3630 #ifdef RTABMAP_REALSENSE2 3638 const std::string & device,
3641 Camera(imageRate, localTransform)
3642 #ifdef RTABMAP_REALSENSE2
3644 ctx_(new
rs2::context),
3645 dev_(new
rs2::device),
3647 syncer_(new
rs2::syncer),
3648 depth_scale_meters_(1.0
f),
3649 depthIntrinsics_(new rs2_intrinsics),
3650 rgbIntrinsics_(new rs2_intrinsics),
3651 depthToRGBExtrinsics_(new rs2_extrinsics),
3652 emitterEnabled_(
true),
3661 #ifdef RTABMAP_REALSENSE2 3665 delete depthIntrinsics_;
3666 delete rgbIntrinsics_;
3667 delete depthToRGBExtrinsics_;
3672 #ifdef RTABMAP_REALSENSE2 3673 void alignFrame(
const rs2_intrinsics& from_intrin,
3674 const rs2_intrinsics& other_intrin,
3675 rs2::frame from_image,
3676 uint32_t output_image_bytes_per_pixel,
3677 const rs2_extrinsics& from_to_other,
3678 cv::Mat & registeredDepth,
3679 float depth_scale_meters)
3681 static const auto meter_to_mm = 0.001f;
3682 uint8_t* p_out_frame = registeredDepth.data;
3683 auto from_vid_frame = from_image.as<rs2::video_frame>();
3684 auto from_bytes_per_pixel = from_vid_frame.get_bytes_per_pixel();
3686 static const auto blank_color = 0x00;
3687 UASSERT(registeredDepth.total()*registeredDepth.channels()*registeredDepth.depth() == other_intrin.height * other_intrin.width * output_image_bytes_per_pixel);
3688 memset(p_out_frame, blank_color, other_intrin.height * other_intrin.width * output_image_bytes_per_pixel);
3690 auto p_from_frame =
reinterpret_cast<const uint8_t*
>(from_image.get_data());
3691 auto from_stream_type = from_image.get_profile().stream_type();
3692 float depth_units = ((from_stream_type == RS2_STREAM_DEPTH)? depth_scale_meters:1.
f);
3693 UASSERT(from_stream_type == RS2_STREAM_DEPTH);
3694 UASSERT_MSG(depth_units > 0.0f,
uFormat(
"depth_scale_meters=%f", depth_scale_meters).c_str());
3695 #pragma omp parallel for schedule(dynamic) 3696 for (
int from_y = 0; from_y < from_intrin.height; ++from_y)
3698 int from_pixel_index = from_y * from_intrin.width;
3699 for (
int from_x = 0; from_x < from_intrin.width; ++from_x, ++from_pixel_index)
3702 float depth = (from_stream_type == RS2_STREAM_DEPTH)?(depth_units * ((
const uint16_t*)p_from_frame)[from_pixel_index]): 1.f;
3706 float from_pixel[2] = { from_x - 0.5f, from_y - 0.5f }, from_point[3], other_point[3], other_pixel[2];
3707 rs2_deproject_pixel_to_point(from_point, &from_intrin, from_pixel, depth);
3708 rs2_transform_point_to_point(other_point, &from_to_other, from_point);
3709 rs2_project_point_to_pixel(other_pixel, &other_intrin, other_point);
3710 const int other_x0 =
static_cast<int>(other_pixel[0] + 0.5f);
3711 const int other_y0 =
static_cast<int>(other_pixel[1] + 0.5f);
3714 from_pixel[0] = from_x + 0.5f; from_pixel[1] = from_y + 0.5f;
3715 rs2_deproject_pixel_to_point(from_point, &from_intrin, from_pixel, depth);
3716 rs2_transform_point_to_point(other_point, &from_to_other, from_point);
3717 rs2_project_point_to_pixel(other_pixel, &other_intrin, other_point);
3718 const int other_x1 =
static_cast<int>(other_pixel[0] + 0.5f);
3719 const int other_y1 =
static_cast<int>(other_pixel[1] + 0.5f);
3721 if (other_x0 < 0 || other_y0 < 0 || other_x1 >= other_intrin.width || other_y1 >= other_intrin.height)
3724 for (
int y = other_y0; y <= other_y1; ++y)
3726 for (
int x = other_x0; x <= other_x1; ++x)
3728 int out_pixel_index = y * other_intrin.width + x;
3730 for (
int i = 0; i < from_bytes_per_pixel; i++)
3732 const auto out_offset = out_pixel_index * output_image_bytes_per_pixel + i;
3733 const auto from_offset = from_pixel_index * output_image_bytes_per_pixel + i;
3734 p_out_frame[out_offset] = p_from_frame[from_offset] * (depth_units / meter_to_mm);
3747 #ifdef RTABMAP_REALSENSE2 3749 UINFO(
"setupDevice...");
3751 auto list = ctx_->query_devices();
3752 if (0 == list.size())
3754 UERROR(
"No RealSense2 devices were found!");
3759 for (
auto&& dev : list)
3761 auto sn = dev.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
3762 auto pid_str = dev.get_info(RS2_CAMERA_INFO_PRODUCT_ID);
3764 std::stringstream ss;
3765 ss << std::hex << pid_str;
3767 UINFO(
"Device with serial number %s was found with product ID=%d.", sn, (
int)pid);
3768 if (deviceId_.empty() || deviceId_ == sn)
3778 UERROR(
"The requested device %s is NOT found!", deviceId_.c_str());
3782 ctx_->set_devices_changed_callback([
this](rs2::event_information& info)
3784 if (info.was_removed(*dev_))
3786 UERROR(
"The device has been disconnected!");
3791 auto camera_name = dev_->get_info(RS2_CAMERA_INFO_NAME);
3792 UINFO(
"Device Name: %s", camera_name);
3794 auto sn = dev_->get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
3795 UINFO(
"Device Serial No: %s", sn);
3797 auto fw_ver = dev_->get_info(RS2_CAMERA_INFO_FIRMWARE_VERSION);
3798 UINFO(
"Device FW version: %s", fw_ver);
3800 auto pid = dev_->get_info(RS2_CAMERA_INFO_PRODUCT_ID);
3801 UINFO(
"Device Product ID: 0x%s", pid);
3803 auto dev_sensors = dev_->query_sensors();
3805 UINFO(
"Device Sensors: ");
3806 std::vector<rs2::sensor> sensors(2);
3807 for(
auto&& elem : dev_sensors)
3809 std::string module_name = elem.get_info(RS2_CAMERA_INFO_NAME);
3810 if (
"Stereo Module" == module_name)
3813 sensors[1].set_option(rs2_option::RS2_OPTION_EMITTER_ENABLED, emitterEnabled_);
3819 else if (
"Coded-Light Depth Sensor" == module_name)
3822 else if (
"RGB Camera" == module_name)
3829 else if (
"Wide FOV Camera" == module_name)
3832 else if (
"Motion Module" == module_name)
3837 UERROR(
"Module Name \"%s\" isn't supported by LibRealSense!", module_name.c_str());
3840 UINFO(
"%s was found.", elem.get_info(RS2_CAMERA_INFO_NAME));
3846 rs2::stream_profile depthStreamProfile;
3847 rs2::stream_profile rgbStreamProfile;
3848 std::vector<std::vector<rs2::stream_profile> > profilesPerSensor(2);
3849 for (
unsigned int i=0; i<sensors.size(); ++i)
3852 auto profiles = sensors[i].get_stream_profiles();
3854 UDEBUG(
"profiles=%d", (
int)profiles.size());
3855 for (
auto&
profile : profiles)
3857 auto video_profile =
profile.as<rs2::video_stream_profile>();
3858 if (video_profile.format() == (i==1?RS2_FORMAT_Z16:irDepth_?RS2_FORMAT_Y8:RS2_FORMAT_RGB8) &&
3859 video_profile.width() == 640 &&
3860 video_profile.height() == 480 &&
3861 video_profile.fps() == 30)
3863 profilesPerSensor[irDepth_?1:i].push_back(
profile);
3864 auto intrinsic = video_profile.get_intrinsics();
3867 depthBuffer_ = cv::Mat(cv::Size(640, 480), CV_16UC1, cv::Scalar(0));
3869 *depthIntrinsics_ = intrinsic;
3873 rgbBuffer_ = cv::Mat(cv::Size(640, 480), irDepth_?CV_8UC1:CV_8UC3, irDepth_?cv::Scalar(0):cv::Scalar(0, 0, 0));
3874 model_ =
CameraModel(camera_name, intrinsic.fx, intrinsic.fy, intrinsic.ppx, intrinsic.ppy, this->getLocalTransform(), 0, cv::Size(intrinsic.width, intrinsic.height));
3876 *rgbIntrinsics_ = intrinsic;
3884 UERROR(
"Given stream configuration is not supported by the device! " 3885 "Stream Index: %d, Width: %d, Height: %d, FPS: %d", i, 640, 480, 30);
3890 if(!model_.isValidForProjection())
3892 UERROR(
"Calibration info not valid!");
3895 *depthToRGBExtrinsics_ = depthStreamProfile.get_extrinsics_to(rgbStreamProfile);
3897 for (
unsigned int i=0; i<sensors.size(); ++i)
3899 if(profilesPerSensor[i].size())
3901 UINFO(
"Starting sensor %d with %d profiles", (
int)i, (
int)profilesPerSensor[i].size());
3902 sensors[i].open(profilesPerSensor[i]);
3905 auto depth_sensor = sensors[i].as<rs2::depth_sensor>();
3906 depth_scale_meters_ = depth_sensor.get_depth_scale();
3908 sensors[i].start(*syncer_);
3913 UINFO(
"Enabling streams...done!");
3918 UERROR(
"CameraRealSense: RTAB-Map is not built with RealSense2 support!");
3930 #ifdef RTABMAP_REALSENSE2 3931 return dev_->get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
3938 #ifdef RTABMAP_REALSENSE2 3939 emitterEnabled_ = enabled;
3945 #ifdef RTABMAP_REALSENSE2 3953 #ifdef RTABMAP_REALSENSE2 3956 auto frameset = syncer_->wait_for_frames(5000);
3958 while (frameset.size() != 2 && timer.
elapsed() < 2.0)
3961 frameset = syncer_->wait_for_frames(100);
3963 if (frameset.size() == 2)
3966 UDEBUG(
"Frameset arrived.");
3967 bool is_rgb_arrived =
false;
3968 bool is_depth_arrived =
false;
3969 rs2::frame rgb_frame;
3970 rs2::frame depth_frame;
3971 for (
auto it = frameset.begin(); it != frameset.end(); ++it)
3974 auto stream_type =
f.get_profile().stream_type();
3975 if (stream_type == RS2_STREAM_COLOR || stream_type == RS2_STREAM_INFRARED)
3978 is_rgb_arrived =
true;
3980 else if (stream_type == RS2_STREAM_DEPTH)
3983 is_depth_arrived =
true;
3987 if(is_rgb_arrived && is_depth_arrived)
3989 auto from_image_frame = depth_frame.as<rs2::video_frame>();
3993 depth = cv::Mat(depthBuffer_.size(), depthBuffer_.type(), (
void*)depth_frame.get_data()).clone();
3997 depth = cv::Mat(depthBuffer_.size(), depthBuffer_.type());
3998 alignFrame(*depthIntrinsics_, *rgbIntrinsics_,
3999 depth_frame, from_image_frame.get_bytes_per_pixel(),
4000 *depthToRGBExtrinsics_, depth, depth_scale_meters_);
4003 cv::Mat rgb = cv::Mat(rgbBuffer_.size(), rgbBuffer_.type(), (
void*)rgb_frame.get_data());
4005 if(rgb.channels() == 3)
4007 cv::cvtColor(rgb, bgr, CV_RGB2BGR);
4018 UERROR(
"Not received depth and rgb");
4023 UERROR(
"Missing frames (received %d)", (
int)frameset.size());
4026 catch(
const std::exception& ex)
4028 UERROR(
"An error has occurred during frame callback: %s", ex.what());
4031 UERROR(
"CameraRealSense2: RTAB-Map is not built with RealSense2 support!");
4045 const std::string & pathRGBImages,
4046 const std::string & pathDepthImages,
4047 float depthScaleFactor,
4052 UASSERT(depthScaleFactor >= 1.0);
4063 bool success =
false;
4072 UERROR(
"Cameras don't have the same number of images (%d vs %d)",
struct _freenect_device freenect_device
void setPath(const std::string &dir)
bool setAutoExposure(bool enabled)
GLM_FUNC_DECL bool any(vecType< bool, P > const &v)
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
virtual SensorData captureImage(CameraInfo *info=0)
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
detail::tvec2< float, highp > float2
single-precision floating-point vector with 2 components. (From GLM_GTX_compatibility extension) ...
const std::string & name() const
bool uIsInBounds(const T &value, const T &low, const T &high)
virtual std::string getSerial() const
const Transform & getLocalTransform() const
void setRGBSource(RGBSource source)
void setDepthScaledToRGBSize(bool enabled)
CameraImages cameraDepth_
virtual ~CameraRealSense()
virtual std::string getSerial() const
virtual SensorData captureImage(CameraInfo *info=0)
static const int cDepthWidth
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
virtual bool isCalibrated() const
GLM_FUNC_DECL genType e()
void setEmitterEnabled(bool enabled)
virtual SensorData captureImage(CameraInfo *info=0)
GLM_FUNC_DECL bool all(vecType< bool, P > const &v)
virtual bool isCalibrated() const
cv::VideoCapture _capture
std::string getName(void *handle)
virtual bool isCalibrated() const
Basic mathematics functions.
unsigned int imagesCount() const
Some conversion functions.
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
virtual std::string getSerial() const
cv::Mat RTABMAP_EXP registerDepth(const cv::Mat &depth, const cv::Mat &depthK, const cv::Size &colorSize, const cv::Mat &colorK, const rtabmap::Transform &transform)
bool acquire(int n=1, int ms=0)
std::string getExtension()
const Transform & groundTruth() const
CameraFreenect2(int deviceId=0, Type type=kTypeDepth2ColorSD, float imageRate=0.0f, const Transform &localTransform=Transform::getIdentity(), float minDepth=0.3f, float maxDepth=12.0f, bool bilateralFiltering=true, bool edgeAwareFiltering=true, bool noiseFiltering=true, const std::string &pipelineName="")
const cv::Mat & imageRaw() const
virtual SensorData captureImage(CameraInfo *info=0)
static rtabmap::Transform opticalRotation(1.0f, 0.0f, 0.0f, 0.0f, 0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,-1.0f, 0.0f)
void initRectificationMap()
virtual std::string getSerial() const
virtual ~CameraFreenect2()
void setOpenNI2StampsAndIDsUsed(bool used)
CameraOpenni(const std::string &deviceId="", float imageRate=0, const Transform &localTransform=Transform::getIdentity())
#define UASSERT(condition)
SensorData takeImage(CameraInfo *info=0)
Wrappers of STL for convenient functions.
virtual SensorData captureImage(CameraInfo *info=0)
virtual SensorData captureImage(CameraInfo *info=0)
virtual std::string getSerial() const
bool load(const std::string &directory, const std::string &cameraName)
virtual ~CameraOpenNICV()
#define ULOGGER_DEBUG(...)
virtual bool isCalibrated() const
#define UASSERT_MSG(condition, msg_str)
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
static const int cColorWidth
virtual bool isCalibrated() const
CameraOpenNICV(bool asus=false, float imageRate=0, const Transform &localTransform=Transform::getIdentity())
virtual std::string getSerial() const
virtual SensorData captureImage(CameraInfo *info=0)
const CameraModel & cameraModel() const
virtual ~CameraRGBDImages()
virtual SensorData captureImage(CameraInfo *info=0)
bool setExposure(int value)
virtual bool isCalibrated() const
void setDepth(bool isDepth, float depthScaleFactor=1.0f)
void setIRDepthShift(int horizontal, int vertical)
boost::signals2::connection connection_
virtual std::string getSerial() const
virtual ~CameraRealSense2()
bool setMirroring(bool enabled)
CameraK4W2(int deviceId=0, Type type=kTypeDepth2ColorSD, float imageRate=0.0f, const Transform &localTransform=Transform::getIdentity())
void RTABMAP_EXP fillRegisteredDepthHoles(cv::Mat &depthRegistered, bool vertical, bool horizontal, bool fillDoubleHoles=false)
void project(float u, float v, float depth, float &x, float &y, float &z) const
cv::Mat rectifyImage(const cv::Mat &raw, int interpolation=cv::INTER_LINEAR) const
struct _DepthSpacePoint DepthSpacePoint
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
CameraFreenect(int deviceId=0, Type type=kTypeColorDepth, float imageRate=0.0f, const Transform &localTransform=Transform::getIdentity())
void uSleep(unsigned int ms)
bool isValidForProjection() const
GLM_FUNC_DECL genType tan(genType const &angle)
static const int cDepthHeight
const std::vector< CameraModel > & cameraModels() const
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
static const int cColorHeight
CameraRealSense2(const std::string &deviceId="", float imageRate=0, const Transform &localTransform=Transform::getIdentity())
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
virtual ~CameraFreenect()
struct _freenect_context freenect_context
virtual SensorData captureImage(CameraInfo *info=0)
cv::Mat RTABMAP_EXP fillDepthHoles(const cv::Mat &depth, int maximumHoleSize=1, float errorRatio=0.02f)
#define ULOGGER_WARN(...)
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
virtual bool isCalibrated() const
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
virtual bool odomProvided() const
CameraRealSense(int deviceId=0, int presetRGB=0, int presetDepth=0, bool computeOdometry=false, float imageRate=0, const Transform &localTransform=Transform::getIdentity())
virtual std::string getSerial() const
struct tagRGBQUAD RGBQUAD
virtual bool isCalibrated() const
CameraRGBDImages(const std::string &pathRGBImages, const std::string &pathDepthImages, float depthScaleFactor=1.0f, float imageRate=0.0f, const Transform &localTransform=Transform::getIdentity())
void setGroundTruth(const Transform &pose)
detail::tvec3< float, highp > float3
single-precision floating-point vector with 3 components. (From GLM_GTX_compatibility extension) ...
CameraOpenNI2(const std::string &deviceId="", Type type=kTypeColorDepth, float imageRate=0, const Transform &localTransform=Transform::getIdentity())
static bool exposureGainAvailable()
#define ULOGGER_ERROR(...)
void setIRDepthFormat(bool enabled)
std::string UTILITE_EXP uFormat(const char *fmt,...)
void setName(const std::string &name)
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
virtual bool isCalibrated() const
virtual SensorData captureImage(CameraInfo *info=0)
bool setAutoWhiteBalance(bool enabled)
CameraModel scaled(double scale) const
V uValue(const std::map< K, V > &m, const K &key, const V &defaultValue=V())
pcl::Grabber * interface_
struct _ColorSpacePoint ColorSpacePoint